blob: f19e78ae9d1e250f7bf8362f043877c6d10a9675 [file] [log] [blame]
AKASHI Takahiro473d9b32020-11-17 09:27:55 +09001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * EFI Capsule
4 *
5 * Copyright (c) 2018 Linaro Limited
6 * Author: AKASHI Takahiro
7 */
8
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02009#define LOG_CATEGORY LOGC_EFI
10
Simon Glass37972f42025-05-24 11:28:21 -060011#include <efi_device_path.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090012#include <efi_loader.h>
13#include <efi_variable.h>
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +090014#include <env.h>
15#include <fdtdec.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090016#include <fs.h>
Sughosh Ganu1cadae22022-10-21 18:16:03 +053017#include <fwu.h>
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +090018#include <hang.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090019#include <malloc.h>
AKASHI Takahiro45b819542020-11-17 09:27:56 +090020#include <mapmem.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090021#include <sort.h>
Masami Hiramatsuff744862022-03-21 22:37:56 +090022#include <sysreset.h>
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +090023#include <asm/global_data.h>
Caleb Connolly29cab7c2024-08-30 13:34:37 +010024#include <u-boot/uuid.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090025
Ilias Apalodimasb6196d72025-04-01 14:27:25 +030026#include <asm/sections.h>
Sughosh Ganu586bb982020-12-30 19:27:09 +053027#include <crypto/pkcs7.h>
28#include <crypto/pkcs7_parser.h>
29#include <linux/err.h>
30
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +090031DECLARE_GLOBAL_DATA_PTR;
32
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090033const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
AKASHI Takahiro0d963782020-11-30 18:12:11 +090034static const efi_guid_t efi_guid_firmware_management_capsule_id =
35 EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
36const efi_guid_t efi_guid_firmware_management_protocol =
37 EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
Sughosh Ganu1cadae22022-10-21 18:16:03 +053038const efi_guid_t fwu_guid_os_request_fw_revert =
39 FWU_OS_REQUEST_FW_REVERT_GUID;
40const efi_guid_t fwu_guid_os_request_fw_accept =
41 FWU_OS_REQUEST_FW_ACCEPT_GUID;
42
43#define FW_ACCEPT_OS (u32)0x8000
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090044
AKASHI Takahiro45b819542020-11-17 09:27:56 +090045#ifdef CONFIG_EFI_CAPSULE_ON_DISK
46/* for file system access */
47static struct efi_file_handle *bootdev_root;
48#endif
49
Etienne Carriere6326e912023-02-16 18:21:41 +010050static __maybe_unused unsigned int get_capsule_index(const u16 *variable_name)
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090051{
52 u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010053 char value[5];
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090054 efi_uintn_t size;
55 unsigned long index = 0xffff;
56 efi_status_t ret;
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010057 int i;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090058
59 size = sizeof(value16);
Etienne Carriere6326e912023-02-16 18:21:41 +010060 ret = efi_get_variable_int(variable_name, &efi_guid_capsule_report,
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090061 NULL, &size, value16, NULL);
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010062 if (ret != EFI_SUCCESS || size != 22 ||
Simon Glass90975372022-01-23 12:55:12 -070063 u16_strncmp(value16, u"Capsule", 7))
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090064 goto err;
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010065 for (i = 0; i < 4; ++i) {
66 u16 c = value16[i + 7];
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090067
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010068 if (!c || c > 0x7f)
69 goto err;
70 value[i] = c;
71 }
72 value[4] = 0;
73 if (strict_strtoul(value, 16, &index))
74 index = 0xffff;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090075err:
76 return index;
77}
78
79/**
Etienne Carriere6326e912023-02-16 18:21:41 +010080 * get_last_capsule - get the last capsule index
81 *
82 * Retrieve the index of the capsule invoked last time from "CapsuleLast"
83 * variable.
84 *
85 * Return:
86 * * > 0 - the last capsule index invoked
87 * * 0xffff - on error, or no capsule invoked yet
88 */
89static __maybe_unused unsigned int get_last_capsule(void)
90{
91 return get_capsule_index(u"CapsuleLast");
92}
93
94/**
95 * get_max_capsule - get the max capsule index
96 *
97 * Retrieve the max capsule index value from "CapsuleMax" variable.
98 *
99 * Return:
100 * * > 0 - the max capsule index
101 * * 0xffff - on error, or "CapsuleMax" variable does not exist
102 */
103static __maybe_unused unsigned int get_max_capsule(void)
104{
105 return get_capsule_index(u"CapsuleMax");
106}
107
108/**
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900109 * set_capsule_result - set a result variable
110 * @capsule: Capsule
111 * @return_status: Return status
112 *
113 * Create and set a result variable, "CapsuleXXXX", for the capsule,
114 * @capsule.
115 */
116static __maybe_unused
117void set_capsule_result(int index, struct efi_capsule_header *capsule,
118 efi_status_t return_status)
119{
120 u16 variable_name16[12];
121 struct efi_capsule_result_variable_header result;
122 struct efi_time time;
123 efi_status_t ret;
124
Ilias Apalodimas21575292020-12-31 12:26:46 +0200125 efi_create_indexed_name(variable_name16, sizeof(variable_name16),
126 "Capsule", index);
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900127 result.variable_total_size = sizeof(result);
128 result.capsule_guid = capsule->capsule_guid;
129 ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
130 if (ret == EFI_SUCCESS)
131 memcpy(&result.capsule_processed, &time, sizeof(time));
132 else
133 memset(&result.capsule_processed, 0, sizeof(time));
134 result.capsule_status = return_status;
Heinrich Schuchardt24adaa72021-07-10 11:10:26 +0200135 ret = efi_set_variable_int(variable_name16, &efi_guid_capsule_report,
136 EFI_VARIABLE_NON_VOLATILE |
137 EFI_VARIABLE_BOOTSERVICE_ACCESS |
138 EFI_VARIABLE_RUNTIME_ACCESS,
139 sizeof(result), &result, false);
Heinrich Schuchardtb1fae8c2021-07-10 11:14:13 +0200140 if (ret != EFI_SUCCESS) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200141 log_err("Setting %ls failed\n", variable_name16);
Heinrich Schuchardtb1fae8c2021-07-10 11:14:13 +0200142 return;
143 }
144
145 /* Variable CapsuleLast must not include terminating 0x0000 */
Simon Glass90975372022-01-23 12:55:12 -0700146 ret = efi_set_variable_int(u"CapsuleLast", &efi_guid_capsule_report,
Heinrich Schuchardtb1fae8c2021-07-10 11:14:13 +0200147 EFI_VARIABLE_READ_ONLY |
148 EFI_VARIABLE_NON_VOLATILE |
149 EFI_VARIABLE_BOOTSERVICE_ACCESS |
150 EFI_VARIABLE_RUNTIME_ACCESS,
151 22, variable_name16, false);
152 if (ret != EFI_SUCCESS)
Simon Glass90975372022-01-23 12:55:12 -0700153 log_err("Setting %ls failed\n", u"CapsuleLast");
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900154}
155
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900156#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT
157/**
158 * efi_fmp_find - search for Firmware Management Protocol drivers
159 * @image_type: Image type guid
Sughosh Ganuf55c6b62022-04-15 11:29:36 +0530160 * @image_index: Image Index
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900161 * @instance: Instance number
162 * @handles: Handles of FMP drivers
163 * @no_handles: Number of handles
164 *
165 * Search for Firmware Management Protocol drivers, matching the image
166 * type, @image_type and the machine instance, @instance, from the list,
167 * @handles.
168 *
169 * Return:
170 * * Protocol instance - on success
171 * * NULL - on failure
172 */
173static struct efi_firmware_management_protocol *
Sughosh Ganuf55c6b62022-04-15 11:29:36 +0530174efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance,
175 efi_handle_t *handles, efi_uintn_t no_handles)
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900176{
177 efi_handle_t *handle;
178 struct efi_firmware_management_protocol *fmp;
179 struct efi_firmware_image_descriptor *image_info, *desc;
180 efi_uintn_t info_size, descriptor_size;
181 u32 descriptor_version;
182 u8 descriptor_count;
183 u32 package_version;
184 u16 *package_version_name;
185 bool found = false;
186 int i, j;
187 efi_status_t ret;
188
189 for (i = 0, handle = handles; i < no_handles; i++, handle++) {
Heinrich Schuchardtd8dc3cb2022-10-07 15:29:52 +0200190 struct efi_handler *fmp_handler;
191
192 ret = efi_search_protocol(
193 *handle, &efi_guid_firmware_management_protocol,
194 &fmp_handler);
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900195 if (ret != EFI_SUCCESS)
196 continue;
Heinrich Schuchardtd8dc3cb2022-10-07 15:29:52 +0200197 fmp = fmp_handler->protocol_interface;
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900198
199 /* get device's image info */
200 info_size = 0;
201 image_info = NULL;
202 descriptor_version = 0;
203 descriptor_count = 0;
204 descriptor_size = 0;
205 package_version = 0;
206 package_version_name = NULL;
207 ret = EFI_CALL(fmp->get_image_info(fmp, &info_size,
208 image_info,
209 &descriptor_version,
210 &descriptor_count,
211 &descriptor_size,
212 &package_version,
213 &package_version_name));
214 if (ret != EFI_BUFFER_TOO_SMALL)
215 goto skip;
216
217 image_info = malloc(info_size);
218 if (!image_info)
219 goto skip;
220
221 ret = EFI_CALL(fmp->get_image_info(fmp, &info_size,
222 image_info,
223 &descriptor_version,
224 &descriptor_count,
225 &descriptor_size,
226 &package_version,
227 &package_version_name));
228 if (ret != EFI_SUCCESS ||
229 descriptor_version != EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION)
230 goto skip;
231
232 /* matching */
233 for (j = 0, desc = image_info; j < descriptor_count;
234 j++, desc = (void *)desc + descriptor_size) {
235 log_debug("+++ desc[%d] index: %d, name: %ls\n",
236 j, desc->image_index, desc->image_id_name);
237 if (!guidcmp(&desc->image_type_id, image_type) &&
Sughosh Ganuf55c6b62022-04-15 11:29:36 +0530238 (desc->image_index == image_index) &&
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900239 (!instance ||
240 !desc->hardware_instance ||
241 desc->hardware_instance == instance))
242 found = true;
243 }
244
245skip:
246 efi_free_pool(package_version_name);
247 free(image_info);
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900248 if (found)
249 return fmp;
250 }
251
252 return NULL;
253}
254
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900255/**
256 * efi_remove_auth_hdr - remove authentication data from image
257 * @image: Pointer to pointer to Image
258 * @image_size: Pointer to Image size
259 *
260 * Remove the authentication data from image if possible.
261 * Update @image and @image_size.
262 *
263 * Return: status code
264 */
265static efi_status_t efi_remove_auth_hdr(void **image, efi_uintn_t *image_size)
266{
267 struct efi_firmware_image_authentication *auth_hdr;
268 efi_status_t ret = EFI_INVALID_PARAMETER;
269
270 auth_hdr = (struct efi_firmware_image_authentication *)*image;
271 if (*image_size < sizeof(*auth_hdr))
272 goto out;
273
274 if (auth_hdr->auth_info.hdr.dwLength <=
275 offsetof(struct win_certificate_uefi_guid, cert_data))
276 goto out;
277
278 *image = (uint8_t *)*image + sizeof(auth_hdr->monotonic_count) +
279 auth_hdr->auth_info.hdr.dwLength;
280 *image_size = *image_size - auth_hdr->auth_info.hdr.dwLength -
281 sizeof(auth_hdr->monotonic_count);
282
283 ret = EFI_SUCCESS;
284out:
285 return ret;
286}
287
Sughosh Ganu586bb982020-12-30 19:27:09 +0530288#if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
Ilias Apalodimasb6196d72025-04-01 14:27:25 +0300289static int efi_get_public_key_data(const void **pkey, efi_uintn_t *pkey_len)
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +0900290{
Ilias Apalodimasb6196d72025-04-01 14:27:25 +0300291 const void *blob = __efi_capsule_sig_begin;
292 const int len = __efi_capsule_sig_end - __efi_capsule_sig_begin;
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +0900293
Ilias Apalodimasb6196d72025-04-01 14:27:25 +0300294 *pkey = blob;
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +0900295 *pkey_len = len;
296
297 return 0;
298}
Sughosh Ganu586bb982020-12-30 19:27:09 +0530299
Sughosh Ganu586bb982020-12-30 19:27:09 +0530300efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_size,
301 void **image, efi_uintn_t *image_size)
302{
303 u8 *buf;
304 int ret;
Ilias Apalodimasb6196d72025-04-01 14:27:25 +0300305 void *pkey;
306 const void *stored_pkey;
Sughosh Ganu586bb982020-12-30 19:27:09 +0530307 efi_uintn_t pkey_len;
308 uint64_t monotonic_count;
309 struct efi_signature_store *truststore;
310 struct pkcs7_message *capsule_sig;
311 struct efi_image_regions *regs;
312 struct efi_firmware_image_authentication *auth_hdr;
313 efi_status_t status;
314
315 status = EFI_SECURITY_VIOLATION;
316 capsule_sig = NULL;
317 truststore = NULL;
318 regs = NULL;
319
320 /* Sanity checks */
321 if (capsule == NULL || capsule_size == 0)
322 goto out;
323
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900324 *image = (uint8_t *)capsule;
325 *image_size = capsule_size;
326 if (efi_remove_auth_hdr(image, image_size) != EFI_SUCCESS)
Sughosh Ganu586bb982020-12-30 19:27:09 +0530327 goto out;
328
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900329 auth_hdr = (struct efi_firmware_image_authentication *)capsule;
Sughosh Ganu586bb982020-12-30 19:27:09 +0530330 if (guidcmp(&auth_hdr->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
331 goto out;
332
Sughosh Ganu586bb982020-12-30 19:27:09 +0530333 memcpy(&monotonic_count, &auth_hdr->monotonic_count,
334 sizeof(monotonic_count));
335
336 /* data to be digested */
337 regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 2, 1);
338 if (!regs)
339 goto out;
340
341 regs->max = 2;
342 efi_image_region_add(regs, (uint8_t *)*image,
343 (uint8_t *)*image + *image_size, 1);
344
345 efi_image_region_add(regs, (uint8_t *)&monotonic_count,
346 (uint8_t *)&monotonic_count + sizeof(monotonic_count),
347 1);
348
349 capsule_sig = efi_parse_pkcs7_header(auth_hdr->auth_info.cert_data,
350 auth_hdr->auth_info.hdr.dwLength
351 - sizeof(auth_hdr->auth_info),
352 &buf);
Dan Carpenter15325232023-07-27 10:16:20 +0300353 if (!capsule_sig) {
Sughosh Ganu586bb982020-12-30 19:27:09 +0530354 debug("Parsing variable's pkcs7 header failed\n");
Sughosh Ganu586bb982020-12-30 19:27:09 +0530355 goto out;
356 }
357
Ilias Apalodimasb6196d72025-04-01 14:27:25 +0300358 ret = efi_get_public_key_data(&stored_pkey, &pkey_len);
Sughosh Ganu586bb982020-12-30 19:27:09 +0530359 if (ret < 0)
360 goto out;
361
362 pkey = malloc(pkey_len);
363 if (!pkey)
364 goto out;
365
Ilias Apalodimasb6196d72025-04-01 14:27:25 +0300366 memcpy(pkey, stored_pkey, pkey_len);
Sughosh Ganu586bb982020-12-30 19:27:09 +0530367 truststore = efi_build_signature_store(pkey, pkey_len);
368 if (!truststore)
369 goto out;
370
371 /* verify signature */
372 if (efi_signature_verify(regs, capsule_sig, truststore, NULL)) {
373 debug("Verified\n");
374 } else {
375 debug("Verifying variable's signature failed\n");
376 goto out;
377 }
378
379 status = EFI_SUCCESS;
380
381out:
382 efi_sigstore_free(truststore);
383 pkcs7_free_message(capsule_sig);
384 free(regs);
385
386 return status;
387}
Sughosh Ganu586bb982020-12-30 19:27:09 +0530388#endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */
389
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530390static __maybe_unused bool fwu_empty_capsule(struct efi_capsule_header *capsule)
391{
392 return !guidcmp(&capsule->capsule_guid,
393 &fwu_guid_os_request_fw_revert) ||
394 !guidcmp(&capsule->capsule_guid,
395 &fwu_guid_os_request_fw_accept);
396}
397
398static __maybe_unused efi_status_t fwu_to_efi_error(int err)
399{
400 efi_status_t ret;
401
402 switch(err) {
403 case 0:
404 ret = EFI_SUCCESS;
405 break;
406 case -ERANGE:
407 case -EIO:
408 ret = EFI_DEVICE_ERROR;
409 break;
410 case -EINVAL:
411 ret = EFI_INVALID_PARAMETER;
412 break;
413 case -ENODEV:
414 ret = EFI_NOT_FOUND;
415 break;
416 default:
417 ret = EFI_OUT_OF_RESOURCES;
418 }
419
420 return ret;
421}
422
423static __maybe_unused efi_status_t fwu_empty_capsule_process(
424 struct efi_capsule_header *capsule)
425{
426 int status;
427 u32 active_idx;
428 efi_guid_t *image_guid;
429 efi_status_t ret = EFI_INVALID_PARAMETER;
430
431 if (!guidcmp(&capsule->capsule_guid,
432 &fwu_guid_os_request_fw_revert)) {
433 /*
434 * One of the previously updated image has
435 * failed the OS acceptance test. OS has
436 * requested to revert back to the earlier
437 * boot index
438 */
439 status = fwu_revert_boot_index();
440 ret = fwu_to_efi_error(status);
441 if (ret == EFI_SUCCESS)
442 log_debug("Reverted the FWU active_index. Recommend rebooting the system\n");
443 else
444 log_err("Failed to revert the FWU boot index\n");
445 } else if (!guidcmp(&capsule->capsule_guid,
446 &fwu_guid_os_request_fw_accept)) {
447 /*
448 * Image accepted by the OS. Set the acceptance
449 * status for the image.
450 */
451 image_guid = (void *)(char *)capsule +
452 capsule->header_size;
453
454 status = fwu_get_active_index(&active_idx);
455 ret = fwu_to_efi_error(status);
456 if (ret != EFI_SUCCESS) {
457 log_err("Unable to get the active_index from the FWU metadata\n");
458 return ret;
459 }
460
461 status = fwu_accept_image(image_guid, active_idx);
462 ret = fwu_to_efi_error(status);
463 if (ret != EFI_SUCCESS)
464 log_err("Unable to set the Accept bit for the image %pUs\n",
465 image_guid);
Sughosh Ganu2aa3fe52024-03-22 16:27:22 +0530466
467 status = fwu_state_machine_updates(0, active_idx);
468 if (status < 0)
469 ret = EFI_DEVICE_ERROR;
470
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530471 }
472
473 return ret;
474}
475
476static __maybe_unused void fwu_post_update_checks(
477 struct efi_capsule_header *capsule,
478 bool *fw_accept_os, bool *capsule_update)
479{
480 if (fwu_empty_capsule(capsule))
481 *capsule_update = false;
482 else
483 if (!*fw_accept_os)
484 *fw_accept_os =
485 capsule->flags & FW_ACCEPT_OS ? true : false;
486}
487
488static __maybe_unused efi_status_t fwu_post_update_process(bool fw_accept_os)
489{
490 int status;
491 uint update_index;
492 efi_status_t ret;
493
494 status = fwu_plat_get_update_index(&update_index);
495 if (status < 0) {
496 log_err("Failed to get the FWU update_index value\n");
497 return EFI_DEVICE_ERROR;
498 }
499
500 /*
501 * All the capsules have been updated successfully,
502 * update the FWU metadata.
503 */
504 log_debug("Update Complete. Now updating active_index to %u\n",
505 update_index);
506 status = fwu_set_active_index(update_index);
507 ret = fwu_to_efi_error(status);
508 if (ret != EFI_SUCCESS) {
509 log_err("Failed to update FWU metadata index values\n");
510 } else {
511 log_debug("Successfully updated the active_index\n");
Sughosh Ganu2aa3fe52024-03-22 16:27:22 +0530512 status = fwu_state_machine_updates(fw_accept_os ? 1 : 0,
513 update_index);
514 if (status < 0)
515 ret = EFI_DEVICE_ERROR;
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530516 }
517
518 return ret;
519}
Sughosh Ganu586bb982020-12-30 19:27:09 +0530520
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900521/**
522 * efi_capsule_update_firmware - update firmware from capsule
523 * @capsule_data: Capsule
524 *
525 * Update firmware, using a capsule, @capsule_data. Loading any FMP
526 * drivers embedded in a capsule is not supported.
527 *
528 * Return: status code
529 */
530static efi_status_t efi_capsule_update_firmware(
531 struct efi_capsule_header *capsule_data)
532{
533 struct efi_firmware_management_capsule_header *capsule;
534 struct efi_firmware_management_capsule_image_header *image;
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900535 size_t capsule_size, image_binary_size;
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900536 void *image_binary, *vendor_code;
537 efi_handle_t *handles;
538 efi_uintn_t no_handles;
539 int item;
540 struct efi_firmware_management_protocol *fmp;
541 u16 *abort_reason;
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530542 efi_guid_t *image_type_id;
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900543 efi_status_t ret = EFI_SUCCESS;
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530544 int status;
545 uint update_index;
546 bool fw_accept_os;
547
548 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
Sughosh Ganu20585cd2024-09-09 16:50:21 +0530549 if (fwu_empty_capsule(capsule_data)) {
550 if (fwu_empty_capsule_checks_pass()) {
551 return fwu_empty_capsule_process(capsule_data);
552 } else {
553 log_err("FWU empty capsule checks failed. Cannot start update\n");
554 return EFI_INVALID_PARAMETER;
555 }
556 }
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530557
558 if (!fwu_update_checks_pass()) {
559 log_err("FWU checks failed. Cannot start update\n");
560 return EFI_INVALID_PARAMETER;
561 }
562
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530563 /* Obtain the update_index from the platform */
564 status = fwu_plat_get_update_index(&update_index);
565 if (status < 0) {
566 log_err("Failed to get the FWU update_index value\n");
567 return EFI_DEVICE_ERROR;
568 }
569
570 fw_accept_os = capsule_data->flags & FW_ACCEPT_OS ? 0x1 : 0x0;
571 }
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900572
AKASHI Takahiroa8000b92023-07-27 09:38:00 +0900573 if (guidcmp(&capsule_data->capsule_guid,
574 &efi_guid_firmware_management_capsule_id)) {
575 log_err("Unsupported capsule type: %pUs\n",
576 &capsule_data->capsule_guid);
577 return EFI_UNSUPPORTED;
578 }
579
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900580 /* sanity check */
581 if (capsule_data->header_size < sizeof(*capsule) ||
582 capsule_data->header_size >= capsule_data->capsule_image_size)
583 return EFI_INVALID_PARAMETER;
584
585 capsule = (void *)capsule_data + capsule_data->header_size;
586 capsule_size = capsule_data->capsule_image_size
587 - capsule_data->header_size;
588
589 if (capsule->version != 0x00000001)
590 return EFI_UNSUPPORTED;
591
592 handles = NULL;
593 ret = EFI_CALL(efi_locate_handle_buffer(
594 BY_PROTOCOL,
595 &efi_guid_firmware_management_protocol,
596 NULL, &no_handles, (efi_handle_t **)&handles));
597 if (ret != EFI_SUCCESS)
598 return EFI_UNSUPPORTED;
599
600 /* Payload */
601 for (item = capsule->embedded_driver_count;
602 item < capsule->embedded_driver_count
603 + capsule->payload_item_count; item++) {
604 /* sanity check */
605 if ((capsule->item_offset_list[item] + sizeof(*image)
606 >= capsule_size)) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200607 log_err("Capsule does not have enough data\n");
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900608 ret = EFI_INVALID_PARAMETER;
609 goto out;
610 }
611
612 image = (void *)capsule + capsule->item_offset_list[item];
613
614 if (image->version != 0x00000003) {
615 ret = EFI_UNSUPPORTED;
616 goto out;
617 }
618
619 /* find a device for update firmware */
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900620 fmp = efi_fmp_find(&image->update_image_type_id,
Sughosh Ganuf55c6b62022-04-15 11:29:36 +0530621 image->update_image_index,
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900622 image->update_hardware_instance,
623 handles, no_handles);
624 if (!fmp) {
Heinrich Schuchardt282249d2022-01-16 14:15:31 +0100625 log_err("FMP driver not found for firmware type %pUs, hardware instance %lld\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900626 &image->update_image_type_id,
627 image->update_hardware_instance);
628 ret = EFI_UNSUPPORTED;
629 goto out;
630 }
631
632 /* do update */
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900633 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&
634 !(image->image_capsule_support &
635 CAPSULE_SUPPORT_AUTHENTICATION)) {
636 /* no signature */
637 ret = EFI_SECURITY_VIOLATION;
638 goto out;
639 }
640
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900641 image_binary = (void *)image + sizeof(*image);
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900642 image_binary_size = image->update_image_size;
643 vendor_code = image_binary + image_binary_size;
644 if (!IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&
645 (image->image_capsule_support &
646 CAPSULE_SUPPORT_AUTHENTICATION)) {
647 ret = efi_remove_auth_hdr(&image_binary,
648 &image_binary_size);
649 if (ret != EFI_SUCCESS)
650 goto out;
651 }
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900652
653 abort_reason = NULL;
654 ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index,
655 image_binary,
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900656 image_binary_size,
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900657 vendor_code, NULL,
658 &abort_reason));
659 if (ret != EFI_SUCCESS) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200660 log_err("Firmware update failed: %ls\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900661 abort_reason);
662 efi_free_pool(abort_reason);
663 goto out;
664 }
Sughosh Ganu1cadae22022-10-21 18:16:03 +0530665
666 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
667 image_type_id = &image->update_image_type_id;
668 if (!fw_accept_os) {
669 /*
670 * The OS will not be accepting the firmware
671 * images. Set the accept bit of all the
672 * images contained in this capsule.
673 */
674 status = fwu_accept_image(image_type_id,
675 update_index);
676 } else {
677 status = fwu_clear_accept_image(image_type_id,
678 update_index);
679 }
680 ret = fwu_to_efi_error(status);
681 if (ret != EFI_SUCCESS) {
682 log_err("Unable to %s the accept bit for the image %pUs\n",
683 fw_accept_os ? "clear" : "set",
684 image_type_id);
685 goto out;
686 }
687
688 log_debug("%s the accepted bit for Image %pUs\n",
689 fw_accept_os ? "Cleared" : "Set",
690 image_type_id);
691 }
692
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900693 }
694
695out:
696 efi_free_pool(handles);
697
698 return ret;
699}
700#else
701static efi_status_t efi_capsule_update_firmware(
702 struct efi_capsule_header *capsule_data)
703{
704 return EFI_UNSUPPORTED;
705}
706#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
707
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900708/**
709 * efi_update_capsule() - process information from operating system
710 * @capsule_header_array: Array of virtual address pointers
711 * @capsule_count: Number of pointers in capsule_header_array
712 * @scatter_gather_list: Array of physical address pointers
713 *
714 * This function implements the UpdateCapsule() runtime service.
715 *
716 * See the Unified Extensible Firmware Interface (UEFI) specification for
717 * details.
718 *
719 * Return: status code
720 */
721efi_status_t EFIAPI efi_update_capsule(
722 struct efi_capsule_header **capsule_header_array,
723 efi_uintn_t capsule_count,
724 u64 scatter_gather_list)
725{
726 struct efi_capsule_header *capsule;
727 unsigned int i;
728 efi_status_t ret;
729
Simon Glass83698b22021-02-07 14:27:02 -0700730 EFI_ENTRY("%p, %zu, %llu\n", capsule_header_array, capsule_count,
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900731 scatter_gather_list);
732
733 if (!capsule_count) {
734 ret = EFI_INVALID_PARAMETER;
735 goto out;
736 }
737
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900738 ret = EFI_SUCCESS;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900739 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
740 i++, capsule = *(++capsule_header_array)) {
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900741 /* sanity check */
742 if (capsule->header_size < sizeof(*capsule) ||
743 capsule->capsule_image_size < sizeof(*capsule)) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200744 log_err("Capsule does not have enough data\n");
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900745 continue;
746 }
747
Heinrich Schuchardt282249d2022-01-16 14:15:31 +0100748 log_debug("Capsule[%d] (guid:%pUs)\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900749 i, &capsule->capsule_guid);
AKASHI Takahiroa8000b92023-07-27 09:38:00 +0900750 ret = efi_capsule_update_firmware(capsule);
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900751 if (ret != EFI_SUCCESS)
752 goto out;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900753 }
Jose Marinhoebb61ee2021-03-02 17:26:38 +0000754
755 if (IS_ENABLED(CONFIG_EFI_ESRT)) {
756 /* Rebuild the ESRT to reflect any updated FW images. */
757 ret = efi_esrt_populate();
758 if (ret != EFI_SUCCESS)
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200759 log_warning("ESRT update failed\n");
Jose Marinhoebb61ee2021-03-02 17:26:38 +0000760 }
Jose Marinhoaf886ce2021-04-19 14:54:33 +0100761out:
Jose Marinhoebb61ee2021-03-02 17:26:38 +0000762
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900763 return EFI_EXIT(ret);
764}
765
766/**
767 * efi_query_capsule_caps() - check if capsule is supported
768 * @capsule_header_array: Array of virtual pointers
769 * @capsule_count: Number of pointers in capsule_header_array
770 * @maximum_capsule_size: Maximum capsule size
771 * @reset_type: Type of reset needed for capsule update
772 *
773 * This function implements the QueryCapsuleCapabilities() runtime service.
774 *
775 * See the Unified Extensible Firmware Interface (UEFI) specification for
776 * details.
777 *
778 * Return: status code
779 */
780efi_status_t EFIAPI efi_query_capsule_caps(
781 struct efi_capsule_header **capsule_header_array,
782 efi_uintn_t capsule_count,
783 u64 *maximum_capsule_size,
784 u32 *reset_type)
785{
786 struct efi_capsule_header *capsule __attribute__((unused));
787 unsigned int i;
788 efi_status_t ret;
789
Simon Glass83698b22021-02-07 14:27:02 -0700790 EFI_ENTRY("%p, %zu, %p, %p\n", capsule_header_array, capsule_count,
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900791 maximum_capsule_size, reset_type);
792
793 if (!maximum_capsule_size) {
794 ret = EFI_INVALID_PARAMETER;
795 goto out;
796 }
797
798 *maximum_capsule_size = U64_MAX;
799 *reset_type = EFI_RESET_COLD;
800
801 ret = EFI_SUCCESS;
802 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
803 i++, capsule = *(++capsule_header_array)) {
804 /* TODO */
805 }
806out:
807 return EFI_EXIT(ret);
808}
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900809
Masami Hiramatsud306caa2022-03-21 22:37:45 +0900810/**
811 * efi_load_capsule_drivers - initialize capsule drivers
812 *
813 * Generic FMP drivers backed by DFU
814 *
815 * Return: status code
816 */
817efi_status_t __weak efi_load_capsule_drivers(void)
818{
819 __maybe_unused efi_handle_t handle;
820 efi_status_t ret = EFI_SUCCESS;
821
822 if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_FIT)) {
823 handle = NULL;
Ilias Apalodimas8ac0ebe2022-10-06 16:08:46 +0300824 ret = efi_install_multiple_protocol_interfaces(&handle,
825 &efi_guid_firmware_management_protocol,
826 &efi_fmp_fit,
827 NULL);
Masami Hiramatsud306caa2022-03-21 22:37:45 +0900828 }
829
830 if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_RAW)) {
831 handle = NULL;
Ilias Apalodimas8ac0ebe2022-10-06 16:08:46 +0300832 ret = efi_install_multiple_protocol_interfaces(&handle,
833 &efi_guid_firmware_management_protocol,
834 &efi_fmp_raw,
835 NULL);
Masami Hiramatsud306caa2022-03-21 22:37:45 +0900836 }
837
838 return ret;
839}
840
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900841#ifdef CONFIG_EFI_CAPSULE_ON_DISK
842/**
843 * get_dp_device - retrieve a device path from boot variable
844 * @boot_var: Boot variable name
845 * @device_dp Device path
846 *
847 * Retrieve a device patch from boot variable, @boot_var.
848 *
849 * Return: status code
850 */
851static efi_status_t get_dp_device(u16 *boot_var,
852 struct efi_device_path **device_dp)
853{
854 void *buf = NULL;
855 efi_uintn_t size;
856 struct efi_load_option lo;
857 struct efi_device_path *file_dp;
858 efi_status_t ret;
859
860 size = 0;
861 ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
862 NULL, &size, NULL, NULL);
863 if (ret == EFI_BUFFER_TOO_SMALL) {
864 buf = malloc(size);
865 if (!buf)
866 return EFI_OUT_OF_RESOURCES;
867 ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
868 NULL, &size, buf, NULL);
869 }
870 if (ret != EFI_SUCCESS)
871 return ret;
872
873 efi_deserialize_load_option(&lo, buf, &size);
874
875 if (lo.attributes & LOAD_OPTION_ACTIVE) {
876 efi_dp_split_file_path(lo.file_path, device_dp, &file_dp);
877 efi_free_pool(file_dp);
878
879 ret = EFI_SUCCESS;
880 } else {
881 ret = EFI_NOT_FOUND;
882 }
883
884 free(buf);
885
886 return ret;
887}
888
889/**
890 * device_is_present_and_system_part - check if a device exists
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900891 *
892 * Check if a device pointed to by the device path, @dp, exists and is
893 * located in UEFI system partition.
894 *
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100895 * @dp device path
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900896 * Return: true - yes, false - no
897 */
898static bool device_is_present_and_system_part(struct efi_device_path *dp)
899{
900 efi_handle_t handle;
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100901 struct efi_device_path *rem;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900902
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100903 /* Check device exists */
Heinrich Schuchardt0a04a412022-03-19 06:35:43 +0100904 handle = efi_dp_find_obj(dp, NULL, NULL);
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900905 if (!handle)
906 return false;
907
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100908 /* Check device is on system partition */
909 handle = efi_dp_find_obj(dp, &efi_system_partition_guid, &rem);
910 if (!handle)
911 return false;
912
913 return true;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900914}
915
916/**
917 * find_boot_device - identify the boot device
918 *
919 * Identify the boot device from boot-related variables as UEFI
920 * specification describes and put its handle into bootdev_root.
921 *
922 * Return: status code
923 */
924static efi_status_t find_boot_device(void)
925{
926 char boot_var[9];
927 u16 boot_var16[9], *p, bootnext, *boot_order = NULL;
928 efi_uintn_t size;
929 int i, num;
930 struct efi_simple_file_system_protocol *volume;
931 struct efi_device_path *boot_dev = NULL;
932 efi_status_t ret;
933
934 /* find active boot device in BootNext */
935 bootnext = 0;
936 size = sizeof(bootnext);
Simon Glass90975372022-01-23 12:55:12 -0700937 ret = efi_get_variable_int(u"BootNext",
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900938 (efi_guid_t *)&efi_global_variable_guid,
939 NULL, &size, &bootnext, NULL);
940 if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
941 /* BootNext does exist here */
942 if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) {
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900943 log_err("BootNext must be 16-bit integer\n");
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900944 goto skip;
945 }
946 sprintf((char *)boot_var, "Boot%04X", bootnext);
947 p = boot_var16;
948 utf8_utf16_strcpy(&p, boot_var);
949
950 ret = get_dp_device(boot_var16, &boot_dev);
951 if (ret == EFI_SUCCESS) {
952 if (device_is_present_and_system_part(boot_dev)) {
Masami Hiramatsu10165752021-07-12 18:05:17 +0900953 goto found;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900954 } else {
955 efi_free_pool(boot_dev);
956 boot_dev = NULL;
957 }
958 }
959 }
960
961skip:
962 /* find active boot device in BootOrder */
963 size = 0;
Simon Glass90975372022-01-23 12:55:12 -0700964 ret = efi_get_variable_int(u"BootOrder", &efi_global_variable_guid,
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900965 NULL, &size, NULL, NULL);
966 if (ret == EFI_BUFFER_TOO_SMALL) {
967 boot_order = malloc(size);
968 if (!boot_order) {
969 ret = EFI_OUT_OF_RESOURCES;
970 goto out;
971 }
972
Simon Glass90975372022-01-23 12:55:12 -0700973 ret = efi_get_variable_int(u"BootOrder",
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900974 &efi_global_variable_guid,
975 NULL, &size, boot_order, NULL);
976 }
977 if (ret != EFI_SUCCESS)
978 goto out;
979
980 /* check in higher order */
981 num = size / sizeof(u16);
982 for (i = 0; i < num; i++) {
983 sprintf((char *)boot_var, "Boot%04X", boot_order[i]);
984 p = boot_var16;
985 utf8_utf16_strcpy(&p, boot_var);
986 ret = get_dp_device(boot_var16, &boot_dev);
987 if (ret != EFI_SUCCESS)
988 continue;
989
990 if (device_is_present_and_system_part(boot_dev))
991 break;
992
993 efi_free_pool(boot_dev);
994 boot_dev = NULL;
995 }
Masami Hiramatsu10165752021-07-12 18:05:17 +0900996found:
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900997 if (boot_dev) {
Masami Hiramatsud9763bb2021-07-14 14:19:13 +0900998 log_debug("Boot device %pD\n", boot_dev);
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900999
1000 volume = efi_fs_from_path(boot_dev);
1001 if (!volume)
1002 ret = EFI_DEVICE_ERROR;
1003 else
1004 ret = EFI_CALL(volume->open_volume(volume,
1005 &bootdev_root));
1006 efi_free_pool(boot_dev);
1007 } else {
1008 ret = EFI_NOT_FOUND;
1009 }
AKASHI Takahirofa390e62021-04-20 10:03:16 +09001010out:
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001011 free(boot_order);
1012
1013 return ret;
1014}
1015
1016/**
1017 * efi_capsule_scan_dir - traverse a capsule directory in boot device
1018 * @files: Array of file names
1019 * @num: Number of elements in @files
1020 *
1021 * Traverse a capsule directory in boot device.
1022 * Called by initialization code, and returns an array of capsule file
1023 * names in @files.
1024 *
1025 * Return: status code
1026 */
1027static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num)
1028{
1029 struct efi_file_handle *dirh;
1030 struct efi_file_info *dirent;
1031 efi_uintn_t dirent_size, tmp_size;
1032 unsigned int count;
1033 u16 **tmp_files;
1034 efi_status_t ret;
1035
1036 ret = find_boot_device();
1037 if (ret == EFI_NOT_FOUND) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001038 log_debug("Boot device is not set\n");
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001039 *num = 0;
1040 return EFI_SUCCESS;
1041 } else if (ret != EFI_SUCCESS) {
1042 return EFI_DEVICE_ERROR;
1043 }
1044
1045 /* count capsule files */
1046 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
1047 EFI_CAPSULE_DIR,
1048 EFI_FILE_MODE_READ, 0));
1049 if (ret != EFI_SUCCESS) {
1050 *num = 0;
1051 return EFI_SUCCESS;
1052 }
1053
1054 dirent_size = 256;
1055 dirent = malloc(dirent_size);
1056 if (!dirent)
1057 return EFI_OUT_OF_RESOURCES;
1058
1059 count = 0;
1060 while (1) {
1061 tmp_size = dirent_size;
1062 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
1063 if (ret == EFI_BUFFER_TOO_SMALL) {
Heinrich Schuchardtaa27e5d2021-04-11 06:53:04 +02001064 struct efi_file_info *old_dirent = dirent;
1065
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001066 dirent = realloc(dirent, tmp_size);
1067 if (!dirent) {
Heinrich Schuchardtaa27e5d2021-04-11 06:53:04 +02001068 dirent = old_dirent;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001069 ret = EFI_OUT_OF_RESOURCES;
1070 goto err;
1071 }
1072 dirent_size = tmp_size;
1073 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
1074 }
1075 if (ret != EFI_SUCCESS)
1076 goto err;
1077 if (!tmp_size)
1078 break;
1079
Heinrich Schuchardt76b708a2021-02-09 17:45:33 +01001080 if (!(dirent->attribute & EFI_FILE_DIRECTORY))
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001081 count++;
1082 }
1083
1084 ret = EFI_CALL((*dirh->setpos)(dirh, 0));
1085 if (ret != EFI_SUCCESS)
1086 goto err;
1087
1088 /* make a list */
AKASHI Takahiroc8fc12f2021-01-22 10:43:27 +09001089 tmp_files = malloc(count * sizeof(*tmp_files));
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001090 if (!tmp_files) {
1091 ret = EFI_OUT_OF_RESOURCES;
1092 goto err;
1093 }
1094
1095 count = 0;
1096 while (1) {
1097 tmp_size = dirent_size;
1098 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
1099 if (ret != EFI_SUCCESS)
1100 goto err;
1101 if (!tmp_size)
1102 break;
1103
1104 if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
Simon Glass90975372022-01-23 12:55:12 -07001105 u16_strcmp(dirent->file_name, u".") &&
1106 u16_strcmp(dirent->file_name, u".."))
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001107 tmp_files[count++] = u16_strdup(dirent->file_name);
1108 }
1109 /* ignore an error */
1110 EFI_CALL((*dirh->close)(dirh));
1111
Heinrich Schuchardtba0a2ad2022-12-29 14:44:05 +01001112 /*
1113 * Capsule files are applied in case insensitive alphabetic order
1114 *
1115 * TODO: special handling of rightmost period
1116 */
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001117 qsort(tmp_files, count, sizeof(*tmp_files),
Heinrich Schuchardtba0a2ad2022-12-29 14:44:05 +01001118 (int (*)(const void *, const void *))u16_strcasecmp);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001119 *files = tmp_files;
1120 *num = count;
1121 ret = EFI_SUCCESS;
1122err:
1123 free(dirent);
1124
1125 return ret;
1126}
1127
1128/**
1129 * efi_capsule_read_file - read in a capsule file
1130 * @filename: File name
1131 * @capsule: Pointer to buffer for capsule
1132 *
1133 * Read a capsule file and put its content in @capsule.
1134 *
1135 * Return: status code
1136 */
1137static efi_status_t efi_capsule_read_file(const u16 *filename,
1138 struct efi_capsule_header **capsule)
1139{
1140 struct efi_file_handle *dirh, *fh;
1141 struct efi_file_info *file_info = NULL;
1142 struct efi_capsule_header *buf = NULL;
1143 efi_uintn_t size;
1144 efi_status_t ret;
1145
1146 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
1147 EFI_CAPSULE_DIR,
1148 EFI_FILE_MODE_READ, 0));
1149 if (ret != EFI_SUCCESS)
1150 return ret;
1151 ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
1152 EFI_FILE_MODE_READ, 0));
1153 /* ignore an error */
1154 EFI_CALL((*dirh->close)(dirh));
1155 if (ret != EFI_SUCCESS)
1156 return ret;
1157
1158 /* file size */
1159 size = 0;
1160 ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
1161 &size, file_info));
1162 if (ret == EFI_BUFFER_TOO_SMALL) {
1163 file_info = malloc(size);
1164 if (!file_info) {
1165 ret = EFI_OUT_OF_RESOURCES;
1166 goto err;
1167 }
1168 ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
1169 &size, file_info));
1170 }
1171 if (ret != EFI_SUCCESS)
1172 goto err;
1173 size = file_info->file_size;
1174 free(file_info);
1175 buf = malloc(size);
1176 if (!buf) {
1177 ret = EFI_OUT_OF_RESOURCES;
1178 goto err;
1179 }
1180
1181 /* fetch data */
1182 ret = EFI_CALL((*fh->read)(fh, &size, buf));
1183 if (ret == EFI_SUCCESS) {
1184 if (size >= buf->capsule_image_size) {
1185 *capsule = buf;
1186 } else {
1187 free(buf);
1188 ret = EFI_INVALID_PARAMETER;
1189 }
1190 } else {
1191 free(buf);
1192 }
1193err:
1194 EFI_CALL((*fh->close)(fh));
1195
1196 return ret;
1197}
1198
1199/**
1200 * efi_capsule_delete_file - delete a capsule file
1201 * @filename: File name
1202 *
1203 * Delete a capsule file from capsule directory.
1204 *
1205 * Return: status code
1206 */
1207static efi_status_t efi_capsule_delete_file(const u16 *filename)
1208{
1209 struct efi_file_handle *dirh, *fh;
1210 efi_status_t ret;
1211
1212 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
1213 EFI_CAPSULE_DIR,
1214 EFI_FILE_MODE_READ, 0));
1215 if (ret != EFI_SUCCESS)
1216 return ret;
1217 ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
1218 EFI_FILE_MODE_READ, 0));
1219 /* ignore an error */
1220 EFI_CALL((*dirh->close)(dirh));
1221
Heinrich Schuchardte5c22812021-06-02 19:28:22 +02001222 if (ret == EFI_SUCCESS)
1223 ret = EFI_CALL((*fh->delete)(fh));
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001224
1225 return ret;
1226}
1227
1228/**
1229 * efi_capsule_scan_done - reset a scan help function
1230 *
1231 * Reset a scan help function
1232 */
1233static void efi_capsule_scan_done(void)
1234{
1235 EFI_CALL((*bootdev_root->close)(bootdev_root));
1236 bootdev_root = NULL;
1237}
1238
1239/**
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001240 * check_run_capsules() - check whether capsule update should run
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001241 *
1242 * The spec says OsIndications must be set in order to run the capsule update
1243 * on-disk. Since U-Boot doesn't support runtime SetVariable, allow capsules to
1244 * run explicitly if CONFIG_EFI_IGNORE_OSINDICATIONS is selected
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001245 *
1246 * Return: EFI_SUCCESS if update to run, EFI_NOT_FOUND otherwise
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001247 */
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001248static efi_status_t check_run_capsules(void)
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001249{
Sughosh Ganu0f5ca5c2022-06-01 23:30:39 +05301250 u64 os_indications = 0x0;
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001251 efi_uintn_t size;
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001252 efi_status_t r;
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001253
1254 size = sizeof(os_indications);
Simon Glass90975372022-01-23 12:55:12 -07001255 r = efi_get_variable_int(u"OsIndications", &efi_global_variable_guid,
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001256 NULL, &size, &os_indications, NULL);
Sughosh Ganu0f5ca5c2022-06-01 23:30:39 +05301257 if (!IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS) &&
1258 (r != EFI_SUCCESS || size != sizeof(os_indications)))
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001259 return EFI_NOT_FOUND;
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001260
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001261 if (os_indications &
1262 EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) {
1263 os_indications &=
1264 ~EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
Simon Glass90975372022-01-23 12:55:12 -07001265 r = efi_set_variable_int(u"OsIndications",
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001266 &efi_global_variable_guid,
1267 EFI_VARIABLE_NON_VOLATILE |
1268 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1269 EFI_VARIABLE_RUNTIME_ACCESS,
1270 sizeof(os_indications),
1271 &os_indications, false);
1272 if (r != EFI_SUCCESS)
1273 log_err("Setting %ls failed\n", L"OsIndications");
1274 return EFI_SUCCESS;
1275 } else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) {
1276 return EFI_SUCCESS;
Sughosh Ganu0f5ca5c2022-06-01 23:30:39 +05301277 } else {
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001278 return EFI_NOT_FOUND;
1279 }
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001280}
1281
1282/**
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001283 * efi_launch_capsule - launch capsules
1284 *
1285 * Launch all the capsules in system at boot time.
1286 * Called by efi init code
1287 *
1288 * Return: status codde
1289 */
1290efi_status_t efi_launch_capsules(void)
1291{
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001292 struct efi_capsule_header *capsule = NULL;
1293 u16 **files;
Etienne Carriere6326e912023-02-16 18:21:41 +01001294 unsigned int nfiles, index, index_max, i;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001295 efi_status_t ret;
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301296 bool capsule_update = true;
1297 bool update_status = true;
1298 bool fw_accept_os = false;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001299
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001300 if (check_run_capsules() != EFI_SUCCESS)
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001301 return EFI_SUCCESS;
1302
Etienne Carriere6326e912023-02-16 18:21:41 +01001303 index_max = get_max_capsule();
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001304 index = get_last_capsule();
1305
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001306 /*
1307 * Find capsules on disk.
1308 * All the capsules are collected at the beginning because
1309 * capsule files will be removed instantly.
1310 */
1311 nfiles = 0;
1312 files = NULL;
1313 ret = efi_capsule_scan_dir(&files, &nfiles);
1314 if (ret != EFI_SUCCESS)
1315 return ret;
1316 if (!nfiles)
1317 return EFI_SUCCESS;
1318
1319 /* Launch capsules */
1320 for (i = 0, ++index; i < nfiles; i++, index++) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001321 log_debug("Applying %ls\n", files[i]);
Etienne Carriere6326e912023-02-16 18:21:41 +01001322 if (index > index_max)
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001323 index = 0;
1324 ret = efi_capsule_read_file(files[i], &capsule);
1325 if (ret == EFI_SUCCESS) {
Masami Hiramatsu3454a692022-02-16 15:15:42 +09001326 ret = efi_capsule_update_firmware(capsule);
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301327 if (ret != EFI_SUCCESS) {
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001328 log_err("Applying capsule %ls failed.\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +09001329 files[i]);
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301330 update_status = false;
1331 } else {
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001332 log_info("Applying capsule %ls succeeded.\n",
1333 files[i]);
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301334 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
1335 fwu_post_update_checks(capsule,
1336 &fw_accept_os,
1337 &capsule_update);
1338 }
1339 }
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001340
Masami Hiramatsu1001a102021-11-12 22:05:15 +09001341 /* create CapsuleXXXX */
1342 set_capsule_result(index, capsule, ret);
1343
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001344 free(capsule);
1345 } else {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001346 log_err("Reading capsule %ls failed\n", files[i]);
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301347 update_status = false;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001348 }
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001349 /* delete a capsule either in case of success or failure */
1350 ret = efi_capsule_delete_file(files[i]);
1351 if (ret != EFI_SUCCESS)
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001352 log_err("Deleting capsule %ls failed\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +09001353 files[i]);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001354 }
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301355
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001356 efi_capsule_scan_done();
1357
Sughosh Ganu1cadae22022-10-21 18:16:03 +05301358 if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
1359 if (capsule_update == true && update_status == true) {
1360 ret = fwu_post_update_process(fw_accept_os);
1361 } else if (capsule_update == true && update_status == false) {
1362 log_err("All capsules were not updated. Not updating FWU metadata\n");
1363 }
1364 }
1365
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001366 for (i = 0; i < nfiles; i++)
1367 free(files[i]);
1368 free(files);
1369
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001370 /*
1371 * UEFI spec requires to reset system after complete processing capsule
1372 * update on the storage.
1373 */
Masami Hiramatsuff744862022-03-21 22:37:56 +09001374 log_info("Reboot after firmware update.\n");
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001375 /* Cold reset is required for loading the new firmware. */
Masami Hiramatsuff744862022-03-21 22:37:56 +09001376 sysreset_walk_halt(SYSRESET_COLD);
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001377 hang();
1378 /* not reach here */
1379
1380 return 0;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001381}
1382#endif /* CONFIG_EFI_CAPSULE_ON_DISK */