xref: /rk3399_ARM-atf/lib/hob/hob.c (revision 10ecd58093a34e95e2dfad65b1180610f29397cc)
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