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