1 /*
2 * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <string.h>
9 #include <stdbool.h>
10 #include "tfm_hal_device_header.h"
11 #include "uefi_fmp.h"
12
13 /* The count will increase when partial update is supported.
14 * At present, only full WIC is considered as updatable image.
15 */
16 #define NUMBER_OF_FMP_IMAGES 1
17 #define NO_OF_FMP_VARIABLES_PER_IMAGE 6
18
19 #define UEFI_ARCHITECTURE_64
20
21 #ifdef UEFI_ARCHITECTURE_64
22 typedef uint64_t uefi_ptr_t;
23 typedef uint64_t efi_uintn_t;
24 #else
25 typedef uint32_t uefi_ptr_t;
26 typedef uint32_t efi_uintn_t;
27 #endif
28
29 /* Below macro definations and struct declarations taken from UEFI spec 2.9 */
30
31 /*
32 * Image Attribute Definitions
33 */
34 #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x00000001
35 #define IMAGE_ATTRIBUTE_RESET_REQUIRED 0x00000002
36 #define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x00000004
37 #define IMAGE_ATTRIBUTE_IN_USE 0x00000008
38 #define IMAGE_ATTRIBUTE_UEFI_IMAGE 0x00000010
39 #define IMAGE_ATTRIBUTE_DEPENDENCY 0x00000020
40
41 typedef uint32_t DescriptorVersion_t;
42 typedef uint32_t DescriptorSize_t;
43 typedef uint8_t DescriptorCount_t;
44
45 typedef __PACKED_STRUCT {
46 uint8_t ImageIndex;
47 struct efi_guid ImageTypeId;
48 uint64_t ImageId;
49 uefi_ptr_t PtrImageIdName;
50 uint32_t Version;
51 uefi_ptr_t PtrVersionName;
52 efi_uintn_t Size;
53 uint64_t AttributesSupported;
54 uint64_t AttributesSetting;
55 uint64_t Compatibilities;
56 /* Introduced with DescriptorVersion 2+ */
57 uint32_t LowestSupportedImageVersion;
58 /* Introduced with DescriptorVersion 3+ */
59 uint32_t LastAttemptVersion;
60 uint32_t LastAttemptStatus;
61 uint64_t HardwareInstance;
62 /* Introduced with DescriptorVersion 4+ */
63 uefi_ptr_t PtrDependencies;
64 } EFI_FIRMWARE_IMAGE_DESCRIPTOR;
65
66 typedef __PACKED_STRUCT {
67 DescriptorVersion_t DescriptorVersion;
68 DescriptorSize_t DescriptorsSize;
69 DescriptorCount_t DescriptorCount;
70 EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageDescriptor;
71 uint16_t *ImageName;
72 uint32_t ImageNameSize;
73 uint16_t *ImageVersionName;
74 uint32_t ImageVersionNameSize;
75 } EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO;
76
77
78 static uint16_t corstone_image_name0[] = { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' };
79 static uint16_t corstone_version_name0[] = { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'};
80
81 static EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO fmp_info[NUMBER_OF_FMP_IMAGES];
82
83 extern struct efi_guid full_capsule_image_guid;
84
85 static bool is_fmp_info_initialized = false;
86
init_fmp_info(void)87 static void init_fmp_info(void)
88 {
89 memset(fmp_info, 0,
90 sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO) * NUMBER_OF_FMP_IMAGES);
91
92 /* Fill information for the WIC.
93 * Add further details when partial image is supported.
94 */
95
96 fmp_info[0].DescriptorVersion = 4;
97 fmp_info[0].DescriptorCount = NUMBER_OF_FMP_IMAGES;
98 fmp_info[0].DescriptorsSize =
99 sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) +
100 sizeof(corstone_image_name0) + sizeof(corstone_version_name0);
101
102 fmp_info[0].ImageDescriptor.ImageIndex = 1;
103
104 memcpy(&fmp_info[0].ImageDescriptor.ImageTypeId, &full_capsule_image_guid,
105 sizeof(struct efi_guid));
106
107 fmp_info[0].ImageDescriptor.ImageId = 1;
108 fmp_info[0].ImageDescriptor.Version = FWU_IMAGE_INITIAL_VERSION;
109 fmp_info[0].ImageDescriptor.AttributesSupported = 1;
110 fmp_info[0].ImageDescriptor.AttributesSetting = (
111 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED);
112 fmp_info[0].ImageDescriptor.LowestSupportedImageVersion =
113 FWU_IMAGE_INITIAL_VERSION;
114 fmp_info[0].ImageDescriptor.LastAttemptVersion = FWU_IMAGE_INITIAL_VERSION;
115 fmp_info[0].ImageDescriptor.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
116
117 fmp_info[0].ImageName = corstone_image_name0;
118 fmp_info[0].ImageNameSize = sizeof(corstone_image_name0);
119 fmp_info[0].ImageVersionName = corstone_version_name0;
120 fmp_info[0].ImageVersionNameSize = sizeof(corstone_version_name0);
121
122 is_fmp_info_initialized = true;
123
124 return;
125 }
126
fmp_set_image_info(struct efi_guid * guid,uint32_t current_version,uint32_t attempt_version,uint32_t last_attempt_status)127 enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid,
128 uint32_t current_version, uint32_t attempt_version,
129 uint32_t last_attempt_status)
130 {
131 enum fwu_agent_error_t status = FWU_AGENT_ERROR;
132
133 FWU_LOG_MSG("%s:%d Enter\n\r", __func__, __LINE__);
134
135 if (is_fmp_info_initialized == false) {
136 init_fmp_info();
137 }
138
139 for (int i = 0; i < NUMBER_OF_FMP_IMAGES; i++) {
140 if ((memcmp(guid, &fmp_info[i].ImageDescriptor.ImageTypeId,
141 sizeof(struct efi_guid))) == 0)
142 {
143 FWU_LOG_MSG("FMP image update: image id = %u\n\r",
144 fmp_info[i].ImageDescriptor.ImageId);
145 fmp_info[i].ImageDescriptor.Version = current_version;
146 fmp_info[i].ImageDescriptor.LastAttemptVersion = attempt_version;
147 fmp_info[i].ImageDescriptor.LastAttemptStatus = last_attempt_status;
148 FWU_LOG_MSG("FMP image update: status = %u"
149 "version=%u last_attempt_version=%u.\n\r",
150 last_attempt_status, current_version,
151 attempt_version);
152 status = FWU_AGENT_SUCCESS;
153 break;
154 }
155 }
156
157 FWU_LOG_MSG("%s:%d Exit.\n\r", __func__, __LINE__);
158 return status;
159 }
160
161
162 #define NO_OF_FMP_VARIABLES (NUMBER_OF_FMP_IMAGES * NO_OF_FMP_VARIABLES_PER_IMAGE)
163
pack_image_info(void * buffer,uint32_t size)164 static enum fwu_agent_error_t pack_image_info(void *buffer, uint32_t size)
165 {
166 typedef __PACKED_STRUCT {
167 uint32_t variable_count;
168 uint32_t variable_size[NO_OF_FMP_VARIABLES];
169 uint8_t variable[];
170 } packed_buffer_t;
171
172 packed_buffer_t *packed_buffer = buffer;
173 int runner = 0;
174 int index = 0;
175 int current_size = sizeof(packed_buffer_t);
176 int size_requirement_1 = 0;
177 int size_requirement_2 = 0;
178
179 if (size < current_size) {
180 FWU_LOG_MSG("%s:%d Buffer too small.\n\r", __func__, __LINE__);
181 return FWU_AGENT_ERROR;
182 }
183
184 packed_buffer->variable_count = NO_OF_FMP_VARIABLES;
185
186 for (int i = 0; i < NUMBER_OF_FMP_IMAGES; i++) {
187
188 packed_buffer->variable_size[index++] = sizeof(DescriptorVersion_t);
189 packed_buffer->variable_size[index++] = sizeof(DescriptorSize_t);
190 packed_buffer->variable_size[index++] = sizeof(DescriptorCount_t);
191 packed_buffer->variable_size[index++] = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
192 packed_buffer->variable_size[index++] = fmp_info[i].ImageNameSize;
193 packed_buffer->variable_size[index++] = fmp_info[i].ImageVersionNameSize;
194
195 size_requirement_1 = sizeof(DescriptorVersion_t) + sizeof(DescriptorSize_t) +
196 sizeof(DescriptorCount_t) + sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
197
198 size_requirement_2 = fmp_info[i].ImageNameSize + fmp_info[i].ImageVersionNameSize;
199
200 current_size += size_requirement_1 + size_requirement_2;
201
202 if (size < current_size) {
203 FWU_LOG_MSG("%s:%d Buffer too small.\n\r", __func__, __LINE__);
204 return FWU_AGENT_ERROR;
205 }
206
207 FWU_LOG_MSG("%s:%d ImageInfo size = %u, ImageName size = %u, "
208 "ImageVersionName size = %u\n\r", __func__, __LINE__,
209 sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR), fmp_info[i].ImageNameSize,
210 fmp_info[i].ImageVersionNameSize);
211
212 memcpy(&packed_buffer->variable[runner], &fmp_info[i], size_requirement_1);
213 runner += size_requirement_1;
214
215 memcpy(&packed_buffer->variable[runner], fmp_info[i].ImageName,
216 fmp_info[i].ImageNameSize);
217 runner += fmp_info[i].ImageNameSize;
218
219 memcpy(&packed_buffer->variable[runner], fmp_info[i].ImageVersionName,
220 fmp_info[i].ImageVersionNameSize);
221 runner += fmp_info[i].ImageVersionNameSize;
222
223 }
224
225 return FWU_AGENT_SUCCESS;
226 }
227
fmp_get_image_info(void * buffer,uint32_t size)228 enum fwu_agent_error_t fmp_get_image_info(void *buffer, uint32_t size)
229 {
230 enum fwu_agent_error_t status;
231
232 FWU_LOG_MSG("%s:%d Enter\n\r", __func__, __LINE__);
233
234 status = pack_image_info(buffer, size);
235
236 FWU_LOG_MSG("%s:%d Exit\n\r", __func__, __LINE__);
237
238 return status;
239 }
240
241