+++ /dev/null
-
-#include <asm.inc>
-#include "../../include/arch/pc/x86common.h"
-
-#define IMAGE_DOS_HEADER_e_lfanew 60
-#define IMAGE_FILE_HEADER_SIZE 20
-#define IMAGE_OPTIONAL_HEADER_AddressOfEntryPoint 16
-
-
-.code16
-
-/* fat helper code */
-#include "fathelp.inc"
-
-.org 512
-Startup:
-
- cli
-
- /* Setup real mode segment registers */
- xor ax, ax
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
-
- /* Save the boot drive and partition */
- mov byte ptr ds:[BSS_BootDrive], dl
- mov byte ptr ds:[BSS_BootPartition], dh
-
- /* Setup a real mode stack */
- mov sp, word ptr ds:[stack16]
-
- /* Output first status */
- mov si, offset Msg_Starting
- call writestr
-
- /* Enable A20 address line */
- call EnableA20
-
- /* Check the CPU */
- call CheckFor64BitSupport
- test al, al
- jnz .LongModeSupported
-
- /* Output failure message */
- mov si, offset Msg_Unsupported
- call writestr
-
- /* Wait for a keypress */
- int HEX(16)
- jmp Reboot
-
-Msg_Unsupported:
- .ascii "This CPU is not supported.", CR, LF
- .ascii "Press any key to reboot...", NUL
-
-Msg_Starting:
- .ascii "Starting FreeLoader...", CR, LF, NUL
-
-Msg_LongModeSupported:
- .ascii "Long mode support detected.", CR, LF, NUL
-
-.LongModeSupported:
- /* Output status */
- mov si, offset Msg_LongModeSupported
- call writestr
-
- /* Load the GDT */
- lgdt fword ptr [gdtptr]
-
- /* Build the startup page tables */
- call BuildPageTables
-
- /* Store real mode entry point in shared memory */
- mov dword ptr ds:[BSS_RealModeEntry], offset RealModeEntryPoint
-
- /* Address the image with es segment */
- mov ax, FREELDR_PE_BASE / 16
- mov es, ax
-
- /* Get address of optional header */
- mov eax, dword ptr es:[IMAGE_DOS_HEADER_e_lfanew]
- add eax, 4 + IMAGE_FILE_HEADER_SIZE
-
- /* 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:[LongModeEntryPoint], eax
-
- /* Restore es */
- xor ax, ax
- mov es, ax
-
- /* Output status */
- mov si, offset Msg_SwitchToLongMode
- call writestr
-
- jmp ExitToLongMode
-
-Msg_SwitchToLongMode:
- .ascii "Switching to long mode....", CR, LF, NUL
-
-.align 8
-gdt:
- .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */
- .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 08: */
- .word HEX(0000), HEX(0000), HEX(9800), HEX(0020) /* 10: long mode cs */
- .word HEX(ffff), HEX(0000), HEX(f300), HEX(00cf) /* 18: long mode ds */
- .word HEX(FFFF), HEX(0000), HEX(9E00), HEX(0000) /* 20: 16-bit real mode CS */
- .word HEX(FFFF), HEX(0000), HEX(9200), HEX(0000) /* 28: 16-bit real mode DS */
- .word HEX(FFFF), HEX(0000), HEX(9B00), HEX(00CF) /* 30: compat mode cs */
-
-/* GDT table pointer */
-gdtptr:
- .word HEX(37) /* Limit */
- .long offset gdt /* Base Address */
-
-
-CheckFor64BitSupport:
- /* Check if CPU supports CPUID */
- pushad
- pushfd
- pop eax
- mov ebx, eax
- xor eax, HEX(00200000)
- push eax
- popfd
- pushfd
- pop eax
- cmp eax,ebx
- jnz .CheckForPAE
-
- mov si, offset .Msg_NoCpuidSupport
- call writestr
- popad
- xor al, al
- ret
-
-.Msg_NoCpuidSupport:
- .ascii "The system doesn't support CPUID.", CR, LF, NUL
-
-.CheckForPAE:
- /* CPUID support detected - getting the PAE/PGE */
- mov eax,1 // Fn0000_0001 - PAE in EDX[6]
- cpuid
- and edx, HEX(00a0)
- cmp edx, HEX(00a0)
- je .CheckForLongMode
-
- mov si, offset .Msg_NoPAE
- call writestr
- popad
- xor al, al
- ret
-
-.Msg_NoPAE:
- .ascii "PAE or PGE not set.", CR, LF, NUL
-
-.CheckForLongMode:
- xor edx, edx
- mov eax, HEX(80000001)
- cpuid
- and edx, HEX(20000000)
- test edx,edx
- jnz .Success
-
- mov si, offset .Msg_NoLongMode
- call writestr
- popad
- xor al, al
- ret
-
-.Msg_NoLongMode:
- .ascii "Long mode is not supported.", CR, LF, NUL
-
-.Success:
- popad
- xor al, al
- inc al
- ret
-
-
-BuildPageTables:
- pusha
- push es
-
- /* Get segment of the PML4 */
- mov eax, PML4_ADDRESS / 16
- mov es, ax
- cld
- xor di, di
-
- /* One entry in the PML4 pointing to PDP */
- mov eax, PDP_ADDRESS
- or eax, HEX(0f)
- stosd
-
- /* clear rest */
- xor eax, eax
- mov cx, 1023
- rep stosd
-
- /* One entry in the PDP pointing to PD */
- mov eax, PD_ADDRESS
- or eax, HEX(0f)
- stosd
-
- /* clear rest */
- xor eax, eax
- mov ecx, 1023
- rep stosd
-
- /* 512 entries in the PD, each defining a 2MB page each */
- mov ecx, 512
- mov eax, HEX(008f)
-
-.Bpt2:
- mov es: [di], eax
- mov dword ptr es: [di + 4], 0
- add eax, 512 * 4096 // add 512 4k pages
- add di, 8
-
- /* Loop all PDEs */
- dec cx
- jnz .Bpt2
-
- /* Return */
- pop es
- popa
- ret
-
-
-/******************************************************************************/
-
-#define MSR_EFER HEX(C0000080)
-#define LMODE_CS HEX(10)
-
-/* This is the entry point from long mode */
-RealModeEntryPoint:
- /* Disable Protected Mode */
- mov eax, cr0
- and eax, HEX(0fffffffe) // ~0x00000001
- mov cr0, eax
-
- /* Clear prefetch queue & correct CS */
- ljmp16 0, offset InRealMode
-
-InRealMode:
-
-// mov ax, HEX(0b800)
-// mov es, ax
-// mov word ptr es:[12], HEX(0e00) + '6'
-
- /* Set real mode segments */
- xor ax, ax
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
-
- /* Clear out the high 16-bits of ESP */
- /* This is needed because I have one */
- /* machine that hangs when booted to dos if */
- /* anything other than 0x0000 is in the high */
- /* 16-bits of ESP. Even though real-mode */
- /* code should only use SP and not ESP. */
- xor esp, esp
-
- /* Restore real mode stack */
- mov sp, word ptr ds:[stack16]
-
- // sti /* These are ok now */
-
- /* Do the callback, specified by bx */
- shl bx, 1
- call word ptr ds:CallbackTable[bx]
-
-ExitToLongMode:
- /* Disable interrupts */
- cli
-
- /* Set correct segment registers */
- xor ax,ax
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- mov ss,ax
-
- /* Safe current stack pointer */
- mov word ptr ds:[stack16], sp
-
- /* Set PAE and PGE: 10100000b */
- mov eax, HEX(00a0)
- mov cr4, eax
-
- /* Point cr3 at the PML4 */
- mov eax, PML4_ADDRESS
- mov cr3, eax
-
- /* Enable long mode */
- mov ecx, MSR_EFER
- rdmsr
- or eax, HEX(00000100)
- wrmsr
-
- /* Activate long mode by enabling paging and protection simultaneously,
- skipping protected mode entirely */
- mov eax, cr0
- or eax, HEX(80000001)
- mov cr0, eax
-
- /* Clear prefetch queue & correct CS */
- ljmp16 LMODE_CS, InLongMode
-InLongMode:
- //DB 66h, 0B8h, 18h, 00h // mov ax, LMODE_DS
- //DB 66h, 8Eh, 0D8h // mov ds, ax
- //DB 66h, 66h, 0C7h, 04h, 25h, 00h, 80h, 0Bh, 00h, 31h, 0Eh
- //mov word ptr [HEX(b8000)], HEX(0e00) + '1'
-
- .byte HEX(0ff), HEX(25) // opcode of 64bit indirect jump
- .long 1 // relative address of LongModeEntryPoint
- nop
-LongModeEntryPoint:
- .long 0, 0
-
- int HEX(16)
- jmp Reboot
-
-CallbackTable:
- .word Int386
- .word Reboot
- .word ChainLoadBiosBootSectorCode
- .word PxeCallApi
- .word PnpBiosGetDeviceNodeCount
- .word PnpBiosGetDeviceNode
- .word 0 // BootLinuxKernel
-
- /* 16-bit stack pointer */
-stack16:
- .word STACK16ADDR
-
-
-#include "int386.inc"
-#include "pxe.inc"
-#include "pnp.inc"
-#include "helpers.inc"
-
-.org (FREELDR_PE_BASE - FREELDR_BASE - 1)
-.byte 0
-.endcode16
-
-END