longmode.asm

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· 汇编 代码 · 共 302 行

ASM
302
字号
      TITLE   LongMode.asm: Assembly code for the entering long mode

;------------------------------------------------------------------------------
;*
;*   Copyright 2005, 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:

END

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?