berylliumquestion wrote: ↑Fri Dec 13, 2019 11:54 pm
So the process looks something like this:
isoboot.S --> i386.S + freeldr.spec? --> ? --> freeldr.c --> winldr.c
The first 512 bytes of setupldr.sys is in fathelp.inc, which is mostly skipped over at the entrypoint 0000:FA00 with a .byte directive coded to go to 0000:FA00. I can't really tell what's trying to say other than from the comment attached to it.
Here's the two lines that I can't read, but I understand the comments.
Code: Select all
// This code is loaded at 0000:F800 so we have to
// encode a jmp instruction to jump to 0000:FA00
.byte HEX(e9), HEX(fd), HEX(01)
Code: Select all
.byte HEX(0ff), HEX(25) // opcode of indirect jump
I can't seem find the corresponding opcodes that matches the hex values in the Appendix A Opcode Map of Intel Developer's manual for either of them.
You're right about fathelp.inc -- so it doesn't go to RealModeEntryPoint directly. However it does go there _almost_ directly.
e9 is just the regular "jmp rel16" instruction.
http://ref.x86asm.net/coder32.html is a relatively easy to read table. You can also use something like this:
Code: Select all
$ echo -ne "\xe9\xfd\x01" >tmpfile && objdump -D -bbinary -mi8086 tmpfile
tmpfile: file format binary
Disassembly of section .data:
00000000 <.data>:
0: e9 fd 01 jmp 0x200
So _then_ it jumps to RealModeEntryPoint, which loads the address of the PE file's entry point:
Code: Select all
/* Get address of entry point */
mov eax, dword ptr es:[eax + IMAGE_OPTIONAL_HEADER_AddressOfEntryPoint]
add eax, FREELDR_PE_BASE
/* Save entry point */
mov dword ptr ds:[pm_entrypoint], eax
Then it jumps to exit_to_protected, as you pointed out:
berylliumquestion wrote: ↑Fri Dec 13, 2019 11:54 pm
Now this part of the realmode/i386.S file seems kind of important. (I included a header file.)
boot/freeldr/freeldr/include/arch/pc/x86common.h:
Code: Select all
#define FREELDR_PE_BASE HEX(10000)
boot/freeldr/freeldr/arch/realmode/i386.S:
Code: Select all
add eax, FREELDR_PE_BASE
/* Save entry point */
mov dword ptr ds:[pm_entrypoint], eax
Code: Select all
inpmode:
.byte HEX(0ff), HEX(25) // opcode of indirect jump
word pm_entrypoint, 0
pm_entrypoint:
.long 0 // receives address of PE entry point
nop
This one is harder to look up in the opcode table since 0xff corresponds to different instructions and the second byte is a bit field. The disassembler can do the work for us though:
Code: Select all
$ echo -ne "\xff\x25\x78\x56\x34\x12" >tmpfile && objdump -D -bbinary -mi386 -Mintel tmpfile
tmpfile: file format binary
Disassembly of section .data:
00000000 <.data>:
0: ff 25 78 56 34 12 jmp DWORD PTR ds:0x12345678
So it's just an indirect jump (32 bit protected mode now) to whatever is stored at pm_entrypoint.
To find out the PE file's entry point, we have to look at CMake again. The default for a .sys file is DriverEntry, but it's set manually in this case:
Code: Select all
set_image_base(freeldr_pe 0x10000)
set_subsystem(freeldr_pe native)
set_entrypoint(freeldr_pe RealEntryPoint)
So we look for RealEntryPoint, which as you correctly guessed is in entry.S.
That ends up jumping to BootMain, so we finally end up in C code:
https://git.reactos.org/?p=reactos.git; ... 264a92#l43