1 /* 2 * Copyright (c) 2006-2014, Intel Corporation. All rights reserved. 3 * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 #include <assert.h> 8 #include <errno.h> 9 #include <inttypes.h> 10 #include <string.h> 11 12 #include <arch.h> 13 #include <common/debug.h> 14 #include <lib/hob/hob.h> 15 #include <lib/hob/hob_guid.h> 16 #include <lib/hob/mmram.h> 17 #include <lib/utils_def.h> 18 19 #define ALIGN_UP(x, a) ((x + (a - 1)) & ~(a - 1)) 20 21 static void *_create_hob(struct efi_hob_handoff_info_table *hob_table, 22 uint16_t hob_type, uint16_t hob_length) 23 { 24 size_t free_mem_size; 25 struct efi_hob_generic_header *new_hob; 26 struct efi_hob_generic_header *hob_end; 27 28 if ((hob_table == NULL) || (hob_length == 0)) { 29 return NULL; 30 } 31 32 hob_length = ALIGN_UP(hob_length, 8); 33 free_mem_size = hob_table->efi_free_memory_top - hob_table->efi_free_memory_bottom; 34 35 /** 36 * hob_length already including sizeof(efi_hob_generic_header). 37 * See the each export interface create_xxx_hob. 38 */ 39 if ((size_t) hob_length > free_mem_size) { 40 return NULL; 41 } 42 43 new_hob = (struct efi_hob_generic_header *) hob_table->efi_end_of_hob_list; 44 new_hob->hob_type = hob_type; 45 new_hob->hob_length = hob_length; 46 new_hob->reserved = 0x00; 47 48 hob_end = (struct efi_hob_generic_header *) (hob_table->efi_end_of_hob_list + hob_length); 49 hob_end->hob_type = EFI_HOB_TYPE_END_OF_HOB_LIST; 50 hob_end->hob_length = sizeof(struct efi_hob_generic_header); 51 hob_end->reserved = 0x00; 52 53 hob_table->efi_end_of_hob_list = (efi_physical_address_t) hob_end; 54 hob_table->efi_free_memory_bottom = (efi_physical_address_t) (hob_end + 1); 55 56 return new_hob; 57 } 58 59 /* 60 * Create PHIT HOB list. 61 * 62 * On success, return the address PHIT HOB list 63 * On error, return NULL. 64 * 65 * efi_memory_begin 66 * Base address for partition. 67 * efi_memory_length 68 * Size of memory for patition. 69 * efi_free_memory_bottom 70 * Base address PHIT HOB list can be allocated 71 * efi_free_memory_length. 72 * Maximum size of PHIT HOB list can have 73 */ 74 struct efi_hob_handoff_info_table *create_hob_list( 75 efi_physical_address_t efi_memory_begin, size_t efi_memory_length, 76 efi_physical_address_t efi_free_memory_bottom, size_t efi_free_memory_length) 77 { 78 struct efi_hob_handoff_info_table *hob_table; 79 struct efi_hob_generic_header *hob_end; 80 81 if ((efi_memory_begin == 0) || (efi_free_memory_bottom == 0) || 82 (efi_memory_length == 0) || (efi_free_memory_length == 0)) { 83 return NULL; 84 } 85 86 hob_table = (struct efi_hob_handoff_info_table *) efi_free_memory_bottom; 87 hob_end = (struct efi_hob_generic_header *) (hob_table + 1); 88 89 hob_table->header.hob_type = EFI_HOB_TYPE_HANDOFF; 90 hob_table->header.hob_length = sizeof(struct efi_hob_handoff_info_table); 91 hob_table->header.reserved = 0; 92 93 hob_end->hob_type = EFI_HOB_TYPE_END_OF_HOB_LIST; 94 hob_end->hob_length = sizeof(struct efi_hob_generic_header); 95 hob_end->reserved = 0; 96 97 hob_table->version = EFI_HOB_HANDOFF_TABLE_VERSION; 98 hob_table->boot_mode = EFI_BOOT_WITH_FULL_CONFIGURATION; 99 100 hob_table->efi_memory_top = efi_memory_begin + efi_memory_length; 101 hob_table->efi_memory_bottom = efi_memory_begin; 102 hob_table->efi_free_memory_top = efi_memory_begin + efi_free_memory_length; 103 hob_table->efi_free_memory_bottom = (efi_physical_address_t) (hob_end + 1); 104 hob_table->efi_end_of_hob_list = (efi_physical_address_t) hob_end; 105 106 return hob_table; 107 } 108 109 /* 110 * Create resource description HOB in PHIT HOB list. 111 * 112 * On success, return 0. 113 * On error, return error code. 114 * 115 * hob_table 116 * Address of PHIT HOB list 117 * resource_type 118 * Resource type see EFI_RESOURCE_* in the include/lib/hob/efi_types.h 119 * resource_attribute 120 * Resource attribute see EFI_RESOURCE_ATTRIBUTES_* 121 * in the include/lib/hob/efi_types.h 122 * phy_addr_start 123 * Physical base address of resource 124 * resource_length 125 * Size of resource 126 */ 127 int create_resource_descriptor_hob( 128 struct efi_hob_handoff_info_table *hob_table, 129 efi_resource_type_t resource_type, 130 efi_resource_attribute_type_t resource_attribute, 131 efi_physical_address_t phy_addr_start, 132 uint64_t resource_length) 133 { 134 struct efi_hob_resource_descriptor *rd_hop; 135 136 rd_hop = _create_hob(hob_table, EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, 137 sizeof(struct efi_hob_resource_descriptor)); 138 139 if (rd_hop == NULL) { 140 ERROR("No space for creating resource descriptor type hob...\n"); 141 return -ENOMEM; 142 } 143 144 rd_hop->resource_type = resource_type; 145 rd_hop->resource_attribute = resource_attribute; 146 rd_hop->physical_start = phy_addr_start; 147 rd_hop->resource_length = resource_length; 148 memset(&rd_hop->owner, 0, sizeof(struct efi_guid)); 149 150 return 0; 151 } 152 153 /* 154 * Create GUID HOB in PHIT HOB list. 155 * 156 * On success, return 0. 157 * On error, return error code. 158 * 159 * hob_table 160 * Address of PHIT HOB list 161 * guid 162 * guid. 163 * data length 164 * Size of data 165 * data 166 * Data 167 */ 168 int create_guid_hob(struct efi_hob_handoff_info_table *hob_table, 169 struct efi_guid *guid, uint16_t data_length, void **data) 170 { 171 struct efi_hob_guid_type *guid_hob; 172 uint16_t hob_length; 173 174 hob_length = data_length + sizeof(struct efi_hob_guid_type); 175 176 if ((guid == NULL) || (data == NULL) || (hob_length < data_length)) { 177 return -EINVAL; 178 } 179 180 guid_hob = _create_hob(hob_table, EFI_HOB_TYPE_GUID_EXTENSION, hob_length); 181 if (guid_hob == NULL) { 182 ERROR("No space for creating guid type hob...\n"); 183 return -ENOMEM; 184 } 185 186 memcpy(&guid_hob->name, guid, sizeof(struct efi_guid)); 187 188 *data = (void *) (guid_hob + 1); 189 190 return 0; 191 } 192 193 /* 194 * Create Firmware Volume HOB in PHIT HOB list. 195 * 196 * On success, return 0. 197 * On error, return error code. 198 * 199 * hob_table 200 * Address of PHIT HOB list 201 * base_addr 202 * Base address of firmware volume 203 * size 204 * Size of Firmware Volume 205 */ 206 int create_fv_hob(struct efi_hob_handoff_info_table *hob_table, 207 efi_physical_address_t base_addr, uint64_t size) 208 { 209 struct efi_hob_firmware_volume *fv_hob; 210 211 fv_hob = _create_hob(hob_table, EFI_HOB_TYPE_FV, 212 sizeof(struct efi_hob_firmware_volume)); 213 if (fv_hob == NULL) { 214 ERROR("No space for creating fv type hob...\n"); 215 return -ENOMEM; 216 } 217 218 fv_hob->base_address = base_addr; 219 fv_hob->length = size; 220 221 return 0; 222 } 223