1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. 4 * 5 * @par Reference(s): 6 * - UEFI Platform Initialization Specification 7 * (https://uefi.org/specs/PI/1.8/index.html) 8 */ 9 10 #include <assert.h> 11 #include <inttypes.h> 12 #include <string.h> 13 #include <tee_api_defines.h> 14 #include <trace.h> 15 #include <util.h> 16 17 #include <efi/hob.h> 18 19 static void *create_hob(struct efi_hob_handoff_info_table *hob_table, 20 uint16_t hob_type, uint16_t hob_length) 21 { 22 size_t free_mem_size = 0; 23 struct efi_hob_generic_header *new_hob = NULL; 24 struct efi_hob_generic_header *hob_end = NULL; 25 26 hob_length = ROUNDUP(hob_length, HOB_ALIGN); 27 28 assert(hob_table && hob_length); 29 30 free_mem_size = hob_table->efi_free_memory_top - 31 hob_table->efi_free_memory_bottom; 32 33 /* 34 * hob_length already including sizeof(efi_hob_generic_header). 35 * See the each export interface create_xxx_hob. 36 */ 37 if (hob_length > free_mem_size) 38 return NULL; 39 40 new_hob = (void *)hob_table->efi_end_of_hob_list; 41 new_hob->hob_type = hob_type; 42 new_hob->hob_length = hob_length; 43 new_hob->reserved = 0; 44 45 hob_end = (void *)((vaddr_t)new_hob + hob_length); 46 hob_end->hob_type = EFI_HOB_TYPE_END_OF_HOB_LIST; 47 hob_end->hob_length = sizeof(struct efi_hob_generic_header); 48 hob_end->reserved = 0; 49 50 hob_table->efi_end_of_hob_list = (vaddr_t)hob_end; 51 hob_table->efi_free_memory_bottom = (vaddr_t)(hob_end + 1); 52 53 return new_hob; 54 } 55 56 struct efi_hob_handoff_info_table * 57 efi_create_hob_list(vaddr_t mem_begin, size_t mem_len, 58 vaddr_t mem_free_begin, size_t mem_free_len) 59 { 60 struct efi_hob_handoff_info_table *hob_table = NULL; 61 struct efi_hob_generic_header *hob_end = NULL; 62 63 if (!mem_begin || !mem_free_begin || !mem_len || !mem_free_len) 64 return NULL; 65 66 hob_table = (void *)mem_free_begin; 67 hob_end = (void *)(hob_table + 1); 68 69 hob_table->header.hob_type = EFI_HOB_TYPE_HANDOFF; 70 hob_table->header.hob_length = 71 sizeof(struct efi_hob_handoff_info_table); 72 hob_table->header.reserved = 0; 73 74 hob_end->hob_type = EFI_HOB_TYPE_END_OF_HOB_LIST; 75 hob_end->hob_length = sizeof(struct efi_hob_generic_header); 76 hob_end->reserved = 0; 77 78 hob_table->version = EFI_HOB_HANDOFF_TABLE_VERSION; 79 hob_table->boot_mode = BOOT_WITH_FULL_CONFIGURATION; 80 81 hob_table->efi_memory_top = (vaddr_t)(mem_begin + mem_len); 82 hob_table->efi_memory_bottom = (vaddr_t)mem_begin; 83 hob_table->efi_free_memory_top = (vaddr_t)mem_begin + mem_free_len; 84 hob_table->efi_free_memory_bottom = (vaddr_t)(hob_end + 1); 85 hob_table->efi_end_of_hob_list = (vaddr_t)hob_end; 86 87 return hob_table; 88 } 89 90 TEE_Result 91 efi_create_resource_desc_hob(struct efi_hob_handoff_info_table *hob_table, 92 efi_resource_type_t resource_type, 93 efi_resource_attribute_type_t resource_attribute, 94 efi_physical_address_t phy_addr_start, 95 uint64_t resource_length) 96 { 97 struct efi_hob_resource_descriptor *rd_hop = NULL; 98 99 rd_hop = create_hob(hob_table, EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, 100 sizeof(struct efi_hob_resource_descriptor)); 101 102 if (!rd_hop) 103 return TEE_ERROR_OUT_OF_MEMORY; 104 105 rd_hop->resource_type = resource_type; 106 rd_hop->resource_attribute = resource_attribute; 107 rd_hop->physical_start = phy_addr_start; 108 rd_hop->resource_length = resource_length; 109 memset(&rd_hop->owner, 0, sizeof(TEE_UUID)); 110 111 return TEE_SUCCESS; 112 } 113 114 TEE_Result efi_create_guid_hob(struct efi_hob_handoff_info_table *hob_table, 115 TEE_UUID *guid, uint16_t data_length, 116 void **data) 117 { 118 struct efi_hob_guid_type *guid_hob = NULL; 119 uint16_t hob_length = 0; 120 121 hob_length = data_length + sizeof(struct efi_hob_guid_type); 122 123 if (!guid || !data || hob_length < data_length) 124 return TEE_ERROR_BAD_PARAMETERS; 125 126 guid_hob = create_hob(hob_table, 127 EFI_HOB_TYPE_GUID_EXTENSION, hob_length); 128 if (!guid_hob) { 129 *data = NULL; 130 131 return TEE_ERROR_OUT_OF_MEMORY; 132 } 133 134 memcpy(&guid_hob->name, guid, sizeof(TEE_UUID)); 135 136 *data = (void *)(guid_hob + 1); 137 138 return TEE_SUCCESS; 139 } 140 141 TEE_Result efi_create_fv_hob(struct efi_hob_handoff_info_table *hob_table, 142 efi_physical_address_t base_addr, uint64_t size) 143 { 144 struct efi_hob_firmware_volume *fv_hob = NULL; 145 146 fv_hob = create_hob(hob_table, EFI_HOB_TYPE_FV, 147 sizeof(struct efi_hob_firmware_volume)); 148 if (!fv_hob) 149 return TEE_ERROR_OUT_OF_MEMORY; 150 151 fv_hob->base_address = base_addr; 152 fv_hob->length = size; 153 154 return TEE_SUCCESS; 155 } 156