1 2#include <asm.inc> 3#include <ksamd64.inc> 4#include <arch/pc/x86common.h> 5#include <arch/pc/pcbios.h> 6 7EXTERN BootMain:PROC 8EXTERN cmdline:DWORD 9 10EXTERN DiskStopFloppyMotor:PROC 11 12#ifdef _USE_ML 13EXTERN __bss_start__:FWORD 14EXTERN __bss_end__:FWORD 15#endif 16 17.code64 18 19PUBLIC RealEntryPoint 20RealEntryPoint: 21 /* Setup segment selectors */ 22 mov ax, LMODE_DS 23 mov ds, ax 24 mov es, ax 25 mov fs, ax 26 mov gs, ax 27// mov ss, ax 28 29 //mov word ptr [HEX(b8000)], HEX(0e00) + '1' 30 31 /* Setup long mode stack */ 32 mov rsp, qword ptr [stack64] 33 34 /* Continue execution */ 35 jmp qword ptr [ContinueAddress] 36 37ContinueAddress: 38 .quad FrldrStartup 39 40FrldrStartup: 41 42 /* Set up CR0 for SSE */ 43 mov rax, cr0 44 and eax, not CR0_EM // Clear coprocessor emulation CR0.EM CR0.EM (bit 2) 45 or rax, CR0_MP // Set coprocessor monitoring CR0.MP (bit 1) 46 mov cr0, rax 47 48 /* Set up CR4 for SSE */ 49 mov rax, cr4 50 or eax, CR4_FXSR // Enable fx save/restore CR4.OSFXSR (bit 9) 51 or eax, CR4_XMMEXCPT // Enable XMMI exceptions CR4.OSXMMEXCPT (bit 10) 52 mov cr4, rax 53 54 /* Store BootDrive and BootPartition */ 55 mov al, byte ptr [BSS_BootDrive] 56 mov byte ptr [FrldrBootDrive], al 57 xor eax, eax 58 mov al, byte ptr [BSS_BootPartition] 59 mov dword ptr [FrldrBootPartition], eax 60 61 /* Patch long jump with real mode entry point */ 62 mov eax, dword ptr [BSS_RealModeEntry] 63 mov dword ptr [AddressOfRealModeEntryPoint], eax 64 65 /* Clean out BSS */ 66 xor rax, rax 67 mov rdi, offset __bss_start__ 68 mov rcx, offset __bss_end__ + 7 69 sub rcx, rdi 70 shr rcx, 3 71 rep stosq 72 73 /* Pass the command line to BootMain */ 74 mov rcx, offset cmdline 75 76 /* GO! */ 77 call BootMain 78 79 /* We should never get here */ 80stop: 81 jmp short stop 82 nop 83 nop 84 85 86PUBLIC Reboot 87Reboot: 88 /* Stop the floppy drive motor */ 89 call DiskStopFloppyMotor 90 91 /* Set the function ID and switch to real mode (we don't return) */ 92 mov bx, FNID_Reboot 93 jmp SwitchToReal 94 95 96/* 97 * VOID __cdecl Relocator16Boot( 98 * IN REGS* In<rcx>, 99 * IN USHORT StackSegment<dx>, 100 * IN USHORT StackPointer<r8w>, 101 * IN USHORT CodeSegment<r9w>, 102 * IN USHORT CodePointer<rsp+40>); 103 * 104 * RETURNS: Nothing. 105 * 106 * NOTE: The implementation of this function is similar to that of Int386(), 107 * with the proviso that no attempt is done to save the original values of 108 * the registers since we will not need them anyway, as we do not return back 109 * to the caller but instead place the machine in a permanent new CPU state. 110 */ 111PUBLIC Relocator16Boot 112Relocator16Boot: 113 114 /* Save home registers */ 115 mov qword ptr [rsp + 8], rcx 116 mov word ptr [rsp + 16], dx 117 mov word ptr [rsp + 24], r8w 118 mov word ptr [rsp + 32], r9w 119 120#if 0 121 /* Save non-volatile registers */ 122 push rbx 123 push rsi 124 push rdi 125#endif 126 127 /* Copy input registers */ 128 mov rsi, qword ptr [rsp + 8] 129 mov rdi, BSS_RegisterSet 130 mov rcx, REGS_SIZE / 4 131 rep movsd 132 133 /* Set the stack segment/offset */ 134 // Since BSS_CallbackReturn contains a ULONG, store in its high word 135 // the stack segment and in its low word the stack offset. 136 mov ax, word ptr [rsp + 16] 137 shl eax, 16 138 mov ax, word ptr [rsp + 24] 139 mov dword ptr [BSS_CallbackReturn], eax 140 141 /* 142 * Set the code segment/offset (Copy entry point) 143 * NOTE: We permanently *ERASE* the contents of ds:[BSS_RealModeEntry] 144 * but it is not a problem since we are going to place the machine in 145 * a permanent new CPU state. 146 */ 147 // Since BSS_RealModeEntry contains a ULONG, store in its high word 148 // the code segment and in its low word the code offset. 149 mov ax, word ptr [rsp + 32] 150 shl eax, 16 151 mov ax, word ptr [rsp + 40] 152 mov dword ptr [BSS_RealModeEntry], eax 153 154 /* Set the function ID and switch to real mode (we don't return) */ 155 mov bx, FNID_Relocator16Boot 156 jmp SwitchToReal 157 158 159/* 160 * U16 PxeCallApi(U16 Segment, U16 Offset, U16 Service, VOID *Parameter); 161 * 162 * RETURNS: 163 */ 164PUBLIC PxeCallApi 165PxeCallApi: 166 xor eax, eax 167 ret 168 169 170/* Internal function for realmode calls 171 * bx must be set to the ID of the realmode function to call. */ 172PUBLIC CallRealMode 173CallRealMode: 174 /* Save current stack pointer */ 175 mov qword ptr [stack64], rsp 176 177 /* Set continue address and switch to real mode */ 178 lea rax, [CallRealMode_return] 179 mov qword ptr [ContinueAddress], rax 180 181SwitchToReal: 182 /* Set sane segments */ 183 mov ax, LMODE_DS 184 mov ds, ax 185 mov es, ax 186 mov fs, ax 187 mov gs, ax 188 //mov ss, ax 189 190 //mov word ptr [HEX(0b8008)], HEX(0e00) + '4' 191 192 /* Save 64-bit stack pointer */ 193 mov qword ptr [stack64], rsp 194 195 /* Step 1 - jump to compatibility segment */ 196 jmp fword ptr [jumpvector] 197 198jumpvector: 199 .long SwitchToRealCompSegment 200 .word CMODE_CS 201 202SwitchToRealCompSegment: 203 /* Note: In fact the CPU is in 32 bit mode here. But it will interpret 204 the generated instructions accordingly. rax will become eax */ 205 206 /* Step 2 - deactivate long mode, by disabling paging */ 207 mov rax, cr0 208 and eax, HEX(7fffffff) //~0x80000000, upper bits cleared 209 mov cr0, rax 210 211// mov word ptr [HEX(0b800a)], HEX(0e00) + '5' 212 213 /* Step 3 - jump to 16-bit segment to set the limit correctly */ 214 .byte HEX(0EA) // 32bit long jmp 215AddressOfRealModeEntryPoint: 216 .long 0 // receives address of RealModeEntryPoint 217 .word HEX(20)//RMODE_CS 218 nop 219 220CallRealMode_return: 221 /* restore stack pointer */ 222 mov rsp, qword ptr [stack64] 223 ret 224 225///////////////////////////////////////// 226 227 /* 64-bit stack pointer */ 228stack64: 229 .quad STACKADDR 230 231PUBLIC FrldrBootDrive 232FrldrBootDrive: 233 .byte 0 234 235PUBLIC FrldrBootPartition 236FrldrBootPartition: 237 .long 0 238 239END 240