硬件视角的操作系统 (CPU Reset;固件;为硬件编程) [南京大学2023操作系统-P3]

 

回忆一下写CPU的过程,CPU里的时序电路基本都有一个 reset 的过程

正是这个 reset 的过程,建立了程序员和硬件之间的桥梁

回忆一下我们买的电脑:

电脑的品牌是 惠普HP, CPU是Intel的,主板是华硕的

当开机的时候,屏幕上会显示 惠普HP 的商标

所以,firmware 应该不是由Intel来开发的,而是由惠普来开发的

Intel 会约定好 CPU Reset 之后的状态(寄存器值,比如 PC)  (注意:内存控制器严格来说不是CPU的一部分)

所以,CPU在启动的时候,做的第一件事情就是取出 PC 指向的内存位置,取出一条指令译码执行

所以,主板厂商会和CPU公司约定,只要主板厂商在 PC reset 的地址那里放上代码,那么主板厂商的代码就能够执行  (第一个约定)

再回忆一下,有时候在更新 windows 操作系统时,会看到 “更新固件” 的字样:

实际上,是主板厂商会在主板上放上一个小的存储器,这个存储器可读可写,这个存储器有代码和数据,惠普HP的 logo 就是这个存储器的数据的一部分(这个存储器里的代码和数据应该就叫做firmware了)

(个人猜测:这个小的存储器和DRAM不是一个东西,可以直接通过内存地址访问吗?)

随后,还有第二个约定,那就是主板厂商,或者叫写 firmware 的人和操作系统开发者的约定:

firmware 会读取 存储介质(如硬盘)上的某块数据,把它加载到内存上的某块地方,并且跳转到它的某个地址开始执行。比如,加载存储介质上的第二级loader,或者直接加载操作系统。

接下来看看 x86 处理器的 reset 行为

可以看到 Intel 手册中规定了 上电 和 reset 时的寄存器的值

Firmware 负责加载OS (这就是 bootloader?)

QEMU -kernel 则会跳过 Firmware 直接加载内核

uboot 就是一个开源的加载器(firmware/bootloader)

BIOS 和 UEFI 都是固件,它们除了加载其它程序外,还有一个功能:配置、初始化各个硬件

补充:超线程(hyperthreading),一个物理core可以用来当两个 logic core 使用,在操作系统看来这是两个一样的core

硬件上的某些功能,比如刚刚提到的超线程,被Intel设计成可开关,而开关这些功能并不是由操作系统完成的,而是在加载操作系统之前,由固件配置

还有:配置主板上某些端口的开关、是否使用独立显卡、CDROM启动、U盘启动、软盘启动等等

BIOS 和 UEFI 的不同可以看这里 https://www.freecodecamp.org/news/uefi-vs-bios/

BIOS其实是比较老旧的固件,今天的硬件复杂得多,BIOS已经不再使用,我们使用新的固件:UEFI

 

CPU上电后,PC跳转到 0x0fff, 开始执行 firmware 代码, firmware 代码会从磁盘上读取 MBR,放到内存地址 0x7c00,接着再跳转到 0x7c00 (到这一步,计算机的控制权就到了操作系统开发者手里了!)

MBR(master boot record) 的 512字节中,其实只有446字节可以使用,其中64字节用来存储分区表(partition table)。然后还有两个字节为 0x55 0xAA,用来标识这是一个可引导的设备(在今天看来可能没有什么意义)

如果没有 JTAG 帮助扫描硬件上的信号,想要进行 OS, 固件 的调试几乎是不可能的

这是 16 位的 x86 汇编代码(MBR 代码),建议自己上网找一下完成的代码,分析一下

qemu-system-x86_64 在刚启动时可以看到 $rip = 0xfff0,其实这里隐藏了点东西

由于 x86 刚启动处于 16位模式,此时的IP实际上由 $cs * 16 + $rip 共同构成

此时的汇编指令都是16位指令,直接使用 64位 的反汇编器会出错,应该把这些代码丢给 16位的反汇编器

(注意:原本gdb可以使用 x/10i 来打印10个指令)

一个.gdbinit 的很好的写法

也可以写一个 init.gdb 文件,然后使用 gdb -x init.gdb 去初始化gdb

使用 file a.out 可以把源代码加载进来(没错!汇编代码也可以被加载哦!),就不用再看反汇编器给的代码了

还支持对行号打断点

再修改一下 .gdbinit 文件,我们可以给 内存地址 0x7c00 加上一个 watchpoint,这样就能知道到底是哪块代码加载了 MBR 到 0x7c00 上

在QEMU中,加载 MBR 的 BIOS 是 CBIOS,这是一个开源的firmware,我们可以把它找来,让 gdb 加载,进行代码调试(gdb对16位汇编的支持比较糟糕,一般还是用源码进行调试)

用上述命令可以识别 ${AM_HOME} 环境变量,把它们全部替换成更短的 $AM_HOME,增强可读性 

在 compile_commands.json 里插入编译选项,就可以消除 vscode 上的红线

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值