blob: 9abb29f1dff18aaffcfa197ca0094245d0e650cb [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;
Masahisa Kojima73a5a262023-07-31 17:53:02 +0900162 int parent, ret;
Masahisa Kojima941353c2023-06-07 14:41:54 +0900163
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;
Masahisa Kojima73a5a262023-07-31 17:53:02 +0900176 ret = uuid_str_to_bin(guid_str, guid.b, UUID_STR_FORMAT_GUID);
177 if (ret < 0) {
178 log_warning("Wrong image-type-id format.\n");
179 continue;
180 }
Masahisa Kojima941353c2023-06-07 14:41:54 +0900181
182 val = fdt_getprop(fdt, offset, "image-index", &len);
183 if (!val)
184 continue;
185 index = fdt32_to_cpu(*val);
186
187 if (!guidcmp(&guid, image_type_id) && index == image_index) {
188 val = fdt_getprop(fdt, offset,
189 "lowest-supported-version", &len);
190 if (val)
191 *lsv = fdt32_to_cpu(*val);
192 }
193 }
194}
195
196/**
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900197 * efi_firmware_fill_version_info - fill the version information
198 * @image_info: Image information
199 * @fw_array: Pointer to size of new image
200 *
201 * Fill the version information into image_info strucrure.
202 *
203 */
204static
205void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_info,
206 struct efi_fw_image *fw_array)
207{
208 u16 varname[13]; /* u"FmpStateXXXX" */
209 efi_status_t ret;
210 efi_uintn_t size;
211 struct fmp_state var_state = { 0 };
212
213 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
214 fw_array->image_index);
215 size = sizeof(var_state);
216 ret = efi_get_variable_int(varname, &fw_array->image_type_id,
217 NULL, &size, &var_state, NULL);
218 if (ret == EFI_SUCCESS)
219 image_info->version = var_state.fw_version;
220 else
221 image_info->version = 0;
222
Masahisa Kojima941353c2023-06-07 14:41:54 +0900223 efi_firmware_get_lsv_from_dtb(fw_array->image_index,
224 &fw_array->image_type_id,
225 &image_info->lowest_supported_image_version);
226
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900227 image_info->version_name = NULL; /* not supported */
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900228 image_info->last_attempt_version = 0;
229 image_info->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
230}
231
232/**
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530233 * efi_fill_image_desc_array - populate image descriptor array
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900234 * @image_info_size: Size of @image_info
235 * @image_info: Image information
236 * @descriptor_version: Pointer to version number
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530237 * @descriptor_count: Image count
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900238 * @descriptor_size: Pointer to descriptor size
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530239 * @package_version: Package version
240 * @package_version_name: Package version's name
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900241 *
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530242 * Return information about the current firmware image in @image_info.
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900243 * @image_info will consist of a number of descriptors.
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530244 * Each descriptor will be created based on efi_fw_image array.
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900245 *
246 * Return status code
247 */
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530248static efi_status_t efi_fill_image_desc_array(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900249 efi_uintn_t *image_info_size,
250 struct efi_firmware_image_descriptor *image_info,
251 u32 *descriptor_version,
252 u8 *descriptor_count,
253 efi_uintn_t *descriptor_size,
254 u32 *package_version,
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530255 u16 **package_version_name)
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900256{
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530257 size_t total_size;
258 struct efi_fw_image *fw_array;
259 int i;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900260
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900261 total_size = sizeof(*image_info) * update_info.num_images;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900262
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900263 if (*image_info_size < total_size) {
264 *image_info_size = total_size;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900265
266 return EFI_BUFFER_TOO_SMALL;
267 }
268 *image_info_size = total_size;
269
Sughosh Ganuc212fc72022-05-31 12:45:33 +0530270 fw_array = update_info.images;
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900271 *descriptor_count = update_info.num_images;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900272 *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900273 *descriptor_size = sizeof(*image_info);
274 *package_version = 0xffffffff; /* not supported */
275 *package_version_name = NULL; /* not supported */
276
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900277 for (i = 0; i < update_info.num_images; i++) {
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530278 image_info[i].image_index = fw_array[i].image_index;
279 image_info[i].image_type_id = fw_array[i].image_type_id;
280 image_info[i].image_id = fw_array[i].image_index;
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530281 image_info[i].image_id_name = fw_array[i].fw_name;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900282
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900283 efi_firmware_fill_version_info(&image_info[i], &fw_array[i]);
284
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900285 image_info[i].size = 0;
286 image_info[i].attributes_supported =
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530287 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
288 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900289 image_info[i].attributes_setting =
290 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530291
292 /* Check if the capsule authentication is enabled */
Sughosh Ganud1bd8492021-04-12 20:35:23 +0530293 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530294 image_info[0].attributes_setting |=
295 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
296
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900297 image_info[i].hardware_instance = 1;
298 image_info[i].dependencies = NULL;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900299 }
300
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900301 return EFI_SUCCESS;
302}
303
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200304/**
305 * efi_firmware_capsule_authenticate - authenticate the capsule if enabled
306 * @p_image: Pointer to new image
307 * @p_image_size: Pointer to size of new image
308 *
309 * Authenticate the capsule if authentication is enabled.
310 * The image pointer and the image size are updated in case of success.
311 *
312 * Return: status code
313 */
314static
315efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
316 efi_uintn_t *p_image_size)
317{
318 const void *image = *p_image;
319 efi_uintn_t image_size = *p_image_size;
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200320 void *capsule_payload;
321 efi_status_t status;
322 efi_uintn_t capsule_payload_size;
323
324 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) {
325 capsule_payload = NULL;
326 capsule_payload_size = 0;
327 status = efi_capsule_authenticate(image, image_size,
328 &capsule_payload,
329 &capsule_payload_size);
330
331 if (status == EFI_SECURITY_VIOLATION) {
332 printf("Capsule authentication check failed. Aborting update\n");
333 return status;
334 } else if (status != EFI_SUCCESS) {
335 return status;
336 }
337
338 debug("Capsule authentication successful\n");
339 image = capsule_payload;
340 image_size = capsule_payload_size;
341 } else {
342 debug("Capsule authentication disabled. ");
343 debug("Updating capsule without authenticating.\n");
344 }
345
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200346 *p_image = image;
347 *p_image_size = image_size;
348 return EFI_SUCCESS;
349}
350
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900351/**
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900352 * efi_firmware_set_fmp_state_var - set FmpStateXXXX variable
353 * @state: Pointer to fmp state
354 * @image_index: image index
355 *
356 * Update the FmpStateXXXX variable with the firmware update state.
357 *
358 * Return: status code
359 */
360static
361efi_status_t efi_firmware_set_fmp_state_var(struct fmp_state *state, u8 image_index)
362{
363 u16 varname[13]; /* u"FmpStateXXXX" */
364 efi_status_t ret;
365 efi_guid_t *image_type_id;
366 struct fmp_state var_state = { 0 };
367
368 image_type_id = efi_firmware_get_image_type_id(image_index);
369 if (!image_type_id)
370 return EFI_INVALID_PARAMETER;
371
372 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
373 image_index);
374
375 /*
376 * Only the fw_version is set here.
377 * lowest_supported_version in FmpState variable is ignored since
378 * it can be tampered if the file based EFI variable storage is used.
379 */
380 var_state.fw_version = state->fw_version;
381
382 ret = efi_set_variable_int(varname, image_type_id,
383 EFI_VARIABLE_READ_ONLY |
384 EFI_VARIABLE_NON_VOLATILE |
385 EFI_VARIABLE_BOOTSERVICE_ACCESS |
386 EFI_VARIABLE_RUNTIME_ACCESS,
387 sizeof(var_state), &var_state, false);
388
389 return ret;
390}
391
392/**
393 * efi_firmware_get_fw_version - get fw_version from FMP payload header
394 * @p_image: Pointer to new image
395 * @p_image_size: Pointer to size of new image
396 * @state: Pointer to fmp state
397 *
398 * Parse the FMP payload header and fill the fmp_state structure.
399 * If no FMP payload header is found, fmp_state structure is not updated.
400 *
401 */
402static void efi_firmware_get_fw_version(const void **p_image,
403 efi_uintn_t *p_image_size,
404 struct fmp_state *state)
405{
406 const struct fmp_payload_header *header;
407 u32 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
408
409 header = *p_image;
410 if (header->signature == fmp_hdr_signature) {
411 /* FMP header is inserted above the capsule payload */
412 state->fw_version = header->fw_version;
413
414 *p_image += header->header_size;
415 *p_image_size -= header->header_size;
416 }
417}
418
419/**
420 * efi_firmware_verify_image - verify image
421 * @p_image: Pointer to new image
422 * @p_image_size: Pointer to size of new image
423 * @image_index: Image index
424 * @state: Pointer to fmp state
425 *
Masahisa Kojima94f47802023-06-07 14:41:55 +0900426 * Verify the capsule authentication and check if the fw_version
427 * is equal or greater than the lowest supported version.
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900428 *
429 * Return: status code
430 */
431static
432efi_status_t efi_firmware_verify_image(const void **p_image,
433 efi_uintn_t *p_image_size,
434 u8 image_index,
435 struct fmp_state *state)
436{
Masahisa Kojima94f47802023-06-07 14:41:55 +0900437 u32 lsv;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900438 efi_status_t ret;
Masahisa Kojima94f47802023-06-07 14:41:55 +0900439 efi_guid_t *image_type_id;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900440
441 ret = efi_firmware_capsule_authenticate(p_image, p_image_size);
Masahisa Kojima94f47802023-06-07 14:41:55 +0900442 if (ret != EFI_SUCCESS)
443 return ret;
444
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900445 efi_firmware_get_fw_version(p_image, p_image_size, state);
446
Masahisa Kojima94f47802023-06-07 14:41:55 +0900447 image_type_id = efi_firmware_get_image_type_id(image_index);
448 if (!image_type_id)
449 return EFI_INVALID_PARAMETER;
450
451 efi_firmware_get_lsv_from_dtb(image_index, image_type_id, &lsv);
452 if (state->fw_version < lsv) {
453 log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n",
454 state->fw_version, lsv);
455 return EFI_INVALID_PARAMETER;
456 }
457
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900458 return ret;
459}
460
461/**
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530462 * efi_firmware_get_image_info - return information about the current
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900463 * firmware image
464 * @this: Protocol instance
465 * @image_info_size: Size of @image_info
466 * @image_info: Image information
467 * @descriptor_version: Pointer to version number
468 * @descriptor_count: Pointer to number of descriptors
469 * @descriptor_size: Pointer to descriptor size
Vincent Stehlé0f3c9222022-05-25 11:20:22 +0200470 * @package_version: Package version
471 * @package_version_name: Package version's name
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900472 *
473 * Return information bout the current firmware image in @image_info.
474 * @image_info will consist of a number of descriptors.
475 * Each descriptor will be created based on "dfu_alt_info" variable.
476 *
477 * Return status code
478 */
479static
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530480efi_status_t EFIAPI efi_firmware_get_image_info(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900481 struct efi_firmware_management_protocol *this,
482 efi_uintn_t *image_info_size,
483 struct efi_firmware_image_descriptor *image_info,
484 u32 *descriptor_version,
485 u8 *descriptor_count,
486 efi_uintn_t *descriptor_size,
487 u32 *package_version,
488 u16 **package_version_name)
489{
490 efi_status_t ret;
491
492 EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
493 image_info_size, image_info,
494 descriptor_version, descriptor_count, descriptor_size,
495 package_version, package_version_name);
496
497 if (!image_info_size)
498 return EFI_EXIT(EFI_INVALID_PARAMETER);
499
500 if (*image_info_size &&
501 (!image_info || !descriptor_version || !descriptor_count ||
502 !descriptor_size || !package_version || !package_version_name))
503 return EFI_EXIT(EFI_INVALID_PARAMETER);
504
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530505 ret = efi_fill_image_desc_array(image_info_size, image_info,
506 descriptor_version, descriptor_count,
507 descriptor_size, package_version,
508 package_version_name);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900509
510 return EFI_EXIT(ret);
511}
512
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530513#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
514/*
515 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
516 * method with existing FIT image format, and handles
517 * - multiple regions of firmware via DFU
518 * but doesn't support
519 * - versioning of firmware image
520 * - package information
521 */
522
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900523/**
524 * efi_firmware_fit_set_image - update the firmware image
525 * @this: Protocol instance
526 * @image_index: Image index number
527 * @image: New image
528 * @image_size: Size of new image
529 * @vendor_code: Vendor-specific update policy
530 * @progress: Function to report the progress of update
531 * @abort_reason: Pointer to string of abort reason
532 *
533 * Update the firmware to new image, using dfu. The new image should
534 * have FIT image format commonly used in U-Boot.
535 * @vendor_code, @progress and @abort_reason are not supported.
536 *
537 * Return: status code
538 */
539static
540efi_status_t EFIAPI efi_firmware_fit_set_image(
541 struct efi_firmware_management_protocol *this,
542 u8 image_index,
543 const void *image,
544 efi_uintn_t image_size,
545 const void *vendor_code,
546 efi_status_t (*progress)(efi_uintn_t completion),
547 u16 **abort_reason)
548{
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200549 efi_status_t status;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900550 struct fmp_state state = { 0 };
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200551
Heinrich Schuchardt94f09e02022-02-03 20:13:17 +0100552 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900553 image_size, vendor_code, progress, abort_reason);
554
555 if (!image || image_index != 1)
556 return EFI_EXIT(EFI_INVALID_PARAMETER);
557
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900558 status = efi_firmware_verify_image(&image, &image_size, image_index,
559 &state);
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200560 if (status != EFI_SUCCESS)
561 return EFI_EXIT(status);
562
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900563 if (fit_update(image))
564 return EFI_EXIT(EFI_DEVICE_ERROR);
565
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900566 efi_firmware_set_fmp_state_var(&state, image_index);
567
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900568 return EFI_EXIT(EFI_SUCCESS);
569}
570
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900571const struct efi_firmware_management_protocol efi_fmp_fit = {
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530572 .get_image_info = efi_firmware_get_image_info,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900573 .get_image = efi_firmware_get_image_unsupported,
574 .set_image = efi_firmware_fit_set_image,
575 .check_image = efi_firmware_check_image_unsupported,
576 .get_package_info = efi_firmware_get_package_info_unsupported,
577 .set_package_info = efi_firmware_set_package_info_unsupported,
578};
579#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900580
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900581#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
582/*
583 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
584 * method with raw data.
585 */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900586
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900587/**
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900588 * efi_firmware_raw_set_image - update the firmware image
589 * @this: Protocol instance
590 * @image_index: Image index number
591 * @image: New image
592 * @image_size: Size of new image
593 * @vendor_code: Vendor-specific update policy
594 * @progress: Function to report the progress of update
595 * @abort_reason: Pointer to string of abort reason
596 *
597 * Update the firmware to new image, using dfu. The new image should
598 * be a single raw image.
599 * @vendor_code, @progress and @abort_reason are not supported.
600 *
601 * Return: status code
602 */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900603static
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900604efi_status_t EFIAPI efi_firmware_raw_set_image(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900605 struct efi_firmware_management_protocol *this,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900606 u8 image_index,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900607 const void *image,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900608 efi_uintn_t image_size,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900609 const void *vendor_code,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900610 efi_status_t (*progress)(efi_uintn_t completion),
611 u16 **abort_reason)
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900612{
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530613 int ret;
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530614 efi_status_t status;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900615 struct fmp_state state = { 0 };
Sughosh Ganu7221c6e2020-12-30 19:27:05 +0530616
Heinrich Schuchardt94f09e02022-02-03 20:13:17 +0100617 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900618 image_size, vendor_code, progress, abort_reason);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900619
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900620 if (!image)
621 return EFI_EXIT(EFI_INVALID_PARAMETER);
622
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900623 status = efi_firmware_verify_image(&image, &image_size, image_index,
624 &state);
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200625 if (status != EFI_SUCCESS)
626 return EFI_EXIT(status);
Sughosh Ganu7221c6e2020-12-30 19:27:05 +0530627
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530628 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
629 /*
630 * Based on the value of update bank, derive the
631 * image index value.
632 */
633 ret = fwu_get_image_index(&image_index);
634 if (ret) {
635 log_debug("Unable to get FWU image_index\n");
636 return EFI_EXIT(EFI_DEVICE_ERROR);
637 }
638 }
639
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900640 if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
641 NULL, NULL))
642 return EFI_EXIT(EFI_DEVICE_ERROR);
643
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900644 efi_firmware_set_fmp_state_var(&state, image_index);
645
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900646 return EFI_EXIT(EFI_SUCCESS);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900647}
648
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900649const struct efi_firmware_management_protocol efi_fmp_raw = {
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530650 .get_image_info = efi_firmware_get_image_info,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900651 .get_image = efi_firmware_get_image_unsupported,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900652 .set_image = efi_firmware_raw_set_image,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900653 .check_image = efi_firmware_check_image_unsupported,
654 .get_package_info = efi_firmware_get_package_info_unsupported,
655 .set_package_info = efi_firmware_set_package_info_unsupported,
656};
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900657#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */