Skip to content

Commit

Permalink
Ring3: Added helper function AllocateCoreCopy(), refactored SysCall.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Krichanov committed Jan 29, 2024
1 parent 7730f36 commit e0ad1b1
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 39 deletions.
3 changes: 2 additions & 1 deletion MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions MdePkg/Include/Library/BaseLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -6315,6 +6315,7 @@ AsmReadEflags (
UINTN
EFIAPI
CoreBootServices (
IN UINT8 Type,
IN UINTN FunctionAddress,
...
);
Expand Down
8 changes: 8 additions & 0 deletions MdePkg/Include/Uefi/UefiSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ EFI_STATUS
IN OUT VOID **Memory
);

typedef
VOID *
(EFIAPI *EFI_ALLOCATE_CORE_COPY)(
IN UINTN AllocationSize,
IN CONST VOID *Buffer
);

/**
Frees memory pages.
Expand Down Expand Up @@ -1968,6 +1975,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;

///
Expand Down
178 changes: 149 additions & 29 deletions MdePkg/Library/BaseLib/X64/SwitchStack.nasm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

cmp r10, READ_MEMORY
je readMemory

cmp r10, ALLOCATE_RING3_PAGES
je allocateRing3Pages

cmp r10, ALLOCATE_CORE_COPY
je allocateCoreCopy

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, rdx
mov rdx, r8
mov r8, r9
; mov r9, [rax + 8*3]
; mov r11, [rax + 8*4]
; push r11
; ...
mov rcx, r8
; Allocate space for (VOID *)Memory on Core SysCall Stack.
sub rsp, 8
mov rdx, rsp

; Call Boot Service by FunctionAddress.
call [r10]
call [r11]

; Prepare SYSRET arguments.
pop rcx
DisableSMAP

; Copy (VOID *)Memory from Core SysCall Stack to User Stack.
pop rdx
pop r9
mov [r9], rdx

EnableSMAP

CallSysRet

readMemory:
mov rax, [rdx]
;------------------------------------------------------------------------------
; 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

Expand Down
10 changes: 9 additions & 1 deletion MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit e0ad1b1

Please sign in to comment.