Skip to content

Commit

Permalink
Ring3: Refactored stack operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Krichanov committed Feb 5, 2024
1 parent 44cd3c5 commit 5d084d3
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 113 deletions.
2 changes: 1 addition & 1 deletion MdeModulePkg/Core/Dxe/DxeMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -2817,7 +2817,7 @@ SetUefiImageMemoryAttributes (
IN UINT64 Attributes
);

UINTN
EFI_STATUS
EFIAPI
CoreBootServices (
IN UINT8 Type,
Expand Down
120 changes: 74 additions & 46 deletions MdeModulePkg/Core/Dxe/SysCall/BootServices.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,115 +32,143 @@ InternalEnterUserImage (
IN UINT16 DataSelector
);

UINTN
typedef struct {
UINTN Argument1;
UINTN Argument2;
UINTN Argument3;
} CORE_STACK;

typedef struct {
UINTN Rip;
UINTN Arguments[];
} RING3_STACK;
//
// Stack:
// rsp - User Rsp
// rbp - User Rbp
// rcx - Rip for SYSCALL
// r11 - User data segment selector
// r9 - Argument 3
// r8 - Argument 2
// rdx - Argument 1 <- CoreRbp
//
EFI_STATUS
EFIAPI
CallBootService (
IN UINT8 Type,
IN UINTN CoreRbp,
IN UINTN UserRsp
IN UINT8 Type,
IN CORE_STACK *CoreRbp,
IN RING3_STACK *UserRsp
)
{
UINTN Status;
VOID *Pointer;
VOID * Arg4;
VOID * Arg5;
UINT32 Arg6;

EFI_GUID *CoreProtocol;
UINT32 MemoryCoreSize;

// Stack:
// rcx - Rip for SYSCALL
// rdx - Argument 1
// rbp - User Rbp
// r8 - Argument 2
// r11 - User data segment selector <- CoreRbp
// rsp - User Rsp
// r9 - Argument 3
EFI_STATUS Status;
UINT64 Attributes;
VOID *Interface;
EFI_GUID *CoreProtocol;
UINT32 MemoryCoreSize;
EFI_HANDLE Argument4;
EFI_HANDLE Argument5;
UINT32 Argument6;

gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)UserRsp, &Attributes);
ASSERT ((Attributes & EFI_MEMORY_USER) != 0);

switch (Type) {
case SysCallLocateProtocol:
//
// Argument 1: EFI_GUID *Protocol
// Argument 2: VOID *CoreRegistration
// Argument 3: VOID **Interface
//
DisableSMAP ();
CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)*((UINTN *)CoreRbp + 3));
CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)CoreRbp->Argument1);
EnableSMAP ();
if (CoreProtocol == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n"));
return EFI_OUT_OF_RESOURCES;
}

Status = gBS->LocateProtocol (
CoreProtocol,
(VOID *)*((UINTN *)CoreRbp + 1),
&Pointer
);
CoreProtocol,
(VOID *)CoreRbp->Argument2,
&Interface
);

if (CompareGuid (CoreProtocol, &gEfiDevicePathUtilitiesProtocolGuid)) {
MemoryCoreSize = sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL);
} else {
MemoryCoreSize = 0;
}

Pointer = AllocateRing3CopyPages (Pointer, MemoryCoreSize);
if (Pointer == NULL) {
Interface = AllocateRing3CopyPages (Interface, MemoryCoreSize);
if (Interface == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n"));
FreePool (CoreProtocol);
return EFI_OUT_OF_RESOURCES;
}

DisableSMAP ();
*(UINTN *)(*((UINTN *)CoreRbp - 2)) = (UINTN)Pointer;
*(VOID **)CoreRbp->Argument3 = Interface;
EnableSMAP ();

FreePool (CoreProtocol);

return (UINTN)Status;
return Status;

case SysCallOpenProtocol:
//
// Argument 1: EFI_HANDLE CoreUserHandle
// Argument 2: EFI_GUID *Protocol
// Argument 3: VOID **Interface
// Argument 4: EFI_HANDLE CoreImageHandle
// Argument 5: EFI_HANDLE CoreControllerHandle
// Argument 6: UINT32 Attributes
//
DisableSMAP ();
CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)*((UINTN *)CoreRbp + 1));
Arg4 = (VOID *)*((UINTN *)UserRsp + 5);
Arg5 = (VOID *)*((UINTN *)UserRsp + 6);
Arg6 = (UINT32)*((UINTN *)UserRsp + 7);
CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)CoreRbp->Argument2);
Argument4 = (EFI_HANDLE)UserRsp->Arguments[4];
Argument5 = (EFI_HANDLE)UserRsp->Arguments[5];
Argument6 = (UINT32)UserRsp->Arguments[6];
EnableSMAP ();
if (CoreProtocol == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n"));
return EFI_OUT_OF_RESOURCES;
}

Status = gBS->OpenProtocol (
(VOID *)*((UINTN *)CoreRbp + 3),
CoreProtocol,
&Pointer,
Arg4,
Arg5,
Arg6
);
(EFI_HANDLE)CoreRbp->Argument1,
CoreProtocol,
&Interface,
Argument4,
Argument5,
Argument6
);

if (CompareGuid (CoreProtocol, &gEfiLoadedImageProtocolGuid)) {
MemoryCoreSize = sizeof (EFI_LOADED_IMAGE_PROTOCOL);
} else {
MemoryCoreSize = 0;
}

Pointer = AllocateRing3CopyPages (Pointer, MemoryCoreSize);
if (Pointer == NULL) {
Interface = AllocateRing3CopyPages (Interface, MemoryCoreSize);
if (Interface == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n"));
FreePool (CoreProtocol);
return EFI_OUT_OF_RESOURCES;
}

DisableSMAP ();
*(UINTN *)(*((UINTN *)CoreRbp - 2)) = (UINTN)Pointer;
*(VOID **)CoreRbp->Argument3 = Interface;
EnableSMAP ();

FreePool (CoreProtocol);

return (UINTN)Status;
return Status;

default:
break;
}

return 0;
return EFI_UNSUPPORTED;
}

VOID
Expand Down
89 changes: 40 additions & 49 deletions MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,6 @@ SECTION .text
extern ASM_PFX(CallBootService)
extern ASM_PFX(gCoreSysCallStackTop)

%macro CallSysRet 0
; Prepare SYSRET arguments.
mov rcx, [rbp + 8*4]
pop rdx
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
Expand All @@ -58,7 +30,7 @@ ASM_PFX(EnableSMAP):
ret

;------------------------------------------------------------------------------
; UINTN
; EFI_STATUS
; EFIAPI
; CoreBootServices (
; IN UINT8 Type,
Expand All @@ -71,7 +43,8 @@ ASM_PFX(EnableSMAP):
; (r9) Argument 3 of the called function.
; (r10) Type.
; (r11) RFLAGS saved by SYSCALL in SysCall().
;On stack Argument 4, 5, ...
;
; (On User Stack) Argument 4, 5, ...
;------------------------------------------------------------------------------
global ASM_PFX(CoreBootServices)
ASM_PFX(CoreBootServices):
Expand All @@ -87,32 +60,50 @@ ASM_PFX(CoreBootServices):

; 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], rdx
sub rax, 8
mov [rax], rbp
sub rax, 8
mov [rax], r8
; Save User data segment selector on Core SysCall Stack.
sub rax, 8
mov [rax], r11

mov r8, rsp

mov [rax], rsp
mov rsp, rax

push rbp
; Save return address for SYSRET.
push rcx
; Save User data segment selector.
push r11
; Save User Arguments [1..3].
push r9
push r8
push rdx
mov rbp, rsp

; Prepare CallBootService arguments.
mov rcx, r10
mov rdx, rbp
push r8
push r9
mov r8, [rbp + 8*6]

call ASM_PFX(CallBootService)

CallSysRet
; Step over Arguments [1..3].
add rsp, 8*3

; 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

; Prepare SYSRET arguments.
pop rcx
pushfq
pop r11

; Switch to User Stack.
pop rbp
pop rsp

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

;------------------------------------------------------------------------------
; Routine Description:
Expand Down
2 changes: 1 addition & 1 deletion MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
**/

UINTN
EFI_STATUS
EFIAPI
SysCall (
IN UINT8 Type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,15 +441,15 @@ Ring3OpenProtocol (

EFI_LOADED_IMAGE_PROTOCOL *UserProtocol;

Status = (EFI_STATUS)SysCall (
SysCallOpenProtocol,
CoreUserHandle,
Protocol,
Interface,
CoreImageHandle,
CoreControllerHandle,
Attributes
);
Status = SysCall (
SysCallOpenProtocol,
CoreUserHandle,
Protocol,
Interface,
CoreImageHandle,
CoreControllerHandle,
Attributes
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Ring3: Failed to open protocol %g\n", Protocol));
return Status;
Expand Down Expand Up @@ -528,12 +528,12 @@ Ring3LocateProtocol (

EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol;

Status = (EFI_STATUS)SysCall (
SysCallLocateProtocol,
Protocol,
CoreRegistration,
Interface
);
Status = SysCall (
SysCallLocateProtocol,
Protocol,
CoreRegistration,
Interface
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Ring3: Failed to loacate protocol %g\n", Protocol));
return Status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
SECTION .text

;------------------------------------------------------------------------------
; UINTN
; EFI_STATUS
; EFIAPI
; SysCall (
; IN UINT8 Type,
Expand Down

0 comments on commit 5d084d3

Please sign in to comment.