1 /** @file 2 This PEIM will parse coreboot table in memory and report resource information into pei core. 3 This file contains the main entrypoint of the PEIM. 4 5 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 #include "CbSupportPei.h" 16 17 #define LEGACY_8259_MASK_REGISTER_MASTER 0x21 18 #define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1 19 20 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { 21 { EfiACPIReclaimMemory, FixedPcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory) }, 22 { EfiACPIMemoryNVS, FixedPcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS) }, 23 { EfiReservedMemoryType, FixedPcdGet32 (PcdMemoryTypeEfiReservedMemoryType) }, 24 { EfiRuntimeServicesData, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesData) }, 25 { EfiRuntimeServicesCode, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode) }, 26 { EfiMaxMemoryType, 0 } 27 }; 28 29 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { 30 { 31 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 32 &gEfiPeiMasterBootModePpiGuid, 33 NULL 34 } 35 }; 36 37 /** 38 Create memory mapped io resource hob. 39 40 @param MmioBase Base address of the memory mapped io range 41 @param MmioSize Length of the memory mapped io range 42 43 **/ 44 VOID 45 BuildMemoryMappedIoRangeHob ( 46 EFI_PHYSICAL_ADDRESS MmioBase, 47 UINT64 MmioSize 48 ) 49 { 50 BuildResourceDescriptorHob ( 51 EFI_RESOURCE_MEMORY_MAPPED_IO, 52 (EFI_RESOURCE_ATTRIBUTE_PRESENT | 53 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 54 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 55 EFI_RESOURCE_ATTRIBUTE_TESTED), 56 MmioBase, 57 MmioSize 58 ); 59 60 BuildMemoryAllocationHob ( 61 MmioBase, 62 MmioSize, 63 EfiMemoryMappedIO 64 ); 65 } 66 67 /** 68 Check the integrity of firmware volume header 69 70 @param[in] FwVolHeader A pointer to a firmware volume header 71 72 @retval TRUE The firmware volume is consistent 73 @retval FALSE The firmware volume has corrupted. 74 75 **/ 76 STATIC 77 BOOLEAN 78 IsFvHeaderValid ( 79 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader 80 ) 81 { 82 UINT16 Checksum; 83 84 // Skip nv storage fv 85 if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) { 86 return FALSE; 87 } 88 89 if ( (FwVolHeader->Revision != EFI_FVH_REVISION) || 90 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || 91 (FwVolHeader->FvLength == ((UINTN) -1)) || 92 ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) { 93 return FALSE; 94 } 95 96 Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength); 97 if (Checksum != 0) { 98 DEBUG (( DEBUG_ERROR, 99 "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n", 100 FwVolHeader->Checksum, 101 (UINT16)( Checksum + FwVolHeader->Checksum ))); 102 return FALSE; 103 } 104 105 return TRUE; 106 } 107 108 /** 109 Install FvInfo PPI and create fv hobs for remained fvs 110 111 **/ 112 VOID 113 CbPeiReportRemainedFvs ( 114 VOID 115 ) 116 { 117 UINT8* TempPtr; 118 UINT8* EndPtr; 119 120 TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase); 121 EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize)); 122 123 for (;TempPtr < EndPtr;) { 124 if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) { 125 if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase)) { 126 // Skip the PEI FV 127 DEBUG((EFI_D_ERROR, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength)); 128 129 PeiServicesInstallFvInfoPpi ( 130 NULL, 131 (VOID *) (UINTN) TempPtr, 132 (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength, 133 NULL, 134 NULL 135 ); 136 BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength); 137 } 138 } 139 TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength; 140 } 141 } 142 143 /** 144 Based on memory base, size and type, build resource descripter HOB. 145 146 @param Base Memory base address. 147 @param Size Memory size. 148 @param Type Memory type. 149 @param Param A pointer to CB_MEM_INFO. 150 151 @retval EFI_SUCCESS if it completed successfully. 152 **/ 153 EFI_STATUS 154 CbMemInfoCallback ( 155 UINT64 Base, 156 UINT64 Size, 157 UINT32 Type, 158 VOID *Param 159 ) 160 { 161 CB_MEM_INFO *MemInfo; 162 UINTN Attribue; 163 164 Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT | 165 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 166 EFI_RESOURCE_ATTRIBUTE_TESTED | 167 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 168 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 169 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 170 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE; 171 172 if ((Base < 0x100000) && ((Base + Size) > 0x100000)) { 173 Size -= (0x100000 - Base); 174 Base = 0x100000; 175 } 176 177 MemInfo = (CB_MEM_INFO *)Param; 178 if (Base >= 0x100000) { 179 if (Type == CB_MEM_RAM) { 180 if (Base < 0x100000000ULL) { 181 MemInfo->UsableLowMemTop = (UINT32)(Base + Size); 182 } else { 183 Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED; 184 } 185 BuildResourceDescriptorHob ( 186 EFI_RESOURCE_SYSTEM_MEMORY, 187 Attribue, 188 (EFI_PHYSICAL_ADDRESS)Base, 189 Size 190 ); 191 } else if (Type == CB_MEM_TABLE) { 192 BuildResourceDescriptorHob ( 193 EFI_RESOURCE_MEMORY_RESERVED, 194 Attribue, 195 (EFI_PHYSICAL_ADDRESS)Base, 196 Size 197 ); 198 MemInfo->SystemLowMemTop = ((UINT32)(Base + Size) + 0x0FFFFFFF) & 0xF0000000; 199 } else if (Type == CB_MEM_RESERVED) { 200 if ((MemInfo->SystemLowMemTop == 0) || (Base < MemInfo->SystemLowMemTop)) { 201 BuildResourceDescriptorHob ( 202 EFI_RESOURCE_MEMORY_RESERVED, 203 Attribue, 204 (EFI_PHYSICAL_ADDRESS)Base, 205 Size 206 ); 207 } 208 } 209 } 210 211 return EFI_SUCCESS; 212 } 213 214 /** 215 This is the entrypoint of PEIM 216 217 @param FileHandle Handle of the file being invoked. 218 @param PeiServices Describes the list of possible PEI Services. 219 220 @retval EFI_SUCCESS if it completed successfully. 221 **/ 222 EFI_STATUS 223 EFIAPI 224 CbPeiEntryPoint ( 225 IN EFI_PEI_FILE_HANDLE FileHandle, 226 IN CONST EFI_PEI_SERVICES **PeiServices 227 ) 228 { 229 EFI_STATUS Status; 230 UINT64 LowMemorySize; 231 UINT64 PeiMemSize = SIZE_64MB; // 64 MB 232 EFI_PHYSICAL_ADDRESS PeiMemBase = 0; 233 UINT32 RegEax; 234 UINT8 PhysicalAddressBits; 235 VOID* pCbHeader; 236 VOID* pAcpiTable; 237 UINT32 AcpiTableSize; 238 VOID* pSmbiosTable; 239 UINT32 SmbiosTableSize; 240 SYSTEM_TABLE_INFO* pSystemTableInfo; 241 FRAME_BUFFER_INFO FbInfo; 242 FRAME_BUFFER_INFO* pFbInfo; 243 ACPI_BOARD_INFO* pAcpiBoardInfo; 244 UINTN PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue; 245 UINTN PmEvtBase; 246 UINTN PmGpeEnBase; 247 CB_MEM_INFO CbMemInfo; 248 249 // 250 // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED 251 // is intentionally omitted to prevent erasing of the coreboot header 252 // record before it is processed by CbParseMemoryInfo. 253 // 254 BuildResourceDescriptorHob ( 255 EFI_RESOURCE_SYSTEM_MEMORY, 256 ( 257 EFI_RESOURCE_ATTRIBUTE_PRESENT | 258 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 259 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 260 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 261 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 262 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 263 ), 264 (EFI_PHYSICAL_ADDRESS)(0), 265 (UINT64)(0xA0000) 266 ); 267 268 269 BuildResourceDescriptorHob ( 270 EFI_RESOURCE_MEMORY_RESERVED, 271 ( 272 EFI_RESOURCE_ATTRIBUTE_PRESENT | 273 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 274 EFI_RESOURCE_ATTRIBUTE_TESTED | 275 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 276 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 277 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 278 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 279 ), 280 (EFI_PHYSICAL_ADDRESS)(0xA0000), 281 (UINT64)(0x60000) 282 ); 283 284 ZeroMem (&CbMemInfo, sizeof(CbMemInfo)); 285 Status = CbParseMemoryInfo (CbMemInfoCallback, (VOID *)&CbMemInfo); 286 if (EFI_ERROR(Status)) { 287 return Status; 288 } 289 290 LowMemorySize = CbMemInfo.UsableLowMemTop; 291 DEBUG ((EFI_D_INFO, "Low memory 0x%lx\n", LowMemorySize)); 292 DEBUG ((EFI_D_INFO, "SystemLowMemTop 0x%x\n", CbMemInfo.SystemLowMemTop)); 293 294 // 295 // Should be 64k aligned 296 // 297 PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1)); 298 299 DEBUG((EFI_D_ERROR, "PeiMemBase: 0x%lx.\n", PeiMemBase)); 300 DEBUG((EFI_D_ERROR, "PeiMemSize: 0x%lx.\n", PeiMemSize)); 301 302 Status = PeiServicesInstallPeiMemory ( 303 PeiMemBase, 304 PeiMemSize 305 ); 306 ASSERT_EFI_ERROR (Status); 307 308 // 309 // Set cache on the physical memory 310 // 311 MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack); 312 MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack); 313 314 // 315 // Create Memory Type Information HOB 316 // 317 BuildGuidDataHob ( 318 &gEfiMemoryTypeInformationGuid, 319 mDefaultMemoryTypeInformation, 320 sizeof(mDefaultMemoryTypeInformation) 321 ); 322 323 // 324 // Create Fv hob 325 // 326 CbPeiReportRemainedFvs (); 327 328 BuildMemoryAllocationHob ( 329 PcdGet32 (PcdPayloadFdMemBase), 330 PcdGet32 (PcdPayloadFdMemSize), 331 EfiBootServicesData 332 ); 333 334 // 335 // Build CPU memory space and IO space hob 336 // 337 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); 338 if (RegEax >= 0x80000008) { 339 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); 340 PhysicalAddressBits = (UINT8) RegEax; 341 } else { 342 PhysicalAddressBits = 36; 343 } 344 // 345 // Create a CPU hand-off information 346 // 347 BuildCpuHob (PhysicalAddressBits, 16); 348 349 // 350 // Report Local APIC range 351 // 352 BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB); 353 354 // 355 // Boot mode 356 // 357 Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION); 358 ASSERT_EFI_ERROR (Status); 359 360 Status = PeiServicesInstallPpi (mPpiBootMode); 361 ASSERT_EFI_ERROR (Status); 362 363 // 364 // Set pcd to save the upper coreboot header in case the dxecore will 365 // erase 0~4k memory 366 // 367 pCbHeader = NULL; 368 if ((CbParseGetCbHeader (1, &pCbHeader) == RETURN_SUCCESS) 369 && ((UINTN)pCbHeader > BASE_4KB)) { 370 DEBUG((EFI_D_ERROR, "Actual Coreboot header: %p.\n", pCbHeader)); 371 Status = PcdSet32S (PcdCbHeaderPointer, (UINT32)(UINTN)pCbHeader); 372 ASSERT_EFI_ERROR (Status); 373 } 374 375 // 376 // Create guid hob for system tables like acpi table and smbios table 377 // 378 pAcpiTable = NULL; 379 AcpiTableSize = 0; 380 pSmbiosTable = NULL; 381 SmbiosTableSize = 0; 382 Status = CbParseAcpiTable (&pAcpiTable, &AcpiTableSize); 383 if (EFI_ERROR (Status)) { 384 // ACPI table is oblidgible 385 DEBUG ((EFI_D_ERROR, "Failed to find the required acpi table\n")); 386 ASSERT (FALSE); 387 } 388 CbParseSmbiosTable (&pSmbiosTable, &SmbiosTableSize); 389 390 pSystemTableInfo = NULL; 391 pSystemTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO)); 392 ASSERT (pSystemTableInfo != NULL); 393 pSystemTableInfo->AcpiTableBase = (UINT64) (UINTN)pAcpiTable; 394 pSystemTableInfo->AcpiTableSize = AcpiTableSize; 395 pSystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)pSmbiosTable; 396 pSystemTableInfo->SmbiosTableSize = SmbiosTableSize; 397 DEBUG ((EFI_D_ERROR, "Detected Acpi Table at 0x%lx, length 0x%x\n", pSystemTableInfo->AcpiTableBase, pSystemTableInfo->AcpiTableSize)); 398 DEBUG ((EFI_D_ERROR, "Detected Smbios Table at 0x%lx, length 0x%x\n", pSystemTableInfo->SmbiosTableBase, pSystemTableInfo->SmbiosTableSize)); 399 DEBUG ((EFI_D_ERROR, "Create system table info guid hob\n")); 400 401 // 402 // Create guid hob for acpi board information 403 // 404 Status = CbParseFadtInfo (&PmCtrlRegBase, &PmTimerRegBase, &ResetRegAddress, &ResetValue, &PmEvtBase, &PmGpeEnBase); 405 ASSERT_EFI_ERROR (Status); 406 pAcpiBoardInfo = NULL; 407 pAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); 408 ASSERT (pAcpiBoardInfo != NULL); 409 pAcpiBoardInfo->PmCtrlRegBase = (UINT64)PmCtrlRegBase; 410 pAcpiBoardInfo->PmTimerRegBase = (UINT64)PmTimerRegBase; 411 pAcpiBoardInfo->ResetRegAddress = (UINT64)ResetRegAddress; 412 pAcpiBoardInfo->ResetValue = (UINT8)ResetValue; 413 pAcpiBoardInfo->PmEvtBase = (UINT64)PmEvtBase; 414 pAcpiBoardInfo->PmGpeEnBase = (UINT64)PmGpeEnBase; 415 DEBUG ((EFI_D_ERROR, "Create acpi board info guid hob\n")); 416 417 // 418 // Create guid hob for frame buffer information 419 // 420 ZeroMem (&FbInfo, sizeof (FRAME_BUFFER_INFO)); 421 Status = CbParseFbInfo (&FbInfo); 422 if (!EFI_ERROR (Status)) { 423 pFbInfo = BuildGuidHob (&gUefiFrameBufferInfoGuid, sizeof (FRAME_BUFFER_INFO)); 424 ASSERT (pSystemTableInfo != NULL); 425 CopyMem (pFbInfo, &FbInfo, sizeof (FRAME_BUFFER_INFO)); 426 DEBUG ((EFI_D_ERROR, "Create frame buffer info guid hob\n")); 427 } 428 429 // 430 // Parse platform specific information from coreboot. 431 // 432 Status = CbParsePlatformInfo (); 433 if (EFI_ERROR (Status)) { 434 DEBUG ((EFI_D_ERROR, "Error when parsing platform info, Status = %r\n", Status)); 435 return Status; 436 } 437 438 // 439 // Mask off all legacy 8259 interrupt sources 440 // 441 IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); 442 IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); 443 444 return EFI_SUCCESS; 445 } 446 447