X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdePkg%2FLibrary%2FBaseLib%2FX64%2FThunk16.asm;h=642310869b6fe6ec6574f56ed387f054dd9cab03;hp=b3c0769f1f36099c9e703e85fb900575a3296232;hb=733f4094eece02888d5bc8413a9367ea58137133;hpb=a661b6870a40eebda625a410eafb8f93a75aa2ca diff --git a/MdePkg/Library/BaseLib/X64/Thunk16.asm b/MdePkg/Library/BaseLib/X64/Thunk16.asm index b3c0769f1f..642310869b 100644 --- a/MdePkg/Library/BaseLib/X64/Thunk16.asm +++ b/MdePkg/Library/BaseLib/X64/Thunk16.asm @@ -26,9 +26,6 @@ EXTERNDEF m16Gdt:WORD EXTERNDEF m16GdtrBase:WORD EXTERNDEF mTransition:WORD -;THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 EQU 2 -;THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL EQU 4 - IA32_REGS STRUC 4t _EDI DD ? _ESI DD ? @@ -50,20 +47,24 @@ IA32_REGS ENDS .const -m16Size DW offset InternalAsmThunk16 - offset m16Start -mThunk16Attr DW offset _ThunkAttr - offset m16Start -m16Gdt DW offset _NullSegDesc - offset m16Start -m16GdtrBase DW offset _16GdtrBase - offset m16Start -mTransition DW offset _EntryPoint - offset m16Start +m16Size DW InternalAsmThunk16 - m16Start +mThunk16Attr DW _ThunkAttr - m16Start +m16Gdt DW _NullSeg - m16Start +m16GdtrBase DW _16GdtrBase - m16Start +mTransition DW _EntryPoint - m16Start .code m16Start LABEL BYTE -SavedGdt LABEL FWORD - DW ? - DQ ? +SavedGdt LABEL FWORD + DW ? + DQ ? +;------------------------------------------------------------------------------ +; _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 PROC DB 16h ; push ss DB 0eh ; push cs @@ -95,15 +96,27 @@ _ThunkAttr DD ? @2: mov eax, ss lea bp, [esp + sizeof (IA32_REGS)] + ; + ; rsi in the following 2 instructions is indeed bp in 16-bit code + ; mov word ptr (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._ESP, bp + DB 66h mov ebx, (IA32_REGS ptr [rsi - sizeof (IA32_REGS)])._EIP shl ax, 4 ; shl eax, 4 add bp, ax ; add ebp, 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 SavedCr4 DD ? mov cr4, rax + ; + ; rdi in the instruction below is indeed bx in 16-bit code + ; DB 66h, 2eh - lgdt fword ptr [rdi + (offset SavedGdt - offset @Base)] + lgdt fword ptr [rdi + (SavedGdt - @Base)] DB 66h mov ecx, 0c0000080h rdmsr @@ -112,24 +125,27 @@ SavedCr4 DD ? DB 66h, 0b8h ; mov eax, imm32 SavedCr0 DD ? mov cr0, rax - DB 0b8h ; mov ax, imm16 -SavedSs DW ? - mov ss, eax - DB 66h, 0bch ; mov esp, imm32 -SavedEsp DD ? - DB 66h - retf ; return to protected mode + DB 66h, 0eah ; jmp far cs:@64Bit +@64Eip DD ? +SavedCs DW ? +@64BitCode: + DB 48h, 0b8h ; mov rax, imm64 +SavedRip DQ ? + jmp rax ; return to caller _BackFromUserCode ENDP -_EntryPoint DD offset _ToUserCode - offset m16Start - DW 8h -_16Gdtr LABEL FWORD - DW offset GdtEnd - offset _NullSegDesc - 1 -_16GdtrBase DQ offset _NullSegDesc -_16Idtr FWORD (1 SHL 10) - 1 +_EntryPoint DD _ToUserCode - m16Start + DW CODE16 +_16Gdtr LABEL FWORD + DW GDT_SIZE - 1 +_16GdtrBase DQ _NullSeg +_16Idtr FWORD (1 SHL 10) - 1 +;------------------------------------------------------------------------------ +; _ToUserCode() takes control in real mode before passing control to user code. +; It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ _ToUserCode PROC - mov edi, ss mov ss, edx ; set new segment selectors mov ds, edx mov es, edx @@ -143,22 +159,18 @@ _ToUserCode PROC wrmsr mov cr4, rbp mov ss, esi ; set up 16-bit stack segment - xchg sp, bx ; set up 16-bit stack pointer + mov sp, bx ; set up 16-bit stack pointer DB 66h call @Base ; push eip @Base: - pop bp ; ebp <- offset @Base + pop bp ; ebp <- address of @Base push [esp + sizeof (IA32_REGS) + 2] - lea eax, [rsi + (offset @RealMode - offset @Base)] + lea eax, [rsi + (@RealMode - @Base)] push rax retf @RealMode: - DB 2eh ; cs: - mov [rsi + (offset SavedSs - offset @Base)], edi - DB 2eh ; cs: - mov [rsi + (offset SavedEsp - offset @Base)], bx DB 66h, 2eh ; CS and operand size override - lidt fword ptr [rsi + (offset _16Idtr - offset @Base)] + lidt fword ptr [rsi + (_16Idtr - @Base)] DB 66h, 61h ; popad DB 1fh ; pop ds DB 07h ; pop es @@ -170,31 +182,47 @@ _ToUserCode PROC retf ; transfer control to user code _ToUserCode ENDP -_NullSegDesc DQ 0 -_16CsDesc LABEL QWORD - DW -1 - DW 0 - DB 0 - DB 9bh - DB 8fh ; 16-bit segment, 4GB limit - DB 0 -_16DsDesc LABEL QWORD - DW -1 - DW 0 - DB 0 - DB 93h - DB 8fh ; 16-bit segment, 4GB limit - DB 0 -GdtEnd LABEL QWORD +CODE16 = _16Code - $ +DATA16 = _16Data - $ +DATA32 = _32Data - $ -; -; @param RegSet Pointer to a IA32_DWORD_REGS structure -; @param Transition Pointer to the transition code -; @return The address of the 16-bit stack after returning from user code -; +_NullSeg DQ 0 +_16Code LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 9bh + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +_16Data LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 93h + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +_32Data LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 93h + DB 0cfh ; 16-bit segment, 4GB limit + DB 0 + +GDT_SIZE = $ - _NullSeg + +;------------------------------------------------------------------------------ +; IA32_REGISTER_SET * +; EFIAPI +; InternalAsmThunk16 ( +; IN IA32_REGISTER_SET *RegisterSet, +; IN OUT VOID *Transition +; ); +;------------------------------------------------------------------------------ InternalAsmThunk16 PROC USES rbp rbx rsi rdi mov r10d, ds mov r11d, es + mov r9d, ss push fs push gs mov rsi, rcx @@ -202,37 +230,46 @@ InternalAsmThunk16 PROC USES rbp rbx rsi rdi mov edi, (IA32_REGS ptr [rsi])._ESP lea rdi, [edi - (sizeof (IA32_REGS) + 4)] imul eax, r8d, 16 ; eax <- r8d(stack segment) * 16 - mov ebx, edi ; ebx <- stack offset for 16-bit code + mov ebx, edi ; ebx <- stack for 16-bit code push sizeof (IA32_REGS) / 4 add edi, eax ; edi <- linear address of 16-bit stack pop rcx rep movsd ; copy RegSet - lea ecx, [rdx + (offset SavedCr4 - offset m16Start)] + lea ecx, [rdx + (SavedCr4 - m16Start)] mov eax, edx ; eax <- transition code address and edx, 0fh shl eax, 12 - lea edx, [rdx + (offset _BackFromUserCode - offset m16Start)] - mov ax, dx + lea ax, [rdx + (_BackFromUserCode - m16Start)] stosd ; [edi] <- return address of user code - sgdt fword ptr [rcx + (offset SavedGdt - offset SavedCr4)] + sgdt fword ptr [rcx + (SavedGdt - SavedCr4)] sidt fword ptr [rsp + 38h] ; save IDT stack in argument space mov rax, cr0 - mov [rcx + (offset SavedCr0 - offset SavedCr4)], eax + mov [rcx + (SavedCr0 - SavedCr4)], eax and eax, 7ffffffeh ; clear PE, PG bits mov rbp, cr4 mov [rcx], ebp ; save CR4 in SavedCr4 and ebp, 300h ; clear all but PCE and OSFXSR bits mov esi, r8d ; esi <- 16-bit stack segment - push 10h - pop rdx ; rdx <- selector for data segments - lgdt fword ptr [rcx + (offset _16Gdtr - offset SavedCr4)] + DB 6ah, DATA32 ; push DATA32 + pop rdx ; rdx <- 32-bit data segment selector + lgdt fword ptr [rcx + (_16Gdtr - SavedCr4)] + mov ss, edx pushfq - call fword ptr [rcx + (offset _EntryPoint - offset SavedCr4)] + lea edx, [rdx + DATA16 - DATA32] + lea r8, @RetFromRealMode + mov [rcx + (SavedRip - SavedCr4)], r8 + mov r8d, cs + mov [rcx + (SavedCs - SavedCr4)], r8w + mov r8, rsp + jmp fword ptr [rcx + (_EntryPoint - SavedCr4)] +@RetFromRealMode: + mov rsp, r8 popfq lidt fword ptr [rsp + 38h] ; restore protected mode IDTR lea eax, [rbp - sizeof (IA32_REGS)] pop gs pop fs + mov ss, r9d mov es, r11d mov ds, r10d ret