1 /** @file 2 3 Copyright (c) 2014 - 2015, 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 "SecFsp.h" 15 16 /** 17 18 Calculate the FSP IDT gate descriptor. 19 20 @param[in] IdtEntryTemplate IDT gate descriptor template. 21 22 @return FSP specific IDT gate descriptor. 23 24 **/ 25 UINT64 26 FspGetExceptionHandler( 27 IN UINT64 IdtEntryTemplate 28 ) 29 { 30 UINT32 Entry; 31 UINT64 ExceptionHandler; 32 IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor; 33 FSP_INFO_HEADER *FspInfoHeader; 34 35 FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader(); 36 ExceptionHandler = IdtEntryTemplate; 37 IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler; 38 Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow; 39 Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1); 40 IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16); 41 IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry; 42 43 return ExceptionHandler; 44 } 45 46 /** 47 This function gets the FSP UPD region offset in flash. 48 49 @return the offset of the UPD region. 50 51 **/ 52 UINT32 53 EFIAPI 54 GetFspUpdRegionOffset ( 55 VOID 56 ) 57 { 58 FSP_GLOBAL_DATA *FspData; 59 UINT32 *Offset; 60 61 FspData = GetFspGlobalDataPointer (); 62 63 // 64 // It is required to put PcdUpdRegionOffset at offset 0x000C 65 // for all FSPs. 66 // gPlatformFspPkgTokenSpaceGuid.PcdUpdRegionOffset | 0x000C | 0x12345678 67 // 68 Offset = (UINT32 *)(FspData->FspInfoHeader->ImageBase + \ 69 FspData->FspInfoHeader->CfgRegionOffset + 0x0C); 70 71 return *Offset; 72 } 73 74 /** 75 This interface fills platform specific data. 76 77 @param[in,out] FspData Pointer to the FSP global data. 78 79 **/ 80 VOID 81 EFIAPI 82 SecGetPlatformData ( 83 IN OUT FSP_GLOBAL_DATA *FspData 84 ) 85 { 86 FSP_PLAT_DATA *FspPlatformData; 87 UINT32 TopOfCar; 88 UINT32 *StackPtr; 89 UINT32 DwordSize; 90 91 FspPlatformData = &FspData->PlatformData; 92 93 // 94 // The entries of platform information, together with the number of them, 95 // reside in the bottom of stack, left untouched by normal stack operation. 96 // 97 TopOfCar = PcdGet32 (PcdTemporaryRamBase) + PcdGet32 (PcdTemporaryRamSize); 98 99 FspPlatformData->DataPtr = NULL; 100 FspPlatformData->MicrocodeRegionBase = 0; 101 FspPlatformData->MicrocodeRegionSize = 0; 102 FspPlatformData->CodeRegionBase = 0; 103 FspPlatformData->CodeRegionSize = 0; 104 105 // 106 // Pointer to the size field 107 // 108 StackPtr = (UINT32 *)(TopOfCar - sizeof(UINT32)); 109 110 while (*StackPtr != 0) { 111 if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) { 112 // 113 // This following data was pushed onto stack after TempRamInit API 114 // 115 DwordSize = 4; 116 StackPtr = StackPtr - 1 - DwordSize; 117 CopyMem (&(FspPlatformData->MicrocodeRegionBase), StackPtr, (DwordSize << 2)); 118 StackPtr--; 119 } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) { 120 // 121 // This is the performance data for InitTempMemory API entry/exit 122 // 123 DwordSize = 4; 124 StackPtr = StackPtr - 1 - DwordSize; 125 CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2)); 126 ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TMPRAMINIT_ENTRY; 127 ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TMPRAMINIT_EXIT; 128 StackPtr--; 129 } else { 130 StackPtr -= (*StackPtr); 131 } 132 } 133 } 134 135 /** 136 137 Initialize the FSP global data region. 138 It needs to be done as soon as possible after the stack is setup. 139 140 @param[in,out] PeiFspData Pointer of the FSP global data. 141 @param[in] BootLoaderStack BootLoader stack. 142 @param[in] ApiIdx The index of the FSP API. 143 144 **/ 145 VOID 146 FspGlobalDataInit ( 147 IN OUT FSP_GLOBAL_DATA *PeiFspData, 148 IN UINT32 BootLoaderStack, 149 IN UINT8 ApiIdx 150 ) 151 { 152 VOID *UpdDataRgnPtr; 153 FSP_INIT_PARAMS *FspInitParams; 154 CHAR8 ImageId[9]; 155 UINTN Idx; 156 157 // 158 // Init PCIE_BAR with value and set global FSP data pointer. 159 // PciExpress Base should have been programmed by platform already. 160 // 161 SetFspGlobalDataPointer (PeiFspData); 162 ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA)); 163 164 PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE; 165 PeiFspData->CoreStack = BootLoaderStack; 166 PeiFspData->PerfIdx = 2; 167 168 SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_ENTRY); 169 170 // 171 // Get FSP Header offset 172 // It may have multiple FVs, so look into the last one for FSP header 173 // 174 PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader(); 175 SecGetPlatformData (PeiFspData); 176 177 // 178 // Set API calling mode 179 // 180 SetFspApiCallingMode (ApiIdx == 1 ? 0 : 1); 181 182 // 183 // Initialize UPD pointer. 184 // 185 FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter (); 186 UpdDataRgnPtr = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr)->UpdDataRgnPtr; 187 if (UpdDataRgnPtr == NULL) { 188 UpdDataRgnPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + GetFspUpdRegionOffset()); 189 } 190 SetFspUpdDataPointer (UpdDataRgnPtr); 191 192 // 193 // Initialize serial port 194 // It might have been done in ProcessLibraryConstructorList(), however, 195 // the FSP global data is not initialized at that time. So do it again 196 // for safe. 197 // 198 SerialPortInitialize (); 199 200 // 201 // Ensure the golbal data pointer is valid 202 // 203 ASSERT (GetFspGlobalDataPointer () == PeiFspData); 204 205 for (Idx = 0; Idx < 8; Idx++) { 206 ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx]; 207 } 208 ImageId[Idx] = 0; 209 210 DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= PEIM FSP v1.%x (%a v%x.%x.%x.%x) =============\n", \ 211 PeiFspData->FspInfoHeader->HeaderRevision - 1, \ 212 ImageId, \ 213 (PeiFspData->FspInfoHeader->ImageRevision >> 24) & 0xff, \ 214 (PeiFspData->FspInfoHeader->ImageRevision >> 16) & 0xff, \ 215 (PeiFspData->FspInfoHeader->ImageRevision >> 8) & 0xff, \ 216 (PeiFspData->FspInfoHeader->ImageRevision >> 0) & 0xff)); 217 218 } 219 220 /** 221 222 Adjust the FSP data pointers after the stack is migrated to memory. 223 224 @param[in] OffsetGap The offset gap between the old stack and the new stack. 225 226 **/ 227 VOID 228 FspDataPointerFixUp ( 229 IN UINT32 OffsetGap 230 ) 231 { 232 FSP_GLOBAL_DATA *NewFspData; 233 234 NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap); 235 SetFspGlobalDataPointer (NewFspData); 236 } 237 238 /** 239 This function check the FSP API calling condition. 240 241 @param[in] ApiIdx Internal index of the FSP API. 242 @param[in] ApiParam Parameter of the FSP API. 243 244 **/ 245 EFI_STATUS 246 EFIAPI 247 FspApiCallingCheck ( 248 IN UINT32 ApiIdx, 249 IN VOID *ApiParam 250 ) 251 { 252 EFI_STATUS Status; 253 FSP_GLOBAL_DATA *FspData; 254 FSP_INIT_PARAMS *FspInitParams; 255 FSP_INIT_RT_COMMON_BUFFER *FspRtBuffer; 256 257 FspInitParams = (FSP_INIT_PARAMS *) ApiParam; 258 FspRtBuffer = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr); 259 260 Status = EFI_SUCCESS; 261 FspData = GetFspGlobalDataPointer (); 262 if (ApiIdx == 1) { 263 // 264 // FspInit check 265 // 266 if ((UINT32)FspData != 0xFFFFFFFF) { 267 Status = EFI_UNSUPPORTED; 268 } else if ((FspRtBuffer == NULL) || ((FspRtBuffer->BootLoaderTolumSize % EFI_PAGE_SIZE) != 0) || (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam)))) { 269 Status = EFI_INVALID_PARAMETER; 270 } 271 } else if (ApiIdx == 2) { 272 // 273 // NotifyPhase check 274 // 275 if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) { 276 Status = EFI_UNSUPPORTED; 277 } else { 278 if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) { 279 Status = EFI_UNSUPPORTED; 280 } 281 } 282 } else if (ApiIdx == 3) { 283 // 284 // FspMemoryInit check 285 // 286 if ((UINT32)FspData != 0xFFFFFFFF) { 287 Status = EFI_UNSUPPORTED; 288 } else if ((FspRtBuffer == NULL) || ((FspRtBuffer->BootLoaderTolumSize % EFI_PAGE_SIZE) != 0) || (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam)))) { 289 Status = EFI_INVALID_PARAMETER; 290 } 291 } else if (ApiIdx == 4) { 292 // 293 // TempRamExit check 294 // 295 if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) { 296 Status = EFI_UNSUPPORTED; 297 } else { 298 if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) { 299 Status = EFI_UNSUPPORTED; 300 } 301 } 302 } else if (ApiIdx == 5) { 303 // 304 // FspSiliconInit check 305 // 306 if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) { 307 Status = EFI_UNSUPPORTED; 308 } else { 309 if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) { 310 Status = EFI_UNSUPPORTED; 311 } else if (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam))) { 312 Status = EFI_INVALID_PARAMETER; 313 } 314 } 315 } else { 316 Status = EFI_UNSUPPORTED; 317 } 318 319 return Status; 320 } 321 322 /** 323 This function gets the boot FV offset in FSP. 324 @return the boot firmware volumen offset inside FSP binary 325 326 **/ 327 UINT32 328 EFIAPI 329 GetBootFirmwareVolumeOffset ( 330 VOID 331 ) 332 { 333 return PcdGet32 (PcdFspBootFirmwareVolumeBase) - PcdGet32 (PcdFspAreaBaseAddress); 334 } 335