diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 9205bd4281..f298c90baa 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -2823,4 +2823,23 @@ SetUefiImageMemoryAttributes ( IN UINT64 Attributes ); +UINTN +EFIAPI +CoreBootServices ( + IN UINT8 Type, + IN UINTN FunctionAddress, + ... + ); + +VOID +EFIAPI +EnterUserImage ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1 OPTIONAL, + IN VOID *Context2 OPTIONAL, + IN VOID *NewStack, + IN UINT16 CodeSelector, + IN UINT16 DataSelector + ); + #endif diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 55169a392d..7a6332a79c 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -67,6 +67,10 @@ Dispatcher/Dispatcher.c DxeMain/DxeProtocolNotify.c DxeMain/DxeMain.c + SysCall/BootServices.c + +[Sources.X64] + SysCall/X64/CoreBootServices.nasm [Packages] MdePkg/MdePkg.dec diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index 35bcc6a4da..bcd07124ec 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -27,7 +27,7 @@ STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent; STATIC VOID *mPeCoffEmuProtocolNotifyRegistration; extern BOOLEAN gBdsStarted; -extern VOID *gCoreSysCallStackTop; +VOID *gCoreSysCallStackTop; // // This code is needed to build the Image handle for the DXE Core diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c new file mode 100644 index 0000000000..83afff65d5 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c @@ -0,0 +1,154 @@ +/** @file + + Copyright (c) 2024, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +**/ + +#include +#include +#include +#include +#include + +VOID +EFIAPI +DisableSMAP ( + VOID + ); + +VOID +EFIAPI +EnableSMAP ( + VOID + ); + +VOID +EFIAPI +InternalEnterUserImage ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1 OPTIONAL, + IN VOID *Context2 OPTIONAL, + IN VOID *NewStack, + IN UINT16 CodeSelector, + IN UINT16 DataSelector + ); + +typedef enum { + SysCallReadMemory = 0, + SysCallAllocateRing3Pages = 1, + SysCallAllocateCoreCopy = 2, + SysCallLocateProtocol = 3, + SysCallOpenProtocol = 4, + SysCallMax +} SYS_CALL_TYPE; + +UINTN +EFIAPI +CallBootService ( + IN UINT8 Type, + IN VOID **FunctionAddress, + IN UINTN CoreRbp, + IN UINTN UserRsp + ) +{ + UINTN Status; + VOID *Pointer; + VOID * Arg4; + VOID * Arg5; + UINT32 Arg6; + EFI_ALLOCATE_RING3_PAGES Func1; + EFI_ALLOCATE_CORE_COPY Func2; + EFI_LOCATE_PROTOCOL Func3; + EFI_OPEN_PROTOCOL Func4; + // Stack: + // rcx - Rip for SYSCALL + // r8 - Argument 1 + // rbp - User Rbp + // r9 - Argument 2 + // r11 - User data segment selector <- CoreRbp + // rsp - User Rsp + switch (Type) { + case SysCallReadMemory: + return *(UINTN *)FunctionAddress; + + case SysCallAllocateRing3Pages: + Func1 = (EFI_ALLOCATE_RING3_PAGES)*FunctionAddress; + Status = Func1 ( + *((UINTN *)CoreRbp + 3), + &Pointer + ); + DisableSMAP (); + *(UINTN *)(*((UINTN *)CoreRbp + 1)) = (UINTN)Pointer; + EnableSMAP (); + return (UINTN)Status; + + case SysCallAllocateCoreCopy: + DisableSMAP (); + Func2 = (EFI_ALLOCATE_CORE_COPY)*FunctionAddress; + Status = (UINTN)Func2 ( + *((UINTN *)CoreRbp + 3), + (VOID *)*((UINTN *)CoreRbp + 1) + ); + EnableSMAP (); + return (UINTN)Status; + + case SysCallLocateProtocol: + Func3 = (EFI_LOCATE_PROTOCOL)*FunctionAddress; + Status = Func3 ( + (VOID *)*((UINTN *)CoreRbp + 3), + (VOID *)*((UINTN *)CoreRbp + 1), + &Pointer + ); + DisableSMAP (); + *((UINTN *)UserRsp + 5) = (UINTN)Pointer; + EnableSMAP (); + return (UINTN)Status; + + case SysCallOpenProtocol: + DisableSMAP (); + Arg4 = (VOID *)*((UINTN *)UserRsp + 6); + Arg5 = (VOID *)*((UINTN *)UserRsp + 7); + Arg6 = (UINT32)*((UINTN *)UserRsp + 8); + EnableSMAP (); + Func4 = (EFI_OPEN_PROTOCOL)*FunctionAddress; + Status = Func4 ( + (VOID *)*((UINTN *)CoreRbp + 3), + (VOID *)*((UINTN *)CoreRbp + 1), + &Pointer, + Arg4, + Arg5, + Arg6 + ); + DisableSMAP (); + *((UINTN *)UserRsp + 5) = (UINTN)Pointer; + EnableSMAP (); + return (UINTN)Status; + default: + break; + } + + return 0; +} + +VOID +EFIAPI +EnterUserImage ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1 OPTIONAL, + IN VOID *Context2 OPTIONAL, + IN VOID *NewStack, + IN UINT16 CodeSelector, + IN UINT16 DataSelector + ) +{ + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + + // + // New stack must be aligned with CPU_STACK_ALIGNMENT + // + ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0); + + InternalEnterUserImage (EntryPoint, Context1, Context2, NewStack, CodeSelector, DataSelector); +} diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm new file mode 100644 index 0000000000..421dbcc8da --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm @@ -0,0 +1,161 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2024, Mikhail Krichanov. All rights reserved. +; SPDX-License-Identifier: BSD-3-Clause +; +;------------------------------------------------------------------------------ + +DEFAULT REL +SECTION .text + +extern ASM_PFX(CallBootService) +extern ASM_PFX(gCoreSysCallStackTop) + +%macro CallSysRet 0 + ; Prepare SYSRET arguments. + mov rcx, [rbp + 8*4] + pop rdx + + ; Switch from Core to User data segment selectors. + pop r11 + +o16 mov ds, r11 +o16 mov es, r11 +o16 mov fs, r11 +o16 mov gs, r11 + + ; Restore RFLAGS in R11 for SYSRET. + pushfq + pop r11 + + ; Switch to User Stack. + pop rbp + pop rbp + mov rsp, rdx + + ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. +o64 sysret + ; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. +%endmacro + +global ASM_PFX(DisableSMAP) +ASM_PFX(DisableSMAP): + pushfq + pop r10 + or r10, 0x40000 ; Set AC (bit 18) + push r10 + popfq + ret + +global ASM_PFX(EnableSMAP) +ASM_PFX(EnableSMAP): + pushfq + pop r10 + and r10, ~0x40000 ; Clear AC (bit 18) + push r10 + popfq + ret + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; CoreBootServices ( +; IN UINT8 Type, +; IN UINTN FunctionAddress, +; ... +; ); +; +; (rcx) RIP of the next instruction saved by SYSCALL in SysCall(). +; (rdx) FunctionAddress. +; (r8) Argument 1 of the called function. +; (r9) Argument 2 of the called function. +; (r10) Type. +; (r11) RFLAGS saved by SYSCALL in SysCall(). +;On stack Argument 3, 4, ... +;------------------------------------------------------------------------------ +global ASM_PFX(CoreBootServices) +ASM_PFX(CoreBootServices): + ; Save User data segment selector temporarily in R11. + mov r11, ds + + ; Switch from User to Core data segment selectors. + mov ax, ss + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; Save User Stack pointers and switch to Core SysCall Stack. + mov rax, [ASM_PFX(gCoreSysCallStackTop)] + ; Save return address for SYSRET. + sub rax, 8 + mov [rax], rcx + mov rcx, r10 + sub rax, 8 + mov [rax], r8 + sub rax, 8 + mov [rax], rbp + sub rax, 8 + mov [rax], r9 + ; Save User data segment selector on Core SysCall Stack. + sub rax, 8 + mov [rax], r11 + + mov r9, rsp + + mov rsp, rax + + mov rbp, rsp + mov r8, rbp + push r9 + + call ASM_PFX(CallBootService) + + CallSysRet + +;------------------------------------------------------------------------------ +; Routine Description: +; +; Routine for transfering control to user image with 2 parameters +; +; Arguments: +; +; (rcx) EntryPoint - Entry point with new stack. +; (rdx) Context1 - Parameter1 for entry point. +; (r8) Context2 - Parameter2 for entry point. +; (r9) NewStack - The pointer to new stack. +;On stack CodeSelector - Segment selector for code. +;On stack DataSelector - Segment selector for data. +; +; Returns: +; +; None +; +;------------------------------------------------------------------------------ +global ASM_PFX(InternalEnterUserImage) +ASM_PFX(InternalEnterUserImage): + ; Set Data selectors + mov rax, [rsp + 8*6] + or rax, 3H ; RPL = 3 + + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; Save Code selector + mov r10, [rsp + 8*5] + or r10, 3H ; RPL = 3 + + ; Prepare stack before swithcing + push rax ; ss + push r9 ; rsp + push r10 ; cs + push rcx ; rip + + ; Save 2 parameters + mov rcx, rdx + mov rdx, r8 + + ; Pass control to user image + retfq diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 8d0a7a2407..16c77a57eb 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -5114,17 +5114,6 @@ SwitchStack ( ... ); -VOID -EFIAPI -EnterUserImage ( - IN SWITCH_STACK_ENTRY_POINT EntryPoint, - IN VOID *Context1 OPTIONAL, - IN VOID *Context2 OPTIONAL, - IN VOID *NewStack, - IN UINT16 CodeSelector, - IN UINT16 DataSelector - ); - /** Generates a breakpoint on the CPU. @@ -6596,14 +6585,6 @@ AsmReadEflags ( VOID ); -UINTN -EFIAPI -CoreBootServices ( - IN UINT8 Type, - IN UINTN FunctionAddress, - ... - ); - /** Reads the current value of the Control Register 0 (CR0). diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h b/MdePkg/Library/BaseLib/BaseLibInternals.h index 93a3ffaa3b..d61e604385 100644 --- a/MdePkg/Library/BaseLib/BaseLibInternals.h +++ b/MdePkg/Library/BaseLib/BaseLibInternals.h @@ -332,71 +332,6 @@ InternalSwitchStack ( IN VA_LIST Marker ); -VOID -EFIAPI -InternalEnterUserImage ( - IN SWITCH_STACK_ENTRY_POINT EntryPoint, - IN VOID *Context1 OPTIONAL, - IN VOID *Context2 OPTIONAL, - IN VOID *NewStack, - IN UINT16 CodeSelector, - IN UINT16 DataSelector - ); - -VOID -EFIAPI -DisableSMAP ( - VOID - ); - -VOID -EFIAPI -EnableSMAP ( - VOID - ); - -typedef enum { - SysCallReadMemory = 0, - SysCallAllocateRing3Pages = 1, - SysCallAllocateCoreCopy = 2, - SysCallLocateProtocol = 3, - SysCallOpenProtocol = 4, - SysCallMax -} SYS_CALL_TYPE; - -typedef -UINTN -(EFIAPI *EFI_ALLOCATE_RING3_PAGES)( - IN UINTN Pages, - IN OUT VOID **Memory - ); - -typedef -VOID * -(EFIAPI *EFI_ALLOCATE_CORE_COPY)( - IN UINTN AllocationSize, - IN CONST VOID *Buffer - ); - -typedef -UINTN -(EFIAPI *EFI_LOCATE_PROTOCOL)( - IN VOID *Protocol, - IN VOID *Registration OPTIONAL, - OUT VOID **Interface - ); - -typedef -UINTN -(EFIAPI *EFI_OPEN_PROTOCOL)( - IN VOID * Handle, - IN VOID *Protocol, - OUT VOID **Interface OPTIONAL, - IN VOID * AgentHandle, - IN VOID * ControllerHandle, - IN UINT32 Attributes - ); - /** Worker function that returns a bit field from Operand. diff --git a/MdePkg/Library/BaseLib/SwitchStack.c b/MdePkg/Library/BaseLib/SwitchStack.c index df3d249717..954e863fc1 100644 --- a/MdePkg/Library/BaseLib/SwitchStack.c +++ b/MdePkg/Library/BaseLib/SwitchStack.c @@ -68,113 +68,3 @@ SwitchStack ( // ASSERT (FALSE); } - -VOID -EFIAPI -EnterUserImage ( - IN SWITCH_STACK_ENTRY_POINT EntryPoint, - IN VOID *Context1 OPTIONAL, - IN VOID *Context2 OPTIONAL, - IN VOID *NewStack, - IN UINT16 CodeSelector, - IN UINT16 DataSelector - ) -{ - ASSERT (EntryPoint != NULL); - ASSERT (NewStack != NULL); - - // - // New stack must be aligned with CPU_STACK_ALIGNMENT - // - ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0); - - InternalEnterUserImage (EntryPoint, Context1, Context2, NewStack, CodeSelector, DataSelector); -} - -UINTN -EFIAPI -CallBootService ( - IN UINT8 Type, - IN VOID **FunctionAddress, - IN UINTN CoreRbp, - IN UINTN UserRsp - ) -{ - UINTN Status; - VOID *Pointer; - VOID * Arg4; - VOID * Arg5; - UINT32 Arg6; - EFI_ALLOCATE_RING3_PAGES Func1; - EFI_ALLOCATE_CORE_COPY Func2; - EFI_LOCATE_PROTOCOL Func3; - EFI_OPEN_PROTOCOL Func4; - // Stack: - // rcx - Rip for SYSCALL - // r8 - Argument 1 - // rbp - User Rbp - // r9 - Argument 2 - // r11 - User data segment selector <- CoreRbp - // rsp - User Rsp - switch (Type) { - case SysCallReadMemory: - return *(UINTN *)FunctionAddress; - - case SysCallAllocateRing3Pages: - Func1 = (EFI_ALLOCATE_RING3_PAGES)*FunctionAddress; - Status = Func1 ( - *((UINTN *)CoreRbp + 3), - &Pointer - ); - DisableSMAP (); - *(UINTN *)(*((UINTN *)CoreRbp + 1)) = (UINTN)Pointer; - EnableSMAP (); - return (UINTN)Status; - - case SysCallAllocateCoreCopy: - DisableSMAP (); - Func2 = (EFI_ALLOCATE_CORE_COPY)*FunctionAddress; - Status = (UINTN)Func2 ( - *((UINTN *)CoreRbp + 3), - (VOID *)*((UINTN *)CoreRbp + 1) - ); - EnableSMAP (); - return (UINTN)Status; - - case SysCallLocateProtocol: - Func3 = (EFI_LOCATE_PROTOCOL)*FunctionAddress; - Status = Func3 ( - (VOID *)*((UINTN *)CoreRbp + 3), - (VOID *)*((UINTN *)CoreRbp + 1), - &Pointer - ); - DisableSMAP (); - *((UINTN *)UserRsp + 5) = (UINTN)Pointer; - EnableSMAP (); - return (UINTN)Status; - - case SysCallOpenProtocol: - DisableSMAP (); - Arg4 = (VOID *)*((UINTN *)UserRsp + 6); - Arg5 = (VOID *)*((UINTN *)UserRsp + 7); - Arg6 = (UINT32)*((UINTN *)UserRsp + 8); - EnableSMAP (); - Func4 = (EFI_OPEN_PROTOCOL)*FunctionAddress; - Status = Func4 ( - (VOID *)*((UINTN *)CoreRbp + 3), - (VOID *)*((UINTN *)CoreRbp + 1), - &Pointer, - Arg4, - Arg5, - Arg6 - ); - DisableSMAP (); - *((UINTN *)UserRsp + 5) = (UINTN)Pointer; - EnableSMAP (); - return (UINTN)Status; - default: - break; - } - - return 0; -} diff --git a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm index eb29524c82..81648ccc9f 100644 --- a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm +++ b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -1,6 +1,4 @@ ;------------------------------------------------------------------------------ -; Copyright (c) 2024, Mikhail Krichanov. All rights reserved. -; SPDX-License-Identifier: BSD-3-Clause ; ; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
; SPDX-License-Identifier: BSD-2-Clause-Patent @@ -16,8 +14,6 @@ DEFAULT REL SECTION .text -extern ASM_PFX(CallBootService) - ;------------------------------------------------------------------------------ ; Routine Description: ; @@ -46,158 +42,3 @@ ASM_PFX(InternalSwitchStack): ; lea rsp, [r9 - 0x20] call rax - -;------------------------------------------------------------------------------ -; Routine Description: -; -; Routine for transfering control to user image with 2 parameters -; -; Arguments: -; -; (rcx) EntryPoint - Entry point with new stack. -; (rdx) Context1 - Parameter1 for entry point. -; (r8) Context2 - Parameter2 for entry point. -; (r9) NewStack - The pointer to new stack. -;On stack CodeSelector - Segment selector for code. -;On stack DataSelector - Segment selector for data. -; -; Returns: -; -; None -; -;------------------------------------------------------------------------------ -global ASM_PFX(InternalEnterUserImage) -ASM_PFX(InternalEnterUserImage): - ; Set Data selectors - mov rax, [rsp + 8*6] - or rax, 3H ; RPL = 3 - - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - ; Save Code selector - mov r10, [rsp + 8*5] - or r10, 3H ; RPL = 3 - - ; Prepare stack before swithcing - push rax ; ss - push r9 ; rsp - push r10 ; cs - push rcx ; rip - - ; Save 2 parameters - mov rcx, rdx - mov rdx, r8 - - ; Pass control to user image - retfq - -%macro CallSysRet 0 - ; Prepare SYSRET arguments. - mov rcx, [rbp + 8*4] - pop rdx - - ; Switch from Core to User data segment selectors. - pop r11 - -o16 mov ds, r11 -o16 mov es, r11 -o16 mov fs, r11 -o16 mov gs, r11 - - ; Restore RFLAGS in R11 for SYSRET. - pushfq - pop r11 - - ; Switch to User Stack. - pop rbp - pop rbp - mov rsp, rdx - - ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. -o64 sysret - ; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. -%endmacro - -global ASM_PFX(DisableSMAP) -ASM_PFX(DisableSMAP): - pushfq - pop r10 - or r10, 0x40000 ; Set AC (bit 18) - push r10 - popfq - ret - -global ASM_PFX(EnableSMAP) -ASM_PFX(EnableSMAP): - pushfq - pop r10 - and r10, ~0x40000 ; Clear AC (bit 18) - push r10 - popfq - ret - -;------------------------------------------------------------------------------ -; UINTN -; EFIAPI -; CoreBootServices ( -; IN UINT8 Type, -; IN UINTN FunctionAddress, -; ... -; ); -; -; (rcx) RIP of the next instruction saved by SYSCALL in SysCall(). -; (rdx) FunctionAddress. -; (r8) Argument 1 of the called function. -; (r9) Argument 2 of the called function. -; (r10) Type. -; (r11) RFLAGS saved by SYSCALL in SysCall(). -;On stack Argument 3, 4, ... -;------------------------------------------------------------------------------ -global ASM_PFX(CoreBootServices) -ASM_PFX(CoreBootServices): - ; Save User data segment selector temporarily in R11. - mov r11, ds - - ; Switch from User to Core data segment selectors. - mov ax, ss - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - ; Save User Stack pointers and switch to Core SysCall Stack. - mov rax, [ASM_PFX(gCoreSysCallStackTop)] - ; Save return address for SYSRET. - sub rax, 8 - mov [rax], rcx - mov rcx, r10 - sub rax, 8 - mov [rax], r8 - sub rax, 8 - mov [rax], rbp - sub rax, 8 - mov [rax], r9 - ; Save User data segment selector on Core SysCall Stack. - sub rax, 8 - mov [rax], r11 - - mov r9, rsp - - mov rsp, rax - - mov rbp, rsp - mov r8, rbp - push r9 - - call ASM_PFX(CallBootService) - - CallSysRet - -SECTION .data - -global ASM_PFX(gCoreSysCallStackTop) -ASM_PFX(gCoreSysCallStackTop): - resq 1