I'm currently writing an UEFI OS loader. My goal is to load a 32-bit multiboot compliant kernel. Loading the kernel to memory and relocating it to its final destination is not a big deal using UEFI boot-services.
However, jumping to the kernels start address (after exiting boot services) failes on qemu (TianoCore Firmware-Image) with a "general protection fault".
My entry address is "0x01302298". The code just before jumping to the start address looks like this:
Dump of assembler code for function call_kernel:
0x000000001ead3b31 <+0>: push %rbp
0x000000001ead3b32 <+1>: mov %rsp,%rbp
0x000000001ead3b35 <+4>: sub $0x8,%rsp
0x000000001ead3b39 <+8>: mov %rdi,-0x8(%rbp)
=> 0x000000001ead3b3d <+12>: mov -0x8(%rbp),%rax
0x000000001ead3b41 <+16>: jmpq *%rax
The next instruction (which is expect) would be:
a3 bc 7b 31 01 mov %eax,0x1317bbc
Instead gdb tells me, that the next instruction at this address is
=> 0x1302298: movabs %eax,0x8ed88c6601317bbc
I've some theories (but no clue) what happens:
- The firmware puts the cpu into x86_64-"long mode", this leads to miss-interpretation of the next instruction (which is a 32-bit instruction)
- The last jump instruction itself is wrong: -somehow- a 32-bit jump instruction has to be used.
Can someone give me a hint?