Ring3: Added SysCallOpenProtocol.

This commit is contained in:
Mikhail Krichanov 2024-01-29 20:21:14 +03:00
parent de01af7081
commit a2955bd646
3 changed files with 141 additions and 15 deletions

View File

@ -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

View File

@ -10,6 +10,7 @@ typedef enum {
SysCallAllocateRing3Pages = 1,
SysCallAllocateCoreCopy = 2,
SysCallLocateProtocol = 3,
SysCallOpenProtocol = 4,
SysCallMax
} SYS_CALL_TYPE;

View File

@ -12,6 +12,7 @@
#include <Library/DebugLib.h>
#include <Protocol/DevicePathUtilities.h>
#include <Protocol/LoadedImage.h>
#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