1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * EFI Firmware management protocol
4 *
5 * Copyright (c) 2020 Linaro Limited
6 * Author: AKASHI Takahiro
7 */
8
9 #include <common.h>
10 #include <charset.h>
11 #include <dfu.h>
12 #include <efi_loader.h>
13 #include <fwu.h>
14 #include <image.h>
15 #include <signatures.h>
16
17 #include <linux/list.h>
18
19 #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1')
20
21 /**
22 * struct fmp_payload_header - EDK2 header for the FMP payload
23 *
24 * This structure describes the header which is preprended to the
25 * FMP payload by the edk2 capsule generation scripts.
26 *
27 * @signature: Header signature used to identify the header
28 * @header_size: Size of the structure
29 * @fw_version: Firmware versions used
30 * @lowest_supported_version: Lowest supported version
31 */
32 struct fmp_payload_header {
33 u32 signature;
34 u32 header_size;
35 u32 fw_version;
36 u32 lowest_supported_version;
37 };
38
set_dfu_alt_info(char * interface,char * devstr)39 __weak void set_dfu_alt_info(char *interface, char *devstr)
40 {
41 env_set("dfu_alt_info", update_info.dfu_string);
42 }
43
44 /* Place holder; not supported */
45 static
efi_firmware_get_image_unsupported(struct efi_firmware_management_protocol * this,u8 image_index,void * image,efi_uintn_t * image_size)46 efi_status_t EFIAPI efi_firmware_get_image_unsupported(
47 struct efi_firmware_management_protocol *this,
48 u8 image_index,
49 void *image,
50 efi_uintn_t *image_size)
51 {
52 EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
53
54 return EFI_EXIT(EFI_UNSUPPORTED);
55 }
56
57 /* Place holder; not supported */
58 static
efi_firmware_check_image_unsupported(struct efi_firmware_management_protocol * this,u8 image_index,const void * image,efi_uintn_t * image_size,u32 * image_updatable)59 efi_status_t EFIAPI efi_firmware_check_image_unsupported(
60 struct efi_firmware_management_protocol *this,
61 u8 image_index,
62 const void *image,
63 efi_uintn_t *image_size,
64 u32 *image_updatable)
65 {
66 EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
67 image_updatable);
68
69 return EFI_EXIT(EFI_UNSUPPORTED);
70 }
71
72 /* Place holder; not supported */
73 static
efi_firmware_get_package_info_unsupported(struct efi_firmware_management_protocol * this,u32 * package_version,u16 ** package_version_name,u32 * package_version_name_maxlen,u64 * attributes_supported,u64 * attributes_setting)74 efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
75 struct efi_firmware_management_protocol *this,
76 u32 *package_version,
77 u16 **package_version_name,
78 u32 *package_version_name_maxlen,
79 u64 *attributes_supported,
80 u64 *attributes_setting)
81 {
82 EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
83 package_version_name, package_version_name_maxlen,
84 attributes_supported, attributes_setting);
85
86 return EFI_EXIT(EFI_UNSUPPORTED);
87 }
88
89 /* Place holder; not supported */
90 static
efi_firmware_set_package_info_unsupported(struct efi_firmware_management_protocol * this,const void * image,efi_uintn_t * image_size,const void * vendor_code,u32 package_version,const u16 * package_version_name)91 efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
92 struct efi_firmware_management_protocol *this,
93 const void *image,
94 efi_uintn_t *image_size,
95 const void *vendor_code,
96 u32 package_version,
97 const u16 *package_version_name)
98 {
99 EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
100 package_version, package_version_name);
101
102 return EFI_EXIT(EFI_UNSUPPORTED);
103 }
104
105 /**
106 * efi_fill_image_desc_array - populate image descriptor array
107 * @image_info_size: Size of @image_info
108 * @image_info: Image information
109 * @descriptor_version: Pointer to version number
110 * @descriptor_count: Image count
111 * @descriptor_size: Pointer to descriptor size
112 * @package_version: Package version
113 * @package_version_name: Package version's name
114 *
115 * Return information about the current firmware image in @image_info.
116 * @image_info will consist of a number of descriptors.
117 * Each descriptor will be created based on efi_fw_image array.
118 *
119 * Return status code
120 */
efi_fill_image_desc_array(efi_uintn_t * image_info_size,struct efi_firmware_image_descriptor * image_info,u32 * descriptor_version,u8 * descriptor_count,efi_uintn_t * descriptor_size,u32 * package_version,u16 ** package_version_name)121 static efi_status_t efi_fill_image_desc_array(
122 efi_uintn_t *image_info_size,
123 struct efi_firmware_image_descriptor *image_info,
124 u32 *descriptor_version,
125 u8 *descriptor_count,
126 efi_uintn_t *descriptor_size,
127 u32 *package_version,
128 u16 **package_version_name)
129 {
130 size_t total_size;
131 struct efi_fw_image *fw_array;
132 int i;
133
134 total_size = sizeof(*image_info) * num_image_type_guids;
135
136 if (*image_info_size < total_size) {
137 *image_info_size = total_size;
138
139 return EFI_BUFFER_TOO_SMALL;
140 }
141 *image_info_size = total_size;
142
143 fw_array = update_info.images;
144 *descriptor_count = num_image_type_guids;
145 *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
146 *descriptor_size = sizeof(*image_info);
147 *package_version = 0xffffffff; /* not supported */
148 *package_version_name = NULL; /* not supported */
149
150 for (i = 0; i < num_image_type_guids; i++) {
151 image_info[i].image_index = fw_array[i].image_index;
152 image_info[i].image_type_id = fw_array[i].image_type_id;
153 image_info[i].image_id = fw_array[i].image_index;
154
155 image_info[i].image_id_name = fw_array[i].fw_name;
156
157 image_info[i].version = 0; /* not supported */
158 image_info[i].version_name = NULL; /* not supported */
159 image_info[i].size = 0;
160 image_info[i].attributes_supported =
161 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
162 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
163 image_info[i].attributes_setting =
164 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
165
166 /* Check if the capsule authentication is enabled */
167 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
168 image_info[0].attributes_setting |=
169 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
170
171 image_info[i].lowest_supported_image_version = 0;
172 image_info[i].last_attempt_version = 0;
173 image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
174 image_info[i].hardware_instance = 1;
175 image_info[i].dependencies = NULL;
176 }
177
178 return EFI_SUCCESS;
179 }
180
181 /**
182 * efi_firmware_capsule_authenticate - authenticate the capsule if enabled
183 * @p_image: Pointer to new image
184 * @p_image_size: Pointer to size of new image
185 *
186 * Authenticate the capsule if authentication is enabled.
187 * The image pointer and the image size are updated in case of success.
188 *
189 * Return: status code
190 */
191 static
efi_firmware_capsule_authenticate(const void ** p_image,efi_uintn_t * p_image_size)192 efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
193 efi_uintn_t *p_image_size)
194 {
195 const void *image = *p_image;
196 efi_uintn_t image_size = *p_image_size;
197 u32 fmp_hdr_signature;
198 struct fmp_payload_header *header;
199 void *capsule_payload;
200 efi_status_t status;
201 efi_uintn_t capsule_payload_size;
202
203 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) {
204 capsule_payload = NULL;
205 capsule_payload_size = 0;
206 status = efi_capsule_authenticate(image, image_size,
207 &capsule_payload,
208 &capsule_payload_size);
209
210 if (status == EFI_SECURITY_VIOLATION) {
211 printf("Capsule authentication check failed. Aborting update\n");
212 return status;
213 } else if (status != EFI_SUCCESS) {
214 return status;
215 }
216
217 debug("Capsule authentication successful\n");
218 image = capsule_payload;
219 image_size = capsule_payload_size;
220 } else {
221 debug("Capsule authentication disabled. ");
222 debug("Updating capsule without authenticating.\n");
223 }
224
225 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
226 header = (void *)image;
227
228 if (!memcmp(&header->signature, &fmp_hdr_signature,
229 sizeof(fmp_hdr_signature))) {
230 /*
231 * When building the capsule with the scripts in
232 * edk2, a FMP header is inserted above the capsule
233 * payload. Compensate for this header to get the
234 * actual payload that is to be updated.
235 */
236 image += header->header_size;
237 image_size -= header->header_size;
238 }
239
240 *p_image = image;
241 *p_image_size = image_size;
242 return EFI_SUCCESS;
243 }
244
245 /**
246 * efi_firmware_get_image_info - return information about the current
247 * firmware image
248 * @this: Protocol instance
249 * @image_info_size: Size of @image_info
250 * @image_info: Image information
251 * @descriptor_version: Pointer to version number
252 * @descriptor_count: Pointer to number of descriptors
253 * @descriptor_size: Pointer to descriptor size
254 * @package_version: Package version
255 * @package_version_name: Package version's name
256 *
257 * Return information bout the current firmware image in @image_info.
258 * @image_info will consist of a number of descriptors.
259 * Each descriptor will be created based on "dfu_alt_info" variable.
260 *
261 * Return status code
262 */
263 static
efi_firmware_get_image_info(struct efi_firmware_management_protocol * this,efi_uintn_t * image_info_size,struct efi_firmware_image_descriptor * image_info,u32 * descriptor_version,u8 * descriptor_count,efi_uintn_t * descriptor_size,u32 * package_version,u16 ** package_version_name)264 efi_status_t EFIAPI efi_firmware_get_image_info(
265 struct efi_firmware_management_protocol *this,
266 efi_uintn_t *image_info_size,
267 struct efi_firmware_image_descriptor *image_info,
268 u32 *descriptor_version,
269 u8 *descriptor_count,
270 efi_uintn_t *descriptor_size,
271 u32 *package_version,
272 u16 **package_version_name)
273 {
274 efi_status_t ret;
275
276 EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
277 image_info_size, image_info,
278 descriptor_version, descriptor_count, descriptor_size,
279 package_version, package_version_name);
280
281 if (!image_info_size)
282 return EFI_EXIT(EFI_INVALID_PARAMETER);
283
284 if (*image_info_size &&
285 (!image_info || !descriptor_version || !descriptor_count ||
286 !descriptor_size || !package_version || !package_version_name))
287 return EFI_EXIT(EFI_INVALID_PARAMETER);
288
289 ret = efi_fill_image_desc_array(image_info_size, image_info,
290 descriptor_version, descriptor_count,
291 descriptor_size, package_version,
292 package_version_name);
293
294 return EFI_EXIT(ret);
295 }
296
297 #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
298 /*
299 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
300 * method with existing FIT image format, and handles
301 * - multiple regions of firmware via DFU
302 * but doesn't support
303 * - versioning of firmware image
304 * - package information
305 */
306
307 /**
308 * efi_firmware_fit_set_image - update the firmware image
309 * @this: Protocol instance
310 * @image_index: Image index number
311 * @image: New image
312 * @image_size: Size of new image
313 * @vendor_code: Vendor-specific update policy
314 * @progress: Function to report the progress of update
315 * @abort_reason: Pointer to string of abort reason
316 *
317 * Update the firmware to new image, using dfu. The new image should
318 * have FIT image format commonly used in U-Boot.
319 * @vendor_code, @progress and @abort_reason are not supported.
320 *
321 * Return: status code
322 */
323 static
efi_firmware_fit_set_image(struct efi_firmware_management_protocol * this,u8 image_index,const void * image,efi_uintn_t image_size,const void * vendor_code,efi_status_t (* progress)(efi_uintn_t completion),u16 ** abort_reason)324 efi_status_t EFIAPI efi_firmware_fit_set_image(
325 struct efi_firmware_management_protocol *this,
326 u8 image_index,
327 const void *image,
328 efi_uintn_t image_size,
329 const void *vendor_code,
330 efi_status_t (*progress)(efi_uintn_t completion),
331 u16 **abort_reason)
332 {
333 efi_status_t status;
334
335 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
336 image_size, vendor_code, progress, abort_reason);
337
338 if (!image || image_index != 1)
339 return EFI_EXIT(EFI_INVALID_PARAMETER);
340
341 status = efi_firmware_capsule_authenticate(&image, &image_size);
342 if (status != EFI_SUCCESS)
343 return EFI_EXIT(status);
344
345 if (fit_update(image))
346 return EFI_EXIT(EFI_DEVICE_ERROR);
347
348 return EFI_EXIT(EFI_SUCCESS);
349 }
350
351 const struct efi_firmware_management_protocol efi_fmp_fit = {
352 .get_image_info = efi_firmware_get_image_info,
353 .get_image = efi_firmware_get_image_unsupported,
354 .set_image = efi_firmware_fit_set_image,
355 .check_image = efi_firmware_check_image_unsupported,
356 .get_package_info = efi_firmware_get_package_info_unsupported,
357 .set_package_info = efi_firmware_set_package_info_unsupported,
358 };
359 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
360
361 #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
362 /*
363 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
364 * method with raw data.
365 */
366
367 /**
368 * efi_firmware_raw_set_image - update the firmware image
369 * @this: Protocol instance
370 * @image_index: Image index number
371 * @image: New image
372 * @image_size: Size of new image
373 * @vendor_code: Vendor-specific update policy
374 * @progress: Function to report the progress of update
375 * @abort_reason: Pointer to string of abort reason
376 *
377 * Update the firmware to new image, using dfu. The new image should
378 * be a single raw image.
379 * @vendor_code, @progress and @abort_reason are not supported.
380 *
381 * Return: status code
382 */
383 static
efi_firmware_raw_set_image(struct efi_firmware_management_protocol * this,u8 image_index,const void * image,efi_uintn_t image_size,const void * vendor_code,efi_status_t (* progress)(efi_uintn_t completion),u16 ** abort_reason)384 efi_status_t EFIAPI efi_firmware_raw_set_image(
385 struct efi_firmware_management_protocol *this,
386 u8 image_index,
387 const void *image,
388 efi_uintn_t image_size,
389 const void *vendor_code,
390 efi_status_t (*progress)(efi_uintn_t completion),
391 u16 **abort_reason)
392 {
393 int ret;
394 efi_status_t status;
395
396 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
397 image_size, vendor_code, progress, abort_reason);
398
399 if (!image)
400 return EFI_EXIT(EFI_INVALID_PARAMETER);
401
402 status = efi_firmware_capsule_authenticate(&image, &image_size);
403 if (status != EFI_SUCCESS)
404 return EFI_EXIT(status);
405
406 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
407 /*
408 * Based on the value of update bank, derive the
409 * image index value.
410 */
411 ret = fwu_get_image_index(&image_index);
412 if (ret) {
413 log_debug("Unable to get FWU image_index\n");
414 return EFI_EXIT(EFI_DEVICE_ERROR);
415 }
416 }
417
418 if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
419 NULL, NULL))
420 return EFI_EXIT(EFI_DEVICE_ERROR);
421
422 return EFI_EXIT(EFI_SUCCESS);
423 }
424
425 const struct efi_firmware_management_protocol efi_fmp_raw = {
426 .get_image_info = efi_firmware_get_image_info,
427 .get_image = efi_firmware_get_image_unsupported,
428 .set_image = efi_firmware_raw_set_image,
429 .check_image = efi_firmware_check_image_unsupported,
430 .get_package_info = efi_firmware_get_package_info_unsupported,
431 .set_package_info = efi_firmware_set_package_info_unsupported,
432 };
433 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */
434