From de01af70819c2b33fba24b26cc81c2239d1690ec Mon Sep 17 00:00:00 2001 From: Mikhail Krichanov Date: Mon, 29 Jan 2024 14:00:43 +0300 Subject: [PATCH] Ring3: Added helper function AllocateCoreCopy(), refactored SysCall. --- MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c | 3 +- MdePkg/Include/Library/BaseLib.h | 1 + MdePkg/Include/Uefi/UefiSpec.h | 8 + MdePkg/Library/BaseLib/X64/SwitchStack.nasm | 180 +++++++++++++++--- .../Ring3UefiBootServicesTableLib/Ring3.h | 10 +- .../Ring3UefiBootServicesTableLib.c | 28 ++- .../X64/SysCall.nasm | 3 +- 7 files changed, 193 insertions(+), 40 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index 77bc48a286..33443914f8 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -90,7 +90,8 @@ EFI_BOOT_SERVICES mBootServices = { (EFI_COPY_MEM)CopyMem, // CopyMem (EFI_SET_MEM)SetMem, // SetMem (EFI_CREATE_EVENT_EX)CoreCreateEventEx, // CreateEventEx - (EFI_ALLOCATE_RING3_PAGES)AllocateRing3Pages + (EFI_ALLOCATE_RING3_PAGES)AllocateRing3Pages, + (EFI_ALLOCATE_CORE_COPY)AllocateCopyPool }; EFI_DXE_SERVICES mDxeServices = { diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 4feb43fcc2..8d0a7a2407 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -6599,6 +6599,7 @@ AsmReadEflags ( UINTN EFIAPI CoreBootServices ( + IN UINT8 Type, IN UINTN FunctionAddress, ... ); diff --git a/MdePkg/Include/Uefi/UefiSpec.h b/MdePkg/Include/Uefi/UefiSpec.h index a1d8441273..cc0b5b8282 100644 --- a/MdePkg/Include/Uefi/UefiSpec.h +++ b/MdePkg/Include/Uefi/UefiSpec.h @@ -220,6 +220,13 @@ EFI_STATUS IN OUT VOID **Memory ); +typedef +VOID * +(EFIAPI *EFI_ALLOCATE_CORE_COPY)( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + /** Frees memory pages. @@ -2019,6 +2026,7 @@ typedef struct { EFI_SET_MEM SetMem; EFI_CREATE_EVENT_EX CreateEventEx; EFI_ALLOCATE_RING3_PAGES AllocateRing3Pages; + EFI_ALLOCATE_CORE_COPY AllocateCoreCopy; } EFI_BOOT_SERVICES; /// diff --git a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm index 868d23df87..21112847a4 100644 --- a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm +++ b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -93,22 +93,27 @@ ASM_PFX(InternalEnterUserImage): retfq ;------------------------------------------------------------------------------ -; UINTN -; EFIAPI -; CoreBootServices ( -; IN UINTN FunctionAddress, -; ... -; ); -; -; (rcx) RIP of the next instruction saved by SYSCALL in SysCall(). -; (rdx) Argument 1 of the called function. -; (r8) Argument 2 of the called function. -; (r9) Argument 3 of the called function. -; (r10) FunctionAddress. -; (r11) RFLAGS saved by SYSCALL in SysCall(). -;On stack Argument 4, 5, ... +; typedef enum { +; SysCallReadMemory = 0, +; SysCallAllocateRing3Pages = 1, +; SysCallAllocateCoreCopy = 2, +; SysCallLocateProtocol = 3, +; SysCallMax +; } SYS_CALL_TYPE; ;------------------------------------------------------------------------------ + +%define READ_MEMORY 0 +%define ALLOCATE_RING3_PAGES 1 +%define ALLOCATE_CORE_COPY 2 +%define LOCATE_PROTOCOL 3 + %macro CallSysRet 0 + ; Prepare SYSRET arguments. + pop rcx + + ; Switch from Core to User data segment selectors. + pop r11 + o16 mov ds, r11 o16 mov es, r11 o16 mov fs, r11 @@ -128,11 +133,45 @@ o64 sysret ; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. %endmacro +%macro DisableSMAP 0 + pushfq + pop rcx + or rcx, 0x40000 ; Set AC (bit 18) + push rcx + popfq +%endmacro + +%macro EnableSMAP 0 + pushfq + pop rcx + and rcx, ~0x40000 ; Clear AC (bit 18) + push rcx + popfq +%endmacro + +;------------------------------------------------------------------------------ +; 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. + ; 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 @@ -148,34 +187,115 @@ ASM_PFX(CoreBootServices): push rbp mov rbp, rsp - cmp r10, 0 - je readMemory + ; 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 - ; Replace argument according to UEFI calling convention. - mov rcx, rdx - mov rdx, r8 - mov r8, r9 - ; mov r9, [rax + 8*3] - ; mov r11, [rax + 8*4] - ; push r11 - ; ... + cmp r10, READ_MEMORY + je readMemory - ; Call Boot Service by FunctionAddress. - call [r10] + cmp r10, ALLOCATE_RING3_PAGES + je allocateRing3Pages - ; Prepare SYSRET arguments. - pop rcx + cmp r10, ALLOCATE_CORE_COPY + je allocateCoreCopy - CallSysRet + cmp r10, LOCATE_PROTOCOL + je locateProtocol +;------------------------------------------------------------------------------ +; 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. + push r9 + + ; Replace argument 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 argument 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 argument 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*4], rcx ; 5th argument of SysCall (SysCallLocateProtocol) + + EnableSMAP + + CallSysRet SECTION .data diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h index 11d8819e4e..f0b64ae0c9 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h @@ -5,14 +5,22 @@ **/ +typedef enum { + SysCallReadMemory = 0, + SysCallAllocateRing3Pages = 1, + SysCallAllocateCoreCopy = 2, + SysCallLocateProtocol = 3, + SysCallMax +} SYS_CALL_TYPE; + UINTN EFIAPI SysCall ( + IN UINT8 Type, IN UINTN FunctionAddress, ... ); - /** Raise the task priority level to the new level. High level is implemented by disabling processor interrupts. diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c index a2eab99121..5995ad4870 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c @@ -94,7 +94,7 @@ UefiBootServicesTableLibConstructor ( // Cache pointer to the EFI Boot Services Table // mCoreBS = (EFI_BOOT_SERVICES *)SysCall ( - 0, + SysCallReadMemory, (UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices) ); ASSERT (mCoreBS != NULL); @@ -504,16 +504,31 @@ EFI_STATUS EFIAPI Ring3LocateProtocol ( IN EFI_GUID *Protocol, - IN VOID *Registration OPTIONAL, + IN VOID *CoreRegistration OPTIONAL, OUT VOID **Interface ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_GUID *CoreProtocol; + + EFI_DEVICE_PATH_UTILITIES_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 ( + SysCallLocateProtocol, (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, LocateProtocol), - Protocol, - Registration, + CoreProtocol, + CoreRegistration, Interface ); if (EFI_ERROR (Status)) { @@ -522,11 +537,10 @@ Ring3LocateProtocol ( } if (CompareGuid (Protocol, &gEfiDevicePathUtilitiesProtocolGuid)) { - EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol; - mCoreDevicePathUtilitiesProtocol = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *)*Interface; Status = (EFI_STATUS)SysCall ( + SysCallAllocateRing3Pages, (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, AllocateRing3Pages), EFI_SIZE_TO_PAGES (sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL)), (VOID **)&UserProtocol diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm b/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm index 64670a6a25..b888ab5d8c 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm @@ -10,13 +10,14 @@ ; UINTN ; EFIAPI ; SysCall ( +; IN UINT8 Type, ; IN UINTN FunctionAddress, ; ... ; ); ;------------------------------------------------------------------------------ global ASM_PFX(SysCall) ASM_PFX(SysCall): - ; Save FunctionAddress for CoreBootServices(). + ; Save Type for CoreBootServices(). mov r10, rcx ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX.