blob: b557738370eb6caae6afb3c86b51e3dd1f4f689f [file] [log] [blame]
AKASHI Takahirof4818e62020-11-30 18:12:12 +09001// 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>
Masahisa Kojima45a18f02023-06-07 14:41:52 +090013#include <efi_variable.h>
Sughosh Ganu1cadae22022-10-21 18:16:03 +053014#include <fwu.h>
AKASHI Takahirof4818e62020-11-30 18:12:12 +090015#include <image.h>
Sughosh Ganu7221c6e2020-12-30 19:27:05 +053016#include <signatures.h>
17
AKASHI Takahirof4818e62020-11-30 18:12:12 +090018#include <linux/list.h>
19
Sughosh Ganu7221c6e2020-12-30 19:27:05 +053020#define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1')
21
22/**
23 * struct fmp_payload_header - EDK2 header for the FMP payload
24 *
25 * This structure describes the header which is preprended to the
26 * FMP payload by the edk2 capsule generation scripts.
27 *
28 * @signature: Header signature used to identify the header
29 * @header_size: Size of the structure
30 * @fw_version: Firmware versions used
31 * @lowest_supported_version: Lowest supported version
32 */
33struct fmp_payload_header {
34 u32 signature;
35 u32 header_size;
36 u32 fw_version;
37 u32 lowest_supported_version;
38};
39
Masahisa Kojima45a18f02023-06-07 14:41:52 +090040/**
41 * struct fmp_state - fmp firmware update state
42 *
43 * This structure describes the state of the firmware update
44 * through FMP protocol.
45 *
46 * @fw_version: Firmware versions used
47 * @lowest_supported_version: Lowest supported version
48 * @last_attempt_version: Last attempt version
49 * @last_attempt_status: Last attempt status
50 */
51struct fmp_state {
52 u32 fw_version;
53 u32 lowest_supported_version; /* not used */
54 u32 last_attempt_version; /* not used */
55 u32 last_attempt_status; /* not used */
56};
57
Sughosh Ganua1d9f672022-04-15 11:29:37 +053058__weak void set_dfu_alt_info(char *interface, char *devstr)
59{
60 env_set("dfu_alt_info", update_info.dfu_string);
61}
62
Masahisa Kojima45a18f02023-06-07 14:41:52 +090063/**
64 * efi_firmware_get_image_type_id - get image_type_id
65 * @image_index: image index
66 *
67 * Return the image_type_id identified by the image index.
68 *
69 * Return: pointer to the image_type_id, NULL if image_index is invalid
70 */
71static
72efi_guid_t *efi_firmware_get_image_type_id(u8 image_index)
73{
74 int i;
75 struct efi_fw_image *fw_array;
76
77 fw_array = update_info.images;
78 for (i = 0; i < update_info.num_images; i++) {
79 if (fw_array[i].image_index == image_index)
80 return &fw_array[i].image_type_id;
81 }
82
83 return NULL;
84}
85
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +090086/* Place holder; not supported */
87static
88efi_status_t EFIAPI efi_firmware_get_image_unsupported(
89 struct efi_firmware_management_protocol *this,
90 u8 image_index,
91 void *image,
92 efi_uintn_t *image_size)
93{
94 EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
95
96 return EFI_EXIT(EFI_UNSUPPORTED);
97}
98
99/* Place holder; not supported */
100static
101efi_status_t EFIAPI efi_firmware_check_image_unsupported(
102 struct efi_firmware_management_protocol *this,
103 u8 image_index,
104 const void *image,
105 efi_uintn_t *image_size,
106 u32 *image_updatable)
107{
108 EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
109 image_updatable);
110
111 return EFI_EXIT(EFI_UNSUPPORTED);
112}
113
114/* Place holder; not supported */
115static
116efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
117 struct efi_firmware_management_protocol *this,
118 u32 *package_version,
119 u16 **package_version_name,
120 u32 *package_version_name_maxlen,
121 u64 *attributes_supported,
122 u64 *attributes_setting)
123{
124 EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
125 package_version_name, package_version_name_maxlen,
126 attributes_supported, attributes_setting);
127
128 return EFI_EXIT(EFI_UNSUPPORTED);
129}
130
131/* Place holder; not supported */
132static
133efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
134 struct efi_firmware_management_protocol *this,
135 const void *image,
136 efi_uintn_t *image_size,
137 const void *vendor_code,
138 u32 package_version,
139 const u16 *package_version_name)
140{
141 EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
142 package_version, package_version_name);
143
144 return EFI_EXIT(EFI_UNSUPPORTED);
145}
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900146
147/**
Masahisa Kojima941353c2023-06-07 14:41:54 +0900148 * efi_firmware_get_lsv_from_dtb - get lowest supported version from dtb
149 * @image_index: Image index
150 * @image_type_id: Image type id
151 * @lsv: Pointer to store the lowest supported version
152 *
153 * Read the firmware version information from dtb.
154 */
155static void efi_firmware_get_lsv_from_dtb(u8 image_index,
156 efi_guid_t *image_type_id, u32 *lsv)
157{
158 const void *fdt = gd->fdt_blob;
159 const fdt32_t *val;
160 const char *guid_str;
161 int len, offset, index;
162 int parent;
163
164 *lsv = 0;
165
166 parent = fdt_subnode_offset(fdt, 0, "firmware-version");
167 if (parent < 0)
168 return;
169
170 fdt_for_each_subnode(offset, fdt, parent) {
171 efi_guid_t guid;
172
173 guid_str = fdt_getprop(fdt, offset, "image-type-id", &len);
174 if (!guid_str)
175 continue;
176 uuid_str_to_bin(guid_str, guid.b, UUID_STR_FORMAT_GUID);
177
178 val = fdt_getprop(fdt, offset, "image-index", &len);
179 if (!val)
180 continue;
181 index = fdt32_to_cpu(*val);
182
183 if (!guidcmp(&guid, image_type_id) && index == image_index) {
184 val = fdt_getprop(fdt, offset,
185 "lowest-supported-version", &len);
186 if (val)
187 *lsv = fdt32_to_cpu(*val);
188 }
189 }
190}
191
192/**
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900193 * efi_firmware_fill_version_info - fill the version information
194 * @image_info: Image information
195 * @fw_array: Pointer to size of new image
196 *
197 * Fill the version information into image_info strucrure.
198 *
199 */
200static
201void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_info,
202 struct efi_fw_image *fw_array)
203{
204 u16 varname[13]; /* u"FmpStateXXXX" */
205 efi_status_t ret;
206 efi_uintn_t size;
207 struct fmp_state var_state = { 0 };
208
209 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
210 fw_array->image_index);
211 size = sizeof(var_state);
212 ret = efi_get_variable_int(varname, &fw_array->image_type_id,
213 NULL, &size, &var_state, NULL);
214 if (ret == EFI_SUCCESS)
215 image_info->version = var_state.fw_version;
216 else
217 image_info->version = 0;
218
Masahisa Kojima941353c2023-06-07 14:41:54 +0900219 efi_firmware_get_lsv_from_dtb(fw_array->image_index,
220 &fw_array->image_type_id,
221 &image_info->lowest_supported_image_version);
222
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900223 image_info->version_name = NULL; /* not supported */
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900224 image_info->last_attempt_version = 0;
225 image_info->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
226}
227
228/**
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530229 * efi_fill_image_desc_array - populate image descriptor array
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900230 * @image_info_size: Size of @image_info
231 * @image_info: Image information
232 * @descriptor_version: Pointer to version number
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530233 * @descriptor_count: Image count
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900234 * @descriptor_size: Pointer to descriptor size
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530235 * @package_version: Package version
236 * @package_version_name: Package version's name
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900237 *
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530238 * Return information about the current firmware image in @image_info.
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900239 * @image_info will consist of a number of descriptors.
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530240 * Each descriptor will be created based on efi_fw_image array.
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900241 *
242 * Return status code
243 */
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530244static efi_status_t efi_fill_image_desc_array(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900245 efi_uintn_t *image_info_size,
246 struct efi_firmware_image_descriptor *image_info,
247 u32 *descriptor_version,
248 u8 *descriptor_count,
249 efi_uintn_t *descriptor_size,
250 u32 *package_version,
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530251 u16 **package_version_name)
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900252{
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530253 size_t total_size;
254 struct efi_fw_image *fw_array;
255 int i;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900256
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900257 total_size = sizeof(*image_info) * update_info.num_images;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900258
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900259 if (*image_info_size < total_size) {
260 *image_info_size = total_size;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900261
262 return EFI_BUFFER_TOO_SMALL;
263 }
264 *image_info_size = total_size;
265
Sughosh Ganuc212fc72022-05-31 12:45:33 +0530266 fw_array = update_info.images;
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900267 *descriptor_count = update_info.num_images;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900268 *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900269 *descriptor_size = sizeof(*image_info);
270 *package_version = 0xffffffff; /* not supported */
271 *package_version_name = NULL; /* not supported */
272
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900273 for (i = 0; i < update_info.num_images; i++) {
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530274 image_info[i].image_index = fw_array[i].image_index;
275 image_info[i].image_type_id = fw_array[i].image_type_id;
276 image_info[i].image_id = fw_array[i].image_index;
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530277 image_info[i].image_id_name = fw_array[i].fw_name;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900278
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900279 efi_firmware_fill_version_info(&image_info[i], &fw_array[i]);
280
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900281 image_info[i].size = 0;
282 image_info[i].attributes_supported =
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530283 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
284 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900285 image_info[i].attributes_setting =
286 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530287
288 /* Check if the capsule authentication is enabled */
Sughosh Ganud1bd8492021-04-12 20:35:23 +0530289 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530290 image_info[0].attributes_setting |=
291 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
292
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900293 image_info[i].hardware_instance = 1;
294 image_info[i].dependencies = NULL;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900295 }
296
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900297 return EFI_SUCCESS;
298}
299
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200300/**
301 * efi_firmware_capsule_authenticate - authenticate the capsule if enabled
302 * @p_image: Pointer to new image
303 * @p_image_size: Pointer to size of new image
304 *
305 * Authenticate the capsule if authentication is enabled.
306 * The image pointer and the image size are updated in case of success.
307 *
308 * Return: status code
309 */
310static
311efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
312 efi_uintn_t *p_image_size)
313{
314 const void *image = *p_image;
315 efi_uintn_t image_size = *p_image_size;
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200316 void *capsule_payload;
317 efi_status_t status;
318 efi_uintn_t capsule_payload_size;
319
320 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) {
321 capsule_payload = NULL;
322 capsule_payload_size = 0;
323 status = efi_capsule_authenticate(image, image_size,
324 &capsule_payload,
325 &capsule_payload_size);
326
327 if (status == EFI_SECURITY_VIOLATION) {
328 printf("Capsule authentication check failed. Aborting update\n");
329 return status;
330 } else if (status != EFI_SUCCESS) {
331 return status;
332 }
333
334 debug("Capsule authentication successful\n");
335 image = capsule_payload;
336 image_size = capsule_payload_size;
337 } else {
338 debug("Capsule authentication disabled. ");
339 debug("Updating capsule without authenticating.\n");
340 }
341
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200342 *p_image = image;
343 *p_image_size = image_size;
344 return EFI_SUCCESS;
345}
346
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900347/**
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900348 * efi_firmware_set_fmp_state_var - set FmpStateXXXX variable
349 * @state: Pointer to fmp state
350 * @image_index: image index
351 *
352 * Update the FmpStateXXXX variable with the firmware update state.
353 *
354 * Return: status code
355 */
356static
357efi_status_t efi_firmware_set_fmp_state_var(struct fmp_state *state, u8 image_index)
358{
359 u16 varname[13]; /* u"FmpStateXXXX" */
360 efi_status_t ret;
361 efi_guid_t *image_type_id;
362 struct fmp_state var_state = { 0 };
363
364 image_type_id = efi_firmware_get_image_type_id(image_index);
365 if (!image_type_id)
366 return EFI_INVALID_PARAMETER;
367
368 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
369 image_index);
370
371 /*
372 * Only the fw_version is set here.
373 * lowest_supported_version in FmpState variable is ignored since
374 * it can be tampered if the file based EFI variable storage is used.
375 */
376 var_state.fw_version = state->fw_version;
377
378 ret = efi_set_variable_int(varname, image_type_id,
379 EFI_VARIABLE_READ_ONLY |
380 EFI_VARIABLE_NON_VOLATILE |
381 EFI_VARIABLE_BOOTSERVICE_ACCESS |
382 EFI_VARIABLE_RUNTIME_ACCESS,
383 sizeof(var_state), &var_state, false);
384
385 return ret;
386}
387
388/**
389 * efi_firmware_get_fw_version - get fw_version from FMP payload header
390 * @p_image: Pointer to new image
391 * @p_image_size: Pointer to size of new image
392 * @state: Pointer to fmp state
393 *
394 * Parse the FMP payload header and fill the fmp_state structure.
395 * If no FMP payload header is found, fmp_state structure is not updated.
396 *
397 */
398static void efi_firmware_get_fw_version(const void **p_image,
399 efi_uintn_t *p_image_size,
400 struct fmp_state *state)
401{
402 const struct fmp_payload_header *header;
403 u32 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
404
405 header = *p_image;
406 if (header->signature == fmp_hdr_signature) {
407 /* FMP header is inserted above the capsule payload */
408 state->fw_version = header->fw_version;
409
410 *p_image += header->header_size;
411 *p_image_size -= header->header_size;
412 }
413}
414
415/**
416 * efi_firmware_verify_image - verify image
417 * @p_image: Pointer to new image
418 * @p_image_size: Pointer to size of new image
419 * @image_index: Image index
420 * @state: Pointer to fmp state
421 *
Masahisa Kojima94f47802023-06-07 14:41:55 +0900422 * Verify the capsule authentication and check if the fw_version
423 * is equal or greater than the lowest supported version.
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900424 *
425 * Return: status code
426 */
427static
428efi_status_t efi_firmware_verify_image(const void **p_image,
429 efi_uintn_t *p_image_size,
430 u8 image_index,
431 struct fmp_state *state)
432{
Masahisa Kojima94f47802023-06-07 14:41:55 +0900433 u32 lsv;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900434 efi_status_t ret;
Masahisa Kojima94f47802023-06-07 14:41:55 +0900435 efi_guid_t *image_type_id;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900436
437 ret = efi_firmware_capsule_authenticate(p_image, p_image_size);
Masahisa Kojima94f47802023-06-07 14:41:55 +0900438 if (ret != EFI_SUCCESS)
439 return ret;
440
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900441 efi_firmware_get_fw_version(p_image, p_image_size, state);
442
Masahisa Kojima94f47802023-06-07 14:41:55 +0900443 image_type_id = efi_firmware_get_image_type_id(image_index);
444 if (!image_type_id)
445 return EFI_INVALID_PARAMETER;
446
447 efi_firmware_get_lsv_from_dtb(image_index, image_type_id, &lsv);
448 if (state->fw_version < lsv) {
449 log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n",
450 state->fw_version, lsv);
451 return EFI_INVALID_PARAMETER;
452 }
453
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900454 return ret;
455}
456
457/**
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530458 * efi_firmware_get_image_info - return information about the current
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900459 * firmware image
460 * @this: Protocol instance
461 * @image_info_size: Size of @image_info
462 * @image_info: Image information
463 * @descriptor_version: Pointer to version number
464 * @descriptor_count: Pointer to number of descriptors
465 * @descriptor_size: Pointer to descriptor size
Vincent Stehlé0f3c9222022-05-25 11:20:22 +0200466 * @package_version: Package version
467 * @package_version_name: Package version's name
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900468 *
469 * Return information bout the current firmware image in @image_info.
470 * @image_info will consist of a number of descriptors.
471 * Each descriptor will be created based on "dfu_alt_info" variable.
472 *
473 * Return status code
474 */
475static
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530476efi_status_t EFIAPI efi_firmware_get_image_info(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900477 struct efi_firmware_management_protocol *this,
478 efi_uintn_t *image_info_size,
479 struct efi_firmware_image_descriptor *image_info,
480 u32 *descriptor_version,
481 u8 *descriptor_count,
482 efi_uintn_t *descriptor_size,
483 u32 *package_version,
484 u16 **package_version_name)
485{
486 efi_status_t ret;
487
488 EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
489 image_info_size, image_info,
490 descriptor_version, descriptor_count, descriptor_size,
491 package_version, package_version_name);
492
493 if (!image_info_size)
494 return EFI_EXIT(EFI_INVALID_PARAMETER);
495
496 if (*image_info_size &&
497 (!image_info || !descriptor_version || !descriptor_count ||
498 !descriptor_size || !package_version || !package_version_name))
499 return EFI_EXIT(EFI_INVALID_PARAMETER);
500
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530501 ret = efi_fill_image_desc_array(image_info_size, image_info,
502 descriptor_version, descriptor_count,
503 descriptor_size, package_version,
504 package_version_name);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900505
506 return EFI_EXIT(ret);
507}
508
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530509#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
510/*
511 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
512 * method with existing FIT image format, and handles
513 * - multiple regions of firmware via DFU
514 * but doesn't support
515 * - versioning of firmware image
516 * - package information
517 */
518
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900519/**
520 * efi_firmware_fit_set_image - update the firmware image
521 * @this: Protocol instance
522 * @image_index: Image index number
523 * @image: New image
524 * @image_size: Size of new image
525 * @vendor_code: Vendor-specific update policy
526 * @progress: Function to report the progress of update
527 * @abort_reason: Pointer to string of abort reason
528 *
529 * Update the firmware to new image, using dfu. The new image should
530 * have FIT image format commonly used in U-Boot.
531 * @vendor_code, @progress and @abort_reason are not supported.
532 *
533 * Return: status code
534 */
535static
536efi_status_t EFIAPI efi_firmware_fit_set_image(
537 struct efi_firmware_management_protocol *this,
538 u8 image_index,
539 const void *image,
540 efi_uintn_t image_size,
541 const void *vendor_code,
542 efi_status_t (*progress)(efi_uintn_t completion),
543 u16 **abort_reason)
544{
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200545 efi_status_t status;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900546 struct fmp_state state = { 0 };
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200547
Heinrich Schuchardt94f09e02022-02-03 20:13:17 +0100548 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900549 image_size, vendor_code, progress, abort_reason);
550
551 if (!image || image_index != 1)
552 return EFI_EXIT(EFI_INVALID_PARAMETER);
553
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900554 status = efi_firmware_verify_image(&image, &image_size, image_index,
555 &state);
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200556 if (status != EFI_SUCCESS)
557 return EFI_EXIT(status);
558
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900559 if (fit_update(image))
560 return EFI_EXIT(EFI_DEVICE_ERROR);
561
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900562 efi_firmware_set_fmp_state_var(&state, image_index);
563
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900564 return EFI_EXIT(EFI_SUCCESS);
565}
566
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900567const struct efi_firmware_management_protocol efi_fmp_fit = {
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530568 .get_image_info = efi_firmware_get_image_info,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900569 .get_image = efi_firmware_get_image_unsupported,
570 .set_image = efi_firmware_fit_set_image,
571 .check_image = efi_firmware_check_image_unsupported,
572 .get_package_info = efi_firmware_get_package_info_unsupported,
573 .set_package_info = efi_firmware_set_package_info_unsupported,
574};
575#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900576
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900577#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
578/*
579 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
580 * method with raw data.
581 */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900582
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900583/**
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900584 * efi_firmware_raw_set_image - update the firmware image
585 * @this: Protocol instance
586 * @image_index: Image index number
587 * @image: New image
588 * @image_size: Size of new image
589 * @vendor_code: Vendor-specific update policy
590 * @progress: Function to report the progress of update
591 * @abort_reason: Pointer to string of abort reason
592 *
593 * Update the firmware to new image, using dfu. The new image should
594 * be a single raw image.
595 * @vendor_code, @progress and @abort_reason are not supported.
596 *
597 * Return: status code
598 */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900599static
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900600efi_status_t EFIAPI efi_firmware_raw_set_image(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900601 struct efi_firmware_management_protocol *this,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900602 u8 image_index,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900603 const void *image,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900604 efi_uintn_t image_size,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900605 const void *vendor_code,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900606 efi_status_t (*progress)(efi_uintn_t completion),
607 u16 **abort_reason)
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900608{
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530609 int ret;
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530610 efi_status_t status;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900611 struct fmp_state state = { 0 };
Sughosh Ganu7221c6e2020-12-30 19:27:05 +0530612
Heinrich Schuchardt94f09e02022-02-03 20:13:17 +0100613 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900614 image_size, vendor_code, progress, abort_reason);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900615
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900616 if (!image)
617 return EFI_EXIT(EFI_INVALID_PARAMETER);
618
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900619 status = efi_firmware_verify_image(&image, &image_size, image_index,
620 &state);
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200621 if (status != EFI_SUCCESS)
622 return EFI_EXIT(status);
Sughosh Ganu7221c6e2020-12-30 19:27:05 +0530623
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530624 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
625 /*
626 * Based on the value of update bank, derive the
627 * image index value.
628 */
629 ret = fwu_get_image_index(&image_index);
630 if (ret) {
631 log_debug("Unable to get FWU image_index\n");
632 return EFI_EXIT(EFI_DEVICE_ERROR);
633 }
634 }
635
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900636 if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
637 NULL, NULL))
638 return EFI_EXIT(EFI_DEVICE_ERROR);
639
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900640 efi_firmware_set_fmp_state_var(&state, image_index);
641
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900642 return EFI_EXIT(EFI_SUCCESS);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900643}
644
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900645const struct efi_firmware_management_protocol efi_fmp_raw = {
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530646 .get_image_info = efi_firmware_get_image_info,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900647 .get_image = efi_firmware_get_image_unsupported,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900648 .set_image = efi_firmware_raw_set_image,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900649 .check_image = efi_firmware_check_image_unsupported,
650 .get_package_info = efi_firmware_get_package_info_unsupported,
651 .set_package_info = efi_firmware_set_package_info_unsupported,
652};
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900653#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */