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 #define LOG_CATEGORY LOGC_EFI
10
11 #include <charset.h>
12 #include <dfu.h>
13 #include <efi_loader.h>
14 #include <efi_variable.h>
15 #include <env.h>
16 #include <fwu.h>
17 #include <image.h>
18 #include <signatures.h>
19
20 #include <linux/list.h>
21
22 #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1')
23
24 /**
25 * struct fmp_payload_header - EDK2 header for the FMP payload
26 *
27 * This structure describes the header which is preprended to the
28 * FMP payload by the edk2 capsule generation scripts.
29 *
30 * @signature: Header signature used to identify the header
31 * @header_size: Size of the structure
32 * @fw_version: Firmware versions used
33 * @lowest_supported_version: Lowest supported version
34 */
35 struct fmp_payload_header {
36 u32 signature;
37 u32 header_size;
38 u32 fw_version;
39 u32 lowest_supported_version;
40 };
41
42 /**
43 * struct fmp_state - fmp firmware update state
44 *
45 * This structure describes the state of the firmware update
46 * through FMP protocol.
47 *
48 * @fw_version: Firmware versions used
49 * @lowest_supported_version: Lowest supported version
50 * @last_attempt_version: Last attempt version
51 * @last_attempt_status: Last attempt status
52 */
53 struct fmp_state {
54 u32 fw_version;
55 u32 lowest_supported_version; /* not used */
56 u32 last_attempt_version; /* not used */
57 u32 last_attempt_status; /* not used */
58 };
59
60 /**
61 * efi_firmware_get_image_type_id - get image_type_id
62 * @image_index: image index
63 *
64 * Return the image_type_id identified by the image index.
65 *
66 * Return: pointer to the image_type_id, NULL if image_index is invalid
67 */
68 static
efi_firmware_get_image_type_id(u8 image_index)69 efi_guid_t *efi_firmware_get_image_type_id(u8 image_index)
70 {
71 int i;
72 struct efi_fw_image *fw_array;
73
74 fw_array = update_info.images;
75 for (i = 0; i < update_info.num_images; i++) {
76 if (fw_array[i].image_index == image_index)
77 return &fw_array[i].image_type_id;
78 }
79
80 return NULL;
81 }
82
83 /* Place holder; not supported */
84 static
efi_firmware_get_image_unsupported(struct efi_firmware_management_protocol * this,u8 image_index,void * image,efi_uintn_t * image_size)85 efi_status_t EFIAPI efi_firmware_get_image_unsupported(
86 struct efi_firmware_management_protocol *this,
87 u8 image_index,
88 void *image,
89 efi_uintn_t *image_size)
90 {
91 EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
92
93 return EFI_EXIT(EFI_UNSUPPORTED);
94 }
95
96 /* Place holder; not supported */
97 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)98 efi_status_t EFIAPI efi_firmware_check_image_unsupported(
99 struct efi_firmware_management_protocol *this,
100 u8 image_index,
101 const void *image,
102 efi_uintn_t *image_size,
103 u32 *image_updatable)
104 {
105 EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
106 image_updatable);
107
108 return EFI_EXIT(EFI_UNSUPPORTED);
109 }
110
111 /* Place holder; not supported */
112 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)113 efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
114 struct efi_firmware_management_protocol *this,
115 u32 *package_version,
116 u16 **package_version_name,
117 u32 *package_version_name_maxlen,
118 u64 *attributes_supported,
119 u64 *attributes_setting)
120 {
121 EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
122 package_version_name, package_version_name_maxlen,
123 attributes_supported, attributes_setting);
124
125 return EFI_EXIT(EFI_UNSUPPORTED);
126 }
127
128 /* Place holder; not supported */
129 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)130 efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
131 struct efi_firmware_management_protocol *this,
132 const void *image,
133 efi_uintn_t *image_size,
134 const void *vendor_code,
135 u32 package_version,
136 const u16 *package_version_name)
137 {
138 EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
139 package_version, package_version_name);
140
141 return EFI_EXIT(EFI_UNSUPPORTED);
142 }
143
144 /**
145 * efi_firmware_get_lsv_from_dtb - get lowest supported version from dtb
146 * @image_index: Image index
147 * @image_type_id: Image type id
148 * @lsv: Pointer to store the lowest supported version
149 *
150 * Read the firmware version information from dtb.
151 */
efi_firmware_get_lsv_from_dtb(u8 image_index,efi_guid_t * image_type_id,u32 * lsv)152 static void efi_firmware_get_lsv_from_dtb(u8 image_index,
153 efi_guid_t *image_type_id, u32 *lsv)
154 {
155 const void *fdt = gd->fdt_blob;
156 const fdt32_t *val;
157 const char *guid_str;
158 int len, offset, index;
159 int parent, ret;
160
161 *lsv = 0;
162
163 parent = fdt_subnode_offset(fdt, 0, "firmware-version");
164 if (parent < 0)
165 return;
166
167 fdt_for_each_subnode(offset, fdt, parent) {
168 efi_guid_t guid;
169
170 guid_str = fdt_getprop(fdt, offset, "image-type-id", &len);
171 if (!guid_str)
172 continue;
173 ret = uuid_str_to_bin(guid_str, guid.b, UUID_STR_FORMAT_GUID);
174 if (ret < 0) {
175 log_warning("Wrong image-type-id format.\n");
176 continue;
177 }
178
179 val = fdt_getprop(fdt, offset, "image-index", &len);
180 if (!val)
181 continue;
182 index = fdt32_to_cpu(*val);
183
184 if (!guidcmp(&guid, image_type_id) && index == image_index) {
185 val = fdt_getprop(fdt, offset,
186 "lowest-supported-version", &len);
187 if (val)
188 *lsv = fdt32_to_cpu(*val);
189 }
190 }
191 }
192
193 /**
194 * efi_firmware_fill_version_info - fill the version information
195 * @image_info: Image information
196 * @fw_array: Pointer to size of new image
197 *
198 * Fill the version information into image_info strucrure.
199 *
200 */
201 static
efi_firmware_fill_version_info(struct efi_firmware_image_descriptor * image_info,struct efi_fw_image * fw_array)202 void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_info,
203 struct efi_fw_image *fw_array)
204 {
205 u16 varname[13]; /* u"FmpStateXXXX" */
206 efi_status_t ret;
207 efi_uintn_t size, expected_size;
208 uint num_banks = 1;
209 uint active_index = 0;
210 struct fmp_state *var_state;
211
212 efi_firmware_get_lsv_from_dtb(fw_array->image_index,
213 &fw_array->image_type_id,
214 &image_info->lowest_supported_image_version);
215
216 image_info->version_name = NULL; /* not supported */
217 image_info->last_attempt_version = 0;
218 image_info->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
219 image_info->version = 0;
220
221 /* get the fw_version */
222 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
223 fw_array->image_index);
224 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
225 ret = fwu_get_active_index(&active_index);
226 if (ret)
227 return;
228
229 num_banks = CONFIG_FWU_NUM_BANKS;
230 }
231
232 size = num_banks * sizeof(*var_state);
233 expected_size = size;
234 var_state = calloc(1, size);
235 if (!var_state)
236 return;
237
238 ret = efi_get_variable_int(varname, &fw_array->image_type_id,
239 NULL, &size, var_state, NULL);
240 if (ret == EFI_SUCCESS && expected_size == size)
241 image_info->version = var_state[active_index].fw_version;
242
243 free(var_state);
244 }
245
246 /**
247 * efi_gen_capsule_guids - generate GUIDs for the images
248 *
249 * Generate the image_type_id for each image in the update_info.images array
250 * using the first compatible from the device tree and a salt
251 * UUID defined at build time.
252 *
253 * Returns: status code
254 */
efi_gen_capsule_guids(void)255 static efi_status_t efi_gen_capsule_guids(void)
256 {
257 int ret, i;
258 struct uuid namespace;
259 const char *compatible; /* Full array including null bytes */
260 struct efi_fw_image *fw_array;
261
262 fw_array = update_info.images;
263 /* Check if we need to run (there are images and we didn't already generate their IDs) */
264 if (!update_info.num_images ||
265 memchr_inv(&fw_array[0].image_type_id, 0, sizeof(fw_array[0].image_type_id)))
266 return EFI_SUCCESS;
267
268 ret = uuid_str_to_bin(CONFIG_EFI_CAPSULE_NAMESPACE_GUID,
269 (unsigned char *)&namespace, UUID_STR_FORMAT_GUID);
270 if (ret) {
271 log_debug("%s: EFI_CAPSULE_NAMESPACE_GUID is invalid: %d\n", __func__, ret);
272 return EFI_INVALID_PARAMETER;
273 }
274
275 compatible = ofnode_read_string(ofnode_root(), "compatible");
276 if (!compatible) {
277 log_debug("%s: model or compatible not defined\n", __func__);
278 return EFI_INVALID_PARAMETER;
279 }
280
281 for (i = 0; i < update_info.num_images; i++) {
282 if (!fw_array[i].fw_name) {
283 log_err("fw_name is not defined. Not generating capsule GUIDs\n");
284 return EFI_INVALID_PARAMETER;
285 }
286 gen_v5_guid(&namespace,
287 &fw_array[i].image_type_id,
288 compatible, strlen(compatible),
289 fw_array[i].fw_name, u16_strlen(fw_array[i].fw_name) * sizeof(uint16_t),
290 NULL);
291
292 log_debug("Image %ls UUID %pUl\n", fw_array[i].fw_name,
293 &fw_array[i].image_type_id);
294 }
295
296 return EFI_SUCCESS;
297 }
298
299 /**
300 * efi_fill_image_desc_array - populate image descriptor array
301 * @image_info_size: Size of @image_info
302 * @image_info: Image information
303 * @descriptor_version: Pointer to version number
304 * @descriptor_count: Image count
305 * @descriptor_size: Pointer to descriptor size
306 * @package_version: Package version
307 * @package_version_name: Package version's name
308 *
309 * Return information about the current firmware image in @image_info.
310 * @image_info will consist of a number of descriptors.
311 * Each descriptor will be created based on efi_fw_image array.
312 *
313 * Return status code
314 */
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)315 static efi_status_t efi_fill_image_desc_array(
316 efi_uintn_t *image_info_size,
317 struct efi_firmware_image_descriptor *image_info,
318 u32 *descriptor_version,
319 u8 *descriptor_count,
320 efi_uintn_t *descriptor_size,
321 u32 *package_version,
322 u16 **package_version_name)
323 {
324 size_t total_size;
325 struct efi_fw_image *fw_array;
326 int i, ret;
327
328 total_size = sizeof(*image_info) * update_info.num_images;
329
330 if (*image_info_size < total_size) {
331 *image_info_size = total_size;
332
333 return EFI_BUFFER_TOO_SMALL;
334 }
335 if (!image_info)
336 return EFI_INVALID_PARAMETER;
337 *image_info_size = total_size;
338
339 ret = efi_gen_capsule_guids();
340 if (ret != EFI_SUCCESS)
341 return ret;
342
343 fw_array = update_info.images;
344 *descriptor_count = update_info.num_images;
345 *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
346 *descriptor_size = sizeof(*image_info);
347 *package_version = 0xffffffff; /* not supported */
348 *package_version_name = NULL; /* not supported */
349
350 for (i = 0; i < update_info.num_images; i++) {
351 image_info[i].image_index = fw_array[i].image_index;
352 image_info[i].image_type_id = fw_array[i].image_type_id;
353 image_info[i].image_id = fw_array[i].image_index;
354 image_info[i].image_id_name = fw_array[i].fw_name;
355
356 efi_firmware_fill_version_info(&image_info[i], &fw_array[i]);
357
358 image_info[i].size = 0;
359 image_info[i].attributes_supported =
360 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
361 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
362 image_info[i].attributes_setting =
363 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
364
365 /* Check if the capsule authentication is enabled */
366 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
367 image_info[0].attributes_setting |=
368 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
369
370 image_info[i].hardware_instance = 1;
371 image_info[i].dependencies = NULL;
372 }
373
374 return EFI_SUCCESS;
375 }
376
377 /**
378 * efi_firmware_capsule_authenticate - authenticate the capsule if enabled
379 * @p_image: Pointer to new image
380 * @p_image_size: Pointer to size of new image
381 *
382 * Authenticate the capsule if authentication is enabled.
383 * The image pointer and the image size are updated in case of success.
384 *
385 * Return: status code
386 */
387 static
efi_firmware_capsule_authenticate(const void ** p_image,efi_uintn_t * p_image_size)388 efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
389 efi_uintn_t *p_image_size)
390 {
391 const void *image = *p_image;
392 efi_uintn_t image_size = *p_image_size;
393 void *capsule_payload;
394 efi_status_t status;
395 efi_uintn_t capsule_payload_size;
396
397 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) {
398 capsule_payload = NULL;
399 capsule_payload_size = 0;
400 status = efi_capsule_authenticate(image, image_size,
401 &capsule_payload,
402 &capsule_payload_size);
403
404 if (status == EFI_SECURITY_VIOLATION) {
405 printf("Capsule authentication check failed. Aborting update\n");
406 return status;
407 } else if (status != EFI_SUCCESS) {
408 return status;
409 }
410
411 debug("Capsule authentication successful\n");
412 image = capsule_payload;
413 image_size = capsule_payload_size;
414 } else {
415 debug("Capsule authentication disabled. ");
416 debug("Updating capsule without authenticating.\n");
417 }
418
419 *p_image = image;
420 *p_image_size = image_size;
421 return EFI_SUCCESS;
422 }
423
424 /**
425 * efi_firmware_set_fmp_state_var - set FmpStateXXXX variable
426 * @state: Pointer to fmp state
427 * @image_index: image index
428 *
429 * Update the FmpStateXXXX variable with the firmware update state.
430 *
431 * Return: status code
432 */
433 static
efi_firmware_set_fmp_state_var(struct fmp_state * state,u8 image_index)434 efi_status_t efi_firmware_set_fmp_state_var(struct fmp_state *state, u8 image_index)
435 {
436 u16 varname[13]; /* u"FmpStateXXXX" */
437 efi_status_t ret;
438 uint num_banks = 1;
439 uint update_bank = 0;
440 efi_uintn_t size;
441 efi_guid_t *image_type_id;
442 struct fmp_state *var_state;
443
444 image_type_id = efi_firmware_get_image_type_id(image_index);
445 if (!image_type_id)
446 return EFI_INVALID_PARAMETER;
447
448 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
449 image_index);
450
451 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
452 ret = fwu_plat_get_update_index(&update_bank);
453 if (ret)
454 return EFI_INVALID_PARAMETER;
455
456 num_banks = CONFIG_FWU_NUM_BANKS;
457 }
458
459 size = num_banks * sizeof(*var_state);
460 var_state = malloc(size);
461 if (!var_state)
462 return EFI_OUT_OF_RESOURCES;
463
464 /*
465 * GetVariable may fail, EFI_NOT_FOUND is returned if FmpState
466 * variable has not been set yet.
467 */
468 ret = efi_get_variable_int(varname, image_type_id, NULL, &size,
469 var_state, NULL);
470 if (ret != EFI_SUCCESS)
471 memset(var_state, 0, num_banks * sizeof(*var_state));
472
473 /*
474 * Only the fw_version is set here.
475 * lowest_supported_version in FmpState variable is ignored since
476 * it can be tampered if the file based EFI variable storage is used.
477 */
478 var_state[update_bank].fw_version = state->fw_version;
479
480 size = num_banks * sizeof(*var_state);
481 ret = efi_set_variable_int(varname, image_type_id,
482 EFI_VARIABLE_READ_ONLY |
483 EFI_VARIABLE_NON_VOLATILE |
484 EFI_VARIABLE_BOOTSERVICE_ACCESS |
485 EFI_VARIABLE_RUNTIME_ACCESS,
486 size, var_state, false);
487
488 free(var_state);
489
490 return ret;
491 }
492
493 /**
494 * efi_firmware_get_fw_version - get fw_version from FMP payload header
495 * @p_image: Pointer to new image
496 * @p_image_size: Pointer to size of new image
497 * @state: Pointer to fmp state
498 *
499 * Parse the FMP payload header and fill the fmp_state structure.
500 * If no FMP payload header is found, fmp_state structure is not updated.
501 *
502 */
efi_firmware_get_fw_version(const void ** p_image,efi_uintn_t * p_image_size,struct fmp_state * state)503 static void efi_firmware_get_fw_version(const void **p_image,
504 efi_uintn_t *p_image_size,
505 struct fmp_state *state)
506 {
507 const struct fmp_payload_header *header;
508 u32 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
509
510 header = *p_image;
511 if (header->signature == fmp_hdr_signature) {
512 /* FMP header is inserted above the capsule payload */
513 state->fw_version = header->fw_version;
514
515 *p_image += header->header_size;
516 *p_image_size -= header->header_size;
517 }
518 }
519
520 /**
521 * efi_firmware_verify_image - verify image
522 * @p_image: Pointer to new image
523 * @p_image_size: Pointer to size of new image
524 * @image_index: Image index
525 * @state: Pointer to fmp state
526 *
527 * Verify the capsule authentication and check if the fw_version
528 * is equal or greater than the lowest supported version.
529 *
530 * Return: status code
531 */
532 static
efi_firmware_verify_image(const void ** p_image,efi_uintn_t * p_image_size,u8 image_index,struct fmp_state * state)533 efi_status_t efi_firmware_verify_image(const void **p_image,
534 efi_uintn_t *p_image_size,
535 u8 image_index,
536 struct fmp_state *state)
537 {
538 u32 lsv;
539 efi_status_t ret;
540 efi_guid_t *image_type_id;
541
542 ret = efi_firmware_capsule_authenticate(p_image, p_image_size);
543 if (ret != EFI_SUCCESS)
544 return ret;
545
546 efi_firmware_get_fw_version(p_image, p_image_size, state);
547
548 image_type_id = efi_firmware_get_image_type_id(image_index);
549 if (!image_type_id)
550 return EFI_INVALID_PARAMETER;
551
552 efi_firmware_get_lsv_from_dtb(image_index, image_type_id, &lsv);
553 if (state->fw_version < lsv) {
554 log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n",
555 state->fw_version, lsv);
556 return EFI_INVALID_PARAMETER;
557 }
558
559 return ret;
560 }
561
562 /**
563 * efi_firmware_get_image_info - return information about the current
564 * firmware image
565 * @this: Protocol instance
566 * @image_info_size: Size of @image_info
567 * @image_info: Image information
568 * @descriptor_version: Pointer to version number
569 * @descriptor_count: Pointer to number of descriptors
570 * @descriptor_size: Pointer to descriptor size
571 * @package_version: Package version
572 * @package_version_name: Package version's name
573 *
574 * Return information bout the current firmware image in @image_info.
575 * @image_info will consist of a number of descriptors.
576 * Each descriptor will be created based on "dfu_alt_info" variable.
577 *
578 * Return status code
579 */
580 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)581 efi_status_t EFIAPI efi_firmware_get_image_info(
582 struct efi_firmware_management_protocol *this,
583 efi_uintn_t *image_info_size,
584 struct efi_firmware_image_descriptor *image_info,
585 u32 *descriptor_version,
586 u8 *descriptor_count,
587 efi_uintn_t *descriptor_size,
588 u32 *package_version,
589 u16 **package_version_name)
590 {
591 efi_status_t ret;
592
593 EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
594 image_info_size, image_info,
595 descriptor_version, descriptor_count, descriptor_size,
596 package_version, package_version_name);
597
598 if (!image_info_size)
599 return EFI_EXIT(EFI_INVALID_PARAMETER);
600
601 if (*image_info_size &&
602 (!image_info || !descriptor_version || !descriptor_count ||
603 !descriptor_size || !package_version || !package_version_name))
604 return EFI_EXIT(EFI_INVALID_PARAMETER);
605
606 ret = efi_fill_image_desc_array(image_info_size, image_info,
607 descriptor_version, descriptor_count,
608 descriptor_size, package_version,
609 package_version_name);
610
611 return EFI_EXIT(ret);
612 }
613
614 #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
615 /*
616 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
617 * method with existing FIT image format, and handles
618 * - multiple regions of firmware via DFU
619 * but doesn't support
620 * - versioning of firmware image
621 * - package information
622 */
623
624 /**
625 * efi_firmware_fit_set_image - update the firmware image
626 * @this: Protocol instance
627 * @image_index: Image index number
628 * @image: New image
629 * @image_size: Size of new image
630 * @vendor_code: Vendor-specific update policy
631 * @progress: Function to report the progress of update
632 * @abort_reason: Pointer to string of abort reason
633 *
634 * Update the firmware to new image, using dfu. The new image should
635 * have FIT image format commonly used in U-Boot.
636 * @vendor_code, @progress and @abort_reason are not supported.
637 *
638 * Return: status code
639 */
640 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)641 efi_status_t EFIAPI efi_firmware_fit_set_image(
642 struct efi_firmware_management_protocol *this,
643 u8 image_index,
644 const void *image,
645 efi_uintn_t image_size,
646 const void *vendor_code,
647 efi_status_t (*progress)(efi_uintn_t completion),
648 u16 **abort_reason)
649 {
650 int ret;
651 efi_status_t status;
652 struct fmp_state state = { 0 };
653 char *orig_dfu_env;
654
655 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
656 image_size, vendor_code, progress, abort_reason);
657
658 if (!image || image_index != 1)
659 return EFI_EXIT(EFI_INVALID_PARAMETER);
660
661 status = efi_firmware_verify_image(&image, &image_size, image_index,
662 &state);
663 if (status != EFI_SUCCESS)
664 return EFI_EXIT(status);
665
666 orig_dfu_env = env_get("dfu_alt_info");
667 if (orig_dfu_env) {
668 orig_dfu_env = strdup(orig_dfu_env);
669 if (!orig_dfu_env) {
670 log_err("strdup() failed!\n");
671 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
672 }
673 }
674 if (env_set("dfu_alt_info", update_info.dfu_string)) {
675 log_err("Unable to set env variable \"dfu_alt_info\"!\n");
676 free(orig_dfu_env);
677 return EFI_EXIT(EFI_DEVICE_ERROR);
678 }
679
680 ret = fit_update(image);
681
682 if (env_set("dfu_alt_info", orig_dfu_env))
683 log_warning("Unable to restore env variable \"dfu_alt_info\". Further DFU operations may fail!\n");
684
685 free(orig_dfu_env);
686
687 if (ret)
688 return EFI_EXIT(EFI_DEVICE_ERROR);
689
690 efi_firmware_set_fmp_state_var(&state, image_index);
691
692 return EFI_EXIT(EFI_SUCCESS);
693 }
694
695 const struct efi_firmware_management_protocol efi_fmp_fit = {
696 .get_image_info = efi_firmware_get_image_info,
697 .get_image = efi_firmware_get_image_unsupported,
698 .set_image = efi_firmware_fit_set_image,
699 .check_image = efi_firmware_check_image_unsupported,
700 .get_package_info = efi_firmware_get_package_info_unsupported,
701 .set_package_info = efi_firmware_set_package_info_unsupported,
702 };
703 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
704
705 #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
706 /*
707 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
708 * method with raw data.
709 */
710
711 /**
712 * efi_firmware_raw_set_image - update the firmware image
713 * @this: Protocol instance
714 * @image_index: Image index number
715 * @image: New image
716 * @image_size: Size of new image
717 * @vendor_code: Vendor-specific update policy
718 * @progress: Function to report the progress of update
719 * @abort_reason: Pointer to string of abort reason
720 *
721 * Update the firmware to new image, using dfu. The new image should
722 * be a single raw image.
723 * @vendor_code, @progress and @abort_reason are not supported.
724 *
725 * Return: status code
726 */
727 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)728 efi_status_t EFIAPI efi_firmware_raw_set_image(
729 struct efi_firmware_management_protocol *this,
730 u8 image_index,
731 const void *image,
732 efi_uintn_t image_size,
733 const void *vendor_code,
734 efi_status_t (*progress)(efi_uintn_t completion),
735 u16 **abort_reason)
736 {
737 int ret;
738 u8 dfu_alt_num;
739 efi_status_t status;
740 struct fmp_state state = { 0 };
741 char *orig_dfu_env;
742
743 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
744 image_size, vendor_code, progress, abort_reason);
745
746 if (!image)
747 return EFI_EXIT(EFI_INVALID_PARAMETER);
748
749 status = efi_firmware_verify_image(&image, &image_size, image_index,
750 &state);
751 if (status != EFI_SUCCESS)
752 return EFI_EXIT(status);
753
754 /*
755 * dfu_alt_num is assigned from 0 while image_index starts from 1.
756 * dfu_alt_num is calculated by (image_index - 1) when multi bank update
757 * is not used.
758 */
759 dfu_alt_num = image_index - 1;
760 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
761 /*
762 * Based on the value of update bank, derive the
763 * image index value.
764 */
765 ret = fwu_get_dfu_alt_num(image_index, &dfu_alt_num);
766 if (ret) {
767 log_debug("Unable to get FWU image_index\n");
768 return EFI_EXIT(EFI_DEVICE_ERROR);
769 }
770 }
771
772 orig_dfu_env = env_get("dfu_alt_info");
773 if (orig_dfu_env) {
774 orig_dfu_env = strdup(orig_dfu_env);
775 if (!orig_dfu_env) {
776 log_err("strdup() failed!\n");
777 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
778 }
779 }
780 if (env_set("dfu_alt_info", update_info.dfu_string)) {
781 log_err("Unable to set env variable \"dfu_alt_info\"!\n");
782 free(orig_dfu_env);
783 return EFI_EXIT(EFI_DEVICE_ERROR);
784 }
785
786 ret = dfu_write_by_alt(dfu_alt_num, (void *)image, image_size,
787 NULL, NULL);
788
789 if (env_set("dfu_alt_info", orig_dfu_env))
790 log_warning("Unable to restore env variable \"dfu_alt_info\". Further DFU operations may fail!\n");
791
792 free(orig_dfu_env);
793
794 if (ret)
795 return EFI_EXIT(EFI_DEVICE_ERROR);
796
797 efi_firmware_set_fmp_state_var(&state, image_index);
798
799 return EFI_EXIT(EFI_SUCCESS);
800 }
801
802 const struct efi_firmware_management_protocol efi_fmp_raw = {
803 .get_image_info = efi_firmware_get_image_info,
804 .get_image = efi_firmware_get_image_unsupported,
805 .set_image = efi_firmware_raw_set_image,
806 .check_image = efi_firmware_check_image_unsupported,
807 .get_package_info = efi_firmware_get_package_info_unsupported,
808 .set_package_info = efi_firmware_set_package_info_unsupported,
809 };
810 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */
811