admin管理员组文章数量:1291103
(This question is related, but concerns x86 legacy BIOS instead of UEFI).
We are developing an OS for x86_64 using UEFI. I'm finding that while the OS boots perfectly fine in the OVMF firmware in QEMU, the computer seems to hang forever with a black screen and no activity on all 4 pieces of real hardware I have tried (a Lenovo Thinkpad, a System76 laptop, a Steam Deck, and a random x86 SBC). Worse, when putting some code at the beginning of the entry point to try to show some life (triggering an exception, writing to ConOut
, and writing to the serial port), the hang-with-no-activity result is the same, suggesting that the real hardware is failing to load the image before it ever reaches the entry point at all, or is jumping to the wrong address.
For reasons, we are rolling our own code to generate the PE image (i.e. not using any standard C tools) and cannot share that code. We can, however, share the header of the EFI as well as the first bootloader stage:
00000000 4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |MZ..............|
00000010 b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 |................|
00000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 |........!..L.!Th|
00000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f |is program canno|
00000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 |t be run in DOS |
00000070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 |mode....$.......|
00000080 50 45 00 00 64 86 03 00 00 00 00 00 00 00 00 00 |PE..d...........|
00000090 00 00 00 00 70 00 06 02 0b 02 02 26 00 10 00 00 |....p......&....|
000000a0 00 d0 16 00 00 00 00 00 00 10 00 00 00 10 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 10 00 00 00 10 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000d0 00 f0 16 00 00 10 00 00 00 00 00 00 0a 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000110 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 |................|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 |............ ..`|
00000130 00 00 00 00 00 00 00 00 00 80 11 00 00 20 00 00 |............. ..|
00000140 00 80 11 00 00 20 00 00 00 00 00 00 00 00 00 00 |..... ..........|
00000150 00 00 00 00 40 00 00 c0 00 00 00 00 00 00 00 00 |....@...........|
00000160 00 50 05 00 00 a0 11 00 00 50 05 00 00 a0 11 00 |.P.......P......|
00000170 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 c0 |............@...|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 51 52 48 89 e5 48 89 d3 48 c7 c2 54 00 21 00 52 |QRH..H..H..T.!.R|
00001010 48 ba 53 00 54 00 41 00 52 00 52 48 89 e2 48 83 |H.S.T.A.R.RH..H.|
00001020 ec 40 48 8b 4b 40 ff 51 08 48 89 ec 48 89 da 48 |[email protected]@.Q.H..H..H|
00001030 8b 42 60 68 01 00 00 00 59 89 ca 68 98 01 00 00 |.B`h....Y..h....|
00001040 41 58 68 00 00 00 01 49 89 e1 48 83 ec 48 ff 50 |AXh....I..H..H.P|
00001050 28 48 83 c4 48 5f 81 c7 00 00 08 00 57 68 00 80 |(H..H_......Wh..|
00001060 11 00 59 48 8d 35 96 0f 00 00 f3 a4 5f 48 8d 35 |..YH.5......_H.5|
00001070 8c 8f 11 00 68 7f 53 01 00 59 ad 01 3c 07 e2 fa |....h.S..Y..<...|
00001080 5a 5e 89 fc 8b 07 50 c3 00 00 00 00 00 00 00 00 |Z^....P.........|
00001090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
(Disassembly of code section at 0x1000
, which prints a message, then copies the other two sections to newly allocated pages of memory and jumps to one of them):
push rcx ; rcx contains EFI handle
push rdx ; rdx contains System Table
mov rbp, rsp
mov rbx, rdx
mov rdx, 0x210054 ; push L"T!"
push rdx
movabs rdx, 0x52004100540053 ; push L"STAR"
push rdx
mov rdx, rsp
sub rsp, 0x40
mov rcx, qword ptr [rbx + 0x40] ; ConOut
call qword ptr [rcx + 8] ; StringOutput
mov rsp, rbp
mov rdx, rbx
mov rax, qword ptr [rdx + 0x60] ; BootServices
push 1
pop rcx
mov edx, ecx
push 0x198
pop r8
push 0x1000000
mov r9, rsp
sub rsp, 0x48
call qword ptr [rax + 0x28] ; AllocatePages
add rsp, 0x48
pop rdi
add edi, 0x80000
push rdi
push 0x118000
pop rcx
lea rsi, qword ptr [rip + 0xf96] ; pointer to first section
rep movsb byte ptr es:[rdi], byte ptr [rsi]
pop rdi
lea rsi, qword ptr [rip + 0x118f8c] ; pointer to second section
push 0x1537f
pop rcx
lodsd eax, dword ptr [rsi]
add dword ptr [rdi + rax], edi
loop 0x1007a
pop rdx
pop rsi
mov esp, edi
mov eax, dword ptr [rdi]
push rax
ret
I've attempted to verify correctness by comparing to other known good EFI files, such as Limine and the EFI Shell (using the PE-Bear utility). I've also attempted to get more information by running the executable in the EFI shell and using the Intel Management Engine. The result is unfortunately the same: works perfectly in QEMU, hangs with no output on real hardware.
ADDENDUM: The watchdog timer has no effect - the real hardware machine is still in the same hung state after 10 minutes. Also, Ctrl+Alt+Del does not work - I have to power cycle the machine.
EDIT 1: @prl pointed out that we need to provide the shadow register space for EFI function calls. That does fix some issues shown in QEMU, but changes nothing on real hardware. I have updated the dump and disassembly above.
(This question is related, but concerns x86 legacy BIOS instead of UEFI).
We are developing an OS for x86_64 using UEFI. I'm finding that while the OS boots perfectly fine in the OVMF firmware in QEMU, the computer seems to hang forever with a black screen and no activity on all 4 pieces of real hardware I have tried (a Lenovo Thinkpad, a System76 laptop, a Steam Deck, and a random x86 SBC). Worse, when putting some code at the beginning of the entry point to try to show some life (triggering an exception, writing to ConOut
, and writing to the serial port), the hang-with-no-activity result is the same, suggesting that the real hardware is failing to load the image before it ever reaches the entry point at all, or is jumping to the wrong address.
For reasons, we are rolling our own code to generate the PE image (i.e. not using any standard C tools) and cannot share that code. We can, however, share the header of the EFI as well as the first bootloader stage:
00000000 4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |MZ..............|
00000010 b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 |................|
00000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 |........!..L.!Th|
00000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f |is program canno|
00000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 |t be run in DOS |
00000070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 |mode....$.......|
00000080 50 45 00 00 64 86 03 00 00 00 00 00 00 00 00 00 |PE..d...........|
00000090 00 00 00 00 70 00 06 02 0b 02 02 26 00 10 00 00 |....p......&....|
000000a0 00 d0 16 00 00 00 00 00 00 10 00 00 00 10 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 10 00 00 00 10 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000d0 00 f0 16 00 00 10 00 00 00 00 00 00 0a 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000110 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00 |................|
00000120 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 |............ ..`|
00000130 00 00 00 00 00 00 00 00 00 80 11 00 00 20 00 00 |............. ..|
00000140 00 80 11 00 00 20 00 00 00 00 00 00 00 00 00 00 |..... ..........|
00000150 00 00 00 00 40 00 00 c0 00 00 00 00 00 00 00 00 |....@...........|
00000160 00 50 05 00 00 a0 11 00 00 50 05 00 00 a0 11 00 |.P.......P......|
00000170 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 c0 |............@...|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 51 52 48 89 e5 48 89 d3 48 c7 c2 54 00 21 00 52 |QRH..H..H..T.!.R|
00001010 48 ba 53 00 54 00 41 00 52 00 52 48 89 e2 48 83 |H.S.T.A.R.RH..H.|
00001020 ec 40 48 8b 4b 40 ff 51 08 48 89 ec 48 89 da 48 |[email protected]@.Q.H..H..H|
00001030 8b 42 60 68 01 00 00 00 59 89 ca 68 98 01 00 00 |.B`h....Y..h....|
00001040 41 58 68 00 00 00 01 49 89 e1 48 83 ec 48 ff 50 |AXh....I..H..H.P|
00001050 28 48 83 c4 48 5f 81 c7 00 00 08 00 57 68 00 80 |(H..H_......Wh..|
00001060 11 00 59 48 8d 35 96 0f 00 00 f3 a4 5f 48 8d 35 |..YH.5......_H.5|
00001070 8c 8f 11 00 68 7f 53 01 00 59 ad 01 3c 07 e2 fa |....h.S..Y..<...|
00001080 5a 5e 89 fc 8b 07 50 c3 00 00 00 00 00 00 00 00 |Z^....P.........|
00001090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
(Disassembly of code section at 0x1000
, which prints a message, then copies the other two sections to newly allocated pages of memory and jumps to one of them):
push rcx ; rcx contains EFI handle
push rdx ; rdx contains System Table
mov rbp, rsp
mov rbx, rdx
mov rdx, 0x210054 ; push L"T!"
push rdx
movabs rdx, 0x52004100540053 ; push L"STAR"
push rdx
mov rdx, rsp
sub rsp, 0x40
mov rcx, qword ptr [rbx + 0x40] ; ConOut
call qword ptr [rcx + 8] ; StringOutput
mov rsp, rbp
mov rdx, rbx
mov rax, qword ptr [rdx + 0x60] ; BootServices
push 1
pop rcx
mov edx, ecx
push 0x198
pop r8
push 0x1000000
mov r9, rsp
sub rsp, 0x48
call qword ptr [rax + 0x28] ; AllocatePages
add rsp, 0x48
pop rdi
add edi, 0x80000
push rdi
push 0x118000
pop rcx
lea rsi, qword ptr [rip + 0xf96] ; pointer to first section
rep movsb byte ptr es:[rdi], byte ptr [rsi]
pop rdi
lea rsi, qword ptr [rip + 0x118f8c] ; pointer to second section
push 0x1537f
pop rcx
lodsd eax, dword ptr [rsi]
add dword ptr [rdi + rax], edi
loop 0x1007a
pop rdx
pop rsi
mov esp, edi
mov eax, dword ptr [rdi]
push rax
ret
I've attempted to verify correctness by comparing to other known good EFI files, such as Limine and the EFI Shell (using the PE-Bear utility). I've also attempted to get more information by running the executable in the EFI shell and using the Intel Management Engine. The result is unfortunately the same: works perfectly in QEMU, hangs with no output on real hardware.
ADDENDUM: The watchdog timer has no effect - the real hardware machine is still in the same hung state after 10 minutes. Also, Ctrl+Alt+Del does not work - I have to power cycle the machine.
EDIT 1: @prl pointed out that we need to provide the shadow register space for EFI function calls. That does fix some issues shown in QEMU, but changes nothing on real hardware. I have updated the dump and disassembly above.
Share Improve this question edited Feb 14 at 16:07 TheHans255 asked Feb 13 at 21:52 TheHans255TheHans255 2,2552 gold badges24 silver badges40 bronze badges 1- In my experience, this a symptom of an unhandled fault. I found UEFI programming much easier once I had a reliable fault handler that printed the processor state and returned to the EFI shell. – prl Commented Feb 14 at 5:06
1 Answer
Reset to default 1It is calling StringOutput without aligning the stack nor allocating the required 32 bytes of shadow space at the top of the stack before the call.
Add sub rsp, 0x28
before the call and I expect you will see your start message.
本文标签:
版权声明:本文标题:uefi - EFI application hangs without running on real hardware, but works perfectly in QEMU OVMF - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741504720a2382250.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论