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

This commit is contained in:
Mikhail Krichanov 2024-01-29 14:00:43 +03:00
parent 87a397740d
commit de01af7081
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_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 = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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