https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			320 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			320 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
 | 
						|
#include "BaseLibInternals.h"
 | 
						|
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
;
 | 
						|
; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
; SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
;
 | 
						|
; Module Name:
 | 
						|
;
 | 
						|
;   Thunk.asm
 | 
						|
;
 | 
						|
; Abstract:
 | 
						|
;
 | 
						|
;   Real mode thunk
 | 
						|
;
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
 | 
						|
global ASM_PFX(m16Size)
 | 
						|
global ASM_PFX(mThunk16Attr)
 | 
						|
global ASM_PFX(m16Gdt)
 | 
						|
global ASM_PFX(m16GdtrBase)
 | 
						|
global ASM_PFX(mTransition)
 | 
						|
global ASM_PFX(m16Start)
 | 
						|
 | 
						|
struc IA32_REGS
 | 
						|
 | 
						|
  ._EDI:       resd      1
 | 
						|
  ._ESI:       resd      1
 | 
						|
  ._EBP:       resd      1
 | 
						|
  ._ESP:       resd      1
 | 
						|
  ._EBX:       resd      1
 | 
						|
  ._EDX:       resd      1
 | 
						|
  ._ECX:       resd      1
 | 
						|
  ._EAX:       resd      1
 | 
						|
  ._DS:        resw      1
 | 
						|
  ._ES:        resw      1
 | 
						|
  ._FS:        resw      1
 | 
						|
  ._GS:        resw      1
 | 
						|
  ._EFLAGS:    resq      1
 | 
						|
  ._EIP:       resd      1
 | 
						|
  ._CS:        resw      1
 | 
						|
  ._SS:        resw      1
 | 
						|
  .size:
 | 
						|
 | 
						|
endstruc
 | 
						|
 | 
						|
SECTION .data
 | 
						|
 | 
						|
;
 | 
						|
; These are global constant to convey information to C code.
 | 
						|
;
 | 
						|
ASM_PFX(m16Size)         DW      ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)
 | 
						|
ASM_PFX(mThunk16Attr)    DW      _BackFromUserCode.ThunkAttrEnd - 4 - ASM_PFX(m16Start)
 | 
						|
ASM_PFX(m16Gdt)          DW      _NullSeg - ASM_PFX(m16Start)
 | 
						|
ASM_PFX(m16GdtrBase)     DW      _16GdtrBase - ASM_PFX(m16Start)
 | 
						|
ASM_PFX(mTransition)     DW      _EntryPoint - ASM_PFX(m16Start)
 | 
						|
 | 
						|
SECTION .text
 | 
						|
 | 
						|
ASM_PFX(m16Start):
 | 
						|
 | 
						|
SavedGdt:
 | 
						|
            dw  0
 | 
						|
            dq  0
 | 
						|
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
; _BackFromUserCode() takes control in real mode after 'retf' has been executed
 | 
						|
; by user code. It will be shadowed to somewhere in memory below 1MB.
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
_BackFromUserCode:
 | 
						|
    ;
 | 
						|
    ; The order of saved registers on the stack matches the order they appears
 | 
						|
    ; in IA32_REGS structure. This facilitates wrapper function to extract them
 | 
						|
    ; into that structure.
 | 
						|
    ;
 | 
						|
BITS    16
 | 
						|
    push    ss
 | 
						|
    push    cs
 | 
						|
    ;
 | 
						|
    ; Note: We can't use o32 on the next instruction because of a bug
 | 
						|
    ; in NASM 2.09.04 through 2.10rc1.
 | 
						|
    ;
 | 
						|
    call    dword .Base                 ; push eip
 | 
						|
.Base:
 | 
						|
    push    dword 0                     ; reserved high order 32 bits of EFlags
 | 
						|
    pushfd
 | 
						|
    cli                                 ; disable interrupts
 | 
						|
    push    gs
 | 
						|
    push    fs
 | 
						|
    push    es
 | 
						|
    push    ds
 | 
						|
    pushad
 | 
						|
    mov     edx, strict dword 0
 | 
						|
.ThunkAttrEnd:
 | 
						|
    test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
 | 
						|
    jz      .1
 | 
						|
    mov     ax, 2401h
 | 
						|
    int     15h
 | 
						|
    cli                                 ; disable interrupts
 | 
						|
    jnc     .2
 | 
						|
.1:
 | 
						|
    test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL
 | 
						|
    jz      .2
 | 
						|
    in      al, 92h
 | 
						|
    or      al, 2
 | 
						|
    out     92h, al                     ; deactivate A20M#
 | 
						|
.2:
 | 
						|
    xor     eax, eax
 | 
						|
    mov     ax, ss
 | 
						|
    lea     ebp, [esp + IA32_REGS.size]
 | 
						|
    mov     [bp - IA32_REGS.size + IA32_REGS._ESP], ebp
 | 
						|
    mov     ebx, [bp - IA32_REGS.size + IA32_REGS._EIP]
 | 
						|
    shl     eax, 4                      ; shl eax, 4
 | 
						|
    add     ebp, eax                    ; add ebp, eax
 | 
						|
    mov     eax, cs
 | 
						|
    shl     eax, 4
 | 
						|
    lea     eax, [eax + ebx + (.X64JmpEnd - .Base)]
 | 
						|
    mov     [cs:bx + (.X64JmpEnd - 6 - .Base)], eax
 | 
						|
    mov     eax, strict dword 0
 | 
						|
.SavedCr4End:
 | 
						|
    mov     cr4, eax
 | 
						|
o32 lgdt [cs:bx + (SavedGdt - .Base)]
 | 
						|
    mov     ecx, 0c0000080h
 | 
						|
    rdmsr
 | 
						|
    or      ah, 1
 | 
						|
    wrmsr
 | 
						|
    mov     eax, strict dword 0
 | 
						|
.SavedCr0End:
 | 
						|
    mov     cr0, eax
 | 
						|
    jmp     0:strict dword 0
 | 
						|
.X64JmpEnd:
 | 
						|
BITS    64
 | 
						|
    nop
 | 
						|
    mov rsp, strict qword 0
 | 
						|
.SavedSpEnd:
 | 
						|
    nop
 | 
						|
    ret
 | 
						|
 | 
						|
_EntryPoint:
 | 
						|
        DD      _ToUserCode - ASM_PFX(m16Start)
 | 
						|
        DW      CODE16
 | 
						|
_16Gdtr:
 | 
						|
        DW      GDT_SIZE - 1
 | 
						|
_16GdtrBase:
 | 
						|
        DQ      0
 | 
						|
_16Idtr:
 | 
						|
        DW      (1 << 10) - 1
 | 
						|
        DD      0
 | 
						|
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
; _ToUserCode() takes control in real mode before passing control to user code.
 | 
						|
; It will be shadowed to somewhere in memory below 1MB.
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
_ToUserCode:
 | 
						|
BITS    16
 | 
						|
    mov     ss, dx                      ; set new segment selectors
 | 
						|
    mov     ds, dx
 | 
						|
    mov     es, dx
 | 
						|
    mov     fs, dx
 | 
						|
    mov     gs, dx
 | 
						|
    mov     ecx, 0c0000080h
 | 
						|
    mov     cr0, eax                    ; real mode starts at next instruction
 | 
						|
    rdmsr
 | 
						|
    and     ah, ~1
 | 
						|
    wrmsr
 | 
						|
    mov     cr4, ebp
 | 
						|
    mov     ss, si                      ; set up 16-bit stack segment
 | 
						|
    mov     esp, ebx                    ; set up 16-bit stack pointer
 | 
						|
    call    dword .Base                 ; push eip
 | 
						|
.Base:
 | 
						|
    pop     ebp                         ; ebp <- address of .Base
 | 
						|
    push    word [dword esp + IA32_REGS.size + 2]
 | 
						|
    lea     ax, [bp + (.RealMode - .Base)]
 | 
						|
    push    ax
 | 
						|
    retf                                ; execution begins at next instruction
 | 
						|
.RealMode:
 | 
						|
 | 
						|
o32 lidt    [cs:bp + (_16Idtr - .Base)]
 | 
						|
 | 
						|
    popad
 | 
						|
    pop     ds
 | 
						|
    pop     es
 | 
						|
    pop     fs
 | 
						|
    pop     gs
 | 
						|
    popfd
 | 
						|
    lea     esp, [esp + 4]        ; skip high order 32 bits of EFlags
 | 
						|
 | 
						|
o32 retf                                ; transfer control to user code
 | 
						|
 | 
						|
ALIGN   8
 | 
						|
 | 
						|
CODE16  equ _16Code - $
 | 
						|
DATA16  equ _16Data - $
 | 
						|
DATA32  equ _32Data - $
 | 
						|
 | 
						|
_NullSeg    DQ      0
 | 
						|
_16Code:
 | 
						|
            DW      -1
 | 
						|
            DW      0
 | 
						|
            DB      0
 | 
						|
            DB      9bh
 | 
						|
            DB      8fh                 ; 16-bit segment, 4GB limit
 | 
						|
            DB      0
 | 
						|
_16Data:
 | 
						|
            DW      -1
 | 
						|
            DW      0
 | 
						|
            DB      0
 | 
						|
            DB      93h
 | 
						|
            DB      8fh                 ; 16-bit segment, 4GB limit
 | 
						|
            DB      0
 | 
						|
_32Data:
 | 
						|
            DW      -1
 | 
						|
            DW      0
 | 
						|
            DB      0
 | 
						|
            DB      93h
 | 
						|
            DB      0cfh                ; 16-bit segment, 4GB limit
 | 
						|
            DB      0
 | 
						|
 | 
						|
GDT_SIZE equ $ - _NullSeg
 | 
						|
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
; IA32_REGISTER_SET *
 | 
						|
; EFIAPI
 | 
						|
; InternalAsmThunk16 (
 | 
						|
;   IN      IA32_REGISTER_SET         *RegisterSet,
 | 
						|
;   IN OUT  VOID                      *Transition
 | 
						|
;   );
 | 
						|
;------------------------------------------------------------------------------
 | 
						|
global ASM_PFX(InternalAsmThunk16)
 | 
						|
ASM_PFX(InternalAsmThunk16):
 | 
						|
BITS    64
 | 
						|
    push    rbp
 | 
						|
    push    rbx
 | 
						|
    push    rsi
 | 
						|
    push    rdi
 | 
						|
 | 
						|
    mov     ebx, ds
 | 
						|
    push    rbx          ; Save ds segment register on the stack
 | 
						|
    mov     ebx, es
 | 
						|
    push    rbx          ; Save es segment register on the stack
 | 
						|
    mov     ebx, ss
 | 
						|
    push    rbx          ; Save ss segment register on the stack
 | 
						|
 | 
						|
    push    fs
 | 
						|
    push    gs
 | 
						|
    mov     rsi, rcx
 | 
						|
    movzx   r8d, word [rsi + IA32_REGS._SS]
 | 
						|
    mov     edi, [rsi + IA32_REGS._ESP]
 | 
						|
    lea     rdi, [edi - (IA32_REGS.size + 4)]
 | 
						|
    imul    eax, r8d, 16                ; eax <- r8d(stack segment) * 16
 | 
						|
    mov     ebx, edi                    ; ebx <- stack for 16-bit code
 | 
						|
    push    IA32_REGS.size / 4
 | 
						|
    add     edi, eax                    ; edi <- linear address of 16-bit stack
 | 
						|
    pop     rcx
 | 
						|
    rep     movsd                       ; copy RegSet
 | 
						|
    lea     ecx, [rdx + (_BackFromUserCode.SavedCr4End - ASM_PFX(m16Start))]
 | 
						|
    mov     eax, edx                    ; eax <- transition code address
 | 
						|
    and     edx, 0fh
 | 
						|
    shl     eax, 12                     ; segment address in high order 16 bits
 | 
						|
    lea     ax, [rdx + (_BackFromUserCode - ASM_PFX(m16Start))]  ; offset address
 | 
						|
    stosd                               ; [edi] <- return address of user code
 | 
						|
 | 
						|
    sgdt    [rsp + 60h]       ; save GDT stack in argument space
 | 
						|
    movzx   r10, word [rsp + 60h]   ; r10 <- GDT limit
 | 
						|
    lea     r11, [rcx + (ASM_PFX(InternalAsmThunk16) - _BackFromUserCode.SavedCr4End) + 0xf]
 | 
						|
    and     r11, ~0xf            ; r11 <- 16-byte aligned shadowed GDT table in real mode buffer
 | 
						|
 | 
						|
    mov     [rcx + (SavedGdt - _BackFromUserCode.SavedCr4End)], r10w      ; save the limit of shadowed GDT table
 | 
						|
    mov     [rcx + (SavedGdt - _BackFromUserCode.SavedCr4End) + 2], r11  ; save the base address of shadowed GDT table
 | 
						|
 | 
						|
    mov     rsi, [rsp + 62h]  ; rsi <- the original GDT base address
 | 
						|
    xchg    rcx, r10                    ; save rcx to r10 and initialize rcx to be the limit of GDT table
 | 
						|
    inc     rcx                         ; rcx <- the size of memory to copy
 | 
						|
    xchg    rdi, r11                    ; save rdi to r11 and initialize rdi to the base address of shadowed GDT table
 | 
						|
    rep     movsb                       ; perform memory copy to shadow GDT table
 | 
						|
    mov     rcx, r10                    ; restore the orignal rcx before memory copy
 | 
						|
    mov     rdi, r11                    ; restore the original rdi before memory copy
 | 
						|
 | 
						|
    sidt    [rsp + 50h]       ; save IDT stack in argument space
 | 
						|
    mov     rax, cr0
 | 
						|
    mov     [rcx + (_BackFromUserCode.SavedCr0End - 4 - _BackFromUserCode.SavedCr4End)], eax
 | 
						|
    and     eax, 7ffffffeh              ; clear PE, PG bits
 | 
						|
    mov     rbp, cr4
 | 
						|
    mov     [rcx - 4], ebp              ; save CR4 in _BackFromUserCode.SavedCr4End - 4
 | 
						|
    and     ebp, ~30h                ; clear PAE, PSE bits
 | 
						|
    mov     esi, r8d                    ; esi <- 16-bit stack segment
 | 
						|
    push    DATA32
 | 
						|
    pop     rdx                         ; rdx <- 32-bit data segment selector
 | 
						|
    lgdt    [rcx + (_16Gdtr - _BackFromUserCode.SavedCr4End)]
 | 
						|
    mov     ss, edx
 | 
						|
    pushfq
 | 
						|
    lea     edx, [rdx + DATA16 - DATA32]
 | 
						|
    lea     r8, [REL .RetFromRealMode]
 | 
						|
    push    r8
 | 
						|
    mov     r8d, cs
 | 
						|
    mov     [rcx + (_BackFromUserCode.X64JmpEnd - 2 - _BackFromUserCode.SavedCr4End)], r8w
 | 
						|
    mov     [rcx + (_BackFromUserCode.SavedSpEnd - 8 - _BackFromUserCode.SavedCr4End)], rsp
 | 
						|
    jmp     dword far [rcx + (_EntryPoint - _BackFromUserCode.SavedCr4End)]
 | 
						|
.RetFromRealMode:
 | 
						|
    popfq
 | 
						|
    lgdt    [rsp + 60h]       ; restore protected mode GDTR
 | 
						|
    lidt    [rsp + 50h]       ; restore protected mode IDTR
 | 
						|
    lea     eax, [rbp - IA32_REGS.size]
 | 
						|
    pop     gs
 | 
						|
    pop     fs
 | 
						|
    pop     rbx
 | 
						|
    mov     ss, ebx
 | 
						|
    pop     rbx
 | 
						|
    mov     es, ebx
 | 
						|
    pop     rbx
 | 
						|
    mov     ds, ebx
 | 
						|
 | 
						|
    pop     rdi
 | 
						|
    pop     rsi
 | 
						|
    pop     rbx
 | 
						|
    pop     rbp
 | 
						|
 | 
						|
    ret
 |