diff --git a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm index 21112847a4..9b25802690 100644 --- a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm +++ b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -98,6 +98,7 @@ ASM_PFX(InternalEnterUserImage): ; SysCallAllocateRing3Pages = 1, ; SysCallAllocateCoreCopy = 2, ; SysCallLocateProtocol = 3, +; SysCallOpenProtocol = 4, ; SysCallMax ; } SYS_CALL_TYPE; ;------------------------------------------------------------------------------ @@ -106,6 +107,7 @@ ASM_PFX(InternalEnterUserImage): %define ALLOCATE_RING3_PAGES 1 %define ALLOCATE_CORE_COPY 2 %define LOCATE_PROTOCOL 3 +%define OPEN_PROTOCOL 4 %macro CallSysRet 0 ; Prepare SYSRET arguments. @@ -135,17 +137,17 @@ o64 sysret %macro DisableSMAP 0 pushfq - pop rcx - or rcx, 0x40000 ; Set AC (bit 18) - push rcx + pop r10 + or r10, 0x40000 ; Set AC (bit 18) + push r10 popfq %endmacro %macro EnableSMAP 0 pushfq - pop rcx - and rcx, ~0x40000 ; Clear AC (bit 18) - push rcx + pop r10 + and r10, ~0x40000 ; Clear AC (bit 18) + push r10 popfq %endmacro @@ -208,6 +210,9 @@ ASM_PFX(CoreBootServices): cmp r10, LOCATE_PROTOCOL je locateProtocol + cmp r10, OPEN_PROTOCOL + je openProtocol + ;------------------------------------------------------------------------------ ; UINTN ; ReadMemory ( @@ -228,7 +233,7 @@ allocateRing3Pages: ; Save User (VOID **)Memory on Core SysCall Stack. push r9 - ; Replace argument according to UEFI calling convention. + ; Replace arguments according to UEFI calling convention. mov rcx, r8 ; Allocate space for (VOID *)Memory on Core SysCall Stack. sub rsp, 8 @@ -257,7 +262,7 @@ allocateRing3Pages: allocateCoreCopy: DisableSMAP - ; Replace argument according to UEFI calling convention. + ; Replace arguments according to UEFI calling convention. mov rcx, r8 mov rdx, r9 @@ -276,7 +281,7 @@ allocateCoreCopy: ; OUT VOID **Interface ; ); locateProtocol: - ; Replace argument according to UEFI calling convention. + ; Replace arguments according to UEFI calling convention. mov rcx, r8 mov rdx, r9 ; Allocate space for (VOID *)Interface on Core SysCall Stack. @@ -291,7 +296,55 @@ locateProtocol: ; Copy (VOID *)Interface from Core SysCall Stack to User Stack. pop rcx mov rdx, [rbp + 8] ; rdx = User rsp - mov [rdx + 8*4], rcx ; 5th argument of SysCall (SysCallLocateProtocol) + 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 diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h index f0b64ae0c9..4f14ead758 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h @@ -10,6 +10,7 @@ typedef enum { SysCallAllocateRing3Pages = 1, SysCallAllocateCoreCopy = 2, SysCallLocateProtocol = 3, + SysCallOpenProtocol = 4, SysCallMax } SYS_CALL_TYPE; diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c index 5995ad4870..d62d8d50ef 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c @@ -12,6 +12,7 @@ #include #include +#include #include "Ring3.h" @@ -73,6 +74,7 @@ EFI_BOOT_SERVICES *gBS = &mBootServices; EFI_BOOT_SERVICES *mCoreBS = NULL; EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mCoreDevicePathUtilitiesProtocol = NULL; +EFI_LOADED_IMAGE_PROTOCOL *mCoreLoadedImageProtocol = NULL; /** The function constructs Ring 3 wrappers for the EFI_BOOT_SERVICES. @@ -441,14 +443,82 @@ Ring3DisconnectController ( EFI_STATUS EFIAPI Ring3OpenProtocol ( - IN EFI_HANDLE UserHandle, + IN EFI_HANDLE CoreUserHandle, IN EFI_GUID *Protocol, OUT VOID **Interface OPTIONAL, - IN EFI_HANDLE ImageHandle, - IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE CoreImageHandle, + IN EFI_HANDLE CoreControllerHandle, IN UINT32 Attributes ) { + EFI_STATUS Status; + EFI_GUID *CoreProtocol; + + EFI_LOADED_IMAGE_PROTOCOL *UserProtocol; + + CoreProtocol = (VOID *)SysCall ( + SysCallAllocateCoreCopy, + (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, AllocateCoreCopy), + sizeof (EFI_GUID), + Protocol + ); + if (CoreProtocol == NULL) { + DEBUG ((DEBUG_ERROR, "Ring3: Failed to allocate core copy of the Protocol variable.\n")); + return EFI_OUT_OF_RESOURCES; + } + + Status = (EFI_STATUS)SysCall ( + SysCallOpenProtocol, + (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, OpenProtocol), + CoreUserHandle, + CoreProtocol, + Interface, + CoreImageHandle, + CoreControllerHandle, + Attributes + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Ring3: Failed to open protocol %g\n", Protocol)); + return Status; + } + + // TODO: FreePool (CoreProtocol); + + if (CompareGuid (Protocol, &gEfiLoadedImageProtocolGuid)) { + mCoreLoadedImageProtocol = (EFI_LOADED_IMAGE_PROTOCOL *)*Interface; + + Status = (EFI_STATUS)SysCall ( + SysCallAllocateRing3Pages, + (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, AllocateRing3Pages), + EFI_SIZE_TO_PAGES (sizeof (EFI_LOADED_IMAGE_PROTOCOL)), + (VOID **)&UserProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Ring3: Failed to allocate pages for Ring3 EFI_LOADED_IMAGE_PROTOCOL structure.\n")); + return Status; + } + + // TODO: Copy Core Interface fields with AllocateRing3Pages(). + + UserProtocol->Revision = 0; + UserProtocol->ParentHandle = NULL; + UserProtocol->SystemTable = NULL; + UserProtocol->DeviceHandle = NULL; + UserProtocol->FilePath = NULL; + UserProtocol->Reserved = 0; + UserProtocol->LoadOptionsSize = 0; + UserProtocol->LoadOptions = NULL; + UserProtocol->ImageBase = NULL; + UserProtocol->ImageSize = 0; + UserProtocol->ImageCodeType = 0; + UserProtocol->ImageDataType = 0; + UserProtocol->Unload = NULL; + + *Interface = UserProtocol; + + return Status; + } + return EFI_UNSUPPORTED; } @@ -536,6 +606,8 @@ Ring3LocateProtocol ( return Status; } + // TODO: FreePool (CoreProtocol); + if (CompareGuid (Protocol, &gEfiDevicePathUtilitiesProtocolGuid)) { mCoreDevicePathUtilitiesProtocol = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *)*Interface; @@ -546,7 +618,7 @@ Ring3LocateProtocol ( (VOID **)&UserProtocol ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Ring3: Failed to allocate pages for Ring3\n")); + DEBUG ((DEBUG_ERROR, "Ring3: Failed to allocate pages for Ring3 EFI_DEVICE_PATH_UTILITIES_PROTOCOL structure.\n")); return Status; } @@ -564,7 +636,7 @@ Ring3LocateProtocol ( return Status; } - return Status; + return EFI_UNSUPPORTED; } EFI_STATUS