在Mac上将内核编译成二进制文件

3

我正在跟随这些教程制作一个简单的内核,然后使用GRUB进行加载。编译指令没有起作用(ld找不到-T选项),最终得到的编译文件是Macho格式。在Mac上编译这些文件的正确步骤是什么?
编辑:
我在Ubuntu虚拟机上编译了代码,现在我有了kernel.bin文件。现在我该如何制作一个可启动的映像以运行内核?

3个回答

4

为了使这个工作起来,你需要做几件事情。

首先,你需要确保nasm、gcc和ld创建的是macho i386二进制文件。这意味着要在nasm中传递-f macho,在gcc中传递-m32,在ld中传递-arch i386,否则你将得到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部分的结尾位置。在macho中,它就在最后,因此将其设置为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

完成以上步骤后,当您使用kernel 200+x命令告诉GRUB加载内核时,您将看到屏幕上弹出一个关于从哪里加载所有内容的“multiboot-kludge”消息。输入boot将加载您的内核并完成设置!

3

在Mac上直接操作是不可能的,因为Mac使用EFI作为它们的引导程序(有点像)。处理这种问题的最佳方法是下载Sun VirtualBox并创建一个Linux虚拟机 - 这样做还有另一个优点,即您可以拍摄快照,以便如果出现问题,您始终可以回滚(在编写I/O例程时易于损坏硬盘)。


0

我使用rEFIt制作引导程序,使Windows和Linux与Mac引导程序兼容(或不那么麻烦)。

如果您想要一个Mac虚拟机环境,我听说Q很好,我个人使用过VMWare的Fusion。


1
引导加载程序如何阻止我使用链接脚本?我认为这与Mac使用BSD链接器而不是GNU链接器有关。我不想在我的Mac上烧录和运行操作系统,我只想将其编译成可引导的镜像。 - None

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接