Joh*_*ber 15
具有 EFI 功能的现代台式机和笔记本电脑。与使用了 20 多年的传统 BIOS 系统不同,这些系统的固件中实际上有一个操作系统——能够一次性加载大量软件项目。此外,面对以某种方式获得了存储启动软件能力的软件的攻击,这些可以在具有更高安全性的计算机上启动。
更传统的硬件具有更少的固件并且一点一点地开始。此处描述的这些系统在其固件中运行自检,然后开始启动过程。
这是从软盘启动第一台 PC 的固件代码(在软盘子系统重置后):
MOV AX,201H
SUB DX,DX
MOV ES,DX
MOV BS,OFFSET BOOT_LOCN
MOV CX,1
INT 13H
JNC H4
Run Code Online (Sandbox Code Playgroud)
接下来是从重置开始的错误处理(4 次重试)。
H4 的位置稍早一点,是:
JMP BOOT_LOCN
Run Code Online (Sandbox Code Playgroud)
BOOT_LOCN 被定义为位置 7C00H
[1] IBM PC 技术参考手册 (1984)
没有太多东西可以让您的系统启动。存储介质的第一个扇区,即主引导记录,在位置 0:7c00 处被读入计算机内存,然后执行跳转到其开始位置。
据说,boot 是指用你的靴子把自己捡起来。有一系列事件必须正确发生才能启动您的系统。一旦从磁盘加载了足够多的代码并启动,系统就可以提供诸如错误消息、提示和错误处理之类的信息。单个部门没有足够的空间来处理任何这种复杂性。
顺便说一句,最终代码发生了一些变化。DX 的高位字节设置为 80H 以引用第一张磁盘而不是第一张软盘。当然,后来对 PC BIOS 的添加包括弯曲几何和基于数据包的 I/O 以用于更大的扇区地址,并允许它从 CD 引导,通过 USB 等。传统 PC 硬件的想法仍然相同,读取第一个扇区并传输控制。
除此之外,在 EFI 之前没有发生太多事情。
由第一个扇区决定接下来应该发生什么并至少加载它的第一个扇区,然后由该扇区加载多个扇区——然后您的系统应该关闭并运行。这就是现代 Ubuntu 系统在近乎现代的硬件上启动的方式。
来源:http : //bazaar.launchpad.net/~ubuntu-branches/ubuntu/utopic/grub2/utopic/view/head :
/grub-core/boot/i386/pc/boot.S
第一个扇区是 MBR,下一个扇区是 Grub2 的第一部分。我应该补充一点,四个主分区也在 MBR 中定义,其中一个可以描述包含扩展分区链的磁盘区域。第一个扇区的地址是扇区 0。
可能出错的地方:
如果在 Grub 之后安装或重新安装了 Windows,它可以用自己的 Grub MBR 代码替换。随着指向 Grub 代码的指针消失,新的 Windows 代码将搜索带有引导标志的分区,从其开头加载一个扇区并将控制权转移给它。
在通常的安装中,grub 代码核心的其余部分直接跟随,并且 Grub MBR 指向下一个扇区,扇区 1。如果您将 Grub 安装到一个分区,指针可能会改变。该 grub 指针位于 MBR 的 0x5c-0x60 中,必须进行相应更改。
00000050 f7 c1 01 00 74 03 fe 46 10 66 00 80 01 00 00 00 |....t..F.f......|
^
Run Code Online (Sandbox Code Playgroud)
4 字节指针将保存的最大扇区数是 2^32、2,294,967,296 个扇区,或小于 2.2 x 10 12字节。以下 grub 代码必须位于磁盘的该部分内。
来源:http : //bazaar.launchpad.net/~ubuntu-branches/ubuntu/utopic/grub2/utopic/view/head :
/grub-core/boot/i386/pc/diskboot.S
通常从扇区 1 开始(例如,如果您将 Grub2 安装到 /dev/sda)是 core.img 的部分。必须为 grub 加载整个图像才能给您提示。在它的第一个扇区的最后是一个块列表,一个扇区和计数的列表,必须从中加载图像的其余部分。与 MBR 不同,扇区中有足够的空间来加载多组多扇区。现在我们正在到达某个地方。扇区每 0x200 字节定位一次。每个范围用 16 个字节描述。
|
00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003f0 00 00 00 00 02 00 00 00 00 00 00 00 63 00 20 08 |............c. .|
Run Code Online (Sandbox Code Playgroud)
可能出什么问题:
GPT 格式的驱动器的分区描述符位于第二个扇区开始处。在这种情况下,grub 映像必须位于分区中的其他位置。最好格式化一个小分区,以便 grub 保存其核心映像。将它放在靠近磁盘开头的某个地方,在那里您不会想要移动或打扰它。如果不重新安装 grub 就不能移动它。
如果在此位置安装了诸如整个磁盘加密系统之类的东西,它就会被清除。它可能必须在那里引导您的系统或访问您的数据。哎哟。
如果您稍后安装加密或其他使用此区域的软件,则其某些内容核心 grub 将不再启动。
阻止列表为扇区号保留了 2 个长字,因此每个位都必须存储在驱动器开头的 2^21 TB 内。这应该足够好一段时间了。它加载的大部分内容都是压缩的。较旧的系统在 MBR 和只有 1 个磁道 - 1 个 MBR 扇区的第一个分区之间有空间。这可能是大约 63 个扇区,而 63 个扇区是 Ubuntu 14.04 在撰写本文时加载的内容。压缩是为了使图像中的整个 grub 内核以及几个方便的 grub 模块都可以容纳。这将包括首次启动时的整个 grub 系统。
来源:
http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/utopic/grub2/utopic/view/head:/grub-core/boot/i386/pc/startup_raw.S
HTTP://bazaar.launchpad .net/~ubuntu-branches/ubuntu/utopic/grub2/utopic/view/head:/grub-core/boot/i386/pc/lzma_decode.S
这是最后一步加载内容的开始,通常位于扇区 2,即第三个扇区。
整个核心映像现在都已加载。这部分获取其后的其余信息并将其解压缩到内存中。
来源:
http : //bazaar.launchpad.net/~ubuntu-branches/ubuntu/utopic/grub2/utopic/files/head :/ grub-core/
http://www.gnu.org/software/grub/manual/ html_node/index.html
此时,大量的 Grub2 代码被加载和解压缩。这段代码包含几个模块,与 grub2 内核一样长。看起来像一个模块是一个包含 grub前缀的短段。这是一个字符串,如:
(hd0,msdos5)
当 grub 启动时,如果您输入c密钥,您可以输入 grub 命令,如果您这样做并输入set命令,您可以看到在您的磁盘上安装 Grub2 代码时设置的前缀。(按ESC返回)。
Grub 现在可以访问和浏览多种文件系统,前缀是它开始查找位置的关键。
从前缀 grub 描述的目录加载 grub.cfg 文件。该文件由update-grub命令(重新)创建,该命令查找您可能想要从中启动的所有位置,并在文件定义的菜单结构中指定这些位置。该文件还指定是否应加载 grubenv 文件。该文件加载 grub2 环境,对于某些 grub 配置,可能包括上次成功加载的引导菜单。grub.cfg 文件还指示从同一目录加载更多 grub 模块。
如果需要进行选择,grub 现在可以显示菜单。
当您从菜单中选择一个项目时,该项目用于运行该菜单项中的 grub 命令。这些可能会在该菜单项引用的位置加载处理内核和 initrd 映像所需的更多模块。
菜单项的最后命令特别有趣。
linux命令指定要加载的linux内核grub,以及应该传递的linux boot命令。Linux 内核命令中特别有趣的是 root= 参数。它会告诉内核,用内核的术语而不是 grub 的术语,应该以 root 身份挂载哪个分区。
initrd 命令指定匹配的压缩 cpio initramfs 文件(称为 initrd.img- version)的位置,该文件包含一个内存文件树,其中包含 linux 内核启动所需的额外信息,以及它可能需要的内核模块。
然后,引导命令将 CPU 控制权转移到加载的内核以使其启动。
可能出错的地方:
如果前缀错误,grub 将无法正常启动,并且无法加载菜单或适当的模块。如果对分区重新排序或删除以前的分区,更改分区编号,则可能会导致这种情况。如果指定分区中的信息已更改,也可能导致此问题。它应该始终与 grub-install 存储的内容相匹配,grub-install 给出了一个特定的安装目录。如果在 grub 正在工作的分区上更改了实际的 grub 代码,则可能应该在驱动器上重新安装grub-install. 即便如此,如果您能找到正确的分区,您应该能够手动设置前缀并使 grub 工作。
运行 Grub2 时需要知道的事情:
pager=1以避免项目从屏幕顶部滚出。debug=all以发出调试消息,以便为您提供有关输入命令时发生的情况的额外信息。内核引导
内核初始化一般开始并在书籍等中进行了描述。稍后它指的是 initrd 文件系统映像中的 Debian 和 Ubuntu 特定信息。部分:找到为根目录指定的分区,必要时检查,并挂载写入,将内存日志复制到其中,并运行新贵。Upstart 接管系统初始化,包括在其 /etc/init/rc-sysinit.conf 作业中的 /etc/rc.#/ 目录中运行传统脚本。
可能出错的地方:
也许最常见的 grub 引入问题是从 grub 传递给内核的 root= kernel 命令是错误的。由于busybox无法找到所需系统的根目录,这可能会导致内核初始化提前停止并提示。
[1] IBM 个人计算机硬件参考库:技术参考;部件号 6361453 (1984),第 5-50 页(对于 IBM 5150 个人计算机,当时唯一的“PC™”)
http://www.minuszerodegrees.net/manuals/IBM_5150_Technical_Reference_6322507_APR84.pdf第 143 页