340 lines
11 KiB
C
340 lines
11 KiB
C
/** @file
|
|
This module provide Hand-Off Block manupulation.
|
|
|
|
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <PiPei.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/BootloaderCoreLib.h>
|
|
|
|
/**
|
|
Add a new HOB to the HOB List.
|
|
|
|
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
|
@param Type Type of the new HOB.
|
|
@param Length Length of the new HOB to allocate.
|
|
@param Hob Pointer to the new HOB.
|
|
|
|
@return EFI_SUCCESS Success to create hob.
|
|
@retval EFI_INVALID_PARAMETER if Hob is NULL
|
|
@retval EFI_NOT_AVAILABLE_YET if HobList is still not available.
|
|
@retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiCreateHob (
|
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
|
IN UINT16 Type,
|
|
IN UINT16 Length,
|
|
IN OUT VOID **Hob
|
|
)
|
|
{
|
|
EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
|
|
EFI_HOB_GENERIC_HEADER *HobEnd;
|
|
EFI_PHYSICAL_ADDRESS FreeMemory;
|
|
|
|
//
|
|
// Get Hob list pointer
|
|
//
|
|
*Hob = GetHobList();
|
|
|
|
if ( *Hob == NULL ) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
HandOffHob = *Hob;
|
|
|
|
//
|
|
// Check Length to avoid data overflow.
|
|
//
|
|
if (0x10000 - Length <= 0x7) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
Length = (UINT16) ((Length + 0x7) & (~0x7));
|
|
|
|
FreeMemory = HandOffHob->EfiFreeMemoryTop -
|
|
HandOffHob->EfiFreeMemoryBottom;
|
|
|
|
if (FreeMemory < Length) {
|
|
DEBUG ((DEBUG_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length));
|
|
DEBUG ((DEBUG_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
|
|
DEBUG ((DEBUG_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
*Hob = (VOID *) (UINTN) HandOffHob->EfiEndOfHobList;
|
|
((EFI_HOB_GENERIC_HEADER *) *Hob)->HobType = Type;
|
|
((EFI_HOB_GENERIC_HEADER *) *Hob)->HobLength = Length;
|
|
((EFI_HOB_GENERIC_HEADER *) *Hob)->Reserved = 0;
|
|
|
|
HobEnd = (EFI_HOB_GENERIC_HEADER *) ((UINTN) * Hob + Length);
|
|
HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
|
|
|
|
HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
|
|
HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
|
|
HobEnd->Reserved = 0;
|
|
HobEnd++;
|
|
HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Adds a new HOB to the HOB List.
|
|
|
|
This internal function enables PEIMs to create various types of HOBs.
|
|
|
|
@param Type Type of the new HOB.
|
|
@param Length Length of the new HOB to allocate.
|
|
|
|
@retval NULL The HOB could not be allocated.
|
|
@retval others The address of new HOB.
|
|
|
|
**/
|
|
VOID *
|
|
EFIAPI
|
|
InternalPeiCreateHob (
|
|
IN UINT16 Type,
|
|
IN UINT16 Length
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *Hob;
|
|
|
|
Status = PeiCreateHob (NULL, Type, Length, &Hob);
|
|
if (EFI_ERROR (Status)) {
|
|
Hob = NULL;
|
|
}
|
|
//
|
|
// Assume the process of HOB building is always successful.
|
|
//
|
|
ASSERT (Hob != NULL);
|
|
return Hob;
|
|
}
|
|
|
|
/**
|
|
|
|
Builds a Handoff Information Table HOB
|
|
|
|
@param BootMode - Current Bootmode
|
|
@param MemoryBegin - Start Memory Address.
|
|
@param MemoryLength - Length of Memory.
|
|
|
|
@return EFI_SUCCESS Always success to initialize HOB.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BuildHobHandoffInfoTable (
|
|
IN EFI_BOOT_MODE BootMode,
|
|
IN EFI_PHYSICAL_ADDRESS MemoryBegin,
|
|
IN UINT64 MemoryLength
|
|
)
|
|
{
|
|
EFI_HOB_HANDOFF_INFO_TABLE *Hob;
|
|
EFI_HOB_GENERIC_HEADER *HobEnd;
|
|
|
|
Hob = (VOID *) (UINTN)MemoryBegin;
|
|
HobEnd = (EFI_HOB_GENERIC_HEADER *) (Hob + 1);
|
|
Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
|
|
Hob->Header.HobLength = (UINT16) sizeof (EFI_HOB_HANDOFF_INFO_TABLE);
|
|
Hob->Header.Reserved = 0;
|
|
|
|
HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
|
|
HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER);
|
|
HobEnd->Reserved = 0;
|
|
|
|
Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
|
|
Hob->BootMode = BootMode;
|
|
|
|
Hob->EfiMemoryTop = MemoryBegin + MemoryLength;
|
|
Hob->EfiMemoryBottom = MemoryBegin;
|
|
Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;
|
|
Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd + 1);
|
|
Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
|
|
|
|
SetHobList ((VOID *)Hob);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Builds a HOB that describes a chunk of system memory.
|
|
|
|
This function builds a HOB that describes a chunk of system memory.
|
|
It can only be invoked during PEI phase;
|
|
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
|
|
|
|
If there is no additional space for HOB creation, then ASSERT().
|
|
|
|
@param ResourceType The type of resource described by this HOB.
|
|
@param ResourceAttribute The resource attributes of the memory described by this HOB.
|
|
@param PhysicalStart The 64 bit physical address of memory described by this HOB.
|
|
@param NumberOfBytes The length of the memory described by this HOB in bytes.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
BuildResourceDescriptorHob (
|
|
IN EFI_RESOURCE_TYPE ResourceType,
|
|
IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
|
|
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
|
|
IN UINT64 NumberOfBytes
|
|
)
|
|
{
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
|
|
|
|
Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (UINT16) sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
|
|
if (Hob == NULL) {
|
|
return;
|
|
}
|
|
|
|
Hob->ResourceType = ResourceType;
|
|
Hob->ResourceAttribute = ResourceAttribute;
|
|
Hob->PhysicalStart = PhysicalStart;
|
|
Hob->ResourceLength = NumberOfBytes;
|
|
ZeroMem (& (Hob->Owner), sizeof (EFI_GUID));
|
|
}
|
|
|
|
/**
|
|
Builds a customized HOB tagged with a GUID for identification and returns
|
|
the start address of GUID HOB data.
|
|
|
|
This function builds a customized HOB tagged with a GUID for identification
|
|
and returns the start address of GUID HOB data so that caller can fill the customized data.
|
|
The HOB Header and Name field is already stripped.
|
|
It can only be invoked during PEI phase;
|
|
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
|
|
|
|
If Guid is NULL, then ASSERT().
|
|
If there is no additional space for HOB creation, then ASSERT().
|
|
If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
|
|
HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8.
|
|
|
|
@param Guid The GUID to tag the customized HOB.
|
|
@param DataLength The size of the data payload for the GUID HOB.
|
|
|
|
@retval NULL The GUID HOB could not be allocated.
|
|
@retval others The start address of GUID HOB data.
|
|
|
|
**/
|
|
VOID *
|
|
EFIAPI
|
|
BuildGuidHob (
|
|
IN CONST EFI_GUID *Guid,
|
|
IN UINTN DataLength
|
|
)
|
|
{
|
|
EFI_HOB_GUID_TYPE *Hob;
|
|
|
|
//
|
|
// Make sure Guid is valid
|
|
//
|
|
ASSERT (Guid != NULL);
|
|
|
|
//
|
|
// Make sure that data length is not too long.
|
|
//
|
|
ASSERT (DataLength <= (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)));
|
|
|
|
Hob = InternalPeiCreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
|
|
if (Hob == NULL) {
|
|
return Hob;
|
|
}
|
|
CopyGuid (&Hob->Name, Guid);
|
|
return Hob + 1;
|
|
}
|
|
|
|
/**
|
|
Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB
|
|
data field, and returns the start address of the GUID HOB data.
|
|
|
|
This function builds a customized HOB tagged with a GUID for identification and copies the input
|
|
data to the HOB data field and returns the start address of the GUID HOB data. It can only be
|
|
invoked during PEI phase; for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
|
|
The HOB Header and Name field is already stripped.
|
|
It can only be invoked during PEI phase;
|
|
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
|
|
|
|
If Guid is NULL, then ASSERT().
|
|
If Data is NULL and DataLength > 0, then ASSERT().
|
|
If there is no additional space for HOB creation, then ASSERT().
|
|
If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
|
|
HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8.
|
|
|
|
@param Guid The GUID to tag the customized HOB.
|
|
@param Data The data to be copied into the data field of the GUID HOB.
|
|
@param DataLength The size of the data payload for the GUID HOB.
|
|
|
|
@retval NULL The GUID HOB could not be allocated.
|
|
@retval others The start address of GUID HOB data.
|
|
|
|
**/
|
|
VOID *
|
|
EFIAPI
|
|
BuildGuidDataHob (
|
|
IN CONST EFI_GUID *Guid,
|
|
IN VOID *Data,
|
|
IN UINTN DataLength
|
|
)
|
|
{
|
|
VOID *HobData;
|
|
|
|
ASSERT (Data != NULL || DataLength == 0);
|
|
|
|
HobData = BuildGuidHob (Guid, DataLength);
|
|
if (HobData == NULL) {
|
|
return HobData;
|
|
}
|
|
|
|
return CopyMem (HobData, Data, DataLength);
|
|
}
|
|
|
|
/**
|
|
Builds a HOB that describes a chunk of system memory with Owner GUID.
|
|
|
|
This function builds a HOB that describes a chunk of system memory.
|
|
It can only be invoked during PEI phase;
|
|
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
|
|
|
|
If there is no additional space for HOB creation, then ASSERT().
|
|
|
|
@param ResourceType The type of resource described by this HOB.
|
|
@param ResourceAttribute The resource attributes of the memory described by this HOB.
|
|
@param PhysicalStart The 64 bit physical address of memory described by this HOB.
|
|
@param NumberOfBytes The length of the memory described by this HOB in bytes.
|
|
@param OwnerGUID GUID for the owner of this resource.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
BuildResourceDescriptorWithOwnerHob (
|
|
IN EFI_RESOURCE_TYPE ResourceType,
|
|
IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
|
|
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
|
|
IN UINT64 NumberOfBytes,
|
|
IN EFI_GUID *OwnerGUID
|
|
)
|
|
{
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
|
|
|
|
Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (UINT16) sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
|
|
if (Hob == NULL) {
|
|
return;
|
|
}
|
|
|
|
Hob->ResourceType = ResourceType;
|
|
Hob->ResourceAttribute = ResourceAttribute;
|
|
Hob->PhysicalStart = PhysicalStart;
|
|
Hob->ResourceLength = NumberOfBytes;
|
|
|
|
CopyGuid (&Hob->Owner, OwnerGUID);
|
|
}
|