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