]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
67e08a9e7eb4cb91702266baf5723171bf7e0752
[mirror_edk2.git] / IntelFsp2Pkg / Library / BaseFspCommonLib / FspCommonLib.c
1 /** @file
2
3 Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include <PiPei.h>
9 #include <Library/BaseLib.h>
10 #include <Library/DebugLib.h>
11 #include <Library/PcdLib.h>
12 #include <FspGlobalData.h>
13 #include <FspEas.h>
14 #include <Library/FspSwitchStackLib.h>
15
16 #pragma pack(1)
17
18 //
19 // API Parameter +0x34
20 // API return address +0x30
21 //
22 // push FspInfoHeader +0x2C
23 // pushfd +0x28
24 // cli
25 // pushad +0x24
26 // sub esp, 8 +0x00
27 // sidt fword ptr [esp]
28 //
29 typedef struct {
30 UINT16 IdtrLimit;
31 UINT32 IdtrBase;
32 UINT16 Reserved;
33 UINT32 Registers[8]; // General Purpose Registers: Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx and Eax
34 UINT16 Flags[2];
35 UINT32 FspInfoHeader;
36 UINT32 ApiRet;
37 UINT32 ApiParam[2];
38 } CONTEXT_STACK;
39
40 //
41 // API return address +0xB8
42 // Reserved +0xB0
43 // push API Parameter2 +0xA8
44 // push API Parameter1 +0xA0
45 // push FspInfoHeader +0x98
46 // pushfq +0x90
47 // cli
48 // PUSHA_64 +0x10
49 // sub rsp, 16 +0x00
50 // sidt [rsp]
51 //
52 typedef struct {
53 UINT64 Idtr[2]; // IDTR Limit - bit0:bi15, IDTR Base - bit16:bit79
54 UINT64 Registers[16]; // General Purpose Registers: RDI, RSI, RBP, RSP, RBX, RDX, RCX, RAX, and R15 to R8
55 UINT32 Flags[2];
56 UINT64 FspInfoHeader;
57 UINT64 ApiParam[2];
58 UINT64 Reserved; // The reserved QWORD is needed for stack alignment in X64.
59 UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention
60 } CONTEXT_STACK_64;
61
62 #define CONTEXT_STACK_OFFSET(x) (sizeof(UINTN) == sizeof (UINT32) ? (UINTN)&((CONTEXT_STACK *)(UINTN)0)->x : (UINTN)&((CONTEXT_STACK_64 *)(UINTN)0)->x)
63
64 #pragma pack()
65
66 /**
67 This function sets the FSP global data pointer.
68
69 @param[in] FspData FSP global data pointer.
70
71 **/
72 VOID
73 EFIAPI
74 SetFspGlobalDataPointer (
75 IN FSP_GLOBAL_DATA *FspData
76 )
77 {
78 ASSERT (FspData != NULL);
79 *((volatile UINT32 *)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;
80 }
81
82 /**
83 This function gets the FSP global data pointer.
84
85 **/
86 FSP_GLOBAL_DATA *
87 EFIAPI
88 GetFspGlobalDataPointer (
89 VOID
90 )
91 {
92 FSP_GLOBAL_DATA *FspData;
93
94 FspData = *(FSP_GLOBAL_DATA **)(UINTN)PcdGet32 (PcdGlobalDataPointerAddress);
95 return FspData;
96 }
97
98 /**
99 This function gets back the FSP API first parameter passed by the bootloader.
100
101 @retval ApiParameter FSP API first parameter passed by the bootloader.
102 **/
103 UINTN
104 EFIAPI
105 GetFspApiParameter (
106 VOID
107 )
108 {
109 FSP_GLOBAL_DATA *FspData;
110
111 FspData = GetFspGlobalDataPointer ();
112 return *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[0]));
113 }
114
115 /**
116 This function returns the FSP entry stack pointer from address of the first API parameter.
117
118 @retval FSP entry stack pointer.
119 **/
120 VOID *
121 EFIAPI
122 GetFspEntryStack (
123 VOID
124 )
125 {
126 FSP_GLOBAL_DATA *FspData;
127
128 FspData = GetFspGlobalDataPointer ();
129 return (VOID *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[0]));
130 }
131
132 /**
133 This function gets back the FSP API second parameter passed by the bootloader.
134
135 @retval ApiParameter FSP API second parameter passed by the bootloader.
136 **/
137 UINTN
138 EFIAPI
139 GetFspApiParameter2 (
140 VOID
141 )
142 {
143 FSP_GLOBAL_DATA *FspData;
144
145 FspData = GetFspGlobalDataPointer ();
146 return *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam[1]));
147 }
148
149 /**
150 This function sets the FSP API parameter in the stack.
151
152 @param[in] Value New parameter value.
153
154 **/
155 VOID
156 EFIAPI
157 SetFspApiParameter (
158 IN UINT32 Value
159 )
160 {
161 FSP_GLOBAL_DATA *FspData;
162
163 FspData = GetFspGlobalDataPointer ();
164 *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (ApiParam)) = Value;
165 }
166
167 /**
168 This function set the API status code returned to the BootLoader.
169
170 @param[in] ReturnStatus Status code to return.
171
172 **/
173 VOID
174 EFIAPI
175 SetFspApiReturnStatus (
176 IN UINTN ReturnStatus
177 )
178 {
179 FSP_GLOBAL_DATA *FspData;
180
181 FspData = GetFspGlobalDataPointer ();
182 *(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (Registers[7])) = ReturnStatus;
183 }
184
185 /**
186 This function sets the context switching stack to a new stack frame.
187
188 @param[in] NewStackTop New core stack to be set.
189
190 **/
191 VOID
192 EFIAPI
193 SetFspCoreStackPointer (
194 IN VOID *NewStackTop
195 )
196 {
197 FSP_GLOBAL_DATA *FspData;
198 UINTN *OldStack;
199 UINTN *NewStack;
200 UINT32 StackContextLen;
201
202 FspData = GetFspGlobalDataPointer ();
203 StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINTN);
204
205 //
206 // Reserve space for the ContinuationFunc two parameters
207 //
208 OldStack = (UINTN *)FspData->CoreStack;
209 NewStack = (UINTN *)NewStackTop - StackContextLen - 2;
210 FspData->CoreStack = (UINTN)NewStack;
211 while (StackContextLen-- != 0) {
212 *NewStack++ = *OldStack++;
213 }
214 }
215
216 /**
217 This function sets the platform specific data pointer.
218
219 @param[in] PlatformData FSP platform specific data pointer.
220
221 **/
222 VOID
223 EFIAPI
224 SetFspPlatformDataPointer (
225 IN VOID *PlatformData
226 )
227 {
228 FSP_GLOBAL_DATA *FspData;
229
230 FspData = GetFspGlobalDataPointer ();
231 FspData->PlatformData.DataPtr = PlatformData;
232 }
233
234 /**
235 This function gets the platform specific data pointer.
236
237 @param[in] PlatformData FSP platform specific data pointer.
238
239 **/
240 VOID *
241 EFIAPI
242 GetFspPlatformDataPointer (
243 VOID
244 )
245 {
246 FSP_GLOBAL_DATA *FspData;
247
248 FspData = GetFspGlobalDataPointer ();
249 return FspData->PlatformData.DataPtr;
250 }
251
252 /**
253 This function sets the UPD data pointer.
254
255 @param[in] UpdDataPtr UPD data pointer.
256 **/
257 VOID
258 EFIAPI
259 SetFspUpdDataPointer (
260 IN VOID *UpdDataPtr
261 )
262 {
263 FSP_GLOBAL_DATA *FspData;
264
265 //
266 // Get the FSP Global Data Pointer
267 //
268 FspData = GetFspGlobalDataPointer ();
269
270 //
271 // Set the UPD pointer.
272 //
273 FspData->UpdDataPtr = UpdDataPtr;
274 }
275
276 /**
277 This function gets the UPD data pointer.
278
279 @return UpdDataPtr UPD data pointer.
280 **/
281 VOID *
282 EFIAPI
283 GetFspUpdDataPointer (
284 VOID
285 )
286 {
287 FSP_GLOBAL_DATA *FspData;
288
289 FspData = GetFspGlobalDataPointer ();
290 return FspData->UpdDataPtr;
291 }
292
293 /**
294 This function sets the FspMemoryInit UPD data pointer.
295
296 @param[in] MemoryInitUpdPtr FspMemoryInit UPD data pointer.
297 **/
298 VOID
299 EFIAPI
300 SetFspMemoryInitUpdDataPointer (
301 IN VOID *MemoryInitUpdPtr
302 )
303 {
304 FSP_GLOBAL_DATA *FspData;
305
306 //
307 // Get the FSP Global Data Pointer
308 //
309 FspData = GetFspGlobalDataPointer ();
310
311 //
312 // Set the FspMemoryInit UPD pointer.
313 //
314 FspData->MemoryInitUpdPtr = MemoryInitUpdPtr;
315 }
316
317 /**
318 This function gets the FspMemoryInit UPD data pointer.
319
320 @return FspMemoryInit UPD data pointer.
321 **/
322 VOID *
323 EFIAPI
324 GetFspMemoryInitUpdDataPointer (
325 VOID
326 )
327 {
328 FSP_GLOBAL_DATA *FspData;
329
330 FspData = GetFspGlobalDataPointer ();
331 return FspData->MemoryInitUpdPtr;
332 }
333
334 /**
335 This function sets the FspSiliconInit UPD data pointer.
336
337 @param[in] SiliconInitUpdPtr FspSiliconInit UPD data pointer.
338 **/
339 VOID
340 EFIAPI
341 SetFspSiliconInitUpdDataPointer (
342 IN VOID *SiliconInitUpdPtr
343 )
344 {
345 FSP_GLOBAL_DATA *FspData;
346
347 //
348 // Get the FSP Global Data Pointer
349 //
350 FspData = GetFspGlobalDataPointer ();
351
352 //
353 // Set the FspSiliconInit UPD data pointer.
354 //
355 FspData->SiliconInitUpdPtr = SiliconInitUpdPtr;
356 }
357
358 /**
359 This function gets the FspSiliconInit UPD data pointer.
360
361 @return FspSiliconInit UPD data pointer.
362 **/
363 VOID *
364 EFIAPI
365 GetFspSiliconInitUpdDataPointer (
366 VOID
367 )
368 {
369 FSP_GLOBAL_DATA *FspData;
370
371 FspData = GetFspGlobalDataPointer ();
372 return FspData->SiliconInitUpdPtr;
373 }
374
375 /**
376 Set FSP measurement point timestamp.
377
378 @param[in] Id Measurement point ID.
379
380 @return performance timestamp.
381 **/
382 UINT64
383 EFIAPI
384 SetFspMeasurePoint (
385 IN UINT8 Id
386 )
387 {
388 FSP_GLOBAL_DATA *FspData;
389
390 //
391 // Bit [55: 0] will be the timestamp
392 // Bit [63:56] will be the ID
393 //
394 FspData = GetFspGlobalDataPointer ();
395 if (FspData->PerfIdx < sizeof (FspData->PerfData) / sizeof (FspData->PerfData[0])) {
396 FspData->PerfData[FspData->PerfIdx] = AsmReadTsc ();
397 ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;
398 }
399
400 return FspData->PerfData[(FspData->PerfIdx)++];
401 }
402
403 /**
404 This function gets the FSP info header pointer.
405
406 @retval FspInfoHeader FSP info header pointer
407 **/
408 FSP_INFO_HEADER *
409 EFIAPI
410 GetFspInfoHeader (
411 VOID
412 )
413 {
414 return GetFspGlobalDataPointer ()->FspInfoHeader;
415 }
416
417 /**
418 This function sets the FSP info header pointer.
419
420 @param[in] FspInfoHeader FSP info header pointer
421 **/
422 VOID
423 EFIAPI
424 SetFspInfoHeader (
425 FSP_INFO_HEADER *FspInfoHeader
426 )
427 {
428 GetFspGlobalDataPointer ()->FspInfoHeader = FspInfoHeader;
429 }
430
431 /**
432 This function gets the FSP info header pointer using the API stack context.
433
434 @retval FspInfoHeader FSP info header pointer using the API stack context
435 **/
436 FSP_INFO_HEADER *
437 EFIAPI
438 GetFspInfoHeaderFromApiContext (
439 VOID
440 )
441 {
442 FSP_GLOBAL_DATA *FspData;
443
444 FspData = GetFspGlobalDataPointer ();
445 return (FSP_INFO_HEADER *)(*(UINTN *)(FspData->CoreStack + CONTEXT_STACK_OFFSET (FspInfoHeader)));
446 }
447
448 /**
449 This function gets the CfgRegion data pointer.
450
451 @return CfgRegion data pointer.
452 **/
453 VOID *
454 EFIAPI
455 GetFspCfgRegionDataPointer (
456 VOID
457 )
458 {
459 FSP_INFO_HEADER *FspInfoHeader;
460
461 FspInfoHeader = GetFspInfoHeader ();
462 return (VOID *)(UINTN)(FspInfoHeader->ImageBase + FspInfoHeader->CfgRegionOffset);
463 }
464
465 /**
466 This function gets FSP API calling index.
467
468 @retval API calling index
469 **/
470 UINT8
471 EFIAPI
472 GetFspApiCallingIndex (
473 VOID
474 )
475 {
476 return GetFspGlobalDataPointer ()->ApiIdx;
477 }
478
479 /**
480 This function sets FSP API calling mode.
481
482 @param[in] Index API calling index
483 **/
484 VOID
485 EFIAPI
486 SetFspApiCallingIndex (
487 UINT8 Index
488 )
489 {
490 FSP_GLOBAL_DATA *FspData;
491
492 FspData = GetFspGlobalDataPointer ();
493 FspData->ApiIdx = Index;
494 }
495
496 /**
497 This function gets FSP Phase StatusCode.
498
499 @retval StatusCode
500 **/
501 UINT32
502 EFIAPI
503 GetPhaseStatusCode (
504 VOID
505 )
506 {
507 return GetFspGlobalDataPointer ()->StatusCode;
508 }
509
510 /**
511 This function sets FSP Phase StatusCode.
512
513 @param[in] Mode Phase StatusCode
514 **/
515 VOID
516 EFIAPI
517 SetPhaseStatusCode (
518 UINT32 StatusCode
519 )
520 {
521 FSP_GLOBAL_DATA *FspData;
522
523 FspData = GetFspGlobalDataPointer ();
524 FspData->StatusCode = StatusCode;
525 }
526
527 /**
528 This function updates the return status of the FSP API with requested reset type and returns to Boot Loader.
529
530 @param[in] FspResetType Reset type that needs to returned as API return status
531
532 **/
533 VOID
534 EFIAPI
535 FspApiReturnStatusReset (
536 IN UINT32 FspResetType
537 )
538 {
539 volatile BOOLEAN LoopUntilReset;
540
541 LoopUntilReset = TRUE;
542 DEBUG ((DEBUG_INFO, "FSP returning control to Bootloader with reset required return status %x\n", FspResetType));
543 if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
544 ///
545 /// Below code is not an infinite loop.The control will go back to API calling function in BootLoader each time BootLoader
546 /// calls the FSP API without honoring the reset request by FSP
547 ///
548 do {
549 SetFspApiReturnStatus ((EFI_STATUS)FspResetType);
550 Pei2LoaderSwitchStack ();
551 DEBUG ((DEBUG_ERROR, "!!!ERROR: FSP has requested BootLoader for reset. But BootLoader has not honored the reset\n"));
552 DEBUG ((DEBUG_ERROR, "!!!ERROR: Please add support in BootLoader to honor the reset request from FSP\n"));
553 } while (LoopUntilReset);
554 }
555 }