我按照这些教程制作了一个简单的内核,然后我将使用 GRUB 加载该内核。编译说明不起作用(ld 找不到 -T 选项),当我最终得到一个编译文件时,它是 Macho 格式的。在 Mac 上编译这些文件时要采取的正确步骤是什么。
编辑:
我在 Ubuntu 虚拟机上编译了代码,所以我有 kernel.bin 文件。现在如何制作运行内核的可引导映像?
3 回答
您需要做一些事情才能使其正常工作。
首先,您需要确保 nasm、gcc 和 ld 正在创建 macho i386 二进制文件。这意味着传递-f macho
给 nasm、-m32
gcc 和-arch i386
ld,否则您将获得 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
将加载您的男子气概内核,您将被设置!
您不能直接在 Mac 上执行此操作,因为 Mac 使用 EFI 作为其引导加载程序(有点)。你最好的选择是去下载 Sun VirtualBox 并制作一个 Linux 虚拟机——这还有一个额外的好处是你可以拍摄快照,所以如果事情变成梨形,你总是可以回滚(当你开始编写 I/O 例程)。
我使用 rEFIt 使 Windows 和 Linux 的引导加载程序与 Mac 引导加载程序兼容(或不那么讨厌)。
如果你想要 Mac VM 环境,我听说 Q 很好,我个人使用过 VMWare 的 Fusion。