blob: 1fde1885e3ca95696a57b301f7cd760e66c46d4a [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
AKASHI Takahirof4818e62020-11-30 18:12:12 +09009#include <charset.h>
10#include <dfu.h>
11#include <efi_loader.h>
Masahisa Kojima45a18f02023-06-07 14:41:52 +090012#include <efi_variable.h>
Sughosh Ganu1cadae22022-10-21 18:16:03 +053013#include <fwu.h>
AKASHI Takahirof4818e62020-11-30 18:12:12 +090014#include <image.h>
Sughosh Ganu7221c6e2020-12-30 19:27:05 +053015#include <signatures.h>
16
AKASHI Takahirof4818e62020-11-30 18:12:12 +090017#include <linux/list.h>
18
Sughosh Ganu7221c6e2020-12-30 19:27:05 +053019#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 */
32struct fmp_payload_header {
33 u32 signature;
34 u32 header_size;
35 u32 fw_version;
36 u32 lowest_supported_version;
37};
38
Masahisa Kojima45a18f02023-06-07 14:41:52 +090039/**
40 * struct fmp_state - fmp firmware update state
41 *
42 * This structure describes the state of the firmware update
43 * through FMP protocol.
44 *
45 * @fw_version: Firmware versions used
46 * @lowest_supported_version: Lowest supported version
47 * @last_attempt_version: Last attempt version
48 * @last_attempt_status: Last attempt status
49 */
50struct fmp_state {
51 u32 fw_version;
52 u32 lowest_supported_version; /* not used */
53 u32 last_attempt_version; /* not used */
54 u32 last_attempt_status; /* not used */
55};
56
Sughosh Ganua1d9f672022-04-15 11:29:37 +053057__weak void set_dfu_alt_info(char *interface, char *devstr)
58{
59 env_set("dfu_alt_info", update_info.dfu_string);
60}
61
Masahisa Kojima45a18f02023-06-07 14:41:52 +090062/**
63 * efi_firmware_get_image_type_id - get image_type_id
64 * @image_index: image index
65 *
66 * Return the image_type_id identified by the image index.
67 *
68 * Return: pointer to the image_type_id, NULL if image_index is invalid
69 */
70static
71efi_guid_t *efi_firmware_get_image_type_id(u8 image_index)
72{
73 int i;
74 struct efi_fw_image *fw_array;
75
76 fw_array = update_info.images;
77 for (i = 0; i < update_info.num_images; i++) {
78 if (fw_array[i].image_index == image_index)
79 return &fw_array[i].image_type_id;
80 }
81
82 return NULL;
83}
84
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +090085/* Place holder; not supported */
86static
87efi_status_t EFIAPI efi_firmware_get_image_unsupported(
88 struct efi_firmware_management_protocol *this,
89 u8 image_index,
90 void *image,
91 efi_uintn_t *image_size)
92{
93 EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
94
95 return EFI_EXIT(EFI_UNSUPPORTED);
96}
97
98/* Place holder; not supported */
99static
100efi_status_t EFIAPI efi_firmware_check_image_unsupported(
101 struct efi_firmware_management_protocol *this,
102 u8 image_index,
103 const void *image,
104 efi_uintn_t *image_size,
105 u32 *image_updatable)
106{
107 EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
108 image_updatable);
109
110 return EFI_EXIT(EFI_UNSUPPORTED);
111}
112
113/* Place holder; not supported */
114static
115efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
116 struct efi_firmware_management_protocol *this,
117 u32 *package_version,
118 u16 **package_version_name,
119 u32 *package_version_name_maxlen,
120 u64 *attributes_supported,
121 u64 *attributes_setting)
122{
123 EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
124 package_version_name, package_version_name_maxlen,
125 attributes_supported, attributes_setting);
126
127 return EFI_EXIT(EFI_UNSUPPORTED);
128}
129
130/* Place holder; not supported */
131static
132efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
133 struct efi_firmware_management_protocol *this,
134 const void *image,
135 efi_uintn_t *image_size,
136 const void *vendor_code,
137 u32 package_version,
138 const u16 *package_version_name)
139{
140 EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
141 package_version, package_version_name);
142
143 return EFI_EXIT(EFI_UNSUPPORTED);
144}
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900145
146/**
Masahisa Kojima941353c2023-06-07 14:41:54 +0900147 * efi_firmware_get_lsv_from_dtb - get lowest supported version from dtb
148 * @image_index: Image index
149 * @image_type_id: Image type id
150 * @lsv: Pointer to store the lowest supported version
151 *
152 * Read the firmware version information from dtb.
153 */
154static void efi_firmware_get_lsv_from_dtb(u8 image_index,
155 efi_guid_t *image_type_id, u32 *lsv)
156{
157 const void *fdt = gd->fdt_blob;
158 const fdt32_t *val;
159 const char *guid_str;
160 int len, offset, index;
Masahisa Kojima73a5a262023-07-31 17:53:02 +0900161 int parent, ret;
Masahisa Kojima941353c2023-06-07 14:41:54 +0900162
163 *lsv = 0;
164
165 parent = fdt_subnode_offset(fdt, 0, "firmware-version");
166 if (parent < 0)
167 return;
168
169 fdt_for_each_subnode(offset, fdt, parent) {
170 efi_guid_t guid;
171
172 guid_str = fdt_getprop(fdt, offset, "image-type-id", &len);
173 if (!guid_str)
174 continue;
Masahisa Kojima73a5a262023-07-31 17:53:02 +0900175 ret = uuid_str_to_bin(guid_str, guid.b, UUID_STR_FORMAT_GUID);
176 if (ret < 0) {
177 log_warning("Wrong image-type-id format.\n");
178 continue;
179 }
Masahisa Kojima941353c2023-06-07 14:41:54 +0900180
181 val = fdt_getprop(fdt, offset, "image-index", &len);
182 if (!val)
183 continue;
184 index = fdt32_to_cpu(*val);
185
186 if (!guidcmp(&guid, image_type_id) && index == image_index) {
187 val = fdt_getprop(fdt, offset,
188 "lowest-supported-version", &len);
189 if (val)
190 *lsv = fdt32_to_cpu(*val);
191 }
192 }
193}
194
195/**
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900196 * efi_firmware_fill_version_info - fill the version information
197 * @image_info: Image information
198 * @fw_array: Pointer to size of new image
199 *
200 * Fill the version information into image_info strucrure.
201 *
202 */
203static
204void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_info,
205 struct efi_fw_image *fw_array)
206{
207 u16 varname[13]; /* u"FmpStateXXXX" */
208 efi_status_t ret;
209 efi_uintn_t size;
210 struct fmp_state var_state = { 0 };
211
212 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
213 fw_array->image_index);
214 size = sizeof(var_state);
215 ret = efi_get_variable_int(varname, &fw_array->image_type_id,
216 NULL, &size, &var_state, NULL);
217 if (ret == EFI_SUCCESS)
218 image_info->version = var_state.fw_version;
219 else
220 image_info->version = 0;
221
Masahisa Kojima941353c2023-06-07 14:41:54 +0900222 efi_firmware_get_lsv_from_dtb(fw_array->image_index,
223 &fw_array->image_type_id,
224 &image_info->lowest_supported_image_version);
225
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900226 image_info->version_name = NULL; /* not supported */
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900227 image_info->last_attempt_version = 0;
228 image_info->last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
229}
230
231/**
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530232 * efi_fill_image_desc_array - populate image descriptor array
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900233 * @image_info_size: Size of @image_info
234 * @image_info: Image information
235 * @descriptor_version: Pointer to version number
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530236 * @descriptor_count: Image count
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900237 * @descriptor_size: Pointer to descriptor size
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530238 * @package_version: Package version
239 * @package_version_name: Package version's name
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900240 *
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530241 * Return information about the current firmware image in @image_info.
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900242 * @image_info will consist of a number of descriptors.
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530243 * Each descriptor will be created based on efi_fw_image array.
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900244 *
245 * Return status code
246 */
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530247static efi_status_t efi_fill_image_desc_array(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900248 efi_uintn_t *image_info_size,
249 struct efi_firmware_image_descriptor *image_info,
250 u32 *descriptor_version,
251 u8 *descriptor_count,
252 efi_uintn_t *descriptor_size,
253 u32 *package_version,
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530254 u16 **package_version_name)
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900255{
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530256 size_t total_size;
257 struct efi_fw_image *fw_array;
258 int i;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900259
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900260 total_size = sizeof(*image_info) * update_info.num_images;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900261
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900262 if (*image_info_size < total_size) {
263 *image_info_size = total_size;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900264
265 return EFI_BUFFER_TOO_SMALL;
266 }
267 *image_info_size = total_size;
268
Sughosh Ganuc212fc72022-05-31 12:45:33 +0530269 fw_array = update_info.images;
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900270 *descriptor_count = update_info.num_images;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900271 *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900272 *descriptor_size = sizeof(*image_info);
273 *package_version = 0xffffffff; /* not supported */
274 *package_version_name = NULL; /* not supported */
275
Masahisa Kojima5d2438b2023-06-07 14:41:51 +0900276 for (i = 0; i < update_info.num_images; i++) {
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530277 image_info[i].image_index = fw_array[i].image_index;
278 image_info[i].image_type_id = fw_array[i].image_type_id;
279 image_info[i].image_id = fw_array[i].image_index;
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530280 image_info[i].image_id_name = fw_array[i].fw_name;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900281
Masahisa Kojimaff96fa12023-06-07 14:41:53 +0900282 efi_firmware_fill_version_info(&image_info[i], &fw_array[i]);
283
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900284 image_info[i].size = 0;
285 image_info[i].attributes_supported =
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530286 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
287 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900288 image_info[i].attributes_setting =
289 IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530290
291 /* Check if the capsule authentication is enabled */
Sughosh Ganud1bd8492021-04-12 20:35:23 +0530292 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530293 image_info[0].attributes_setting |=
294 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
295
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900296 image_info[i].hardware_instance = 1;
297 image_info[i].dependencies = NULL;
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900298 }
299
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900300 return EFI_SUCCESS;
301}
302
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200303/**
304 * efi_firmware_capsule_authenticate - authenticate the capsule if enabled
305 * @p_image: Pointer to new image
306 * @p_image_size: Pointer to size of new image
307 *
308 * Authenticate the capsule if authentication is enabled.
309 * The image pointer and the image size are updated in case of success.
310 *
311 * Return: status code
312 */
313static
314efi_status_t efi_firmware_capsule_authenticate(const void **p_image,
315 efi_uintn_t *p_image_size)
316{
317 const void *image = *p_image;
318 efi_uintn_t image_size = *p_image_size;
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200319 void *capsule_payload;
320 efi_status_t status;
321 efi_uintn_t capsule_payload_size;
322
323 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) {
324 capsule_payload = NULL;
325 capsule_payload_size = 0;
326 status = efi_capsule_authenticate(image, image_size,
327 &capsule_payload,
328 &capsule_payload_size);
329
330 if (status == EFI_SECURITY_VIOLATION) {
331 printf("Capsule authentication check failed. Aborting update\n");
332 return status;
333 } else if (status != EFI_SUCCESS) {
334 return status;
335 }
336
337 debug("Capsule authentication successful\n");
338 image = capsule_payload;
339 image_size = capsule_payload_size;
340 } else {
341 debug("Capsule authentication disabled. ");
342 debug("Updating capsule without authenticating.\n");
343 }
344
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200345 *p_image = image;
346 *p_image_size = image_size;
347 return EFI_SUCCESS;
348}
349
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900350/**
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900351 * efi_firmware_set_fmp_state_var - set FmpStateXXXX variable
352 * @state: Pointer to fmp state
353 * @image_index: image index
354 *
355 * Update the FmpStateXXXX variable with the firmware update state.
356 *
357 * Return: status code
358 */
359static
360efi_status_t efi_firmware_set_fmp_state_var(struct fmp_state *state, u8 image_index)
361{
362 u16 varname[13]; /* u"FmpStateXXXX" */
363 efi_status_t ret;
364 efi_guid_t *image_type_id;
365 struct fmp_state var_state = { 0 };
366
367 image_type_id = efi_firmware_get_image_type_id(image_index);
368 if (!image_type_id)
369 return EFI_INVALID_PARAMETER;
370
371 efi_create_indexed_name(varname, sizeof(varname), "FmpState",
372 image_index);
373
374 /*
375 * Only the fw_version is set here.
376 * lowest_supported_version in FmpState variable is ignored since
377 * it can be tampered if the file based EFI variable storage is used.
378 */
379 var_state.fw_version = state->fw_version;
380
381 ret = efi_set_variable_int(varname, image_type_id,
382 EFI_VARIABLE_READ_ONLY |
383 EFI_VARIABLE_NON_VOLATILE |
384 EFI_VARIABLE_BOOTSERVICE_ACCESS |
385 EFI_VARIABLE_RUNTIME_ACCESS,
386 sizeof(var_state), &var_state, false);
387
388 return ret;
389}
390
391/**
392 * efi_firmware_get_fw_version - get fw_version from FMP payload header
393 * @p_image: Pointer to new image
394 * @p_image_size: Pointer to size of new image
395 * @state: Pointer to fmp state
396 *
397 * Parse the FMP payload header and fill the fmp_state structure.
398 * If no FMP payload header is found, fmp_state structure is not updated.
399 *
400 */
401static void efi_firmware_get_fw_version(const void **p_image,
402 efi_uintn_t *p_image_size,
403 struct fmp_state *state)
404{
405 const struct fmp_payload_header *header;
406 u32 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
407
408 header = *p_image;
409 if (header->signature == fmp_hdr_signature) {
410 /* FMP header is inserted above the capsule payload */
411 state->fw_version = header->fw_version;
412
413 *p_image += header->header_size;
414 *p_image_size -= header->header_size;
415 }
416}
417
418/**
419 * efi_firmware_verify_image - verify image
420 * @p_image: Pointer to new image
421 * @p_image_size: Pointer to size of new image
422 * @image_index: Image index
423 * @state: Pointer to fmp state
424 *
Masahisa Kojima94f47802023-06-07 14:41:55 +0900425 * Verify the capsule authentication and check if the fw_version
426 * is equal or greater than the lowest supported version.
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900427 *
428 * Return: status code
429 */
430static
431efi_status_t efi_firmware_verify_image(const void **p_image,
432 efi_uintn_t *p_image_size,
433 u8 image_index,
434 struct fmp_state *state)
435{
Masahisa Kojima94f47802023-06-07 14:41:55 +0900436 u32 lsv;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900437 efi_status_t ret;
Masahisa Kojima94f47802023-06-07 14:41:55 +0900438 efi_guid_t *image_type_id;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900439
440 ret = efi_firmware_capsule_authenticate(p_image, p_image_size);
Masahisa Kojima94f47802023-06-07 14:41:55 +0900441 if (ret != EFI_SUCCESS)
442 return ret;
443
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900444 efi_firmware_get_fw_version(p_image, p_image_size, state);
445
Masahisa Kojima94f47802023-06-07 14:41:55 +0900446 image_type_id = efi_firmware_get_image_type_id(image_index);
447 if (!image_type_id)
448 return EFI_INVALID_PARAMETER;
449
450 efi_firmware_get_lsv_from_dtb(image_index, image_type_id, &lsv);
451 if (state->fw_version < lsv) {
452 log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n",
453 state->fw_version, lsv);
454 return EFI_INVALID_PARAMETER;
455 }
456
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900457 return ret;
458}
459
460/**
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530461 * efi_firmware_get_image_info - return information about the current
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900462 * firmware image
463 * @this: Protocol instance
464 * @image_info_size: Size of @image_info
465 * @image_info: Image information
466 * @descriptor_version: Pointer to version number
467 * @descriptor_count: Pointer to number of descriptors
468 * @descriptor_size: Pointer to descriptor size
Vincent Stehlé0f3c9222022-05-25 11:20:22 +0200469 * @package_version: Package version
470 * @package_version_name: Package version's name
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900471 *
472 * Return information bout the current firmware image in @image_info.
473 * @image_info will consist of a number of descriptors.
474 * Each descriptor will be created based on "dfu_alt_info" variable.
475 *
476 * Return status code
477 */
478static
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530479efi_status_t EFIAPI efi_firmware_get_image_info(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900480 struct efi_firmware_management_protocol *this,
481 efi_uintn_t *image_info_size,
482 struct efi_firmware_image_descriptor *image_info,
483 u32 *descriptor_version,
484 u8 *descriptor_count,
485 efi_uintn_t *descriptor_size,
486 u32 *package_version,
487 u16 **package_version_name)
488{
489 efi_status_t ret;
490
491 EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
492 image_info_size, image_info,
493 descriptor_version, descriptor_count, descriptor_size,
494 package_version, package_version_name);
495
496 if (!image_info_size)
497 return EFI_EXIT(EFI_INVALID_PARAMETER);
498
499 if (*image_info_size &&
500 (!image_info || !descriptor_version || !descriptor_count ||
501 !descriptor_size || !package_version || !package_version_name))
502 return EFI_EXIT(EFI_INVALID_PARAMETER);
503
Sughosh Ganu2a9fd7d2022-04-15 11:29:35 +0530504 ret = efi_fill_image_desc_array(image_info_size, image_info,
505 descriptor_version, descriptor_count,
506 descriptor_size, package_version,
507 package_version_name);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900508
509 return EFI_EXIT(ret);
510}
511
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530512#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
513/*
514 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
515 * method with existing FIT image format, and handles
516 * - multiple regions of firmware via DFU
517 * but doesn't support
518 * - versioning of firmware image
519 * - package information
520 */
521
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900522/**
523 * efi_firmware_fit_set_image - update the firmware image
524 * @this: Protocol instance
525 * @image_index: Image index number
526 * @image: New image
527 * @image_size: Size of new image
528 * @vendor_code: Vendor-specific update policy
529 * @progress: Function to report the progress of update
530 * @abort_reason: Pointer to string of abort reason
531 *
532 * Update the firmware to new image, using dfu. The new image should
533 * have FIT image format commonly used in U-Boot.
534 * @vendor_code, @progress and @abort_reason are not supported.
535 *
536 * Return: status code
537 */
538static
539efi_status_t EFIAPI efi_firmware_fit_set_image(
540 struct efi_firmware_management_protocol *this,
541 u8 image_index,
542 const void *image,
543 efi_uintn_t image_size,
544 const void *vendor_code,
545 efi_status_t (*progress)(efi_uintn_t completion),
546 u16 **abort_reason)
547{
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200548 efi_status_t status;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900549 struct fmp_state state = { 0 };
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200550
Heinrich Schuchardt94f09e02022-02-03 20:13:17 +0100551 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900552 image_size, vendor_code, progress, abort_reason);
553
554 if (!image || image_index != 1)
555 return EFI_EXIT(EFI_INVALID_PARAMETER);
556
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900557 status = efi_firmware_verify_image(&image, &image_size, image_index,
558 &state);
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200559 if (status != EFI_SUCCESS)
560 return EFI_EXIT(status);
561
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900562 if (fit_update(image))
563 return EFI_EXIT(EFI_DEVICE_ERROR);
564
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900565 efi_firmware_set_fmp_state_var(&state, image_index);
566
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900567 return EFI_EXIT(EFI_SUCCESS);
568}
569
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900570const struct efi_firmware_management_protocol efi_fmp_fit = {
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530571 .get_image_info = efi_firmware_get_image_info,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900572 .get_image = efi_firmware_get_image_unsupported,
573 .set_image = efi_firmware_fit_set_image,
574 .check_image = efi_firmware_check_image_unsupported,
575 .get_package_info = efi_firmware_get_package_info_unsupported,
576 .set_package_info = efi_firmware_set_package_info_unsupported,
577};
578#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900579
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900580#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
581/*
582 * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
583 * method with raw data.
584 */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900585
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900586/**
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900587 * efi_firmware_raw_set_image - update the firmware image
588 * @this: Protocol instance
589 * @image_index: Image index number
590 * @image: New image
591 * @image_size: Size of new image
592 * @vendor_code: Vendor-specific update policy
593 * @progress: Function to report the progress of update
594 * @abort_reason: Pointer to string of abort reason
595 *
596 * Update the firmware to new image, using dfu. The new image should
597 * be a single raw image.
598 * @vendor_code, @progress and @abort_reason are not supported.
599 *
600 * Return: status code
601 */
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900602static
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900603efi_status_t EFIAPI efi_firmware_raw_set_image(
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900604 struct efi_firmware_management_protocol *this,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900605 u8 image_index,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900606 const void *image,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900607 efi_uintn_t image_size,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900608 const void *vendor_code,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900609 efi_status_t (*progress)(efi_uintn_t completion),
610 u16 **abort_reason)
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900611{
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530612 int ret;
Sughosh Ganuc9a821b2020-12-30 19:27:10 +0530613 efi_status_t status;
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900614 struct fmp_state state = { 0 };
Sughosh Ganu7221c6e2020-12-30 19:27:05 +0530615
Heinrich Schuchardt94f09e02022-02-03 20:13:17 +0100616 EFI_ENTRY("%p %d %p %zu %p %p %p\n", this, image_index, image,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900617 image_size, vendor_code, progress, abort_reason);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900618
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900619 if (!image)
620 return EFI_EXIT(EFI_INVALID_PARAMETER);
621
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900622 status = efi_firmware_verify_image(&image, &image_size, image_index,
623 &state);
Vincent Stehlé6a4625e2022-05-31 09:55:34 +0200624 if (status != EFI_SUCCESS)
625 return EFI_EXIT(status);
Sughosh Ganu7221c6e2020-12-30 19:27:05 +0530626
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530627 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
628 /*
629 * Based on the value of update bank, derive the
630 * image index value.
631 */
632 ret = fwu_get_image_index(&image_index);
633 if (ret) {
634 log_debug("Unable to get FWU image_index\n");
635 return EFI_EXIT(EFI_DEVICE_ERROR);
636 }
637 }
638
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900639 if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
640 NULL, NULL))
641 return EFI_EXIT(EFI_DEVICE_ERROR);
642
Masahisa Kojima45a18f02023-06-07 14:41:52 +0900643 efi_firmware_set_fmp_state_var(&state, image_index);
644
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900645 return EFI_EXIT(EFI_SUCCESS);
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900646}
647
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900648const struct efi_firmware_management_protocol efi_fmp_raw = {
Sughosh Ganu4ed72612022-06-01 23:30:41 +0530649 .get_image_info = efi_firmware_get_image_info,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900650 .get_image = efi_firmware_get_image_unsupported,
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900651 .set_image = efi_firmware_raw_set_image,
AKASHI Takahirof4818e62020-11-30 18:12:12 +0900652 .check_image = efi_firmware_check_image_unsupported,
653 .get_package_info = efi_firmware_get_package_info_unsupported,
654 .set_package_info = efi_firmware_set_package_info_unsupported,
655};
AKASHI Takahiro7ff3f3c2020-11-17 09:28:00 +0900656#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */