-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ring3: Moved SysCall code to DxeCore.
- Loading branch information
Mikhail Krichanov
committed
Feb 2, 2024
1 parent
4153e95
commit 50016e9
Showing
9 changed files
with
339 additions
and
354 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
/** @file | ||
Copyright (c) 2024, Mikhail Krichanov. All rights reserved. | ||
SPDX-License-Identifier: BSD-3-Clause | ||
**/ | ||
|
||
#include <Base.h> | ||
#include <Library/BaseLib.h> | ||
#include <Library/BaseMemoryLib.h> | ||
#include <Library/DebugLib.h> | ||
#include <Library/PcdLib.h> | ||
|
||
VOID | ||
EFIAPI | ||
DisableSMAP ( | ||
VOID | ||
); | ||
|
||
VOID | ||
EFIAPI | ||
EnableSMAP ( | ||
VOID | ||
); | ||
|
||
VOID | ||
EFIAPI | ||
InternalEnterUserImage ( | ||
IN SWITCH_STACK_ENTRY_POINT EntryPoint, | ||
IN VOID *Context1 OPTIONAL, | ||
IN VOID *Context2 OPTIONAL, | ||
IN VOID *NewStack, | ||
IN UINT16 CodeSelector, | ||
IN UINT16 DataSelector | ||
); | ||
|
||
typedef enum { | ||
SysCallReadMemory = 0, | ||
SysCallAllocateRing3Pages = 1, | ||
SysCallAllocateCoreCopy = 2, | ||
SysCallLocateProtocol = 3, | ||
SysCallOpenProtocol = 4, | ||
SysCallMax | ||
} SYS_CALL_TYPE; | ||
|
||
UINTN | ||
EFIAPI | ||
CallBootService ( | ||
IN UINT8 Type, | ||
IN VOID **FunctionAddress, | ||
IN UINTN CoreRbp, | ||
IN UINTN UserRsp | ||
) | ||
{ | ||
UINTN Status; | ||
VOID *Pointer; | ||
VOID * Arg4; | ||
VOID * Arg5; | ||
UINT32 Arg6; | ||
EFI_ALLOCATE_RING3_PAGES Func1; | ||
EFI_ALLOCATE_CORE_COPY Func2; | ||
EFI_LOCATE_PROTOCOL Func3; | ||
EFI_OPEN_PROTOCOL Func4; | ||
// Stack: | ||
// rcx - Rip for SYSCALL | ||
// r8 - Argument 1 | ||
// rbp - User Rbp | ||
// r9 - Argument 2 | ||
// r11 - User data segment selector <- CoreRbp | ||
// rsp - User Rsp | ||
switch (Type) { | ||
case SysCallReadMemory: | ||
return *(UINTN *)FunctionAddress; | ||
|
||
case SysCallAllocateRing3Pages: | ||
Func1 = (EFI_ALLOCATE_RING3_PAGES)*FunctionAddress; | ||
Status = Func1 ( | ||
*((UINTN *)CoreRbp + 3), | ||
&Pointer | ||
); | ||
DisableSMAP (); | ||
*(UINTN *)(*((UINTN *)CoreRbp + 1)) = (UINTN)Pointer; | ||
EnableSMAP (); | ||
return (UINTN)Status; | ||
|
||
case SysCallAllocateCoreCopy: | ||
DisableSMAP (); | ||
Func2 = (EFI_ALLOCATE_CORE_COPY)*FunctionAddress; | ||
Status = (UINTN)Func2 ( | ||
*((UINTN *)CoreRbp + 3), | ||
(VOID *)*((UINTN *)CoreRbp + 1) | ||
); | ||
EnableSMAP (); | ||
return (UINTN)Status; | ||
|
||
case SysCallLocateProtocol: | ||
Func3 = (EFI_LOCATE_PROTOCOL)*FunctionAddress; | ||
Status = Func3 ( | ||
(VOID *)*((UINTN *)CoreRbp + 3), | ||
(VOID *)*((UINTN *)CoreRbp + 1), | ||
&Pointer | ||
); | ||
DisableSMAP (); | ||
*((UINTN *)UserRsp + 5) = (UINTN)Pointer; | ||
EnableSMAP (); | ||
return (UINTN)Status; | ||
|
||
case SysCallOpenProtocol: | ||
DisableSMAP (); | ||
Arg4 = (VOID *)*((UINTN *)UserRsp + 6); | ||
Arg5 = (VOID *)*((UINTN *)UserRsp + 7); | ||
Arg6 = (UINT32)*((UINTN *)UserRsp + 8); | ||
EnableSMAP (); | ||
Func4 = (EFI_OPEN_PROTOCOL)*FunctionAddress; | ||
Status = Func4 ( | ||
(VOID *)*((UINTN *)CoreRbp + 3), | ||
(VOID *)*((UINTN *)CoreRbp + 1), | ||
&Pointer, | ||
Arg4, | ||
Arg5, | ||
Arg6 | ||
); | ||
DisableSMAP (); | ||
*((UINTN *)UserRsp + 5) = (UINTN)Pointer; | ||
EnableSMAP (); | ||
return (UINTN)Status; | ||
default: | ||
break; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
VOID | ||
EFIAPI | ||
EnterUserImage ( | ||
IN SWITCH_STACK_ENTRY_POINT EntryPoint, | ||
IN VOID *Context1 OPTIONAL, | ||
IN VOID *Context2 OPTIONAL, | ||
IN VOID *NewStack, | ||
IN UINT16 CodeSelector, | ||
IN UINT16 DataSelector | ||
) | ||
{ | ||
ASSERT (EntryPoint != NULL); | ||
ASSERT (NewStack != NULL); | ||
|
||
// | ||
// New stack must be aligned with CPU_STACK_ALIGNMENT | ||
// | ||
ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0); | ||
|
||
InternalEnterUserImage (EntryPoint, Context1, Context2, NewStack, CodeSelector, DataSelector); | ||
} |
161 changes: 161 additions & 0 deletions
161
MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
;------------------------------------------------------------------------------ | ||
; | ||
; Copyright (c) 2024, Mikhail Krichanov. All rights reserved. | ||
; SPDX-License-Identifier: BSD-3-Clause | ||
; | ||
;------------------------------------------------------------------------------ | ||
|
||
DEFAULT REL | ||
SECTION .text | ||
|
||
extern ASM_PFX(CallBootService) | ||
extern ASM_PFX(gCoreSysCallStackTop) | ||
|
||
%macro CallSysRet 0 | ||
; Prepare SYSRET arguments. | ||
mov rcx, [rbp + 8*4] | ||
pop rdx | ||
|
||
; Switch from Core to User data segment selectors. | ||
pop r11 | ||
|
||
o16 mov ds, r11 | ||
o16 mov es, r11 | ||
o16 mov fs, r11 | ||
o16 mov gs, r11 | ||
|
||
; Restore RFLAGS in R11 for SYSRET. | ||
pushfq | ||
pop r11 | ||
|
||
; Switch to User Stack. | ||
pop rbp | ||
pop rbp | ||
mov rsp, rdx | ||
|
||
; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. | ||
o64 sysret | ||
; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. | ||
%endmacro | ||
|
||
global ASM_PFX(DisableSMAP) | ||
ASM_PFX(DisableSMAP): | ||
pushfq | ||
pop r10 | ||
or r10, 0x40000 ; Set AC (bit 18) | ||
push r10 | ||
popfq | ||
ret | ||
|
||
global ASM_PFX(EnableSMAP) | ||
ASM_PFX(EnableSMAP): | ||
pushfq | ||
pop r10 | ||
and r10, ~0x40000 ; Clear AC (bit 18) | ||
push r10 | ||
popfq | ||
ret | ||
|
||
;------------------------------------------------------------------------------ | ||
; 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 temporarily in R11. | ||
mov r11, ds | ||
|
||
; Switch from User to Core data segment selectors. | ||
mov ax, ss | ||
mov ds, ax | ||
mov es, ax | ||
mov fs, ax | ||
mov gs, ax | ||
|
||
; Save User Stack pointers and switch to Core SysCall Stack. | ||
mov rax, [ASM_PFX(gCoreSysCallStackTop)] | ||
; Save return address for SYSRET. | ||
sub rax, 8 | ||
mov [rax], rcx | ||
mov rcx, r10 | ||
sub rax, 8 | ||
mov [rax], r8 | ||
sub rax, 8 | ||
mov [rax], rbp | ||
sub rax, 8 | ||
mov [rax], r9 | ||
; Save User data segment selector on Core SysCall Stack. | ||
sub rax, 8 | ||
mov [rax], r11 | ||
|
||
mov r9, rsp | ||
|
||
mov rsp, rax | ||
|
||
mov rbp, rsp | ||
mov r8, rbp | ||
push r9 | ||
|
||
call ASM_PFX(CallBootService) | ||
|
||
CallSysRet | ||
|
||
;------------------------------------------------------------------------------ | ||
; Routine Description: | ||
; | ||
; Routine for transfering control to user image with 2 parameters | ||
; | ||
; Arguments: | ||
; | ||
; (rcx) EntryPoint - Entry point with new stack. | ||
; (rdx) Context1 - Parameter1 for entry point. | ||
; (r8) Context2 - Parameter2 for entry point. | ||
; (r9) NewStack - The pointer to new stack. | ||
;On stack CodeSelector - Segment selector for code. | ||
;On stack DataSelector - Segment selector for data. | ||
; | ||
; Returns: | ||
; | ||
; None | ||
; | ||
;------------------------------------------------------------------------------ | ||
global ASM_PFX(InternalEnterUserImage) | ||
ASM_PFX(InternalEnterUserImage): | ||
; Set Data selectors | ||
mov rax, [rsp + 8*6] | ||
or rax, 3H ; RPL = 3 | ||
|
||
mov ds, ax | ||
mov es, ax | ||
mov fs, ax | ||
mov gs, ax | ||
|
||
; Save Code selector | ||
mov r10, [rsp + 8*5] | ||
or r10, 3H ; RPL = 3 | ||
|
||
; Prepare stack before swithcing | ||
push rax ; ss | ||
push r9 ; rsp | ||
push r10 ; cs | ||
push rcx ; rip | ||
|
||
; Save 2 parameters | ||
mov rcx, rdx | ||
mov rdx, r8 | ||
|
||
; Pass control to user image | ||
retfq |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.