X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FCore%2FDxeIplPeim%2Fx64%2FLongMode.asm;h=ae87bd83e4b78ce4d9429cd12deedd544cf4668a;hp=a9c4e774cf9993c8ee6eb384d8f1f3fbe700f58d;hb=e20ee534ac22960fef84e868cb45eb54b813a290;hpb=d4864e235043b5adacfc50b47c0a747161398a1d diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm index a9c4e774cf..ae87bd83e4 100644 --- a/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm +++ b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm @@ -1,1357 +1,1350 @@ - TITLE LongMode.asm: Assembly code for the entering long mode - -;------------------------------------------------------------------------------ -;* -;* Copyright (c) 2006, Intel Corporation -;* All rights reserved. This program and the accompanying materials -;* are licensed and made available under the terms and conditions of the BSD License -;* which accompanies this distribution. The full text of the license may be found at -;* http://opensource.org/licenses/bsd-license.php -;* -;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -;* -;* LongMode.asm -;* -;* Abstract: -;* -;* Transition from 32-bit protected mode EFI environment into x64 -;* 64-bit bit long mode. -;* -;------------------------------------------------------------------------------ - -.686p -.model flat - -; -; Create the exception handler code in IA32 C code -; - -.code -.stack -.MMX -.XMM - -_LoadGo64Gdt PROC Near Public - push ebp ; C prolog - push edi - mov ebp, esp - ; - ; Disable interrupts - ; - cli - ; - ; Reload the selectors - ; Note: - ; Make the Selectors 64-bit ready - ; - mov edi, OFFSET gdtr ; Load GDT register - mov ax,cs ; Get the selector data from our code image - mov es,ax - lgdt FWORD PTR es:[edi] ; and update the GDTR - - db 067h - db 0eah ; Far Jump Offset:Selector to reload CS - dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary - dw LINEAR_CODE_SEL ; Selector is our code selector, 10h -DataSelectorRld:: - mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - - pop edi - pop ebp - ret -_LoadGo64Gdt endp - - -; VOID -; ActivateLongMode ( -; IN EFI_PHYSICAL_ADDRESS PageTables, -; IN EFI_PHYSICAL_ADDRESS HobStart, -; IN EFI_PHYSICAL_ADDRESS Stack, -; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint, -; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint -; ) -; -; Input: [ebp][0h] = Original ebp -; [ebp][4h] = Return address -; [ebp][8h] = PageTables -; [ebp][10h] = HobStart -; [ebp][18h] = Stack -; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer) -; [ebp][28h] = CodeEntryPoint2 <--- Call this second -; -; -_ActivateLongMode PROC Near Public - push ebp ; C prolog - mov ebp, esp - - ; - ; Use CPUID to determine if the processor supports long mode. - ; - mov eax, 80000000h ; Extended-function code 8000000h. - cpuid ; Is largest extended function - cmp eax, 80000000h ; any function > 80000000h? - jbe no_long_mode ; If not, no long mode. - mov eax, 80000001h ; Extended-function code 8000001h. - cpuid ; Now EDX = extended-features flags. - bt edx, 29 ; Test if long mode is supported. - jnc no_long_mode ; Exit if not supported. - - ; - ; Enable the 64-bit page-translation-table entries by - ; setting CR4.PAE=1 (this is _required_ before activating - ; long mode). Paging is not enabled until after long mode - ; is enabled. - ; - mov eax, cr4 - bts eax, 5 - mov cr4, eax - - ; - ; Get the long-mode page tables, and initialize the - ; 64-bit CR3 (page-table base address) to point to the base - ; of the PML4 page table. The PML4 page table must be located - ; below 4 Gbytes because only 32 bits of CR3 are loaded when - ; the processor is not in 64-bit mode. - ; - mov eax, [ebp+8h] ; Get Page Tables - mov cr3, eax ; Initialize CR3 with PML4 base. - - ; - ; Enable long mode (set EFER.LME=1). - ; - mov ecx, 0c0000080h ; EFER MSR number. - rdmsr ; Read EFER. - bts eax, 8 ; Set LME=1. - wrmsr ; Write EFER. - - ; - ; Enable paging to activate long mode (set CR0.PG=1) - ; - - - mov eax, cr0 ; Read CR0. - bts eax, 31 ; Set PG=1. - mov cr0, eax ; Write CR0. - jmp go_to_long_mode -go_to_long_mode: - - ; - ; This is the next instruction after enabling paging. Jump to long mode - ; - db 067h - db 0eah ; Far Jump Offset:Selector to reload CS - dd OFFSET in_long_mode; Offset is ensuing instruction boundary - dw SYS_CODE64_SEL ; Selector is our code selector, 10h -in_long_mode:: - mov ax, SYS_DATA64_SEL - mov es, ax - mov ss, ax - mov ds, ax -;; jmp $ - - - ; - ; We're in long mode, so marshall the arguments to call the - ; passed in function pointers - ; Recall - ; [ebp][10h] = HobStart - ; [ebp][18h] = Stack - ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer) - ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second - ; - db 48h - mov ebx, [ebp+18h] ; Setup the stack - db 48h - mov esp, ebx ; On a new stack now - - db 48h - mov ecx, [ebp+10h] ; Pass Hob Start in RCX - db 48h - mov eax, [ebp+20h] ; Get the function pointer for - ; PpisNeededByDxeIplEntryPoint into EAX - -;; 00000905 FF D0 call rax - db 0ffh - db 0d0h - - db 48h - mov ecx, [ebp+10h] ; Pass Hob Start in RCX - db 48h - mov eax, [ebp+28h] ; Get the function pointer for - ; DxeCoreEntryPoint into EAX - -;; 00000905 FF D0 call rax - db 0ffh - db 0d0h - - ; - ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!! - ; -no_long_mode: - jmp no_long_mode -_ActivateLongMode endp - - align 16 - -gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit - dd OFFSET GDT_BASE ; (GDT base gets set above) - -;-----------------------------------------------------------------------------; -; global descriptor table (GDT) -;-----------------------------------------------------------------------------; - - align 16 - -public GDT_BASE -GDT_BASE: -; null descriptor -NULL_SEL equ $-GDT_BASE ; Selector [0] - dw 0 ; limit 15:0 - dw 0 ; base 15:0 - db 0 ; base 23:16 - db 0 ; type - db 0 ; limit 19:16, flags - db 0 ; base 31:24 - -; linear data segment descriptor -LINEAR_SEL equ $-GDT_BASE ; Selector [0x8] - dw 0FFFFh ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 092h ; present, ring 0, data, expand-up, writable - db 0CFh ; page-granular, 32-bit - db 0 - -; linear code segment descriptor -LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10] - dw 0FFFFh ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 09Fh ; present, ring 0, data, expand-up, writable - db 0CFh ; page-granular, 32-bit - db 0 - -; system data segment descriptor -SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18] - dw 0FFFFh ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 093h ; present, ring 0, data, expand-up, writable - db 0CFh ; page-granular, 32-bit - db 0 - -; system code segment descriptor -SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20] - dw 0FFFFh ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 09Ah ; present, ring 0, data, expand-up, writable - db 0CFh ; page-granular, 32-bit - db 0 - -; spare segment descriptor -SPARE3_SEL equ $-GDT_BASE ; Selector [0x28] - dw 0 ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 0 ; present, ring 0, data, expand-up, writable - db 0 ; page-granular, 32-bit - db 0 - -; -; system data segment descriptor -; -SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30] - dw 0FFFFh ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A - db 0CFh ; G | D | L | AVL | Segment [19..16] - db 0 - -; -; system code segment descriptor -; -SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38] - dw 0FFFFh ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A - db 0AFh ; G | D | L | AVL | Segment [19..16] - db 0 - -; spare segment descriptor -SPARE4_SEL equ $-GDT_BASE ; Selector [0x40] - dw 0 ; limit 0xFFFFF - dw 0 ; base 0 - db 0 - db 0 ; present, ring 0, data, expand-up, writable - db 0 ; page-granular, 32-bit - db 0 - -GDT_END: - -; -; -;------------------------------------------------------------------------------ -; Generic IDT Vector Handlers for the Host. They are all the same so they -; will compress really well. -; -; By knowing the return address for Vector 00 you can can calculate the -; vector number by looking at the call CommonInterruptEntry return address. -; (return address - AsmIdtVector00Base)/8 == IDT index -; -;------------------------------------------------------------------------------ - -_AsmIdtVector00 PROC NEAR PUBLIC - call CommonInterruptEntry -_AsmIdtVector00 ENDP -AsmIdtVector00Base PROC NEAR PUBLIC - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop - call CommonInterruptEntry - nop - nop - nop -AsmIdtVector00Base ENDP - - -;---------------------------------------; -; CommonInterruptEntry ; -;---------------------------------------; -; The follow algorithm is used for the common interrupt routine. -; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition -; -; -CommonInterruptEntry PROC NEAR PUBLIC - cli - jmp $ - iret - -CommonInterruptEntry ENDP - -END - + TITLE LongMode.asm: Assembly code for the entering long mode + +;------------------------------------------------------------------------------ +;* +;* Copyright (c) 2006, Intel Corporation +;* All rights reserved. This program and the accompanying materials +;* are licensed and made available under the terms and conditions of the BSD License +;* which accompanies this distribution. The full text of the license may be found at +;* http://opensource.org/licenses/bsd-license.php +;* +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +;* +;* LongMode.asm +;* +;* Abstract: +;* +;* Transition from 32-bit protected mode EFI environment into x64 +;* 64-bit bit long mode. +;* +;------------------------------------------------------------------------------ + +.686p +.model flat + +; +; Create the exception handler code in IA32 C code +; + +.code +.stack +.MMX +.XMM + +_LoadGo64Gdt PROC Near Public + push ebp ; C prolog + push edi + mov ebp, esp + ; + ; Disable interrupts + ; + cli + ; + ; Reload the selectors + ; Note: + ; Make the Selectors 64-bit ready + ; + mov edi, OFFSET gdtr ; Load GDT register + mov ax,cs ; Get the selector data from our code image + mov es,ax + lgdt FWORD PTR es:[edi] ; and update the GDTR + + db 067h + db 0eah ; Far Jump Offset:Selector to reload CS + dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary + dw LINEAR_CODE_SEL ; Selector is our code selector, 10h +DataSelectorRld:: + mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + pop edi + pop ebp + ret +_LoadGo64Gdt endp + + +; VOID +; ActivateLongMode ( +; IN EFI_PHYSICAL_ADDRESS PageTables, +; IN EFI_PHYSICAL_ADDRESS HobStart, +; IN EFI_PHYSICAL_ADDRESS Stack, +; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint, +; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint +; ) +; +; Input: [ebp][0h] = Original ebp +; [ebp][4h] = Return address +; [ebp][8h] = PageTables +; [ebp][10h] = HobStart +; [ebp][18h] = Stack +; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer) +; [ebp][28h] = CodeEntryPoint2 <--- Call this second +; +; +_ActivateLongMode PROC Near Public + push ebp ; C prolog + mov ebp, esp + + ; + ; Use CPUID to determine if the processor supports long mode. + ; + mov eax, 80000000h ; Extended-function code 8000000h. + cpuid ; Is largest extended function + cmp eax, 80000000h ; any function > 80000000h? + jbe no_long_mode ; If not, no long mode. + mov eax, 80000001h ; Extended-function code 8000001h. + cpuid ; Now EDX = extended-features flags. + bt edx, 29 ; Test if long mode is supported. + jnc no_long_mode ; Exit if not supported. + + ; + ; Enable the 64-bit page-translation-table entries by + ; setting CR4.PAE=1 (this is _required_ before activating + ; long mode). Paging is not enabled until after long mode + ; is enabled. + ; + mov eax, cr4 + bts eax, 5 + mov cr4, eax + + ; + ; Get the long-mode page tables, and initialize the + ; 64-bit CR3 (page-table base address) to point to the base + ; of the PML4 page table. The PML4 page table must be located + ; below 4 Gbytes because only 32 bits of CR3 are loaded when + ; the processor is not in 64-bit mode. + ; + mov eax, [ebp+8h] ; Get Page Tables + mov cr3, eax ; Initialize CR3 with PML4 base. + + ; + ; Enable long mode (set EFER.LME=1). + ; + mov ecx, 0c0000080h ; EFER MSR number. + rdmsr ; Read EFER. + bts eax, 8 ; Set LME=1. + wrmsr ; Write EFER. + + ; + ; Enable paging to activate long mode (set CR0.PG=1) + ; + + + mov eax, cr0 ; Read CR0. + bts eax, 31 ; Set PG=1. + mov cr0, eax ; Write CR0. + jmp go_to_long_mode +go_to_long_mode: + + ; + ; This is the next instruction after enabling paging. Jump to long mode + ; + db 067h + db 0eah ; Far Jump Offset:Selector to reload CS + dd OFFSET in_long_mode; Offset is ensuing instruction boundary + dw SYS_CODE64_SEL ; Selector is our code selector, 10h +in_long_mode:: + mov ax, SYS_DATA64_SEL + mov es, ax + mov ss, ax + mov ds, ax +;; jmp $ + + + ; + ; We're in long mode, so marshall the arguments to call the + ; passed in function pointers + ; Recall + ; [ebp][10h] = HobStart + ; [ebp][18h] = Stack + ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer) + ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second + ; + db 48h + mov ebx, [ebp+18h] ; Setup the stack + db 48h + mov esp, ebx ; On a new stack now + + +;; 00000905 FF D0 call rax + + db 48h + mov ecx, [ebp+10h] ; Pass Hob Start in RCX + db 48h + mov eax, [ebp+28h] ; Get the function pointer for + ; DxeCoreEntryPoint into EAX + +;; 00000905 FF D0 call rax + db 0ffh + db 0d0h + + ; + ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!! + ; +no_long_mode: + jmp no_long_mode +_ActivateLongMode endp + + align 16 + +gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit + dd OFFSET GDT_BASE ; (GDT base gets set above) + +;-----------------------------------------------------------------------------; +; global descriptor table (GDT) +;-----------------------------------------------------------------------------; + + align 16 + +public GDT_BASE +GDT_BASE: +; null descriptor +NULL_SEL equ $-GDT_BASE ; Selector [0] + dw 0 ; limit 15:0 + dw 0 ; base 15:0 + db 0 ; base 23:16 + db 0 ; type + db 0 ; limit 19:16, flags + db 0 ; base 31:24 + +; linear data segment descriptor +LINEAR_SEL equ $-GDT_BASE ; Selector [0x8] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; linear code segment descriptor +LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Fh ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system data segment descriptor +SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 093h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system code segment descriptor +SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; spare segment descriptor +SPARE3_SEL equ $-GDT_BASE ; Selector [0x28] + dw 0 ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 0 ; present, ring 0, data, expand-up, writable + db 0 ; page-granular, 32-bit + db 0 + +; +; system data segment descriptor +; +SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A + db 0CFh ; G | D | L | AVL | Segment [19..16] + db 0 + +; +; system code segment descriptor +; +SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A + db 0AFh ; G | D | L | AVL | Segment [19..16] + db 0 + +; spare segment descriptor +SPARE4_SEL equ $-GDT_BASE ; Selector [0x40] + dw 0 ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 0 ; present, ring 0, data, expand-up, writable + db 0 ; page-granular, 32-bit + db 0 + +GDT_END: + +; +; +;------------------------------------------------------------------------------ +; Generic IDT Vector Handlers for the Host. They are all the same so they +; will compress really well. +; +; By knowing the return address for Vector 00 you can can calculate the +; vector number by looking at the call CommonInterruptEntry return address. +; (return address - AsmIdtVector00Base)/8 == IDT index +; +;------------------------------------------------------------------------------ + +_AsmIdtVector00 PROC NEAR PUBLIC + call CommonInterruptEntry +_AsmIdtVector00 ENDP +AsmIdtVector00Base PROC NEAR PUBLIC + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop +AsmIdtVector00Base ENDP + + +;---------------------------------------; +; CommonInterruptEntry ; +;---------------------------------------; +; The follow algorithm is used for the common interrupt routine. +; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition +; +; +CommonInterruptEntry PROC NEAR PUBLIC + cli + jmp $ + iret + +CommonInterruptEntry ENDP + +END +