/** @file Copyright (c) 2006 - 2007, Intel Corporation All rights reserved. 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. Module Name: HobGeneration.c Abstract: Revision History: **/ #include "DxeIpl.h" #include "HobGeneration.h" #include "PpisNeededByDxeCore.h" #include "FlashLayout.h" #include "Debug.h" #define EFI_DXE_FILE_GUID \ { 0xb1644c1a, 0xc16a, 0x4c5b, {0x88, 0xde, 0xea, 0xfb, 0xa9, 0x7e, 0x74, 0xd8 }} #define CPUID_EXTENDED_ADD_SIZE 0x80000008 HOB_TEMPLATE gHobTemplate = { { // Phit { // Header EFI_HOB_TYPE_HANDOFF, // HobType sizeof (EFI_HOB_HANDOFF_INFO_TABLE), // HobLength 0 // Reserved }, EFI_HOB_HANDOFF_TABLE_VERSION, // Version BOOT_WITH_FULL_CONFIGURATION, // BootMode 0, // EfiMemoryTop 0, // EfiMemoryBottom 0, // EfiFreeMemoryTop 0, // EfiFreeMemoryBottom 0 // EfiEndOfHobList }, { // Bfv { EFI_HOB_TYPE_FV, // HobType sizeof (EFI_HOB_FIRMWARE_VOLUME), // HobLength 0 // Reserved }, 0, // BaseAddress 0 // Length }, { // BfvResource { EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength 0 // Reserved }, { 0 // Owner Guid }, EFI_RESOURCE_FIRMWARE_DEVICE, // ResourceType (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), // ResourceAttribute 0, // PhysicalStart 0 // ResourceLength }, { // Cpu { // Header EFI_HOB_TYPE_CPU, // HobType sizeof (EFI_HOB_CPU), // HobLength 0 // Reserved }, 52, // SizeOfMemorySpace - Architecture Max 16, // SizeOfIoSpace, { 0, 0, 0, 0, 0, 0 // Reserved[6] } }, { // Stack HOB { // header EFI_HOB_TYPE_MEMORY_ALLOCATION, // Hob type sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK), // Hob size 0 // reserved }, { EFI_HOB_MEMORY_ALLOC_STACK_GUID, 0x0, // EFI_PHYSICAL_ADDRESS MemoryBaseAddress; 0x0, // UINT64 MemoryLength; EfiBootServicesData, // EFI_MEMORY_TYPE MemoryType; {0, 0, 0, 0} // Reserved Reserved[4]; } }, { // MemoryAllocation for HOB's & Images { EFI_HOB_TYPE_MEMORY_ALLOCATION, // HobType sizeof (EFI_HOB_MEMORY_ALLOCATION), // HobLength 0 // Reserved }, { { 0, //EFI_HOB_MEMORY_ALLOC_MODULE_GUID // Name }, 0x0, // EFI_PHYSICAL_ADDRESS MemoryBaseAddress; 0x0, // UINT64 MemoryLength; EfiBootServicesData, // EFI_MEMORY_TYPE MemoryType; { 0, 0, 0, 0 // Reserved Reserved[4]; } } }, { // MemoryFreeUnder1MB for unused memory that DXE core will claim { EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength 0 // Reserved }, { 0 // Owner Guid }, EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_TESTED | 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), 0x0, // PhysicalStart 0 // ResourceLength }, { // MemoryFreeAbove1MB for unused memory that DXE core will claim { EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength 0 // Reserved }, { 0 // Owner Guid }, EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_TESTED | 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), 0x0, // PhysicalStart 0 // ResourceLength }, { // MemoryFreeAbove4GB for unused memory that DXE core will claim { EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength 0 // Reserved }, { 0 // Owner Guid }, EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType (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), 0x0, // PhysicalStart 0 // ResourceLength }, { // Memory Allocation Module for DxeCore { // header EFI_HOB_TYPE_MEMORY_ALLOCATION, // Hob type sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE), // Hob size 0 // reserved }, { EFI_HOB_MEMORY_ALLOC_MODULE_GUID, 0x0, // EFI_PHYSICAL_ADDRESS MemoryBaseAddress; 0x0, // UINT64 MemoryLength; EfiBootServicesCode, // EFI_MEMORY_TYPE MemoryType; { 0, 0, 0, 0 // UINT8 Reserved[4]; }, }, EFI_DXE_FILE_GUID, 0x0 // EFI_PHYSICAL_ADDRESS of EntryPoint; }, { // Memory Map Hints to reduce fragmentation in the memory map { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (MEMORY_TYPE_INFORMATION_HOB), // Hob size 0, // reserved }, EFI_MEMORY_TYPE_INFORMATION_GUID }, { { EfiACPIReclaimMemory, 0x80 }, // 0x80 pages = 512k for ASL { EfiACPIMemoryNVS, 0x100 }, // 0x100 pages = 1024k for S3, SMM, etc { EfiReservedMemoryType, 0x04 }, // 16k for BIOS Reserved { EfiRuntimeServicesData, 0x100 }, { EfiRuntimeServicesCode, 0x100 }, { EfiBootServicesCode, 0x200 }, { EfiBootServicesData, 0x200 }, { EfiLoaderCode, 0x100 }, { EfiLoaderData, 0x100 }, { EfiMaxMemoryType, 0 } } }, { // Pointer to ACPI Table { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (TABLE_HOB), // Hob size 0 // reserved }, EFI_ACPI_TABLE_GUID }, 0 }, { // Pointer to ACPI20 Table { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (TABLE_HOB), // Hob size 0 // reserved }, EFI_ACPI_20_TABLE_GUID }, 0 }, { // Pointer to SMBIOS Table { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (TABLE_HOB), // Hob size 0 // reserved }, EFI_SMBIOS_TABLE_GUID }, 0 }, { // Pointer to MPS Table { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (TABLE_HOB), // Hob size 0, // reserved }, EFI_MPS_TABLE_GUID }, 0 }, /** { // Pointer to FlushInstructionCache EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PROTOCOL_HOB), // Hob size 0, // reserved EFI_PEI_FLUSH_INSTRUCTION_CACHE_GUID, NULL }, { // Pointer to TransferControl EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PROTOCOL_HOB), // Hob size 0, // reserved EFI_PEI_TRANSFER_CONTROL_GUID, NULL }, { // Pointer to PeCoffLoader EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PROTOCOL_HOB), // Hob size 0, // reserved EFI_PEI_PE_COFF_LOADER_GUID, NULL }, { // Pointer to EfiDecompress EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PROTOCOL_HOB), // Hob size 0, // reserved EFI_DECOMPRESS_PROTOCOL_GUID, NULL }, { // Pointer to TianoDecompress EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PROTOCOL_HOB), // Hob size 0, // reserved EFI_TIANO_DECOMPRESS_PROTOCOL_GUID, NULL }, **/ { // Pointer to ReportStatusCode { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PROTOCOL_HOB), // Hob size 0 // reserved }, EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID }, NULL }, { // EFILDR Memory Descriptor { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (MEMORY_DESC_HOB), // Hob size 0 // reserved }, EFI_LDR_MEMORY_DESCRIPTOR_GUID }, 0, NULL }, { // Pci Express Base Address Hob { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (PCI_EXPRESS_BASE_HOB), // Hob size 0 // reserved }, EFI_PCI_EXPRESS_BASE_ADDRESS_GUID }, { 0, 0, 0, } }, { // Acpi Description Hob { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (ACPI_DESCRIPTION_HOB), // Hob size 0 // reserved }, EFI_ACPI_DESCRIPTION_GUID }, { { 0, }, } }, { // NV Storage FV Resource { EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength 0 // Reserved }, { 0 // Owner Guid }, EFI_RESOURCE_FIRMWARE_DEVICE, // ResourceType (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), // ResourceAttribute 0, // PhysicalStart (Fixed later) NV_STORAGE_FVB_SIZE // ResourceLength }, { // FVB holding NV Storage { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (FVB_HOB), 0 }, EFI_FLASH_MAP_HOB_GUID }, { {0, 0, 0}, // Reserved[3] EFI_FLASH_AREA_GUID_DEFINED, // AreaType EFI_SYSTEM_NV_DATA_HOB_GUID, // AreaTypeGuid 1, { { EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes 0, // SubAreaData.Reserved 0, // SubAreaData.Base (Fixed later) NV_STORAGE_FVB_SIZE, // SubAreaData.Length EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem } }, 0, // VolumeSignature (Fixed later) NV_STORAGE_FILE_PATH, // Mapped file without padding // TotalFVBSize = FileSize + PaddingSize = multiple of BLOCK_SIZE NV_STORAGE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH, // ActuralSize EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH } }, { // NV Storage Hob { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (FVB_HOB), // Hob size 0 // reserved }, EFI_FLASH_MAP_HOB_GUID }, { {0, 0, 0}, // Reserved[3] EFI_FLASH_AREA_EFI_VARIABLES, // AreaType { 0 }, // AreaTypeGuid 1, { { EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes 0, // SubAreaData.Reserved 0, // SubAreaData.Base (Fixed later) NV_STORAGE_SIZE, // SubAreaData.Length EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem } }, 0, NV_STORAGE_FILE_PATH, NV_STORAGE_SIZE, 0 } }, { // FVB holding FTW spaces including Working & Spare space { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (FVB_HOB), 0 }, EFI_FLASH_MAP_HOB_GUID }, { {0, 0, 0}, // Reserved[3] EFI_FLASH_AREA_GUID_DEFINED, // AreaType EFI_SYSTEM_NV_DATA_HOB_GUID, // AreaTypeGuid 1, { { EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes 0, // SubAreaData.Reserved 0, // SubAreaData.Base (Fixed later) NV_FTW_FVB_SIZE, // SubAreaData.Length EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem } }, 0, L"", // Empty String indicates using memory 0, 0 } }, { // NV Ftw working Hob { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (FVB_HOB), // Hob size 0 // reserved }, EFI_FLASH_MAP_HOB_GUID }, { {0, 0, 0}, // Reserved[3] EFI_FLASH_AREA_FTW_STATE, // AreaType { 0 }, // AreaTypeGuid 1, { { EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes 0, // SubAreaData.Reserved 0, // SubAreaData.Base (Fixed later) NV_FTW_WORKING_SIZE, // SubAreaData.Length EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem } }, 0, // VolumeSignature L"", 0, 0 } }, { // NV Ftw spare Hob { { EFI_HOB_TYPE_GUID_EXTENSION, // Hob type sizeof (FVB_HOB), // Hob size 0 // reserved }, EFI_FLASH_MAP_HOB_GUID }, { {0, 0, 0}, // Reserved[3] EFI_FLASH_AREA_FTW_BACKUP, // AreaType { 0 }, // AreaTypeGuid 1, { { EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes 0, // SubAreaData.Reserved 0, // SubAreaData.Base (Fixed later) NV_FTW_SPARE_SIZE, // SubAreaData.Length EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem } }, 0, L"", 0, 0 } }, { // EndOfHobList EFI_HOB_TYPE_END_OF_HOB_LIST, // HobType sizeof (EFI_HOB_GENERIC_HEADER), // HobLength 0 // Reserved } }; HOB_TEMPLATE *gHob = &gHobTemplate; VOID * PrepareHobMemory ( IN UINTN NumberOfMemoryMapEntries, IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor ) /*++ Description: Update the Hob filling MemoryFreeUnder1MB, MemoryAbove1MB, MemoryAbove4GB Arguments: NumberOfMemoryMapEntries - Count of Memory Descriptors EfiMemoryDescriptor - Point to the buffer containing NumberOfMemoryMapEntries Memory Descriptors Return: VOID * : The end address of MemoryAbove1MB (or the top free memory under 4GB) --*/ { UINTN Index; // // Prepare Low Memory // 0x18 pages is 72 KB. // gHob->MemoryFreeUnder1MB.ResourceLength = EFI_MEMORY_BELOW_1MB_END - EFI_MEMORY_BELOW_1MB_START; gHob->MemoryFreeUnder1MB.PhysicalStart = EFI_MEMORY_BELOW_1MB_START; // // Prepare High Memory // Assume Memory Map is ordered from low to high // gHob->MemoryAbove1MB.PhysicalStart = 0; gHob->MemoryAbove1MB.ResourceLength = 0; gHob->MemoryAbove4GB.PhysicalStart = 0; gHob->MemoryAbove4GB.ResourceLength = 0; for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) { // // Skip regions below 1MB // if (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000) { continue; } // // Process regions above 1MB // if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000) { if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) { if (gHob->MemoryAbove1MB.PhysicalStart == 0) { gHob->MemoryAbove1MB.PhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; gHob->MemoryAbove1MB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); } else if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength == EfiMemoryDescriptor[Index].PhysicalStart) { gHob->MemoryAbove1MB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); } } if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) || (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) { continue; } if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) || (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) { break; } } // // Process region above 4GB // if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000000LL) { if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) { if (gHob->MemoryAbove4GB.PhysicalStart == 0) { gHob->MemoryAbove4GB.PhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; gHob->MemoryAbove4GB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); } if (gHob->MemoryAbove4GB.PhysicalStart + gHob->MemoryAbove4GB.ResourceLength == EfiMemoryDescriptor[Index].PhysicalStart) { gHob->MemoryAbove4GB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); } } } } if (gHob->MemoryAbove4GB.ResourceLength == 0) { // // If there is no memory above 4GB then change the resource descriptor HOB // into another type. I'm doing this as it's unclear if a resource // descriptor HOB of length zero is valid. Spec does not say it's illegal, // but code in EDK does not seem to handle this case. // gHob->MemoryAbove4GB.Header.HobType = EFI_HOB_TYPE_UNUSED; } return (VOID *)(UINTN)(gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength); } VOID * PrepareHobStack ( IN VOID *StackTop ) { gHob->Stack.AllocDescriptor.MemoryLength = EFI_MEMORY_STACK_PAGE_NUM * EFI_PAGE_SIZE; gHob->Stack.AllocDescriptor.MemoryBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)StackTop - gHob->Stack.AllocDescriptor.MemoryLength; return (VOID *)(UINTN)gHob->Stack.AllocDescriptor.MemoryBaseAddress; } VOID * PrepareHobMemoryDescriptor ( VOID *MemoryDescriptorTop, UINTN MemDescCount, EFI_MEMORY_DESCRIPTOR *MemDesc ) { gHob->MemoryDescriptor.MemDescCount = MemDescCount; gHob->MemoryDescriptor.MemDesc = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryDescriptorTop - MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR)); // // Make MemoryDescriptor.MemDesc page aligned // gHob->MemoryDescriptor.MemDesc = (EFI_MEMORY_DESCRIPTOR *)((UINTN) gHob->MemoryDescriptor.MemDesc & ~EFI_PAGE_MASK); CopyMem (gHob->MemoryDescriptor.MemDesc, MemDesc, MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR)); return gHob->MemoryDescriptor.MemDesc; } VOID PrepareHobBfv ( VOID *Bfv, UINTN BfvLength ) { //UINTN BfvLengthPageSize; // // Calculate BFV location at top of the memory region. // This is like a RAM Disk. Align to page boundry. // //BfvLengthPageSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (BfvLength)); gHob->Bfv.BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Bfv; gHob->Bfv.Length = BfvLength; // // Resource descriptor for the FV // gHob->BfvResource.PhysicalStart = gHob->Bfv.BaseAddress; gHob->BfvResource.ResourceLength = gHob->Bfv.Length; } VOID PrepareHobDxeCore ( VOID *DxeCoreEntryPoint, EFI_PHYSICAL_ADDRESS DxeCoreImageBase, UINT64 DxeCoreLength ) { gHob->DxeCore.MemoryAllocationHeader.MemoryBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreImageBase; gHob->DxeCore.MemoryAllocationHeader.MemoryLength = DxeCoreLength; gHob->DxeCore.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreEntryPoint; } VOID * PrepareHobNvStorage ( VOID *NvStorageTop ) /* Initialize Block-Aligned Firmware Block. Variable: +-------------------+ | FV_Header | +-------------------+ | | |VAR_STORAGE(0x4000)| | | +-------------------+ FTW: +-------------------+ | FV_Header | +-------------------+ | | | Working(0x2000) | | | +-------------------+ | | | Spare(0x10000) | | | +-------------------+ */ { STATIC VARIABLE_STORE_HEADER VarStoreHeader = { VARIABLE_STORE_SIGNATURE, 0xffffffff, // will be fixed in Variable driver VARIABLE_STORE_FORMATTED, VARIABLE_STORE_HEALTHY, 0, 0 }; STATIC EFI_FIRMWARE_VOLUME_HEADER NvStorageFvbHeader = { { 0, }, // ZeroVector[16] EFI_SYSTEM_NV_DATA_FV_GUID, NV_STORAGE_FVB_SIZE, EFI_FVH_SIGNATURE, EFI_FVB_READ_ENABLED_CAP | EFI_FVB_READ_STATUS | EFI_FVB_WRITE_ENABLED_CAP | EFI_FVB_WRITE_STATUS | EFI_FVB_ERASE_POLARITY, EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH, 0, // CheckSum 0, // ExtHeaderOffset { 0, }, // Reserved[1] 1, // Revision { { NV_STORAGE_FVB_BLOCK_NUM, FV_BLOCK_SIZE, } } }; STATIC EFI_FV_BLOCK_MAP_ENTRY BlockMapEntryEnd = {0, 0}; EFI_PHYSICAL_ADDRESS StorageFvbBase; EFI_PHYSICAL_ADDRESS FtwFvbBase; UINT16 *Ptr; UINT16 Checksum; // // Use first 16-byte Reset Vector of FVB to store extra information // UINT32 Offset 0 stores the volume signature // UINT8 Offset 4 : should init the Variable Store Header if non-zero // gHob->NvStorageFvb.FvbInfo.VolumeId = *(UINT32 *) (UINTN) (NV_STORAGE_STATE); gHob->NvStorage. FvbInfo.VolumeId = *(UINT32 *) (UINTN) (NV_STORAGE_STATE); // // *(NV_STORAGE_STATE + 4): // 2 - Size error // 1 - File not exist // 0 - File exist with correct size // if (*(UINT8 *) (UINTN) (NV_STORAGE_STATE + 4) == 2) { ClearScreen (); PrintString ("Error: Size of Efivar.bin should be 16k!\n"); CpuDeadLoop(); } if (*(UINT8 *) (UINTN) (NV_STORAGE_STATE + 4) != 0) { // // Efivar.bin doesn't exist // 1. Init variable storage header to valid header // CopyMem ( (VOID *) (UINTN) NV_STORAGE_START, &VarStoreHeader, sizeof (VARIABLE_STORE_HEADER) ); // // 2. set all bits in variable storage body to 1 // SetMem ( (VOID *) (UINTN) (NV_STORAGE_START + sizeof (VARIABLE_STORE_HEADER)), NV_STORAGE_SIZE - sizeof (VARIABLE_STORE_HEADER), 0xff ); } // // Relocate variable storage // // 1. Init FVB Header to valid header: First 0x48 bytes // In real platform, these fields are fixed by tools // // Checksum = 0; for ( Ptr = (UINT16 *) &NvStorageFvbHeader; Ptr < (UINT16 *) ((UINTN) (UINT8 *) &NvStorageFvbHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER)); ++Ptr ) { Checksum = (UINT16) (Checksum + (*Ptr)); } NvStorageFvbHeader.Checksum = (UINT16) (0x10000 - Checksum); StorageFvbBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)NvStorageTop - NV_STORAGE_FVB_SIZE - NV_FTW_FVB_SIZE) & ~EFI_PAGE_MASK); CopyMem ((VOID *) (UINTN) StorageFvbBase, &NvStorageFvbHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); CopyMem ( (VOID *) (UINTN) (StorageFvbBase + sizeof (EFI_FIRMWARE_VOLUME_HEADER)), &BlockMapEntryEnd, sizeof (EFI_FV_BLOCK_MAP_ENTRY) ); // // 2. Relocate variable data // CopyMem ( (VOID *) (UINTN) (StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH), (VOID *) (UINTN) NV_STORAGE_START, NV_STORAGE_SIZE ); // // 3. Set the remaining memory to 0xff // SetMem ( (VOID *) (UINTN) (StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + NV_STORAGE_SIZE), NV_STORAGE_FVB_SIZE - NV_STORAGE_SIZE - EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH, 0xff ); // // Create the FVB holding NV Storage in memory // gHob->NvStorageFvResource.PhysicalStart = gHob->NvStorageFvb.FvbInfo.Entries[0].Base = StorageFvbBase; // // Create the NV Storage Hob // gHob->NvStorage.FvbInfo.Entries[0].Base = StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH; // // Create the FVB holding FTW spaces // FtwFvbBase = (EFI_PHYSICAL_ADDRESS)((UINTN) StorageFvbBase + NV_STORAGE_FVB_SIZE); gHob->NvFtwFvb.FvbInfo.Entries[0].Base = FtwFvbBase; // // Put FTW Working in front // gHob->NvFtwWorking.FvbInfo.Entries[0].Base = FtwFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH; // // Put FTW Spare area after FTW Working area // gHob->NvFtwSpare.FvbInfo.Entries[0].Base = (EFI_PHYSICAL_ADDRESS)((UINTN) FtwFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + NV_FTW_WORKING_SIZE); return (VOID *)(UINTN)StorageFvbBase; } VOID PrepareHobPhit ( VOID *MemoryTop, VOID *FreeMemoryTop ) { gHob->Phit.EfiMemoryTop = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryTop; gHob->Phit.EfiMemoryBottom = gHob->Phit.EfiMemoryTop - CONSUMED_MEMORY; gHob->Phit.EfiFreeMemoryTop = (EFI_PHYSICAL_ADDRESS)(UINTN)FreeMemoryTop; gHob->Phit.EfiFreeMemoryBottom = gHob->Phit.EfiMemoryBottom + sizeof(HOB_TEMPLATE); CopyMem ((VOID *)(UINTN)gHob->Phit.EfiMemoryBottom, gHob, sizeof(HOB_TEMPLATE)); gHob = (HOB_TEMPLATE *)(UINTN)gHob->Phit.EfiMemoryBottom; gHob->Phit.EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)&gHob->EndOfHobList; } VOID PrepareHobCpu ( VOID ) { EFI_CPUID_REGISTER Reg; UINT8 CpuMemoryAddrBitNumber; // // Create a CPU hand-off information // CpuMemoryAddrBitNumber = 36; AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &Reg.RegEax, &Reg.RegEbx, &Reg.RegEcx, &Reg.RegEdx); if (Reg.RegEax >= CPUID_EXTENDED_ADD_SIZE) { AsmCpuid (CPUID_EXTENDED_ADD_SIZE, &Reg.RegEax, &Reg.RegEbx, &Reg.RegEcx, &Reg.RegEdx); CpuMemoryAddrBitNumber = (UINT8)(UINTN)(Reg.RegEax & 0xFF); } gHob->Cpu.SizeOfMemorySpace = CpuMemoryAddrBitNumber; } VOID CompleteHobGeneration ( VOID ) { gHob->MemoryAllocation.AllocDescriptor.MemoryBaseAddress = gHob->Phit.EfiFreeMemoryTop; // // Reserve all the memory under Stack above FreeMemoryTop as allocated // gHob->MemoryAllocation.AllocDescriptor.MemoryLength = gHob->Stack.AllocDescriptor.MemoryBaseAddress - gHob->Phit.EfiFreeMemoryTop; // // adjust Above1MB ResourceLength // if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength > gHob->Phit.EfiMemoryTop) { gHob->MemoryAbove1MB.ResourceLength = gHob->Phit.EfiMemoryTop - gHob->MemoryAbove1MB.PhysicalStart; } }