mirror of https://github.com/acidanthera/audk.git
Ring3: Refactored stack operations.
This commit is contained in:
parent
fd478cb534
commit
a746842957
|
@ -2823,7 +2823,7 @@ SetUefiImageMemoryAttributes (
|
|||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreBootServices (
|
||||
IN UINT8 Type,
|
||||
|
|
|
@ -32,35 +32,55 @@ 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_STATUS Status;
|
||||
UINT64 Attributes;
|
||||
VOID *Interface;
|
||||
EFI_GUID *CoreProtocol;
|
||||
UINT32 MemoryCoreSize;
|
||||
EFI_HANDLE Argument4;
|
||||
EFI_HANDLE Argument5;
|
||||
UINT32 Argument6;
|
||||
|
||||
EFI_GUID *CoreProtocol;
|
||||
UINT32 MemoryCoreSize;
|
||||
gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)UserRsp, &Attributes);
|
||||
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) {
|
||||
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"));
|
||||
|
@ -68,10 +88,10 @@ CallBootService (
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -79,27 +99,35 @@ CallBootService (
|
|||
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"));
|
||||
|
@ -107,13 +135,13 @@ CallBootService (
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -121,26 +149,26 @@ CallBootService (
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
@ -58,7 +30,7 @@ ASM_PFX(EnableSMAP):
|
|||
ret
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; UINTN
|
||||
; EFI_STATUS
|
||||
; EFIAPI
|
||||
; CoreBootServices (
|
||||
; IN UINT8 Type,
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
mov rbp, rsp
|
||||
mov rdx, rbp
|
||||
push r8
|
||||
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
|
||||
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:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
**/
|
||||
|
||||
UINTN
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SysCall (
|
||||
IN UINT8 Type,
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
SECTION .text
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; UINTN
|
||||
; EFI_STATUS
|
||||
; EFIAPI
|
||||
; SysCall (
|
||||
; IN UINT8 Type,
|
||||
|
|
Loading…
Reference in New Issue