]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseLib/X64/Thunk16.asm
Updated BaseLib for THUNK functions and some CPU functions
[mirror_edk2.git] / MdePkg / Library / BaseLib / X64 / Thunk16.asm
index f3e80840b3ef6240952899b2a513f927a7ff9f9c..15aaa80090774af1e8a94a03ed398283bde3819a 100644 (file)
 ;\r
 ;------------------------------------------------------------------------------\r
 \r
-    .data\r
+EXTERNDEF   m16Start:BYTE\r
+EXTERNDEF   m16Size:WORD\r
+EXTERNDEF   mThunk16Attr:WORD\r
+EXTERNDEF   m16Gdt:WORD\r
+EXTERNDEF   m16GdtrBase:WORD\r
+EXTERNDEF   mTransition:WORD\r
 \r
-NullSegSel      DQ      0\r
-_16CsSegSel     LABEL   QWORD\r
-                DW      -1\r
-                DW      0\r
-                DB      0\r
-                DB      9bh\r
-                DB      8fh             ; 16-bit segment\r
-                DB      0\r
-_16BitDsSel     LABEL   QWORD\r
-                DW      -1\r
-                DW      0\r
-                DB      0\r
-                DB      93h\r
-                DB      8fh             ; 16-bit segment\r
-                DB      0\r
-GdtEnd          LABEL   QWORD\r
-\r
-    .const\r
-\r
-_16Gdtr         LABEL   FWORD\r
-                DW      offset GdtEnd - offset NullSegSel - 1\r
-                DQ      offset NullSegSel\r
-\r
-_16Idtr         FWORD   (1 SHL 10) - 1\r
-\r
-    .code\r
+THUNK_ATTRIBUTE_BIG_REAL_MODE               EQU 1\r
+THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15     EQU 2\r
+THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL   EQU 4\r
 \r
 IA32_REGS   STRUC   4t\r
 _EDI        DD      ?\r
@@ -61,128 +43,192 @@ _DS         DW      ?
 _ES         DW      ?\r
 _FS         DW      ?\r
 _GS         DW      ?\r
-_RFLAGS     DQ      ?\r
+_EFLAGS     DQ      ?\r
 _EIP        DD      ?\r
 _CS         DW      ?\r
 _SS         DW      ?\r
 IA32_REGS   ENDS\r
 \r
-InternalAsmThunk16  PROC    USES    rbp rbx rsi rdi r12 r13 r14 r15\r
-    mov     eax, ds\r
-    push    rax\r
-    mov     eax, es\r
-    push    rax\r
-    push    fs\r
-    push    gs\r
-    mov     rsi, rcx                    ; rsi <- RegSet\r
-    push    sizeof (IA32_REGS)\r
-    pop     rcx\r
-    movzx   r8, (IA32_REGS ptr [rsi])._SS\r
-    xor     rdi, rdi\r
-    mov     edi, (IA32_REGS ptr [rsi])._ESP\r
-    sub     rdi, rcx                    ; reserve space on realmode stack\r
-    push    rdi                         ; save stack offset\r
-    imul    rax, r8, 16\r
-    add     rdi, rax                    ; rdi <- linear address of 16-bit stack\r
-    rep     movsb                       ; copy RegSet\r
-    mov     rsi, r8                     ; si <- 16-bit stack segment\r
-    pop     rbx                         ; rbx <- 16-bit stack offset\r
-    mov     rdi, rdx                    ; rdi <- realmode patch\r
-    lea     eax, @BackToThunk           ; rax <- address to back from real mode\r
-    push    rax                         ; use in a far return\r
-    mov     eax, cs\r
-    mov     [rsp + 4], eax              ; save CS\r
-    lea     eax, @16Return              ; thus @Return must < 4GB\r
-    stosd                               ; set ret address offset\r
-    xor     eax, eax\r
-    stosw                               ; set ret CS base to 0\r
-    mov     eax, esp\r
-    stosd                               ; rsp must < 4GB\r
-    mov     eax, ss\r
-    stosd\r
-    mov     rax, cr0\r
-    mov     ecx, eax                    ; ecx <- CR0\r
-    and     ecx, 7ffffffeh              ; clear PE, PG bits\r
-    stosd\r
-    mov     rax, cr4\r
-    mov     ebp, eax\r
-    and     ebp, 300h                   ; clear all but PCE and OSFXSR bits\r
-    stosd\r
-    sidt    fword ptr [rsp + 70h]       ; use parameter space to save IDTR\r
-    sgdt    fword ptr [rdi]\r
-    lea     edi, _16Idtr\r
-    lea     eax, @16Start               ; rax <- seg:offset of @16Start\r
-    push    rax\r
-    mov     dword ptr [rsp + 4], 8\r
-    push    10h\r
-    pop     rax                         ; rax <- 10h as dataseg selector\r
-    lgdt    _16Gdtr\r
-    retf\r
-@16Start:                               ; 16-bit starts here\r
-    mov     ss, eax                     ; set SS to be a 16-bit segment\r
-    mov     cr0, rcx                    ; disable protected mode\r
-    mov     cr4, rbp\r
-    DB      66h\r
-    mov     ecx, 0c0000080h\r
-    rdmsr\r
-    and     ah, NOT 1                   ; clear LME\r
-    wrmsr\r
-    mov     ss, esi                     ; set up 16-bit stack\r
-    mov     sp, bx                      ; mov esp, ebx actually\r
-    lidt    fword ptr [edi]\r
-    DB      66h, 61h                    ; popad\r
-    DB      1fh                         ; pop ds\r
-    DB      7                           ; pop es\r
-    pop     fs\r
-    pop     gs\r
-    add     sp, 8                       ; skip _RFLAGS\r
+    .const\r
+\r
+m16Size         DW      offset InternalAsmThunk16 - offset m16Start\r
+mThunk16Attr    DW      offset _ThunkAttr - offset m16Start\r
+m16Gdt          DW      offset _NullSegDesc - offset m16Start\r
+m16GdtrBase     DW      offset _16GdtrBase - offset m16Start\r
+mTransition     DW      offset _EntryPoint - offset m16Start\r
+\r
+    .code\r
+\r
+m16Start    LABEL   BYTE\r
+\r
+SavedGdt        LABEL   FWORD\r
+                DW      ?\r
+                DQ      ?\r
+\r
+_BackFromUserCode   PROC\r
+    DB      16h                         ; push ss\r
+    DB      0eh                         ; push cs\r
     DB      66h\r
-    retf                                ; transfer control to 16-bit code\r
-@16Return:\r
+    call    @Base                       ; push eip\r
+@Base:\r
     DB      66h\r
-    push    0                           ; high order 32 bits of rflags\r
+    push    0                           ; reserved high order 32 bits of EFlags\r
     pushf                               ; pushfd actually\r
+    cli                                 ; disable interrupts\r
     push    gs\r
     push    fs\r
     DB      6                           ; push es\r
     DB      1eh                         ; push ds\r
     DB      66h, 60h                    ; pushad\r
-    DB      67h, 66h, 0c5h, 74h, 24h, 30h   ; lds esi, [esp + 12*4]\r
-    DB      66h\r
-    mov     eax, [esi + 12]\r
-    mov     cr4, rax                    ; restore CR4\r
-    DB      66h\r
-    lgdt    fword ptr [esi + 16]\r
+    DB      66h, 0bah                   ; mov edx, imm32\r
+_ThunkAttr  DD      ?\r
+    test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15\r
+    jz      @1\r
+    mov     eax, 15cd2401h              ; mov ax, 2401h & int 15h\r
+    cli                                 ; disable interrupts\r
+    jnc     @2\r
+@1:\r
+    test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL\r
+    jz      @2\r
+    in      al, 92h\r
+    or      al, 2\r
+    out     92h, al                     ; deactivate A20M#\r
+@2:\r
+    mov     eax, ss\r
+    lea     bp, [esp + sizeof (IA32_REGS)]\r
+    mov     word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp\r
+    mov     ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP\r
+    shl     ax, 4                       ; shl eax, 4\r
+    add     bp, ax                      ; add ebp, eax\r
+    DB      66h, 0b8h                   ; mov eax, imm32\r
+SavedCr4    DD      ?\r
+    mov     cr4, rax\r
+    DB      66h, 2eh\r
+    lgdt    fword ptr [rdi + (offset SavedGdt - offset @Base)]\r
     DB      66h\r
     mov     ecx, 0c0000080h\r
     rdmsr\r
-    or      ah, 1                       ; set LME\r
+    or      ah, 1\r
     wrmsr\r
+    DB      66h, 0b8h                   ; mov eax, imm32\r
+SavedCr0    DD      ?\r
+    mov     cr0, rax\r
+    DB      0b8h                        ; mov ax, imm16\r
+SavedSs     DW      ?\r
+    mov     ss, eax\r
+    DB      66h, 0bch                   ; mov esp, imm32\r
+SavedEsp    DD      ?\r
     DB      66h\r
-    mov     eax, [esi + 8]\r
-    mov     cr0, rax                    ; restore CR0\r
-    xor     ax, ax                      ; xor eax, eax actually\r
-    mov     eax, ss\r
-    mov     dword ptr (IA32_REGS ptr [esp])._SS, eax\r
-    shl     ax, 4                       ; shl eax, 4 actually\r
-    add     ax, sp                      ; add eax, esp actually\r
-    add     sp, sizeof (IA32_REGS)      ; add esp, sizeof (IA32_REGS)\r
+    retf                                ; return to protected mode\r
+_BackFromUserCode   ENDP\r
+\r
+_EntryPoint     DD      offset _ToUserCode - offset m16Start\r
+                DW      8h\r
+_16Gdtr         LABEL   FWORD\r
+                DW      offset GdtEnd - offset _NullSegDesc - 1\r
+_16GdtrBase     DQ      offset _NullSegDesc\r
+_16Idtr         FWORD   (1 SHL 10) - 1\r
+\r
+_ToUserCode PROC\r
+    mov     edi, ss\r
+    mov     ss, edx                     ; set new segment selectors\r
+    mov     ds, edx\r
+    mov     es, edx\r
+    mov     fs, edx\r
+    mov     gs, edx\r
     DB      66h\r
-    mov     dword ptr (IA32_REGS ptr [esp - sizeof (IA32_REGS)])._ESP, esp\r
+    mov     ecx, 0c0000080h\r
+    mov     cr0, rax                    ; real mode starts at next instruction\r
+    rdmsr\r
+    and     ah, NOT 1\r
+    wrmsr\r
+    mov     cr4, rbp\r
+    mov     ss, esi                     ; set up 16-bit stack segment\r
+    xchg    sp, bx                      ; set up 16-bit stack pointer\r
     DB      66h\r
-    lss     esp, fword ptr [esi]        ; restore protected mode stack\r
+    call    @Base                       ; push eip\r
+@Base:\r
+    pop     bp                          ; ebp <- offset @Base\r
+    DB      2eh                         ; cs:\r
+    mov     [rsi + (offset SavedSs - offset @Base)], edi\r
+    DB      2eh                         ; cs:\r
+    mov     [rsi + (offset SavedEsp - offset @Base)], bx\r
+    DB      66h, 2eh                    ; CS and operand size override\r
+    lidt    fword ptr [rsi + (offset _16Idtr - offset @Base)]\r
+    DB      66h, 61h                    ; popad\r
+    DB      1fh                         ; pop ds\r
+    DB      07h                         ; pop es\r
+    pop     fs\r
+    pop     gs\r
+    popf                                ; popfd\r
+    lea     sp, [esp + 4]               ; skip high order 32 bits of EFlags\r
     DB      66h\r
-    retf                                ; go back to protected mode\r
-@BackToThunk:\r
-    lidt    fword ptr [rsp + 68h]       ; restore protected mode IDTR\r
-    shl     rax, 32\r
-    shr     rax, 32                     ; clear high order 32 bits of RAX\r
+    retf                                ; transfer control to user code\r
+_ToUserCode ENDP\r
+\r
+_NullSegDesc    DQ      0\r
+_16CsDesc       LABEL   QWORD\r
+                DW      -1\r
+                DW      0\r
+                DB      0\r
+                DB      9bh\r
+                DB      8fh             ; 16-bit segment, 4GB limit\r
+                DB      0\r
+_16DsDesc       LABEL   QWORD\r
+                DW      -1\r
+                DW      0\r
+                DB      0\r
+                DB      93h\r
+                DB      8fh             ; 16-bit segment, 4GB limit\r
+                DB      0\r
+GdtEnd          LABEL   QWORD\r
+\r
+;\r
+;   @param  RegSet  Pointer to a IA32_DWORD_REGS structure\r
+;   @param  Transition  Pointer to the transition code\r
+;   @return The address of the 16-bit stack after returning from user code\r
+;\r
+InternalAsmThunk16  PROC    USES    rbp rbx rsi rdi\r
+    mov     r10d, ds\r
+    mov     r11d, es\r
+    push    fs\r
+    push    gs\r
+    mov     rsi, rcx\r
+    movzx   r8d, (IA32_REGS ptr [rsi])._SS\r
+    mov     edi, (IA32_REGS ptr [rsi])._ESP\r
+    lea     rdi, [edi - (sizeof (IA32_REGS) + 4)]\r
+    imul    eax, r8d, 16                ; eax <- r8d(stack segment) * 16\r
+    mov     ebx, edi                    ; ebx <- stack offset for 16-bit code\r
+    push    sizeof (IA32_REGS) / 4\r
+    add     edi, eax                    ; edi <- linear address of 16-bit stack\r
+    pop     rcx\r
+    rep     movsd                       ; copy RegSet\r
+    lea     ecx, [rdx + (offset SavedCr4 - offset m16Start)]\r
+    mov     eax, edx                    ; eax <- transition code address\r
+    and     edx, 0fh\r
+    shl     eax, 12\r
+    lea     edx, [rdx + (offset _BackFromUserCode - offset m16Start)]\r
+    mov     ax, dx\r
+    stosd                               ; [edi] <- return address of user code\r
+    sgdt    fword ptr [rcx + (offset SavedGdt - offset SavedCr4)]\r
+    sidt    fword ptr [rsp + 38h]       ; save IDT stack in argument space\r
+    mov     rax, cr0\r
+    mov     [rcx + (offset SavedCr0 - offset SavedCr4)], eax\r
+    and     eax, 7ffffffeh              ; clear PE, PG bits\r
+    mov     rbp, cr4\r
+    mov     [rcx], ebp                  ; save CR4 in SavedCr4\r
+    and     ebp, 300h                   ; clear all but PCE and OSFXSR bits\r
+    mov     esi, r8d                    ; esi <- 16-bit stack segment\r
+    push    10h\r
+    pop     rdx                         ; rdx <- selector for data segments\r
+    lgdt    fword ptr [rcx + (offset _16Gdtr - offset SavedCr4)]\r
+    call    fword ptr [rcx + (offset _EntryPoint - offset SavedCr4)]\r
+    lidt    fword ptr [rsp + 38h]       ; restore protected mode IDTR\r
+    lea     eax, [rbp - sizeof (IA32_REGS)]\r
     pop     gs\r
     pop     fs\r
-    pop     rcx\r
-    mov     es, ecx\r
-    pop     rcx\r
-    mov     ds, ecx\r
+    mov     es, r11d\r
+    mov     ds, r10d\r
     ret\r
 InternalAsmThunk16  ENDP\r
 \r