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