--- /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 are fixed PCDs\r
+;\r
+extern ASM_PFX(PcdGet32(PcdTemporaryRamBase))\r
+extern ASM_PFX(PcdGet32(PcdTemporaryRamSize))\r
+extern ASM_PFX(PcdGet32(PcdFspTemporaryRamSize))\r
+extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
+\r
+struc FSPM_UPD_COMMON\r
+ ; FSP_UPD_HEADER {\r
+ .FspUpdHeader: resd 8\r
+ ; }\r
+ ; FSPM_ARCH_UPD {\r
+ .Revision: resb 1\r
+ .Reserved: resb 3\r
+ .NvsBufferPtr: resd 1\r
+ .StackBase: resd 1\r
+ .StackSize: resd 1\r
+ .BootLoaderTolumSize: resd 1\r
+ .BootMode: resd 1\r
+ .Reserved1: resb 8\r
+ ; }\r
+ .size:\r
+endstruc\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
+extern ASM_PFX(FspMultiPhaseMemInitApiHandler)\r
+\r
+STACK_SAVED_EAX_OFFSET EQU 4 * 7 ; size of a general purpose register * eax index\r
+API_PARAM1_OFFSET EQU 34h ; ApiParam1 [ sub esp,8 + pushad + pushfd + push eax + call]\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
+; FspMultiPhaseMemoryInitApi API\r
+;\r
+; This FSP API provides multi-phase Memory initialization, which brings greater\r
+; modularity beyond the existing FspMemoryInit() API.\r
+; Increased modularity is achieved by adding an extra API to FSP-M.\r
+; This allows the bootloader to add board specific initialization steps throughout\r
+; the MemoryInit flow as needed.\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(FspMultiPhaseMemoryInitApi)\r
+ASM_PFX(FspMultiPhaseMemoryInitApi):\r
+ mov eax, 8 ; FSP_API_INDEX.FspMultiPhaseMemInitApiIndex\r
+ jmp ASM_PFX(FspApiCommon)\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
+ ; Handle FspMultiPhaseMemInitApiIndex API\r
+ ;\r
+ cmp eax, 8 ; FspMultiPhaseMemInitApiIndex\r
+ jnz NotMultiPhaseMemoryInitApi\r
+\r
+ pushad\r
+ push DWORD [esp + (4 * 8 + 4)] ; push ApiParam\r
+ push eax ; push ApiIdx\r
+ call ASM_PFX(FspMultiPhaseMemInitApiHandler)\r
+ add esp, 8\r
+ mov dword [esp + STACK_SAVED_EAX_OFFSET], eax\r
+ popad\r
+ ret\r
+\r
+NotMultiPhaseMemoryInitApi:\r
+\r
+ ;\r
+ ; FspMemoryInit API setup the initial stack frame\r
+ ;\r
+\r
+ ;\r
+ ; Place holder to store the FspInfoHeader pointer\r
+ ;\r
+ push eax\r
+\r
+ ;\r
+ ; Update the FspInfoHeader pointer\r
+ ;\r
+ push eax\r
+ call ASM_PFX(AsmGetFspInfoHeader)\r
+ mov [esp + 4], eax\r
+ pop eax\r
+\r
+ ;\r
+ ; Create a Task Frame in the stack for the Boot Loader\r
+ ;\r
+ pushfd ; 2 pushf for 4 byte alignment\r
+ cli\r
+ pushad\r
+\r
+ ; Reserve 8 bytes for IDT save/restore\r
+ sub esp, 8\r
+ sidt [esp]\r
+\r
+\r
+ ; Get Stackbase and StackSize from FSPM_UPD Param\r
+ mov edx, [esp + API_PARAM1_OFFSET]\r
+ cmp edx, 0\r
+ jnz FspStackSetup\r
+\r
+ ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null\r
+ push eax\r
+ call ASM_PFX(AsmGetFspInfoHeader)\r
+ mov edx, [eax + FSP_HEADER_IMGBASE_OFFSET]\r
+ add edx, [eax + FSP_HEADER_CFGREG_OFFSET]\r
+ pop eax\r
+\r
+FspStackSetup:\r
+ mov ecx, [edx + FSPM_UPD_COMMON.Revision]\r
+ cmp ecx, 3\r
+ jae FspmUpdCommon2\r
+\r
+ ;\r
+ ; StackBase = temp memory base, StackSize = temp memory size\r
+ ;\r
+ mov edi, [edx + FSPM_UPD_COMMON.StackBase]\r
+ mov ecx, [edx + FSPM_UPD_COMMON.StackSize]\r
+ jmp ChkFspHeapSize\r
+\r
+FspmUpdCommon2:\r
+ mov edi, [edx + FSPM_UPD_COMMON_FSP24.StackBase]\r
+ mov ecx, [edx + FSPM_UPD_COMMON_FSP24.StackSize]\r
+\r
+ChkFspHeapSize:\r
+ ;\r
+ ; Keep using bootloader stack if heap size % is 0\r
+ ;\r
+ mov bl, BYTE [ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))]\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 edi, ecx\r
+ ;\r
+ ; Switch to new FSP stack\r
+ ;\r
+ xchg edi, esp ; Exchange edi and esp, edi will be assigned to the current esp pointer and esp will be Stack base + Stack size\r
+\r
+SkipStackSwitch:\r
+ ;\r
+ ; If heap size % is 0:\r
+ ; EDI is FSPM_UPD_COMMON.StackBase and will hold ESP later (boot loader stack pointer)\r
+ ; ECX is FSPM_UPD_COMMON.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.StackBase later)\r
+ ;\r
+ ; If heap size % is not 0\r
+ ; EDI is boot loader stack pointer\r
+ ; ECX is FSPM_UPD_COMMON.StackSize\r
+ ; ESP is new stack (FSPM_UPD_COMMON.StackBase + FSPM_UPD_COMMON.StackSize)\r
+ ; BL is NOT 0 to indicate stack has switched\r
+ ;\r
+ cmp bl, 0\r
+ jnz StackHasBeenSwitched\r
+\r
+ mov ebx, edi ; Put FSPM_UPD_COMMON.StackBase to ebx as temp memory base\r
+ mov edi, esp ; Put boot loader stack pointer to edi\r
+ jmp StackSetupDone\r
+\r
+StackHasBeenSwitched:\r
+ mov ebx, esp ; Put Stack base + Stack size in ebx\r
+ sub ebx, ecx ; Stack base + Stack size - Stack size as temp memory base\r
+\r
+StackSetupDone:\r
+\r
+ ;\r
+ ; Pass the API Idx to SecStartup\r
+ ;\r
+ push eax\r
+\r
+ ;\r
+ ; Pass the BootLoader stack to SecStartup\r
+ ;\r
+ push edi\r
+\r
+ ;\r
+ ; Pass entry point of the PEI core\r
+ ;\r
+ call ASM_PFX(AsmGetFspBaseAddress)\r
+ mov edi, eax\r
+ call ASM_PFX(AsmGetPeiCoreOffset)\r
+ add edi, eax\r
+ push edi\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
+ push eax\r
+\r
+ ;\r
+ ; Pass stack base and size into the PEI Core\r
+ ;\r
+ push ebx\r
+ push ecx\r
+\r
+ ;\r
+ ; Pass Control into the PEI Core\r
+ ;\r
+ call ASM_PFX(SecStartup)\r
+ add esp, 4\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
+ mov eax, dword [ASM_PFX(FspPeiCoreEntryOff)]\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