blob: b6bd2d6af88250489ce82c22bbbc8150423ef635 [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
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090011#include <common.h>
12#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>
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +090017#include <hang.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090018#include <malloc.h>
AKASHI Takahiro45b819542020-11-17 09:27:56 +090019#include <mapmem.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090020#include <sort.h>
Masami Hiramatsuff744862022-03-21 22:37:56 +090021#include <sysreset.h>
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +090022#include <asm/global_data.h>
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090023
Sughosh Ganu586bb982020-12-30 19:27:09 +053024#include <crypto/pkcs7.h>
25#include <crypto/pkcs7_parser.h>
26#include <linux/err.h>
27
AKASHI Takahirob71a0ae2021-10-07 15:23:32 +090028DECLARE_GLOBAL_DATA_PTR;
29
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090030const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
AKASHI Takahiro0d963782020-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 Takahiro473d9b32020-11-17 09:27:55 +090035
AKASHI Takahiro45b819542020-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 Takahiro473d9b32020-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 Schuchardt812f6e02021-02-09 20:20:34 +010054 char value[5];
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090055 efi_uintn_t size;
56 unsigned long index = 0xffff;
57 efi_status_t ret;
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010058 int i;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090059
60 size = sizeof(value16);
Simon Glass90975372022-01-23 12:55:12 -070061 ret = efi_get_variable_int(u"CapsuleLast", &efi_guid_capsule_report,
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090062 NULL, &size, value16, NULL);
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010063 if (ret != EFI_SUCCESS || size != 22 ||
Simon Glass90975372022-01-23 12:55:12 -070064 u16_strncmp(value16, u"Capsule", 7))
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090065 goto err;
Heinrich Schuchardt812f6e02021-02-09 20:20:34 +010066 for (i = 0; i < 4; ++i) {
67 u16 c = value16[i + 7];
AKASHI Takahiro473d9b32020-11-17 09:27:55 +090068
Heinrich Schuchardt812f6e02021-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 Takahiro473d9b32020-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 Apalodimas21575292020-12-31 12:26:46 +020097 efi_create_indexed_name(variable_name16, sizeof(variable_name16),
98 "Capsule", index);
AKASHI Takahiro473d9b32020-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 Schuchardt24adaa72021-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 Schuchardtb1fae8c2021-07-10 11:14:13 +0200112 if (ret != EFI_SUCCESS) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200113 log_err("Setting %ls failed\n", variable_name16);
Heinrich Schuchardtb1fae8c2021-07-10 11:14:13 +0200114 return;
115 }
116
117 /* Variable CapsuleLast must not include terminating 0x0000 */
Simon Glass90975372022-01-23 12:55:12 -0700118 ret = efi_set_variable_int(u"CapsuleLast", &efi_guid_capsule_report,
Heinrich Schuchardtb1fae8c2021-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 Glass90975372022-01-23 12:55:12 -0700125 log_err("Setting %ls failed\n", u"CapsuleLast");
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900126}
127
AKASHI Takahiro0d963782020-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 Ganuf55c6b62022-04-15 11:29:36 +0530132 * @image_index: Image Index
AKASHI Takahiro0d963782020-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 Ganuf55c6b62022-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 Takahiro0d963782020-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 Ganuf55c6b62022-04-15 11:29:36 +0530208 (desc->image_index == image_index) &&
AKASHI Takahiro0d963782020-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 Takahiro920671c2021-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 Ganu586bb982020-12-30 19:27:09 +0530262#if defined(CONFIG_EFI_CAPSULE_AUTHENTICATE)
AKASHI Takahirof155bf52021-11-02 09:55:01 +0900263int efi_get_public_key_data(void **pkey, efi_uintn_t *pkey_len)
AKASHI Takahirob71a0ae2021-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 Ganu586bb982020-12-30 19:27:09 +0530294
Sughosh Ganu586bb982020-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 Glass1f78c122021-08-02 08:44:31 -0600300 void *fdt_pkey, *pkey;
Sughosh Ganu586bb982020-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 Takahiro920671c2021-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)
Sughosh Ganu586bb982020-12-30 19:27:09 +0530321 goto out;
322
AKASHI Takahiro920671c2021-07-20 14:52:05 +0900323 auth_hdr = (struct efi_firmware_image_authentication *)capsule;
Sughosh Ganu586bb982020-12-30 19:27:09 +0530324 if (guidcmp(&auth_hdr->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
325 goto out;
326
Sughosh Ganu586bb982020-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 Glass1f78c122021-08-02 08:44:31 -0600353 ret = efi_get_public_key_data(&fdt_pkey, &pkey_len);
Sughosh Ganu586bb982020-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 Glass1f78c122021-08-02 08:44:31 -0600361 memcpy(pkey, fdt_pkey, pkey_len);
Sughosh Ganu586bb982020-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 Takahiro0d963782020-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 Takahiro920671c2021-07-20 14:52:05 +0900406 size_t capsule_size, image_binary_size;
AKASHI Takahiro0d963782020-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 Schuchardte3087a12021-07-10 11:03:27 +0200442 log_err("Capsule does not have enough data\n");
AKASHI Takahiro0d963782020-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 Takahiro0d963782020-11-30 18:12:11 +0900455 fmp = efi_fmp_find(&image->update_image_type_id,
Sughosh Ganuf55c6b62022-04-15 11:29:36 +0530456 image->update_image_index,
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900457 image->update_hardware_instance,
458 handles, no_handles);
459 if (!fmp) {
Heinrich Schuchardt282249d2022-01-16 14:15:31 +0100460 log_err("FMP driver not found for firmware type %pUs, hardware instance %lld\n",
AKASHI Takahiro0d963782020-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 Takahiro920671c2021-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 Takahiro0d963782020-11-30 18:12:11 +0900476 image_binary = (void *)image + sizeof(*image);
AKASHI Takahiro920671c2021-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 Takahiro0d963782020-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 Takahiro920671c2021-07-20 14:52:05 +0900491 image_binary_size,
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900492 vendor_code, NULL,
493 &abort_reason));
494 if (ret != EFI_SUCCESS) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200495 log_err("Firmware update failed: %ls\n",
AKASHI Takahiro0d963782020-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 Takahiro473d9b32020-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 Glass83698b22021-02-07 14:27:02 -0700537 EFI_ENTRY("%p, %zu, %llu\n", capsule_header_array, capsule_count,
AKASHI Takahiro473d9b32020-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 Takahiro0d963782020-11-30 18:12:11 +0900545 ret = EFI_SUCCESS;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900546 for (i = 0, capsule = *capsule_header_array; i < capsule_count;
547 i++, capsule = *(++capsule_header_array)) {
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900548 /* sanity check */
549 if (capsule->header_size < sizeof(*capsule) ||
550 capsule->capsule_image_size < sizeof(*capsule)) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200551 log_err("Capsule does not have enough data\n");
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900552 continue;
553 }
554
Heinrich Schuchardt282249d2022-01-16 14:15:31 +0100555 log_debug("Capsule[%d] (guid:%pUs)\n",
AKASHI Takahiro0d963782020-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 Schuchardt282249d2022-01-16 14:15:31 +0100561 log_err("Unsupported capsule type: %pUs\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900562 &capsule->capsule_guid);
563 ret = EFI_UNSUPPORTED;
564 }
565
566 if (ret != EFI_SUCCESS)
567 goto out;
AKASHI Takahiro473d9b32020-11-17 09:27:55 +0900568 }
Jose Marinhoebb61ee2021-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 Schuchardte3087a12021-07-10 11:03:27 +0200574 log_warning("ESRT update failed\n");
Jose Marinhoebb61ee2021-03-02 17:26:38 +0000575 }
Jose Marinhoaf886ce2021-04-19 14:54:33 +0100576out:
Jose Marinhoebb61ee2021-03-02 17:26:38 +0000577
AKASHI Takahiro473d9b32020-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 Glass83698b22021-02-07 14:27:02 -0700605 EFI_ENTRY("%p, %zu, %p, %p\n", capsule_header_array, capsule_count,
AKASHI Takahiro473d9b32020-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 Takahiro45b819542020-11-17 09:27:56 +0900624
Masami Hiramatsud306caa2022-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;
Ilias Apalodimas8ac0ebe2022-10-06 16:08:46 +0300639 ret = efi_install_multiple_protocol_interfaces(&handle,
640 &efi_guid_firmware_management_protocol,
641 &efi_fmp_fit,
642 NULL);
Masami Hiramatsud306caa2022-03-21 22:37:45 +0900643 }
644
645 if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_RAW)) {
646 handle = NULL;
Ilias Apalodimas8ac0ebe2022-10-06 16:08:46 +0300647 ret = efi_install_multiple_protocol_interfaces(&handle,
648 &efi_guid_firmware_management_protocol,
649 &efi_fmp_raw,
650 NULL);
Masami Hiramatsud306caa2022-03-21 22:37:45 +0900651 }
652
653 return ret;
654}
655
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900656#ifdef CONFIG_EFI_CAPSULE_ON_DISK
657/**
658 * get_dp_device - retrieve a device path from boot variable
659 * @boot_var: Boot variable name
660 * @device_dp Device path
661 *
662 * Retrieve a device patch from boot variable, @boot_var.
663 *
664 * Return: status code
665 */
666static efi_status_t get_dp_device(u16 *boot_var,
667 struct efi_device_path **device_dp)
668{
669 void *buf = NULL;
670 efi_uintn_t size;
671 struct efi_load_option lo;
672 struct efi_device_path *file_dp;
673 efi_status_t ret;
674
675 size = 0;
676 ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
677 NULL, &size, NULL, NULL);
678 if (ret == EFI_BUFFER_TOO_SMALL) {
679 buf = malloc(size);
680 if (!buf)
681 return EFI_OUT_OF_RESOURCES;
682 ret = efi_get_variable_int(boot_var, &efi_global_variable_guid,
683 NULL, &size, buf, NULL);
684 }
685 if (ret != EFI_SUCCESS)
686 return ret;
687
688 efi_deserialize_load_option(&lo, buf, &size);
689
690 if (lo.attributes & LOAD_OPTION_ACTIVE) {
691 efi_dp_split_file_path(lo.file_path, device_dp, &file_dp);
692 efi_free_pool(file_dp);
693
694 ret = EFI_SUCCESS;
695 } else {
696 ret = EFI_NOT_FOUND;
697 }
698
699 free(buf);
700
701 return ret;
702}
703
704/**
705 * device_is_present_and_system_part - check if a device exists
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900706 *
707 * Check if a device pointed to by the device path, @dp, exists and is
708 * located in UEFI system partition.
709 *
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100710 * @dp device path
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900711 * Return: true - yes, false - no
712 */
713static bool device_is_present_and_system_part(struct efi_device_path *dp)
714{
715 efi_handle_t handle;
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100716 struct efi_device_path *rem;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900717
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100718 /* Check device exists */
Heinrich Schuchardt0a04a412022-03-19 06:35:43 +0100719 handle = efi_dp_find_obj(dp, NULL, NULL);
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900720 if (!handle)
721 return false;
722
Heinrich Schuchardta76fc032022-03-05 00:36:50 +0100723 /* Check device is on system partition */
724 handle = efi_dp_find_obj(dp, &efi_system_partition_guid, &rem);
725 if (!handle)
726 return false;
727
728 return true;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900729}
730
731/**
732 * find_boot_device - identify the boot device
733 *
734 * Identify the boot device from boot-related variables as UEFI
735 * specification describes and put its handle into bootdev_root.
736 *
737 * Return: status code
738 */
739static efi_status_t find_boot_device(void)
740{
741 char boot_var[9];
742 u16 boot_var16[9], *p, bootnext, *boot_order = NULL;
743 efi_uintn_t size;
744 int i, num;
745 struct efi_simple_file_system_protocol *volume;
746 struct efi_device_path *boot_dev = NULL;
747 efi_status_t ret;
748
749 /* find active boot device in BootNext */
750 bootnext = 0;
751 size = sizeof(bootnext);
Simon Glass90975372022-01-23 12:55:12 -0700752 ret = efi_get_variable_int(u"BootNext",
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900753 (efi_guid_t *)&efi_global_variable_guid,
754 NULL, &size, &bootnext, NULL);
755 if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
756 /* BootNext does exist here */
757 if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) {
AKASHI Takahiro0d963782020-11-30 18:12:11 +0900758 log_err("BootNext must be 16-bit integer\n");
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900759 goto skip;
760 }
761 sprintf((char *)boot_var, "Boot%04X", bootnext);
762 p = boot_var16;
763 utf8_utf16_strcpy(&p, boot_var);
764
765 ret = get_dp_device(boot_var16, &boot_dev);
766 if (ret == EFI_SUCCESS) {
767 if (device_is_present_and_system_part(boot_dev)) {
Masami Hiramatsu10165752021-07-12 18:05:17 +0900768 goto found;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900769 } else {
770 efi_free_pool(boot_dev);
771 boot_dev = NULL;
772 }
773 }
774 }
775
776skip:
777 /* find active boot device in BootOrder */
778 size = 0;
Simon Glass90975372022-01-23 12:55:12 -0700779 ret = efi_get_variable_int(u"BootOrder", &efi_global_variable_guid,
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900780 NULL, &size, NULL, NULL);
781 if (ret == EFI_BUFFER_TOO_SMALL) {
782 boot_order = malloc(size);
783 if (!boot_order) {
784 ret = EFI_OUT_OF_RESOURCES;
785 goto out;
786 }
787
Simon Glass90975372022-01-23 12:55:12 -0700788 ret = efi_get_variable_int(u"BootOrder",
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900789 &efi_global_variable_guid,
790 NULL, &size, boot_order, NULL);
791 }
792 if (ret != EFI_SUCCESS)
793 goto out;
794
795 /* check in higher order */
796 num = size / sizeof(u16);
797 for (i = 0; i < num; i++) {
798 sprintf((char *)boot_var, "Boot%04X", boot_order[i]);
799 p = boot_var16;
800 utf8_utf16_strcpy(&p, boot_var);
801 ret = get_dp_device(boot_var16, &boot_dev);
802 if (ret != EFI_SUCCESS)
803 continue;
804
805 if (device_is_present_and_system_part(boot_dev))
806 break;
807
808 efi_free_pool(boot_dev);
809 boot_dev = NULL;
810 }
Masami Hiramatsu10165752021-07-12 18:05:17 +0900811found:
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900812 if (boot_dev) {
Masami Hiramatsud9763bb2021-07-14 14:19:13 +0900813 log_debug("Boot device %pD\n", boot_dev);
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900814
815 volume = efi_fs_from_path(boot_dev);
816 if (!volume)
817 ret = EFI_DEVICE_ERROR;
818 else
819 ret = EFI_CALL(volume->open_volume(volume,
820 &bootdev_root));
821 efi_free_pool(boot_dev);
822 } else {
823 ret = EFI_NOT_FOUND;
824 }
AKASHI Takahirofa390e62021-04-20 10:03:16 +0900825out:
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900826 free(boot_order);
827
828 return ret;
829}
830
831/**
832 * efi_capsule_scan_dir - traverse a capsule directory in boot device
833 * @files: Array of file names
834 * @num: Number of elements in @files
835 *
836 * Traverse a capsule directory in boot device.
837 * Called by initialization code, and returns an array of capsule file
838 * names in @files.
839 *
840 * Return: status code
841 */
842static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num)
843{
844 struct efi_file_handle *dirh;
845 struct efi_file_info *dirent;
846 efi_uintn_t dirent_size, tmp_size;
847 unsigned int count;
848 u16 **tmp_files;
849 efi_status_t ret;
850
851 ret = find_boot_device();
852 if (ret == EFI_NOT_FOUND) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +0200853 log_debug("Boot device is not set\n");
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900854 *num = 0;
855 return EFI_SUCCESS;
856 } else if (ret != EFI_SUCCESS) {
857 return EFI_DEVICE_ERROR;
858 }
859
860 /* count capsule files */
861 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
862 EFI_CAPSULE_DIR,
863 EFI_FILE_MODE_READ, 0));
864 if (ret != EFI_SUCCESS) {
865 *num = 0;
866 return EFI_SUCCESS;
867 }
868
869 dirent_size = 256;
870 dirent = malloc(dirent_size);
871 if (!dirent)
872 return EFI_OUT_OF_RESOURCES;
873
874 count = 0;
875 while (1) {
876 tmp_size = dirent_size;
877 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
878 if (ret == EFI_BUFFER_TOO_SMALL) {
Heinrich Schuchardtaa27e5d2021-04-11 06:53:04 +0200879 struct efi_file_info *old_dirent = dirent;
880
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900881 dirent = realloc(dirent, tmp_size);
882 if (!dirent) {
Heinrich Schuchardtaa27e5d2021-04-11 06:53:04 +0200883 dirent = old_dirent;
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900884 ret = EFI_OUT_OF_RESOURCES;
885 goto err;
886 }
887 dirent_size = tmp_size;
888 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
889 }
890 if (ret != EFI_SUCCESS)
891 goto err;
892 if (!tmp_size)
893 break;
894
Heinrich Schuchardt76b708a2021-02-09 17:45:33 +0100895 if (!(dirent->attribute & EFI_FILE_DIRECTORY))
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900896 count++;
897 }
898
899 ret = EFI_CALL((*dirh->setpos)(dirh, 0));
900 if (ret != EFI_SUCCESS)
901 goto err;
902
903 /* make a list */
AKASHI Takahiroc8fc12f2021-01-22 10:43:27 +0900904 tmp_files = malloc(count * sizeof(*tmp_files));
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900905 if (!tmp_files) {
906 ret = EFI_OUT_OF_RESOURCES;
907 goto err;
908 }
909
910 count = 0;
911 while (1) {
912 tmp_size = dirent_size;
913 ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
914 if (ret != EFI_SUCCESS)
915 goto err;
916 if (!tmp_size)
917 break;
918
919 if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
Simon Glass90975372022-01-23 12:55:12 -0700920 u16_strcmp(dirent->file_name, u".") &&
921 u16_strcmp(dirent->file_name, u".."))
AKASHI Takahiro45b819542020-11-17 09:27:56 +0900922 tmp_files[count++] = u16_strdup(dirent->file_name);
923 }
924 /* ignore an error */
925 EFI_CALL((*dirh->close)(dirh));
926
927 /* in ascii order */
928 /* FIXME: u16 version of strcasecmp */
929 qsort(tmp_files, count, sizeof(*tmp_files),
930 (int (*)(const void *, const void *))strcasecmp);
931 *files = tmp_files;
932 *num = count;
933 ret = EFI_SUCCESS;
934err:
935 free(dirent);
936
937 return ret;
938}
939
940/**
941 * efi_capsule_read_file - read in a capsule file
942 * @filename: File name
943 * @capsule: Pointer to buffer for capsule
944 *
945 * Read a capsule file and put its content in @capsule.
946 *
947 * Return: status code
948 */
949static efi_status_t efi_capsule_read_file(const u16 *filename,
950 struct efi_capsule_header **capsule)
951{
952 struct efi_file_handle *dirh, *fh;
953 struct efi_file_info *file_info = NULL;
954 struct efi_capsule_header *buf = NULL;
955 efi_uintn_t size;
956 efi_status_t ret;
957
958 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
959 EFI_CAPSULE_DIR,
960 EFI_FILE_MODE_READ, 0));
961 if (ret != EFI_SUCCESS)
962 return ret;
963 ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
964 EFI_FILE_MODE_READ, 0));
965 /* ignore an error */
966 EFI_CALL((*dirh->close)(dirh));
967 if (ret != EFI_SUCCESS)
968 return ret;
969
970 /* file size */
971 size = 0;
972 ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
973 &size, file_info));
974 if (ret == EFI_BUFFER_TOO_SMALL) {
975 file_info = malloc(size);
976 if (!file_info) {
977 ret = EFI_OUT_OF_RESOURCES;
978 goto err;
979 }
980 ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
981 &size, file_info));
982 }
983 if (ret != EFI_SUCCESS)
984 goto err;
985 size = file_info->file_size;
986 free(file_info);
987 buf = malloc(size);
988 if (!buf) {
989 ret = EFI_OUT_OF_RESOURCES;
990 goto err;
991 }
992
993 /* fetch data */
994 ret = EFI_CALL((*fh->read)(fh, &size, buf));
995 if (ret == EFI_SUCCESS) {
996 if (size >= buf->capsule_image_size) {
997 *capsule = buf;
998 } else {
999 free(buf);
1000 ret = EFI_INVALID_PARAMETER;
1001 }
1002 } else {
1003 free(buf);
1004 }
1005err:
1006 EFI_CALL((*fh->close)(fh));
1007
1008 return ret;
1009}
1010
1011/**
1012 * efi_capsule_delete_file - delete a capsule file
1013 * @filename: File name
1014 *
1015 * Delete a capsule file from capsule directory.
1016 *
1017 * Return: status code
1018 */
1019static efi_status_t efi_capsule_delete_file(const u16 *filename)
1020{
1021 struct efi_file_handle *dirh, *fh;
1022 efi_status_t ret;
1023
1024 ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
1025 EFI_CAPSULE_DIR,
1026 EFI_FILE_MODE_READ, 0));
1027 if (ret != EFI_SUCCESS)
1028 return ret;
1029 ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename,
1030 EFI_FILE_MODE_READ, 0));
1031 /* ignore an error */
1032 EFI_CALL((*dirh->close)(dirh));
1033
Heinrich Schuchardte5c22812021-06-02 19:28:22 +02001034 if (ret == EFI_SUCCESS)
1035 ret = EFI_CALL((*fh->delete)(fh));
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001036
1037 return ret;
1038}
1039
1040/**
1041 * efi_capsule_scan_done - reset a scan help function
1042 *
1043 * Reset a scan help function
1044 */
1045static void efi_capsule_scan_done(void)
1046{
1047 EFI_CALL((*bootdev_root->close)(bootdev_root));
1048 bootdev_root = NULL;
1049}
1050
1051/**
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001052 * check_run_capsules() - check whether capsule update should run
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001053 *
1054 * The spec says OsIndications must be set in order to run the capsule update
1055 * on-disk. Since U-Boot doesn't support runtime SetVariable, allow capsules to
1056 * run explicitly if CONFIG_EFI_IGNORE_OSINDICATIONS is selected
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001057 *
1058 * Return: EFI_SUCCESS if update to run, EFI_NOT_FOUND otherwise
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001059 */
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001060static efi_status_t check_run_capsules(void)
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001061{
Sughosh Ganu0f5ca5c2022-06-01 23:30:39 +05301062 u64 os_indications = 0x0;
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001063 efi_uintn_t size;
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001064 efi_status_t r;
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001065
1066 size = sizeof(os_indications);
Simon Glass90975372022-01-23 12:55:12 -07001067 r = efi_get_variable_int(u"OsIndications", &efi_global_variable_guid,
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001068 NULL, &size, &os_indications, NULL);
Sughosh Ganu0f5ca5c2022-06-01 23:30:39 +05301069 if (!IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS) &&
1070 (r != EFI_SUCCESS || size != sizeof(os_indications)))
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001071 return EFI_NOT_FOUND;
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001072
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001073 if (os_indications &
1074 EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) {
1075 os_indications &=
1076 ~EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
Simon Glass90975372022-01-23 12:55:12 -07001077 r = efi_set_variable_int(u"OsIndications",
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001078 &efi_global_variable_guid,
1079 EFI_VARIABLE_NON_VOLATILE |
1080 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1081 EFI_VARIABLE_RUNTIME_ACCESS,
1082 sizeof(os_indications),
1083 &os_indications, false);
1084 if (r != EFI_SUCCESS)
1085 log_err("Setting %ls failed\n", L"OsIndications");
1086 return EFI_SUCCESS;
1087 } else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) {
1088 return EFI_SUCCESS;
Sughosh Ganu0f5ca5c2022-06-01 23:30:39 +05301089 } else {
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001090 return EFI_NOT_FOUND;
1091 }
Ilias Apalodimasa38d0cb2021-06-29 07:55:51 +03001092}
1093
1094/**
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001095 * efi_launch_capsule - launch capsules
1096 *
1097 * Launch all the capsules in system at boot time.
1098 * Called by efi init code
1099 *
1100 * Return: status codde
1101 */
1102efi_status_t efi_launch_capsules(void)
1103{
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001104 struct efi_capsule_header *capsule = NULL;
1105 u16 **files;
1106 unsigned int nfiles, index, i;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001107 efi_status_t ret;
1108
Heinrich Schuchardte9e84992021-11-20 11:53:12 +01001109 if (check_run_capsules() != EFI_SUCCESS)
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001110 return EFI_SUCCESS;
1111
1112 index = get_last_capsule();
1113
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001114 /*
1115 * Find capsules on disk.
1116 * All the capsules are collected at the beginning because
1117 * capsule files will be removed instantly.
1118 */
1119 nfiles = 0;
1120 files = NULL;
1121 ret = efi_capsule_scan_dir(&files, &nfiles);
1122 if (ret != EFI_SUCCESS)
1123 return ret;
1124 if (!nfiles)
1125 return EFI_SUCCESS;
1126
1127 /* Launch capsules */
1128 for (i = 0, ++index; i < nfiles; i++, index++) {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001129 log_debug("Applying %ls\n", files[i]);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001130 if (index > 0xffff)
1131 index = 0;
1132 ret = efi_capsule_read_file(files[i], &capsule);
1133 if (ret == EFI_SUCCESS) {
Masami Hiramatsu3454a692022-02-16 15:15:42 +09001134 ret = efi_capsule_update_firmware(capsule);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001135 if (ret != EFI_SUCCESS)
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001136 log_err("Applying capsule %ls failed.\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +09001137 files[i]);
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001138 else
1139 log_info("Applying capsule %ls succeeded.\n",
1140 files[i]);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001141
Masami Hiramatsu1001a102021-11-12 22:05:15 +09001142 /* create CapsuleXXXX */
1143 set_capsule_result(index, capsule, ret);
1144
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001145 free(capsule);
1146 } else {
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001147 log_err("Reading capsule %ls failed\n", files[i]);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001148 }
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001149 /* delete a capsule either in case of success or failure */
1150 ret = efi_capsule_delete_file(files[i]);
1151 if (ret != EFI_SUCCESS)
Heinrich Schuchardte3087a12021-07-10 11:03:27 +02001152 log_err("Deleting capsule %ls failed\n",
AKASHI Takahiro0d963782020-11-30 18:12:11 +09001153 files[i]);
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001154 }
1155 efi_capsule_scan_done();
1156
1157 for (i = 0; i < nfiles; i++)
1158 free(files[i]);
1159 free(files);
1160
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001161 /*
1162 * UEFI spec requires to reset system after complete processing capsule
1163 * update on the storage.
1164 */
Masami Hiramatsuff744862022-03-21 22:37:56 +09001165 log_info("Reboot after firmware update.\n");
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001166 /* Cold reset is required for loading the new firmware. */
Masami Hiramatsuff744862022-03-21 22:37:56 +09001167 sysreset_walk_halt(SYSRESET_COLD);
Masami Hiramatsu4b2f8c12022-02-16 15:16:12 +09001168 hang();
1169 /* not reach here */
1170
1171 return 0;
AKASHI Takahiro45b819542020-11-17 09:27:56 +09001172}
1173#endif /* CONFIG_EFI_CAPSULE_ON_DISK */