10 .global RealEntryPoint
15 /* Setup real mode segment registers */
23 /* checkPoint Charlie - where it all began... */
24 mov si, offset CheckPoint0
27 /* Setup a real mode stack */
30 /* Zero BootDrive and BootPartition */
33 mov BootPartition, eax
35 /* Store the boot drive */
38 /* Store the boot partition */
48 /* checkPoint Charlie - where it all began... */
49 mov si, offset CheckPoint1
52 call x86_16_BuildPageTables
54 /* checkPoint Charlie - where it all began... */
55 mov si, offset CheckPoint2
58 /* Check if CPU supports CPUID */
69 jz NO_CPUID_SUPPORT_DETECTED
71 /* CPUID support detected - getting the PAE/PGE */
73 mov eax,1 // Fn0000_0001 - PAE in EDX[6]
77 test edx,edx // are PAE and PGE bits set?
78 jz NO_X64_SUPPORT_DETECTED
80 /* PAE and PGE are here */
87 jz NO_X64_SUPPORT_DETECTED
91 /* checkPoint Charlie - where it all began... */
92 mov si, offset CheckPoint3
97 NO_X64_SUPPORT_DETECTED:
98 mov si, offset NotAnX64Processor // Loading message
102 NO_CPUID_SUPPORT_DETECTED:
103 mov si, offset NoCPUIDSupport // Loading message
112 call x86_16_SwitchToLong
118 // mov word ptr ds:[0xb8000], 0x0e00 + '1'
127 // mov word ptr ds:[0xb8002], 0x0e02 + '2'
130 /* Return into real mode */
131 call x86_64_SwitchToReal
136 /* We should never get here */
143 /** 16 Bit helper functions ***************************************************/
147 .word 0x00eb,0x00eb // jmp $+2, jmp $+2
149 cmp al, 0xff // legacy-free machine without keyboard
150 jz empty_8042_ret // controllers on Intel Macs read back 0xFF
158 call x86_16_Empty8042
159 mov al, 0xD1 // command write
161 call x86_16_Empty8042
162 mov al, 0xDF // A20 on
164 call x86_16_Empty8042
169 * We define 512 2MB pages at the start of memory, so we can access the first
170 * 1 GB as if paging was disabled
172 x86_16_BuildPageTables:
176 /* Get segment of pml4 */
177 mov eax, offset pml4_startup
183 /* One entry in the PML4 pointing to PDP */
184 mov eax, offset pdp_startup
192 /* One entry in the PDP pointing to PD */
193 mov eax, offset pd_startup
201 /* 512 entries in the PD defining a 2MB page each */
207 mov dword ptr es: [di + 4], 0
208 add eax, 512 << 12 // add 512 4k pages
250 //.global x86_16_SwitchToLong
262 /* Get the return address off the stack */
263 pop word ptr code64ret
265 /* Save 16-bit stack pointer */
268 mov eax, 0x00a0 // Set PAE and PGE: 10100000b
271 mov edx, offset pml4_startup // Point cr3 at PML4
274 mov ecx, 0xC0000080 // Specify EFER MSR
276 rdmsr // Enable long mode
280 mov ebx, cr0 // Activate long mode
281 or ebx, 0x80000001 // by enabling paging and protection simultaneously
282 mov cr0, ebx // skipping protected mode entirely
284 jmp LMODE_CS:offset LongCat //Load CS with 64 bit segment and flush the instruction cache
288 /* Set up 64 bit stack */
291 /* Put the return address back onto the stack */
292 push qword ptr code64ret
294 /* Now return in long mode! */
297 /** 64 Bit functions **********************************************************/
300 .global x86_64_SwitchToReal
303 /* Get the return address off the stack */
304 pop qword ptr code64ret
306 /* Save 64-bit stack pointer */
311 // mov word ptr ds:[0xb8004], 0x0e00 + '3'
313 /* Step 1 - jump to compatibility segment */
323 // mov word ptr ds:[0xb8006], 0x0e00 + '4'
325 /* Step 2 - deactivate long mode, by disabling paging */
327 and eax, 0x000000007fffffff //~0x80000000
330 /* Step 2 - disable long mode in EFER MSR */
331 // mov ecx, 0xC0000080 // Specify EFER MSR
333 // and eax, ~0x00000100 // Disable EFER.LME
336 /* Step 3 - jump to 16-bit segment to set the limit correctly */
337 jmp RMODE_CS: offset SwitchToReal2
342 /* Step 4 - Disable Protected Mode */
347 /* Clear prefetch queue & correct CS */
354 // mov word ptr fs:[0x0C], 0x0e00 + '7'
356 /* Restore segment registers */
364 /* Restore 16 bit stack */
367 // lidt rmode_idtptr /* Load IDTR with real mode value */
369 // sti /* These are ok now */
371 /* Put the return address back onto the stack */
372 push word ptr code64ret
374 /* Now return in real mode! */
379 /** Some data *****************************************************************/
394 .quad 0x0000000000000000 /* 00: NULL descriptor */
395 .quad 0x0000000000000000 /* 08: */
396 .quad 0x0020980000000000 /* 10: long mode cs */
397 .quad 0x00cff3000000ffff /* 18: long mode ds */
398 .word 0xFFFF, 0x0000, 0x9E00, 0x0000 /* 16-bit real mode CS */
399 .word 0xFFFF, 0x0000, 0x9200, 0x0000 /* 16-bit real mode DS */
400 .quad 0x00CF9B000000FFFF /* 30: compat mode cs */
402 /* GDT table pointer */
404 .word 0x37 /* Limit */
405 .long gdt /* Base Address */
412 .global BootPartition
416 .global NotAnX64Processor
418 .ascii "FreeLoader: No x64-compatible CPU detected! Exiting..."
421 .global NoCPUIDSupport
423 .ascii "FreeLoader: No CPUID instruction support detected! Exiting..."
426 /////////////////////////// Checkpoint messages ///////////////////////////////
429 .ascii "Starting FreeLoader..."
434 .ascii "FreeLoader[16-bit]: building page tables..."
439 .ascii "FreeLoader[16-bit]: checking CPU for x64 long mode..."
444 .ascii "FreeLoader: Switching to x64 long mode..."
447 ///////////////////////////////////////////////////////////////////////////////
449 /* Need to include them here, because of linking issues between 64 / 16 bit */
450 //#include "debug16.S"