Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么BIOS入口点以WBINVD指令开始?_Assembly_X86_Boot_Bios - Fatal编程技术网

Assembly 为什么BIOS入口点以WBINVD指令开始?

Assembly 为什么BIOS入口点以WBINVD指令开始?,assembly,x86,boot,bios,Assembly,X86,Boot,Bios,我正在研究我的机器(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 [

我正在研究我的机器(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
为了总结这一奇怪之处,此BIOS代码正在读取自身的
0xffff0
,并将字节与
0xea
进行比较,后者正是跳远的操作码:

            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
如果它发现
0xffff0
处的代码是一个远跳转,那么它将进入一个无限循环

更准确地说,APs(应用程序处理器)将在
hlt
指令处无限循环,而BSP(引导处理器)将循环回起始
0xffff0
。由于
0xffff0
处的代码不会更改,因此我们可以得出结论,BSP将始终找到
0xea
的字节,并且永远不会退出循环


那么自我检查的目的是什么?我很难相信这是一种天真的阻止修改的尝试。

尽管很难推理,但请记住,加载
mov al,字节es:[0xfff0]
没有从BIOS第一条指令中读取,即使
es
设置为
0xf000

第一条指令是从
0xFFFFF0
读取的,PCH也可能在重置时将
0xf0000-0xfffff
别名为
0xffff0000-0xffffffff
,因此当BSP启动时,它将执行您转储的代码。
IIRC,除非明确唤醒,否则AP不会启动

然后BSP将继续初始化硬件(从转储判断)。
在某个时刻,它将为
0xf0000-0xfffff
设置属性映射,以引导对内存的读写操作(或只是先写后读)。
最终结果是,当处理器(硬件线程)启动时,它将从闪存执行代码,直到执行跳远。
此时,根据实模式规则(非常类似于非实模式)正确计算
cs
base,指令将从
0xf0000-0xfffff
(即从RAM)中提取。
所有这些,而
cs
段值实际上没有改变

BSP将在某个点启动其多处理器初始化例程,在该例程中,它向每个人(包括他自己)广播一个INIT-SIPI-SIPI,该INIT-SIPI-SIPI将导致AP睡眠,并向BSP广播一个
ljmp 0xf000:0xfff0

这里的技巧是跳转的目标,
0xf000:0xfff0
,与
wbinvd
指令的总线地址不同。
可能还有其他东西,可能是另一个初始化程序

在初始化结束时,BIOS可以简单地将
0xf0000-0xfffff
的属性重置为闪存(因此可以进行软件重置),从而防止(并非有意)中间代码转储

这不是很有效,但bios通常不是代码的杰作

我没有足够的元素来确定发生了什么,我的观点是
ljmp 0xf000:0xfff0
mov al,byte es:[0xfff0]
不必从它们所在的相同区域读取。

考虑到这一点,所有的赌注都是无效的。
只有正确的逆向工程才能说明问题

关于
wbinvd
,我在评论中建议它可能与热启动功能有关,Peter Cordes建议它可能与缓存作为RAM有关。
这是有道理的,但我想永远也无法确定。

这也可能是cargo cult的一个案例,程序员认为基于谣言的指令是必要的

这实际上是标题问题的答案:

Hadi BRISH:根据BIOS和系统管理模式内部的幻灯片14,UDK2010中有wbinv指令,但后来在UDK2012中被删除。也许这与安全有关。我不知道确切是什么

我可以确认,从2016年起,我的BIOS版本上的
0xfffff0
中不存在此指令

这里有一个更紧迫的问题,那就是与0xea的比较意味着什么

0xFFFFF0
处的重置向量包含
90 90 E9 43 FC
,这是到
0xFFFFF5-3bd
的相对跳跃,即
0xfffffc38
,我的SEC核心PE32图像的入口点,来自
0xffffca18
-
0xffffffbb

0x00:  DB E3                      fninit 
0x02:  0F 6E C0                   movd   mm0, eax   //move BIST value to mm0
0x05:  0F 31                      rdtsc  
0x07:  0F 6E EA                   movd   mm5, edx
0x0a:  0F 6E F0                   movd   mm6, eax  //save tsc
0x0d:  66 33 C0                   xor    eax, eax //clear eax

0x10:  8E C0                      mov    es, ax
0x12:  8C C8                      mov    ax, cs
0x14:  8E D8                      mov    ds, ax
0x16:  B8 00 F0                   mov    ax, 0xf000
0x19:  8E C0                      mov    es, ax
0x1b:  67 26 A0 F0 FF 00 00       mov    al, byte ptr es:[0xfff0]
0x22:  3C EA                      cmp    al, 0xea
0x24:  74 0E                      je     0x34   //if ea is at ffff0h then jump to the 0xf000e05b check 

0x26:  BA F9 0C                   mov    dx, 0xcf9
0x29:  EC                         in     al, dx    //read port 0xcf9
0x2a:  3C 04                      cmp    al, 4    
0x2c:  75 25                      jne    0x53      
0x2e:  BA F9 0C                   mov    dx, 0xcf9 //perform hard reset since if CPU only reset is issued not all MSRs are restored to their defaults
0x31:  B0 06                      mov    al, 6
0x33:  EE                         out    dx, al  

0x34:  67 66 26 A1 F1 FF 00 00    mov    eax, dword ptr es:[0xfff1]
0x3c:  66 3D 5B E0 00 F0          cmp    eax, 0xf000e05b
0x42:  75 0F                      jne    0x53      //if the ptr16:16 of the EA instruction isn't 0xf000e05b, move to notwarmstart

0x44:  B9 1B 00                   mov    cx, 0x1b //if it is equal, read bsp bit from apic_base msr
0x47:  0F 32                      rdmsr  
0x49:  F6 C4 01                   test   ah, 1
0x4c:  74 41                      je     0x8f   //if the and operation with 00000001b produces a zero result i.e. it's an AP then jump to cli, hlt

0x4e:  EA F0 FF 00 F0             ljmp   0xf000:0xfff0 //if it's the BSP and legacy bios is present, far jump to 0xffff0, exiting unreal mode

notwarmstart:
0x53:  B0 01                      mov    al, 1
0x55:  E6 80                      out    0x80, al  //send 1 as a debug POST code
0x57:  66 BE 68 FF FF FF          mov    esi, 0xffffff68
0x5d:  66 2E 0F 01 14             lgdt   cs:[si] //loads 32&16 GDT pointer (not 16&6, due to 66 prefix) at 16bit address fff68 in si into GDTR (base:ffffff28 limit:003f).

//enter 16 bit protected mode//
0x62:  0F 20 C0                   mov    eax, cr0
0x65:  66 83 C8 03                or     eax, 3   //Set PE bit (bit #0) & MP bit (bit #1)
0x69:  0F 22 C0                   mov    cr0, eax  //Activate protected mode
0x6c:  0F 20 E0                   mov    eax, cr4 
0x6f:  66 0D 00 06 00 00          or     eax, 0x600 //Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
0x75:  0F 22 E0                   mov    cr4, eax

//set up selectors for 32 bit protected mode entry
0x78:  B8 18 00                   mov    ax, 0x18 //segment descriptor at 0x18 in GDT is (raw): 00cf93000000ffff
0x7b:  8E D8                      mov    ds, ax
0x7d:  8E C0                      mov    es, ax
0x7f:  8E E0                      mov    fs, ax
0x81:  8E E8                      mov    gs, ax
0x83:  8E D0                      mov    ss, ax
0x85:  66 BE 6E FF FF FF          mov    esi, 0xffffff6e
0x8b:  66 2E FF 2C                ljmp   cs:[si]   //transition to flat 32 bit protected mode and jump to address at 0x0:0xffffff6e aka. 0xffffff6e which is fffffcd8. CS contains 0 remember (it's the base that is 0xffff) so it will load the first entry.
                                                   //SEC continues at that address

0x8f:  FA                         cli    
0x90:  F4                         hlt    
.
.
我们注意到我的代码与你的不同。与
0xf000e05b
进行额外比较,并对
0xcf9
进行读/写。此外,您的系统还包含我们在
0xfffffff0
处看到的
e9
跳转代码,这是因为您必须处于UEFI引导状态,因此在
0xf0000
处没有旧版BIOS隐藏到旧版BIOS范围。在相对跳转之前,您的包含一个
wbinvd
,而我的包含2个
nop
s

edk2源代码中的一条线索是跳转到的代码称为“NotWarmStart”。代码本身就说明了问题

在我的中,如果EA位于
0xffff0
,那么它会检查
0xffff1
中的
0xf000e05b
。如果存在
0xf000e05b
,则检查BSP标志,如果是BSP标志,则跳到
0xffff0
。如果不存在
0xf000e05b
,它将跳转到16位+32位保护模式设置(称为“NotWarmStart”),然后跳转到32位平面保护模式(edk2称此PEI,但我认为PEI通常从PEI核心开始,它跳转到的代码实际上仍然是秒(鉴于此代码使用FSP设置CAR,如果BootGuard不存在,可以选择执行微码更新,然后将控制权传递给PEI core,它显然是我的SEC core PE32映像的代码部分中的一个地址,而PEI core映像条目位于
0xffe91854
))在
0x18实现
0x00:  DB E3                      fninit 
0x02:  0F 6E C0                   movd   mm0, eax   //move BIST value to mm0
0x05:  0F 31                      rdtsc  
0x07:  0F 6E EA                   movd   mm5, edx
0x0a:  0F 6E F0                   movd   mm6, eax  //save tsc
0x0d:  66 33 C0                   xor    eax, eax //clear eax

0x10:  8E C0                      mov    es, ax
0x12:  8C C8                      mov    ax, cs
0x14:  8E D8                      mov    ds, ax
0x16:  B8 00 F0                   mov    ax, 0xf000
0x19:  8E C0                      mov    es, ax
0x1b:  67 26 A0 F0 FF 00 00       mov    al, byte ptr es:[0xfff0]
0x22:  3C EA                      cmp    al, 0xea
0x24:  74 0E                      je     0x34   //if ea is at ffff0h then jump to the 0xf000e05b check 

0x26:  BA F9 0C                   mov    dx, 0xcf9
0x29:  EC                         in     al, dx    //read port 0xcf9
0x2a:  3C 04                      cmp    al, 4    
0x2c:  75 25                      jne    0x53      
0x2e:  BA F9 0C                   mov    dx, 0xcf9 //perform hard reset since if CPU only reset is issued not all MSRs are restored to their defaults
0x31:  B0 06                      mov    al, 6
0x33:  EE                         out    dx, al  

0x34:  67 66 26 A1 F1 FF 00 00    mov    eax, dword ptr es:[0xfff1]
0x3c:  66 3D 5B E0 00 F0          cmp    eax, 0xf000e05b
0x42:  75 0F                      jne    0x53      //if the ptr16:16 of the EA instruction isn't 0xf000e05b, move to notwarmstart

0x44:  B9 1B 00                   mov    cx, 0x1b //if it is equal, read bsp bit from apic_base msr
0x47:  0F 32                      rdmsr  
0x49:  F6 C4 01                   test   ah, 1
0x4c:  74 41                      je     0x8f   //if the and operation with 00000001b produces a zero result i.e. it's an AP then jump to cli, hlt

0x4e:  EA F0 FF 00 F0             ljmp   0xf000:0xfff0 //if it's the BSP and legacy bios is present, far jump to 0xffff0, exiting unreal mode

notwarmstart:
0x53:  B0 01                      mov    al, 1
0x55:  E6 80                      out    0x80, al  //send 1 as a debug POST code
0x57:  66 BE 68 FF FF FF          mov    esi, 0xffffff68
0x5d:  66 2E 0F 01 14             lgdt   cs:[si] //loads 32&16 GDT pointer (not 16&6, due to 66 prefix) at 16bit address fff68 in si into GDTR (base:ffffff28 limit:003f).

//enter 16 bit protected mode//
0x62:  0F 20 C0                   mov    eax, cr0
0x65:  66 83 C8 03                or     eax, 3   //Set PE bit (bit #0) & MP bit (bit #1)
0x69:  0F 22 C0                   mov    cr0, eax  //Activate protected mode
0x6c:  0F 20 E0                   mov    eax, cr4 
0x6f:  66 0D 00 06 00 00          or     eax, 0x600 //Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
0x75:  0F 22 E0                   mov    cr4, eax

//set up selectors for 32 bit protected mode entry
0x78:  B8 18 00                   mov    ax, 0x18 //segment descriptor at 0x18 in GDT is (raw): 00cf93000000ffff
0x7b:  8E D8                      mov    ds, ax
0x7d:  8E C0                      mov    es, ax
0x7f:  8E E0                      mov    fs, ax
0x81:  8E E8                      mov    gs, ax
0x83:  8E D0                      mov    ss, ax
0x85:  66 BE 6E FF FF FF          mov    esi, 0xffffff6e
0x8b:  66 2E FF 2C                ljmp   cs:[si]   //transition to flat 32 bit protected mode and jump to address at 0x0:0xffffff6e aka. 0xffffff6e which is fffffcd8. CS contains 0 remember (it's the base that is 0xffff) so it will load the first entry.
                                                   //SEC continues at that address

0x8f:  FA                         cli    
0x90:  F4                         hlt    
.
.
kd> !db [uc] 00000000`ffffff80
#ffffff80 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#ffffff90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#ffffffa0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#ffffffb0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#ffffffc0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#ffffffd0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#ffffffe0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 58 4d ..............XM
#fffffff0 ea 5b e0 00 f0 30 36 2f-32 33 2f 39 39 00 fc 8f .[...06/23/99...
kd> !db [uc] fff80
#   fff80 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fff90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffa0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffb0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffc0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffd0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffe0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 58 4d ..............XM
#   ffff0 ea 5b e0 00 f0 30 36 2f-32 33 2f 39 39 00 fc 8f .[...06/23/99...
 ffffff80 FF 46 A0 70 CC CC CC CC E9 1B F6 FF FF E9 26 F6  Fáp¦¦¦¦Ú.÷  Ú&÷
 ffffff90 FF FF E9 71 F6 FF FF E9 7C F6 FF FF E9 3C FD FF   Úq÷  Ú|÷  Ú<² 
 ffffffa0 FF E9 3C FD FF FF E9 75 FF FF FF 00 00 00 00 00  Ú<²  Úu   .....
 ffffffb0 00 00 00 00 00 00 00 00 04 00 00 19 44 00 00 19 ............D...
 ffffffc0 00 01 D9 FF 00 00 00 00 00 00 00 00 00 00 00 00 ..+ ............
 ffffffd0 BF 50 41 EB 1D 00 00 00 00 00 00 00 00 00 00 00 +PAÙ............
 ffffffe0 54 18 E9 FF EB FE CF 00 00 00 00 00 00 00 00 00 T.Ú Ù¦¤.........
 fffffff0 90 90 E9 43 FC 00 00 00 FB 00 00 00 00 00 E9 FF ..ÚC³...¹.....Ú 

lkd> !db fff80
#   fff80 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fff90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffa0 00 00 00 00 00 00 00 00-00 00 e9 e3 3b 00 00 00 ............;...
#   fffb0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffc0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffd0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   fffe0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#   ffff0 ea 5b e0 00 f0 30 37 2f-32 32 2f 31 36 00 fc 00 .[...07/22/16...