我正在研究我的机器(x86_64 Linux,IvyBridge)中的BIOS代码。我使用以下过程转储BIOS代码:
$ sudo cat /proc/iomem | grep ROM
000f0000-000fffff : System ROM
$ sudo dd if=/dev/mem of=bios.dump bs=1M count=1
然后使用radare2
读取和反汇编二进制转储:
$ r2 -b 16 bios.dump
[0000:0000]> s 0xffff0
[f000:fff0]> pd 3
: f000:fff0 0f09 wbinvd
`=< f000:fff2 e927f5 jmp 0xff51c
f000:fff5 0000 add byte [bx + si], al
我知道x86处理器初始化总是从16位8086环境开始,执行的第一条指令在f000:fff0
处,即0xfff0
。所以我去那个位置,反汇编代码。
令我惊讶的是,第一条指令是wbinvd
,其功能是使缓存无效,这在处理器上电或重置时似乎不相关。我希望第一条指令只是一个JMP
到较低的内存地址。
为什么在JMP
之前有WBINVD
?
我已经搜索了Intel手册第3卷第9章处理器管理和初始化的相关部分,但其中没有提到任何关于WBINVD
的内容。我也搜索了一些在线资源,但没有找到任何解释。
按照JMP
指令执行0xFF51C
后,代码更有趣;它在做自我检查:
[f000:f51c]> pd
f000:f51c dbe3 fninit
f000:f51e 0f6ec0 movd mm0, eax
f000:f521 6631c0 xor eax, eax
f000:f524 8ec0 mov es, ax
f000:f526 8cc8 mov ax, cs
f000:f528 8ed8 mov ds, ax
f000:f52a b800f0 mov ax, 0xf000
f000:f52d 8ec0 mov es, ax
f000:f52f 6726a0f0ff00. mov al, byte es:[0xfff0] ; [0xfff0:1]=0
f000:f536 3cea cmp al, 0xea
,=< f000:f538 750f jne 0xff549
| f000:f53a b91b00 mov cx, 0x1b
| f000:f53d 0f32 rdmsr ; check BSP (Boot Strap Processor) flag, if set, loop back to 0xffff0; otherwise, infinite hlt
| f000:f53f f6c401 test ah, 1
,==< f000:f542 7441 je 0xff585
,===< f000:f544 eaf0ff00f0 ljmp 0xf000:0xfff0
||`-> f000:f549 b001 mov al, 1
|| f000:f54b e680 out 0x80, al
|| f000:f54d 66be8cfdffff mov esi, 0xfffffd8c ; 4294966668
|| f000:f553 662e0f0114 lgdt cs:[si]
|| f000:f558 0f20c0 mov eax, cr0
|| f000:f55b 6683c803 or eax, 3
|| f000:f55f 0f22c0 mov cr0, eax
|| f000:f562 0f20e0 mov eax, cr4
|| f000:f565 660d00060000 or eax, 0x600
|| f000:f56b 0f22e0 mov cr4, eax
|| f000:f56e b81800 mov ax, 0x18
|| f000:f571 8ed8 mov ds, ax
|| f000:f573 8ec0 mov es, ax
|| f000:f575 8ee0 mov fs, ax
|| f000:f577 8ee8 mov gs, ax
|| f000:f579 8ed0 mov ss, ax
|| f000:f57b 66be92fdffff mov esi, 0xfffffd92 ; 4294966674
|| f000:f581 662eff2c ljmp cs:[si]
|`.-> f000:f585 fa cli
| : f000:f586 f4 hlt
| `=< f000:f587 ebfc jmp 0xff585
f000:f52a b800f0 mov ax, 0xf000
f000:f52d 8ec0 mov es, ax
f000:f52f 6726a0f0ff00. mov al, byte es:[0xfff0] ; [0xfff0:1]=0
f000:f536 3cea cmp al, 0xea
那么这种自检的目的是什么呢?我很难相信这是一个天真的企图阻止修改。
尽管很难推断,但请记住,即使es
被设置为0xf000
,加载MOV al,byte es:[0xfff0]
并不是从BIOS第一条指令读取的。
第一条指令是从0xFFFFFF0
读取的,PCH还可能在重置时将0xFFF0000-0xFFFF
别名为0xFFFF0000-0xFFFFF
,因此当BSP启动时,它将执行您转储的代码。
IIRC,APs不会启动,除非显式唤醒。
然后,BSP将继续初始化HW(根据转储判断)。
在某个时候,它将为0xF0000-0xFFFFF
设置属性映射,以引导读写(或只写然后读)到内存。
最终结果是,当处理器(一个HW线程)启动时,它将从闪存中执行代码,直到执行远跳转。
在这一点上,CS
基是按照实模式规则正确计算的(非常类似于非实模式),指令将从0xF0000-0xFFFF
中提取(即。
所有这些,而cs
段值实际上并没有改变。
BSP会在某个时刻启动它的多处理器初始化例程,其中它向每个人(包括他自己)广播一个INIT-SIPI-SIPI,这将导致APs的Hibernate,并为BSP广播一个LJMP0xF000:0xFFF0
。
这里的诀窍是跳转的目标0xF000:0xFFF0
不是WBINVD
指令的相同总线地址。
可能有其他东西,可能是另一个初始化例程。
在初始化结束时,BIOS可以简单地将0xF0000-0xFFFFF
的属性重置为flash(因此可以进行软件重置),防止中间代码的转储(不是故意的)。
这不是很有效,但BIOSes通常不是代码的杰作。
我没有足够的元素来确定发生了什么,我的观点是LJMP0xF000:0xFFF0
和MOV al,byte ES:[0xFFF0]
不必从它们所在的同一区域读取。
记住这一点,所有的赌注都取消了。
只有适当的反向工程才能知道。
关于wbinvd
,我在评论中建议它可能与warm boot功能有关,而Peter Cordes建议它可能与cache-as-ram有关。
这是有道理的,但我想永远不会确定。
这也可能是一种货邪教,程序员认为指令是必要的,基于谣言。
BIOS的主要作用有三点 1.自检及初始化:开机后BIOS最先被启动,然后它会对电脑的硬件设备进行完全彻底的检验和测试。如果发现问题,分两种情况处理:严重故障停机,不给出任何提示或信号;非严重故障则给出屏幕提示或声音报警信号,等待用户处理。如果未发现问题,则将硬件设置为备用状态,然后启动操作系统,把对电脑的控制权交给用户。 2.程序服务:BIOS直接与计算机的I/O(Input/Output,即输
计算机用户在使用计算机的过程中,都会接触到BIOS,它在计算机系统中起着非常重要的作用。 BIOS,完整地说应该是ROM-BIOS,是只读存储器基本输入/输出系统的简写,它实际上是被固化到计算机中的一组程序,为计算机提供最低级的、最直接的硬件控制。准确地说,BIOS是硬件与软件程序之间的一个“转换器”或者说是接口(虽然它本身也只是一个程序),负责解决硬件的即时需求,并按软件对硬件的操作要求具体执行
免费获得新功能 升级BIOS最直接的好处就是不用花钱就能获得许多新功能,比如原来你用的是PⅡ的CPU,升级BIOS后也许就能直接使用PⅢ的CPU,不用换主板了;看着别人能用光驱来启动的计算机,自己的不行,升级BIOS后,成了;另外还能增加PnP即插即用功能、新硬盘的LBA和DMA功能、识别其它新硬件等等,简直就是免费升级电脑! 解决莫名其妙的故障 另外,升级BIOS还可以解决一些特殊的电脑故障,这
问题内容: ..如果您使用ng-model,则必须在某处有一个点。如果没有点,那么您就在做错误..” 但是,Angular.JS网站中的第一个示例(基础知识)似乎与此矛盾。是什么赋予了?自从MTV聚会以来,Angular.JS是否已更改,因为它现在对ng- model更宽容了? 问题答案: 在处理范围继承的复杂性时,这个小点非常重要。 该egghead.io视频“点”有一个很好的概述,做到这一点非
BIOS是英文Basic Input/Output System(基本输入/输出系统)的缩写,其程序储存在主板上的EPROM或Flash ROM内,作用是测试装在主板上的部件能否正常工作,并提供驱动程序接口,设定系统相关配备的组态。当你的系统配件与原CMOS参数不符合时,或CMOS参数遗失时,或系统不稳定时,就需要进入BIOS设定程序,以重新配置正确的系统组态。 进入AMI BIOS设定程序 1.
我们所使用的计算机都是由一些硬件设备组成的,而这些硬件设备会由于用户的不同需要而在品牌、类型、性能上有很大差异。例如,对于硬盘,就可能存在容量大小和接口类型等方面的不同,而不同的硬件配置所对应的参数也不同,因此,我们在使用计算机之前,一定要确定它的硬件配置和参数,并将它们记录下来,存入计算机,以便计算机启动时能够读取这些设置,保证系统正常运行。 通常情况下,我们通过设置程序对硬件系统设置参数。由于