]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm
IntelFsp2Pkg: Adopt FSP 2.4 MultiPhase functions.
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / Ia32 / Fsp24ApiEntryM.nasm
diff --git a/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm b/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm
new file mode 100644 (file)
index 0000000..997b9c0
--- /dev/null
@@ -0,0 +1,304 @@
+;; @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