Ring3: Added helper function AllocateCoreCopy(), refactored SysCall.

This commit is contained in:
Mikhail Krichanov 2024-01-29 14:00:43 +03:00
parent e170598395
commit 12cc1a9a5d
7 changed files with 193 additions and 40 deletions

View File

@ -90,7 +90,8 @@ EFI_BOOT_SERVICES mBootServices = {
(EFI_COPY_MEM)CopyMem, // CopyMem (EFI_COPY_MEM)CopyMem, // CopyMem
(EFI_SET_MEM)SetMem, // SetMem (EFI_SET_MEM)SetMem, // SetMem
(EFI_CREATE_EVENT_EX)CoreCreateEventEx, // CreateEventEx (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 = { EFI_DXE_SERVICES mDxeServices = {

View File

@ -6699,6 +6699,7 @@ AsmReadEflags (
UINTN UINTN
EFIAPI EFIAPI
CoreBootServices ( CoreBootServices (
IN UINT8 Type,
IN UINTN FunctionAddress, IN UINTN FunctionAddress,
... ...
); );

View File

@ -229,6 +229,13 @@ EFI_STATUS
IN OUT VOID **Memory IN OUT VOID **Memory
); );
typedef
VOID *
(EFIAPI *EFI_ALLOCATE_CORE_COPY)(
IN UINTN AllocationSize,
IN CONST VOID *Buffer
);
/** /**
Frees memory pages. Frees memory pages.
@ -2031,6 +2038,7 @@ typedef struct {
EFI_SET_MEM SetMem; EFI_SET_MEM SetMem;
EFI_CREATE_EVENT_EX CreateEventEx; EFI_CREATE_EVENT_EX CreateEventEx;
EFI_ALLOCATE_RING3_PAGES AllocateRing3Pages; EFI_ALLOCATE_RING3_PAGES AllocateRing3Pages;
EFI_ALLOCATE_CORE_COPY AllocateCoreCopy;
} EFI_BOOT_SERVICES; } EFI_BOOT_SERVICES;
/// ///

View File

@ -93,22 +93,27 @@ ASM_PFX(InternalEnterUserImage):
retfq retfq
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
; UINTN ; typedef enum {
; EFIAPI ; SysCallReadMemory = 0,
; CoreBootServices ( ; SysCallAllocateRing3Pages = 1,
; IN UINTN FunctionAddress, ; SysCallAllocateCoreCopy = 2,
; ... ; SysCallLocateProtocol = 3,
; ); ; SysCallMax
; ; } SYS_CALL_TYPE;
; (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, ...
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
%define READ_MEMORY 0
%define ALLOCATE_RING3_PAGES 1
%define ALLOCATE_CORE_COPY 2
%define LOCATE_PROTOCOL 3
%macro CallSysRet 0 %macro CallSysRet 0
; Prepare SYSRET arguments.
pop rcx
; Switch from Core to User data segment selectors.
pop r11
o16 mov ds, r11 o16 mov ds, r11
o16 mov es, r11 o16 mov es, r11
o16 mov fs, r11 o16 mov fs, r11
@ -128,11 +133,45 @@ o64 sysret
; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. ; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11.
%endmacro %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) global ASM_PFX(CoreBootServices)
ASM_PFX(CoreBootServices): ASM_PFX(CoreBootServices):
; Save User data segment selector. ; Save User data segment selector temporarily in R11.
mov r11, ds mov r11, ds
; Switch from User to Core data segment selectors.
mov ax, ss mov ax, ss
mov ds, ax mov ds, ax
mov es, ax mov es, ax
@ -148,34 +187,115 @@ ASM_PFX(CoreBootServices):
push rbp push rbp
mov rbp, rsp mov rbp, rsp
cmp r10, 0 ; Save User data segment selector on Core SysCall Stack.
je readMemory push r11
; Save FunctionAddress in R11 as it will be called later.
mov r11, rdx
; Save return address for SYSRET. ; Save return address for SYSRET.
push rcx push rcx
; Replace argument according to UEFI calling convention. cmp r10, READ_MEMORY
mov rcx, rdx je readMemory
mov rdx, r8
mov r8, r9
; mov r9, [rax + 8*3]
; mov r11, [rax + 8*4]
; push r11
; ...
; Call Boot Service by FunctionAddress. cmp r10, ALLOCATE_RING3_PAGES
call [r10] je allocateRing3Pages
; Prepare SYSRET arguments. cmp r10, ALLOCATE_CORE_COPY
pop rcx je allocateCoreCopy
CallSysRet cmp r10, LOCATE_PROTOCOL
je locateProtocol
;------------------------------------------------------------------------------
; UINTN
; ReadMemory (
; IN UINTN Address
; );
readMemory: readMemory:
mov rax, [rdx] mov rax, [rdx]
CallSysRet 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 SECTION .data

View File

@ -5,14 +5,22 @@
**/ **/
typedef enum {
SysCallReadMemory = 0,
SysCallAllocateRing3Pages = 1,
SysCallAllocateCoreCopy = 2,
SysCallLocateProtocol = 3,
SysCallMax
} SYS_CALL_TYPE;
UINTN UINTN
EFIAPI EFIAPI
SysCall ( SysCall (
IN UINT8 Type,
IN UINTN FunctionAddress, IN UINTN FunctionAddress,
... ...
); );
/** /**
Raise the task priority level to the new level. Raise the task priority level to the new level.
High level is implemented by disabling processor interrupts. High level is implemented by disabling processor interrupts.

View File

@ -94,7 +94,7 @@ UefiBootServicesTableLibConstructor (
// Cache pointer to the EFI Boot Services Table // Cache pointer to the EFI Boot Services Table
// //
mCoreBS = (EFI_BOOT_SERVICES *)SysCall ( mCoreBS = (EFI_BOOT_SERVICES *)SysCall (
0, SysCallReadMemory,
(UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices) (UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices)
); );
ASSERT (mCoreBS != NULL); ASSERT (mCoreBS != NULL);
@ -504,16 +504,31 @@ EFI_STATUS
EFIAPI EFIAPI
Ring3LocateProtocol ( Ring3LocateProtocol (
IN EFI_GUID *Protocol, IN EFI_GUID *Protocol,
IN VOID *Registration OPTIONAL, IN VOID *CoreRegistration OPTIONAL,
OUT VOID **Interface 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 ( Status = (EFI_STATUS)SysCall (
SysCallLocateProtocol,
(UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, LocateProtocol), (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, LocateProtocol),
Protocol, CoreProtocol,
Registration, CoreRegistration,
Interface Interface
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -522,11 +537,10 @@ Ring3LocateProtocol (
} }
if (CompareGuid (Protocol, &gEfiDevicePathUtilitiesProtocolGuid)) { if (CompareGuid (Protocol, &gEfiDevicePathUtilitiesProtocolGuid)) {
EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol;
mCoreDevicePathUtilitiesProtocol = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *)*Interface; mCoreDevicePathUtilitiesProtocol = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *)*Interface;
Status = (EFI_STATUS)SysCall ( Status = (EFI_STATUS)SysCall (
SysCallAllocateRing3Pages,
(UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, AllocateRing3Pages), (UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, AllocateRing3Pages),
EFI_SIZE_TO_PAGES (sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL)), EFI_SIZE_TO_PAGES (sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL)),
(VOID **)&UserProtocol (VOID **)&UserProtocol

View File

@ -10,13 +10,14 @@
; UINTN ; UINTN
; EFIAPI ; EFIAPI
; SysCall ( ; SysCall (
; IN UINT8 Type,
; IN UINTN FunctionAddress, ; IN UINTN FunctionAddress,
; ... ; ...
; ); ; );
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
global ASM_PFX(SysCall) global ASM_PFX(SysCall)
ASM_PFX(SysCall): ASM_PFX(SysCall):
; Save FunctionAddress for CoreBootServices(). ; Save Type for CoreBootServices().
mov r10, rcx mov r10, rcx
; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX.