xref: /optee_os/core/lib/libefi/hob.c (revision 5d5d7d0b1c038a6836be9f0b38585f5aa6a4dd01)
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