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