MdePkg BaseLib NASM Thunk16: Use bits 16 for 16-bit code
By using 'bits 16', we can write code for 16-bit use the actual assembly syntax rather than 'DB' and sometimes writing code with seemingly incorrect operands because we know it will run correctly when the processor is running in 16-bit mode. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16023 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
a8458d6cb3
commit
f6888eea46
@ -82,23 +82,24 @@ _BackFromUserCode:
|
|||||||
; in IA32_REGS structure. This facilitates wrapper function to extract them
|
; in IA32_REGS structure. This facilitates wrapper function to extract them
|
||||||
; into that structure.
|
; into that structure.
|
||||||
;
|
;
|
||||||
|
BITS 16
|
||||||
push ss
|
push ss
|
||||||
push cs
|
push cs
|
||||||
DB 66h
|
o32 call dword .Base ; push eip
|
||||||
call .Base ; push eip
|
|
||||||
.Base:
|
.Base:
|
||||||
pushfw ; pushfd actually
|
pushfd
|
||||||
cli ; disable interrupts
|
cli ; disable interrupts
|
||||||
push gs
|
push gs
|
||||||
push fs
|
push fs
|
||||||
push es
|
push es
|
||||||
push ds
|
push ds
|
||||||
pushaw ; pushad actually
|
pushad
|
||||||
DB 66h, 0bah ; mov edx, imm32
|
DB 66h, 0bah ; mov edx, imm32
|
||||||
.ThunkAttr: dd 0
|
.ThunkAttr: dd 0
|
||||||
test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
|
test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
|
||||||
jz .1
|
jz .1
|
||||||
mov eax, 15cd2401h ; mov ax, 2401h & int 15h
|
mov ax, 2401h
|
||||||
|
int 15h
|
||||||
cli ; disable interrupts
|
cli ; disable interrupts
|
||||||
jnc .2
|
jnc .2
|
||||||
.1:
|
.1:
|
||||||
@ -108,24 +109,17 @@ _BackFromUserCode:
|
|||||||
or al, 2
|
or al, 2
|
||||||
out 92h, al ; deactivate A20M#
|
out 92h, al ; deactivate A20M#
|
||||||
.2:
|
.2:
|
||||||
xor ax, ax ; xor eax, eax
|
xor eax, eax
|
||||||
mov eax, ss ; mov ax, ss
|
mov ax, ss
|
||||||
DB 67h
|
lea ebp, [esp + IA32_REGS.size]
|
||||||
lea bp, [esp + IA32_REGS.size]
|
mov [bp - IA32_REGS.size + IA32_REGS._ESP], ebp
|
||||||
;
|
mov bx, [bp - IA32_REGS.size + IA32_REGS._EIP]
|
||||||
; esi's in the following 2 instructions are indeed bp in 16-bit code. Fact
|
shl eax, 4 ; shl eax, 4
|
||||||
; is "esi" in 32-bit addressing mode has the same encoding of "bp" in 16-
|
add ebp, eax ; add ebp, eax
|
||||||
; bit addressing mode.
|
|
||||||
;
|
|
||||||
mov [esi - IA32_REGS.size + IA32_REGS._ESP], bp
|
|
||||||
mov ebx, [esi - IA32_REGS.size + IA32_REGS._EIP]
|
|
||||||
shl ax, 4 ; shl eax, 4
|
|
||||||
add bp, ax ; add ebp, eax
|
|
||||||
DB 66h, 0b8h ; mov eax, imm32
|
DB 66h, 0b8h ; mov eax, imm32
|
||||||
.SavedCr4: DD 0
|
.SavedCr4: DD 0
|
||||||
mov cr4, eax
|
mov cr4, eax
|
||||||
DB 66h
|
o32 lgdt [cs:bx + (SavedGdt - .Base)]
|
||||||
lgdt [cs:edi + (SavedGdt - .Base)]
|
|
||||||
DB 66h, 0b8h ; mov eax, imm32
|
DB 66h, 0b8h ; mov eax, imm32
|
||||||
.SavedCr0: DD 0
|
.SavedCr0: DD 0
|
||||||
mov cr0, eax
|
mov cr0, eax
|
||||||
@ -134,8 +128,7 @@ _BackFromUserCode:
|
|||||||
mov ss, eax
|
mov ss, eax
|
||||||
DB 66h, 0bch ; mov esp, imm32
|
DB 66h, 0bch ; mov esp, imm32
|
||||||
.SavedEsp DD 0
|
.SavedEsp DD 0
|
||||||
DB 66h
|
o32 retf ; return to protected mode
|
||||||
retf ; return to protected mode
|
|
||||||
|
|
||||||
_EntryPoint:
|
_EntryPoint:
|
||||||
DD _ToUserCode - ASM_PFX(m16Start)
|
DD _ToUserCode - ASM_PFX(m16Start)
|
||||||
@ -153,45 +146,34 @@ _16GdtrBase:
|
|||||||
; It will be shadowed to somewhere in memory below 1MB.
|
; It will be shadowed to somewhere in memory below 1MB.
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
_ToUserCode:
|
_ToUserCode:
|
||||||
mov edx, ss
|
BITS 16
|
||||||
mov ss, ecx ; set new segment selectors
|
mov dx, ss
|
||||||
mov ds, ecx
|
mov ss, cx ; set new segment selectors
|
||||||
mov es, ecx
|
mov ds, cx
|
||||||
mov fs, ecx
|
mov es, cx
|
||||||
mov gs, ecx
|
mov fs, cx
|
||||||
|
mov gs, cx
|
||||||
mov cr0, eax ; real mode starts at next instruction
|
mov cr0, eax ; real mode starts at next instruction
|
||||||
; which (per SDM) *must* be a far JMP.
|
; which (per SDM) *must* be a far JMP.
|
||||||
DB 0eah
|
DB 0eah
|
||||||
.RealAddr: DW 0, 0
|
.RealAddr: DW 0, 0
|
||||||
|
|
||||||
mov cr4, ebp
|
mov cr4, ebp
|
||||||
mov ss, esi ; set up 16-bit stack segment
|
mov ss, si ; set up 16-bit stack segment
|
||||||
xchg sp, bx ; set up 16-bit stack pointer
|
xchg esp, ebx ; set up 16-bit stack pointer
|
||||||
|
mov bp, [esp + IA32_REGS.size]
|
||||||
|
mov [cs:bp + (_BackFromUserCode.SavedSs - _BackFromUserCode)], dx
|
||||||
|
mov [cs:bp + (_BackFromUserCode.SavedEsp - _BackFromUserCode)], ebx
|
||||||
|
lidt [cs:bp + (_16Idtr - _BackFromUserCode)]
|
||||||
|
|
||||||
; mov bp, [esp + sizeof(IA32_REGS)
|
popad
|
||||||
DB 67h
|
|
||||||
mov ebp, [esp + IA32_REGS.size] ; BackFromUserCode address from stack
|
|
||||||
|
|
||||||
; mov cs:[bp + (_BackFromUserCode.SavedSs - _BackFromUserCode)], dx
|
|
||||||
mov [cs:esi + (_BackFromUserCode.SavedSs - _BackFromUserCode)], edx
|
|
||||||
|
|
||||||
; mov cs:[bp + (_BackFromUserCode.SavedEsp - _BackFromUserCode)], ebx
|
|
||||||
DB 2eh, 66h, 89h, 9eh
|
|
||||||
DW _BackFromUserCode.SavedEsp - _BackFromUserCode
|
|
||||||
|
|
||||||
; lidt cs:[bp + (_16Idtr - _BackFromUserCode)]
|
|
||||||
DB 2eh, 66h, 0fh, 01h, 9eh
|
|
||||||
DW _16Idtr - _BackFromUserCode
|
|
||||||
|
|
||||||
popaw ; popad actually
|
|
||||||
pop ds
|
pop ds
|
||||||
pop es
|
pop es
|
||||||
pop fs
|
pop fs
|
||||||
pop gs
|
pop gs
|
||||||
popfw ; popfd
|
popfd
|
||||||
|
|
||||||
DB 66h ; Use 32-bit addressing for "retf" below
|
o32 retf ; transfer control to user code
|
||||||
retf ; transfer control to user code
|
|
||||||
|
|
||||||
ALIGN 16
|
ALIGN 16
|
||||||
_NullSegDesc DQ 0
|
_NullSegDesc DQ 0
|
||||||
@ -221,6 +203,7 @@ GdtEnd:
|
|||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
global ASM_PFX(InternalAsmThunk16)
|
global ASM_PFX(InternalAsmThunk16)
|
||||||
ASM_PFX(InternalAsmThunk16):
|
ASM_PFX(InternalAsmThunk16):
|
||||||
|
BITS 32
|
||||||
push ebp
|
push ebp
|
||||||
push ebx
|
push ebx
|
||||||
push esi
|
push esi
|
||||||
|
@ -80,28 +80,25 @@ _BackFromUserCode:
|
|||||||
; in IA32_REGS structure. This facilitates wrapper function to extract them
|
; in IA32_REGS structure. This facilitates wrapper function to extract them
|
||||||
; into that structure.
|
; into that structure.
|
||||||
;
|
;
|
||||||
; Some instructions for manipulation of segment registers have to be written
|
BITS 16
|
||||||
; in opcode since 64-bit MASM prevents accesses to those registers.
|
push ss
|
||||||
;
|
push cs
|
||||||
DB 16h ; push ss
|
o32 call dword .Base ; push eip
|
||||||
DB 0eh ; push cs
|
|
||||||
DB 66h
|
|
||||||
call .Base ; push eip
|
|
||||||
.Base:
|
.Base:
|
||||||
DB 66h
|
push dword 0 ; reserved high order 32 bits of EFlags
|
||||||
push 0 ; reserved high order 32 bits of EFlags
|
pushfd
|
||||||
pushfw ; pushfd actually
|
|
||||||
cli ; disable interrupts
|
cli ; disable interrupts
|
||||||
push gs
|
push gs
|
||||||
push fs
|
push fs
|
||||||
DB 6 ; push es
|
push es
|
||||||
DB 1eh ; push ds
|
push ds
|
||||||
DB 66h, 60h ; pushad
|
pushad
|
||||||
DB 66h, 0bah ; mov edx, imm32
|
DB 66h, 0bah ; mov edx, imm32
|
||||||
.ThunkAttr: dd 0
|
.ThunkAttr: dd 0
|
||||||
test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
|
test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
|
||||||
jz .1
|
jz .1
|
||||||
mov eax, 15cd2401h ; mov ax, 2401h & int 15h
|
mov ax, 2401h
|
||||||
|
int 15h
|
||||||
cli ; disable interrupts
|
cli ; disable interrupts
|
||||||
jnc .2
|
jnc .2
|
||||||
.1:
|
.1:
|
||||||
@ -111,43 +108,34 @@ _BackFromUserCode:
|
|||||||
or al, 2
|
or al, 2
|
||||||
out 92h, al ; deactivate A20M#
|
out 92h, al ; deactivate A20M#
|
||||||
.2:
|
.2:
|
||||||
xor ax, ax ; xor eax, eax
|
xor eax, eax
|
||||||
mov eax, ss ; mov ax, ss
|
mov ax, ss
|
||||||
lea bp, [esp + IA32_REGS.size]
|
lea ebp, [esp + IA32_REGS.size]
|
||||||
;
|
mov [bp - IA32_REGS.size + IA32_REGS._ESP], ebp
|
||||||
; rsi in the following 2 instructions is indeed bp in 16-bit code
|
mov ebx, [bp - IA32_REGS.size + IA32_REGS._EIP]
|
||||||
;
|
shl eax, 4 ; shl eax, 4
|
||||||
mov [rsi - IA32_REGS.size + IA32_REGS._ESP], bp
|
add ebp, eax ; add ebp, eax
|
||||||
DB 66h
|
mov eax, cs
|
||||||
mov ebx, [rsi - IA32_REGS.size + IA32_REGS._EIP]
|
shl eax, 4
|
||||||
shl ax, 4 ; shl eax, 4
|
lea eax, [eax + ebx + (.64BitCode - .Base)]
|
||||||
add bp, ax ; add ebp, eax
|
mov [cs:bx + (.64Eip - .Base)], eax
|
||||||
mov ax, cs
|
|
||||||
shl ax, 4
|
|
||||||
lea ax, [eax + ebx + (.64BitCode - .Base)]
|
|
||||||
DB 66h, 2eh, 89h, 87h ; mov cs:[bx + (.64Eip - .Base)], eax
|
|
||||||
DW .64Eip - .Base
|
|
||||||
DB 66h, 0b8h ; mov eax, imm32
|
DB 66h, 0b8h ; mov eax, imm32
|
||||||
.SavedCr4: DD 0
|
.SavedCr4: DD 0
|
||||||
mov cr4, rax
|
mov cr4, eax
|
||||||
;
|
o32 lgdt [cs:bx + (SavedGdt - .Base)]
|
||||||
; rdi in the instruction below is indeed bx in 16-bit code
|
|
||||||
;
|
|
||||||
DB 66h, 2eh ; 2eh is "cs:" segment override
|
|
||||||
lgdt [rdi + (SavedGdt - .Base)]
|
|
||||||
DB 66h
|
|
||||||
mov ecx, 0c0000080h
|
mov ecx, 0c0000080h
|
||||||
rdmsr
|
rdmsr
|
||||||
or ah, 1
|
or ah, 1
|
||||||
wrmsr
|
wrmsr
|
||||||
DB 66h, 0b8h ; mov eax, imm32
|
DB 66h, 0b8h ; mov eax, imm32
|
||||||
.SavedCr0: DD 0
|
.SavedCr0: DD 0
|
||||||
mov cr0, rax
|
mov cr0, eax
|
||||||
DB 66h, 0eah ; jmp far cs:.64Bit
|
DB 66h, 0eah ; jmp far cs:.64Bit
|
||||||
.64Eip: DD 0
|
.64Eip: DD 0
|
||||||
.SavedCs: DW 0
|
.SavedCs: DW 0
|
||||||
.64BitCode:
|
.64BitCode:
|
||||||
db 090h
|
BITS 64
|
||||||
|
nop
|
||||||
db 048h, 0bch ; mov rsp, imm64
|
db 048h, 0bch ; mov rsp, imm64
|
||||||
.SavedSp: DQ 0 ; restore stack
|
.SavedSp: DQ 0 ; restore stack
|
||||||
nop
|
nop
|
||||||
@ -169,40 +157,40 @@ _16Idtr:
|
|||||||
; It will be shadowed to somewhere in memory below 1MB.
|
; It will be shadowed to somewhere in memory below 1MB.
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
_ToUserCode:
|
_ToUserCode:
|
||||||
mov ss, edx ; set new segment selectors
|
BITS 16
|
||||||
mov ds, edx
|
mov ss, dx ; set new segment selectors
|
||||||
mov es, edx
|
mov ds, dx
|
||||||
mov fs, edx
|
mov es, dx
|
||||||
mov gs, edx
|
mov fs, dx
|
||||||
DB 66h
|
mov gs, dx
|
||||||
mov ecx, 0c0000080h
|
mov ecx, 0c0000080h
|
||||||
mov cr0, rax ; real mode starts at next instruction
|
mov cr0, eax ; real mode starts at next instruction
|
||||||
rdmsr
|
rdmsr
|
||||||
and ah, ~1
|
and ah, ~1
|
||||||
wrmsr
|
wrmsr
|
||||||
mov cr4, rbp
|
mov cr4, ebp
|
||||||
mov ss, esi ; set up 16-bit stack segment
|
mov ss, si ; set up 16-bit stack segment
|
||||||
mov sp, bx ; set up 16-bit stack pointer
|
mov esp, ebx ; set up 16-bit stack pointer
|
||||||
DB 66h ; make the following call 32-bit
|
call dword .Base ; push eip
|
||||||
call .Base ; push eip
|
|
||||||
.Base:
|
.Base:
|
||||||
pop bp ; ebp <- address of .Base
|
pop ebp ; ebp <- address of .Base
|
||||||
push qword [esp + IA32_REGS.size + 2]
|
push word [dword esp + IA32_REGS.size + 2]
|
||||||
lea eax, [rsi + (.RealMode - .Base)] ; rsi is "bp" in 16-bit code
|
lea ax, [bp + (.RealMode - .Base)]
|
||||||
push rax
|
push ax
|
||||||
retf ; execution begins at next instruction
|
retf ; execution begins at next instruction
|
||||||
.RealMode:
|
.RealMode:
|
||||||
DB 66h, 2eh ; CS and operand size override
|
|
||||||
lidt [rsi + (_16Idtr - .Base)]
|
o32 lidt [cs:bp + (_16Idtr - .Base)]
|
||||||
DB 66h, 61h ; popad
|
|
||||||
DB 1fh ; pop ds
|
popad
|
||||||
DB 07h ; pop es
|
pop ds
|
||||||
|
pop es
|
||||||
pop fs
|
pop fs
|
||||||
pop gs
|
pop gs
|
||||||
popfw ; popfd
|
popfd
|
||||||
lea sp, [esp + 4] ; skip high order 32 bits of EFlags
|
lea esp, [esp + 4] ; skip high order 32 bits of EFlags
|
||||||
DB 66h ; make the following retf 32-bit
|
|
||||||
retf ; transfer control to user code
|
o32 retf ; transfer control to user code
|
||||||
|
|
||||||
ALIGN 8
|
ALIGN 8
|
||||||
|
|
||||||
@ -245,6 +233,7 @@ GDT_SIZE equ $ - _NullSeg
|
|||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
global ASM_PFX(InternalAsmThunk16)
|
global ASM_PFX(InternalAsmThunk16)
|
||||||
ASM_PFX(InternalAsmThunk16):
|
ASM_PFX(InternalAsmThunk16):
|
||||||
|
BITS 64
|
||||||
push rbp
|
push rbp
|
||||||
push rbx
|
push rbx
|
||||||
push rsi
|
push rsi
|
||||||
@ -300,7 +289,7 @@ ASM_PFX(InternalAsmThunk16):
|
|||||||
mov [rcx], ebp ; save CR4 in _BackFromUserCode.SavedCr4
|
mov [rcx], ebp ; save CR4 in _BackFromUserCode.SavedCr4
|
||||||
and ebp, ~30h ; clear PAE, PSE bits
|
and ebp, ~30h ; clear PAE, PSE bits
|
||||||
mov esi, r8d ; esi <- 16-bit stack segment
|
mov esi, r8d ; esi <- 16-bit stack segment
|
||||||
DB 6ah, DATA32 ; push DATA32
|
push DATA32
|
||||||
pop rdx ; rdx <- 32-bit data segment selector
|
pop rdx ; rdx <- 32-bit data segment selector
|
||||||
lgdt [rcx + (_16Gdtr - _BackFromUserCode.SavedCr4)]
|
lgdt [rcx + (_16Gdtr - _BackFromUserCode.SavedCr4)]
|
||||||
mov ss, edx
|
mov ss, edx
|
||||||
|
Loading…
x
Reference in New Issue
Block a user