准备加载内核
Preparing to load a kernel
尽管有非常完整的引导装载程序可用,但我一直在业余时间断断续续地写一个,作为一种教育练习。我 运行 遇到了问题。
我能够毫无问题地执行初始引导和链加载其他扇区。如果我自己写 OS 我会很高兴。 :) 相反,我正在尝试 bootstrap Linux。我面临的挑战是双重的。
- 我明白 I need to load the kernel (Linux) into memory at 0x100000。我知道我应该在内核的偏移量 0x202 处找到 "HdrS" 签名。我也知道起始地址应该在0x214。但是,当我跳转到该位置的地址时,它会停止。显然,围绕这个包装调试器非常困难。 :) 我是否遗漏了确定内核正确起始地址所必需的这一系列事实?
- 我怀疑 (1) 的答案可能与需要用硬件发现信息填充一些内存区域有关。我在 OSDev Wiki 上看到过几个对此的传递引用,但我似乎不知道它在哪里,以及哪些数据需要在那里。 引导加载程序负责硬件发现吗?如果是这样,什么数据需要放在哪里?
另外要注意的一点是我已经处于 32 位保护模式,因为我正在处理创建 EFI 引导系统,所以 16 位实模式在这里不是一个真正的选项,消除了真正的模式在内核中的起始位置。
@Jester 找到了我的问题并回答了两个问题。解决方案实际上在 file that I had linked 中,尽管我错过了相关部分。为了后代,我在这里包括了相关的文章:
In 32-bit boot protocol, the first step in loading a Linux kernel
should be to setup the boot parameters (struct boot_params,
traditionally known as "zero page"). The memory for struct boot_params
should be allocated and initialized to all zero. Then the setup header
from offset 0x01f1 of kernel image on should be loaded into struct
boot_params and examined. The end of setup header can be calculated as
follow:
0x0202 + byte value at offset 0x0201
In addition to read/modify/write the setup header of the struct
boot_params as that of 16-bit boot protocol, the boot loader should
also fill the additional fields of the struct boot_params as that
described in zero-page.txt.
After setting up the struct boot_params, the boot loader can load the
32/64-bit kernel in the same way as that of 16-bit boot protocol.
In 32-bit boot protocol, the kernel is started by jumping to the
32-bit kernel entry point, which is the start address of loaded
32/64-bit kernel.
At entry, the CPU must be in 32-bit protected mode with paging
disabled; a GDT must be loaded with the descriptors for selectors
__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat segment; __BOOT_CS must have execute/read permission, and __BOOT_DS
must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
must be __BOOT_DS; interrupt must be disabled; %esi must hold the base
address of the struct boot_params; %ebp, %edi and %ebx must be zero.
64 位指令也可以在同一文档中找到。
尽管有非常完整的引导装载程序可用,但我一直在业余时间断断续续地写一个,作为一种教育练习。我 运行 遇到了问题。
我能够毫无问题地执行初始引导和链加载其他扇区。如果我自己写 OS 我会很高兴。 :) 相反,我正在尝试 bootstrap Linux。我面临的挑战是双重的。
- 我明白 I need to load the kernel (Linux) into memory at 0x100000。我知道我应该在内核的偏移量 0x202 处找到 "HdrS" 签名。我也知道起始地址应该在0x214。但是,当我跳转到该位置的地址时,它会停止。显然,围绕这个包装调试器非常困难。 :) 我是否遗漏了确定内核正确起始地址所必需的这一系列事实?
- 我怀疑 (1) 的答案可能与需要用硬件发现信息填充一些内存区域有关。我在 OSDev Wiki 上看到过几个对此的传递引用,但我似乎不知道它在哪里,以及哪些数据需要在那里。 引导加载程序负责硬件发现吗?如果是这样,什么数据需要放在哪里?
另外要注意的一点是我已经处于 32 位保护模式,因为我正在处理创建 EFI 引导系统,所以 16 位实模式在这里不是一个真正的选项,消除了真正的模式在内核中的起始位置。
@Jester 找到了我的问题并回答了两个问题。解决方案实际上在 file that I had linked 中,尽管我错过了相关部分。为了后代,我在这里包括了相关的文章:
In 32-bit boot protocol, the first step in loading a Linux kernel should be to setup the boot parameters (struct boot_params, traditionally known as "zero page"). The memory for struct boot_params should be allocated and initialized to all zero. Then the setup header from offset 0x01f1 of kernel image on should be loaded into struct boot_params and examined. The end of setup header can be calculated as follow:
0x0202 + byte value at offset 0x0201
In addition to read/modify/write the setup header of the struct boot_params as that of 16-bit boot protocol, the boot loader should also fill the additional fields of the struct boot_params as that described in zero-page.txt.
After setting up the struct boot_params, the boot loader can load the 32/64-bit kernel in the same way as that of 16-bit boot protocol.
In 32-bit boot protocol, the kernel is started by jumping to the 32-bit kernel entry point, which is the start address of loaded 32/64-bit kernel.
At entry, the CPU must be in 32-bit protected mode with paging disabled; a GDT must be loaded with the descriptors for selectors __BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat segment; __BOOT_CS must have execute/read permission, and __BOOT_DS must have read/write permission; CS must be __BOOT_CS and DS, ES, SS must be __BOOT_DS; interrupt must be disabled; %esi must hold the base address of the struct boot_params; %ebp, %edi and %ebx must be zero.
64 位指令也可以在同一文档中找到。