为什么 bootsect 在 linux(x86) 中将自身移至 0x90000?

问题描述 投票:0回答:3

我正在研究x86系统启动的过程 这是启动流程:

  1. BIOS 将 bootsect 从磁盘 MBR 加载到 0x7c00 内存地址
  2. boosect 将自身复制到 0x90000 内存地址并跳转到 0x90000。
  3. booset 将设置从磁盘加载到 0x90200 内存地址。
  4. 获取一些系统外围设备参数(视频、根磁盘、键盘……等)并跳转到0x90200。
  5. 将系统切换到保护模式,将内核从 0x10000(64K) 移动到 0x0000
  6. 跳转到0x0000并执行head.s进行内核启动

我的问题是,为什么我们需要先将 bootsect 本身移动到 0x90000?

为什么我们不能只移动设置和系统?

谢谢。

linux linux-kernel x86
3个回答
3
投票

“影子复制”引导加载程序并跳转到它曾经是(现在仍然是)一个很好的做法。这种做法很早就开始了,当时典型的引导加载程序仅限于 x86 处理器上单个段的大小和磁盘上的单个读取扇区。一旦询问硬件,引导加载程序就可以执行更高级的工作,例如安装系统文件(调用、挂钩、TSR 等)、被病毒接管、或初始化保护模式并开始执行应用程序的硬件分页等。

“行为”的起源早于 Linux,您应该发现这种行为对于 x86 引导加载程序很常见。可能是任何基于 IBM PC 的计算机。

Linux 中目前的代码可能源自此:

FX。 https://stuff.mit.edu/afs/sipb/user/warlord/C/memtest86/bootsect.s

在这种情况下,重新定位到 0x90000 的选择可能是任意的,目标是将加载程序从默认位置移动到它自己选择的位置,这样它就不会被可能从“低内存”分配的程序篡改。 “(实际上:作为实践问题。)

我自己也想知道一个明确的原因:)很确定这确实只是 x86 平台是 DOS 平台时代的残余,随着硬件的发展,人们采用了新的技巧来保持与“不友好”的 lowmem 代码的向后兼容.


0
投票

我相信将引导扇区移开主要是为了方便 - 没有“硬”技术原因表明它“不能”以其他方式完成。 也就是说,0x7c00 距内存起始位置不到 32KiB。 32KiB 通常不足以用于内核的设置阶段,更不用说内核本身了。

0x90000

位于 PC BIOS 保留的区域下方,同时也为内核留出了足够的空间。


无论如何,你所指的进程已经好几年没有被Linux内核使用了。您提到的地址由 v2.02 之前的
Linux Boot Protocol
版本使用,该协议首先与 linux-2.4.0 一起使用。我

认为

内核本身不再可以直接使用 linux-2.6.0 左右启动。当有人尝试直接启动内核时,该版本的 arch/i386/boot/bootsect.S 文件会输出一条消息。 如今,内核通常由单独的引导加载程序加载,只要符合引导协议,它就可以自由地使用任何它想要的方法。引导加载程序可能有多个阶段,甚至可能执行内核相关的操作,例如切换到“保护模式”本身。

    

这可以追溯到 Linux 0.11,它假定系统大小固定为 512K。这就是它的工作原理: (1) BIOS 加载位于 0x7c00 的引导扇区。


0
投票

(3) 从0x90000开始运行,引导扇区在0x10000处加载系统。

最大系统大小:0x90000 - 0x80000 = 0x10000 512K

(4) 最后,引导扇区将加载在 0x10000 处的系统复制到 0x0,Linus 自己在评论中说,这是系统“正确”的位置。

    现在,了解了这一切,将自身复制到 0x90000(或更高内存中的某个位置)的原因很明显:当将系统从 0x10000 重新定位到 0x0(步骤(4))时,它,
  • 假设
  • 系统大小为 512K ,如果没有将引导扇区重新定位到更高的内存并保持在 0x7c00,这肯定会
超过 0x7c00

覆盖

引导扇区。 总之,它最初是为了防止在重新定位系统时覆盖自身。而且,是的,任何类型的自复制都是有原因的,并且主要在加载或重新定位内容时使用,同时确保被移动的内容不会覆盖移动它的代码!

© www.soinside.com 2019 - 2024. All rights reserved.