blob: 224d6a710e9a2fae3f18b266a8a9c56c6cf91965 [file] [log] [blame]
/** @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;
},
{ // MemoryDxeCore
{
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 | // Do not mark as TESTED, or DxeCore will find it and use it before check Allocation
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 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
},
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_FV_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
}
},
{ // NV Ftw 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_FTW_FVB_SIZE // ResourceLength
},
{ // 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_FV_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 = DxeCoreImageBase;
gHob->DxeCore.MemoryAllocationHeader.MemoryLength = DxeCoreLength;
gHob->DxeCore.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreEntryPoint;
gHob->MemoryDxeCore.PhysicalStart = DxeCoreImageBase;
gHob->MemoryDxeCore.ResourceLength = DxeCoreLength;
}
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->NvFtwFvResource.PhysicalStart =
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;
}
}