在mac上将内核编译为二进制文件

发布于 2024-09-11 00:38:44 字数 301 浏览 8 评论 0原文

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

I was following these tutorials to make a simple kernel that I would then load using GRUB. The instructions for compiling didn't work (ld couldn't find the -T option) and when I finally got a compiled file it was in Macho format. What are the correct steps to take when compiling these files on Mac.
Edit:
I compiled the code on an Ubuntu virtual machine and I so I have the kernel.bin file. Now how can I make a bootable image that runs the kernel?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤者何惧 2024-09-18 00:38:44

要使其发挥作用,您需要执行一些操作。

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

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

特别是,您需要在多重引导标头中设置 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

完成此操作后,当您告诉 GRUB 使用 kernel 200+x 命令加载内核时,您将看到屏幕上弹出一条“multiboot-kludge”消息有关所有内容将从何处加载的信息。输入 boot 将加载您的 macho 内核,然后您就可以设置了!

There are a few things you'll need to do for this to work.

First, you need to make sure that nasm, gcc, and ld are creating macho i386 binaries. This means passing -f macho to nasm, -m32 to gcc, and -arch i386 to ld or else you'll get x86_64 macho binaries.

Second, GRUB doesn't support macho binaries - it only comes with out-of-the-box support for ELF binary formats. But that's not a problem - you can tell GRUB exactly what to do in order to boot your macho kernel by using the multiboot header.

In particular, you need to set the 16th bit of FLAGS in the multiboot header:

FLAGS 1<<16 | whateverelse

This will tell GRUB to take info about where to load the kernel from you instead of trying to figure this out automatically.

Now you need to tell GRUB this information. In particular, there are 4 fields that GRUB (or any multiboot-compatible bootloader) needs in order to load a kernel in any binary format:

  • header_addr: The physically memory location your kernel expects to be located at. Set it equal to the address of the .text section. (Hint: Place a label right after .text and simply refer to it here)
  • load_addr: The address that GRUB should start loading from disk. In macho's case, .text is the first address, so we also set this to .text's location
  • load_end_addr: Where GRUB should stop loading. Usually, something like stack+STACKSIZE would work.
  • bss_end_addr: Where the end of the BSS section is located. In macho, it's right there at the end, so setting it equal to load_end_addr will work.
  • entry_addr: The entry point for your kernel code. On OS X, this defaults to start though according that guide it is loader.

My sample code for this:

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

Having done so, when you tell GRUB to load your kernel with the kernel 200+x command, you'll see a "multiboot-kludge" message pop up on the screen with information about where everything will be loaded from. Typing in boot will load your macho kernel and you'll be set!

慕烟庭风 2024-09-18 00:38:44

您不能直接在 Mac 上执行此操作,因为 Mac 使用 EFI 作为引导加载程序(某种意义上)。对于这类东西,你最好的选择是下载 Sun VirtualBox 并创建一个 Linux VM - 这还有一个额外的好处,你可以拍摄快照,这样如果事情变得梨形,你可以随时回滚(当你开始编写 I/O 例程)。

You can't do this on a Mac directly, because Macs use EFI as their bootloader (kind of). Your best bet for this kind of stuff is to go download Sun VirtualBox and make a Linux VM - this has the additional advantage that you can take snapshots so if things go pear-shaped you can always roll back (easy to corrupt the HD when you get to writing the I/O routines).

当梦初醒 2024-09-18 00:38:44

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

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

I've used rEFIt to make bootloaders for Windows and Linux compatible (or not so nasty) with the Mac bootloader.

If you want a Mac VM environment, I've heard Q is good and I've used VMWare's Fusion personally.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文