3

我按照这些教程制作了一个简单的内核,然后我将使用 GRUB 加载该内核。编译说明不起作用(ld 找不到 -T 选项),当我最终得到一个编译文件时,它是 Macho 格式的。在 Mac 上编译这些文件时要采取的正确步骤是什么。
编辑:
我在 Ubuntu 虚拟机上编译了代码,所以我有 kernel.bin 文件。现在如何制作运行内核的可引导映像?

4

3 回答 3

4

您需要做一些事情才能使其正常工作。

首先,您需要确保 nasm、gcc 和 ld 正在创建 macho i386 二进制文件。这意味着传递-f macho给 nasm、-m32gcc 和-arch i386ld,否则您将获得 x86_64 macho 二进制文件。

其次,GRUB 不支持 macho 二进制文件——它只提供对 ELF 二进制格式的开箱即用支持。但这不是问题——你可以通过使用 multiboot 头文件来准确地告诉 GRUB 做什么来引导你的 macho 内核。

特别是,您需要在 multiboot 标头中设置 FLAGS 的第 16 位:

FLAGS 1<<16 | whateverelse

这将告诉 GRUB 从您那里获取有关从何处加载内核的信息,而不是试图自动找出这一点。

现在你需要告诉 GRUB 这个信息。特别是,为了以任何二进制格式加载内核,GRUB(或任何与多重引导兼容的引导加载程序)需要 4 个字段:

  • header_addr:您的内核期望位于的物理内存位置。将其设置为 .text 部分的地址。(提示:在 .text 之后放置一个标签并在此处简单地引用它)
  • load_addr: GRUB 应该开始从磁盘加载的地址。在 macho 的情况下,.text 是第一个地址,所以我们也将其设置为 .text 的位置
  • load_end_addr: GRUB 应该停止加载的地方。通常,类似的东西stack+STACKSIZE会起作用。
  • bss_end_addr: BSS 部分的末端所在的位置。在男子气概中,它就在最后,因此将其设置为等于load_end_addr将起作用。
  • entry_addr:内核代码的入口点。在 OS X 上,start尽管根据该指南,它默认为loader.

我的示例代码:

global start           ; making entry point visible to linker
extern _kmain            ; kmain is defined elsewhere

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
MACHO       equ  1<<16
FLAGS       equ  MODULEALIGN | MEMINFO | MACHO  ; this is the Multiboot 'flag' field
MAGIC       equ  0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM
   dd MultiBootHeader
   dd MultiBootHeader
   dd stack+STACKSIZE
   dd stack+STACKSIZE
   dd start

; reserve initial kernel stack space
STACKSIZE equ 0x4000                  ; that's 16k.

start:
   mov esp, stack+STACKSIZE           ; set up the stack
   push eax                           ; pass Multiboot magic number
   push ebx                           ; pass Multiboot info structure

   call  _kmain                       ; call kernel proper

   cli
hang:
   hlt                                ; halt machine should kernel return
   jmp   hang

section .bss
align 4
stack:
   resb STACKSIZE                     ; reserve 16k stack on a doubleword boundary

这样做之后,当您告诉 GRUB 使用该kernel 200+x命令加载内核时,您会看到屏幕上弹出“multiboot-kludge”消息,其中包含有关从何处加载所有内容的信息。输入boot将加载您的男子气概内核,您将被设置!

于 2011-07-18T11:15:44.370 回答
3

您不能直接在 Mac 上执行此操作,因为 Mac 使用 EFI 作为其引导加载程序(有点)。你最好的选择是去下载 Sun VirtualBox 并制作一个 Linux 虚拟机——这还有一个额外的好处是你可以拍摄快照,所以如果事情变成梨形,你总是可以回滚(当你开始编写 I/O 例程)。

于 2010-07-30T18:14:28.320 回答
0

我使用 rEFIt 使 Windows 和 Linux 的引导加载程序与 Mac 引导加载程序兼容(或不那么讨厌)。

如果你想要 Mac VM 环境,我听说 Q 很好,我个人使用过 VMWare 的 Fusion。

于 2010-08-05T23:08:26.877 回答