123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- /** @file
- Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "UefiPayloadEntry.h"
- #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
- EFI_RESOURCE_ATTRIBUTE_TESTED | \
- EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
- EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
- EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
- EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
- EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
- EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
- EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
- EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
- #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
- EFI_RESOURCE_ATTRIBUTE_TESTED )
- extern VOID *mHobList;
- /**
- Print all HOBs info from the HOB list.
- @return The pointer to the HOB list.
- **/
- VOID
- PrintHob (
- IN CONST VOID *HobStart
- );
- /**
- Some bootloader may pass a pcd database, and UPL also contain a PCD database.
- Dxe PCD driver has the assumption that the two PCD database can be catenated and
- the local token number should be successive.
- This function will fix up the UPL PCD database to meet that assumption.
- @param[in] DxeFv The FV where to find the Universal PCD database.
- @retval EFI_SUCCESS If it completed successfully.
- @retval other Failed to fix up.
- **/
- EFI_STATUS
- FixUpPcdDatabase (
- IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv
- )
- {
- EFI_STATUS Status;
- EFI_FFS_FILE_HEADER *FileHeader;
- VOID *PcdRawData;
- PEI_PCD_DATABASE *PeiDatabase;
- PEI_PCD_DATABASE *UplDatabase;
- EFI_HOB_GUID_TYPE *GuidHob;
- DYNAMICEX_MAPPING *ExMapTable;
- UINTN Index;
- GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
- if (GuidHob == NULL) {
- //
- // No fix-up is needed.
- //
- return EFI_SUCCESS;
- }
- PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
- DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
- Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
- ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset);
- for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
- ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
- }
- DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
- return EFI_SUCCESS;
- }
- /**
- Add HOB into HOB list
- @param[in] Hob The HOB to be added into the HOB list.
- **/
- VOID
- AddNewHob (
- IN EFI_PEI_HOB_POINTERS *Hob
- )
- {
- EFI_PEI_HOB_POINTERS NewHob;
- if (Hob->Raw == NULL) {
- return;
- }
- NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
- if (NewHob.Header != NULL) {
- CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
- }
- }
- /**
- Found the Resource Descriptor HOB that contains a range (Base, Top)
- @param[in] HobList Hob start address
- @param[in] Base Memory start address
- @param[in] Top Memory end address.
- @retval The pointer to the Resource Descriptor HOB.
- **/
- EFI_HOB_RESOURCE_DESCRIPTOR *
- FindResourceDescriptorByRange (
- IN VOID *HobList,
- IN EFI_PHYSICAL_ADDRESS Base,
- IN EFI_PHYSICAL_ADDRESS Top
- )
- {
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
- for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // Skip all HOBs except Resource Descriptor HOBs
- //
- if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- continue;
- }
- //
- // Skip Resource Descriptor HOBs that do not describe tested system memory
- //
- ResourceHob = Hob.ResourceDescriptor;
- if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
- continue;
- }
- if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
- continue;
- }
- //
- // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
- //
- if (Base < ResourceHob->PhysicalStart) {
- continue;
- }
- if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
- continue;
- }
- return ResourceHob;
- }
- return NULL;
- }
- /**
- Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
- @param[in] HobList Hob start address
- @param[in] MinimalNeededSize Minimal needed size.
- @param[in] ExceptResourceHob Ignore this Resource Descriptor.
- @retval The pointer to the Resource Descriptor HOB.
- **/
- EFI_HOB_RESOURCE_DESCRIPTOR *
- FindAnotherHighestBelow4GResourceDescriptor (
- IN VOID *HobList,
- IN UINTN MinimalNeededSize,
- IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob
- )
- {
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
- EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;
- ReturnResourceHob = NULL;
- for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // Skip all HOBs except Resource Descriptor HOBs
- //
- if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- continue;
- }
- //
- // Skip Resource Descriptor HOBs that do not describe tested system memory
- //
- ResourceHob = Hob.ResourceDescriptor;
- if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
- continue;
- }
- if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
- continue;
- }
- //
- // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
- //
- if (ResourceHob == ExceptResourceHob) {
- continue;
- }
- //
- // Skip Resource Descriptor HOBs that are beyond 4G
- //
- if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
- continue;
- }
- //
- // Skip Resource Descriptor HOBs that are too small
- //
- if (ResourceHob->ResourceLength < MinimalNeededSize) {
- continue;
- }
- //
- // Return the topest Resource Descriptor
- //
- if (ReturnResourceHob == NULL) {
- ReturnResourceHob = ResourceHob;
- } else {
- if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
- ReturnResourceHob = ResourceHob;
- }
- }
- }
- return ReturnResourceHob;
- }
- /**
- Check the HOB and decide if it is need inside Payload
- Payload maintainer may make decision which HOB is need or needn't
- Then add the check logic in the function.
- @param[in] Hob The HOB to check
- @retval TRUE If HOB is need inside Payload
- @retval FALSE If HOB is needn't inside Payload
- **/
- BOOLEAN
- IsHobNeed (
- EFI_PEI_HOB_POINTERS Hob
- )
- {
- if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
- return FALSE;
- }
- if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
- if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
- return FALSE;
- }
- }
- // Arrive here mean the HOB is need
- return TRUE;
- }
- /**
- It will build HOBs based on information from bootloaders.
- @param[in] BootloaderParameter The starting memory address of bootloader parameter block.
- @param[out] DxeFv The pointer to the DXE FV in memory.
- @retval EFI_SUCCESS If it completed successfully.
- @retval Others If it failed to build required HOBs.
- **/
- EFI_STATUS
- BuildHobs (
- IN UINTN BootloaderParameter,
- OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
- )
- {
- EFI_PEI_HOB_POINTERS Hob;
- UINTN MinimalNeededSize;
- EFI_PHYSICAL_ADDRESS FreeMemoryBottom;
- EFI_PHYSICAL_ADDRESS FreeMemoryTop;
- EFI_PHYSICAL_ADDRESS MemoryBottom;
- EFI_PHYSICAL_ADDRESS MemoryTop;
- EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
- UNIVERSAL_PAYLOAD_EXTRA_DATA *ExtraData;
- UINT8 *GuidHob;
- EFI_HOB_FIRMWARE_VOLUME *FvHob;
- UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
- ACPI_BOARD_INFO *AcpiBoardInfo;
- EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
- UINT8 Idx;
- Hob.Raw = (UINT8 *)BootloaderParameter;
- MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
- ASSERT (Hob.Raw != NULL);
- ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
- ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
- ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
- ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
- //
- // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
- //
- PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
- if (PhitResourceHob == NULL) {
- //
- // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
- //
- ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
- if (ResourceHob == NULL) {
- return EFI_NOT_FOUND;
- }
- MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
- FreeMemoryBottom = MemoryBottom;
- FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
- MemoryTop = FreeMemoryTop;
- } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
- //
- // New availiable Memory range in new hob is right above memory top in old hob.
- //
- MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop;
- FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
- FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize;
- MemoryTop = FreeMemoryTop;
- } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
- //
- // New availiable Memory range in new hob is right below memory bottom in old hob.
- //
- MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
- FreeMemoryBottom = MemoryBottom;
- FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom;
- MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop;
- } else {
- //
- // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
- // Find another Resource Descriptor Hob
- //
- ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
- if (ResourceHob == NULL) {
- return EFI_NOT_FOUND;
- }
- MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
- FreeMemoryBottom = MemoryBottom;
- FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
- MemoryTop = FreeMemoryTop;
- }
- HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
- HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
- //
- // From now on, mHobList will point to the new Hob range.
- //
- //
- // Create an empty FvHob for the DXE FV that contains DXE core.
- //
- BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
- //
- // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
- //
- while (!END_OF_HOB_LIST (Hob)) {
- if (IsHobNeed (Hob)) {
- // Add this hob to payload HOB
- AddNewHob (&Hob);
- }
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
- //
- // Get DXE FV location
- //
- GuidHob = GetFirstGuidHob (&gUniversalPayloadExtraDataGuid);
- ASSERT (GuidHob != NULL);
- ExtraData = (UNIVERSAL_PAYLOAD_EXTRA_DATA *)GET_GUID_HOB_DATA (GuidHob);
- DEBUG ((DEBUG_INFO, "Multiple Fv Count=%d\n", ExtraData->Count));
- ASSERT (AsciiStrCmp (ExtraData->Entry[0].Identifier, "uefi_fv") == 0);
- *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)ExtraData->Entry[0].Base;
- ASSERT ((*DxeFv)->FvLength == ExtraData->Entry[0].Size);
- //
- // support multiple FVs provided by UPL
- //
- for (Idx = 1; Idx < ExtraData->Count; Idx++) {
- BuildFvHob (ExtraData->Entry[Idx].Base, ExtraData->Entry[Idx].Size);
- DEBUG ((
- DEBUG_INFO,
- "UPL Multiple fv[%d], Base=0x%x, size=0x%x\n",
- Idx,
- ExtraData->Entry[Idx].Base,
- ExtraData->Entry[Idx].Size
- ));
- }
- //
- // Create guid hob for acpi board information
- //
- GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
- if (GuidHob != NULL) {
- AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
- AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
- ASSERT (AcpiBoardInfo != NULL);
- }
- //
- // Update DXE FV information to first fv hob in the hob list, which
- // is the empty FvHob created before.
- //
- FvHob = GetFirstHob (EFI_HOB_TYPE_FV);
- FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
- FvHob->Length = (*DxeFv)->FvLength;
- return EFI_SUCCESS;
- }
- /**
- Entry point to the C language phase of UEFI payload.
- @param[in] BootloaderParameter The starting address of bootloader parameter block.
- @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
- **/
- EFI_STATUS
- EFIAPI
- _ModuleEntryPoint (
- IN UINTN BootloaderParameter
- )
- {
- EFI_STATUS Status;
- PHYSICAL_ADDRESS DxeCoreEntryPoint;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_FIRMWARE_VOLUME_HEADER *DxeFv;
- mHobList = (VOID *)BootloaderParameter;
- DxeFv = NULL;
- // Call constructor for all libraries
- ProcessLibraryConstructorList ();
- DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
- DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
- DEBUG_CODE (
- //
- // Dump the Hobs from boot loader
- //
- PrintHob (mHobList);
- );
- // Initialize floating point operating environment to be compliant with UEFI spec.
- InitializeFloatingPointUnits ();
- // Build HOB based on information from Bootloader
- Status = BuildHobs (BootloaderParameter, &DxeFv);
- ASSERT_EFI_ERROR (Status);
- FixUpPcdDatabase (DxeFv);
- Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
- ASSERT_EFI_ERROR (Status);
- //
- // Mask off all legacy 8259 interrupt sources
- //
- IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
- IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
- Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
- HandOffToDxeCore (DxeCoreEntryPoint, Hob);
- // Should not get here
- CpuDeadLoop ();
- return EFI_SUCCESS;
- }
|