From 6b68b4a42f9858102f2c804026ed1ce136e15813 Mon Sep 17 00:00:00 2001 From: Levi Yun Date: Mon, 13 May 2024 10:10:05 +0100 Subject: [PATCH] feat(lib): modify Hob creation code imported from edk2 According to Platform Initialization (PI) Specification [1] and Discussion on edk2 mailing list [2], StandaloneMm shouldn't create Hob but it should be passed from TF-A. IOW, TF-A should pass boot information via PHIT Hob to initialize StandaloneMm properly. This patch modifies Hob creation code from edk2 codebase so that TF-A could create Hob information properly to boot StandaloneMm Link: https://uefi.org/sites/default/files/resources/PI_Spec_1_6.pdf [1] Link: https://edk2.groups.io/g/devel/topic/103675962#114283 [2] Signed-off-by: Levi Yun Change-Id: I5e427b620d8006b118b266370bd08d4b0ff56a83 --- docs/license.rst | 7 + lib/hob/StandaloneMmCoreHobLib.c | 367 ------------------------------- lib/hob/hob.c | 222 +++++++++++++++++++ 3 files changed, 229 insertions(+), 367 deletions(-) delete mode 100644 lib/hob/StandaloneMmCoreHobLib.c create mode 100644 lib/hob/hob.c diff --git a/docs/license.rst b/docs/license.rst index 9e0298b7f..22d0e067d 100644 --- a/docs/license.rst +++ b/docs/license.rst @@ -110,6 +110,12 @@ license text is included in those source files. - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py`` - ``tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py`` +- Some source files originating from the `edk2`_ project. + These files are licensed under the BSD-2-Clause. Any contributions to this + code must also be made under the terms of BSD-2-Clause. + These files are: + + - ``lib/hob/hob.c`` .. _FreeBSD: http://www.freebsd.org .. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT @@ -117,3 +123,4 @@ license text is included in those source files. .. _Open Profile for DICE: https://pigweed.googlesource.com/open-dice/ .. _Apache License 2.0: https://www.apache.org/licenses/LICENSE-2.0.txt .. _pydevicetree: https://pypi.org/project/pydevicetree/ +.. _edk2: https://github.com/tianocore/edk2 diff --git a/lib/hob/StandaloneMmCoreHobLib.c b/lib/hob/StandaloneMmCoreHobLib.c deleted file mode 100644 index afe20f858..000000000 --- a/lib/hob/StandaloneMmCoreHobLib.c +++ /dev/null @@ -1,367 +0,0 @@ -/** @file - HOB Library implementation for Standalone MM Core. - -Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
-Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
- -SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include - -#include -#include -#include - -#include - -// -// Cache copy of HobList pointer. -// -VOID *gHobList = NULL; - -VOID * -CreateHob ( - IN UINT16 HobType, - IN UINT16 HobLength - ) -{ - EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; - EFI_HOB_GENERIC_HEADER *HobEnd; - EFI_PHYSICAL_ADDRESS FreeMemory; - VOID *Hob; - - HandOffHob = GetHobList (); - - // - // Check Length to avoid data overflow. - // - if (HobLength > MAX_UINT16 - 0x7) { - return NULL; - } - - HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); - - FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; - - if (FreeMemory < HobLength) { - return NULL; - } - - Hob = (VOID *)(UINTN)HandOffHob->EfiEndOfHobList; - ((EFI_HOB_GENERIC_HEADER *)Hob)->HobType = HobType; - ((EFI_HOB_GENERIC_HEADER *)Hob)->HobLength = HobLength; - ((EFI_HOB_GENERIC_HEADER *)Hob)->Reserved = 0; - - HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)Hob + HobLength); - HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; - - HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; - HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER); - HobEnd->Reserved = 0; - HobEnd++; - HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; - - return Hob; -} - -/** - Builds a HOB for a loaded PE32 module. - - This function builds a HOB for a loaded PE32 module. - If ModuleName is NULL, then ASSERT(). - If there is no additional space for HOB creation, then ASSERT(). - - @param ModuleName The GUID File Name of the module. - @param MemoryAllocationModule The 64 bit physical address of the module. - @param ModuleLength The length of the module in bytes. - @param EntryPoint The 64 bit physical address of the module entry point. - -**/ -VOID -EFIAPI -BuildModuleHob ( - IN CONST EFI_GUID *ModuleName, - IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, - IN UINT64 ModuleLength, - IN EFI_PHYSICAL_ADDRESS EntryPoint - ) -{ - EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; - - ASSERT ( - ((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && - ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0) - ); - - Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return; - } - - CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); - Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; - Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; - Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; - - // - // Zero the reserved space to match HOB spec - // - ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); - - CopyGuid (&Hob->ModuleName, ModuleName); - Hob->EntryPoint = EntryPoint; -} - -/** - Builds a HOB that describes a chunk of system memory. - - This function builds a HOB that describes a chunk of system memory. - 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 = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return; - } - - Hob->ResourceType = ResourceType; - Hob->ResourceAttribute = ResourceAttribute; - Hob->PhysicalStart = PhysicalStart; - Hob->ResourceLength = NumberOfBytes; -} - -/** - Builds a GUID HOB with a certain data length. - - 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. - If Guid is NULL, then ASSERT(). - If there is no additional space for HOB creation, then ASSERT(). - If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). - - @param Guid The GUID to tag the customized HOB. - @param DataLength The size of the data payload for the GUID HOB. - - @return 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 that data length is not too long. - // - ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); - - Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return NULL; - } - - CopyGuid (&Hob->Name, Guid); - return Hob + 1; -} - -/** - Copies a data buffer to a newly-built HOB. - - This function 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. - The HOB Header and Name field is already stripped. - 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 >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). - - @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. - - @return 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); - - return CopyMem (HobData, Data, DataLength); -} - -/** - Builds a Firmware Volume HOB. - - This function builds a Firmware Volume HOB. - If there is no additional space for HOB creation, then ASSERT(). - - @param BaseAddress The base address of the Firmware Volume. - @param Length The size of the Firmware Volume in bytes. - -**/ -VOID -EFIAPI -BuildFvHob ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length - ) -{ - EFI_HOB_FIRMWARE_VOLUME *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return; - } - - Hob->BaseAddress = BaseAddress; - Hob->Length = Length; -} - -/** - Builds a EFI_HOB_TYPE_FV2 HOB. - - This function builds a EFI_HOB_TYPE_FV2 HOB. - If there is no additional space for HOB creation, then ASSERT(). - - @param BaseAddress The base address of the Firmware Volume. - @param Length The size of the Firmware Volume in bytes. - @param FvName The name of the Firmware Volume. - @param FileName The name of the file. - -**/ -VOID -EFIAPI -BuildFv2Hob ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN CONST EFI_GUID *FvName, - IN CONST EFI_GUID *FileName - ) -{ - EFI_HOB_FIRMWARE_VOLUME2 *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return; - } - - Hob->BaseAddress = BaseAddress; - Hob->Length = Length; - CopyGuid (&Hob->FvName, FvName); - CopyGuid (&Hob->FileName, FileName); -} - -/** - Builds a HOB for the CPU. - - This function builds a HOB for the CPU. - If there is no additional space for HOB creation, then ASSERT(). - - @param SizeOfMemorySpace The maximum physical memory addressability of the processor. - @param SizeOfIoSpace The maximum physical I/O addressability of the processor. - -**/ -VOID -EFIAPI -BuildCpuHob ( - IN UINT8 SizeOfMemorySpace, - IN UINT8 SizeOfIoSpace - ) -{ - EFI_HOB_CPU *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return; - } - - Hob->SizeOfMemorySpace = SizeOfMemorySpace; - Hob->SizeOfIoSpace = SizeOfIoSpace; - - // - // Zero the reserved space to match HOB spec - // - ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); -} - -/** - Builds a HOB for the memory allocation. - - This function builds a HOB for the memory allocation. - If there is no additional space for HOB creation, then ASSERT(). - - @param BaseAddress The 64 bit physical address of the memory. - @param Length The length of the memory allocation in bytes. - @param MemoryType Type of memory allocated by this HOB. - -**/ -VOID -EFIAPI -BuildMemoryAllocationHob ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN EFI_MEMORY_TYPE MemoryType - ) -{ - EFI_HOB_MEMORY_ALLOCATION *Hob; - - ASSERT ( - ((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && - ((Length & (EFI_PAGE_SIZE - 1)) == 0) - ); - - Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); - ASSERT (Hob != NULL); - if (Hob == NULL) { - return; - } - - ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); - Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; - Hob->AllocDescriptor.MemoryLength = Length; - Hob->AllocDescriptor.MemoryType = MemoryType; - // - // Zero the reserved space to match HOB spec - // - ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); -} - diff --git a/lib/hob/hob.c b/lib/hob/hob.c new file mode 100644 index 000000000..60d857168 --- /dev/null +++ b/lib/hob/hob.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2006-2014, Intel Corporation. All rights reserved. + * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ALIGN_UP(x, a) ((x + (a - 1)) & ~(a - 1)) + +static void *_create_hob(struct efi_hob_handoff_info_table *hob_table, + uint16_t hob_type, uint16_t hob_length) +{ + size_t free_mem_size; + struct efi_hob_generic_header *new_hob; + struct efi_hob_generic_header *hob_end; + + if ((hob_table == NULL) || (hob_length == 0)) { + return NULL; + } + + hob_length = ALIGN_UP(hob_length, 8); + free_mem_size = hob_table->efi_free_memory_top - hob_table->efi_free_memory_bottom; + + /** + * hob_length already including sizeof(efi_hob_generic_header). + * See the each export interface create_xxx_hob. + */ + if ((size_t) hob_length > free_mem_size) { + return NULL; + } + + new_hob = (struct efi_hob_generic_header *) hob_table->efi_end_of_hob_list; + new_hob->hob_type = hob_type; + new_hob->hob_length = hob_length; + new_hob->reserved = 0x00; + + hob_end = (struct efi_hob_generic_header *) (hob_table->efi_end_of_hob_list + hob_length); + hob_end->hob_type = EFI_HOB_TYPE_END_OF_HOB_LIST; + hob_end->hob_length = sizeof(struct efi_hob_generic_header); + hob_end->reserved = 0x00; + + hob_table->efi_end_of_hob_list = (efi_physical_address_t) hob_end; + hob_table->efi_free_memory_bottom = (efi_physical_address_t) (hob_end + 1); + + return new_hob; +} + +/* + * Create PHIT HOB list. + * + * On success, return the address PHIT HOB list + * On error, return NULL. + * + * efi_memory_begin + * Base address for partition. + * efi_memory_length + * Size of memory for patition. + * efi_free_memory_bottom + * Base address PHIT HOB list can be allocated + * efi_free_memory_length. + * Maximum size of PHIT HOB list can have + */ +struct efi_hob_handoff_info_table *create_hob_list( + efi_physical_address_t efi_memory_begin, size_t efi_memory_length, + efi_physical_address_t efi_free_memory_bottom, size_t efi_free_memory_length) +{ + struct efi_hob_handoff_info_table *hob_table; + struct efi_hob_generic_header *hob_end; + + if ((efi_memory_begin == 0) || (efi_free_memory_bottom == 0) || + (efi_memory_length == 0) || (efi_free_memory_length == 0)) { + return NULL; + } + + hob_table = (struct efi_hob_handoff_info_table *) efi_free_memory_bottom; + hob_end = (struct efi_hob_generic_header *) (hob_table + 1); + + hob_table->header.hob_type = EFI_HOB_TYPE_HANDOFF; + hob_table->header.hob_length = sizeof(struct efi_hob_handoff_info_table); + hob_table->header.reserved = 0; + + hob_end->hob_type = EFI_HOB_TYPE_END_OF_HOB_LIST; + hob_end->hob_length = sizeof(struct efi_hob_generic_header); + hob_end->reserved = 0; + + hob_table->version = EFI_HOB_HANDOFF_TABLE_VERSION; + hob_table->boot_mode = EFI_BOOT_WITH_FULL_CONFIGURATION; + + hob_table->efi_memory_top = efi_memory_begin + efi_memory_length; + hob_table->efi_memory_bottom = efi_memory_begin; + hob_table->efi_free_memory_top = efi_memory_begin + efi_free_memory_length; + hob_table->efi_free_memory_bottom = (efi_physical_address_t) (hob_end + 1); + hob_table->efi_end_of_hob_list = (efi_physical_address_t) hob_end; + + return hob_table; +} + +/* + * Create resource description HOB in PHIT HOB list. + * + * On success, return 0. + * On error, return error code. + * + * hob_table + * Address of PHIT HOB list + * resource_type + * Resource type see EFI_RESOURCE_* in the include/lib/hob/efi_types.h + * resource_attribute + * Resource attribute see EFI_RESOURCE_ATTRIBUTES_* + * in the include/lib/hob/efi_types.h + * phy_addr_start + * Physical base address of resource + * resource_length + * Size of resource + */ +int create_resource_descriptor_hob( + struct efi_hob_handoff_info_table *hob_table, + efi_resource_type_t resource_type, + efi_resource_attribute_type_t resource_attribute, + efi_physical_address_t phy_addr_start, + uint64_t resource_length) +{ + struct efi_hob_resource_descriptor *rd_hop; + + rd_hop = _create_hob(hob_table, EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + sizeof(struct efi_hob_resource_descriptor)); + + if (rd_hop == NULL) { + ERROR("No space for creating resource descriptor type hob...\n"); + return -ENOMEM; + } + + rd_hop->resource_type = resource_type; + rd_hop->resource_attribute = resource_attribute; + rd_hop->physical_start = phy_addr_start; + rd_hop->resource_length = resource_length; + memset(&rd_hop->owner, 0, sizeof(struct efi_guid)); + + return 0; +} + +/* + * Create GUID HOB in PHIT HOB list. + * + * On success, return 0. + * On error, return error code. + * + * hob_table + * Address of PHIT HOB list + * guid + * guid. + * data length + * Size of data + * data + * Data + */ +int create_guid_hob(struct efi_hob_handoff_info_table *hob_table, + struct efi_guid *guid, uint16_t data_length, void **data) +{ + struct efi_hob_guid_type *guid_hob; + uint16_t hob_length; + + hob_length = data_length + sizeof(struct efi_hob_guid_type); + + if ((guid == NULL) || (data == NULL) || (hob_length < data_length)) { + return -EINVAL; + } + + guid_hob = _create_hob(hob_table, EFI_HOB_TYPE_GUID_EXTENSION, hob_length); + if (guid_hob == NULL) { + ERROR("No space for creating guid type hob...\n"); + return -ENOMEM; + } + + memcpy(&guid_hob->name, guid, sizeof(struct efi_guid)); + + *data = (void *) (guid_hob + 1); + + return 0; +} + +/* + * Create Firmware Volume HOB in PHIT HOB list. + * + * On success, return 0. + * On error, return error code. + * + * hob_table + * Address of PHIT HOB list + * base_addr + * Base address of firmware volume + * size + * Size of Firmware Volume + */ +int create_fv_hob(struct efi_hob_handoff_info_table *hob_table, + efi_physical_address_t base_addr, uint64_t size) +{ + struct efi_hob_firmware_volume *fv_hob; + + fv_hob = _create_hob(hob_table, EFI_HOB_TYPE_FV, + sizeof(struct efi_hob_firmware_volume)); + if (fv_hob == NULL) { + ERROR("No space for creating fv type hob...\n"); + return -ENOMEM; + } + + fv_hob->base_address = base_addr; + fv_hob->length = size; + + return 0; +}