]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
IntelFsp2Pkg: FspSecCore support for X64
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / X64 / FspApiEntryM.nasm
diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
new file mode 100644 (file)
index 0000000..4d965e1
--- /dev/null
@@ -0,0 +1,271 @@
+;; @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