efi64.asm

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

ASM
788
字号
;------------------------------------------------------------------------------
;*
;*   Copyright 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.             
;*   
;*    efi64.asm
;*  
;*   Abstract:
;*
;------------------------------------------------------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Now in 64-bit long mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        .486
        .model  flat        
        .stack
        .code
        org 21000h
        
DEFAULT_HANDLER_SIZE EQU INT1 - INT0

JmpCommonIdtEntry  macro
    ; jmp     commonIdtEntry - this must be hand coded to keep the assembler from
    ;                          using a 8 bit reletive jump when the entries are
    ;                          within 255 bytes of the common entry.  This must
    ;                          be done to maintain the consistency of the size
    ;                          of entry points...
    db      0e9h                        ; jmp 16 bit reletive 
    dd      commonIdtEntry - $ - 4      ;  offset to jump to
endm    

        
Start:  

    mov     esp,0001fffe8h ; make final stack aligned

    ; set OSFXSR and OSXMMEXCPT because some code will use XMM register
    db 0fh
    db 20h
    db 0e0h
;    mov rax, cr4
    bts eax, 9
    bts eax, 0ah
    db 0fh
    db 22h
    db 0e0h
;    mov cr4, rax

    call    ClearScreen

    ; Populate IDT with meaningful offsets for exception handlers...
    mov     eax, offset Idtr
    sidt    fword ptr [eax]             ; get fword address of IDT

    mov     eax, offset Halt
    mov     ebx, eax                    ; use bx to copy 15..0 to descriptors
    shr     eax, 16                     ; use ax to copy 31..16 to descriptors 
                                        ; 63..32 of descriptors is 0
    mov     ecx, 78h                    ; 78h IDT entries to initialize with unique entry points (exceptions)
    mov     esi, [offset Idtr + 2]
    mov     edi, [esi]

@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler
    mov     word ptr [edi], bx                  ; write bits 15..0 of offset
    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT
    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present
    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset
    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset
    add     edi, 16                             ; move up to next descriptor
    add     bx, DEFAULT_HANDLER_SIZE            ; move to next entry point
    loop    @b                                  ; loop back through again until all descriptors are initialized
    
    ;; at this point edi contains the offset of the descriptor for INT 20
    ;; and bx contains the low 16 bits of the offset of the default handler
    ;; so initialize all the rest of the descriptors with these two values...
;    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)
;@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler
;    mov     word ptr [edi], bx                  ; write bits 15..0 of offset
;    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT
;    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present
;    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset
;    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset
;    add     edi, 16                             ; move up to next descriptor
;    loop    @b                                  ; loop back through again until all descriptors are initialized
    
    
;;  DUMP    location of IDT and several of the descriptors
;    mov     ecx, 8
;    mov     eax, [offset Idtr + 2]
;    mov     eax, [eax]
;    mov     edi, 0b8000h
;    call    PrintQword
;    mov     esi, eax
;    mov     edi, 0b80a0h
;    jmp     OuterLoop
    
;;    
;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...
;    mov     eax, 011111111h
;    mov     ebx, 022222222h
;    mov     ecx, 033333333h
;    mov     edx, 044444444h
;    mov     ebp, 055555555h
;    mov     esi, 066666666h
;    mov     edi, 077777777h
;    push    011111111h
;    push    022222222h
;    push    033333333h
;    int     119

    mov     esi,022000h                 ; esi = 22000
    mov     eax,[esi+014h]              ; eax = [22014]
    add     esi,eax                     ; esi = 22000 + [22014] = Base of EFILDR.C
    mov     ebp,[esi+03ch]              ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C
    add     ebp,esi
    mov     edi,[ebp+030h]              ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)
    mov     eax,[ebp+028h]              ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint
    add     eax,edi                     ; eax = ImageBase + EntryPoint
    mov     ebx, offset EfiLdrOffset
    mov     dword ptr [ebx],eax         ; Modify far jump instruction for correct entry point

    mov     bx,word ptr[ebp+6]          ; bx = Number of sections
    xor     eax,eax
    mov     ax,word ptr[ebp+014h]       ; ax = Optional Header Size
    add     ebp,eax
    add     ebp,018h                    ; ebp = Start of 1st Section

SectionLoop:
    push    esi                         ; Save Base of EFILDR.C
    push    edi                         ; Save ImageBase
    add     esi,[ebp+014h]              ; esi = Base of EFILDR.C + PointerToRawData
    add     edi,[ebp+00ch]              ; edi = ImageBase + VirtualAddress
    mov     ecx,[ebp+010h]              ; ecs = SizeOfRawData

    cld
    shr     ecx,2
    rep     movsd

    pop     edi                         ; Restore ImageBase
    pop     esi                         ; Restore Base of EFILDR.C

    add     bp,028h                     ; ebp = ebp + 028h = Pointer to next section record
    db 66h
    db 0ffh
    db 0cbh
;    dec     bx
    cmp     bx,0
    jne     SectionLoop

    mov     edx, offset Idtr
    movzx   eax, word ptr [edx]          ; get size of IDT
    db 0ffh
    db 0c0h
;    inc     eax
    add     eax, dword ptr [edx + 2]     ; add to base of IDT to get location of memory map...
    xor     ecx, ecx
    mov     ecx, eax                     ; put argument to RCX

    db 48h
    db 0c7h
    db 0c0h
EfiLdrOffset:
    dd      000401000h                  ; Offset of EFILDR
;   mov rax, 401000h
    db 50h
;   push rax

; ret
    db 0c3h

;    db      "**** DEFAULT IDT ENTRY ***",0
    align 02h
Halt:
INT0:
    push    0h      ; push error code place holder on the stack
    push    0h
    JmpCommonIdtEntry
;    db      0e9h                        ; jmp 16 bit reletive 
;    dd      commonIdtEntry - $ - 4      ;  offset to jump to
    
INT1:
    push    0h      ; push error code place holder on the stack
    push    1h
    JmpCommonIdtEntry
    
INT2:
    push    0h      ; push error code place holder on the stack
    push    2h
    JmpCommonIdtEntry
    
INT3:
    push    0h      ; push error code place holder on the stack
    push    3h
    JmpCommonIdtEntry
    
INT4:
    push    0h      ; push error code place holder on the stack
    push    4h
    JmpCommonIdtEntry
    
INT5:
    push    0h      ; push error code place holder on the stack
    push    5h
    JmpCommonIdtEntry
    
INT6:
    push    0h      ; push error code place holder on the stack
    push    6h
    JmpCommonIdtEntry
    
INT7:
    push    0h      ; push error code place holder on the stack
    push    7h
    JmpCommonIdtEntry
    
INT8:
;   Double fault causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    8h
    JmpCommonIdtEntry
    
INT9:
    push    0h      ; push error code place holder on the stack
    push    9h
    JmpCommonIdtEntry
    
INT10:
;   Invalid TSS causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    10
    JmpCommonIdtEntry
    
INT11:
;   Segment Not Present causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    11
    JmpCommonIdtEntry
    
INT12:
;   Stack fault causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    12
    JmpCommonIdtEntry
    
INT13:
;   GP fault causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    13
    JmpCommonIdtEntry
    
INT14:
;   Page fault causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    14
    JmpCommonIdtEntry
    
INT15:
    push    0h      ; push error code place holder on the stack
    push    15
    JmpCommonIdtEntry
    
INT16:
    push    0h      ; push error code place holder on the stack
    push    16
    JmpCommonIdtEntry
    
INT17:
;   Alignment check causes an error code to be pushed so no phony push necessary
    nop
    nop
    push    17
    JmpCommonIdtEntry
    
INT18:
    push    0h      ; push error code place holder on the stack
    push    18
    JmpCommonIdtEntry
    
INT19:
    push    0h      ; push error code place holder on the stack
    push    19
    JmpCommonIdtEntry

INTUnknown:
REPEAT  (78h - 20)
    push    0h      ; push error code place holder on the stack
;    push    xxh     ; push vector number
    db      06ah
    db      ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
    JmpCommonIdtEntry
ENDM

commonIdtEntry:
    push    eax
    push    ecx
    push    edx
    push    ebx
    push    esp
    push    ebp
    push    esi
    push    edi
    db 41h
    db 50h
;    push    r8
    db 41h
    db 51h
;    push    r9
    db 41h
    db 52h
;    push    r10
    db 41h
    db 53h
;    push    r11
    db 41h
    db 54h
;    push    r12
    db 41h
    db 55h
;    push    r13
    db 41h
    db 56h
;    push    r14
    db 41h
    db 57h
;    push    r15
    db 48h
    mov     ebp, esp
;    mov     rbp, rsp

;;
;;  At this point the stack looks like this:
;;
;;      Calling SS
;;      Calling RSP
;;      rflags
;;      Calling CS
;;      Calling RIP
;;      Error code or 0
;;      Int num or 0ffh for unknown int num
;;      rax
;;      rcx
;;      rdx
;;      rbx
;;      rsp
;;      rbp
;;      rsi
;;      rdi
;;      r8
;;      r9
;;      r10
;;      r11
;;      r12
;;      r13
;;      r14
;;      r15 <------- RSP, RBP
;;      

    call    ClearScreen
    mov     esi, offset String1
    call    PrintString
    db 48h
    mov     eax, [ebp + 16*8]     ;; move Int number into RAX 
    db 48h
    cmp     eax, 18
    ja      PrintDefaultString
PrintExceptionString:
    shl     eax, 3              ;; multiply by 8 to get offset from StringTable to actual string address
    add     eax, offset StringTable
    mov     esi, [eax]
    jmp     PrintTheString
PrintDefaultString:
    mov     esi, offset IntUnknownString
    ; patch Int number
    mov     edx, eax
    call    A2C
    mov     [esi + 1], al
    mov     eax, edx
    shr     eax, 4
    call    A2C
    mov     [esi], al

⌨️ 快捷键说明

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