#include #include #include EXTERN BootMain:PROC // EXTERN cmdline:DWORD EXTERN DiskStopFloppyMotor:PROC #ifdef _USE_ML EXTERN __bss_start__:FWORD EXTERN __bss_end__:FWORD #endif .code64 PUBLIC RealEntryPoint RealEntryPoint: /* Setup segment selectors */ mov ax, LMODE_DS mov ds, ax mov es, ax mov fs, ax mov gs, ax // mov ss, ax //mov word ptr [HEX(b8000)], HEX(0e00) + '1' /* Setup long mode stack */ mov rsp, qword ptr [stack64] /* Continue execution */ jmp qword ptr [ContinueAddress] ContinueAddress: .quad offset FrldrStartup FrldrStartup: /* Store BootDrive and BootPartition */ mov al, byte ptr [BSS_BootDrive] mov byte ptr [FrldrBootDrive], al xor eax, eax mov al, byte ptr [BSS_BootPartition] mov dword ptr [FrldrBootPartition], eax /* Patch long jump with real mode entry point */ mov eax, dword ptr [BSS_RealModeEntry] mov dword ptr [AddressOfRealModeEntryPoint], eax /* Clean out BSS */ xor rax, rax mov rdi, offset __bss_start__ mov rcx, offset __bss_end__ + 7 sub rcx, rdi shr rcx, 3 rep stosq /* Pass the command line to BootMain */ // mov rcx, offset cmdline xor rcx, rcx /* GO! */ call BootMain /* We should never get here */ stop: jmp short stop nop nop PUBLIC Reboot Reboot: /* Stop the floppy drive motor */ call DiskStopFloppyMotor /* Set the function ID and switch to real mode (we don't return) */ mov bx, FNID_Reboot jmp SwitchToReal /* * VOID __cdecl Relocator16Boot( * IN REGS* In, * IN USHORT StackSegment, * IN USHORT StackPointer, * IN USHORT CodeSegment, * IN USHORT CodePointer); * * RETURNS: Nothing. * * NOTE: The implementation of this function is similar to that of Int386(), * with the proviso that no attempt is done to save the original values of * the registers since we will not need them anyway, as we do not return back * to the caller but instead place the machine in a permanent new CPU state. */ PUBLIC Relocator16Boot Relocator16Boot: /* Save home registers */ mov qword ptr [rsp + 8], rcx mov word ptr [rsp + 16], dx mov word ptr [rsp + 24], r8w mov word ptr [rsp + 32], r9w #if 0 /* Save non-volatile registers */ push rbx push rsi push rdi #endif /* Copy input registers */ mov rsi, qword ptr [rsp + 8] mov rdi, BSS_RegisterSet mov rcx, REGS_SIZE / 4 rep movsd /* Set the stack segment/offset */ // Since BSS_CallbackReturn contains a ULONG, store in its high word // the stack segment and in its low word the stack offset. mov ax, word ptr [rsp + 16] shl eax, 16 mov ax, word ptr [rsp + 24] mov dword ptr [BSS_CallbackReturn], eax /* * Set the code segment/offset (Copy entry point) * NOTE: We permanently *ERASE* the contents of ds:[BSS_RealModeEntry] * but it is not a problem since we are going to place the machine in * a permanent new CPU state. */ // Since BSS_RealModeEntry contains a ULONG, store in its high word // the code segment and in its low word the code offset. mov ax, word ptr [rsp + 32] shl eax, 16 mov ax, word ptr [rsp + 40] mov dword ptr [BSS_RealModeEntry], eax /* Set the function ID and switch to real mode (we don't return) */ mov bx, FNID_Relocator16Boot jmp SwitchToReal /* * U16 PxeCallApi(U16 Segment, U16 Offset, U16 Service, VOID *Parameter); * * RETURNS: */ PUBLIC PxeCallApi PxeCallApi: xor eax, eax ret /* Internal function for realmode calls * bx must be set to the ID of the realmode function to call. */ PUBLIC CallRealMode CallRealMode: /* Save current stack pointer */ mov qword ptr [stack64], rsp /* Set continue address and switch to real mode */ lea rax, [CallRealMode_return] mov qword ptr [ContinueAddress], rax SwitchToReal: /* Set sane segments */ mov ax, LMODE_DS mov ds, ax mov es, ax mov fs, ax mov gs, ax //mov ss, ax //mov word ptr [HEX(0b8008)], HEX(0e00) + '4' /* Save 64-bit stack pointer */ mov qword ptr [stack64], rsp /* Step 1 - jump to compatibility segment */ jmp fword ptr [jumpvector] jumpvector: .long offset SwitchToRealCompSegment .word CMODE_CS SwitchToRealCompSegment: /* Note: In fact the CPU is in 32 bit mode here. But it will interpret the generated instructions accordingly. rax will become eax */ /* Step 2 - deactivate long mode, by disabling paging */ mov rax, cr0 and eax, HEX(7fffffff) //~0x80000000, upper bits cleared mov cr0, rax // mov word ptr [HEX(0b800a)], HEX(0e00) + '5' /* Step 3 - jump to 16-bit segment to set the limit correctly */ .byte HEX(0EA) // 32bit long jmp AddressOfRealModeEntryPoint: .long 0 // receives address of RealModeEntryPoint .word HEX(20)//RMODE_CS nop CallRealMode_return: /* restore stack pointer */ mov rsp, qword ptr [stack64] ret ///////////////////////////////////////// // void __fastfail(unsigned int Code); PUBLIC __fastfail __fastfail: // mov ecx, [rsp + 4] int HEX(29) // void __lgdt(void *Source); PUBLIC __lgdt __lgdt: lgdt fword ptr [rcx] ret // void __ltr(unsigned short Source); PUBLIC __ltr __ltr: ltr cx ret // void _sgdt(void *Destination); PUBLIC __sgdt __sgdt: sgdt fword ptr [rcx] ret /* 64-bit stack pointer */ stack64: .quad STACKADDR PUBLIC FrldrBootDrive FrldrBootDrive: .byte 0 PUBLIC FrldrBootPartition FrldrBootPartition: .long 0 END