blob: a6b98f066a0babb844797e7afd070490e7662711 [file] [log] [blame]
AKASHI Takahiro2bc27ca2020-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 Schuchardt3e491192021-07-10 11:03:27 +02009#define LOG_CATEGORY LOGC_EFI
10
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090011#include <common.h>
12#include <efi_loader.h>
13#include <efi_variable.h>
AKASHI Takahiro7a6fb282021-10-07 15:23:32 +090014#include <env.h>
15#include <fdtdec.h>
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090016#include <fs.h>
Masami Hiramatsu3e6f8102022-02-16 15:16:12 +090017#include <hang.h>
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090018#include <malloc.h>
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +090019#include <mapmem.h>
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090020#include <sort.h>
Masami Hiramatsu7660cfe2022-03-21 22:37:56 +090021#include <sysreset.h>
AKASHI Takahiro7a6fb282021-10-07 15:23:32 +090022#include <asm/global_data.h>
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090023
Sughosh Ganu04be98b2020-12-30 19:27:09 +053024#include <crypto/pkcs7.h>
25#include <crypto/pkcs7_parser.h>
26#include <linux/err.h>
27
AKASHI Takahiro7a6fb282021-10-07 15:23:32 +090028DECLARE_GLOBAL_DATA_PTR;
29
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090030const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
AKASHI Takahiro8d990262020-11-30 18:12:11 +090031static const efi_guid_t efi_guid_firmware_management_capsule_id =
32 EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
33const efi_guid_t efi_guid_firmware_management_protocol =
34 EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090035
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +090036#ifdef CONFIG_EFI_CAPSULE_ON_DISK
37/* for file system access */
38static struct efi_file_handle *bootdev_root;
39#endif
40
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090041/**
42 * get_last_capsule - get the last capsule index
43 *
44 * Retrieve the index of the capsule invoked last time from "CapsuleLast"
45 * variable.
46 *
47 * Return:
48 * * > 0 - the last capsule index invoked
49 * * 0xffff - on error, or no capsule invoked yet
50 */
51static __maybe_unused unsigned int get_last_capsule(void)
52{
53 u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */
Heinrich Schuchardt15bbcaf2021-02-09 20:20:34 +010054 char value[5];
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090055 efi_uintn_t size;
56 unsigned long index = 0xffff;
57 efi_status_t ret;
Heinrich Schuchardt15bbcaf2021-02-09 20:20:34 +010058 int i;
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090059
60 size = sizeof(value16);
Simon Glass156ccbc2022-01-23 12:55:12 -070061 ret = efi_get_variable_int(u"CapsuleLast", &efi_guid_capsule_report,
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090062 NULL, &size, value16, NULL);
Heinrich Schuchardt15bbcaf2021-02-09 20:20:34 +010063 if (ret != EFI_SUCCESS || size != 22 ||
Simon Glass156ccbc2022-01-23 12:55:12 -070064 u16_strncmp(value16, u"Capsule", 7))
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090065 goto err;
Heinrich Schuchardt15bbcaf2021-02-09 20:20:34 +010066 for (i = 0; i < 4; ++i) {
67 u16 c = value16[i + 7];
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090068
Heinrich Schuchardt15bbcaf2021-02-09 20:20:34 +010069 if (!c || c > 0x7f)
70 goto err;
71 value[i] = c;
72 }
73 value[4] = 0;
74 if (strict_strtoul(value, 16, &index))
75 index = 0xffff;
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090076err:
77 return index;
78}
79
80/**
81 * set_capsule_result - set a result variable
82 * @capsule: Capsule
83 * @return_status: Return status
84 *
85 * Create and set a result variable, "CapsuleXXXX", for the capsule,
86 * @capsule.
87 */
88static __maybe_unused
89void set_capsule_result(int index, struct efi_capsule_header *capsule,
90 efi_status_t return_status)
91{
92 u16 variable_name16[12];
93 struct efi_capsule_result_variable_header result;
94 struct efi_time time;
95 efi_status_t ret;
96
Ilias Apalodimasfe179d72020-12-31 12:26:46 +020097 efi_create_indexed_name(variable_name16, sizeof(variable_name16),
98 "Capsule", index);
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +090099 result.variable_total_size = sizeof(result);
100 result.capsule_guid = capsule->capsule_guid;
101 ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
102 if (ret == EFI_SUCCESS)
103 memcpy(&result.capsule_processed, &time, sizeof(time));
104 else
105 memset(&result.capsule_processed, 0, sizeof(time));
106 result.capsule_status = return_status;
Heinrich Schuchardtd7eedd92021-07-10 11:10:26 +0200107 ret = efi_set_variable_int(variable_name16, &efi_guid_capsule_report,
108 EFI_VARIABLE_NON_VOLATILE |
109 EFI_VARIABLE_BOOTSERVICE_ACCESS |
110 EFI_VARIABLE_RUNTIME_ACCESS,
111 sizeof(result), &result, false);
Heinrich Schuchardt70bad542021-07-10 11:14:13 +0200112 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +0200113 log_err("Setting %ls failed\n", variable_name16);
Heinrich Schuchardt70bad542021-07-10 11:14:13 +0200114 return;
115 }
116
117 /* Variable CapsuleLast must not include terminating 0x0000 */
Simon Glass156ccbc2022-01-23 12:55:12 -0700118 ret = efi_set_variable_int(u"CapsuleLast", &efi_guid_capsule_report,
Heinrich Schuchardt70bad542021-07-10 11:14:13 +0200119 EFI_VARIABLE_READ_ONLY |
120 EFI_VARIABLE_NON_VOLATILE |
121 EFI_VARIABLE_BOOTSERVICE_ACCESS |
122 EFI_VARIABLE_RUNTIME_ACCESS,
123 22, variable_name16, false);
124 if (ret != EFI_SUCCESS)
Simon Glass156ccbc2022-01-23 12:55:12 -0700125 log_err("Setting %ls failed\n", u"CapsuleLast");
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900126}
127
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900128#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT
129/**
130 * efi_fmp_find - search for Firmware Management Protocol drivers
131 * @image_type: Image type guid
Sughosh Ganu7cf06f02022-04-15 11:29:36 +0530132 * @image_index: Image Index
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900133 * @instance: Instance number
134 * @handles: Handles of FMP drivers
135 * @no_handles: Number of handles
136 *
137 * Search for Firmware Management Protocol drivers, matching the image
138 * type, @image_type and the machine instance, @instance, from the list,
139 * @handles.
140 *
141 * Return:
142 * * Protocol instance - on success
143 * * NULL - on failure
144 */
145static struct efi_firmware_management_protocol *
Sughosh Ganu7cf06f02022-04-15 11:29:36 +0530146efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance,
147 efi_handle_t *handles, efi_uintn_t no_handles)
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900148{
149 efi_handle_t *handle;
150 struct efi_firmware_management_protocol *fmp;
151 struct efi_firmware_image_descriptor *image_info, *desc;
152 efi_uintn_t info_size, descriptor_size;
153 u32 descriptor_version;
154 u8 descriptor_count;
155 u32 package_version;
156 u16 *package_version_name;
157 bool found = false;
158 int i, j;
159 efi_status_t ret;
160
161 for (i = 0, handle = handles; i < no_handles; i++, handle++) {
162 ret = EFI_CALL(efi_handle_protocol(
163 *handle,
164 &efi_guid_firmware_management_protocol,
165 (void **)&fmp));
166 if (ret != EFI_SUCCESS)
167 continue;
168
169 /* get device's image info */
170 info_size = 0;
171 image_info = NULL;
172 descriptor_version = 0;
173 descriptor_count = 0;
174 descriptor_size = 0;
175 package_version = 0;
176 package_version_name = NULL;
177 ret = EFI_CALL(fmp->get_image_info(fmp, &info_size,
178 image_info,
179 &descriptor_version,
180 &descriptor_count,
181 &descriptor_size,
182 &package_version,
183 &package_version_name));
184 if (ret != EFI_BUFFER_TOO_SMALL)
185 goto skip;
186
187 image_info = malloc(info_size);
188 if (!image_info)
189 goto skip;
190
191 ret = EFI_CALL(fmp->get_image_info(fmp, &info_size,
192 image_info,
193 &descriptor_version,
194 &descriptor_count,
195 &descriptor_size,
196 &package_version,
197 &package_version_name));
198 if (ret != EFI_SUCCESS ||
199 descriptor_version != EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION)
200 goto skip;
201
202 /* matching */
203 for (j = 0, desc = image_info; j < descriptor_count;
204 j++, desc = (void *)desc + descriptor_size) {
205 log_debug("+++ desc[%d] index: %d, name: %ls\n",
206 j, desc->image_index, desc->image_id_name);
207 if (!guidcmp(&desc->image_type_id, image_type) &&
Sughosh Ganu7cf06f02022-04-15 11:29:36 +0530208 (desc->image_index == image_index) &&
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900209 (!instance ||
210 !desc->hardware_instance ||
211 desc->hardware_instance == instance))
212 found = true;
213 }
214
215skip:
216 efi_free_pool(package_version_name);
217 free(image_info);
218 EFI_CALL(efi_close_protocol(
219 (efi_handle_t)fmp,
220 &efi_guid_firmware_management_protocol,
221 NULL, NULL));
222 if (found)
223 return fmp;
224 }
225
226 return NULL;
227}
228
AKASHI Takahiroc2cc60c2021-07-20 14:52:05 +0900229/**
230 * efi_remove_auth_hdr - remove authentication data from image
231 * @image: Pointer to pointer to Image
232 * @image_size: Pointer to Image size
233 *
234 * Remove the authentication data from image if possible.
235 * Update @image and @image_size.
236 *
237 * Return: status code
238 */
239static efi_status_t efi_remove_auth_hdr(void **image, efi_uintn_t *image_size)
240{
241 struct efi_firmware_image_authentication *auth_hdr;
242 efi_status_t ret = EFI_INVALID_PARAMETER;
243
244 auth_hdr = (struct efi_firmware_image_authentication *)*image;
245 if (*image_size < sizeof(*auth_hdr))
246 goto out;
247
248 if (auth_hdr->auth_info.hdr.dwLength <=
249 offsetof(struct win_certificate_uefi_guid, cert_data))
250 goto out;
251
252 *image = (uint8_t *)*image + sizeof(auth_hdr->monotonic_count) +
253 auth_hdr->auth_info.hdr.dwLength;
254 *image_size = *image_size - auth_hdr->auth_info.hdr.dwLength -
255 sizeof(auth_hdr->monotonic_count);
256
257 ret = EFI_SUCCESS;
258out:
259 return ret;
260}
261
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530262#if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
AKASHI Takahiro50b05eb2021-11-02 09:55:01 +0900263int efi_get_public_key_data(void **pkey, efi_uintn_t *pkey_len)
AKASHI Takahiro7a6fb282021-10-07 15:23:32 +0900264{
265 const void *fdt_blob = gd->fdt_blob;
266 const void *blob;
267 const char *cnode_name = "capsule-key";
268 const char *snode_name = "signature";
269 int sig_node;
270 int len;
271
272 sig_node = fdt_subnode_offset(fdt_blob, 0, snode_name);
273 if (sig_node < 0) {
274 log_err("Unable to get signature node offset\n");
275
276 return -FDT_ERR_NOTFOUND;
277 }
278
279 blob = fdt_getprop(fdt_blob, sig_node, cnode_name, &len);
280
281 if (!blob || len < 0) {
282 log_err("Unable to get capsule-key value\n");
283 *pkey = NULL;
284 *pkey_len = 0;
285
286 return -FDT_ERR_NOTFOUND;
287 }
288
289 *pkey = (void *)blob;
290 *pkey_len = len;
291
292 return 0;
293}
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530294
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530295efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_size,
296 void **image, efi_uintn_t *image_size)
297{
298 u8 *buf;
299 int ret;
Simon Glass47a25e82021-08-02 08:44:31 -0600300 void *fdt_pkey, *pkey;
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530301 efi_uintn_t pkey_len;
302 uint64_t monotonic_count;
303 struct efi_signature_store *truststore;
304 struct pkcs7_message *capsule_sig;
305 struct efi_image_regions *regs;
306 struct efi_firmware_image_authentication *auth_hdr;
307 efi_status_t status;
308
309 status = EFI_SECURITY_VIOLATION;
310 capsule_sig = NULL;
311 truststore = NULL;
312 regs = NULL;
313
314 /* Sanity checks */
315 if (capsule == NULL || capsule_size == 0)
316 goto out;
317
AKASHI Takahiroc2cc60c2021-07-20 14:52:05 +0900318 *image = (uint8_t *)capsule;
319 *image_size = capsule_size;
320 if (efi_remove_auth_hdr(image, image_size) != EFI_SUCCESS)
321 goto out;
322
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530323 auth_hdr = (struct efi_firmware_image_authentication *)capsule;
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530324 if (guidcmp(&auth_hdr->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
325 goto out;
326
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530327 memcpy(&monotonic_count, &auth_hdr->monotonic_count,
328 sizeof(monotonic_count));
329
330 /* data to be digested */
331 regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 2, 1);
332 if (!regs)
333 goto out;
334
335 regs->max = 2;
336 efi_image_region_add(regs, (uint8_t *)*image,
337 (uint8_t *)*image + *image_size, 1);
338
339 efi_image_region_add(regs, (uint8_t *)&monotonic_count,
340 (uint8_t *)&monotonic_count + sizeof(monotonic_count),
341 1);
342
343 capsule_sig = efi_parse_pkcs7_header(auth_hdr->auth_info.cert_data,
344 auth_hdr->auth_info.hdr.dwLength
345 - sizeof(auth_hdr->auth_info),
346 &buf);
347 if (IS_ERR(capsule_sig)) {
348 debug("Parsing variable's pkcs7 header failed\n");
349 capsule_sig = NULL;
350 goto out;
351 }
352
Simon Glass47a25e82021-08-02 08:44:31 -0600353 ret = efi_get_public_key_data(&fdt_pkey, &pkey_len);
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530354 if (ret < 0)
355 goto out;
356
357 pkey = malloc(pkey_len);
358 if (!pkey)
359 goto out;
360
Simon Glass47a25e82021-08-02 08:44:31 -0600361 memcpy(pkey, fdt_pkey, pkey_len);
Sughosh Ganu04be98b2020-12-30 19:27:09 +0530362 truststore = efi_build_signature_store(pkey, pkey_len);
363 if (!truststore)
364 goto out;
365
366 /* verify signature */
367 if (efi_signature_verify(regs, capsule_sig, truststore, NULL)) {
368 debug("Verified\n");
369 } else {
370 debug("Verifying variable's signature failed\n");
371 goto out;
372 }
373
374 status = EFI_SUCCESS;
375
376out:
377 efi_sigstore_free(truststore);
378 pkcs7_free_message(capsule_sig);
379 free(regs);
380
381 return status;
382}
383#else
384efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_size,
385 void **image, efi_uintn_t *image_size)
386{
387 return EFI_UNSUPPORTED;
388}
389#endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */
390
391
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900392/**
393 * efi_capsule_update_firmware - update firmware from capsule
394 * @capsule_data: Capsule
395 *
396 * Update firmware, using a capsule, @capsule_data. Loading any FMP
397 * drivers embedded in a capsule is not supported.
398 *
399 * Return: status code
400 */
401static efi_status_t efi_capsule_update_firmware(
402 struct efi_capsule_header *capsule_data)
403{
404 struct efi_firmware_management_capsule_header *capsule;
405 struct efi_firmware_management_capsule_image_header *image;
AKASHI Takahiroc2cc60c2021-07-20 14:52:05 +0900406 size_t capsule_size, image_binary_size;
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900407 void *image_binary, *vendor_code;
408 efi_handle_t *handles;
409 efi_uintn_t no_handles;
410 int item;
411 struct efi_firmware_management_protocol *fmp;
412 u16 *abort_reason;
413 efi_status_t ret = EFI_SUCCESS;
414
415 /* sanity check */
416 if (capsule_data->header_size < sizeof(*capsule) ||
417 capsule_data->header_size >= capsule_data->capsule_image_size)
418 return EFI_INVALID_PARAMETER;
419
420 capsule = (void *)capsule_data + capsule_data->header_size;
421 capsule_size = capsule_data->capsule_image_size
422 - capsule_data->header_size;
423
424 if (capsule->version != 0x00000001)
425 return EFI_UNSUPPORTED;
426
427 handles = NULL;
428 ret = EFI_CALL(efi_locate_handle_buffer(
429 BY_PROTOCOL,
430 &efi_guid_firmware_management_protocol,
431 NULL, &no_handles, (efi_handle_t **)&handles));
432 if (ret != EFI_SUCCESS)
433 return EFI_UNSUPPORTED;
434
435 /* Payload */
436 for (item = capsule->embedded_driver_count;
437 item < capsule->embedded_driver_count
438 + capsule->payload_item_count; item++) {
439 /* sanity check */
440 if ((capsule->item_offset_list[item] + sizeof(*image)
441 >= capsule_size)) {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +0200442 log_err("Capsule does not have enough data\n");
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900443 ret = EFI_INVALID_PARAMETER;
444 goto out;
445 }
446
447 image = (void *)capsule + capsule->item_offset_list[item];
448
449 if (image->version != 0x00000003) {
450 ret = EFI_UNSUPPORTED;
451 goto out;
452 }
453
454 /* find a device for update firmware */
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900455 fmp = efi_fmp_find(&image->update_image_type_id,
Sughosh Ganu7cf06f02022-04-15 11:29:36 +0530456 image->update_image_index,
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900457 image->update_hardware_instance,
458 handles, no_handles);
459 if (!fmp) {
Heinrich Schuchardtce00a742022-01-16 14:15:31 +0100460 log_err("FMP driver not found for firmware type %pUs, hardware instance %lld\n",
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900461 &image->update_image_type_id,
462 image->update_hardware_instance);
463 ret = EFI_UNSUPPORTED;
464 goto out;
465 }
466
467 /* do update */
AKASHI Takahiroc2cc60c2021-07-20 14:52:05 +0900468 if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&
469 !(image->image_capsule_support &
470 CAPSULE_SUPPORT_AUTHENTICATION)) {
471 /* no signature */
472 ret = EFI_SECURITY_VIOLATION;
473 goto out;
474 }
475
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900476 image_binary = (void *)image + sizeof(*image);
AKASHI Takahiroc2cc60c2021-07-20 14:52:05 +0900477 image_binary_size = image->update_image_size;
478 vendor_code = image_binary + image_binary_size;
479 if (!IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE) &&
480 (image->image_capsule_support &
481 CAPSULE_SUPPORT_AUTHENTICATION)) {
482 ret = efi_remove_auth_hdr(&image_binary,
483 &image_binary_size);
484 if (ret != EFI_SUCCESS)
485 goto out;
486 }
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900487
488 abort_reason = NULL;
489 ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index,
490 image_binary,
AKASHI Takahiroc2cc60c2021-07-20 14:52:05 +0900491 image_binary_size,
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900492 vendor_code, NULL,
493 &abort_reason));
494 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +0200495 log_err("Firmware update failed: %ls\n",
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900496 abort_reason);
497 efi_free_pool(abort_reason);
498 goto out;
499 }
500 }
501
502out:
503 efi_free_pool(handles);
504
505 return ret;
506}
507#else
508static efi_status_t efi_capsule_update_firmware(
509 struct efi_capsule_header *capsule_data)
510{
511 return EFI_UNSUPPORTED;
512}
513#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */
514
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900515/**
516 * efi_update_capsule() - process information from operating system
517 * @capsule_header_array: Array of virtual address pointers
518 * @capsule_count: Number of pointers in capsule_header_array
519 * @scatter_gather_list: Array of physical address pointers
520 *
521 * This function implements the UpdateCapsule() runtime service.
522 *
523 * See the Unified Extensible Firmware Interface (UEFI) specification for
524 * details.
525 *
526 * Return: status code
527 */
528efi_status_t EFIAPI efi_update_capsule(
529 struct efi_capsule_header **capsule_header_array,
530 efi_uintn_t capsule_count,
531 u64 scatter_gather_list)
532{
533 struct efi_capsule_header *capsule;
534 unsigned int i;
535 efi_status_t ret;
536
Simon Glassdf7d89a2021-02-07 14:27:02 -0700537 EFI_ENTRY("%p, %zu, %llu\n", capsule_header_array, capsule_count,
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900538 scatter_gather_list);
539
540 if (!capsule_count) {
541 ret = EFI_INVALID_PARAMETER;
542 goto out;
543 }
544
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900545 ret = EFI_SUCCESS;
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900546 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
547 i++, capsule = *(++capsule_header_array)) {
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900548 /* sanity check */
549 if (capsule->header_size < sizeof(*capsule) ||
550 capsule->capsule_image_size < sizeof(*capsule)) {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +0200551 log_err("Capsule does not have enough data\n");
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900552 continue;
553 }
554
Heinrich Schuchardtce00a742022-01-16 14:15:31 +0100555 log_debug("Capsule[%d] (guid:%pUs)\n",
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900556 i, &capsule->capsule_guid);
557 if (!guidcmp(&capsule->capsule_guid,
558 &efi_guid_firmware_management_capsule_id)) {
559 ret = efi_capsule_update_firmware(capsule);
560 } else {
Heinrich Schuchardtce00a742022-01-16 14:15:31 +0100561 log_err("Unsupported capsule type: %pUs\n",
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900562 &capsule->capsule_guid);
563 ret = EFI_UNSUPPORTED;
564 }
565
566 if (ret != EFI_SUCCESS)
567 goto out;
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900568 }
Jose Marinho64a8aae2021-03-02 17:26:38 +0000569
570 if (IS_ENABLED(CONFIG_EFI_ESRT)) {
571 /* Rebuild the ESRT to reflect any updated FW images. */
572 ret = efi_esrt_populate();
573 if (ret != EFI_SUCCESS)
Heinrich Schuchardt3e491192021-07-10 11:03:27 +0200574 log_warning("ESRT update failed\n");
Jose Marinho64a8aae2021-03-02 17:26:38 +0000575 }
Jose Marinho3627cf42021-04-19 14:54:33 +0100576out:
Jose Marinho64a8aae2021-03-02 17:26:38 +0000577
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900578 return EFI_EXIT(ret);
579}
580
581/**
582 * efi_query_capsule_caps() - check if capsule is supported
583 * @capsule_header_array: Array of virtual pointers
584 * @capsule_count: Number of pointers in capsule_header_array
585 * @maximum_capsule_size: Maximum capsule size
586 * @reset_type: Type of reset needed for capsule update
587 *
588 * This function implements the QueryCapsuleCapabilities() runtime service.
589 *
590 * See the Unified Extensible Firmware Interface (UEFI) specification for
591 * details.
592 *
593 * Return: status code
594 */
595efi_status_t EFIAPI efi_query_capsule_caps(
596 struct efi_capsule_header **capsule_header_array,
597 efi_uintn_t capsule_count,
598 u64 *maximum_capsule_size,
599 u32 *reset_type)
600{
601 struct efi_capsule_header *capsule __attribute__((unused));
602 unsigned int i;
603 efi_status_t ret;
604
Simon Glassdf7d89a2021-02-07 14:27:02 -0700605 EFI_ENTRY("%p, %zu, %p, %p\n", capsule_header_array, capsule_count,
AKASHI Takahiro2bc27ca2020-11-17 09:27:55 +0900606 maximum_capsule_size, reset_type);
607
608 if (!maximum_capsule_size) {
609 ret = EFI_INVALID_PARAMETER;
610 goto out;
611 }
612
613 *maximum_capsule_size = U64_MAX;
614 *reset_type = EFI_RESET_COLD;
615
616 ret = EFI_SUCCESS;
617 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
618 i++, capsule = *(++capsule_header_array)) {
619 /* TODO */
620 }
621out:
622 return EFI_EXIT(ret);
623}
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900624
Masami Hiramatsu39bdf112022-03-21 22:37:45 +0900625/**
626 * efi_load_capsule_drivers - initialize capsule drivers
627 *
628 * Generic FMP drivers backed by DFU
629 *
630 * Return: status code
631 */
632efi_status_t __weak efi_load_capsule_drivers(void)
633{
634 __maybe_unused efi_handle_t handle;
635 efi_status_t ret = EFI_SUCCESS;
636
637 if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_FIT)) {
638 handle = NULL;
639 ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
640 &handle, &efi_guid_firmware_management_protocol,
641 &efi_fmp_fit, NULL));
642 }
643
644 if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_RAW)) {
645 handle = NULL;
646 ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
647 &handle,
648 &efi_guid_firmware_management_protocol,
649 &efi_fmp_raw, NULL));
650 }
651
652 return ret;
653}
654
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900655#ifdef CONFIG_EFI_CAPSULE_ON_DISK
656/**
657 * get_dp_device - retrieve a device path from boot variable
658 * @boot_var: Boot variable name
659 * @device_dp Device path
660 *
661 * Retrieve a device patch from boot variable, @boot_var.
662 *
663 * Return: status code
664 */
665static efi_status_t get_dp_device(u16 *boot_var,
666 struct efi_device_path **device_dp)
667{
668 void *buf = NULL;
669 efi_uintn_t size;
670 struct efi_load_option lo;
671 struct efi_device_path *file_dp;
672 efi_status_t ret;
673
674 size = 0;
675 ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
676 NULL, &size, NULL, NULL);
677 if (ret == EFI_BUFFER_TOO_SMALL) {
678 buf = malloc(size);
679 if (!buf)
680 return EFI_OUT_OF_RESOURCES;
681 ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
682 NULL, &size, buf, NULL);
683 }
684 if (ret != EFI_SUCCESS)
685 return ret;
686
687 efi_deserialize_load_option(&lo, buf, &size);
688
689 if (lo.attributes & LOAD_OPTION_ACTIVE) {
690 efi_dp_split_file_path(lo.file_path, device_dp, &file_dp);
691 efi_free_pool(file_dp);
692
693 ret = EFI_SUCCESS;
694 } else {
695 ret = EFI_NOT_FOUND;
696 }
697
698 free(buf);
699
700 return ret;
701}
702
703/**
704 * device_is_present_and_system_part - check if a device exists
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900705 *
706 * Check if a device pointed to by the device path, @dp, exists and is
707 * located in UEFI system partition.
708 *
Heinrich Schuchardtb78631d2022-03-05 00:36:50 +0100709 * @dp device path
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900710 * Return: true - yes, false - no
711 */
712static bool device_is_present_and_system_part(struct efi_device_path *dp)
713{
714 efi_handle_t handle;
Heinrich Schuchardtb78631d2022-03-05 00:36:50 +0100715 struct efi_device_path *rem;
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900716
Heinrich Schuchardtb78631d2022-03-05 00:36:50 +0100717 /* Check device exists */
Heinrich Schuchardte46ef1d2022-03-19 06:35:43 +0100718 handle = efi_dp_find_obj(dp, NULL, NULL);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900719 if (!handle)
720 return false;
721
Heinrich Schuchardtb78631d2022-03-05 00:36:50 +0100722 /* Check device is on system partition */
723 handle = efi_dp_find_obj(dp, &efi_system_partition_guid, &rem);
724 if (!handle)
725 return false;
726
727 return true;
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900728}
729
730/**
731 * find_boot_device - identify the boot device
732 *
733 * Identify the boot device from boot-related variables as UEFI
734 * specification describes and put its handle into bootdev_root.
735 *
736 * Return: status code
737 */
738static efi_status_t find_boot_device(void)
739{
740 char boot_var[9];
741 u16 boot_var16[9], *p, bootnext, *boot_order = NULL;
742 efi_uintn_t size;
743 int i, num;
744 struct efi_simple_file_system_protocol *volume;
745 struct efi_device_path *boot_dev = NULL;
746 efi_status_t ret;
747
748 /* find active boot device in BootNext */
749 bootnext = 0;
750 size = sizeof(bootnext);
Simon Glass156ccbc2022-01-23 12:55:12 -0700751 ret = efi_get_variable_int(u"BootNext",
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900752 (efi_guid_t *)&efi_global_variable_guid,
753 NULL, &size, &bootnext, NULL);
754 if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
755 /* BootNext does exist here */
756 if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) {
AKASHI Takahiro8d990262020-11-30 18:12:11 +0900757 log_err("BootNext must be 16-bit integer\n");
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900758 goto skip;
759 }
760 sprintf((char *)boot_var, "Boot%04X", bootnext);
761 p = boot_var16;
762 utf8_utf16_strcpy(&p, boot_var);
763
764 ret = get_dp_device(boot_var16, &boot_dev);
765 if (ret == EFI_SUCCESS) {
766 if (device_is_present_and_system_part(boot_dev)) {
Masami Hiramatsub0b14492021-07-12 18:05:17 +0900767 goto found;
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900768 } else {
769 efi_free_pool(boot_dev);
770 boot_dev = NULL;
771 }
772 }
773 }
774
775skip:
776 /* find active boot device in BootOrder */
777 size = 0;
Simon Glass156ccbc2022-01-23 12:55:12 -0700778 ret = efi_get_variable_int(u"BootOrder", &efi_global_variable_guid,
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900779 NULL, &size, NULL, NULL);
780 if (ret == EFI_BUFFER_TOO_SMALL) {
781 boot_order = malloc(size);
782 if (!boot_order) {
783 ret = EFI_OUT_OF_RESOURCES;
784 goto out;
785 }
786
Simon Glass156ccbc2022-01-23 12:55:12 -0700787 ret = efi_get_variable_int(u"BootOrder",
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900788 &efi_global_variable_guid,
789 NULL, &size, boot_order, NULL);
790 }
791 if (ret != EFI_SUCCESS)
792 goto out;
793
794 /* check in higher order */
795 num = size / sizeof(u16);
796 for (i = 0; i < num; i++) {
797 sprintf((char *)boot_var, "Boot%04X", boot_order[i]);
798 p = boot_var16;
799 utf8_utf16_strcpy(&p, boot_var);
800 ret = get_dp_device(boot_var16, &boot_dev);
801 if (ret != EFI_SUCCESS)
802 continue;
803
804 if (device_is_present_and_system_part(boot_dev))
805 break;
806
807 efi_free_pool(boot_dev);
808 boot_dev = NULL;
809 }
Masami Hiramatsub0b14492021-07-12 18:05:17 +0900810found:
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900811 if (boot_dev) {
Masami Hiramatsu484d7d82021-07-14 14:19:13 +0900812 log_debug("Boot device %pD\n", boot_dev);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900813
814 volume = efi_fs_from_path(boot_dev);
815 if (!volume)
816 ret = EFI_DEVICE_ERROR;
817 else
818 ret = EFI_CALL(volume->open_volume(volume,
819 &bootdev_root));
820 efi_free_pool(boot_dev);
821 } else {
822 ret = EFI_NOT_FOUND;
823 }
AKASHI Takahiro2c1a6842021-04-20 10:03:16 +0900824out:
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900825 free(boot_order);
826
827 return ret;
828}
829
830/**
831 * efi_capsule_scan_dir - traverse a capsule directory in boot device
832 * @files: Array of file names
833 * @num: Number of elements in @files
834 *
835 * Traverse a capsule directory in boot device.
836 * Called by initialization code, and returns an array of capsule file
837 * names in @files.
838 *
839 * Return: status code
840 */
841static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num)
842{
843 struct efi_file_handle *dirh;
844 struct efi_file_info *dirent;
845 efi_uintn_t dirent_size, tmp_size;
846 unsigned int count;
847 u16 **tmp_files;
848 efi_status_t ret;
849
850 ret = find_boot_device();
851 if (ret == EFI_NOT_FOUND) {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +0200852 log_debug("Boot device is not set\n");
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900853 *num = 0;
854 return EFI_SUCCESS;
855 } else if (ret != EFI_SUCCESS) {
856 return EFI_DEVICE_ERROR;
857 }
858
859 /* count capsule files */
860 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
861 EFI_CAPSULE_DIR,
862 EFI_FILE_MODE_READ, 0));
863 if (ret != EFI_SUCCESS) {
864 *num = 0;
865 return EFI_SUCCESS;
866 }
867
868 dirent_size = 256;
869 dirent = malloc(dirent_size);
870 if (!dirent)
871 return EFI_OUT_OF_RESOURCES;
872
873 count = 0;
874 while (1) {
875 tmp_size = dirent_size;
876 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
877 if (ret == EFI_BUFFER_TOO_SMALL) {
Heinrich Schuchardte8287b02021-04-11 06:53:04 +0200878 struct efi_file_info *old_dirent = dirent;
879
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900880 dirent = realloc(dirent, tmp_size);
881 if (!dirent) {
Heinrich Schuchardte8287b02021-04-11 06:53:04 +0200882 dirent = old_dirent;
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900883 ret = EFI_OUT_OF_RESOURCES;
884 goto err;
885 }
886 dirent_size = tmp_size;
887 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
888 }
889 if (ret != EFI_SUCCESS)
890 goto err;
891 if (!tmp_size)
892 break;
893
Heinrich Schuchardt841f7a42021-02-09 17:45:33 +0100894 if (!(dirent->attribute & EFI_FILE_DIRECTORY))
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900895 count++;
896 }
897
898 ret = EFI_CALL((*dirh->setpos)(dirh, 0));
899 if (ret != EFI_SUCCESS)
900 goto err;
901
902 /* make a list */
AKASHI Takahiro8f1844c2021-01-22 10:43:27 +0900903 tmp_files = malloc(count * sizeof(*tmp_files));
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900904 if (!tmp_files) {
905 ret = EFI_OUT_OF_RESOURCES;
906 goto err;
907 }
908
909 count = 0;
910 while (1) {
911 tmp_size = dirent_size;
912 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
913 if (ret != EFI_SUCCESS)
914 goto err;
915 if (!tmp_size)
916 break;
917
918 if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
Simon Glass156ccbc2022-01-23 12:55:12 -0700919 u16_strcmp(dirent->file_name, u".") &&
920 u16_strcmp(dirent->file_name, u".."))
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +0900921 tmp_files[count++] = u16_strdup(dirent->file_name);
922 }
923 /* ignore an error */
924 EFI_CALL((*dirh->close)(dirh));
925
926 /* in ascii order */
927 /* FIXME: u16 version of strcasecmp */
928 qsort(tmp_files, count, sizeof(*tmp_files),
929 (int (*)(const void *, const void *))strcasecmp);
930 *files = tmp_files;
931 *num = count;
932 ret = EFI_SUCCESS;
933err:
934 free(dirent);
935
936 return ret;
937}
938
939/**
940 * efi_capsule_read_file - read in a capsule file
941 * @filename: File name
942 * @capsule: Pointer to buffer for capsule
943 *
944 * Read a capsule file and put its content in @capsule.
945 *
946 * Return: status code
947 */
948static efi_status_t efi_capsule_read_file(const u16 *filename,
949 struct efi_capsule_header **capsule)
950{
951 struct efi_file_handle *dirh, *fh;
952 struct efi_file_info *file_info = NULL;
953 struct efi_capsule_header *buf = NULL;
954 efi_uintn_t size;
955 efi_status_t ret;
956
957 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
958 EFI_CAPSULE_DIR,
959 EFI_FILE_MODE_READ, 0));
960 if (ret != EFI_SUCCESS)
961 return ret;
962 ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
963 EFI_FILE_MODE_READ, 0));
964 /* ignore an error */
965 EFI_CALL((*dirh->close)(dirh));
966 if (ret != EFI_SUCCESS)
967 return ret;
968
969 /* file size */
970 size = 0;
971 ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
972 &size, file_info));
973 if (ret == EFI_BUFFER_TOO_SMALL) {
974 file_info = malloc(size);
975 if (!file_info) {
976 ret = EFI_OUT_OF_RESOURCES;
977 goto err;
978 }
979 ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
980 &size, file_info));
981 }
982 if (ret != EFI_SUCCESS)
983 goto err;
984 size = file_info->file_size;
985 free(file_info);
986 buf = malloc(size);
987 if (!buf) {
988 ret = EFI_OUT_OF_RESOURCES;
989 goto err;
990 }
991
992 /* fetch data */
993 ret = EFI_CALL((*fh->read)(fh, &size, buf));
994 if (ret == EFI_SUCCESS) {
995 if (size >= buf->capsule_image_size) {
996 *capsule = buf;
997 } else {
998 free(buf);
999 ret = EFI_INVALID_PARAMETER;
1000 }
1001 } else {
1002 free(buf);
1003 }
1004err:
1005 EFI_CALL((*fh->close)(fh));
1006
1007 return ret;
1008}
1009
1010/**
1011 * efi_capsule_delete_file - delete a capsule file
1012 * @filename: File name
1013 *
1014 * Delete a capsule file from capsule directory.
1015 *
1016 * Return: status code
1017 */
1018static efi_status_t efi_capsule_delete_file(const u16 *filename)
1019{
1020 struct efi_file_handle *dirh, *fh;
1021 efi_status_t ret;
1022
1023 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
1024 EFI_CAPSULE_DIR,
1025 EFI_FILE_MODE_READ, 0));
1026 if (ret != EFI_SUCCESS)
1027 return ret;
1028 ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
1029 EFI_FILE_MODE_READ, 0));
1030 /* ignore an error */
1031 EFI_CALL((*dirh->close)(dirh));
1032
Heinrich Schuchardte27b0ff2021-06-02 19:28:22 +02001033 if (ret == EFI_SUCCESS)
1034 ret = EFI_CALL((*fh->delete)(fh));
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001035
1036 return ret;
1037}
1038
1039/**
1040 * efi_capsule_scan_done - reset a scan help function
1041 *
1042 * Reset a scan help function
1043 */
1044static void efi_capsule_scan_done(void)
1045{
1046 EFI_CALL((*bootdev_root->close)(bootdev_root));
1047 bootdev_root = NULL;
1048}
1049
1050/**
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001051 * check_run_capsules() - check whether capsule update should run
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001052 *
1053 * The spec says OsIndications must be set in order to run the capsule update
1054 * on-disk. Since U-Boot doesn't support runtime SetVariable, allow capsules to
1055 * run explicitly if CONFIG_EFI_IGNORE_OSINDICATIONS is selected
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001056 *
1057 * Return: EFI_SUCCESS if update to run, EFI_NOT_FOUND otherwise
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001058 */
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001059static efi_status_t check_run_capsules(void)
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001060{
Sughosh Ganu119fafd2022-06-01 23:30:39 +05301061 u64 os_indications = 0x0;
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001062 efi_uintn_t size;
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001063 efi_status_t r;
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001064
1065 size = sizeof(os_indications);
Simon Glass156ccbc2022-01-23 12:55:12 -07001066 r = efi_get_variable_int(u"OsIndications", &efi_global_variable_guid,
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001067 NULL, &size, &os_indications, NULL);
Sughosh Ganu119fafd2022-06-01 23:30:39 +05301068 if (!IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS) &&
1069 (r != EFI_SUCCESS || size != sizeof(os_indications)))
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001070 return EFI_NOT_FOUND;
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001071
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001072 if (os_indications &
1073 EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) {
1074 os_indications &=
1075 ~EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
Simon Glass156ccbc2022-01-23 12:55:12 -07001076 r = efi_set_variable_int(u"OsIndications",
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001077 &efi_global_variable_guid,
1078 EFI_VARIABLE_NON_VOLATILE |
1079 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1080 EFI_VARIABLE_RUNTIME_ACCESS,
1081 sizeof(os_indications),
1082 &os_indications, false);
1083 if (r != EFI_SUCCESS)
1084 log_err("Setting %ls failed\n", L"OsIndications");
1085 return EFI_SUCCESS;
1086 } else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) {
1087 return EFI_SUCCESS;
Sughosh Ganu119fafd2022-06-01 23:30:39 +05301088 } else {
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001089 return EFI_NOT_FOUND;
1090 }
Ilias Apalodimas0fa50202021-06-29 07:55:51 +03001091}
1092
1093/**
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001094 * efi_launch_capsule - launch capsules
1095 *
1096 * Launch all the capsules in system at boot time.
1097 * Called by efi init code
1098 *
1099 * Return: status codde
1100 */
1101efi_status_t efi_launch_capsules(void)
1102{
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001103 struct efi_capsule_header *capsule = NULL;
1104 u16 **files;
1105 unsigned int nfiles, index, i;
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001106 efi_status_t ret;
1107
Heinrich Schuchardt9d1564d2021-11-20 11:53:12 +01001108 if (check_run_capsules() != EFI_SUCCESS)
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001109 return EFI_SUCCESS;
1110
1111 index = get_last_capsule();
1112
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001113 /*
1114 * Find capsules on disk.
1115 * All the capsules are collected at the beginning because
1116 * capsule files will be removed instantly.
1117 */
1118 nfiles = 0;
1119 files = NULL;
1120 ret = efi_capsule_scan_dir(&files, &nfiles);
1121 if (ret != EFI_SUCCESS)
1122 return ret;
1123 if (!nfiles)
1124 return EFI_SUCCESS;
1125
1126 /* Launch capsules */
1127 for (i = 0, ++index; i < nfiles; i++, index++) {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +02001128 log_debug("Applying %ls\n", files[i]);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001129 if (index > 0xffff)
1130 index = 0;
1131 ret = efi_capsule_read_file(files[i], &capsule);
1132 if (ret == EFI_SUCCESS) {
Masami Hiramatsua6aafce2022-02-16 15:15:42 +09001133 ret = efi_capsule_update_firmware(capsule);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001134 if (ret != EFI_SUCCESS)
Masami Hiramatsu3e6f8102022-02-16 15:16:12 +09001135 log_err("Applying capsule %ls failed.\n",
AKASHI Takahiro8d990262020-11-30 18:12:11 +09001136 files[i]);
Masami Hiramatsu3e6f8102022-02-16 15:16:12 +09001137 else
1138 log_info("Applying capsule %ls succeeded.\n",
1139 files[i]);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001140
Masami Hiramatsu5d49b322021-11-12 22:05:15 +09001141 /* create CapsuleXXXX */
1142 set_capsule_result(index, capsule, ret);
1143
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001144 free(capsule);
1145 } else {
Heinrich Schuchardt3e491192021-07-10 11:03:27 +02001146 log_err("Reading capsule %ls failed\n", files[i]);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001147 }
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001148 /* delete a capsule either in case of success or failure */
1149 ret = efi_capsule_delete_file(files[i]);
1150 if (ret != EFI_SUCCESS)
Heinrich Schuchardt3e491192021-07-10 11:03:27 +02001151 log_err("Deleting capsule %ls failed\n",
AKASHI Takahiro8d990262020-11-30 18:12:11 +09001152 files[i]);
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001153 }
1154 efi_capsule_scan_done();
1155
1156 for (i = 0; i < nfiles; i++)
1157 free(files[i]);
1158 free(files);
1159
Masami Hiramatsu3e6f8102022-02-16 15:16:12 +09001160 /*
1161 * UEFI spec requires to reset system after complete processing capsule
1162 * update on the storage.
1163 */
Masami Hiramatsu7660cfe2022-03-21 22:37:56 +09001164 log_info("Reboot after firmware update.\n");
Masami Hiramatsu3e6f8102022-02-16 15:16:12 +09001165 /* Cold reset is required for loading the new firmware. */
Masami Hiramatsu7660cfe2022-03-21 22:37:56 +09001166 sysreset_walk_halt(SYSRESET_COLD);
Masami Hiramatsu3e6f8102022-02-16 15:16:12 +09001167 hang();
1168 /* not reach here */
1169
1170 return 0;
AKASHI Takahiroc74cd8b2020-11-17 09:27:56 +09001171}
1172#endif /* CONFIG_EFI_CAPSULE_ON_DISK */