blob: 60d857168a4f1761af4657fa732957b75dd31149 [file] [log] [blame]
Levi Yun32f4f3f2024-05-13 10:10:05 +01001/*
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
21static 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 */
74struct 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 */
127int 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 */
168int 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 */
206int 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}