百科问答小站 logo
百科问答小站 font logo



为什么把内核镜像放在u盘里,电脑(BIOS)加载失败? 第1页

  

user avatar   prettykernel 网友的相关建议: 
      

你是自己写的 32 位操作系统是吗 ?

你只要是 2010 年之后买的电脑,基本上都是 UEFI 方式启动的,MBR (boot sector) 根本就不会执行,boot sector 中只有数据部分是有用的。

以 linux 内核为例,x86 boot protocol 中明确讲了 boot sector 和 setup sectors 的布局。这两者位于内核压缩映像开头,主要用于 bootloader 和 linux kernel 之间交换数据。

启动方式大致如下:

系统上电,跳转到 reset vector (0xfffffff0,这是 x86 的规定),这里映射到 UEFI 映像末尾(UEFI 映像在一块 flash 芯片中,通过 SPI 总线连到 CPU),是一条 jmp 指令,跳转到 UEFI 开头执行,然后一路初始化到 64 位 long mode,然后 UEFI 加载 bootloader,例如 grub2。

注意,现在是 identity map,即物理地址等于虚拟地址。

grub2 调用 UEFI 提供的接口,加载 bzImage (/boot/vmlinuz) 到 0x100000 (1M),对应 startup_32/64,移动到合适位置,然后解压缩,跳转到解压缩后的 startup_32/64 (大于等于 16MB 且对齐到 CONFIG_PHYSICAL_ALIGN 的某个地址),继续执行。startup_32 和 startup_64 之间的偏移是固定的 512B。

如果你用虚拟机。那么默认是使用 BIOS 方式,当然可以执行 MBR 了。你把虚拟机启动方式改为 UEFI ,一样会重启。对于 linux,就是执行到 arch/x86/boot/header.S#L72,导致重启。该文件中的数据就是 boot sector 和 setup sectors,布局参考 Documentation/x86/boot.rst

我简单注释一下导致重启的代码 (arch/x86/boot/header.S 中的所有代码在 UEFI 引导方式下正常启动时都不会执行):

       bs_die:  # Allow the user to press a key, then reboot  xorw %ax, %ax  int $0x16  # Keyboard Service。输入 %ah = 0x00 表示从键盘读入字符,输出 %ah 为键盘扫描码,%al 为字符的 ASCII   int $0x19  # 将第一个扇区的内容载入 0000:7C00   # int 0x19 should never return. In case it does anyway, invoke the BIOS reset code...  ljmp $0xf000, $0xfff0    # 跳转到 UEFI 中的 0xfffffff0     

你之所以搞不清楚,是因为你不明白现代的 bootstrap 流程,你在网上找到的几乎所有资料都讲的是 BIOS 时代的事情(就是跳转到 0x7C00 那一套东西),UEFI 时代的启动流程细节基本没有。

在 UEFI+GPT(现代硬盘分区格式) 中,系统上电时,是 UEFI 加载 bootable device (硬盘/U盘) 中的 FAT32 格式的 EFI Part System 中的 bootx64.efi,该文件可以是由 grub2 等 bootloader 编译而来,也可以是开启 efi stub 机制的 linux 内核编译而来。而硬盘的前 32KB 根本没用,你在网上看到的什么 boot.img,core.img 之类的东西都是过时的 (都在硬盘前 32KB)。

UEFI 启动方式下,boot sector 并不是硬盘第一个扇区(MBR),而是内核映像 bzImage (/boot/vmlinuz) 的前 512 字节,后面紧跟着的几个 512 字节是 setup sectors (见前文),再后面是内核 ELF 文件 vmlinux 压缩后的产物。

UEFI 是一个很大的话题,我就不展开了 (以后有时间补)。总之,你不用纠结这个问题,继续用 BIOS 方式即可。学习操作系统编写时,引导加载流程并不是重点,中断机制,内存管理,任务调度,等等才是。尤其 64 位和 32 位有较大的不同,细节资料基本都来自英文文档,需要花一些时间学习。




  

相关话题

  如果要改进C语言,您最希望添加哪些语言特性,移除哪些语言特性? 
  为什么 C++ 没有 C 语言快? 
  为什么char *a="xxxxx", *b="xxx"; strcpy(a, b);的用法不行? 
  C语言能用指针修改其他程序的地址的值吗? 
  为什么把内核镜像放在u盘里,电脑(BIOS)加载失败? 
  对于一个大一计科新生,有什么代码行数在 500~1000 的程序(C 语言)可以试着写来练手? 
  为什么现在有很多人,甚至大学授课还在坚持 VC 6? 
  为什么汇编语言不能越过操作系统操控硬件? 
  C语言和C++中,为什么malloc函数需要传入申请的内存大小,而free时候却不需要传大小呢? 
  页表放在主存中,那么页表基址寄存器中存放的页表基址是虚拟基址还是主存中页表实际基址? 

前一个讨论
什么是耳机智商税?
下一个讨论
为什么有些男人喜欢身材丰满的女生?





© 2024-11-22 - tinynew.org. All Rights Reserved.
© 2024-11-22 - tinynew.org. 保留所有权利