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