## @file\r
# Sec Core for FSP to support MultiPhase (SeparatePhase) SiInitialization.\r
#\r
-# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
#\r
# The following information is for reference only and not required by the build tools.\r
#\r
-# VALID_ARCHITECTURES = IA32\r
+# VALID_ARCHITECTURES = IA32 X64\r
#\r
\r
[Sources]\r
Ia32/FspApiEntryCommon.nasm\r
Ia32/FspHelper.nasm\r
\r
+[Sources.X64]\r
+ X64/Stack.nasm\r
+ X64/Fsp22ApiEntryS.nasm\r
+ X64/FspApiEntryCommon.nasm\r
+ X64/FspHelper.nasm\r
+\r
[Binaries.Ia32]\r
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC\r
\r
## @file\r
# Sec Core for FSP\r
#\r
-# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
#\r
# The following information is for reference only and not required by the build tools.\r
#\r
-# VALID_ARCHITECTURES = IA32\r
+# VALID_ARCHITECTURES = IA32 X64\r
#\r
\r
[Sources]\r
Ia32/FspHelper.nasm\r
Ia32/ReadEsp.nasm\r
\r
+[Sources.X64]\r
+ X64/Stack.nasm\r
+ X64/FspApiEntryM.nasm\r
+ X64/FspApiEntryCommon.nasm\r
+ X64/FspHelper.nasm\r
+ X64/ReadRsp.nasm\r
+\r
[Binaries.Ia32]\r
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC\r
\r
## @file\r
# Sec Core for FSP\r
#\r
-# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
#\r
# The following information is for reference only and not required by the build tools.\r
#\r
-# VALID_ARCHITECTURES = IA32\r
+# VALID_ARCHITECTURES = IA32 X64\r
#\r
\r
[Sources]\r
Ia32/FspApiEntryCommon.nasm\r
Ia32/FspHelper.nasm\r
\r
+[Sources.X64]\r
+ X64/Stack.nasm\r
+ X64/FspApiEntryS.nasm\r
+ X64/FspApiEntryCommon.nasm\r
+ X64/FspHelper.nasm\r
+\r
[Binaries.Ia32]\r
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC\r
\r
## @file\r
# Sec Core for FSP\r
#\r
-# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
#\r
# The following information is for reference only and not required by the build tools.\r
#\r
-# VALID_ARCHITECTURES = IA32\r
+# VALID_ARCHITECTURES = IA32 X64\r
#\r
\r
-[Sources]\r
-\r
-\r
[Sources.IA32]\r
Ia32/Stack.nasm\r
Ia32/FspApiEntryT.nasm\r
Ia32/FspHelper.nasm\r
\r
+[Sources.X64]\r
+ X64/Stack.nasm\r
+ X64/FspApiEntryT.nasm\r
+ X64/FspHelper.nasm\r
+\r
[Binaries.Ia32]\r
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC\r
\r
;; @file\r
; Provide FSP API entry points.\r
;\r
-; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>\r
; SPDX-License-Identifier: BSD-2-Clause-Patent\r
;;\r
\r
SECTION .text\r
\r
+STACK_SAVED_EAX_OFFSET EQU 4 * 7 ; size of a general purpose register * eax index\r
+\r
;\r
; Following functions will be provided in C\r
;\r
add esp, 8\r
cmp eax, 0\r
jz FspApiCommon2\r
- mov dword [esp + (4 * 7)], eax\r
+ mov dword [esp + STACK_SAVED_EAX_OFFSET], eax\r
popad\r
exit:\r
ret\r
--- /dev/null
+;; @file\r
+; Provide FSP API entry points.\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+\r
+ SECTION .text\r
+\r
+;\r
+; Following functions will be provided in C\r
+;\r
+extern ASM_PFX(FspApiCommon)\r
+extern ASM_PFX(FspMultiPhaseSiInitApiHandler)\r
+\r
+STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index\r
+\r
+;----------------------------------------------------------------------------\r
+; NotifyPhase API\r
+;\r
+; This FSP API will notify the FSP about the different phases in the boot\r
+; process\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(NotifyPhaseApi)\r
+ASM_PFX(NotifyPhaseApi):\r
+ mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspSiliconInit API\r
+;\r
+; This FSP API initializes the CPU and the chipset including the IO\r
+; controllers in the chipset to enable normal operation of these devices.\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspSiliconInitApi)\r
+ASM_PFX(FspSiliconInitApi):\r
+ mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspMultiPhaseSiInitApi API\r
+;\r
+; This FSP API provides multi-phase silicon initialization, which brings greater\r
+; modularity beyond the existing FspSiliconInit() API.\r
+; Increased modularity is achieved by adding an extra API to FSP-S.\r
+; This allows the bootloader to add board specific initialization steps throughout\r
+; the SiliconInit flow as needed.\r
+;\r
+;----------------------------------------------------------------------------\r
+\r
+%include "PushPopRegsNasm.inc"\r
+\r
+global ASM_PFX(FspMultiPhaseSiInitApi)\r
+ASM_PFX(FspMultiPhaseSiInitApi):\r
+ mov eax, 6 ; FSP_API_INDEX.FspMultiPhaseSiInitApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspApiCommonContinue API\r
+;\r
+; This is the FSP API common entry point to resume the FSP execution\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspApiCommonContinue)\r
+ASM_PFX(FspApiCommonContinue):\r
+ ;\r
+ ; Handle FspMultiPhaseSiInitApiIndex API\r
+ ;\r
+ cmp eax, 6\r
+ jnz NotMultiPhaseSiInitApi\r
+\r
+ PUSHA_64\r
+ mov rdx, rcx ; move ApiParam to rdx\r
+ mov rcx, rax ; move ApiIdx to rcx\r
+ call ASM_PFX(FspMultiPhaseSiInitApiHandler)\r
+ mov qword [rsp + STACK_SAVED_RAX_OFFSET], rax\r
+ POPA_64\r
+ ret\r
+\r
+NotMultiPhaseSiInitApi:\r
+ jmp $\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; TempRamInit API\r
+;\r
+; Empty function for WHOLEARCHIVE build option\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(TempRamInitApi)\r
+ASM_PFX(TempRamInitApi):\r
+ jmp $\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; Module Entrypoint API\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+ jmp $\r
+\r
--- /dev/null
+;; @file\r
+; Provide FSP API entry points.\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+\r
+ SECTION .text\r
+\r
+%include "PushPopRegsNasm.inc"\r
+\r
+STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index\r
+\r
+;\r
+; Following functions will be provided in C\r
+;\r
+extern ASM_PFX(Loader2PeiSwitchStack)\r
+extern ASM_PFX(FspApiCallingCheck)\r
+\r
+;\r
+; Following functions will be provided in ASM\r
+;\r
+extern ASM_PFX(FspApiCommonContinue)\r
+extern ASM_PFX(AsmGetFspInfoHeader)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspApiCommon API\r
+;\r
+; This is the FSP API common entry point to resume the FSP execution\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspApiCommon)\r
+ASM_PFX(FspApiCommon):\r
+ ;\r
+ ; RAX holds the API index\r
+ ;\r
+\r
+ ;\r
+ ; Stack must be ready\r
+ ;\r
+ push rax\r
+ add rsp, 8\r
+ cmp rax, [rsp - 8]\r
+ jz FspApiCommon1\r
+ mov rax, 08000000000000003h\r
+ jmp exit\r
+\r
+FspApiCommon1:\r
+ ;\r
+ ; Verify the calling condition\r
+ ;\r
+ PUSHA_64\r
+ mov rdx, rcx ; move ApiParam to rdx\r
+ mov rcx, rax ; move ApiIdx to rcx\r
+ call ASM_PFX(FspApiCallingCheck)\r
+ cmp rax, 0\r
+ jz FspApiCommon2\r
+ mov [rsp + STACK_SAVED_RAX_OFFSET], rax\r
+ POPA_64\r
+exit:\r
+ ret\r
+\r
+FspApiCommon2:\r
+ POPA_64\r
+ cmp rax, 3 ; FspMemoryInit API\r
+ jz FspApiCommon3\r
+\r
+ cmp rax, 6 ; FspMultiPhaseSiInitApiIndex API\r
+ jz FspApiCommon3\r
+\r
+ call ASM_PFX(AsmGetFspInfoHeader)\r
+ jmp ASM_PFX(Loader2PeiSwitchStack)\r
+\r
+FspApiCommon3:\r
+ jmp ASM_PFX(FspApiCommonContinue)\r
+\r
--- /dev/null
+;; @file\r
+; Provide FSP API entry points.\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+\r
+ SECTION .text\r
+\r
+%include "PushPopRegsNasm.inc"\r
+\r
+;\r
+; Following are fixed PCDs\r
+;\r
+extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
+\r
+struc FSPM_UPD_COMMON_FSP24\r
+ ; FSP_UPD_HEADER {\r
+ .FspUpdHeader: resd 8\r
+ ; }\r
+ ; FSPM_ARCH2_UPD {\r
+ .Revision: resb 1\r
+ .Reserved: resb 3\r
+ .Length resd 1\r
+ .StackBase: resq 1\r
+ .StackSize: resq 1\r
+ .BootLoaderTolumSize: resd 1\r
+ .BootMode: resd 1\r
+ .FspEventHandler resq 1\r
+ .Reserved1: resb 24\r
+ ; }\r
+ .size:\r
+endstruc\r
+\r
+;\r
+; Following functions will be provided in C\r
+;\r
+extern ASM_PFX(SecStartup)\r
+extern ASM_PFX(FspApiCommon)\r
+\r
+;\r
+; Following functions will be provided in PlatformSecLib\r
+;\r
+extern ASM_PFX(AsmGetFspBaseAddress)\r
+extern ASM_PFX(AsmGetFspInfoHeader)\r
+\r
+FSP_HEADER_IMGBASE_OFFSET EQU 1Ch\r
+FSP_HEADER_CFGREG_OFFSET EQU 24h\r
+\r
+;----------------------------------------------------------------------------\r
+; FspMemoryInit API\r
+;\r
+; This FSP API is called after TempRamInit and initializes the memory.\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspMemoryInitApi)\r
+ASM_PFX(FspMemoryInitApi):\r
+ mov eax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; TempRamExitApi API\r
+;\r
+; This API tears down temporary RAM\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(TempRamExitApi)\r
+ASM_PFX(TempRamExitApi):\r
+ mov eax, 4 ; FSP_API_INDEX.TempRamExitApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspApiCommonContinue API\r
+;\r
+; This is the FSP API common entry point to resume the FSP execution\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspApiCommonContinue)\r
+ASM_PFX(FspApiCommonContinue):\r
+ ;\r
+ ; RAX holds the API index\r
+ ; Push RDX and RCX to form CONTEXT_STACK_64\r
+ ;\r
+ push rdx ; Push a QWORD data for stack alignment\r
+ push rdx ; Push API Parameter2 on stack\r
+ push rcx ; Push API Parameter1 on stack\r
+\r
+ ;\r
+ ; FspMemoryInit API setup the initial stack frame\r
+ ;\r
+\r
+ ;\r
+ ; Place holder to store the FspInfoHeader pointer\r
+ ;\r
+ push rax\r
+\r
+ ;\r
+ ; Update the FspInfoHeader pointer\r
+ ;\r
+ push rax\r
+ call ASM_PFX(AsmGetFspInfoHeader)\r
+ mov [rsp + 8], rax\r
+ pop rax\r
+\r
+ ;\r
+ ; Create a Task Frame in the stack for the Boot Loader\r
+ ;\r
+ pushfq\r
+ cli\r
+ PUSHA_64\r
+\r
+ ; Reserve 16 bytes for IDT save/restore\r
+ sub rsp, 16\r
+ sidt [rsp]\r
+\r
+ ; Get Stackbase and StackSize from FSPM_UPD Param\r
+ mov rdx, rcx ; Put FSPM_UPD Param to rdx\r
+ cmp rdx, 0\r
+ jnz FspStackSetup\r
+\r
+ ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null\r
+ xchg rbx, rax\r
+ call ASM_PFX(AsmGetFspInfoHeader)\r
+ mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET]\r
+ add edx, [rax + FSP_HEADER_CFGREG_OFFSET]\r
+ xchg rbx, rax\r
+\r
+FspStackSetup:\r
+ mov cl, [rdx + FSPM_UPD_COMMON_FSP24.Revision]\r
+ cmp cl, 3\r
+ jae FspmUpdCommonFsp24\r
+\r
+ mov rax, 08000000000000002h ; RETURN_INVALID_PARAMETER\r
+ sub rsp, 0b8h\r
+ ret\r
+\r
+FspmUpdCommonFsp24:\r
+ ;\r
+ ; StackBase = temp memory base, StackSize = temp memory size\r
+ ;\r
+ mov rdi, [rdx + FSPM_UPD_COMMON_FSP24.StackBase]\r
+ mov ecx, [rdx + FSPM_UPD_COMMON_FSP24.StackSize]\r
+\r
+ ;\r
+ ; Keep using bootloader stack if heap size % is 0\r
+ ;\r
+ mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
+ mov bl, BYTE [rbx]\r
+ cmp bl, 0\r
+ jz SkipStackSwitch\r
+\r
+ ;\r
+ ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0\r
+ ;\r
+ add rdi, rcx\r
+ ;\r
+ ; Switch to new FSP stack\r
+ ;\r
+ xchg rdi, rsp ; Exchange rdi and rsp, rdi will be assigned to the current rsp pointer and rsp will be Stack base + Stack size\r
+\r
+SkipStackSwitch:\r
+ ;\r
+ ; If heap size % is 0:\r
+ ; EDI is FSPM_UPD_COMMON_FSP24.StackBase and will hold ESP later (boot loader stack pointer)\r
+ ; ECX is FSPM_UPD_COMMON_FSP24.StackSize\r
+ ; ESP is boot loader stack pointer (no stack switch)\r
+ ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON_FSP24.StackBase later)\r
+ ;\r
+ ; If heap size % is not 0\r
+ ; EDI is boot loader stack pointer\r
+ ; ECX is FSPM_UPD_COMMON_FSP24.StackSize\r
+ ; ESP is new stack (FSPM_UPD_COMMON_FSP24.StackBase + FSPM_UPD_COMMON_FSP24.StackSize)\r
+ ; BL is NOT 0 to indicate stack has switched\r
+ ;\r
+ cmp bl, 0\r
+ jnz StackHasBeenSwitched\r
+\r
+ mov rbx, rdi ; Put FSPM_UPD_COMMON_FSP24.StackBase to rbx as temp memory base\r
+ mov rdi, rsp ; Put boot loader stack pointer to rdi\r
+ jmp StackSetupDone\r
+\r
+StackHasBeenSwitched:\r
+ mov rbx, rsp ; Put Stack base + Stack size in ebx\r
+ sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base\r
+\r
+StackSetupDone:\r
+\r
+ ;\r
+ ; Per X64 calling convention, make sure RSP is 16-byte aligned.\r
+ ;\r
+ mov rdx, rsp\r
+ and rdx, 0fh\r
+ sub rsp, rdx\r
+\r
+ ;\r
+ ; Pass the API Idx to SecStartup\r
+ ;\r
+ push rax\r
+\r
+ ;\r
+ ; Pass the BootLoader stack to SecStartup\r
+ ;\r
+ push rdi\r
+\r
+ ;\r
+ ; Pass BFV into the PEI Core\r
+ ; It uses relative address to calculate the actual boot FV base\r
+ ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and\r
+ ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs,\r
+ ; they are different. The code below can handle both cases.\r
+ ;\r
+ call ASM_PFX(AsmGetFspBaseAddress)\r
+ mov r8, rax\r
+\r
+ ;\r
+ ; Pass entry point of the PEI core\r
+ ;\r
+ call ASM_PFX(AsmGetPeiCoreOffset)\r
+ lea r9, [r8 + rax]\r
+\r
+ ;\r
+ ; Pass stack base and size into the PEI Core\r
+ ;\r
+ mov rcx, rcx\r
+ mov rdx, rbx\r
+\r
+ ;\r
+ ; Pass Control into the PEI Core\r
+ ; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index\r
+ ; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before\r
+ ; calling the function.\r
+ ;\r
+ sub rsp, 20h\r
+ call ASM_PFX(SecStartup)\r
+ add rsp, 20h\r
+exit:\r
+ ret\r
+\r
+global ASM_PFX(FspPeiCoreEntryOff)\r
+ASM_PFX(FspPeiCoreEntryOff):\r
+ ;\r
+ ; This value will be patched by the build script\r
+ ;\r
+ DD 0x12345678\r
+\r
+global ASM_PFX(AsmGetPeiCoreOffset)\r
+ASM_PFX(AsmGetPeiCoreOffset):\r
+ push rbx\r
+ mov rbx, ASM_PFX(FspPeiCoreEntryOff)\r
+ mov eax, dword[ebx]\r
+ pop rbx\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; TempRamInit API\r
+;\r
+; Empty function for WHOLEARCHIVE build option\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(TempRamInitApi)\r
+ASM_PFX(TempRamInitApi):\r
+ jmp $\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; Module Entrypoint API\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+ jmp $\r
+\r
--- /dev/null
+;; @file\r
+; Provide FSP API entry points.\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+\r
+ SECTION .text\r
+\r
+;\r
+; Following functions will be provided in C\r
+;\r
+extern ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; NotifyPhase API\r
+;\r
+; This FSP API will notify the FSP about the different phases in the boot\r
+; process\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(NotifyPhaseApi)\r
+ASM_PFX(NotifyPhaseApi):\r
+ mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspSiliconInit API\r
+;\r
+; This FSP API initializes the CPU and the chipset including the IO\r
+; controllers in the chipset to enable normal operation of these devices.\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspSiliconInitApi)\r
+ASM_PFX(FspSiliconInitApi):\r
+ mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\r
+\r
+;----------------------------------------------------------------------------\r
+; FspApiCommonContinue API\r
+;\r
+; This is the FSP API common entry point to resume the FSP execution\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspApiCommonContinue)\r
+ASM_PFX(FspApiCommonContinue):\r
+ jmp $\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; TempRamInit API\r
+;\r
+; Empty function for WHOLEARCHIVE build option\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(TempRamInitApi)\r
+ASM_PFX(TempRamInitApi):\r
+ jmp $\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; Module Entrypoint API\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+ jmp $\r
+\r
--- /dev/null
+;; @file\r
+; Provide FSP API entry points.\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+\r
+ SECTION .text\r
+\r
+%include "SaveRestoreSseAvxNasm.inc"\r
+%include "MicrocodeLoadNasm.inc"\r
+\r
+;\r
+; Following are fixed PCDs\r
+;\r
+extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
+extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))\r
+extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))\r
+\r
+;\r
+; Following functions will be provided in PlatformSecLib\r
+;\r
+extern ASM_PFX(AsmGetFspBaseAddress)\r
+extern ASM_PFX(AsmGetFspInfoHeader)\r
+;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation\r
+extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation\r
+extern ASM_PFX(SecCarInit)\r
+\r
+;\r
+; Define the data length that we saved on the stack top\r
+;\r
+DATA_LEN_OF_PER0 EQU 18h\r
+DATA_LEN_OF_MCUD EQU 18h\r
+DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
+\r
+;\r
+; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid\r
+; build error. This needs to be fixed later on.\r
+;\r
+struc MicrocodeHdr\r
+ .MicrocodeHdrVersion: resd 1\r
+ .MicrocodeHdrRevision: resd 1\r
+ .MicrocodeHdrDate: resd 1\r
+ .MicrocodeHdrProcessor: resd 1\r
+ .MicrocodeHdrChecksum: resd 1\r
+ .MicrocodeHdrLoader: resd 1\r
+ .MicrocodeHdrFlags: resd 1\r
+ .MicrocodeHdrDataSize: resd 1\r
+ .MicrocodeHdrTotalSize: resd 1\r
+ .MicrocodeHdrRsvd: resd 3\r
+ .size:\r
+endstruc\r
+\r
+struc ExtSigHdr\r
+ .ExtSigHdrCount: resd 1\r
+ .ExtSigHdrChecksum: resd 1\r
+ .ExtSigHdrRsvd: resd 3\r
+ .size:\r
+endstruc\r
+\r
+struc ExtSig\r
+ .ExtSigProcessor: resd 1\r
+ .ExtSigFlags: resd 1\r
+ .ExtSigChecksum: resd 1\r
+ .size:\r
+endstruc\r
+\r
+struc LoadMicrocodeParamsFsp24\r
+ ; FSP_UPD_HEADER {\r
+ .FspUpdHeaderSignature: resd 2\r
+ .FspUpdHeaderRevision: resb 1\r
+ .FspUpdHeaderReserved: resb 23\r
+ ; }\r
+ ; FSPT_ARCH2_UPD {\r
+ .FsptArchRevision: resb 1\r
+ .FsptArchReserved: resb 3\r
+ .FsptArchLength: resd 1\r
+ .FspDebugHandler resq 1\r
+ .FsptArchUpd: resd 4\r
+ ; }\r
+ ; FSPT_CORE_UPD {\r
+ .MicrocodeCodeAddr: resq 1\r
+ .MicrocodeCodeSize: resq 1\r
+ .CodeRegionBase: resq 1\r
+ .CodeRegionSize: resq 1\r
+ ; }\r
+ .size:\r
+endstruc\r
+\r
+;\r
+; @todo: The strong/weak implementation does not work.\r
+; This needs to be reviewed later.\r
+;\r
+;------------------------------------------------------------------------------\r
+;\r
+;;global ASM_PFX(SecPlatformInitDefault)\r
+;ASM_PFX(SecPlatformInitDefault):\r
+; ; Inputs:\r
+; ; ymm7 -> Return address\r
+; ; Outputs:\r
+; ; rax -> 0 - Successful, Non-zero - Failed.\r
+; ; Register Usage:\r
+; ; rax is cleared and rbp is used for return address.\r
+; ; All others reserved.\r
+;\r
+; ; Save return address to RBP\r
+; LOAD_RBP\r
+;\r
+; xor rax, rax\r
+;Exit1:\r
+; jmp rbp\r
+\r
+;------------------------------------------------------------------------------\r
+global ASM_PFX(LoadMicrocodeDefault)\r
+ASM_PFX(LoadMicrocodeDefault):\r
+ ; Inputs:\r
+ ; rsp -> LoadMicrocodeParams pointer\r
+ ; Register Usage:\r
+ ; rsp Preserved\r
+ ; All others destroyed\r
+ ; Assumptions:\r
+ ; No memory available, stack is hard-coded and used for return address\r
+ ; Executed by SBSP and NBSP\r
+ ; Beginning of microcode update region starts on paragraph boundary\r
+\r
+ ;\r
+ ; Save return address to RBP\r
+ ;\r
+ LOAD_RBP\r
+\r
+ cmp rsp, 0\r
+ jz ParamError\r
+ mov eax, dword [rsp + 8] ; Parameter pointer\r
+ cmp eax, 0\r
+ jz ParamError\r
+ mov esp, eax\r
+\r
+ ; skip loading Microcode if the MicrocodeCodeSize is zero\r
+ ; and report error if size is less than 2k\r
+ ; first check UPD header revision\r
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2\r
+ jb ParamError\r
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2\r
+ jne ParamError\r
+\r
+ ; UPD structure is compliant with FSP spec 2.4\r
+ mov eax, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]\r
+ cmp eax, 0\r
+ jz Exit2\r
+ cmp eax, 0800h\r
+ jl ParamError\r
+\r
+ mov esi, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]\r
+ cmp esi, 0\r
+ jnz CheckMainHeader\r
+\r
+ParamError:\r
+ mov rax, 08000000000000002h\r
+ jmp Exit2\r
+\r
+CheckMainHeader:\r
+ ; Get processor signature and platform ID from the installed processor\r
+ ; and save into registers for later use\r
+ ; ebx = processor signature\r
+ ; edx = platform ID\r
+ mov eax, 1\r
+ cpuid\r
+ mov ebx, eax\r
+ mov ecx, MSR_IA32_PLATFORM_ID\r
+ rdmsr\r
+ mov ecx, edx\r
+ shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits\r
+ and ecx, 7h ; platform id at bit[52..50]\r
+ mov edx, 1\r
+ shl edx, cl\r
+\r
+ ; Current register usage\r
+ ; esp -> stack with parameters\r
+ ; esi -> microcode update to check\r
+ ; ebx = processor signature\r
+ ; edx = platform ID\r
+\r
+ ; Check for valid microcode header\r
+ ; Minimal test checking for header version and loader version as 1\r
+ mov eax, dword 1\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax\r
+ jne AdvanceFixedSize\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax\r
+ jne AdvanceFixedSize\r
+\r
+ ; Check if signature and plaform ID match\r
+ cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]\r
+ jne LoadMicrocodeDefault1\r
+ test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]\r
+ jnz LoadCheck ; Jif signature and platform ID match\r
+\r
+LoadMicrocodeDefault1:\r
+ ; Check if extended header exists\r
+ ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
+ xor rax, rax\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
+ je NextMicrocode\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax\r
+ je NextMicrocode\r
+\r
+ ; Then verify total size - sizeof header > data size\r
+ mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
+ sub ecx, MicrocodeHdr.size\r
+ cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
+ jng NextMicrocode ; Jif extended header does not exist\r
+\r
+ ; Set edi -> extended header\r
+ mov edi, esi\r
+ add edi, MicrocodeHdr.size\r
+ add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
+\r
+ ; Get count of extended structures\r
+ mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]\r
+\r
+ ; Move pointer to first signature structure\r
+ add edi, ExtSigHdr.size\r
+\r
+CheckExtSig:\r
+ ; Check if extended signature and platform ID match\r
+ cmp dword [edi + ExtSig.ExtSigProcessor], ebx\r
+ jne LoadMicrocodeDefault2\r
+ test dword [edi + ExtSig.ExtSigFlags], edx\r
+ jnz LoadCheck ; Jif signature and platform ID match\r
+LoadMicrocodeDefault2:\r
+ ; Check if any more extended signatures exist\r
+ add edi, ExtSig.size\r
+ loop CheckExtSig\r
+\r
+NextMicrocode:\r
+ ; Advance just after end of this microcode\r
+ xor rax, rax\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
+ je LoadMicrocodeDefault3\r
+ add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
+ jmp CheckAddress\r
+LoadMicrocodeDefault3:\r
+ add esi, dword 2048\r
+ jmp CheckAddress\r
+\r
+AdvanceFixedSize:\r
+ ; Advance by 4X dwords\r
+ add esi, dword 1024\r
+\r
+CheckAddress:\r
+ ; Check UPD header revision\r
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2\r
+ jb ParamError\r
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2\r
+ jne ParamError\r
+\r
+ ; UPD structure is compliant with FSP spec 2.4\r
+ ; Is automatic size detection ?\r
+ mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]\r
+ cmp rax, 0ffffffffffffffffh\r
+ jz LoadMicrocodeDefault4\r
+\r
+ ; Address >= microcode region address + microcode region size?\r
+ add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]\r
+ cmp rsi, rax\r
+ jae Done ;Jif address is outside of microcode region\r
+ jmp CheckMainHeader\r
+\r
+LoadMicrocodeDefault4:\r
+ ; Is valid Microcode start point ?\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh\r
+ jz Done\r
+\r
+LoadCheck:\r
+ ; Get the revision of the current microcode update loaded\r
+ mov ecx, MSR_IA32_BIOS_SIGN_ID\r
+ xor eax, eax ; Clear EAX\r
+ xor edx, edx ; Clear EDX\r
+ wrmsr ; Load 0 to MSR at 8Bh\r
+\r
+ mov eax, 1\r
+ cpuid\r
+ mov ecx, MSR_IA32_BIOS_SIGN_ID\r
+ rdmsr ; Get current microcode signature\r
+\r
+ ; Verify this microcode update is not already loaded\r
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx\r
+ je Continue\r
+\r
+LoadMicrocode:\r
+ ; EAX contains the linear address of the start of the Update Data\r
+ ; EDX contains zero\r
+ ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
+ ; Start microcode load with wrmsr\r
+ mov eax, esi\r
+ add eax, MicrocodeHdr.size\r
+ xor edx, edx\r
+ mov ecx, MSR_IA32_BIOS_UPDT_TRIG\r
+ wrmsr\r
+ mov eax, 1\r
+ cpuid\r
+\r
+Continue:\r
+ jmp NextMicrocode\r
+\r
+Done:\r
+ mov eax, 1\r
+ cpuid\r
+ mov ecx, MSR_IA32_BIOS_SIGN_ID\r
+ rdmsr ; Get current microcode signature\r
+ xor eax, eax\r
+ cmp edx, 0\r
+ jnz Exit2\r
+ mov eax, 0800000000000000Eh\r
+\r
+Exit2:\r
+ jmp rbp\r
+\r
+\r
+global ASM_PFX(EstablishStackFsp)\r
+ASM_PFX(EstablishStackFsp):\r
+ ;\r
+ ; Save parameter pointer in rdx\r
+ ;\r
+ mov rdx, qword [rsp + 8]\r
+\r
+ ;\r
+ ; Enable FSP STACK\r
+ ;\r
+ mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
+ mov esp, DWORD[rax]\r
+ mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))\r
+ add esp, DWORD[rax]\r
+\r
+ sub esp, 4\r
+ mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region\r
+ sub esp, 4\r
+ mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'\r
+\r
+ ; check UPD structure revision (rdx + 8)\r
+ cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2\r
+ jb ParamError1\r
+ cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2\r
+ je Fsp24UpdHeader\r
+\r
+ParamError1:\r
+ mov rax, 08000000000000002h\r
+ jmp EstablishStackFspExit\r
+\r
+Fsp24UpdHeader:\r
+ ; UPD structure is compliant with FSP spec 2.4\r
+ xor rax, rax\r
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h\r
+ sub rsp, 8\r
+ mov qword[rsp], rax\r
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h\r
+ sub rsp, 8\r
+ mov qword[rsp], rax\r
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h\r
+ sub rsp, 8\r
+ mov qword[rsp], rax\r
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h\r
+ sub rsp, 8\r
+ mov qword[rsp], rax\r
+\r
+ContinueAfterUpdPush:\r
+ ;\r
+ ; Save API entry/exit timestamp into stack\r
+ ;\r
+ sub esp, 4\r
+ mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region\r
+ sub esp, 4\r
+ mov dword[esp], 30524550h ; Signature of the data region 'PER0'\r
+ rdtsc\r
+ sub esp, 4\r
+ mov dword[esp], edx\r
+ sub esp, 4\r
+ mov dword[esp], eax\r
+ LOAD_TS rax\r
+ push rax\r
+\r
+ ;\r
+ ; Terminator for the data on stack\r
+ ;\r
+ push 0\r
+\r
+ ;\r
+ ; Set ECX/EDX to the BootLoader temporary memory range\r
+ ;\r
+ mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
+ mov edx, [ecx]\r
+ mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))\r
+ add edx, [ecx]\r
+ mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))\r
+ sub edx, [ecx]\r
+ mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
+ mov ecx, [ecx]\r
+\r
+ cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.\r
+ jb EstablishStackFspSuccess\r
+ mov rax, 08000000000000003h ; EFI_UNSUPPORTED\r
+ jmp EstablishStackFspExit\r
+EstablishStackFspSuccess:\r
+ xor rax, rax\r
+\r
+EstablishStackFspExit:\r
+ RET_YMM\r
+\r
+;----------------------------------------------------------------------------\r
+; TempRamInit API\r
+;\r
+; This FSP API will load the microcode update, enable code caching for the\r
+; region specified by the boot loader and also setup a temporary stack to be\r
+; used till main memory is initialized.\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(TempRamInitApi)\r
+ASM_PFX(TempRamInitApi):\r
+ ;\r
+ ; Ensure both SSE and AVX are enabled\r
+ ;\r
+ ENABLE_SSE\r
+ ENABLE_AVX\r
+\r
+ ;\r
+ ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6\r
+ ;\r
+ SAVE_REGS\r
+\r
+ ;\r
+ ; Save BFV address in YMM9\r
+ ;\r
+ SAVE_BFV rbp\r
+\r
+ ;\r
+ ; Save timestamp into YMM6\r
+ ;\r
+ rdtsc\r
+ shl rdx, 32\r
+ or rax, rdx\r
+ SAVE_TS rax\r
+\r
+ ;\r
+ ; Check Parameter\r
+ ;\r
+ mov rax, qword [rsp + 8]\r
+ cmp rax, 0\r
+ mov rax, 08000000000000002h\r
+ jz TempRamInitExit\r
+\r
+ ;\r
+ ; Sec Platform Init\r
+ ;\r
+ CALL_YMM ASM_PFX(SecPlatformInit)\r
+ cmp eax, 0\r
+ jnz TempRamInitExit\r
+\r
+ ; Load microcode\r
+ LOAD_RSP\r
+ CALL_YMM ASM_PFX(LoadMicrocodeDefault)\r
+ SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).\r
+ ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.\r
+\r
+ ; Call Sec CAR Init\r
+ LOAD_RSP\r
+ CALL_YMM ASM_PFX(SecCarInit)\r
+ cmp rax, 0\r
+ jnz TempRamInitExit\r
+\r
+ LOAD_RSP\r
+ CALL_YMM ASM_PFX(EstablishStackFsp)\r
+ cmp rax, 0\r
+ jnz TempRamInitExit\r
+\r
+ LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).\r
+\r
+TempRamInitExit:\r
+ mov bl, al ; save al data in bl\r
+ mov al, 07Fh ; API exit postcode 7f\r
+ out 080h, al\r
+ mov al, bl ; restore al data from bl\r
+\r
+ ;\r
+ ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6\r
+ ;\r
+ LOAD_REGS\r
+ LOAD_BFV rbp\r
+ ret\r
+\r
+;----------------------------------------------------------------------------\r
+; Module Entrypoint API\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+ jmp $\r
+\r
--- /dev/null
+;; @file\r
+; Provide FSP helper function.\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+ DEFAULT REL\r
+ SECTION .text\r
+\r
+global ASM_PFX(AsmGetFspBaseAddress)\r
+ASM_PFX(AsmGetFspBaseAddress):\r
+ call ASM_PFX(AsmGetFspInfoHeader)\r
+ add rax, 0x1C\r
+ mov eax, [rax]\r
+ ret\r
+\r
+global ASM_PFX(AsmGetFspInfoHeader)\r
+ASM_PFX(AsmGetFspInfoHeader):\r
+ lea rax, [ASM_PFX(AsmGetFspInfoHeader)]\r
+ DB 0x48, 0x2d ; sub rax, 0x????????\r
+global ASM_PFX(FspInfoHeaderRelativeOff)\r
+ASM_PFX(FspInfoHeaderRelativeOff):\r
+ DD 0x12345678 ; This value must be patched by the build script\r
+ and rax, 0xffffffff\r
+ ret\r
+\r
+global ASM_PFX(AsmGetFspInfoHeaderNoStack)\r
+ASM_PFX(AsmGetFspInfoHeaderNoStack):\r
+ lea rax, [ASM_PFX(AsmGetFspInfoHeader)]\r
+ lea rcx, [ASM_PFX(FspInfoHeaderRelativeOff)]\r
+ mov ecx, [rcx]\r
+ sub rax, rcx\r
+ and rax, 0xffffffff\r
+ jmp rdi\r
--- /dev/null
+;; @file\r
+;\r
+;@copyright\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+\r
+MSR_IA32_PLATFORM_ID equ 000000017h\r
+MSR_IA32_BIOS_UPDT_TRIG equ 000000079h\r
+MSR_IA32_BIOS_SIGN_ID equ 00000008bh\r
+\r
--- /dev/null
+;; @file\r
+; Provide read RSP function\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;;\r
+;------------------------------------------------------------------------------\r
+\r
+ SECTION .text\r
+\r
+;------------------------------------------------------------------------------\r
+; UINTN\r
+; EFIAPI\r
+; AsmReadStackPointer (\r
+; VOID\r
+; );\r
+;------------------------------------------------------------------------------\r
+global ASM_PFX(AsmReadStackPointer)\r
+ASM_PFX(AsmReadStackPointer):\r
+ mov rax, rsp\r
+ ret\r
+\r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;\r
+; Abstract:\r
+;\r
+; Switch the stack from temporary memory to permanent memory.\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+ SECTION .text\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; EFIAPI\r
+; SecSwitchStack (\r
+; UINT64 TemporaryMemoryBase,\r
+; UINT64 PermanentMemoryBase\r
+; );\r
+;------------------------------------------------------------------------------\r
+global ASM_PFX(SecSwitchStack)\r
+ASM_PFX(SecSwitchStack):\r
+ ;\r
+ ; Save four register: rax, rbx, rcx, rdx\r
+ ;\r
+ push rax\r
+ push rbx\r
+ push rcx\r
+ push rdx\r
+\r
+ ;\r
+ ; !!CAUTION!! this function address's is pushed into stack after\r
+ ; migration of whole temporary memory, so need save it to permanent\r
+ ; memory at first!\r
+ ;\r
+\r
+ mov rbx, rcx ; Save the first parameter\r
+ mov rcx, rdx ; Save the second parameter\r
+\r
+ ;\r
+ ; Save this function's return address into permanent memory at first.\r
+ ; Then, Fixup the esp point to permanent memory\r
+ ;\r
+ mov rax, rsp\r
+ sub rax, rbx\r
+ add rax, rcx\r
+ mov rdx, qword [rsp] ; copy pushed register's value to permanent memory\r
+ mov qword [rax], rdx\r
+ mov rdx, qword [rsp + 8]\r
+ mov qword [rax + 8], rdx\r
+ mov rdx, qword [rsp + 16]\r
+ mov qword [rax + 16], rdx\r
+ mov rdx, qword [rsp + 24]\r
+ mov qword [rax + 24], rdx\r
+ mov rdx, qword [rsp + 32] ; Update this function's return address into permanent memory\r
+ mov qword [rax + 32], rdx\r
+ mov rsp, rax ; From now, rsp is pointed to permanent memory\r
+\r
+ ;\r
+ ; Fixup the rbp point to permanent memory\r
+ ;\r
+ mov rax, rbp\r
+ sub rax, rbx\r
+ add rax, rcx\r
+ mov rbp, rax ; From now, rbp is pointed to permanent memory\r
+\r
+ pop rdx\r
+ pop rcx\r
+ pop rbx\r
+ pop rax\r
+ ret\r
+\r
Intel FSP Header File definition from Intel Firmware Support Package External\r
Architecture Specification v2.0 and above.\r
\r
- Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
+#include <Base.h>\r
+\r
#ifndef __FSP_HEADER_FILE_H__\r
#define __FSP_HEADER_FILE_H__\r
\r
\r
#define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H')\r
\r
+#define IMAGE_ATTRIBUTE_GRAPHICS_SUPPORT BIT0\r
+#define IMAGE_ATTRIBUTE_DISPATCH_MODE_SUPPORT BIT1\r
+#define IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT BIT2\r
+#define FSP_IA32 0\r
+#define FSP_X64 1\r
+\r
#pragma pack(1)\r
\r
///\r
UINT8 SpecVersion;\r
///\r
/// Byte 0x0B: Revision of the FSP Information Header.\r
- /// The Current value for this field is 0x6.\r
+ /// The Current value for this field is 0x7.\r
///\r
UINT8 HeaderRevision;\r
///\r
UINT32 ImageBase;\r
///\r
/// Byte 0x20: Attribute for the FSP binary.\r
+ /// Bit 0: Graphics Support - Set to 1 when FSP supports enabling Graphics Display.\r
+ /// 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.\r
+ /// 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.\r
+ /// Bits 15:3 - Reserved\r
///\r
UINT16 ImageAttribute;\r
///\r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+; SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;\r
+; Abstract:\r
+;\r
+; Provide macro for register save/restore using SSE registers\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+;\r
+; Define SSE and AVX instruction set\r
+;\r
+;\r
+; Define SSE macros using SSE 4.1 instructions\r
+; args 1:XMM, 2:IDX, 3:REG\r
+;\r
+%macro SXMMN 3\r
+ pinsrq %1, %3, (%2 & 3)\r
+ %endmacro\r
+\r
+;\r
+; args 1:XMM, 2:REG, 3:IDX\r
+;\r
+%macro LXMMN 3\r
+ pextrq %2, %1, (%3 & 3)\r
+ %endmacro\r
+\r
+;\r
+; Define AVX macros using AVX instructions\r
+; Save XMM to YMM\r
+; args 1:YMM, 2:IDX (0 - lower 128bits, 1 - upper 128bits), 3:XMM\r
+;\r
+%macro SYMMN 3\r
+ vinsertf128 %1, %1, %3, %2\r
+ %endmacro\r
+\r
+;\r
+; Restore XMM from YMM\r
+; args 1:YMM, 2:XMM, 3:IDX (0 - lower 128bits, 1 - upper 128bits)\r
+;\r
+%macro LYMMN 3\r
+ vextractf128 %2, %1, %3\r
+ %endmacro\r
+\r
+;\r
+; Upper half of YMM7 to save RBP and RBX. Upper half of YMM8 to save RSI and RDI.\r
+; Modified: XMM5, YMM6, YMM7 and YMM8\r
+;\r
+%macro SAVE_REGS 0\r
+ SXMMN xmm5, 0, rbp\r
+ SXMMN xmm5, 1, rbx\r
+ SYMMN ymm7, 1, xmm5\r
+ SXMMN xmm5, 0, rsi\r
+ SXMMN xmm5, 1, rdi\r
+ SYMMN ymm8, 1, xmm5\r
+ SAVE_RSP\r
+ %endmacro\r
+\r
+;\r
+; Upper half of YMM7 to restore RBP and RBX. Upper half of YMM8 to restore RSI and RDI.\r
+; Modified: XMM5, RBP, RBX, RSI, RDI and RSP\r
+;\r
+%macro LOAD_REGS 0\r
+ LYMMN ymm7, xmm5, 1\r
+ LXMMN xmm5, rbp, 0\r
+ LXMMN xmm5, rbx, 1\r
+ LYMMN ymm8, xmm5, 1\r
+ LXMMN xmm5, rsi, 0\r
+ LXMMN xmm5, rdi, 1\r
+ LOAD_RSP\r
+ %endmacro\r
+;\r
+; Restore RBP from YMM7[128:191]\r
+; Modified: XMM5 and RBP\r
+;\r
+%macro LOAD_RBP 0\r
+ LYMMN ymm7, xmm5, 1\r
+ movq rbp, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Restore RBX from YMM7[192:255]\r
+; Modified: XMM5 and RBX\r
+;\r
+%macro LOAD_RBX 0\r
+ LYMMN ymm7, xmm5, 1\r
+ LXMMN xmm5, rbx, 1\r
+ %endmacro\r
+\r
+;\r
+; Upper half of YMM6 to save/restore Time Stamp, RSP\r
+;\r
+;\r
+; Save Time Stamp to YMM6[192:255]\r
+; arg 1:general purpose register which holds time stamp\r
+; Modified: XMM5 and YMM6\r
+;\r
+%macro SAVE_TS 1\r
+ LYMMN ymm6, xmm5, 1\r
+ SXMMN xmm5, 1, %1\r
+ SYMMN ymm6, 1, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Restore Time Stamp from YMM6[192:255]\r
+; arg 1:general purpose register where to save time stamp\r
+; Modified: XMM5 and %1\r
+;\r
+%macro LOAD_TS 1\r
+ LYMMN ymm6, xmm5, 1\r
+ LXMMN xmm5, %1, 1\r
+ %endmacro\r
+\r
+;\r
+; Save RSP to YMM6[128:191]\r
+; Modified: XMM5 and YMM6\r
+;\r
+%macro SAVE_RSP 0\r
+ LYMMN ymm6, xmm5, 1\r
+ SXMMN xmm5, 0, rsp\r
+ SYMMN ymm6, 1, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Restore RSP from YMM6[128:191]\r
+; Modified: XMM5 and RSP\r
+;\r
+%macro LOAD_RSP 0\r
+ LYMMN ymm6, xmm5, 1\r
+ movq rsp, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Upper half of YMM9 to save/restore UCODE status, BFV address\r
+;\r
+;\r
+; Save uCode status to YMM9[192:255]\r
+; arg 1:general purpose register which holds uCode status\r
+; Modified: XMM5 and YMM9\r
+;\r
+%macro SAVE_UCODE_STATUS 1\r
+ LYMMN ymm9, xmm5, 1\r
+ SXMMN xmm5, 0, %1\r
+ SYMMN ymm9, 1, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Restore uCode status from YMM9[192:255]\r
+; arg 1:general purpose register where to save uCode status\r
+; Modified: XMM5 and %1\r
+;\r
+%macro LOAD_UCODE_STATUS 1\r
+ LYMMN ymm9, xmm5, 1\r
+ movq %1, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Save BFV address to YMM9[128:191]\r
+; arg 1:general purpose register which holds BFV address\r
+; Modified: XMM5 and YMM9\r
+;\r
+%macro SAVE_BFV 1\r
+ LYMMN ymm9, xmm5, 1\r
+ SXMMN xmm5, 1, %1\r
+ SYMMN ymm9, 1, xmm5\r
+ %endmacro\r
+\r
+;\r
+; Restore BFV address from YMM9[128:191]\r
+; arg 1:general purpose register where to save BFV address\r
+; Modified: XMM5 and %1\r
+;\r
+%macro LOAD_BFV 1\r
+ LYMMN ymm9, xmm5, 1\r
+ LXMMN xmm5, %1, 1\r
+ %endmacro\r
+\r
+;\r
+; YMM7[128:191] for calling stack\r
+; arg 1:Entry\r
+; Modified: RSI, XMM5, YMM7\r
+;\r
+%macro CALL_YMM 1\r
+ mov rsi, %%ReturnAddress\r
+ LYMMN ymm7, xmm5, 1\r
+ SXMMN xmm5, 0, rsi\r
+ SYMMN ymm7, 1, xmm5\r
+ mov rsi, %1\r
+ jmp rsi\r
+%%ReturnAddress:\r
+ %endmacro\r
+;\r
+; Restore RIP from YMM7[128:191]\r
+; Modified: RSI, XMM5\r
+;\r
+%macro RET_YMM 0\r
+ LYMMN ymm7, xmm5, 1\r
+ movq rsi, xmm5\r
+ jmp rsi\r
+ %endmacro\r
+\r
+%macro ENABLE_SSE 0\r
+ ;\r
+ ; Initialize floating point units\r
+ ;\r
+ jmp NextAddress\r
+align 4\r
+ ;\r
+ ; Float control word initial value:\r
+ ; all exceptions masked, double-precision, round-to-nearest\r
+ ;\r
+FpuControlWord DW 027Fh\r
+ ;\r
+ ; Multimedia-extensions control word:\r
+ ; all exceptions masked, round-to-nearest, flush to zero for masked underflow\r
+ ;\r
+MmxControlWord DQ 01F80h\r
+SseError:\r
+ ;\r
+ ; Processor has to support SSE\r
+ ;\r
+ jmp SseError\r
+NextAddress:\r
+ finit\r
+ mov rax, FpuControlWord\r
+ fldcw [rax]\r
+\r
+ ;\r
+ ; Use CpuId instruction (CPUID.01H:EDX.SSE[bit 25] = 1) to test\r
+ ; whether the processor supports SSE instruction.\r
+ ;\r
+ mov rax, 1\r
+ cpuid\r
+ bt rdx, 25\r
+ jnc SseError\r
+\r
+ ;\r
+ ; SSE 4.1 support\r
+ ;\r
+ bt ecx, 19\r
+ jnc SseError\r
+\r
+ ;\r
+ ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)\r
+ ;\r
+ mov rax, cr4\r
+ or rax, 00000600h\r
+ mov cr4, rax\r
+\r
+ ;\r
+ ; The processor should support SSE instruction and we can use\r
+ ; ldmxcsr instruction\r
+ ;\r
+ mov rax, MmxControlWord\r
+ ldmxcsr [rax]\r
+ %endmacro\r
+\r
+%macro ENABLE_AVX 0\r
+ mov eax, 1\r
+ cpuid\r
+ and ecx, 10000000h\r
+ cmp ecx, 10000000h ; check AVX feature flag\r
+ je EnableAvx\r
+AvxError:\r
+ ;\r
+ ; Processor has to support AVX\r
+ ;\r
+ jmp AvxError\r
+EnableAvx:\r
+ ;\r
+ ; Set OSXSAVE bit (bit #18) to enable xgetbv/xsetbv instruction\r
+ ;\r
+ mov rax, cr4\r
+ or rax, 00040000h\r
+ mov cr4, rax\r
+\r
+ mov rcx, 0 ; index 0\r
+ xgetbv ; result in edx:eax\r
+ or eax, 00000006h ; Set XCR0 bit #1 and bit #2 to enable SSE state and AVX state\r
+ xsetbv\r
+ %endmacro\r
+\r
/** @file\r
\r
- Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
} CONTEXT_STACK;\r
\r
//\r
-// API return address +0xB0\r
+// API return address +0xB8\r
+// Reserved +0xB0\r
// push API Parameter2 +0xA8\r
// push API Parameter1 +0xA0\r
// push FspInfoHeader +0x98\r
UINT32 Flags[2];\r
UINT64 FspInfoHeader;\r
UINT64 ApiParam[2];\r
+ UINT64 Reserved; // The reserved QWORD is needed for stack alignment in X64.\r
UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention\r
} CONTEXT_STACK_64;\r
\r
;------------------------------------------------------------------------------\r
global ASM_PFX(FspSwitchStack)\r
ASM_PFX(FspSwitchStack):\r
- ; Save current contexts\r
+ ; Save current contexts. The format must align with CONTEXT_STACK_64.\r
+ push rdx ; Reserved QWORD for stack alignment\r
push rdx ; ApiParam2\r
push rcx ; ApiParam1\r
push rax ; FspInfoHeader\r
add rsp, 16\r
POPA_64\r
popfq\r
- add rsp, 24 ; FspInfoHeader + ApiParam[2]\r
+ add rsp, 32 ; FspInfoHeader + ApiParam[2] + Reserved QWORD\r
ret\r
\r