]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg CpuExceptionHandlerLib:Convert Ia32/ExceptionHandlerAsm.asm to NASM
authorLiming Gao <liming.gao@intel.com>
Tue, 14 Jun 2016 08:11:24 +0000 (16:11 +0800)
committerLiming Gao <liming.gao@intel.com>
Tue, 28 Jun 2016 01:52:09 +0000 (09:52 +0800)
The BaseTools/Scripts/ConvertMasmToNasm.py script was used to convert
Ia32/ExceptionHandlerAsm.asm to Ia32/ExceptionHandlerAsm.nasm.
Then, manually update nasm to pass build.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm [new file with mode: 0644]

diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm
new file mode 100644 (file)
index 0000000..45d6474
--- /dev/null
@@ -0,0 +1,462 @@
+;------------------------------------------------------------------------------ ;\r
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution.  The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+;   ExceptionHandlerAsm.Asm\r
+;\r
+; Abstract:\r
+;\r
+;   IA32 CPU Exception Handler\r
+;\r
+; Notes:\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+;\r
+; CommonExceptionHandler()\r
+;\r
+extern ASM_PFX(CommonExceptionHandler)\r
+\r
+SECTION .data\r
+\r
+extern ASM_PFX(mErrorCodeFlag)            ; Error code flags for exceptions\r
+extern ASM_PFX(mDoFarReturnFlag)          ; Do far return flag\r
+\r
+SECTION .text\r
+\r
+ALIGN   8\r
+\r
+;\r
+; exception handler stub table\r
+;\r
+AsmIdtVectorBegin:\r
+%rep  32\r
+    db      0x6a        ; push  #VectorNum\r
+    db      ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum\r
+    push    eax\r
+    mov     eax, ASM_PFX(CommonInterruptEntry)\r
+    jmp     eax\r
+%endrep\r
+AsmIdtVectorEnd:\r
+\r
+HookAfterStubBegin:\r
+    db      0x6a        ; push\r
+VectorNum:\r
+    db      0          ; 0 will be fixed\r
+    push    eax\r
+    mov     eax, HookAfterStubHeaderEnd\r
+    jmp     eax\r
+HookAfterStubHeaderEnd:\r
+    pop     eax\r
+    sub     esp, 8     ; reserve room for filling exception data later\r
+    push    dword [esp + 8]\r
+    xchg    ecx, [esp] ; get vector number\r
+    bt      [ASM_PFX(mErrorCodeFlag)], ecx\r
+    jnc     .0\r
+    push    dword [esp]      ; addition push if exception data needed\r
+.0:\r
+    xchg    ecx, [esp] ; restore ecx\r
+    push    eax\r
+\r
+;----------------------------------------------------------------------------;\r
+; CommonInterruptEntry                                                               ;\r
+;----------------------------------------------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+; Entry from each interrupt with a push eax and eax=interrupt number\r
+; Stack:\r
+; +---------------------+\r
+; +    EFlags           +\r
+; +---------------------+\r
+; +    CS               +\r
+; +---------------------+\r
+; +    EIP              +\r
+; +---------------------+\r
+; +    Error Code       +\r
+; +---------------------+\r
+; +    Vector Number    +\r
+; +---------------------+\r
+; +    EBP              +\r
+; +---------------------+ <-- EBP\r
+global ASM_PFX(CommonInterruptEntry)\r
+ASM_PFX(CommonInterruptEntry):\r
+    cli\r
+    pop    eax\r
+    ;\r
+    ; All interrupt handlers are invoked through interrupt gates, so\r
+    ; IF flag automatically cleared at the entry point\r
+    ;\r
+\r
+    ;\r
+    ; Get vector number from top of stack\r
+    ;\r
+    xchg    ecx, [esp]\r
+    and     ecx, 0xFF       ; Vector number should be less than 256\r
+    cmp     ecx, 32         ; Intel reserved vector for exceptions?\r
+    jae     NoErrorCode\r
+    bt      [ASM_PFX(mErrorCodeFlag)], ecx\r
+    jc      HasErrorCode\r
+\r
+NoErrorCode:\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    ECX              +\r
+    ; +---------------------+ <-- ESP\r
+    ;\r
+    ; Registers:\r
+    ;   ECX - Vector Number\r
+    ;\r
+\r
+    ;\r
+    ; Put Vector Number on stack\r
+    ;\r
+    push    ecx\r
+\r
+    ;\r
+    ; Put 0 (dummy) error code on stack, and restore ECX\r
+    ;\r
+    xor     ecx, ecx  ; ECX = 0\r
+    xchg    ecx, [esp+4]\r
+\r
+    jmp     ErrorCodeAndVectorOnStack\r
+\r
+HasErrorCode:\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; +    ECX              +\r
+    ; +---------------------+ <-- ESP\r
+    ;\r
+    ; Registers:\r
+    ;   ECX - Vector Number\r
+    ;\r
+\r
+    ;\r
+    ; Put Vector Number on stack and restore ECX\r
+    ;\r
+    xchg    ecx, [esp]\r
+\r
+ErrorCodeAndVectorOnStack:\r
+    push    ebp\r
+    mov     ebp, esp\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; +    Vector Number    +\r
+    ; +---------------------+\r
+    ; +    EBP              +\r
+    ; +---------------------+ <-- EBP\r
+    ;\r
+\r
+    ;\r
+    ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+    ; is 16-byte aligned\r
+    ;\r
+    and     esp, 0xfffffff0\r
+    sub     esp, 12\r
+\r
+    sub     esp, 8\r
+    push    0            ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
+    push    0            ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    push    eax\r
+    push    ecx\r
+    push    edx\r
+    push    ebx\r
+    lea     ecx, [ebp + 6 * 4]\r
+    push    ecx                          ; ESP\r
+    push    dword [ebp]              ; EBP\r
+    push    esi\r
+    push    edi\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+    mov     eax, ss\r
+    push    eax\r
+    movzx   eax, word [ebp + 4 * 4]\r
+    push    eax\r
+    mov     eax, ds\r
+    push    eax\r
+    mov     eax, es\r
+    push    eax\r
+    mov     eax, fs\r
+    push    eax\r
+    mov     eax, gs\r
+    push    eax\r
+\r
+;; UINT32  Eip;\r
+    mov     eax, [ebp + 3 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+    sub     esp, 8\r
+    sidt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0xFFFF\r
+    mov     [esp+4], eax\r
+\r
+    sub     esp, 8\r
+    sgdt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0xFFFF\r
+    mov     [esp+4], eax\r
+\r
+;; UINT32  Ldtr, Tr;\r
+    xor     eax, eax\r
+    str     ax\r
+    push    eax\r
+    sldt    ax\r
+    push    eax\r
+\r
+;; UINT32  EFlags;\r
+    mov     eax, [ebp + 5 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    mov     eax, 1\r
+    push    ebx         ; temporarily save value of ebx on stack\r
+    cpuid               ; use CPUID to determine if FXSAVE/FXRESTOR and DE\r
+                        ; are supported\r
+    pop     ebx         ; retore value of ebx that was overwritten by CPUID\r
+    mov     eax, cr4\r
+    push    eax         ; push cr4 firstly\r
+    test    edx, BIT24  ; Test for FXSAVE/FXRESTOR support\r
+    jz      .1\r
+    or      eax, BIT9   ; Set CR4.OSFXSR\r
+.1:\r
+    test    edx, BIT2   ; Test for Debugging Extensions support\r
+    jz      .2\r
+    or      eax, BIT3   ; Set CR4.DE\r
+.2:\r
+    mov     cr4, eax\r
+    mov     eax, cr3\r
+    push    eax\r
+    mov     eax, cr2\r
+    push    eax\r
+    xor     eax, eax\r
+    push    eax\r
+    mov     eax, cr0\r
+    push    eax\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     eax, dr7\r
+    push    eax\r
+    mov     eax, dr6\r
+    push    eax\r
+    mov     eax, dr3\r
+    push    eax\r
+    mov     eax, dr2\r
+    push    eax\r
+    mov     eax, dr1\r
+    push    eax\r
+    mov     eax, dr0\r
+    push    eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    sub     esp, 512\r
+    mov     edi, esp\r
+    test    edx, BIT24  ; Test for FXSAVE/FXRESTOR support.\r
+                        ; edx still contains result from CPUID above\r
+    jz      .3\r
+    db      0xf, 0xae, 0x7 ;fxsave [edi]\r
+.3:\r
+\r
+;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
+    cld\r
+\r
+;; UINT32  ExceptionData;\r
+    push    dword [ebp + 2 * 4]\r
+\r
+;; Prepare parameter and call\r
+    mov     edx, esp\r
+    push    edx\r
+    mov     edx, dword [ebp + 1 * 4]\r
+    push    edx\r
+\r
+    ;\r
+    ; Call External Exception Handler\r
+    ;\r
+    mov     eax, ASM_PFX(CommonExceptionHandler)\r
+    call    eax\r
+    add     esp, 8\r
+\r
+    cli\r
+;; UINT32  ExceptionData;\r
+    add     esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    mov     esi, esp\r
+    mov     eax, 1\r
+    cpuid               ; use CPUID to determine if FXSAVE/FXRESTOR\r
+                        ; are supported\r
+    test    edx, BIT24  ; Test for FXSAVE/FXRESTOR support\r
+    jz      .4\r
+    db      0xf, 0xae, 0xe ; fxrstor [esi]\r
+.4:\r
+    add     esp, 512\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+;; Skip restoration of DRx registers to support in-circuit emualators\r
+;; or debuggers set breakpoint in interrupt/exception context\r
+    add     esp, 4 * 6\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    pop     eax\r
+    mov     cr0, eax\r
+    add     esp, 4    ; not for Cr1\r
+    pop     eax\r
+    mov     cr2, eax\r
+    pop     eax\r
+    mov     cr3, eax\r
+    pop     eax\r
+    mov     cr4, eax\r
+\r
+;; UINT32  EFlags;\r
+    pop     dword [ebp + 5 * 4]\r
+\r
+;; UINT32  Ldtr, Tr;\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     esp, 24\r
+\r
+;; UINT32  Eip;\r
+    pop     dword [ebp + 3 * 4]\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger...  We\r
+;;        could attempt to insulate ourselves against this possibility,\r
+;;        but that poses risks as well.\r
+;;\r
+    pop     gs\r
+    pop     fs\r
+    pop     es\r
+    pop     ds\r
+    pop     dword [ebp + 4 * 4]\r
+    pop     ss\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    pop     edi\r
+    pop     esi\r
+    add     esp, 4   ; not for ebp\r
+    add     esp, 4   ; not for esp\r
+    pop     ebx\r
+    pop     edx\r
+    pop     ecx\r
+    pop     eax\r
+\r
+    pop     dword [ebp - 8]\r
+    pop     dword [ebp - 4]\r
+    mov     esp, ebp\r
+    pop     ebp\r
+    add     esp, 8\r
+    cmp     dword [esp - 16], 0   ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
+    jz      DoReturn\r
+    cmp     dword [esp - 20], 1   ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
+    jz      ErrorCode\r
+    jmp     dword [esp - 16]\r
+ErrorCode:\r
+    sub     esp, 4\r
+    jmp     dword [esp - 12]\r
+\r
+DoReturn:\r
+    cmp     dword [ASM_PFX(mDoFarReturnFlag)], 0   ; Check if need to do far return instead of IRET\r
+    jz      DoIret\r
+    push    dword [esp + 8]    ; save EFLAGS\r
+    add     esp, 16\r
+    push    dword [esp - 8]    ; save CS in new location\r
+    push    dword [esp - 8]    ; save EIP in new location\r
+    push    dword [esp - 8]    ; save EFLAGS in new location\r
+    popfd                ; restore EFLAGS\r
+    retf                 ; far return\r
+\r
+DoIret:\r
+    iretd\r
+\r
+;---------------------------------------;\r
+; _AsmGetTemplateAddressMap                  ;\r
+;----------------------------------------------------------------------------;\r
+;\r
+; Protocol prototype\r
+;   AsmGetTemplateAddressMap (\r
+;     EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap\r
+;   );\r
+;\r
+; Routine Description:\r
+;\r
+;  Return address map of interrupt handler template so that C code can generate\r
+;  interrupt table.\r
+;\r
+; Arguments:\r
+;\r
+;\r
+; Returns:\r
+;\r
+;   Nothing\r
+;\r
+;\r
+; Input:  [ebp][0]  = Original ebp\r
+;         [ebp][4]  = Return address\r
+;\r
+; Output: Nothing\r
+;\r
+; Destroys: Nothing\r
+;-----------------------------------------------------------------------------;\r
+global ASM_PFX(AsmGetTemplateAddressMap)\r
+ASM_PFX(AsmGetTemplateAddressMap):\r
+    push    ebp                 ; C prolog\r
+    mov     ebp, esp\r
+    pushad\r
+\r
+    mov ebx, dword [ebp + 0x8]\r
+    mov dword [ebx],      AsmIdtVectorBegin\r
+    mov dword [ebx + 0x4], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32\r
+    mov dword [ebx + 0x8], HookAfterStubBegin\r
+\r
+    popad\r
+    pop     ebp\r
+    ret\r
+\r
+;-------------------------------------------------------------------------------------\r
+;  AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);\r
+;-------------------------------------------------------------------------------------\r
+global ASM_PFX(AsmVectorNumFixup)\r
+ASM_PFX(AsmVectorNumFixup):\r
+    mov     eax, dword [esp + 8]\r
+    mov     ecx, [esp + 4]\r
+    mov     [ecx + (VectorNum - HookAfterStubBegin)], al\r
+    ret\r