==== Tracing ==== See [[ida_pro_tracing]] and [[radare2_tracing]] ==== Other firmares ==== * [[embedded_controller]] * [[intel_amt]] * [[video_bios]] ==== Prerequisites ==== 1. radare2 git clone git://github.com/radare/radare2 2. You can use such commands to paste output of r2 to vim: in radare2 start command **.:8080** and in vim use :r!echo x|ncat 127.0.0.1 8080 You should disable color output for that: e scr.color=false ==== All kind of BIOSes ==== Open bios image just typing r2 bios_image.bin It should be opened automatically, created segment relocation and jumped directly on entry point: [f000:fff0]> But, if it not yet recognized automatically, you can do this by your hands: 1. Open bios file with radare2 using this command: r2 -e asm.bits=16 -e io.va=true bios_image.bin 2. Do bootblock segment relocation: [0x00000000]> S $s-0x10000 0xf000:0x0000 0x10000 0x10000 bootblk rwx where '$s' - variable, file size (see output of '???' command) You can also set DOS-like addressing notation: [0x00000000]> e asm.segoff=true [0000:0000]> 3. go to 0xf000:0xfff0, where BIOS starts [0000:0000]> s 0xf000:0xfff0 You can seek also by **s section.bootblk+0xfff0** Also you can add flags base too: [0000:0000]> fb section.bootblk ==== AMIBIOS ==== See example here http://xvilka.me/ami_bios.bin Download example from http://xvilka.me/asrock_p4i65g.bin and open it as usual. Also you can download r2 database file with all mentioned stuff (and more) from http://xvilka.me/asrock_p4i65g.r2 (Just load ut after loading *.bin file using '.' command). It is based on ICH5 southbridge, download datasheet here http://www.intel.com/content/dam/doc/datasheet/82801eb-82801er-io-controller-hub-datasheet.pdf 4. Disassembly, set flag to this as bios_entry [f000:fff0]> pd 1; f entry = 0xfff0 [f000:fff0]> f entry_j 1 0xf000:<addr> where <addr> shown in previous command or just run [f000:fff0]> f entry_j 1 `pi 1~[2]` which take addr from that jump automatically 5. Jump table. From previous entry we have found jump to table of jumps. Int our case it is 34 jumps (found by counting 'jmp' opcode before first 'call' opcode). 'Question 1' - how to count these jumps??? Lets see them: [f000:0040]> pd 34 f000:0040 e9cd00 jmp word 0x111 f000:0043 e94a5c jmp word 0x5c90 f000:0046 e9e50b jmp word 0xc2e f000:0049 e98011 jmp word 0x11cc f000:004c e9a70c jmp word 0xcf6 f000:004f e91246 jmp word 0x4664 f000:0052 e97710 jmp word 0x10cc f000:0055 e9564b jmp word 0x4bae f000:0058 e9624c jmp word 0x4cbd f000:005b e9c34b jmp word 0x4c21 f000:005e e9df48 jmp word 0x4940 f000:0061 e94449 jmp word 0x49a8 f000:0064 e92f57 jmp word 0x5796 f000:0067 e9e54c jmp word 0x4d4f f000:006a e9265c jmp word 0x5c93 f000:006d e9bf00 jmp word 0x12f f000:0070 e92104 jmp word 0x494 f000:0073 e9eb05 jmp word 0x661 f000:0076 e9f105 jmp word 0x66a f000:0079 e93c4d jmp word 0x4db8 f000:007c e96f4c jmp word 0x4cee f000:007f e9cd00 jmp word 0x14f f000:0082 e93a48 jmp word 0x48bf f000:0085 e9fc52 jmp word 0x5384 f000:0088 e9cd00 jmp word 0x158 f000:008b e9a54a jmp word 0x4b33 f000:008e e9ca00 jmp word 0x15b f000:0091 e9ca00 jmp word 0x15e f000:0094 e9ca00 jmp word 0x161 f000:0097 e95211 jmp word 0x11ec f000:009a e9940b jmp word 0xc31 f000:009d e9bf0e jmp word 0xf5f f000:00a0 e9a348 jmp word 0x4946 f000:00a3 e9d200 jmp word 0x178 [f000:0040]> Lets mark these jumps as _j1 - _j34 : [f000:0040]> 6. First function from jump table [f000:0040]> s 0f000:`pi 1~[2]` [f000:0110]> pd f000:0110 fa cli f000:0111 fc cld f000:0112 668be0 mov esp, eax f000:0115 8cc8 mov ax, cs f000:0117 8ed0 mov ss, ax f000:0119 668bea mov ebp, edx f000:011c b0d0 mov al, 0xd0 f000:011e e680 out 0x80, al f000:0120 bf2601 mov di, 0x126 f000:0123 e91a04 jmp word 0x540 f000:0126 8cc8 mov ax, cs f000:0128 8ed8 mov ds, ax f000:012a 8ec0 mov es, ax f000:012c e914ff jmp word 0x43 f000:012f b0d1 mov al, 0xd1 f000:0131 e680 out 0x80, al f000:0133 b00c mov al, 0xc f000:0135 e661 out 0x61, al f000:0137 be9004 mov si, 0x490 f000:013a 81fe9204 cmp si, 0x492 f000:013e 730c jae 0xf014c .... Lets see, what we got: line **f000:011e out 0x80, al** - POST code, with 0xD0 value in this case add comment for that: [f000:0110]> CCa f000:011e D0 POST CODE See also line **f000:0120 mov di, 0x126**, where 0x126 is offset to next+1 instuction Looks suspicios, isnt it? Let see what on addr f000:0540 [f000:0540]> pd f000:0540 6633c0 xor eax, eax f000:0543 0fa2 cpuid f000:0545 6681fb47656e75 cmp ebx, 0x756e6547 f000:054c 7404 jz 0xf0552 f000:054e fa cli f000:054f f4 hlt f000:0550 ebfc jmp 0xf054e f000:0552 0f08 invd f000:0554 0f6eff movd mm7, edi f000:0557 668bc4 mov eax, esp f000:055a e9c806 jmp word 0xc25 Here we are trying to check CPU vendor (0x756e6547 == 'enuG', which is part of 'Genuine Intel'), one deadloop: .-> f000:054f f4 hlt `=< f000:0550 ebfc jmp 0xf054e and one local jump: f000:054c jz 0xf0552 ... f000:0552 invd ... === PCI Access === [f000:12fd]> pd f000:12fd 668be2 mov esp, edx f000:1300 66c1ec10 shr esp, 0x10 f000:1304 660f73fa02 pslldq xmm2, 0x2 f000:1309 660fc4d400 pinsrw xmm2, sp, 0x0 f000:130e 660f73fa02 pslldq xmm2, 0x2 f000:1313 660fc4d200 pinsrw xmm2, dx, 0x0 f000:1318 baf80c mov dx, 0xcf8 f000:131b 660d00000080 or eax, 0x80000000 f000:1321 6683e0fc and eax, 0xfffffffc f000:1325 66ef out dx, eax f000:1327 bafc0c mov dx, 0xcfc f000:132a 668bc3 mov eax, ebx f000:132d 66ef out dx, eax f000:132f 660f7ed2 movd edx, xmm2 f000:1333 660f73da04 psrldq xmm2, 0x4 f000:1338 660fc5e400 pextrw esp, xmm4, 0x0 f000:133d 660f73dc02 psrldq xmm4, 0x2 f000:1342 ffe4 jmp sp This is **PCI_WriteDword_SSE(uint32_t pci_addr<eax>, uint32_t val<ebx>)** function f000:1344 668be1 mov esp, ecx f000:1347 66c1ec10 shr esp, 0x10 f000:134b 660f73f902 pslldq xmm1, 0x2 f000:1350 660fc4cc00 pinsrw xmm1, sp, 0x0 f000:1355 660f73f902 pslldq xmm1, 0x2 f000:135a 660fc4c900 pinsrw xmm1, cx, 0x0 f000:135f 668be2 mov esp, edx f000:1362 66c1ec10 shr esp, 0x10 f000:1366 660f73fa02 pslldq xmm2, 0x2 f000:136b 660fc4d400 pinsrw xmm2, sp, 0x0 f000:1370 660f73fa02 pslldq xmm2, 0x2 f000:1375 660fc4d200 pinsrw xmm2, dx, 0x0 f000:137a 8bc8 mov cx, ax f000:137c baf80c mov dx, 0xcf8 f000:137f 660d00000080 or eax, 0x80000000 f000:1385 6683e0fc and eax, 0xfffffffc f000:1389 66ef out dx, eax f000:138b bafc0c mov dx, 0xcfc f000:138e 83e102 and cx, 0x2 f000:1391 03d1 add dx, cx f000:1393 8bc3 mov ax, bx f000:1395 ef out dx, ax f000:1396 660f7ed2 movd edx, xmm2 f000:139a 660f73da04 psrldq xmm2, 0x4 f000:139f 660f7ec9 movd ecx, xmm1 f000:13a3 660f73d904 psrldq xmm1, 0x4 f000:13a8 660fc5e400 pextrw esp, xmm4, 0x0 f000:13ad 660f73dc02 psrldq xmm4, 0x2 f000:13b2 ffe4 jmp sp This is **PCI_WriteWord_SSE(uint32_t pci_addr<eax>, uint16_t val<bx>)** function f000:13b4 668be1 mov esp, ecx f000:13b7 66c1ec10 shr esp, 0x10 f000:13bb 660f73f902 pslldq xmm1, 0x2 f000:13c0 660fc4cc00 pinsrw xmm1, sp, 0x0 f000:13c5 660f73f902 pslldq xmm1, 0x2 f000:13ca 660fc4c900 pinsrw xmm1, cx, 0x0 f000:13cf 668be2 mov esp, edx f000:13d2 66c1ec10 shr esp, 0x10 f000:13d6 660f73fa02 pslldq xmm2, 0x2 f000:13db 660fc4d400 pinsrw xmm2, sp, 0x0 f000:13e0 660f73fa02 pslldq xmm2, 0x2 f000:13e5 660fc4d200 pinsrw xmm2, dx, 0x0 f000:13ea 8bc8 mov cx, ax f000:13ec baf80c mov dx, 0xcf8 f000:13ef 660d00000080 or eax, 0x80000000 f000:13f5 6683e0fc and eax, 0xfffffffc f000:13f9 66ef out dx, eax f000:13fb bafc0c mov dx, 0xcfc f000:13fe 83e103 and cx, 0x3 f000:1401 03d1 add dx, cx f000:1403 8ac3 mov al, bl f000:1405 ee out dx, al f000:1406 660f7ed2 movd edx, xmm2 f000:140a 660f73da04 psrldq xmm2, 0x4 f000:140f 660f7ec9 movd ecx, xmm1 f000:1413 660f73d904 psrldq xmm1, 0x4 f000:1418 660fc5e400 pextrw esp, xmm4, 0x0 f000:141d 660f73dc02 psrldq xmm4, 0x2 f000:1422 ffe4 jmp sp This is **PCI_WriteByte_SSE(uint32_t pci_addr<eax>, uint8_t val<bl>)** function f000:1424 668be2 mov esp, edx f000:1427 66c1ec10 shr esp, 0x10 f000:142b 660f73fa02 pslldq xmm2, 0x2 f000:1430 660fc4d400 pinsrw xmm2, sp, 0x0 f000:1435 660f73fa02 pslldq xmm2, 0x2 f000:143a 660fc4d200 pinsrw xmm2, dx, 0x0 f000:143f baf80c mov dx, 0xcf8 f000:1442 660d00000080 or eax, 0x80000000 f000:1448 6683e0fc and eax, 0xfffffffc f000:144c 66ef out dx, eax f000:144e bafc0c mov dx, 0xcfc f000:1451 66ed in eax, dx f000:1453 660f7ed2 movd edx, xmm2 f000:1457 660f73da04 psrldq xmm2, 0x4 f000:145c 660fc5e400 pextrw esp, xmm4, 0x0 f000:1461 660f73dc02 psrldq xmm4, 0x2 f000:1466 ffe4 jmp sp === ROM Call === 1. Go to **f000:0b3c** [f000:0b3c]> pd f000:0b3c 8eec mov gs, sp f000:0b3e 8ee3 mov fs, bx f000:0b40 bc460b mov sp, 0xb46 f000:0b43 e99af8 jmp word 0x3e0 f000:0b46 48 dec ax f000:0b47 0b6681 or sp, [bp-0x7f] f000:0b4a ee out dx, al were function, which is calling from f000:0b43 (jmp word f000:0x3e0) is **get_decomp_block_size** [f000:03e0]> pd f000:03e0 662e8b0ed7ff mov ecx, [cs:0xffd7] f000:03e6 668bf1 mov esi, ecx f000:03e9 66f7de neg esi f000:03ec c3 ret ;-------------- So, we have jmp to function, which is to near return. This is ROM call convention (see book from Darmawan Salihun). So, we need fix previous function to properly handle it. We are placing **0xb46** to **sp** before jump. This mean, that code at f000:0b46 should be word data: f000:0b46 48 dec ax f000:0b47 0b6681 or sp, [bp-0x7f] f000:0b4a ee out dx, al **48 0b** - here our word. This mean, that rest of code completely wrong. Lets fix that. [f000:0b3c]> Cd 2 @ f000:0b46 ... [some reversing process]... === SMBus === First, find SMB_BASE addr (see 14.1.8 from ICH5 pdf), it is 0x400 for our mainboard. Then find SMBus registers themselves: SMB_BASE + 0x1 - HST_STS (Host Status) SMB_BASE + 0x2 - HST_CNT (Host Control) SMB_BASE + 0x3 - HST_CMD (Host Command) SMB_BASE + 0x4 - XMIT_SLVA (Transmit Slave Address) SMB_BASE + 0x5 - HST_D0 (Host Data 0) SMB_BASE + 0x6 - HST_D1 (Host Data 1) SMB_BASE + 0x7 - HOST_BLOCK_DB (Host Block Data Byte) ... SMBus reading/writing. So, we've found some SMBus function, and we know, that 0x5786 - offset of **SMBus_ICH5_Reg_Write_Byte_SL** function, and 0x578e - offset of **SMBus_ICH5_Reg_Read_Byte_SL** function. [f000:574d]> pd 24 f000:574d b8d304 mov ax, 0x4d3 f000:5750 bf5557 mov di, 0x5755 ,=< f000:5753 eb31 jmp 0x5786 | f000:5755 66c1c008 rol eax, 0x8 | f000:5759 0c80 or al, 0x80 | f000:575b b403 mov ah, 0x3 | f000:575d bf6257 mov di, 0x5762 ,==< f000:5760 eb24 jmp 0x5786 || f000:5762 b84802 mov ax, 0x248 || f000:5765 bf6a57 mov di, 0x576a ,===< f000:5768 eb1c jmp 0x5786 ||| f000:576a b93075 mov cx, 0x7530 ||| f000:576d e6ed out 0xed, al ||| f000:576f e2fc loop 0x576d ||| f000:5771 b8ff00 mov ax, 0xff ||| f000:5774 bf7957 mov di, 0x5779 ,====< f000:5777 eb0d jmp 0x5786 |||| f000:5779 b405 mov ah, 0x5 |||| f000:577b bf8057 mov di, 0x5780 |||| f000:577e eb0e jmp 0x578e |||| f000:5780 660fcf bswap edi |||| f000:5783 f8 clc |||| f000:5784 ffe7 jmp di |||| ; -------- SMBus_ICH5_Reg_Write_Byte_SL: ````-> f000:5786 ba0004 mov dx, 0x400 Add these functions: [f000:574d]> af+ f000:5786 8 SMBus_ICH5_Reg_Write_Byte_SL [f000:574d]> af+ f000:578e 8 SMBus_ICH5_Reg_Read_Byte_SL where 8 - size of both functions in bytes. "_SL" prefix means "stackless" (just my internal notation). Lets add more metainfo, comments and so on: [f000:574d]> "CCa f000:5786 void SMBus_ICH5_Reg_Write_Byte_SL(uint8_t reg<ah>, uint8_t value<al>);" [f000:574d]> "CCa f000:578e uint8_t SMBus_ICH5_Reg_Read_Byte_SL<al>(uint8_t reg<ah>);" Note, that you should quote **whole** r2 command to mask special symbols **';'**, **'>'** and **'<'**. Then add few comments: [f000:574d]> "CCa 0xf000:0x574d value = 0xD3; reg = 0x4; // XMIT_SLVA - Transmit Slave Address" [f000:574d]> "CCa 0xf000:0x575b reg = 0x3; // HST_CMD - Host Command" [f000:574d]> "CCa 0xf000:0x5762 value = 0x48; reg = 0x2; // HST_CNT - Host Control" Also add these local labels: [f000:574d]> f .SMB_Send_CMD @ 0xf000:0x5755 [f000:574d]> f .SMB_Prepare_Controller @ 0xf000:0x5762 [f000:574d]> f .SMB_Read_Data @ 0xf000:0x5779 [f000:574d]> f .SMB_delay_loop @ 0xf000:0x576d And here is what we have got (in VISUAL mode - **Vp** command to enter): [0x000f574d 255 asrock_p4i65g.bin]> pd $h ; ; value = 0xD3; reg = 0x4; // XMIT_SLVA - Transmit Slave Address f000:574d b8d304 mov ax, 0x4d3 f000:5750 bf5557 mov di, 0x5755 ,=< f000:5753 eb31 jmp 0x5786 | ; -------- SMB_Send_CMD: | f000:5755 66c1c008 rol eax, 0x8 | f000:5759 0c80 or al, 0x80 ; ; value = 0x3; // HST_CMD - Host Command | f000:575b b403 mov ah, 0x3 | f000:575d bf6257 mov di, 0x5762 ,==< f000:5760 eb24 jmp 0x5786 ; ; value = 0x48; reg = 0x2; // HST_CNT - Host Control || ; -------- SMB_Prepare_Controller: || f000:5762 b84802 mov ax, 0x248 || f000:5765 bf6a57 mov di, 0x576a ,===< f000:5768 eb1c jmp 0x5786 ||| f000:576a b93075 mov cx, 0x7530 ||| ; -------- SMB_delay_loop: ||| f000:576d e6ed out 0xed, al ||| f000:576f e2fc loop 0x576d ||| f000:5771 b8ff00 mov ax, 0xff ||| f000:5774 bf7957 mov di, 0x5779 ,====< f000:5777 eb0d jmp 0x5786 |||| ; -------- SMB_Read_Data: |||| f000:5779 b405 mov ah, 0x5 |||| f000:577b bf8057 mov di, 0x5780 ,=====< f000:577e eb0e jmp 0x578e ||||| f000:5780 660fcf bswap edi ||||| f000:5783 f8 clc ||||| f000:5784 ffe7 jmp di ; ; void SMBus_ICH5_Reg_Write_Byte_SL(uint8_t reg<ah>, uint8_t value<al>); / function: SMBus_ICH5_Reg_Write_Byte_SL (8) | |````-> f000:5786 ba0004 mov dx, 0x400 | | f000:5789 8ad4 mov dl, ah | | f000:578b ee out dx, al \ | f000:578c ffe7 jmp di ; ; uint8_t SMBus_ICH5_Reg_Read_Byte_SL<al>(uint8_t reg<ah>); / function: SMBus_ICH5_Reg_Read_Byte_SL (8) | `-----> f000:578e ba0004 mov dx, 0x400 | f000:5791 8ad4 mov dl, ah | f000:5793 ec in al, dx \ f000:5794 ffe7 jmp di ,======< f000:5796 7426 jz 0x57be | f000:5798 b87000 mov ax, 0x70 | f000:579b 90 nop | f000:579c bca257 mov sp, 0x57a2 | f000:579f e9b9f2 jmp 0x4a5b | f000:57a2 a4 movsb | f000:57a3 57 push di | f000:57a4 b87200 mov ax, 0x72 ==== Award ==== ==== Phoenix ==== ==== HP BIOS ==== See example here http://xvilka.me/hp_bios.bin 1. Disassembly, set flag to this as bios_entry Note, that instead of long jump HP bioses widely using short jumps, so you should add **0xf000:** prefix in these jumps. [f000:fff0]> pd 1; f entry = 0xfff0 [f000:fff0]> f entry_j 1 0xf000:<addr> where <addr> shown in previous command or just run [f000:fff0]> f entry_j 1 0f000:`pi 1~[2]` which take addr from that jump automatically ==== UEFI ==== === Phoenix === See example here http://xvilka.me/phx_uefi.bin 1. Open bios file with radare2 using this command: r2 -e asm.bits=32 -e io.va=true phx_uefi.bin You should choose valid asm.bits value due to arch of image. 2. Do bootblock segment relocation: [0x00000000]> S $s-0x10000 0xf000:0x0000 0x10000 0x10000 bootblk rwx where '$s' - variable, file size (see output of '???' command) Then set this as 16bit segment [0x00000000]> Sa x86 16 @ 0xf000:0x0000 You can check result by typing just 'S' command. You can also set DOS-like addressing notation: [0x00000000]> e asm.segoff=true [0000:0000]> 3. go to 0xf000:0xfff0, where BIOS starts [0000:0000]> s 0xf000:0xfff0 You can seek also by **s section.bootblk+0xfff0** Also you can add flags base too: [0000:0000]> fb section.bootblk 4. Disassembly, set flag to this as bios_entry [f000:fff0]> pd 1; f entry = 0xfff0 f000:fff0 e908ff jmp word 0xfefb [f000:fff0]> f entry_j 1 <addr> where <addr> shown in previous command or just run [f000:fff0]> f entry_j 1 0xf000:`pi 1~[2]` which take addr from that jump automatically 5. Go to **entry_j** [f000:fff0]> s entry_j; pd 1 ; -------- entry_j: f000:fefb e913fd jmp word 0xfc11 Call it 'boot' for example: [f000:fefb]> f boot 1 0xf000:fc11 Then go to this addr **s boot** and do disassembly: [f000:fc11]> s boot; pd ; -------- boot: 0x000ffc11 66b801000000 mov eax, 0x1 0x000ffc17 0fa2 cpuid 0x000ffc19 660fbaea1a bts edx, 0x1a ,=< 0x000ffc1e 7309 jae 0xffc29 | 0x000ffc20 0f20e0 mov eax, cr4 | 0x000ffc23 80cc02 or ah, 0x2 | 0x000ffc26 0f22e0 mov cr4, eax `-> 0x000ffc29 6633c0 xor eax, eax 0x000ffc2c fec0 inc al 0x000ffc2e 0fa2 cpuid 0x000ffc30 6625f00fff0f and eax, 0xfff0ff0 0x000ffc36 663d70060100 cmp eax, 0x10670 ,==< 0x000ffc3c 7408 jz 0xffc46 | 0x000ffc3e 3df006 cmp ax, 0x6f0 ,===< 0x000ffc41 7403 jz 0xffc46 || 0x000ffc43 e9b802 jmp word 0xfefe ``--> 0x000ffc46 b060 mov al, 0x60 0x000ffc48 ba7000 mov dx, 0x70 0x000ffc4b ee out dx, al 0x000ffc4c e6ed out 0xed, al 0x000ffc4e ba7100 mov dx, 0x71 0x000ffc51 ec in al, dx 0x000ffc52 0fbae800 bts ax, 0x0 0x000ffc56 0f82a402 jb word 0xfefe 0x000ffc5a 66b9ee000000 mov ecx, 0xee 0x000ffc60 0f32 rdmsr 0x000ffc62 0fbae802 bts ax, 0x2 0x000ffc66 0f30 wrmsr 0x000ffc68 e99302 jmp word 0xfefe Here we're checking for CPU family and features 0x000ffc6b 66b801000000 mov eax, 0x1 0x000ffc71 0fa2 cpuid 0x000ffc73 668bc8 mov ecx, eax 0x000ffc76 67268b46ec mov ax, [es:esi-0x14] 0x000ffc7b 83e818 sub ax, 0x18 0x000ffc7e bb0008 mov bx, 0x800 0x000ffc81 33d2 xor dx, dx 0x000ffc83 f7f3 div bx 0x000ffc85 668bd1 mov edx, ecx 0x000ffc88 8bc8 mov cx, ax 0x000ffc8a 67662639560c cmp [es:esi+0xc], edx ,=< 0x000ffc90 7514 jnz 0xffca6 | 0x000ffc92 66b979000000 mov ecx, 0x79 | 0x000ffc98 668bc6 mov eax, esi | 0x000ffc9b 6683c030 add eax, 0x30 | 0x000ffc9f 6633d2 xor edx, edx | 0x000ffca2 0f30 wrmsr ,==< 0x000ffca4 eb09 jmp 0xffcaf |`-> 0x000ffca6 6681c600080000 add esi, 0x800 | 0x000ffcad e2db loop 0xffc8a `--> 0x000ffcaf 66b9a0010000 mov ecx, 0x1a0 0x000ffcb5 0f32 rdmsr 0x000ffcb7 6683e0fe and eax, 0xfffffffe 0x000ffcbb 0f30 wrmsr 0x000ffcbd e97702 jmp word 0xff37 0x000ffcc0 66b801000000 mov eax, 0x1 0x000ffcc6 0fa2 cpuid 0x000ffcc8 80e40f and ah, 0xf 0x000ffccb 80fc0f cmp ah, 0xf 0x000ffcce 7504 jnz 0xffcd4 ,=< 0x000ffcd0 eb13 jmp 0xffce5 | 0x000ffcd2 eb0e jmp 0xffce2 | 0x000ffcd4 80fc06 cmp ah, 0x6 ,==< 0x000ffcd7 7505 jnz 0xffcde || 0x000ffcd9 e9bc00 jmp word 0xfd98 === AMI (Aptio) === === Insyde ===