audk/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

76 lines
2.0 KiB
NASM
Raw Normal View History

;------------------------------------------------------------------------------
;
IntelFsp2Pkg/SwitchStack: Reserve 32B when calling C function in 64bit When FSP runs in API mode, it saves the IDTR in its own stack then switches to bootloader's stack before it returns from FspMemoryInit. Next time when the bootloader calls TempRamExit, FSP switches to its own stack and restores IDTR from its stack saved earlier. However, due to a bug in BaseFspSwitchStackLib, the IDTR saved on FSP's stack might be corrupted that results the following TempRamExit call fails inside FSP due to PeiServices pointer cannot be retrieved from IDT.base - 8. The bug is the assembly code doesn't reserve 32 bytes before calling the C routine in 64bit. According to the x86-64 calling convention, caller is responsible for allocating 32 bytes of "shadow space" on the stack right before calling the function (regardless of the actual number of parameters used). When FSP is built in optimization-off mode, the C routine makes use of the 32-byte "shadow space" which is not reserved by the assembly caller. That causes the IDTR saved on the stack is corrupted by the C routine. The patch fixes so by reserving the 32 bytes before calling C routine. Signed-off-by: Ray Ni <ray.ni@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Duggapu Chinni B <chinni.b.duggapu@intel.com> Cc: Ray Han Lim Ng <ray.han.lim.ng@intel.com> Cc: Star Zeng <star.zeng@intel.com> Reviewed-by: Ted Kuo <ted.kuo@intel.com> Reviewed-by: Ashraf Ali S <ashraf.ali.s@intel.com> Cc: Susovan Mohapatra <susovan.mohapatra@intel.com>
2023-10-31 09:22:16 +01:00
; Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Abstract:
;
; Switch the stack from temporary memory to permanent memory.
;
;------------------------------------------------------------------------------
SECTION .text
%include "PushPopRegsNasm.inc"
extern ASM_PFX(SwapStack)
;------------------------------------------------------------------------------
; UINT32
; EFIAPI
; Pei2LoaderSwitchStack (
; VOID
; )
;------------------------------------------------------------------------------
global ASM_PFX(Pei2LoaderSwitchStack)
ASM_PFX(Pei2LoaderSwitchStack):
xor rax, rax
jmp ASM_PFX(FspSwitchStack)
;------------------------------------------------------------------------------
; UINT32
; EFIAPI
; Loader2PeiSwitchStack (
; VOID
; )
;------------------------------------------------------------------------------
global ASM_PFX(Loader2PeiSwitchStack)
ASM_PFX(Loader2PeiSwitchStack):
jmp ASM_PFX(FspSwitchStack)
;------------------------------------------------------------------------------
; UINT32
; EFIAPI
; FspSwitchStack (
; VOID
; )
;------------------------------------------------------------------------------
global ASM_PFX(FspSwitchStack)
ASM_PFX(FspSwitchStack):
; Save current contexts. The format must align with CONTEXT_STACK_64.
push rdx ; Reserved QWORD for stack alignment
push rdx ; ApiParam2
push rcx ; ApiParam1
push rax ; FspInfoHeader
pushfq
cli
PUSHA_64
sub rsp, 16
sidt [rsp]
; Load new stack
mov rcx, rsp
IntelFsp2Pkg/SwitchStack: Reserve 32B when calling C function in 64bit When FSP runs in API mode, it saves the IDTR in its own stack then switches to bootloader's stack before it returns from FspMemoryInit. Next time when the bootloader calls TempRamExit, FSP switches to its own stack and restores IDTR from its stack saved earlier. However, due to a bug in BaseFspSwitchStackLib, the IDTR saved on FSP's stack might be corrupted that results the following TempRamExit call fails inside FSP due to PeiServices pointer cannot be retrieved from IDT.base - 8. The bug is the assembly code doesn't reserve 32 bytes before calling the C routine in 64bit. According to the x86-64 calling convention, caller is responsible for allocating 32 bytes of "shadow space" on the stack right before calling the function (regardless of the actual number of parameters used). When FSP is built in optimization-off mode, the C routine makes use of the 32-byte "shadow space" which is not reserved by the assembly caller. That causes the IDTR saved on the stack is corrupted by the C routine. The patch fixes so by reserving the 32 bytes before calling C routine. Signed-off-by: Ray Ni <ray.ni@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Duggapu Chinni B <chinni.b.duggapu@intel.com> Cc: Ray Han Lim Ng <ray.han.lim.ng@intel.com> Cc: Star Zeng <star.zeng@intel.com> Reviewed-by: Ted Kuo <ted.kuo@intel.com> Reviewed-by: Ashraf Ali S <ashraf.ali.s@intel.com> Cc: Susovan Mohapatra <susovan.mohapatra@intel.com>
2023-10-31 09:22:16 +01:00
sub rsp, 0x20
call ASM_PFX(SwapStack)
IntelFsp2Pkg/SwitchStack: Reserve 32B when calling C function in 64bit When FSP runs in API mode, it saves the IDTR in its own stack then switches to bootloader's stack before it returns from FspMemoryInit. Next time when the bootloader calls TempRamExit, FSP switches to its own stack and restores IDTR from its stack saved earlier. However, due to a bug in BaseFspSwitchStackLib, the IDTR saved on FSP's stack might be corrupted that results the following TempRamExit call fails inside FSP due to PeiServices pointer cannot be retrieved from IDT.base - 8. The bug is the assembly code doesn't reserve 32 bytes before calling the C routine in 64bit. According to the x86-64 calling convention, caller is responsible for allocating 32 bytes of "shadow space" on the stack right before calling the function (regardless of the actual number of parameters used). When FSP is built in optimization-off mode, the C routine makes use of the 32-byte "shadow space" which is not reserved by the assembly caller. That causes the IDTR saved on the stack is corrupted by the C routine. The patch fixes so by reserving the 32 bytes before calling C routine. Signed-off-by: Ray Ni <ray.ni@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Duggapu Chinni B <chinni.b.duggapu@intel.com> Cc: Ray Han Lim Ng <ray.han.lim.ng@intel.com> Cc: Star Zeng <star.zeng@intel.com> Reviewed-by: Ted Kuo <ted.kuo@intel.com> Reviewed-by: Ashraf Ali S <ashraf.ali.s@intel.com> Cc: Susovan Mohapatra <susovan.mohapatra@intel.com>
2023-10-31 09:22:16 +01:00
add rsp, 0x20
mov rsp, rax
; Restore previous contexts
lidt [rsp]
add rsp, 16
POPA_64
popfq
add rsp, 32 ; FspInfoHeader + ApiParam[2] + Reserved QWORD
ret