diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h b/MdePkg/Library/BaseLib/BaseLibInternals.h index 340ad96284..93a3ffaa3b 100644 --- a/MdePkg/Library/BaseLib/BaseLibInternals.h +++ b/MdePkg/Library/BaseLib/BaseLibInternals.h @@ -343,6 +343,60 @@ InternalEnterUserImage ( 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 14ad7cd4bf..df3d249717 100644 --- a/MdePkg/Library/BaseLib/SwitchStack.c +++ b/MdePkg/Library/BaseLib/SwitchStack.c @@ -90,3 +90,91 @@ EnterUserImage ( 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 9b25802690..eb29524c82 100644 --- a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm +++ b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -16,6 +16,8 @@ DEFAULT REL SECTION .text +extern ASM_PFX(CallBootService) + ;------------------------------------------------------------------------------ ; Routine Description: ; @@ -92,26 +94,10 @@ ASM_PFX(InternalEnterUserImage): ; Pass control to user image retfq -;------------------------------------------------------------------------------ -; typedef enum { -; SysCallReadMemory = 0, -; SysCallAllocateRing3Pages = 1, -; SysCallAllocateCoreCopy = 2, -; SysCallLocateProtocol = 3, -; SysCallOpenProtocol = 4, -; SysCallMax -; } SYS_CALL_TYPE; -;------------------------------------------------------------------------------ - -%define READ_MEMORY 0 -%define ALLOCATE_RING3_PAGES 1 -%define ALLOCATE_CORE_COPY 2 -%define LOCATE_PROTOCOL 3 -%define OPEN_PROTOCOL 4 - %macro CallSysRet 0 ; Prepare SYSRET arguments. - pop rcx + mov rcx, [rbp + 8*4] + pop rdx ; Switch from Core to User data segment selectors. pop r11 @@ -127,7 +113,7 @@ o16 mov gs, r11 ; Switch to User Stack. pop rbp - pop rdx + pop rbp mov rsp, rdx ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. @@ -135,21 +121,23 @@ o64 sysret ; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. %endmacro -%macro DisableSMAP 0 +global ASM_PFX(DisableSMAP) +ASM_PFX(DisableSMAP): pushfq pop r10 or r10, 0x40000 ; Set AC (bit 18) push r10 popfq -%endmacro + ret -%macro EnableSMAP 0 +global ASM_PFX(EnableSMAP) +ASM_PFX(EnableSMAP): pushfq pop r10 and r10, ~0x40000 ; Clear AC (bit 18) push r10 popfq -%endmacro + ret ;------------------------------------------------------------------------------ ; UINTN @@ -182,171 +170,29 @@ ASM_PFX(CoreBootServices): ; 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], rsp + 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 - push rbp mov rbp, rsp - - ; Save User data segment selector on Core SysCall Stack. - push r11 - - ; Save FunctionAddress in R11 as it will be called later. - mov r11, rdx - - ; Save return address for SYSRET. - push rcx - - cmp r10, READ_MEMORY - je readMemory - - cmp r10, ALLOCATE_RING3_PAGES - je allocateRing3Pages - - cmp r10, ALLOCATE_CORE_COPY - je allocateCoreCopy - - cmp r10, LOCATE_PROTOCOL - je locateProtocol - - cmp r10, OPEN_PROTOCOL - je openProtocol - -;------------------------------------------------------------------------------ -; UINTN -; ReadMemory ( -; IN UINTN Address -; ); -readMemory: - mov rax, [rdx] - - CallSysRet - -;------------------------------------------------------------------------------ -; EFI_STATUS -; AllocateRing3Pages ( -; IN UINTN NumberOfPages, -; IN OUT VOID **Memory -; ); -allocateRing3Pages: - ; Save User (VOID **)Memory on Core SysCall Stack. + mov r8, rbp push r9 - ; Replace arguments according to UEFI calling convention. - mov rcx, r8 - ; Allocate space for (VOID *)Memory on Core SysCall Stack. - sub rsp, 8 - mov rdx, rsp - - ; Call Boot Service by FunctionAddress. - call [r11] - - DisableSMAP - - ; Copy (VOID *)Memory from Core SysCall Stack to User Stack. - pop rdx - pop r9 - mov [r9], rdx - - EnableSMAP - - CallSysRet - -;------------------------------------------------------------------------------ -; VOID * -; AllocateCoreCopy ( -; IN UINTN AllocationSize, -; IN CONST VOID *Buffer -; ); -allocateCoreCopy: - DisableSMAP - - ; Replace arguments according to UEFI calling convention. - mov rcx, r8 - mov rdx, r9 - - ; Call Boot Service by FunctionAddress. - call [r11] - - EnableSMAP - - CallSysRet - -;------------------------------------------------------------------------------ -; EFI_STATUS -; LocateProtocol ( -; IN EFI_GUID *Protocol, -; IN VOID *Registration OPTIONAL, -; OUT VOID **Interface -; ); -locateProtocol: - ; Replace arguments according to UEFI calling convention. - mov rcx, r8 - mov rdx, r9 - ; Allocate space for (VOID *)Interface on Core SysCall Stack. - sub rsp, 8 - mov r8, rsp - - ; Call Boot Service by FunctionAddress. - call [r11] - - DisableSMAP - - ; Copy (VOID *)Interface from Core SysCall Stack to User Stack. - pop rcx - mov rdx, [rbp + 8] ; rdx = User rsp - mov [rdx + 8*5], rcx ; 5th argument of SysCall (SysCallLocateProtocol) - - EnableSMAP - - CallSysRet - -;------------------------------------------------------------------------------ -; EFI_STATUS -; OpenProtocol ( -; IN EFI_HANDLE UserHandle, -; IN EFI_GUID *Protocol, -; OUT VOID **Interface OPTIONAL, -; IN EFI_HANDLE ImageHandle, -; IN EFI_HANDLE ControllerHandle, -; IN UINT32 Attributes -; ); -openProtocol: - ; Replace arguments according to UEFI calling convention. - mov rcx, r8 ; UserHandle - mov rdx, r9 ; Protocol - ; Allocate space for (VOID *)Interface on Core SysCall Stack. - sub rsp, 8 - mov r8, rsp ; Interface - - DisableSMAP - - ; Copy ImageHandle, ControllerHandle, Attributes from User Stack to Core SysCall Stack. - mov rax, [rbp + 8] ; rax = User rsp - mov r9, [rax + 8*8] ; Attributes - 8th argument of SysCall (SysCallOpenProtocol) - push r9 - mov r9, [rax + 8*7] ; ControllerHandle - 7th argument of SysCall (SysCallOpenProtocol) - push r9 - mov r9, [rax + 8*6] ; ImageHandle - 6th argument of SysCall (SysCallOpenProtocol) - - EnableSMAP - - ; Step over first 4 arguments, which are passed through registers. - sub rsp, 8*4 - - ; Call Boot Service by FunctionAddress. - call [r11] - - DisableSMAP - - ; Copy (VOID *)Interface from Core SysCall Stack to User Stack. - add rsp, 8*6 - pop rcx - mov rdx, [rbp + 8] ; rdx = User rsp - mov [rdx + 8*5], rcx ; 5th argument of SysCall (SysCallOpenProtocol) - - EnableSMAP + call ASM_PFX(CallBootService) CallSysRet