| /** @file | |
| This PEIM will parse coreboot table in memory and report resource information into pei core. | |
| This file contains the main entrypoint of the PEIM. | |
| Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "CbSupportPei.h" | |
| #define LEGACY_8259_MASK_REGISTER_MASTER 0x21 | |
| #define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1 | |
| EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { | |
| { EfiACPIReclaimMemory, 0x008 }, | |
| { EfiACPIMemoryNVS, 0x004 }, | |
| { EfiReservedMemoryType, 0x004 }, | |
| { EfiRuntimeServicesData, 0x080 }, | |
| { EfiRuntimeServicesCode, 0x080 }, | |
| { EfiMaxMemoryType, 0 } | |
| }; | |
| EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { | |
| { | |
| EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, | |
| &gEfiPeiMasterBootModePpiGuid, | |
| NULL | |
| } | |
| }; | |
| /** | |
| Create memory mapped io resource hob. | |
| @param MmioBase Base address of the memory mapped io range | |
| @param MmioSize Length of the memory mapped io range | |
| **/ | |
| VOID | |
| BuildMemoryMappedIoRangeHob ( | |
| EFI_PHYSICAL_ADDRESS MmioBase, | |
| UINT64 MmioSize | |
| ) | |
| { | |
| BuildResourceDescriptorHob ( | |
| EFI_RESOURCE_MEMORY_MAPPED_IO, | |
| (EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
| EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
| EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_TESTED), | |
| MmioBase, | |
| MmioSize | |
| ); | |
| BuildMemoryAllocationHob ( | |
| MmioBase, | |
| MmioSize, | |
| EfiMemoryMappedIO | |
| ); | |
| } | |
| /** | |
| Check the integrity of firmware volume header | |
| @param[in] FwVolHeader A pointer to a firmware volume header | |
| @retval TRUE The firmware volume is consistent | |
| @retval FALSE The firmware volume has corrupted. | |
| **/ | |
| STATIC | |
| BOOLEAN | |
| IsFvHeaderValid ( | |
| IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader | |
| ) | |
| { | |
| UINT16 Checksum; | |
| // Skip nv storage fv | |
| if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) { | |
| return FALSE; | |
| } | |
| if ( (FwVolHeader->Revision != EFI_FVH_REVISION) || | |
| (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || | |
| (FwVolHeader->FvLength == ((UINTN) -1)) || | |
| ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) { | |
| return FALSE; | |
| } | |
| Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength); | |
| if (Checksum != 0) { | |
| DEBUG (( DEBUG_ERROR, | |
| "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n", | |
| FwVolHeader->Checksum, | |
| (UINT16)( Checksum + FwVolHeader->Checksum ))); | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| Install FvInfo PPI and create fv hobs for remained fvs | |
| **/ | |
| VOID | |
| CbPeiReportRemainedFvs ( | |
| VOID | |
| ) | |
| { | |
| UINT8* TempPtr; | |
| UINT8* EndPtr; | |
| TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase); | |
| EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize)); | |
| for (;TempPtr < EndPtr;) { | |
| if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) { | |
| if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase)) { | |
| // Skip the PEI FV | |
| DEBUG((EFI_D_ERROR, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength)); | |
| PeiServicesInstallFvInfoPpi ( | |
| NULL, | |
| (VOID *) (UINTN) TempPtr, | |
| (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength, | |
| NULL, | |
| NULL | |
| ); | |
| BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength); | |
| } | |
| } | |
| TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength; | |
| } | |
| } | |
| /** | |
| This is the entrypoint of PEIM | |
| @param FileHandle Handle of the file being invoked. | |
| @param PeiServices Describes the list of possible PEI Services. | |
| @retval EFI_SUCCESS if it completed successfully. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| CbPeiEntryPoint ( | |
| IN EFI_PEI_FILE_HANDLE FileHandle, | |
| IN CONST EFI_PEI_SERVICES **PeiServices | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT64 LowMemorySize, HighMemorySize; | |
| UINT64 PeiMemSize = SIZE_64MB; // 64 MB | |
| EFI_PHYSICAL_ADDRESS PeiMemBase = 0; | |
| UINT32 RegEax; | |
| UINT8 PhysicalAddressBits; | |
| VOID* pCbHeader; | |
| VOID* pAcpiTable; | |
| UINT32 AcpiTableSize; | |
| VOID* pSmbiosTable; | |
| UINT32 SmbiosTableSize; | |
| SYSTEM_TABLE_INFO* pSystemTableInfo; | |
| FRAME_BUFFER_INFO FbInfo; | |
| FRAME_BUFFER_INFO* pFbInfo; | |
| ACPI_BOARD_INFO* pAcpiBoardInfo; | |
| UINTN PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue; | |
| UINTN PmEvtBase; | |
| UINTN PmGpeEnBase; | |
| LowMemorySize = 0; | |
| HighMemorySize = 0; | |
| Status = CbParseMemoryInfo (&LowMemorySize, &HighMemorySize); | |
| if (EFI_ERROR(Status)) | |
| return Status; | |
| DEBUG((EFI_D_ERROR, "LowMemorySize: 0x%lx.\n", LowMemorySize)); | |
| DEBUG((EFI_D_ERROR, "HighMemorySize: 0x%lx.\n", HighMemorySize)); | |
| ASSERT (LowMemorySize > 0); | |
| // | |
| // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED | |
| // is intentionally omitted to prevent erasing of the coreboot header | |
| // record before it is processed by CbParseMemoryInfo. | |
| // | |
| BuildResourceDescriptorHob ( | |
| EFI_RESOURCE_SYSTEM_MEMORY, | |
| ( | |
| EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
| EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
| EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | |
| ), | |
| (EFI_PHYSICAL_ADDRESS)(0), | |
| (UINT64)(0xA0000) | |
| ); | |
| BuildResourceDescriptorHob ( | |
| EFI_RESOURCE_MEMORY_RESERVED, | |
| ( | |
| EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
| EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
| EFI_RESOURCE_ATTRIBUTE_TESTED | | |
| EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | |
| ), | |
| (EFI_PHYSICAL_ADDRESS)(0xA0000), | |
| (UINT64)(0x60000) | |
| ); | |
| BuildResourceDescriptorHob ( | |
| EFI_RESOURCE_SYSTEM_MEMORY, | |
| ( | |
| EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
| EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
| EFI_RESOURCE_ATTRIBUTE_TESTED | | |
| EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | |
| ), | |
| (EFI_PHYSICAL_ADDRESS)(0x100000), | |
| (UINT64) (LowMemorySize - 0x100000) | |
| ); | |
| if (HighMemorySize > 0) { | |
| BuildResourceDescriptorHob ( | |
| EFI_RESOURCE_SYSTEM_MEMORY, | |
| ( | |
| EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
| EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
| EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | |
| ), | |
| (EFI_PHYSICAL_ADDRESS)(0x100000000ULL), | |
| HighMemorySize | |
| ); | |
| } | |
| // | |
| // Should be 64k aligned | |
| // | |
| PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1)); | |
| DEBUG((EFI_D_ERROR, "PeiMemBase: 0x%lx.\n", PeiMemBase)); | |
| DEBUG((EFI_D_ERROR, "PeiMemSize: 0x%lx.\n", PeiMemSize)); | |
| Status = PeiServicesInstallPeiMemory ( | |
| PeiMemBase, | |
| PeiMemSize | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| // | |
| // Set cache on the physical memory | |
| // | |
| MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack); | |
| MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack); | |
| // | |
| // Create Memory Type Information HOB | |
| // | |
| BuildGuidDataHob ( | |
| &gEfiMemoryTypeInformationGuid, | |
| mDefaultMemoryTypeInformation, | |
| sizeof(mDefaultMemoryTypeInformation) | |
| ); | |
| // | |
| // Create Fv hob | |
| // | |
| CbPeiReportRemainedFvs (); | |
| BuildMemoryAllocationHob ( | |
| PcdGet32 (PcdPayloadFdMemBase), | |
| PcdGet32 (PcdPayloadFdMemSize), | |
| EfiBootServicesData | |
| ); | |
| // | |
| // Build CPU memory space and IO space hob | |
| // | |
| AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); | |
| if (RegEax >= 0x80000008) { | |
| AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); | |
| PhysicalAddressBits = (UINT8) RegEax; | |
| } else { | |
| PhysicalAddressBits = 36; | |
| } | |
| // | |
| // Create a CPU hand-off information | |
| // | |
| BuildCpuHob (PhysicalAddressBits, 16); | |
| // | |
| // Report Local APIC range | |
| // | |
| BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB); | |
| // | |
| // Boot mode | |
| // | |
| Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PeiServicesInstallPpi (mPpiBootMode); | |
| ASSERT_EFI_ERROR (Status); | |
| // | |
| // Set pcd to save the upper coreboot header in case the dxecore will | |
| // erase 0~4k memory | |
| // | |
| pCbHeader = NULL; | |
| if ((CbParseGetCbHeader (1, &pCbHeader) == RETURN_SUCCESS) | |
| && ((UINTN)pCbHeader > BASE_4KB)) { | |
| DEBUG((EFI_D_ERROR, "Actual Coreboot header: %p.\n", pCbHeader)); | |
| PcdSet32 (PcdCbHeaderPointer, (UINT32)(UINTN)pCbHeader); | |
| } | |
| // | |
| // Create guid hob for system tables like acpi table and smbios table | |
| // | |
| pAcpiTable = NULL; | |
| AcpiTableSize = 0; | |
| pSmbiosTable = NULL; | |
| SmbiosTableSize = 0; | |
| Status = CbParseAcpiTable (&pAcpiTable, &AcpiTableSize); | |
| if (EFI_ERROR (Status)) { | |
| // ACPI table is oblidgible | |
| DEBUG ((EFI_D_ERROR, "Failed to find the required acpi table\n")); | |
| ASSERT (FALSE); | |
| } | |
| CbParseSmbiosTable (&pSmbiosTable, &SmbiosTableSize); | |
| pSystemTableInfo = NULL; | |
| pSystemTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO)); | |
| ASSERT (pSystemTableInfo != NULL); | |
| pSystemTableInfo->AcpiTableBase = (UINT64) (UINTN)pAcpiTable; | |
| pSystemTableInfo->AcpiTableSize = AcpiTableSize; | |
| pSystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)pSmbiosTable; | |
| pSystemTableInfo->SmbiosTableSize = SmbiosTableSize; | |
| DEBUG ((EFI_D_ERROR, "Detected Acpi Table at 0x%lx, length 0x%x\n", pSystemTableInfo->AcpiTableBase, pSystemTableInfo->AcpiTableSize)); | |
| DEBUG ((EFI_D_ERROR, "Detected Smbios Table at 0x%lx, length 0x%x\n", pSystemTableInfo->SmbiosTableBase, pSystemTableInfo->SmbiosTableSize)); | |
| DEBUG ((EFI_D_ERROR, "Create system table info guid hob\n")); | |
| // | |
| // Create guid hob for acpi board information | |
| // | |
| Status = CbParseFadtInfo (&PmCtrlRegBase, &PmTimerRegBase, &ResetRegAddress, &ResetValue, &PmEvtBase, &PmGpeEnBase); | |
| ASSERT_EFI_ERROR (Status); | |
| pAcpiBoardInfo = NULL; | |
| pAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); | |
| ASSERT (pAcpiBoardInfo != NULL); | |
| pAcpiBoardInfo->PmCtrlRegBase = (UINT64)PmCtrlRegBase; | |
| pAcpiBoardInfo->PmTimerRegBase = (UINT64)PmTimerRegBase; | |
| pAcpiBoardInfo->ResetRegAddress = (UINT64)ResetRegAddress; | |
| pAcpiBoardInfo->ResetValue = (UINT8)ResetValue; | |
| pAcpiBoardInfo->PmEvtBase = (UINT64)PmEvtBase; | |
| pAcpiBoardInfo->PmGpeEnBase = (UINT64)PmGpeEnBase; | |
| DEBUG ((EFI_D_ERROR, "Create acpi board info guid hob\n")); | |
| // | |
| // Create guid hob for frame buffer information | |
| // | |
| ZeroMem (&FbInfo, sizeof (FRAME_BUFFER_INFO)); | |
| Status = CbParseFbInfo (&FbInfo); | |
| if (!EFI_ERROR (Status)) { | |
| pFbInfo = BuildGuidHob (&gUefiFrameBufferInfoGuid, sizeof (FRAME_BUFFER_INFO)); | |
| ASSERT (pSystemTableInfo != NULL); | |
| CopyMem (pFbInfo, &FbInfo, sizeof (FRAME_BUFFER_INFO)); | |
| DEBUG ((EFI_D_ERROR, "Create frame buffer info guid hob\n")); | |
| } | |
| // | |
| // Mask off all legacy 8259 interrupt sources | |
| // | |
| IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); | |
| IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); | |
| return EFI_SUCCESS; | |
| } | |