+++ /dev/null
- 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:
-
-END
-