From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web08.31244.1649045679565934493 for ; Sun, 03 Apr 2022 21:14:41 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=Pq59C6zf; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: ted.kuo@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649045680; x=1680581680; h=from:to:cc:subject:date:message-id; bh=XT50u6nD9W2/QaOXY1eNcN2pY4QLDJAel4IVrtqsE9o=; b=Pq59C6zfW9y4RNv6HhwmAGka1jp7ccE0fjo1cahLvbbPA1XdQ1I2O1Lo oDqaEzytCH/Wd9ei6U/FtCCtf+mKznAaKJW8AWyHh4JNfSNeEVeVsxab0 Ozv/PthAVPMfH7yA6ZZsB4kEObq2K4x4dx0JtFIhZgsybPOIqrPumsRAP P6BCPVA5MrMlMGHWgZRHOgSdUgMZI6ms54Icq8aXal0EhtAMzz5RqHQbt Sb2wZBWX1pbrRxCHoSDd1EgrOReh/QQXUPkWa0L5UbTYhOGgssmuQPzbi w881nGJvydSE1ldumEFbRElZKVh9xG6XstlkMhkv+gOC8d5AbUaz3hdp9 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10306"; a="258015864" X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="258015864" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Apr 2022 21:14:40 -0700 X-IronPort-AV: E=Sophos;i="5.90,233,1643702400"; d="scan'208";a="696444587" Received: from tedkuo1-win10.gar.corp.intel.com ([10.5.215.13]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Apr 2022 21:14:39 -0700 From: "Kuo, Ted" To: devel@edk2.groups.io Cc: Chasel Chiu , Nate DeSimone , Star Zeng , Ashraf Ali S Subject: [edk2-devel][PATCH 4/5] IntelFsp2Pkg: FspSecCore support for X64 Date: Mon, 4 Apr 2022 12:13:59 +0800 Message-Id: <22b5a736d1ff565ebf69b7fc70e43ea741317462.1649045384.git.ted.kuo@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: References: In-Reply-To: References: REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3893 1.Added FspSecCore support for X64. 2.Bumped FSP header revision to 7 to indicate FSP 64bit is supported. Cc: Chasel Chiu Cc: Nate DeSimone Cc: Star Zeng Cc: Ashraf Ali S Signed-off-by: Ted Kuo --- IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf | 8 +- IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf | 9 +- IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf | 8 +- IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf | 10 +- .../FspSecCore/Ia32/FspApiEntryCommon.nasm | 4 +- IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm | 103 +++++ IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm | 76 ++++ IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm | 263 +++++++++++ IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm | 67 +++ IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm | 492 +++++++++++++++++++++ IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm | 34 ++ IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc | 11 + IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm | 22 + IntelFsp2Pkg/FspSecCore/X64/Stack.nasm | 73 +++ IntelFsp2Pkg/Include/Guid/FspHeaderFile.h | 14 +- IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc | 284 ++++++++++++ .../Library/BaseFspCommonLib/FspCommonLib.c | 1 + .../Library/BaseFspSwitchStackLib/X64/Stack.nasm | 5 +- 18 files changed, 1473 insertions(+), 11 deletions(-) create mode 100644 IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc create mode 100644 IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm create mode 100644 IntelFsp2Pkg/FspSecCore/X64/Stack.nasm create mode 100644 IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc diff --git a/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf b/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf index 0a24eb2a8b..d64ec12499 100644 --- a/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf +++ b/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf @@ -17,7 +17,7 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = IA32 +# VALID_ARCHITECTURES = IA32 X64 # [Sources] @@ -30,6 +30,12 @@ Ia32/FspApiEntryCommon.nasm Ia32/FspHelper.nasm +[Sources.X64] + X64/Stack.nasm + X64/Fsp22ApiEntryS.nasm + X64/FspApiEntryCommon.nasm + X64/FspHelper.nasm + [Binaries.Ia32] RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC diff --git a/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf b/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf index 7b05cae641..34794dd16e 100644 --- a/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf +++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf @@ -17,7 +17,7 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = IA32 +# VALID_ARCHITECTURES = IA32 X64 # [Sources] @@ -34,6 +34,13 @@ Ia32/FspHelper.nasm Ia32/ReadEsp.nasm +[Sources.X64] + X64/Stack.nasm + X64/FspApiEntryM.nasm + X64/FspApiEntryCommon.nasm + X64/FspHelper.nasm + X64/ReadRsp.nasm + [Binaries.Ia32] RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC diff --git a/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf b/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf index 1d9c2554d1..79d4e0674e 100644 --- a/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf +++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf @@ -17,7 +17,7 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = IA32 +# VALID_ARCHITECTURES = IA32 X64 # [Sources] @@ -30,6 +30,12 @@ Ia32/FspApiEntryCommon.nasm Ia32/FspHelper.nasm +[Sources.X64] + X64/Stack.nasm + X64/FspApiEntryS.nasm + X64/FspApiEntryCommon.nasm + X64/FspHelper.nasm + [Binaries.Ia32] RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC diff --git a/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf b/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf index 664bde5678..f08a3b2c2b 100644 --- a/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf +++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf @@ -17,17 +17,19 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = IA32 +# VALID_ARCHITECTURES = IA32 X64 # -[Sources] - - [Sources.IA32] Ia32/Stack.nasm Ia32/FspApiEntryT.nasm Ia32/FspHelper.nasm +[Sources.X64] + X64/Stack.nasm + X64/FspApiEntryT.nasm + X64/FspHelper.nasm + [Binaries.Ia32] RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC diff --git a/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm index 26ae7d9fd3..024f7aec5c 100644 --- a/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm +++ b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm @@ -7,6 +7,8 @@ SECTION .text +STACK_SAVED_EAX_OFFSET EQU 4 * 7 ; size of a general purpose register * eax index + ; ; Following functions will be provided in C ; @@ -52,7 +54,7 @@ FspApiCommon1: add esp, 8 cmp eax, 0 jz FspApiCommon2 - mov dword [esp + (4 * 7)], eax + mov dword [esp + STACK_SAVED_EAX_OFFSET], eax popad exit: ret diff --git a/IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm b/IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm new file mode 100644 index 0000000000..c739793a39 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm @@ -0,0 +1,103 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + + SECTION .text + +; +; Following functions will be provided in C +; +extern ASM_PFX(FspApiCommon) +extern ASM_PFX(FspMultiPhaseSiInitApiHandler) + +STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index + +;---------------------------------------------------------------------------- +; NotifyPhase API +; +; This FSP API will notify the FSP about the different phases in the boot +; process +; +;---------------------------------------------------------------------------- +global ASM_PFX(NotifyPhaseApi) +ASM_PFX(NotifyPhaseApi): + mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspSiliconInit API +; +; This FSP API initializes the CPU and the chipset including the IO +; controllers in the chipset to enable normal operation of these devices. +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspSiliconInitApi) +ASM_PFX(FspSiliconInitApi): + mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspMultiPhaseSiInitApi API +; +; This FSP API provides multi-phase silicon initialization, which brings greater +; modularity beyond the existing FspSiliconInit() API. +; Increased modularity is achieved by adding an extra API to FSP-S. +; This allows the bootloader to add board specific initialization steps throughout +; the SiliconInit flow as needed. +; +;---------------------------------------------------------------------------- + +%include "PushPopRegsNasm.inc" + +global ASM_PFX(FspMultiPhaseSiInitApi) +ASM_PFX(FspMultiPhaseSiInitApi): + mov eax, 6 ; FSP_API_INDEX.FspMultiPhaseSiInitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspApiCommonContinue API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommonContinue) +ASM_PFX(FspApiCommonContinue): + ; + ; Handle FspMultiPhaseSiInitApiIndex API + ; + cmp eax, 6 + jnz NotMultiPhaseSiInitApi + + PUSHA_64 + mov rdx, rcx ; move ApiParam to rdx + mov rcx, rax ; move ApiIdx to rcx + call ASM_PFX(FspMultiPhaseSiInitApiHandler) + mov qword [rsp + STACK_SAVED_RAX_OFFSET], rax + POPA_64 + ret + +NotMultiPhaseSiInitApi: + jmp $ + ret + +;---------------------------------------------------------------------------- +; TempRamInit API +; +; Empty function for WHOLEARCHIVE build option +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamInitApi) +ASM_PFX(TempRamInitApi): + jmp $ + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ + diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm new file mode 100644 index 0000000000..718e672e02 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm @@ -0,0 +1,76 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + + SECTION .text + +%include "PushPopRegsNasm.inc" + +STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index + +; +; Following functions will be provided in C +; +extern ASM_PFX(Loader2PeiSwitchStack) +extern ASM_PFX(FspApiCallingCheck) + +; +; Following functions will be provided in ASM +; +extern ASM_PFX(FspApiCommonContinue) +extern ASM_PFX(AsmGetFspInfoHeader) + +;---------------------------------------------------------------------------- +; FspApiCommon API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommon) +ASM_PFX(FspApiCommon): + ; + ; RAX holds the API index + ; + + ; + ; Stack must be ready + ; + push rax + add rsp, 8 + cmp rax, [rsp - 8] + jz FspApiCommon1 + mov rax, 08000000000000003h + jmp exit + +FspApiCommon1: + ; + ; Verify the calling condition + ; + PUSHA_64 + mov rdx, rcx ; move ApiParam to rdx + mov rcx, rax ; move ApiIdx to rcx + call ASM_PFX(FspApiCallingCheck) + cmp rax, 0 + jz FspApiCommon2 + mov [rsp + STACK_SAVED_RAX_OFFSET], rax + POPA_64 +exit: + ret + +FspApiCommon2: + POPA_64 + cmp rax, 3 ; FspMemoryInit API + jz FspApiCommon3 + + cmp rax, 6 ; FspMultiPhaseSiInitApiIndex API + jz FspApiCommon3 + + call ASM_PFX(AsmGetFspInfoHeader) + jmp ASM_PFX(Loader2PeiSwitchStack) + +FspApiCommon3: + jmp ASM_PFX(FspApiCommonContinue) + diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm new file mode 100644 index 0000000000..f149066ad8 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm @@ -0,0 +1,263 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + + SECTION .text + +%include "PushPopRegsNasm.inc" + +; +; Following are fixed PCDs +; +extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage)) + +struc FSPM_UPD_COMMON + ; FSP_UPD_HEADER { + .FspUpdHeader: resd 8 + ; } + ; FSPM_ARCH2_UPD { + .Revision: resb 1 + .Reserved: resb 3 + .Length resd 1 + .StackBase: resq 1 + .StackSize: resq 1 + .BootLoaderTolumSize: resd 1 + .BootMode: resd 1 + .FspEventHandler resq 1 + .EnableMultiPhaseMemoryInit resb 1 + .Reserved1: resb 23 + ; } + .size: +endstruc + +; +; Following functions will be provided in C +; +extern ASM_PFX(SecStartup) +extern ASM_PFX(FspApiCommon) + +; +; Following functions will be provided in PlatformSecLib +; +extern ASM_PFX(AsmGetFspBaseAddress) +extern ASM_PFX(AsmGetFspInfoHeader) + +FSP_HEADER_IMGBASE_OFFSET EQU 1Ch +FSP_HEADER_CFGREG_OFFSET EQU 24h + +;---------------------------------------------------------------------------- +; FspMemoryInit API +; +; This FSP API is called after TempRamInit and initializes the memory. +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspMemoryInitApi) +ASM_PFX(FspMemoryInitApi): + mov eax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; TempRamExitApi API +; +; This API tears down temporary RAM +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamExitApi) +ASM_PFX(TempRamExitApi): + mov eax, 4 ; FSP_API_INDEX.TempRamExitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspApiCommonContinue API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommonContinue) +ASM_PFX(FspApiCommonContinue): + ; + ; RAX holds the API index + ; Push RDX and RCX to form CONTEXT_STACK_64 + ; + push rdx ; Push a QWORD data for stack alignment + push rdx ; Push API Parameter2 on stack + push rcx ; Push API Parameter1 on stack + + ; + ; FspMemoryInit API setup the initial stack frame + ; + + ; + ; Place holder to store the FspInfoHeader pointer + ; + push rax + + ; + ; Update the FspInfoHeader pointer + ; + push rax + call ASM_PFX(AsmGetFspInfoHeader) + mov [rsp + 8], rax + pop rax + + ; + ; Create a Task Frame in the stack for the Boot Loader + ; + pushfq + cli + PUSHA_64 + + ; Reserve 16 bytes for IDT save/restore + sub rsp, 16 + sidt [rsp] + + ; Get Stackbase and StackSize from FSPM_UPD Param + mov rdx, rcx ; Put FSPM_UPD Param to rdx + cmp rdx, 0 + jnz FspStackSetup + + ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null + xchg rbx, rax + call ASM_PFX(AsmGetFspInfoHeader) + mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET] + add edx, [rax + FSP_HEADER_CFGREG_OFFSET] + xchg rbx, rax + +FspStackSetup: + ; + ; StackBase = temp memory base, StackSize = temp memory size + ; + mov rdi, [rdx + FSPM_UPD_COMMON.StackBase] + mov ecx, [rdx + FSPM_UPD_COMMON.StackSize] + + ; + ; Keep using bootloader stack if heap size % is 0 + ; + mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage)) + mov bl, BYTE [rbx] + cmp bl, 0 + jz SkipStackSwitch + + ; + ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0 + ; + add rdi, rcx + ; + ; Switch to new FSP stack + ; + xchg rdi, rsp ; Exchange rdi and rsp, rdi will be assigned to the current rsp pointer and rsp will be Stack base + Stack size + +SkipStackSwitch: + ; + ; If heap size % is 0: + ; EDI is FSPM_UPD_COMMON.StackBase and will hold ESP later (boot loader stack pointer) + ; ECX is FSPM_UPD_COMMON.StackSize + ; ESP is boot loader stack pointer (no stack switch) + ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON.StackBase later) + ; + ; If heap size % is not 0 + ; EDI is boot loader stack pointer + ; ECX is FSPM_UPD_COMMON.StackSize + ; ESP is new stack (FSPM_UPD_COMMON.StackBase + FSPM_UPD_COMMON.StackSize) + ; BL is NOT 0 to indicate stack has switched + ; + cmp bl, 0 + jnz StackHasBeenSwitched + + mov rbx, rdi ; Put FSPM_UPD_COMMON.StackBase to rbx as temp memory base + mov rdi, rsp ; Put boot loader stack pointer to rdi + jmp StackSetupDone + +StackHasBeenSwitched: + mov rbx, rsp ; Put Stack base + Stack size in ebx + sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base + +StackSetupDone: + + ; + ; Per X64 calling convention, make sure RSP is 16-byte aligned. + ; + mov rdx, rsp + and rdx, 0fh + sub rsp, rdx + + ; + ; Pass the API Idx to SecStartup + ; + push rax + + ; + ; Pass the BootLoader stack to SecStartup + ; + push rdi + + ; + ; Pass BFV into the PEI Core + ; It uses relative address to calculate the actual boot FV base + ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and + ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs, + ; they are different. The code below can handle both cases. + ; + call ASM_PFX(AsmGetFspBaseAddress) + mov r8, rax + + ; + ; Pass entry point of the PEI core + ; + call ASM_PFX(AsmGetPeiCoreOffset) + lea r9, [r8 + rax] + + ; + ; Pass stack base and size into the PEI Core + ; + mov rcx, rcx + mov rdx, rbx + + ; + ; Pass Control into the PEI Core + ; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index + ; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before + ; calling the function. + ; + sub rsp, 20h + call ASM_PFX(SecStartup) + add rsp, 20h +exit: + ret + +global ASM_PFX(FspPeiCoreEntryOff) +ASM_PFX(FspPeiCoreEntryOff): + ; + ; This value will be pached by the build script + ; + DD 0x12345678 + +global ASM_PFX(AsmGetPeiCoreOffset) +ASM_PFX(AsmGetPeiCoreOffset): + push rbx + mov rbx, ASM_PFX(FspPeiCoreEntryOff) + mov eax, dword[ebx] + pop rbx + ret + +;---------------------------------------------------------------------------- +; TempRamInit API +; +; Empty function for WHOLEARCHIVE build option +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamInitApi) +ASM_PFX(TempRamInitApi): + jmp $ + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ + diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm new file mode 100644 index 0000000000..f863ef0078 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm @@ -0,0 +1,67 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + + SECTION .text + +; +; Following functions will be provided in C +; +extern ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; NotifyPhase API +; +; This FSP API will notify the FSP about the different phases in the boot +; process +; +;---------------------------------------------------------------------------- +global ASM_PFX(NotifyPhaseApi) +ASM_PFX(NotifyPhaseApi): + mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspSiliconInit API +; +; This FSP API initializes the CPU and the chipset including the IO +; controllers in the chipset to enable normal operation of these devices. +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspSiliconInitApi) +ASM_PFX(FspSiliconInitApi): + mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspApiCommonContinue API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommonContinue) +ASM_PFX(FspApiCommonContinue): + jmp $ + ret + +;---------------------------------------------------------------------------- +; TempRamInit API +; +; Empty function for WHOLEARCHIVE build option +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamInitApi) +ASM_PFX(TempRamInitApi): + jmp $ + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ + diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm new file mode 100644 index 0000000000..1406ba8833 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm @@ -0,0 +1,492 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + + SECTION .text + +%include "SaveRestoreSseAvxNasm.inc" +%include "MicrocodeLoadNasm.inc" + +; +; Following are fixed PCDs +; +extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase)) +extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize)) +extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize)) + +; +; Following functions will be provided in PlatformSecLib +; +extern ASM_PFX(AsmGetFspBaseAddress) +extern ASM_PFX(AsmGetFspInfoHeader) +;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation +extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation +extern ASM_PFX(SecCarInit) + +; +; Define the data length that we saved on the stack top +; +DATA_LEN_OF_PER0 EQU 18h +DATA_LEN_OF_MCUD EQU 18h +DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4) + +; +; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid +; build error. This needs to be fixed later on. +; +struc MicrocodeHdr + .MicrocodeHdrVersion: resd 1 + .MicrocodeHdrRevision: resd 1 + .MicrocodeHdrDate: resd 1 + .MicrocodeHdrProcessor: resd 1 + .MicrocodeHdrChecksum: resd 1 + .MicrocodeHdrLoader: resd 1 + .MicrocodeHdrFlags: resd 1 + .MicrocodeHdrDataSize: resd 1 + .MicrocodeHdrTotalSize: resd 1 + .MicrocodeHdrRsvd: resd 3 + .size: +endstruc + +struc ExtSigHdr + .ExtSigHdrCount: resd 1 + .ExtSigHdrChecksum: resd 1 + .ExtSigHdrRsvd: resd 3 + .size: +endstruc + +struc ExtSig + .ExtSigProcessor: resd 1 + .ExtSigFlags: resd 1 + .ExtSigChecksum: resd 1 + .size: +endstruc + +struc LoadMicrocodeParamsFsp24 + ; FSP_UPD_HEADER { + .FspUpdHeaderSignature: resd 2 + .FspUpdHeaderRevision: resb 1 + .FspUpdHeaderReserved: resb 23 + ; } + ; FSPT_ARCH2_UPD { + .FsptArchRevision: resb 1 + .FsptArchReserved: resb 3 + .FsptArchLength: resd 1 + .FspDebugHandler resq 1 + .MicrocodeCodeAddr: resq 1 + .MicrocodeCodeSize: resq 1 + .CodeRegionBase: resq 1 + .CodeRegionSize: resq 1 + ; } + .size: +endstruc + +; +; @todo: The strong/weak implementation does not work. +; This needs to be reviewed later. +; +;------------------------------------------------------------------------------ +; +;;global ASM_PFX(SecPlatformInitDefault) +;ASM_PFX(SecPlatformInitDefault): +; ; Inputs: +; ; ymm7 -> Return address +; ; Outputs: +; ; rax -> 0 - Successful, Non-zero - Failed. +; ; Register Usage: +; ; rax is cleared and rbp is used for return address. +; ; All others reserved. +; +; ; Save return address to RBP +; LOAD_RBP +; +; xor rax, rax +;Exit1: +; jmp rbp + +;------------------------------------------------------------------------------ +global ASM_PFX(LoadMicrocodeDefault) +ASM_PFX(LoadMicrocodeDefault): + ; Inputs: + ; rsp -> LoadMicrocodeParams pointer + ; Register Usage: + ; rsp Preserved + ; All others destroyed + ; Assumptions: + ; No memory available, stack is hard-coded and used for return address + ; Executed by SBSP and NBSP + ; Beginning of microcode update region starts on paragraph boundary + + ; + ; Save return address to RBP + ; + LOAD_RBP + + cmp rsp, 0 + jz ParamError + mov eax, dword [rsp + 8] ; Parameter pointer + cmp eax, 0 + jz ParamError + mov esp, eax + + ; skip loading Microcode if the MicrocodeCodeSize is zero + ; and report error if size is less than 2k + ; first check UPD header revision + cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2 + jb ParamError + cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2 + jne ParamError + + ; UPD structure is compliant with FSP spec 2.4 + mov eax, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] + cmp eax, 0 + jz Exit2 + cmp eax, 0800h + jl ParamError + + mov esi, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] + cmp esi, 0 + jnz CheckMainHeader + +ParamError: + mov rax, 08000000000000002h + jmp Exit2 + +CheckMainHeader: + ; Get processor signature and platform ID from the installed processor + ; and save into registers for later use + ; ebx = processor signature + ; edx = platform ID + mov eax, 1 + cpuid + mov ebx, eax + mov ecx, MSR_IA32_PLATFORM_ID + rdmsr + mov ecx, edx + shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits + and ecx, 7h ; platform id at bit[52..50] + mov edx, 1 + shl edx, cl + + ; Current register usage + ; esp -> stack with parameters + ; esi -> microcode update to check + ; ebx = processor signature + ; edx = platform ID + + ; Check for valid microcode header + ; Minimal test checking for header version and loader version as 1 + mov eax, dword 1 + cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax + jne AdvanceFixedSize + cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax + jne AdvanceFixedSize + + ; Check if signature and plaform ID match + cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor] + jne LoadMicrocodeDefault1 + test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ] + jnz LoadCheck ; Jif signature and platform ID match + +LoadMicrocodeDefault1: + ; Check if extended header exists + ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid + xor rax, rax + cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax + je NextMicrocode + cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax + je NextMicrocode + + ; Then verify total size - sizeof header > data size + mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize] + sub ecx, MicrocodeHdr.size + cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize] + jng NextMicrocode ; Jif extended header does not exist + + ; Set edi -> extended header + mov edi, esi + add edi, MicrocodeHdr.size + add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize] + + ; Get count of extended structures + mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount] + + ; Move pointer to first signature structure + add edi, ExtSigHdr.size + +CheckExtSig: + ; Check if extended signature and platform ID match + cmp dword [edi + ExtSig.ExtSigProcessor], ebx + jne LoadMicrocodeDefault2 + test dword [edi + ExtSig.ExtSigFlags], edx + jnz LoadCheck ; Jif signature and platform ID match +LoadMicrocodeDefault2: + ; Check if any more extended signatures exist + add edi, ExtSig.size + loop CheckExtSig + +NextMicrocode: + ; Advance just after end of this microcode + xor rax, rax + cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax + je LoadMicrocodeDefault3 + add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize] + jmp CheckAddress +LoadMicrocodeDefault3: + add esi, dword 2048 + jmp CheckAddress + +AdvanceFixedSize: + ; Advance by 4X dwords + add esi, dword 1024 + +CheckAddress: + ; Check UPD header revision + cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2 + jb ParamError + cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2 + jne ParamError + + ; UPD structure is compliant with FSP spec 2.4 + ; Is automatic size detection ? + mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] + cmp rax, 0ffffffffffffffffh + jz LoadMicrocodeDefault4 + + ; Address >= microcode region address + microcode region size? + add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] + cmp rsi, rax + jae Done ;Jif address is outside of microcode region + jmp CheckMainHeader + +LoadMicrocodeDefault4: + ; Is valid Microcode start point ? + cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh + jz Done + +LoadCheck: + ; Get the revision of the current microcode update loaded + mov ecx, MSR_IA32_BIOS_SIGN_ID + xor eax, eax ; Clear EAX + xor edx, edx ; Clear EDX + wrmsr ; Load 0 to MSR at 8Bh + + mov eax, 1 + cpuid + mov ecx, MSR_IA32_BIOS_SIGN_ID + rdmsr ; Get current microcode signature + + ; Verify this microcode update is not already loaded + cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx + je Continue + +LoadMicrocode: + ; EAX contains the linear address of the start of the Update Data + ; EDX contains zero + ; ECX contains 79h (IA32_BIOS_UPDT_TRIG) + ; Start microcode load with wrmsr + mov eax, esi + add eax, MicrocodeHdr.size + xor edx, edx + mov ecx, MSR_IA32_BIOS_UPDT_TRIG + wrmsr + mov eax, 1 + cpuid + +Continue: + jmp NextMicrocode + +Done: + mov eax, 1 + cpuid + mov ecx, MSR_IA32_BIOS_SIGN_ID + rdmsr ; Get current microcode signature + xor eax, eax + cmp edx, 0 + jnz Exit2 + mov eax, 0800000000000000Eh + +Exit2: + jmp rbp + + +global ASM_PFX(EstablishStackFsp) +ASM_PFX(EstablishStackFsp): + ; + ; Save parameter pointer in rdx + ; + mov rdx, qword [rsp + 8] + + ; + ; Enable FSP STACK + ; + mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase)) + mov esp, DWORD[rax] + mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize)) + add esp, DWORD[rax] + + sub esp, 4 + mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region + sub esp, 4 + mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD' + + ; check UPD structure revision (rdx + 8) + cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2 + jb ParamError1 + cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2 + je Fsp24UpdHeader + +ParamError1: + mov rax, 08000000000000002h + jmp EstablishStackFspExit + +Fsp24UpdHeader: + ; UPD structure is compliant with FSP spec 2.4 + xor rax, rax + mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h + sub rsp, 8 + mov qword[rsp], rax + mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h + sub rsp, 8 + mov qword[rsp], rax + mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h + sub rsp, 8 + mov qword[rsp], rax + mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h + sub rsp, 8 + mov qword[rsp], rax + +ContinueAfterUpdPush: + ; + ; Save API entry/exit timestamp into stack + ; + sub esp, 4 + mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region + sub esp, 4 + mov dword[esp], 30524550h ; Signature of the data region 'PER0' + rdtsc + sub esp, 4 + mov dword[esp], edx + sub esp, 4 + mov dword[esp], eax + LOAD_TS rax + push rax + + ; + ; Terminator for the data on stack + ; + push 0 + + ; + ; Set ECX/EDX to the BootLoader temporary memory range + ; + mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase)) + mov edx, [ecx] + mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize)) + add edx, [ecx] + mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize)) + sub edx, [ecx] + mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase)) + mov ecx, [ecx] + + cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error. + jb EstablishStackFspSuccess + mov rax, 08000000000000003h ; EFI_UNSUPPORTED + jmp EstablishStackFspExit +EstablishStackFspSuccess: + xor rax, rax + +EstablishStackFspExit: + RET_YMM + +;---------------------------------------------------------------------------- +; TempRamInit API +; +; This FSP API will load the microcode update, enable code caching for the +; region specified by the boot loader and also setup a temporary stack to be +; used till main memory is initialized. +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamInitApi) +ASM_PFX(TempRamInitApi): + ; + ; Ensure both SSE and AVX are enabled + ; + ENABLE_SSE + ENABLE_AVX + + ; + ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6 + ; + SAVE_REGS + + ; + ; Save BFV address in YMM9 + ; + SAVE_BFV rbp + + ; + ; Save timestamp into YMM6 + ; + rdtsc + shl rdx, 32 + or rax, rdx + SAVE_TS rax + + ; + ; Check Parameter + ; + mov rax, qword [rsp + 8] + cmp rax, 0 + mov rax, 08000000000000002h + jz TempRamInitExit + + ; + ; Sec Platform Init + ; + CALL_YMM ASM_PFX(SecPlatformInit) + cmp eax, 0 + jnz TempRamInitExit + + ; Load microcode + LOAD_RSP + CALL_YMM ASM_PFX(LoadMicrocodeDefault) + SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits). + ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot. + + ; Call Sec CAR Init + LOAD_RSP + CALL_YMM ASM_PFX(SecCarInit) + cmp rax, 0 + jnz TempRamInitExit + + LOAD_RSP + CALL_YMM ASM_PFX(EstablishStackFsp) + cmp rax, 0 + jnz TempRamInitExit + + LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits). + +TempRamInitExit: + mov bl, al ; save al data in bl + mov al, 07Fh ; API exit postcode 7f + out 080h, al + mov al, bl ; restore al data from bl + + ; + ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6 + ; + LOAD_REGS + LOAD_BFV rbp + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ + diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm new file mode 100644 index 0000000000..122fa1d174 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm @@ -0,0 +1,34 @@ +;; @file +; Provide FSP helper function. +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + DEFAULT REL + SECTION .text + +global ASM_PFX(AsmGetFspBaseAddress) +ASM_PFX(AsmGetFspBaseAddress): + call ASM_PFX(AsmGetFspInfoHeader) + add rax, 0x1C + mov eax, [rax] + ret + +global ASM_PFX(AsmGetFspInfoHeader) +ASM_PFX(AsmGetFspInfoHeader): + lea rax, [ASM_PFX(AsmGetFspInfoHeader)] + DB 0x48, 0x2d ; sub rax, 0x???????? +global ASM_PFX(FspInfoHeaderRelativeOff) +ASM_PFX(FspInfoHeaderRelativeOff): + DD 0x12345678 ; This value must be patched by the build script + and rax, 0xffffffff + ret + +global ASM_PFX(AsmGetFspInfoHeaderNoStack) +ASM_PFX(AsmGetFspInfoHeaderNoStack): + lea rax, [ASM_PFX(AsmGetFspInfoHeader)] + lea rcx, [ASM_PFX(FspInfoHeaderRelativeOff)] + mov ecx, [rcx] + sub rax, rcx + and rax, 0xffffffff + jmp rdi diff --git a/IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc b/IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc new file mode 100644 index 0000000000..4ec5070d25 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc @@ -0,0 +1,11 @@ +;; @file +; +;@copyright +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; + +MSR_IA32_PLATFORM_ID equ 000000017h +MSR_IA32_BIOS_UPDT_TRIG equ 000000079h +MSR_IA32_BIOS_SIGN_ID equ 00000008bh + diff --git a/IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm b/IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm new file mode 100644 index 0000000000..af82509803 --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm @@ -0,0 +1,22 @@ +;; @file +; Provide read RSP function +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +;; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadStackPointer ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadStackPointer) +ASM_PFX(AsmReadStackPointer): + mov rax, rsp + ret + diff --git a/IntelFsp2Pkg/FspSecCore/X64/Stack.nasm b/IntelFsp2Pkg/FspSecCore/X64/Stack.nasm new file mode 100644 index 0000000000..0af7f54f6f --- /dev/null +++ b/IntelFsp2Pkg/FspSecCore/X64/Stack.nasm @@ -0,0 +1,73 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Abstract: +; +; Switch the stack from temporary memory to permanent memory. +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; SecSwitchStack ( +; UINT64 TemporaryMemoryBase, +; UINT64 PermanentMemoryBase +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(SecSwitchStack) +ASM_PFX(SecSwitchStack): + ; + ; Save four register: rax, rbx, rcx, rdx + ; + push rax + push rbx + push rcx + push rdx + + ; + ; !!CAUTION!! this function address's is pushed into stack after + ; migration of whole temporary memory, so need save it to permanent + ; memory at first! + ; + + mov rbx, rcx ; Save the first parameter + mov rcx, rdx ; Save the second parameter + + ; + ; Save this function's return address into permanent memory at first. + ; Then, Fixup the esp point to permanent memory + ; + mov rax, rsp + sub rax, rbx + add rax, rcx + mov rdx, qword [rsp] ; copy pushed register's value to permanent memory + mov qword [rax], rdx + mov rdx, qword [rsp + 8] + mov qword [rax + 8], rdx + mov rdx, qword [rsp + 16] + mov qword [rax + 16], rdx + mov rdx, qword [rsp + 24] + mov qword [rax + 24], rdx + mov rdx, qword [rsp + 32] ; Update this function's return address into permanent memory + mov qword [rax + 32], rdx + mov rsp, rax ; From now, rsp is pointed to permanent memory + + ; + ; Fixup the rbp point to permanent memory + ; + mov rax, rbp + sub rax, rbx + add rax, rcx + mov rbp, rax ; From now, rbp is pointed to permanent memory + + pop rdx + pop rcx + pop rbx + pop rax + ret + diff --git a/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h b/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h index e5a9d7a2b4..79ad57116a 100644 --- a/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h +++ b/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h @@ -7,6 +7,8 @@ **/ +#include + #ifndef __FSP_HEADER_FILE_H__ #define __FSP_HEADER_FILE_H__ @@ -24,6 +26,12 @@ #define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H') +#define IMAGE_ATTRIBUTE_GRAPHICS_SUPPORT BIT0 +#define IMAGE_ATTRIBUTE_DISPATCH_MODE_SUPPORT BIT1 +#define IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT BIT2 +#define FSP_IA32 0 +#define FSP_X64 1 + #pragma pack(1) /// @@ -49,7 +57,7 @@ typedef struct { UINT8 SpecVersion; /// /// Byte 0x0B: Revision of the FSP Information Header. - /// The Current value for this field is 0x6. + /// The Current value for this field is 0x7. /// UINT8 HeaderRevision; /// @@ -82,6 +90,10 @@ typedef struct { UINT32 ImageBase; /// /// Byte 0x20: Attribute for the FSP binary. + /// Bit 0: Graphics Support - Set to 1 when FSP supports enabling Graphics Display. + /// Bit 1: Dispatch Mode Support - Set to 1 when FSP supports the optional Dispatch Mode API defined in Section 7.2 and 9. This bit is only valid if FSP HeaderRevision is >= 4. + /// Bit 2: 64-bit mode support - Set to 1 to indicate FSP supports 64-bit long mode interfaces. Set to 0 to indicate FSP supports 32-bit mode interfaces. This bit is only valid if FSP HeaderRevision is >= 7. + /// Bits 15:3 - Reserved /// UINT16 ImageAttribute; /// diff --git a/IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc b/IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc new file mode 100644 index 0000000000..e8bd91669d --- /dev/null +++ b/IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc @@ -0,0 +1,284 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Abstract: +; +; Provide macro for register save/restore using SSE registers +; +;------------------------------------------------------------------------------ + +; +; Define SSE and AVX instruction set +; +; +; Define SSE macros using SSE 4.1 instructions +; args 1:XMM, 2:IDX, 3:REG +; +%macro SXMMN 3 + pinsrq %1, %3, (%2 & 3) + %endmacro + +; +; args 1:XMM, 2:REG, 3:IDX +; +%macro LXMMN 3 + pextrq %2, %1, (%3 & 3) + %endmacro + +; +; Define AVX macros using AVX instructions +; Save XMM to YMM +; args 1:YMM, 2:IDX (0 - lower 128bits, 1 - upper 128bits), 3:XMM +; +%macro SYMMN 3 + vinsertf128 %1, %1, %3, %2 + %endmacro + +; +; Restore XMM from YMM +; args 1:YMM, 2:XMM, 3:IDX (0 - lower 128bits, 1 - upper 128bits) +; +%macro LYMMN 3 + vextractf128 %2, %1, %3 + %endmacro + +; +; Upper half of YMM7 to save RBP and RBX. Upper half of YMM8 to save RSI and RDI. +; Modified: XMM5, YMM6, YMM7 and YMM8 +; +%macro SAVE_REGS 0 + SXMMN xmm5, 0, rbp + SXMMN xmm5, 1, rbx + SYMMN ymm7, 1, xmm5 + SXMMN xmm5, 0, rsi + SXMMN xmm5, 1, rdi + SYMMN ymm8, 1, xmm5 + SAVE_RSP + %endmacro + +; +; Upper half of YMM7 to restore RBP and RBX. Upper half of YMM8 to restore RSI and RDI. +; Modified: XMM5, RBP, RBX, RSI, RDI and RSP +; +%macro LOAD_REGS 0 + LYMMN ymm7, xmm5, 1 + LXMMN xmm5, rbp, 0 + LXMMN xmm5, rbx, 1 + LYMMN ymm8, xmm5, 1 + LXMMN xmm5, rsi, 0 + LXMMN xmm5, rdi, 1 + LOAD_RSP + %endmacro +; +; Restore RBP from YMM7[128:191] +; Modified: XMM5 and RBP +; +%macro LOAD_RBP 0 + LYMMN ymm7, xmm5, 1 + movq rbp, xmm5 + %endmacro + +; +; Restore RBX from YMM7[192:255] +; Modified: XMM5 and RBX +; +%macro LOAD_RBX 0 + LYMMN ymm7, xmm5, 1 + LXMMN xmm5, rbx, 1 + %endmacro + +; +; Upper half of YMM6 to save/restore Time Stamp, RSP +; +; +; Save Time Stamp to YMM6[192:255] +; arg 1:general purpose register which holds time stamp +; Modified: XMM5 and YMM6 +; +%macro SAVE_TS 1 + LYMMN ymm6, xmm5, 1 + SXMMN xmm5, 1, %1 + SYMMN ymm6, 1, xmm5 + %endmacro + +; +; Restore Time Stamp from YMM6[192:255] +; arg 1:general purpose register where to save time stamp +; Modified: XMM5 and %1 +; +%macro LOAD_TS 1 + LYMMN ymm6, xmm5, 1 + LXMMN xmm5, %1, 1 + %endmacro + +; +; Save RSP to YMM6[128:191] +; Modified: XMM5 and YMM6 +; +%macro SAVE_RSP 0 + LYMMN ymm6, xmm5, 1 + SXMMN xmm5, 0, rsp + SYMMN ymm6, 1, xmm5 + %endmacro + +; +; Restore RSP from YMM6[128:191] +; Modified: XMM5 and RSP +; +%macro LOAD_RSP 0 + LYMMN ymm6, xmm5, 1 + movq rsp, xmm5 + %endmacro + +; +; Upper half of YMM9 to save/restore UCODE status, BFV address +; +; +; Save uCode status to YMM9[192:255] +; arg 1:general purpose register which holds uCode status +; Modified: XMM5 and YMM9 +; +%macro SAVE_UCODE_STATUS 1 + LYMMN ymm9, xmm5, 1 + SXMMN xmm5, 0, %1 + SYMMN ymm9, 1, xmm5 + %endmacro + +; +; Restore uCode status from YMM9[192:255] +; arg 1:general purpose register where to save uCode status +; Modified: XMM5 and %1 +; +%macro LOAD_UCODE_STATUS 1 + LYMMN ymm9, xmm5, 1 + movq %1, xmm5 + %endmacro + +; +; Save BFV address to YMM9[128:191] +; arg 1:general purpose register which holds BFV address +; Modified: XMM5 and YMM9 +; +%macro SAVE_BFV 1 + LYMMN ymm9, xmm5, 1 + SXMMN xmm5, 1, %1 + SYMMN ymm9, 1, xmm5 + %endmacro + +; +; Restore BFV address from YMM9[128:191] +; arg 1:general purpose register where to save BFV address +; Modified: XMM5 and %1 +; +%macro LOAD_BFV 1 + LYMMN ymm9, xmm5, 1 + LXMMN xmm5, %1, 1 + %endmacro + +; +; YMM7[128:191] for calling stack +; arg 1:Entry +; Modified: RSI, XMM5, YMM7 +; +%macro CALL_YMM 1 + mov rsi, %%ReturnAddress + LYMMN ymm7, xmm5, 1 + SXMMN xmm5, 0, rsi + SYMMN ymm7, 1, xmm5 + mov rsi, %1 + jmp rsi +%%ReturnAddress: + %endmacro +; +; Restore RIP from YMM7[128:191] +; Modified: RSI, XMM5 +; +%macro RET_YMM 0 + LYMMN ymm7, xmm5, 1 + movq rsi, xmm5 + jmp rsi + %endmacro + +%macro ENABLE_SSE 0 + ; + ; Initialize floating point units + ; + jmp NextAddress +align 4 + ; + ; Float control word initial value: + ; all exceptions masked, double-precision, round-to-nearest + ; +FpuControlWord DW 027Fh + ; + ; Multimedia-extensions control word: + ; all exceptions masked, round-to-nearest, flush to zero for masked underflow + ; +MmxControlWord DQ 01F80h +SseError: + ; + ; Processor has to support SSE + ; + jmp SseError +NextAddress: + finit + mov rax, FpuControlWord + fldcw [rax] + + ; + ; Use CpuId instruction (CPUID.01H:EDX.SSE[bit 25] = 1) to test + ; whether the processor supports SSE instruction. + ; + mov rax, 1 + cpuid + bt rdx, 25 + jnc SseError + + ; + ; SSE 4.1 support + ; + bt ecx, 19 + jnc SseError + + ; + ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) + ; + mov rax, cr4 + or rax, 00000600h + mov cr4, rax + + ; + ; The processor should support SSE instruction and we can use + ; ldmxcsr instruction + ; + mov rax, MmxControlWord + ldmxcsr [rax] + %endmacro + +%macro ENABLE_AVX 0 + mov eax, 1 + cpuid + and ecx, 10000000h + cmp ecx, 10000000h ; check AVX feature flag + je EnableAvx +AvxError: + ; + ; Processor has to support AVX + ; + jmp AvxError +EnableAvx: + ; + ; Set OSXSAVE bit (bit #18) to enable xgetbv/xsetbv instruction + ; + mov rax, cr4 + or rax, 00040000h + mov cr4, rax + + mov rcx, 0 ; index 0 + xgetbv ; result in edx:eax + or eax, 00000006h ; Set XCR0 bit #1 and bit #2 to enable SSE state and AVX state + xsetbv + %endmacro + diff --git a/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c b/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c index cd10b63c95..7aac68bf23 100644 --- a/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c +++ b/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c @@ -54,6 +54,7 @@ typedef struct { UINT32 Flags[2]; UINT64 FspInfoHeader; UINT64 ApiParam[2]; + UINT64 Reserved; // The reserved QWORD is needed for stack alignment in X64. UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention } CONTEXT_STACK_64; diff --git a/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm b/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm index bd36fe4b8b..1ea1220608 100644 --- a/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm +++ b/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm @@ -47,7 +47,8 @@ ASM_PFX(Loader2PeiSwitchStack): ;------------------------------------------------------------------------------ global ASM_PFX(FspSwitchStack) ASM_PFX(FspSwitchStack): - ; Save current contexts + ; 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 @@ -67,6 +68,6 @@ ASM_PFX(FspSwitchStack): add rsp, 16 POPA_64 popfq - add rsp, 24 ; FspInfoHeader + ApiParam[2] + add rsp, 32 ; FspInfoHeader + ApiParam[2] + Reserved QWORD ret -- 2.16.2.windows.1