diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index b6004f293c..16091d3f09 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -228,6 +228,7 @@ typedef struct { VOID *HiiData; BOOLEAN IsUserImage; + BOOLEAN IsRing3EntryPoint; } LOADED_IMAGE_PRIVATE_DATA; #define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \ @@ -2739,13 +2740,15 @@ RemoveImageRecord ( @param[in] ImageOrigin Where File comes from. @param[in] LoadedImageDevicePath The loaded image device path protocol @param[out] IsUserImage Whether the loaded image is in user space. + @param[out] IsRing3EntryPoint Whether the loaded image is a wrapper for Ring3 calls. **/ VOID ProtectUefiImage ( IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, IN UINT8 ImageOrigin, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext, - OUT BOOLEAN *IsUserImage + OUT BOOLEAN *IsUserImage, + OUT BOOLEAN *IsRing3EntryPoint ); /** diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 46e1310d6d..014f6576c5 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -69,7 +69,7 @@ DxeMain/DxeMain.c SysCall/BootServices.c SysCall/SupportedProtocols.h - SysCall/DriverBindingProtocol.c + SysCall/SupportedProtocols.c [Sources.X64] SysCall/X64/CoreBootServices.nasm diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index d36d0061af..937194f4fc 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -332,7 +332,7 @@ DxeMain ( CoreInitializeMemoryProtection (); - ProtectUefiImage (&mCurrentImage->Info, UefiImageOriginFv, &ImageContext, &mCurrentImage->IsUserImage); + ProtectUefiImage (&mCurrentImage->Info, UefiImageOriginFv, &ImageContext, &mCurrentImage->IsUserImage, &mCurrentImage->IsRing3EntryPoint); // // Call constructor for all libraries diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index e9f030fb3d..89d3658d09 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -28,6 +28,8 @@ STATIC VOID *mPeCoffEmuProtocolNotifyRegistration; extern BOOLEAN gBdsStarted; VOID *gCoreSysCallStackTop; +VOID *gRing3CallStackTop; +VOID *gRing3EntryPoint; // // This code is needed to build the Image handle for the DXE Core @@ -70,7 +72,8 @@ LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = { NULL, // LoadedImageDevicePath EFI_SUCCESS, // LoadImageStatus NULL, // HiiData - FALSE // IsUserImage + FALSE, // IsUserImage + FALSE // IsRing3EntryPoint }; // // The field is define for Loading modules at fixed address feature to tracker the PEI code @@ -1441,7 +1444,7 @@ CoreLoadImageCommon ( } Status = EFI_SUCCESS; - ProtectUefiImage (&Image->Info, ImageOrigin, &ImageContext, &Image->IsUserImage); + ProtectUefiImage (&Image->Info, ImageOrigin, &ImageContext, &Image->IsUserImage, &Image->IsRing3EntryPoint); RegisterMemoryProfileImage ( Image->LoadedImageDevicePath, @@ -1718,6 +1721,13 @@ CoreStartImage ( if (!Image->IsUserImage) { Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable); + } else if (Image->IsRing3EntryPoint) { + gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)Image->EntryPoint, &Attributes); + ASSERT ((Attributes & EFI_MEMORY_USER) != 0); + + gRing3EntryPoint = (VOID *)Image->EntryPoint; + + Image->Status = EFI_SUCCESS; } else { gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)Image->EntryPoint, &Attributes); ASSERT ((Attributes & EFI_MEMORY_USER) != 0); @@ -1753,8 +1763,10 @@ CoreStartImage ( TopOfStack = (VOID *)((UINTN)BaseOfStack + SizeOfStack - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + gRing3CallStackTop = TopOfStack; + SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER); - DEBUG ((DEBUG_ERROR, "Core: UserTopOfStack = %p\n", TopOfStack)); + DEBUG ((DEBUG_ERROR, "Core: gRing3CallStackTop = %p\n", gRing3CallStackTop)); // // Necessary fix for ProcessLibraryConstructorList() -> DxeCcProbeLibConstructor() @@ -1780,7 +1792,7 @@ CoreStartImage ( (SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint, ImageHandle, Image->Info.SystemTable, - TopOfStack, + gRing3CallStackTop, (UINT16)RING3_CODE64_SEL, (UINT16)RING3_DATA64_SEL ); diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index 76ab3fbbd6..9a24006ee0 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -170,13 +170,15 @@ IsMemoryProtectionSectionAligned ( @param[in] ImageOrigin Where File comes from. @param[in] LoadedImageDevicePath The loaded image device path protocol @param[out] IsUserImage Whether the loaded image is in user space. + @param[out] IsRing3EntryPoint Whether the loaded image is a wrapper for Ring3 calls. **/ VOID ProtectUefiImage ( IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, IN UINT8 ImageOrigin, IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext, - OUT BOOLEAN *IsUserImage + OUT BOOLEAN *IsUserImage, + OUT BOOLEAN *IsRing3EntryPoint ) { RETURN_STATUS PdbStatus; @@ -231,6 +233,8 @@ ProtectUefiImage ( // InsertTailList (&mProtectedImageRecordList, &ImageRecord->Link); + *IsRing3EntryPoint = FALSE; + if (gCpu != NULL) { // // CPU ARCH present. Update memory attribute directly. @@ -238,7 +242,11 @@ ProtectUefiImage ( if (AsciiStrStr (PdbPointer, "Ntfs") != NULL) { SetUefiImageProtectionAttributes (ImageRecord, TRUE); *IsUserImage = TRUE; - } else { + } else if (AsciiStrStr (PdbPointer, "Ring3") != NULL) { + SetUefiImageProtectionAttributes (ImageRecord, TRUE); + *IsUserImage = TRUE; + *IsRing3EntryPoint = TRUE; + } else { SetUefiImageProtectionAttributes (ImageRecord, FALSE); *IsUserImage = FALSE; } diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c index c579873bec..df73724486 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c +++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c @@ -191,6 +191,10 @@ CallBootService ( if (CompareGuid ((EFI_GUID *)ArgList[Index], &gEfiDriverBindingProtocolGuid)) { CoreDriverBinding = (EFI_DRIVER_BINDING_PROTOCOL *)ArgList[Index + 1]; + mUserDriverBindingSupported = CoreDriverBinding->Supported; + mUserDriverBindingStart = CoreDriverBinding->Start; + mUserDriverBindingStop = CoreDriverBinding->Stop; + CoreDriverBinding->Supported = CoreDriverBindingSupported; CoreDriverBinding->Start = CoreDriverBindingStart; CoreDriverBinding->Stop = CoreDriverBindingStop; diff --git a/MdeModulePkg/Core/Dxe/SysCall/DriverBindingProtocol.c b/MdeModulePkg/Core/Dxe/SysCall/DriverBindingProtocol.c deleted file mode 100644 index 80143dccb6..0000000000 --- a/MdeModulePkg/Core/Dxe/SysCall/DriverBindingProtocol.c +++ /dev/null @@ -1,42 +0,0 @@ -/** @file - - Copyright (c) 2024, Mikhail Krichanov. All rights reserved. - SPDX-License-Identifier: BSD-3-Clause - -**/ - -#include "DxeMain.h" - -EFI_STATUS -EFIAPI -CoreDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - return EFI_UNSUPPORTED; -} - -EFI_STATUS -EFIAPI -CoreDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - return EFI_UNSUPPORTED; -} - -EFI_STATUS -EFIAPI -CoreDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer OPTIONAL - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/MdeModulePkg/Core/Dxe/SysCall/Ring3Dxe.c b/MdeModulePkg/Core/Dxe/SysCall/Ring3Dxe.c new file mode 100644 index 0000000000..d2e4b75816 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/Ring3Dxe.c @@ -0,0 +1,18 @@ +/** @file + + Copyright (c) 2024, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +**/ + +#include + +EFI_STATUS +EFIAPI +Ring3EntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Dxe/SysCall/Ring3Dxe.inf b/MdeModulePkg/Core/Dxe/SysCall/Ring3Dxe.inf new file mode 100644 index 0000000000..f66a5def48 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/Ring3Dxe.inf @@ -0,0 +1,42 @@ +## @file +# +# Ring3 driver for SysCalls. +# +# Copyright (c) 2024, Mikhail Krichanov. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Ring3Dxe + FILE_GUID = 88EA50C2-0DEA-4F13-B691-B506554E632B + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = Ring3EntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Ring3Dxe.c + +[Sources.X64] + X64/Ring3Dxe.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + +[Protocols] + +[Guids] + +[Depex] + TRUE diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c new file mode 100644 index 0000000000..952b88ddbe --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c @@ -0,0 +1,88 @@ +/** @file + + Copyright (c) 2024, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +**/ + +#include "DxeMain.h" + +EFI_DRIVER_BINDING_SUPPORTED mUserDriverBindingSupported; +EFI_DRIVER_BINDING_START mUserDriverBindingStart; +EFI_DRIVER_BINDING_STOP mUserDriverBindingStop; + +typedef enum { + UserDriverBindingSupported = 1, + UserDriverBindingStart = 2, + UserDriverBindingStop = 3, + UserCallMax +} USER_CALL_TYPE; + +EFI_STATUS +EFIAPI +CallRing3 ( + IN UINT8 Type, + IN UINT16 CodeSelector, + IN UINT16 DataSelector, + IN VOID *FunctionAddress, + ... + ); + +EFI_STATUS +EFIAPI +CoreDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return CallRing3 ( + UserDriverBindingSupported, + (UINT16)RING3_CODE64_SEL, + (UINT16)RING3_DATA64_SEL, + (VOID *)mUserDriverBindingSupported, + This, + ControllerHandle, + RemainingDevicePath + ); +} + +EFI_STATUS +EFIAPI +CoreDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return CallRing3 ( + UserDriverBindingStart, + (UINT16)RING3_CODE64_SEL, + (UINT16)RING3_DATA64_SEL, + (VOID *)mUserDriverBindingStart, + This, + ControllerHandle, + RemainingDevicePath + ); +} + +EFI_STATUS +EFIAPI +CoreDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + return CallRing3 ( + UserDriverBindingStop, + (UINT16)RING3_CODE64_SEL, + (UINT16)RING3_DATA64_SEL, + (VOID *)mUserDriverBindingStop, + This, + ControllerHandle, + NumberOfChildren, + ChildHandleBuffer + ); +} diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h index 07c43d162a..4737cc696e 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h +++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h @@ -5,6 +5,10 @@ **/ +extern EFI_DRIVER_BINDING_SUPPORTED mUserDriverBindingSupported; +extern EFI_DRIVER_BINDING_START mUserDriverBindingStart; +extern EFI_DRIVER_BINDING_STOP mUserDriverBindingStop; + EFI_STATUS EFIAPI CoreDriverBindingSupported ( @@ -12,7 +16,7 @@ CoreDriverBindingSupported ( IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL ); - + EFI_STATUS EFIAPI CoreDriverBindingStart ( diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm index 34d21a02e7..83508675f2 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm @@ -10,6 +10,8 @@ SECTION .text extern ASM_PFX(CallBootService) extern ASM_PFX(gCoreSysCallStackTop) +extern ASM_PFX(gRing3CallStackTop) +extern ASM_PFX(gRing3EntryPoint) global ASM_PFX(DisableSMAP) ASM_PFX(DisableSMAP): @@ -151,3 +153,47 @@ ASM_PFX(InternalEnterUserImage): ; Pass control to user image retfq + +;------------------------------------------------------------------------------ +; EFI_STATUS +; EFIAPI +; CallRing3 ( +; IN UINT8 Type, +; IN UINT16 CodeSelector, +; IN UINT16 DataSelector, +; IN VOID *FunctionAddress, +; ... +; ); +; +; (rcx) Type. +; (rdx) CodeSelector - Segment selector for code. +; (r8) DataSelector - Segment selector for data. +; (r9) FunctionAddress +; +; (On User Stack) Argument 1, 2, 3, ... +;------------------------------------------------------------------------------ +global ASM_PFX(CallRing3) +ASM_PFX(CallRing3): + ; Set Data selectors + or r8, 3H ; RPL = 3 + +o16 mov ds, r8 +o16 mov es, r8 +o16 mov fs, r8 +o16 mov gs, r8 + + ; Save Code selector + or rdx, 3H ; RPL = 3 + + ; Prepare stack before swithcing + push r8 ; ss + push qword [gRing3CallStackTop] ; rsp + push rdx ; cs + push qword [gRing3EntryPoint] ; rip + + ; Copy Arguments from Core Stack to User Stack + return address + + ; Pass control to User driver function. + retfq +coreReturnAddress: + ret diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/Ring3Dxe.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/Ring3Dxe.nasm new file mode 100644 index 0000000000..ec4780bdc8 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/Ring3Dxe.nasm @@ -0,0 +1,21 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2024, Mikhail Krichanov. All rights reserved. +; SPDX-License-Identifier: BSD-3-Clause +; +;------------------------------------------------------------------------------ + +DEFAULT REL +SECTION .text + +;------------------------------------------------------------------------------ +; EFI_STATUS +; EFIAPI +; _ModuleEntryPoint ( +; IN EFI_HANDLE ImageHandle, +; IN EFI_SYSTEM_TABLE *SystemTable +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + ret