1 // SPDX-License-Identifier: GPL-2.0+
3 * EFI Firmware management protocol
5 * Copyright (c) 2020 Linaro Limited
6 * Author: AKASHI Takahiro
12 #include <efi_loader.h>
15 #include <signatures.h>
17 #include <linux/list.h>
19 #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1')
22 * struct fmp_payload_header - EDK2 header for the FMP payload
24 * This structure describes the header which is preprended to the
25 * FMP payload by the edk2 capsule generation scripts.
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
32 struct fmp_payload_header {
36 u32 lowest_supported_version;
39 __weak void set_dfu_alt_info(char *interface, char *devstr)
41 env_set("dfu_alt_info", update_info.dfu_string);
44 /* Place holder; not supported */
46 efi_status_t EFIAPI efi_firmware_get_image_unsupported(
47 struct efi_firmware_management_protocol *this,
50 efi_uintn_t *image_size)
52 EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
54 return EFI_EXIT(EFI_UNSUPPORTED);
57 /* Place holder; not supported */
59 efi_status_t EFIAPI efi_firmware_check_image_unsupported(
60 struct efi_firmware_management_protocol *this,
63 efi_uintn_t *image_size,
66 EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
69 return EFI_EXIT(EFI_UNSUPPORTED);
72 /* Place holder; not supported */
74 efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
75 struct efi_firmware_management_protocol *this,
77 u16 **package_version_name,
78 u32 *package_version_name_maxlen,
79 u64 *attributes_supported,
80 u64 *attributes_setting)
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);
86 return EFI_EXIT(EFI_UNSUPPORTED);
89 /* Place holder; not supported */
91 efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
92 struct efi_firmware_management_protocol *this,
94 efi_uintn_t *image_size,
95 const void *vendor_code,
97 const u16 *package_version_name)
99 EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
100 package_version, package_version_name);
102 return EFI_EXIT(EFI_UNSUPPORTED);
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
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.
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)
131 struct efi_fw_image *fw_array;
134 total_size = sizeof(*image_info) * num_image_type_guids;
136 if (*image_info_size < total_size) {
137 *image_info_size = total_size;
139 return EFI_BUFFER_TOO_SMALL;
141 *image_info_size = total_size;
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 */
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;
155 image_info[i].image_id_name = fw_array[i].fw_name;
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;
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;
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;
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
186 * Authenticate the capsule if authentication is enabled.
187 * The image pointer and the image size are updated in case of success.
189 * Return: status code
192 efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
193 efi_uintn_t *p_image_size)
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;
201 efi_uintn_t capsule_payload_size;
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,
208 &capsule_payload_size);
210 if (status == EFI_SECURITY_VIOLATION) {
211 printf("Capsule authentication check failed. Aborting update\n");
213 } else if (status != EFI_SUCCESS) {
217 debug("Capsule authentication successful\n");
218 image = capsule_payload;
219 image_size = capsule_payload_size;
221 debug("Capsule authentication disabled. ");
222 debug("Updating capsule without authenticating.\n");
225 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
226 header = (void *)image;
228 if (!memcmp(&header->signature, &fmp_hdr_signature,
229 sizeof(fmp_hdr_signature))) {
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.
236 image += header->header_size;
237 image_size -= header->header_size;
241 *p_image_size = image_size;
246 * efi_firmware_get_image_info - return information about the current
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
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.
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)
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);
281 if (!image_info_size)
282 return EFI_EXIT(EFI_INVALID_PARAMETER);
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);
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);
294 return EFI_EXIT(ret);
297 #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
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
308 * efi_firmware_fit_set_image - update the firmware image
309 * @this: Protocol instance
310 * @image_index: Image index number
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
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.
321 * Return: status code
324 efi_status_t EFIAPI efi_firmware_fit_set_image(
325 struct efi_firmware_management_protocol *this,
328 efi_uintn_t image_size,
329 const void *vendor_code,
330 efi_status_t (*progress)(efi_uintn_t completion),
335 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
336 image_size, vendor_code, progress, abort_reason);
338 if (!image || image_index != 1)
339 return EFI_EXIT(EFI_INVALID_PARAMETER);
341 status = efi_firmware_capsule_authenticate(&image, &image_size);
342 if (status != EFI_SUCCESS)
343 return EFI_EXIT(status);
345 if (fit_update(image))
346 return EFI_EXIT(EFI_DEVICE_ERROR);
348 return EFI_EXIT(EFI_SUCCESS);
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,
359 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
361 #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
363 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
364 * method with raw data.
368 * efi_firmware_raw_set_image - update the firmware image
369 * @this: Protocol instance
370 * @image_index: Image index number
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
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.
381 * Return: status code
384 efi_status_t EFIAPI efi_firmware_raw_set_image(
385 struct efi_firmware_management_protocol *this,
388 efi_uintn_t image_size,
389 const void *vendor_code,
390 efi_status_t (*progress)(efi_uintn_t completion),
396 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
397 image_size, vendor_code, progress, abort_reason);
400 return EFI_EXIT(EFI_INVALID_PARAMETER);
402 status = efi_firmware_capsule_authenticate(&image, &image_size);
403 if (status != EFI_SUCCESS)
404 return EFI_EXIT(status);
406 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
408 * Based on the value of update bank, derive the
411 ret = fwu_get_image_index(&image_index);
413 log_debug("Unable to get FWU image_index\n");
414 return EFI_EXIT(EFI_DEVICE_ERROR);
418 if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
420 return EFI_EXIT(EFI_DEVICE_ERROR);
422 return EFI_EXIT(EFI_SUCCESS);
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,
433 #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */