diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 1d2cbe3f23..d886b91398 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -2817,7 +2817,7 @@ SetUefiImageMemoryAttributes ( IN UINT64 Attributes ); -UINTN +EFI_STATUS EFIAPI CoreBootServices ( IN UINT8 Type, diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c index 689754fb9e..925b5d6eea 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c +++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c @@ -32,35 +32,55 @@ InternalEnterUserImage ( IN UINT16 DataSelector ); -UINTN +typedef struct { + UINTN Argument1; + UINTN Argument2; + UINTN Argument3; +} CORE_STACK; + +typedef struct { + UINTN Rip; + UINTN Arguments[]; +} RING3_STACK; +// +// Stack: +// rsp - User Rsp +// rbp - User Rbp +// rcx - Rip for SYSCALL +// r11 - User data segment selector +// r9 - Argument 3 +// r8 - Argument 2 +// rdx - Argument 1 <- CoreRbp +// +EFI_STATUS EFIAPI CallBootService ( - IN UINT8 Type, - IN UINTN CoreRbp, - IN UINTN UserRsp + IN UINT8 Type, + IN CORE_STACK *CoreRbp, + IN RING3_STACK *UserRsp ) { - UINTN Status; - VOID *Pointer; - VOID * Arg4; - VOID * Arg5; - UINT32 Arg6; - - EFI_GUID *CoreProtocol; - UINT32 MemoryCoreSize; - - // Stack: - // rcx - Rip for SYSCALL - // rdx - Argument 1 - // rbp - User Rbp - // r8 - Argument 2 - // r11 - User data segment selector <- CoreRbp - // rsp - User Rsp - // r9 - Argument 3 + EFI_STATUS Status; + UINT64 Attributes; + VOID *Interface; + EFI_GUID *CoreProtocol; + UINT32 MemoryCoreSize; + EFI_HANDLE Argument4; + EFI_HANDLE Argument5; + UINT32 Argument6; + + gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)UserRsp, &Attributes); + ASSERT ((Attributes & EFI_MEMORY_USER) != 0); + switch (Type) { case SysCallLocateProtocol: + // + // Argument 1: EFI_GUID *Protocol + // Argument 2: VOID *CoreRegistration + // Argument 3: VOID **Interface + // DisableSMAP (); - CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)*((UINTN *)CoreRbp + 3)); + CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)CoreRbp->Argument1); EnableSMAP (); if (CoreProtocol == NULL) { DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n")); @@ -68,10 +88,10 @@ CallBootService ( } Status = gBS->LocateProtocol ( - CoreProtocol, - (VOID *)*((UINTN *)CoreRbp + 1), - &Pointer - ); + CoreProtocol, + (VOID *)CoreRbp->Argument2, + &Interface + ); if (CompareGuid (CoreProtocol, &gEfiDevicePathUtilitiesProtocolGuid)) { MemoryCoreSize = sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL); @@ -79,27 +99,35 @@ CallBootService ( MemoryCoreSize = 0; } - Pointer = AllocateRing3CopyPages (Pointer, MemoryCoreSize); - if (Pointer == NULL) { + Interface = AllocateRing3CopyPages (Interface, MemoryCoreSize); + if (Interface == NULL) { DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n")); FreePool (CoreProtocol); return EFI_OUT_OF_RESOURCES; } DisableSMAP (); - *(UINTN *)(*((UINTN *)CoreRbp - 2)) = (UINTN)Pointer; + *(VOID **)CoreRbp->Argument3 = Interface; EnableSMAP (); FreePool (CoreProtocol); - return (UINTN)Status; + return Status; case SysCallOpenProtocol: + // + // Argument 1: EFI_HANDLE CoreUserHandle + // Argument 2: EFI_GUID *Protocol + // Argument 3: VOID **Interface + // Argument 4: EFI_HANDLE CoreImageHandle + // Argument 5: EFI_HANDLE CoreControllerHandle + // Argument 6: UINT32 Attributes + // DisableSMAP (); - CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)*((UINTN *)CoreRbp + 1)); - Arg4 = (VOID *)*((UINTN *)UserRsp + 5); - Arg5 = (VOID *)*((UINTN *)UserRsp + 6); - Arg6 = (UINT32)*((UINTN *)UserRsp + 7); + CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)CoreRbp->Argument2); + Argument4 = (EFI_HANDLE)UserRsp->Arguments[4]; + Argument5 = (EFI_HANDLE)UserRsp->Arguments[5]; + Argument6 = (UINT32)UserRsp->Arguments[6]; EnableSMAP (); if (CoreProtocol == NULL) { DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n")); @@ -107,13 +135,13 @@ CallBootService ( } Status = gBS->OpenProtocol ( - (VOID *)*((UINTN *)CoreRbp + 3), - CoreProtocol, - &Pointer, - Arg4, - Arg5, - Arg6 - ); + (EFI_HANDLE)CoreRbp->Argument1, + CoreProtocol, + &Interface, + Argument4, + Argument5, + Argument6 + ); if (CompareGuid (CoreProtocol, &gEfiLoadedImageProtocolGuid)) { MemoryCoreSize = sizeof (EFI_LOADED_IMAGE_PROTOCOL); @@ -121,26 +149,26 @@ CallBootService ( MemoryCoreSize = 0; } - Pointer = AllocateRing3CopyPages (Pointer, MemoryCoreSize); - if (Pointer == NULL) { + Interface = AllocateRing3CopyPages (Interface, MemoryCoreSize); + if (Interface == NULL) { DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n")); FreePool (CoreProtocol); return EFI_OUT_OF_RESOURCES; } DisableSMAP (); - *(UINTN *)(*((UINTN *)CoreRbp - 2)) = (UINTN)Pointer; + *(VOID **)CoreRbp->Argument3 = Interface; EnableSMAP (); FreePool (CoreProtocol); - return (UINTN)Status; + return Status; default: break; } - return 0; + return EFI_UNSUPPORTED; } VOID diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm index 3eb32b75bd..34d21a02e7 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm @@ -11,34 +11,6 @@ SECTION .text extern ASM_PFX(CallBootService) extern ASM_PFX(gCoreSysCallStackTop) -%macro CallSysRet 0 - ; Prepare SYSRET arguments. - mov rcx, [rbp + 8*4] - pop rdx - 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 @@ -58,7 +30,7 @@ ASM_PFX(EnableSMAP): ret ;------------------------------------------------------------------------------ -; UINTN +; EFI_STATUS ; EFIAPI ; CoreBootServices ( ; IN UINT8 Type, @@ -71,7 +43,8 @@ ASM_PFX(EnableSMAP): ; (r9) Argument 3 of the called function. ; (r10) Type. ; (r11) RFLAGS saved by SYSCALL in SysCall(). -;On stack Argument 4, 5, ... +; +; (On User Stack) Argument 4, 5, ... ;------------------------------------------------------------------------------ global ASM_PFX(CoreBootServices) ASM_PFX(CoreBootServices): @@ -87,32 +60,50 @@ 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], rcx - mov rcx, r10 - sub rax, 8 - mov [rax], rdx sub rax, 8 - mov [rax], rbp - sub rax, 8 - mov [rax], r8 - ; Save User data segment selector on Core SysCall Stack. - sub rax, 8 - mov [rax], r11 - - mov r8, rsp - + mov [rax], rsp mov rsp, rax - + push rbp + ; Save return address for SYSRET. + push rcx + ; Save User data segment selector. + push r11 + ; Save User Arguments [1..3]. + push r9 + push r8 + push rdx mov rbp, rsp + + ; Prepare CallBootService arguments. + mov rcx, r10 mov rdx, rbp - push r8 - push r9 + mov r8, [rbp + 8*6] call ASM_PFX(CallBootService) - CallSysRet + ; Step over Arguments [1..3]. + add rsp, 8*3 + + ; 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 + + ; Prepare SYSRET arguments. + pop rcx + pushfq + pop r11 + + ; Switch to User Stack. + pop rbp + pop rsp + + ; 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. ;------------------------------------------------------------------------------ ; Routine Description: diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h index 66e566f751..2713748f40 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h @@ -5,7 +5,7 @@ **/ -UINTN +EFI_STATUS EFIAPI SysCall ( IN UINT8 Type, diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c index 4c336e1a29..24b87c3f91 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c @@ -441,15 +441,15 @@ Ring3OpenProtocol ( EFI_LOADED_IMAGE_PROTOCOL *UserProtocol; - Status = (EFI_STATUS)SysCall ( - SysCallOpenProtocol, - CoreUserHandle, - Protocol, - Interface, - CoreImageHandle, - CoreControllerHandle, - Attributes - ); + Status = SysCall ( + SysCallOpenProtocol, + CoreUserHandle, + Protocol, + Interface, + CoreImageHandle, + CoreControllerHandle, + Attributes + ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ring3: Failed to open protocol %g\n", Protocol)); return Status; @@ -528,12 +528,12 @@ Ring3LocateProtocol ( EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol; - Status = (EFI_STATUS)SysCall ( - SysCallLocateProtocol, - Protocol, - CoreRegistration, - Interface - ); + Status = SysCall ( + SysCallLocateProtocol, + Protocol, + CoreRegistration, + Interface + ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Ring3: Failed to loacate protocol %g\n", Protocol)); return Status; diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm b/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm index f6ea57d787..742063ce72 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm @@ -7,7 +7,7 @@ SECTION .text ;------------------------------------------------------------------------------ -; UINTN +; EFI_STATUS ; EFIAPI ; SysCall ( ; IN UINT8 Type,