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