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