1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * Firmware Image Package (FIP) parser support.
9 */
10
11 #include <mod_fip.h>
12
13 #include <fwk_id.h>
14 #include <fwk_log.h>
15 #include <fwk_module.h>
16 #include <fwk_status.h>
17 #include <fwk_string.h>
18
19 #include <inttypes.h>
20 #include <string.h>
21
22 static const struct fip_uuid_desc fip_uuid_desc_arr[3] = {
23 FIP_UUID_NULL,
24 FIP_UUID_SCP_BL2,
25 FIP_UUID_TFA_BL31,
26 };
27
28 /*
29 * Static helpers
30 */
fip_entry_type_to_uuid(enum mod_fip_toc_entry_type type,uint8_t * uuid)31 static int fip_entry_type_to_uuid(
32 enum mod_fip_toc_entry_type type,
33 uint8_t *uuid)
34 {
35 const struct mod_fip_module_config *module_config;
36 size_t i;
37
38 module_config = fwk_module_get_data(fwk_module_id_fip);
39 size_t desc_arr_size =
40 sizeof(fip_uuid_desc_arr) / sizeof(fip_uuid_desc_arr[0]);
41
42 if (type < MOD_FIP_TOC_ENTRY_COUNT) {
43 for (i = 0; i < desc_arr_size; i++) {
44 if (fip_uuid_desc_arr[i].image_type == type) {
45 fwk_str_memcpy(
46 uuid, fip_uuid_desc_arr[i].uuid, FIP_UUID_ENTRY_SIZE);
47 return FWK_SUCCESS;
48 }
49 }
50 }
51
52 if (type >= MOD_FIP_TOC_ENTRY_COUNT &&
53 module_config->custom_fip_uuid_desc_arr != NULL) {
54 for (i = 0; i < module_config->custom_uuid_desc_count; i++) {
55 if (module_config->custom_fip_uuid_desc_arr[i].image_type == type) {
56 fwk_str_memcpy(
57 uuid,
58 module_config->custom_fip_uuid_desc_arr[i].uuid,
59 FIP_UUID_ENTRY_SIZE);
60 return FWK_SUCCESS;
61 }
62 }
63 }
64
65 return FWK_E_PARAM;
66 }
67
uuid_cmp(const uint8_t * a,const uint8_t * b)68 static inline bool uuid_cmp(const uint8_t *a, const uint8_t *b)
69 {
70 int match = 0;
71
72 for (unsigned int i = 0; i < FIP_UUID_ENTRY_SIZE; i++) {
73 if (a[i] == b[i]) {
74 match++;
75 } else {
76 match--;
77 }
78 }
79
80 return (match == FIP_UUID_ENTRY_SIZE);
81 }
82
uuid_is_null(const uint8_t * uuid)83 static bool uuid_is_null(const uint8_t *uuid)
84 {
85 static const struct fip_uuid_desc uuid_null = FIP_UUID_NULL;
86 return uuid_cmp(uuid, uuid_null.uuid);
87 }
88
validate_fip_toc(const struct fip_toc * const toc)89 static bool validate_fip_toc(const struct fip_toc *const toc)
90 {
91 return toc->header.name == FIP_TOC_HEADER_NAME;
92 }
93
94 /*
95 * Module API functions
96 */
fip_get_entry(enum mod_fip_toc_entry_type image_type,struct mod_fip_entry_data * const entry_data,uintptr_t base,size_t limit)97 static int fip_get_entry(
98 enum mod_fip_toc_entry_type image_type,
99 struct mod_fip_entry_data *const entry_data,
100 uintptr_t base,
101 size_t limit)
102 {
103 uintptr_t address;
104 uint8_t target_uuid[FIP_UUID_ENTRY_SIZE];
105 struct fip_toc_entry *toc_entry;
106 int status;
107 struct fip_toc *toc = (void *)base;
108
109 if (!validate_fip_toc(toc)) {
110 /*
111 * The error log message here requires the platform to enable an
112 * always-on logging mechanism in order to detect this failure in
113 * early stages, such as in ROM code.
114 */
115 FWK_LOG_ERR(
116 "[FIP] Invalid FIP ToC header name: [0x%08" PRIX32 "]",
117 toc->header.name);
118 return FWK_E_PARAM;
119 }
120
121 toc_entry = toc->entry;
122
123 /* Updates target_uuid field with UUID of corresponding image_type passed */
124 status = fip_entry_type_to_uuid(image_type, target_uuid);
125 if (status != FWK_SUCCESS)
126 return status;
127
128 /*
129 * Traverse all FIP ToC entries until the desired entry is found or ToC
130 * End Marker is reached
131 */
132 while (!uuid_cmp(toc_entry->uuid, target_uuid)) {
133 if (uuid_is_null(toc_entry->uuid))
134 return FWK_E_RANGE;
135 toc_entry++;
136 }
137
138 /* Sanity checks of the retrieved entry data */
139 if (__builtin_add_overflow(
140 (uintptr_t)toc, (uintptr_t)toc_entry->offset_address, &address)) {
141 return FWK_E_DATA;
142 }
143
144 if ((uintptr_t)toc_entry->offset_address + toc_entry->size > limit)
145 return FWK_E_SIZE;
146
147 entry_data->base = (void *)address;
148 entry_data->size = toc_entry->size;
149 entry_data->flags = toc_entry->flags;
150 return FWK_SUCCESS;
151 }
152
153 static const struct mod_fip_api fip_api = {
154 .get_entry = fip_get_entry,
155 };
156
157 /*
158 * Framework handler functions
159 */
fip_init(fwk_id_t module_id,unsigned int element_count,const void * data)160 static int fip_init(
161 fwk_id_t module_id,
162 unsigned int element_count,
163 const void *data)
164 {
165 return FWK_SUCCESS;
166 }
167
fip_process_bind_request(fwk_id_t requester_id,fwk_id_t id,fwk_id_t api_id,const void ** api)168 static int fip_process_bind_request(
169 fwk_id_t requester_id,
170 fwk_id_t id,
171 fwk_id_t api_id,
172 const void **api)
173 {
174 *api = &fip_api;
175 return FWK_SUCCESS;
176 }
177
178 const struct fwk_module module_fip = {
179 .type = FWK_MODULE_TYPE_SERVICE,
180 .api_count = 1,
181 .init = fip_init,
182 .process_bind_request = fip_process_bind_request,
183 };
184