]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm
IntelFsp2Pkg: FSP can utilize bootloader stack
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / Ia32 / FspApiEntryM.nasm
CommitLineData
cf1d4549
JY
1;; @file\r
2; Provide FSP API entry points.\r
3;\r
12a0a80b 4; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
cf1d4549
JY
5; This program and the accompanying materials\r
6; are licensed and made available under the terms and conditions of the BSD License\r
7; which accompanies this distribution. The full text of the license may be found at\r
8; http://opensource.org/licenses/bsd-license.php.\r
9;\r
10; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12;;\r
13\r
14 SECTION .text\r
15\r
16;\r
17; Following are fixed PCDs\r
18;\r
19extern ASM_PFX(PcdGet32(PcdTemporaryRamBase))\r
20extern ASM_PFX(PcdGet32(PcdTemporaryRamSize))\r
21extern ASM_PFX(PcdGet32(PcdFspTemporaryRamSize))\r
12a0a80b 22extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
cf1d4549
JY
23\r
24struc FSPM_UPD_COMMON\r
25 ; FSP_UPD_HEADER {\r
26 .FspUpdHeader: resd 8\r
27 ; }\r
28 ; FSPM_ARCH_UPD {\r
29 .Revision: resb 1\r
30 .Reserved: resb 3\r
31 .NvsBufferPtr: resd 1\r
32 .StackBase: resd 1\r
33 .StackSize: resd 1\r
34 .BootLoaderTolumSize: resd 1\r
35 .BootMode: resd 1\r
36 .Reserved1: resb 8\r
37 ; }\r
38 .size:\r
39endstruc\r
40\r
41;\r
42; Following functions will be provided in C\r
43;\r
44extern ASM_PFX(SecStartup)\r
45extern ASM_PFX(FspApiCommon)\r
46\r
47;\r
48; Following functions will be provided in PlatformSecLib\r
49;\r
50extern ASM_PFX(AsmGetFspBaseAddress)\r
51extern ASM_PFX(AsmGetFspInfoHeader)\r
52\r
53API_PARAM1_OFFSET EQU 34h ; ApiParam1 [ sub esp,8 + pushad + pushfd + push eax + call]\r
54FSP_HEADER_IMGBASE_OFFSET EQU 1Ch\r
55FSP_HEADER_CFGREG_OFFSET EQU 24h\r
56\r
57;----------------------------------------------------------------------------\r
58; FspMemoryInit API\r
59;\r
60; This FSP API is called after TempRamInit and initializes the memory.\r
61;\r
62;----------------------------------------------------------------------------\r
63global ASM_PFX(FspMemoryInitApi)\r
64ASM_PFX(FspMemoryInitApi):\r
65 mov eax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex\r
66 jmp ASM_PFX(FspApiCommon)\r
67\r
68;----------------------------------------------------------------------------\r
69; TempRamExitApi API\r
70;\r
71; This API tears down temporary RAM\r
72;\r
73;----------------------------------------------------------------------------\r
74global ASM_PFX(TempRamExitApi)\r
75ASM_PFX(TempRamExitApi):\r
76 mov eax, 4 ; FSP_API_INDEX.TempRamExitApiIndex\r
77 jmp ASM_PFX(FspApiCommon)\r
78\r
79;----------------------------------------------------------------------------\r
80; FspApiCommonContinue API\r
81;\r
82; This is the FSP API common entry point to resume the FSP execution\r
83;\r
84;----------------------------------------------------------------------------\r
85global ASM_PFX(FspApiCommonContinue)\r
86ASM_PFX(FspApiCommonContinue):\r
87 ;\r
88 ; EAX holds the API index\r
89 ;\r
90\r
91 ;\r
92 ; FspMemoryInit API setup the initial stack frame\r
93 ;\r
94\r
95 ;\r
96 ; Place holder to store the FspInfoHeader pointer\r
97 ;\r
98 push eax\r
99\r
100 ;\r
101 ; Update the FspInfoHeader pointer\r
102 ;\r
103 push eax\r
104 call ASM_PFX(AsmGetFspInfoHeader)\r
105 mov [esp + 4], eax\r
106 pop eax\r
107\r
108 ;\r
109 ; Create a Task Frame in the stack for the Boot Loader\r
110 ;\r
111 pushfd ; 2 pushf for 4 byte alignment\r
112 cli\r
113 pushad\r
114\r
115 ; Reserve 8 bytes for IDT save/restore\r
116 sub esp, 8\r
117 sidt [esp]\r
118\r
119\r
e37bb20c
LG
120 ; Get Stackbase and StackSize from FSPM_UPD Param\r
121 mov edx, [esp + API_PARAM1_OFFSET]\r
cf1d4549 122 cmp edx, 0\r
e37bb20c 123 jnz FspStackSetup\r
cf1d4549
JY
124\r
125 ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null\r
126 push eax\r
127 call ASM_PFX(AsmGetFspInfoHeader)\r
128 mov edx, [eax + FSP_HEADER_IMGBASE_OFFSET]\r
129 add edx, [eax + FSP_HEADER_CFGREG_OFFSET]\r
130 pop eax\r
e37bb20c 131\r
12a0a80b
CC
132FspStackSetup:\r
133 ;\r
134 ; StackBase = temp memory base, StackSize = temp memory size\r
135 ;\r
cf1d4549
JY
136 mov edi, [edx + FSPM_UPD_COMMON.StackBase]\r
137 mov ecx, [edx + FSPM_UPD_COMMON.StackSize]\r
12a0a80b
CC
138\r
139 ;\r
140 ; Keep using bootloader stack if heap size % is 0\r
141 ;\r
142 mov bl, BYTE [ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))]\r
143 cmp bl, 0\r
144 jz SkipStackSwitch\r
145\r
146 ;\r
147 ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0\r
148 ;\r
cf1d4549
JY
149 add edi, ecx\r
150 ;\r
12a0a80b 151 ; Switch to new FSP stack\r
cf1d4549 152 ;\r
12a0a80b
CC
153 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
154\r
155SkipStackSwitch:\r
156 ;\r
157 ; If heap size % is 0:\r
158 ; EDI is FSPM_UPD_COMMON.StackBase and will hold ESP later (boot loader stack pointer)\r
159 ; ECX is FSPM_UPD_COMMON.StackSize\r
160 ; ESP is boot loader stack pointer (no stack switch)\r
161 ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON.StackBase later)\r
162 ;\r
163 ; If heap size % is not 0\r
164 ; EDI is boot loader stack pointer\r
165 ; ECX is FSPM_UPD_COMMON.StackSize\r
166 ; ESP is new stack (FSPM_UPD_COMMON.StackBase + FSPM_UPD_COMMON.StackSize)\r
167 ; BL is NOT 0 to indicate stack has switched\r
168 ;\r
169 cmp bl, 0\r
170 jnz StackHasBeenSwitched\r
171\r
172 mov ebx, edi ; Put FSPM_UPD_COMMON.StackBase to ebx as temp memory base\r
173 mov edi, esp ; Put boot loader stack pointer to edi\r
174 jmp StackSetupDone\r
175\r
176StackHasBeenSwitched:\r
177 mov ebx, esp ; Put Stack base + Stack size in ebx\r
178 sub ebx, ecx ; Stack base + Stack size - Stack size as temp memory base\r
179\r
180StackSetupDone:\r
cf1d4549
JY
181\r
182 ;\r
183 ; Pass the API Idx to SecStartup\r
184 ;\r
185 push eax\r
186\r
187 ;\r
188 ; Pass the BootLoader stack to SecStartup\r
189 ;\r
190 push edi\r
191\r
192 ;\r
193 ; Pass entry point of the PEI core\r
194 ;\r
195 call ASM_PFX(AsmGetFspBaseAddress)\r
196 mov edi, eax\r
197 call ASM_PFX(AsmGetPeiCoreOffset)\r
198 add edi, eax\r
199 push edi\r
200\r
201 ;\r
202 ; Pass BFV into the PEI Core\r
203 ; It uses relative address to calucate the actual boot FV base\r
204 ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and\r
205 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
206 ; they are different. The code below can handle both cases.\r
207 ;\r
208 call ASM_PFX(AsmGetFspBaseAddress)\r
209 push eax\r
210\r
211 ;\r
212 ; Pass stack base and size into the PEI Core\r
213 ;\r
cf1d4549
JY
214 push ebx\r
215 push ecx\r
216\r
217 ;\r
218 ; Pass Control into the PEI Core\r
219 ;\r
220 call ASM_PFX(SecStartup)\r
221 add esp, 4\r
222exit:\r
223 ret\r
224\r
225global ASM_PFX(FspPeiCoreEntryOff)\r
226ASM_PFX(FspPeiCoreEntryOff):\r
227 ;\r
228 ; This value will be pached by the build script\r
229 ;\r
230 DD 0x12345678\r
231\r
232global ASM_PFX(AsmGetPeiCoreOffset)\r
233ASM_PFX(AsmGetPeiCoreOffset):\r
234 mov eax, dword [ASM_PFX(FspPeiCoreEntryOff)]\r
235 ret\r
236\r
c69071bd
SB
237;----------------------------------------------------------------------------\r
238; TempRamInit API\r
239;\r
240; Empty function for WHOLEARCHIVE build option\r
241;\r
242;----------------------------------------------------------------------------\r
243global ASM_PFX(TempRamInitApi)\r
244ASM_PFX(TempRamInitApi):\r
245 jmp $\r
246 ret\r
247\r
cf1d4549
JY
248;----------------------------------------------------------------------------\r
249; Module Entrypoint API\r
250;----------------------------------------------------------------------------\r
251global ASM_PFX(_ModuleEntryPoint)\r
252ASM_PFX(_ModuleEntryPoint):\r
253 jmp $\r