diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/arch.S b/reactos/boot/freeldr/freeldr/arch/amd64/arch.S new file mode 100644 index 00000000000..466dabf5f9e --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/amd64/arch.S @@ -0,0 +1,303 @@ +.intel_syntax noprefix +.text +.code16 + +//.org 0x8000 + +#define STACK16ADDR 0x7000 /* The 16-bit stack top will be at 0000:7000 */ +#define STACK64ADDR 0x74000 /* The 64-bit stack top will be at 0x74000 */ + +.global RealEntryPoint +RealEntryPoint: + + cli + + /* Setup real mode segment registers */ + xor ax, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + /* Setup a real mode stack */ + mov sp, stack16 + + /* Zero BootDrive and BootPartition */ + xor eax, eax + mov _BootDrive, eax + mov _BootPartition, eax + + /* Store the boot drive */ + mov _BootDrive, dl + + /* Store the boot partition */ + mov _BootPartition, dh + + /* Load the GDT */ + lgdt gdtptr + /* Load the IDT */ +// lidt idtptr + + call x86_16_EnableA20 + + call x86_16_BuildPageTables + + /* Switch to long mode */ + call x86_16_SwitchToLong + + .code64 + + /* GO! */ + xor rcx, rcx + call _BootMain + + /* Return into real mode */ + call x86_64_SwitchToReal + .code16 + +// int 0x19 + + /* We should never get here */ +stop: + jmp stop + nop + nop + + +/** 16 Bit helper functions ***************************************************/ +.code16 + +x86_16_Empty8042: + .word 0x00eb,0x00eb // jmp $+2, jmp $+2 + in al, 0x64 + cmp al, 0xff // legacy-free machine without keyboard + jz empty_8042_ret // controllers on Intel Macs read back 0xFF + test al, 0x02 + jnz x86_16_Empty8042 +empty_8042_ret: + ret + +x86_16_EnableA20: + pusha + call x86_16_Empty8042 + mov al, 0xD1 // command write + out 0x64, al + call x86_16_Empty8042 + mov al, 0xDF // A20 on + out 0x60, al + call x86_16_Empty8042 + popa + ret + + +/* + * We defines one 2MB page at the start of memory, so we can access the first + * 2MBs as if paging was disabled + */ + +#define PML4_PAGENUM 60 // Put it high enough so it doesn't interfere with freeldr + +#define PAGESIZE 4096 +#define PDP_PAGENUM (PML4_PAGENUM + 1) +#define PD_PAGENUM (PDP_PAGENUM + 1) +#define PML4_ADDRESS (PML4_PAGENUM * PAGESIZE) +#define PDP_ADDRESS (PDP_PAGENUM * PAGESIZE) +#define PML4_SEG (PML4_ADDRESS / 16) + +x86_16_BuildPageTables: + pusha + push es + + mov ax, PML4_SEG + mov es, ax + cld + xor di, di + + /* One entry in the PML4 pointing to PDP */ + mov ax, ((PDP_PAGENUM << 12) & 0xffff) | 0x00f + stosw + mov ax, (PDP_PAGENUM >> 4) + stosw + xor ax,ax + mov cx, 0x07fe + rep stosw + + /* One entry in the PDP pointing to PD */ + mov ax, ((PD_PAGENUM << 12) & 0xffff) | 0x00f + stosw + mov ax, (PD_PAGENUM >> 4) + stosw + xor ax,ax + mov cx, 0x07fe + rep stosw + + /* One entry in the PD defining a 2MB page */ + mov ax, 0x018f + stosw + xor ax,ax + mov cx,0x07ff + rep stosw + + /* Return */ + pop es + popa + ret + + +#define LMODE_CS 0x08 +#define LMODE_DS 0x10 +#define RMODE_CS 0x18 /* RMode code selector, base 0 limit 64k */ +#define RMODE_DS 0x20 /* RMode data selector, base 0 limit 64k */ + +//.global x86_16_SwitchToLong +x86_16_SwitchToLong: + cli + + xor ax,ax + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + + /* Get the return address off the stack */ + pop word ptr code64ret + + /* Save 16-bit stack pointer */ + mov stack16, sp + + mov eax, 0x00a0 // Set PAE and PGE: 10100000b + mov cr4, eax + + mov edx, PML4_ADDRESS // Point cr3 at PML4 + mov cr3, edx + + mov ecx, 0xC0000080 // Specify EFER MSR + + rdmsr // Enable long mode + or eax, 0x00000100 + wrmsr + + mov ebx, cr0 // Activate long mode + or ebx, 0x80000001 // by enabling paging and protection simultaneously + mov cr0, ebx // skipping protected mode entirely + + jmp LMODE_CS:offset LongCat //Load CS with 64 bit segment and flush the instruction cache + +.code64 +LongCat: + /* Set up 64 bit stack */ + mov rsp, stack64 + + /* Put the return address back onto the stack */ + push qword ptr code64ret + + /* Now return in long mode! */ + ret + + +/** 64 But functions **********************************************************/ +.code64 + +.global x86_64_SwitchToReal +x86_64_SwitchToReal: + + /* Get the return address off the stack */ + pop qword ptr code64ret + + /* Save 64-bit stack pointer */ + mov stack64, rsp + + /* Step 1 - deactivate long mode, by disabling paging */ + mov rax, cr0 + and rax, 0x000000007fffffff //~0x80000000 + mov cr0, rax + + /* Step 2 - disable long mode in EFER MSR */ + mov rcx, 0xC0000080 // Specify EFER MSR + rdmsr + and eax, ~0x00000100 // Disable EFER.LME + wrmsr + + .code32 + /* jmp to 16-bit segment to set the limit correctly */ + jmp RMODE_CS: offset SwitchToReal2 + +SwitchToReal2: + .code16 + + /* Step 3 - Disable Protected Mode */ + mov eax, cr0 + and eax, ~0x00000001 + mov cr0, eax + + /* Clear prefetch queue & correct CS */ + jmp 0:offset BeReal + +BeReal: + /* Restore segment registers */ + mov ax, 0 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + /* Rstore 16 bit stack */ + mov sp, stack16 + +// lidt rmode_idtptr /* Load IDTR with real mode value */ + +// sti /* These are ok now */ + + /* Put the return address back onto the stack */ + push word ptr code64ret + + /* Now return in real mode! */ + ret + + +/** Some data *****************************************************************/ + +.code64 + +stack16: + .quad STACK16ADDR + +stack64: + .quad STACK64ADDR + +code64ret: + .quad 0 + +gdt: + .quad 0x0000000000000000 + .quad 0x0020980000000000 + .quad 0x0000900000000000 + .word 0xFFFF, 0x0000, 0x9E00, 0x0000 /* 16-bit real mode CS */ + .word 0xFFFF, 0x0000, 0x9200, 0x0000 /* 16-bit real mode DS */ + +/* GDT table pointer */ +gdtptr: + .word 0x27 /* Limit */ + .long gdt /* Base Address */ + + +.global _BootDrive +_BootDrive: + .long 0 + +.global _BootPartition +_BootPartition: + .long 0 + + +/////////////////////////////////////////////////////////////////////////////// + +/* Need to include them here, because of linking issues between 64 / 16 bit */ +//#include "debug16.S" +#include "int386.S" +#include "boot.S" +#include "i386pnp.S" + diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/int386.S b/reactos/boot/freeldr/freeldr/arch/amd64/int386.S new file mode 100644 index 00000000000..09caea5c415 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/amd64/int386.S @@ -0,0 +1,170 @@ +/* + * FreeLoader + * Copyright (C) 1998-2002 Brian Palmer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + .intel_syntax noprefix + .text + .code16 + +#define ASM +#include + + +Int386_REGS: + +Int386_eax: + .long 0 +Int386_ebx: + .long 0 +Int386_ecx: + .long 0 +Int386_edx: + .long 0 + +Int386_esi: + .long 0 +Int386_edi: + .long 0 + +Int386_ds: + .word 0 +Int386_es: + .word 0 +Int386_fs: + .word 0 +Int386_gs: + .word 0 + +Int386_eflags: + .long 0 + +Int386_vector: + .quad 0 +Int386_regsin: + .quad 0 +Int386_regsout: + .quad 0 + +/* + * int Int386(int ivec, REGS* in, REGS* out); + */ +EXTERN(_Int386) + .code64 + + /* Get the function parameters */ + mov Int386_vector, rcx + mov Int386_vector_opcode, cl + mov Int386_regsin, rdx + mov Int386_regsout, r8 + + /* Save all registers + segment registers */ +// push ds +// push es + push fs + push gs + push rbx + push rcx + push rdx + push rsi + push rdi + + /* Copy the input regs to our variables */ + lea rdi, Int386_REGS + mov esi, Int386_regsin + mov ecx, 0x24 + rep movsb + + call x86_64_SwitchToReal + .code16 + + /* Setup the registers */ + mov ax, cs:Int386_ds + mov ds, ax /* DS register */ + mov ax, cs:Int386_es + mov es, ax /* ES register */ + mov ax, cs:Int386_fs + mov fs, ax /* FS register */ + mov ax, cs:Int386_gs + mov gs, ax /* GS register */ + + mov eax, cs:Int386_eax /* EAX register */ + mov ebx, cs:Int386_ebx /* EBX register */ + mov ecx, cs:Int386_ecx /* ECX register */ + mov edx, cs:Int386_edx /* EDX register */ + + mov esi, cs:Int386_esi /* ESI register */ + mov edi, cs:Int386_edi /* EDI register */ + + /* Do not set the flags register */ + /* only return its value in regsout */ + //pushl Int386_eflags + //popfl /* EFLAGS register */ + + /* Call the interrupt vector */ + /*int Int386_vector*/ +Int386_int_opcode: + .byte 0xcd +Int386_vector_opcode: + .byte 0x00 + + /* Save the registers */ + mov cs:Int386_eax, eax /* EAX register */ + mov cs:Int386_ebx, ebx /* EBX register */ + mov cs:Int386_ecx, ecx /* ECX register */ + mov cs:Int386_edx, edx /* EDX register */ + + mov cs:Int386_esi, esi /* ESI register */ + mov cs:Int386_edi, edi /* EDI register */ + + mov ax, ds /* DS register */ + mov cs:Int386_ds, ax + mov ax, es /* ES register */ + mov cs:Int386_es, ax + mov ax, fs /* FS register */ + mov cs:Int386_fs, ax + mov ax, gs /* GS register */ + mov cs:Int386_gs, ax + + pushf + pop cs:Int386_eflags /* EFLAGS register */ + + call x86_16_SwitchToLong + .code64 + + /* Copy the variables to the output regs */ + lea rsi, Int386_REGS + mov rdi, Int386_regsout + mov rcx, 0x24 + rep movsb + + /* Restore segment and all other registers */ + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop gs + pop fs +// pop es +// pop ds + + /* Get return value */ + xor rax, rax + mov eax, Int386_eax + + ret diff --git a/reactos/boot/freeldr/freeldr/debug.c b/reactos/boot/freeldr/freeldr/debug.c index 2ae758f41e4..84b01079559 100644 --- a/reactos/boot/freeldr/freeldr/debug.c +++ b/reactos/boot/freeldr/freeldr/debug.c @@ -23,11 +23,11 @@ #ifdef DBG -//#define DEBUG_ALL +#define DEBUG_ALL //#define DEBUG_INIFILE //#define DEBUG_REACTOS //#define DEBUG_CUSTOM -#define DEBUG_NONE +//#define DEBUG_NONE #if defined (DEBUG_ALL) ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | @@ -243,7 +243,7 @@ VOID DebugPrintHeader(ULONG Mask) VOID DebugPrint(ULONG Mask, char *format, ...) { va_list ap; - char Buffer[4096]; + char Buffer[2096]; char *ptr = Buffer; // Mask out unwanted debug messages @@ -271,7 +271,7 @@ VOID DebugPrint(ULONG Mask, char *format, ...) VOID DebugPrint1(char *format, ...) { va_list ap; - char Buffer[4096]; + char Buffer[2096]; char *ptr = Buffer; va_start(ap, format); diff --git a/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild b/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild index 75631cf160e..11f75db4d42 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild +++ b/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild @@ -84,6 +84,7 @@ i386disk.c i386rtl.c i386vid.c + loader.c pccons.c pcdisk.c pcmem.c diff --git a/reactos/boot/freeldr/freeldr/freeldr_base64k.rbuild b/reactos/boot/freeldr/freeldr/freeldr_base64k.rbuild index 9380c2b055f..7a59263a59c 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_base64k.rbuild +++ b/reactos/boot/freeldr/freeldr/freeldr_base64k.rbuild @@ -26,7 +26,6 @@ i386cpu.S i386idt.S i386trap.S - mb.S diff --git a/reactos/boot/freeldr/freeldr/include/disk.h b/reactos/boot/freeldr/freeldr/include/disk.h index 3ecbef15aec..8e8ea56ccf8 100644 --- a/reactos/boot/freeldr/freeldr/include/disk.h +++ b/reactos/boot/freeldr/freeldr/include/disk.h @@ -106,14 +106,14 @@ typedef struct _MASTER_BOOT_RECORD // i386 BIOS Disk Functions (i386disk.c) // /////////////////////////////////////////////////////////////////////////////////////// -#ifdef __i386__ +#if defined(__i386__) || defined(_M_AMD64) BOOLEAN DiskResetController(ULONG DriveNumber); BOOLEAN DiskInt13ExtensionsSupported(ULONG DriveNumber); //VOID DiskStopFloppyMotor(VOID); BOOLEAN DiskGetExtendedDriveParameters(ULONG DriveNumber, PVOID Buffer, USHORT BufferSize); -#endif // defined __i386__ +#endif // defined __i386__ || defined(_M_AMD64) /////////////////////////////////////////////////////////////////////////////////////// // diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index c8d17321ad1..916f5ea92df 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -50,6 +50,17 @@ typedef struct #endif // defined __i386__ or _PPC_ or _MIPS_ +#if defined (_AMD64_) + +#define MM_PAGE_SIZE 4096 +#define MM_PAGE_MASK 0xFFF +#define MM_PAGE_SHIFT 12 + +#define MM_SIZE_TO_PAGES(a) \ + ( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) ) + +#endif + // HEAP and STACK size #define HEAP_PAGES 0x400 #define STACK_PAGES 0x00