Ring3: Refactored stack operations.

This commit is contained in:
Mikhail Krichanov 2024-02-05 13:36:43 +03:00
parent 9d5ef4f68e
commit 028342cb6b
6 changed files with 131 additions and 112 deletions

View File

@ -2835,7 +2835,7 @@ SetUefiImageMemoryAttributes (
IN UINT64 Attributes IN UINT64 Attributes
); );
UINTN EFI_STATUS
EFIAPI EFIAPI
CoreBootServices ( CoreBootServices (
IN UINT8 Type, IN UINT8 Type,

View File

@ -32,35 +32,55 @@ InternalEnterUserImage (
IN UINT16 DataSelector 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 EFIAPI
CallBootService ( CallBootService (
IN UINT8 Type, IN UINT8 Type,
IN UINTN CoreRbp, IN CORE_STACK *CoreRbp,
IN UINTN UserRsp IN RING3_STACK *UserRsp
) )
{ {
UINTN Status; EFI_STATUS Status;
VOID *Pointer; UINT64 Attributes;
VOID * Arg4; VOID *Interface;
VOID * Arg5; EFI_GUID *CoreProtocol;
UINT32 Arg6; UINT32 MemoryCoreSize;
EFI_HANDLE Argument4;
EFI_HANDLE Argument5;
UINT32 Argument6;
EFI_GUID *CoreProtocol; gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)UserRsp, &Attributes);
UINT32 MemoryCoreSize; ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
// 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
switch (Type) { switch (Type) {
case SysCallLocateProtocol: case SysCallLocateProtocol:
//
// Argument 1: EFI_GUID *Protocol
// Argument 2: VOID *CoreRegistration
// Argument 3: VOID **Interface
//
DisableSMAP (); DisableSMAP ();
CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)*((UINTN *)CoreRbp + 3)); CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)CoreRbp->Argument1);
EnableSMAP (); EnableSMAP ();
if (CoreProtocol == NULL) { if (CoreProtocol == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n")); DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n"));
@ -68,10 +88,10 @@ CallBootService (
} }
Status = gBS->LocateProtocol ( Status = gBS->LocateProtocol (
CoreProtocol, CoreProtocol,
(VOID *)*((UINTN *)CoreRbp + 1), (VOID *)CoreRbp->Argument2,
&Pointer &Interface
); );
if (CompareGuid (CoreProtocol, &gEfiDevicePathUtilitiesProtocolGuid)) { if (CompareGuid (CoreProtocol, &gEfiDevicePathUtilitiesProtocolGuid)) {
MemoryCoreSize = sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL); MemoryCoreSize = sizeof (EFI_DEVICE_PATH_UTILITIES_PROTOCOL);
@ -79,27 +99,35 @@ CallBootService (
MemoryCoreSize = 0; MemoryCoreSize = 0;
} }
Pointer = AllocateRing3CopyPages (Pointer, MemoryCoreSize); Interface = AllocateRing3CopyPages (Interface, MemoryCoreSize);
if (Pointer == NULL) { if (Interface == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n")); DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n"));
FreePool (CoreProtocol); FreePool (CoreProtocol);
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }
DisableSMAP (); DisableSMAP ();
*(UINTN *)(*((UINTN *)CoreRbp - 2)) = (UINTN)Pointer; *(VOID **)CoreRbp->Argument3 = Interface;
EnableSMAP (); EnableSMAP ();
FreePool (CoreProtocol); FreePool (CoreProtocol);
return (UINTN)Status; return Status;
case SysCallOpenProtocol: 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 (); DisableSMAP ();
CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)*((UINTN *)CoreRbp + 1)); CoreProtocol = AllocateCopyPool (sizeof (EFI_GUID), (VOID *)CoreRbp->Argument2);
Arg4 = (VOID *)*((UINTN *)UserRsp + 5); Argument4 = (EFI_HANDLE)UserRsp->Arguments[4];
Arg5 = (VOID *)*((UINTN *)UserRsp + 6); Argument5 = (EFI_HANDLE)UserRsp->Arguments[5];
Arg6 = (UINT32)*((UINTN *)UserRsp + 7); Argument6 = (UINT32)UserRsp->Arguments[6];
EnableSMAP (); EnableSMAP ();
if (CoreProtocol == NULL) { if (CoreProtocol == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n")); DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate core copy of the Protocol variable.\n"));
@ -107,13 +135,13 @@ CallBootService (
} }
Status = gBS->OpenProtocol ( Status = gBS->OpenProtocol (
(VOID *)*((UINTN *)CoreRbp + 3), (EFI_HANDLE)CoreRbp->Argument1,
CoreProtocol, CoreProtocol,
&Pointer, &Interface,
Arg4, Argument4,
Arg5, Argument5,
Arg6 Argument6
); );
if (CompareGuid (CoreProtocol, &gEfiLoadedImageProtocolGuid)) { if (CompareGuid (CoreProtocol, &gEfiLoadedImageProtocolGuid)) {
MemoryCoreSize = sizeof (EFI_LOADED_IMAGE_PROTOCOL); MemoryCoreSize = sizeof (EFI_LOADED_IMAGE_PROTOCOL);
@ -121,26 +149,26 @@ CallBootService (
MemoryCoreSize = 0; MemoryCoreSize = 0;
} }
Pointer = AllocateRing3CopyPages (Pointer, MemoryCoreSize); Interface = AllocateRing3CopyPages (Interface, MemoryCoreSize);
if (Pointer == NULL) { if (Interface == NULL) {
DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n")); DEBUG ((DEBUG_ERROR, "Ring0: Failed to allocate pages for Ring3 PROTOCOL structure.\n"));
FreePool (CoreProtocol); FreePool (CoreProtocol);
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }
DisableSMAP (); DisableSMAP ();
*(UINTN *)(*((UINTN *)CoreRbp - 2)) = (UINTN)Pointer; *(VOID **)CoreRbp->Argument3 = Interface;
EnableSMAP (); EnableSMAP ();
FreePool (CoreProtocol); FreePool (CoreProtocol);
return (UINTN)Status; return Status;
default: default:
break; break;
} }
return 0; return EFI_UNSUPPORTED;
} }
VOID VOID

View File

@ -11,34 +11,6 @@ SECTION .text
extern ASM_PFX(CallBootService) extern ASM_PFX(CallBootService)
extern ASM_PFX(gCoreSysCallStackTop) 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) global ASM_PFX(DisableSMAP)
ASM_PFX(DisableSMAP): ASM_PFX(DisableSMAP):
pushfq pushfq
@ -58,7 +30,7 @@ ASM_PFX(EnableSMAP):
ret ret
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
; UINTN ; EFI_STATUS
; EFIAPI ; EFIAPI
; CoreBootServices ( ; CoreBootServices (
; IN UINT8 Type, ; IN UINT8 Type,
@ -71,7 +43,8 @@ ASM_PFX(EnableSMAP):
; (r9) Argument 3 of the called function. ; (r9) Argument 3 of the called function.
; (r10) Type. ; (r10) Type.
; (r11) RFLAGS saved by SYSCALL in SysCall(). ; (r11) RFLAGS saved by SYSCALL in SysCall().
;On stack Argument 4, 5, ... ;
; (On User Stack) Argument 4, 5, ...
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
global ASM_PFX(CoreBootServices) global ASM_PFX(CoreBootServices)
ASM_PFX(CoreBootServices): ASM_PFX(CoreBootServices):
@ -87,32 +60,50 @@ ASM_PFX(CoreBootServices):
; Save User Stack pointers and switch to Core SysCall Stack. ; Save User Stack pointers and switch to Core SysCall Stack.
mov rax, [ASM_PFX(gCoreSysCallStackTop)] mov rax, [ASM_PFX(gCoreSysCallStackTop)]
; Save return address for SYSRET.
sub rax, 8 sub rax, 8
mov [rax], rcx mov [rax], rsp
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 rsp, rax mov rsp, rax
push rbp
mov rbp, rsp ; Save return address for SYSRET.
mov rdx, rbp push rcx
push r8 ; Save User data segment selector.
push r11
; Save User Arguments [1..3].
push r9 push r9
push r8
push rdx
mov rbp, rsp
; Prepare CallBootService arguments.
mov rcx, r10
mov rdx, rbp
mov r8, [rbp + 8*6]
call ASM_PFX(CallBootService) 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: ; Routine Description:

View File

@ -5,7 +5,7 @@
**/ **/
UINTN EFI_STATUS
EFIAPI EFIAPI
SysCall ( SysCall (
IN UINT8 Type, IN UINT8 Type,

View File

@ -441,15 +441,15 @@ Ring3OpenProtocol (
EFI_LOADED_IMAGE_PROTOCOL *UserProtocol; EFI_LOADED_IMAGE_PROTOCOL *UserProtocol;
Status = (EFI_STATUS)SysCall ( Status = SysCall (
SysCallOpenProtocol, SysCallOpenProtocol,
CoreUserHandle, CoreUserHandle,
Protocol, Protocol,
Interface, Interface,
CoreImageHandle, CoreImageHandle,
CoreControllerHandle, CoreControllerHandle,
Attributes Attributes
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Ring3: Failed to open protocol %g\n", Protocol)); DEBUG ((DEBUG_ERROR, "Ring3: Failed to open protocol %g\n", Protocol));
return Status; return Status;
@ -528,12 +528,12 @@ Ring3LocateProtocol (
EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol; EFI_DEVICE_PATH_UTILITIES_PROTOCOL *UserProtocol;
Status = (EFI_STATUS)SysCall ( Status = SysCall (
SysCallLocateProtocol, SysCallLocateProtocol,
Protocol, Protocol,
CoreRegistration, CoreRegistration,
Interface Interface
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Ring3: Failed to loacate protocol %g\n", Protocol)); DEBUG ((DEBUG_ERROR, "Ring3: Failed to loacate protocol %g\n", Protocol));
return Status; return Status;

View File

@ -7,7 +7,7 @@
SECTION .text SECTION .text
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
; UINTN ; EFI_STATUS
; EFIAPI ; EFIAPI
; SysCall ( ; SysCall (
; IN UINT8 Type, ; IN UINT8 Type,