From: AKASHI Takahiro <takahiro.akashi@linaro.org>
To: u-boot@lists.denx.de
Subject: [PATCH 04/10] efi_loader: capsule: add capsule_on_disk support
Date: Tue, 28 Apr 2020 09:28:03 +0900 [thread overview]
Message-ID: <20200428002803.GD16947@laputa> (raw)
In-Reply-To: <3121b167-e8e9-d7fd-73ac-5ea7b2f6140d@gmx.de>
Heinrich,
On Mon, Apr 27, 2020 at 10:28:35PM +0200, Heinrich Schuchardt wrote:
> On 4/27/20 11:48 AM, AKASHI Takahiro wrote:
> > Capsule data can be loaded into the system either via UpdateCapsule
> > runtime service or files on a file system (of boot device).
> > The latter case is called "capsules on disk", and actual updates will
> > take place at the next boot time.
> >
> > In this commit, we will support capsule on disk mechanism.
> >
> > Please note that U-Boot itself has no notion of "boot device" and
> > all the capsule files to be executed will be detected only if they
> > are located in a specific directory, \EFI\UpdateCapsule, on a device
> > that is identified as a boot device by "BootXXXX" variables.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> > common/main.c | 4 +
> > include/efi_loader.h | 16 ++
> > lib/efi_loader/Kconfig | 22 ++
> > lib/efi_loader/efi_capsule.c | 449 +++++++++++++++++++++++++++++++++++
> > lib/efi_loader/efi_setup.c | 9 +
> > 5 files changed, 500 insertions(+)
> >
> > diff --git a/common/main.c b/common/main.c
> > index 06d7ff56d60c..877ae63b708d 100644
> > --- a/common/main.c
> > +++ b/common/main.c
> > @@ -14,6 +14,7 @@
> > #include <env.h>
> > #include <init.h>
> > #include <version.h>
> > +#include <efi_loader.h>
> >
> > static void run_preboot_environment_command(void)
> > {
> > @@ -51,6 +52,9 @@ void main_loop(void)
> > if (IS_ENABLED(CONFIG_UPDATE_TFTP))
> > update_tftp(0UL, NULL, NULL);
> >
> > + if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))
> > + efi_launch_capsules();
> > +
>
> Can't we move this to efi_init_obj_list() and do away with
> CONFIG_EFI_CAPSULE_ON_DISK_EARLY?
With CONFIG_EFI_CAPSULE_ON_DISK_EARLY disabled,
efi_launch_capsules() will be called in efi_init_obj_list()
as you expect. See the code below in efi_setup.c.
> > s = bootdelay_process();
> > if (cli_process_fdt(&s))
> > cli_secure_boot_cmd(s);
> > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > index 19ffc027c171..d49ebcad53ec 100644
> > --- a/include/efi_loader.h
> > +++ b/include/efi_loader.h
> > @@ -793,6 +793,18 @@ efi_status_t EFIAPI efi_query_capsule_caps(
> > u32 *reset_type);
> > #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */
> >
> > +#ifdef CONFIG_EFI_CAPSULE_ON_DISK
> > +#define EFI_CAPSULE_DIR L"\\EFI\\UpdateCapsule\\"
> > +
> > +/* Hook at initialization */
> > +efi_status_t efi_launch_capsules(void);
> > +#else
> > +static inline efi_status_t efi_launch_capsules(void)
> > +{
> > + return EFI_SUCCESS;
> > +}
> > +#endif /* CONFIG_EFI_CAPSULE_ON_DISK */
> > +
> > #else /* CONFIG_IS_ENABLED(EFI_LOADER) */
> >
> > /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
> > @@ -809,6 +821,10 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr,
> > const char *path) { }
> > static inline void efi_net_set_dhcp_ack(void *pkt, int len) { }
> > static inline void efi_print_image_infos(void *pc) { }
> > +static inline efi_status_t efi_launch_capsules(void)
> > +{
> > + return EFI_SUCCESS;
> > +}
> >
> > #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */
> >
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index e2b08251f26a..b48b95a32e03 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -56,6 +56,28 @@ config EFI_RUNTIME_UPDATE_CAPSULE
> > Select this option if you want to use UpdateCapsule and
> > QueryCapsuleCapabilities API's.
> >
> > +config EFI_CAPSULE_ON_DISK
> > + bool "Enable capsule-on-disk support"
> > + select EFI_HAVE_CAPSULE_SUPPORT
> > + default n
> > + help
> > + Select this option if you want to use capsule-on-disk feature,
> > + that is, capsules can be fetched and executed from files
> > + under a specific directory on UEFI system partition instead of
> > + via UpdateCapsule API.
> > +
> > +config EFI_CAPSULE_ON_DISK_EARLY
> > + bool "Initiate capsule-on-disk at U-Boot boottime"
> > + depends on EFI_CAPSULE_ON_DISK
> > + default y
> > + select EFI_SETUP_EARLY
> > + help
> > + Normally, without this option enabled, capsules will be
> > + executed only at the first time of invoking one of efi command.
> > + If this option is enabled, capsules will be enforced to be
> > + executed as part of U-Boot initialisation so that they will
> > + surely take place whatever is set to distro_bootcmd.
>
> Why do we need this Kconfig variable if we have EFI_SETUP_EARLY available?
Good point.
My intent here was to split efi_launch_capsules() from
efi_init_obj_list() so that users can start UEFI early
for some reason without enabling capsule feature in the future.
EFI_SETUP_EARLY is the hook for that.
> > +
> > config EFI_DEVICE_PATH_TO_TEXT
> > bool "Device path to text protocol"
> > default y
> > diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
> > index fb104bb92a6c..938129a41934 100644
> > --- a/lib/efi_loader/efi_capsule.c
> > +++ b/lib/efi_loader/efi_capsule.c
> > @@ -10,10 +10,16 @@
> > #include <efi_loader.h>
> > #include <fs.h>
> > #include <malloc.h>
> > +#include <mapmem.h>
> > #include <sort.h>
> >
> > const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
> >
> > +#ifdef CONFIG_EFI_CAPSULE_ON_DISK
> > +/* for file system access */
> > +static struct efi_file_handle *bootdev_root;
> > +#endif
> > +
> > static __maybe_unused int get_last_capsule(void)
> > {
> > u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */
> > @@ -151,3 +157,446 @@ efi_status_t EFIAPI efi_query_capsule_caps(
> > out:
> > return EFI_EXIT(ret);
> > }
> > +
> > +#ifdef CONFIG_EFI_CAPSULE_ON_DISK
> > +static efi_status_t get_dp_device(u16 *boot_var,
> > + struct efi_device_path **device_dp)
> > +{
> > + void *buf = NULL;
> > + efi_uintn_t size;
> > + struct efi_load_option lo;
> > + struct efi_device_path *file_dp;
> > + efi_status_t ret;
> > +
> > + size = 0;
> > + ret = EFI_CALL(efi_get_variable(boot_var, &efi_global_variable_guid,
> > + NULL, &size, NULL));
> > + if (ret == EFI_BUFFER_TOO_SMALL) {
> > + buf = malloc(size);
> > + if (!buf)
> > + return EFI_OUT_OF_RESOURCES;
> > + ret = EFI_CALL(efi_get_variable(boot_var,
> > + &efi_global_variable_guid,
> > + NULL, &size, buf));
> > + }
> > + if (ret != EFI_SUCCESS)
> > + return ret;
> > +
> > + efi_deserialize_load_option(&lo, buf);
> > +
> > + if (lo.attributes & LOAD_OPTION_ACTIVE) {
> > + efi_dp_split_file_path(lo.file_path, device_dp, &file_dp);
> > + efi_free_pool(file_dp);
> > +
> > + ret = EFI_SUCCESS;
> > + } else {
> > + ret = EFI_NOT_FOUND;
> > + }
> > +
> > + free(buf);
> > +
> > + return ret;
> > +}
> > +
> > +static bool device_is_present_and_system_part(struct efi_device_path *dp)
> > +{
> > + efi_handle_t handle;
> > +
> > + handle = efi_dp_find_obj(dp, NULL);
> > + if (!handle)
> > + return false;
> > +
> > + return efi_disk_is_system_part(handle);
> > +}
> > +
> > +static efi_status_t find_boot_device(void)
> > +{
> > + char boot_var[9];
> > + u16 boot_var16[9], *p, bootnext, *boot_order = NULL;
> > + efi_uintn_t size;
> > + int i, num;
> > + struct efi_simple_file_system_protocol *volume;
> > + struct efi_device_path *boot_dev = NULL;
> > + efi_status_t ret;
> > +
> > + /* find active boot device in BootNext */
> > + bootnext = 0;
> > + size = sizeof(bootnext);
> > + ret = EFI_CALL(efi_get_variable(L"BootNext",
> > + (efi_guid_t *)&efi_global_variable_guid,
> > + NULL, &size, &bootnext));
> > + if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
> > + /* BootNext does exist here */
> > + if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) {
> > + printf("BootNext must be 16-bit integer\n");
> > + goto skip;
> > + }
> > + sprintf((char *)boot_var, "Boot%04X", bootnext);
> > + p = boot_var16;
> > + utf8_utf16_strcpy(&p, boot_var);
> > +
> > + ret = get_dp_device(boot_var16, &boot_dev);
> > + if (ret == EFI_SUCCESS) {
> > + if (device_is_present_and_system_part(boot_dev)) {
> > + goto out;
> > + } else {
> > + efi_free_pool(boot_dev);
> > + boot_dev = NULL;
> > + }
> > + }
> > + }
> > +
> > +skip:
> > + /* find active boot device in BootOrder */
> > + size = 0;
> > + ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
> > + NULL, &size, NULL));
> > + if (ret == EFI_BUFFER_TOO_SMALL) {
> > + boot_order = malloc(size);
> > + if (!boot_order) {
> > + ret = EFI_OUT_OF_RESOURCES;
> > + goto out;
> > + }
> > +
> > + ret = EFI_CALL(efi_get_variable(
> > + L"BootOrder", &efi_global_variable_guid,
> > + NULL, &size, boot_order));
> > + }
> > + if (ret != EFI_SUCCESS)
> > + goto out;
> > +
> > + /* check in higher order */
> > + num = size / sizeof(u16);
> > + for (i = 0; i < num; i++) {
> > + sprintf((char *)boot_var, "Boot%04X", boot_order[i]);
> > + p = boot_var16;
> > + utf8_utf16_strcpy(&p, boot_var);
> > + ret = get_dp_device(boot_var16, &boot_dev);
> > + if (ret != EFI_SUCCESS)
> > + continue;
> > +
> > + if (device_is_present_and_system_part(boot_dev))
> > + break;
> > +
> > + efi_free_pool(boot_dev);
> > + boot_dev = NULL;
> > + }
> > +out:
> > + if (boot_dev) {
> > + u16 *path_str;
> > +
> > + path_str = efi_dp_str(boot_dev);
> > + EFI_PRINT("EFI Capsule: bootdev is %ls\n", path_str);
> > + efi_free_pool(path_str);
> > +
> > + volume = efi_fs_from_path(boot_dev);
> > + if (!volume)
> > + ret = EFI_DEVICE_ERROR;
> > + else
> > + ret = EFI_CALL(volume->open_volume(volume,
> > + &bootdev_root));
> > + efi_free_pool(boot_dev);
> > + } else {
> > + ret = EFI_NOT_FOUND;
> > + }
> > + free(boot_order);
> > +
> > + return ret;
> > +}
> > +
> > +/*
> > + * Traverse a capsule directory in boot device
> > + * Called by initialization code, and returns an array of capsule file
> > + * names in @files
> > + */
> > +static efi_status_t efi_capsule_scan_dir(u16 ***files, int *num)
> > +{
> > + struct efi_file_handle *dirh;
> > + struct efi_file_info *dirent;
> > + efi_uintn_t dirent_size, tmp_size;
> > + int count;
> > + u16 **tmp_files;
> > + efi_status_t ret;
> > +
> > + ret = find_boot_device();
> > + if (ret == EFI_NOT_FOUND) {
> > + EFI_PRINT("EFI Capsule: bootdev is not set\n");
> > + *num = 0;
> > + return EFI_SUCCESS;
> > + } else if (ret != EFI_SUCCESS) {
> > + return EFI_DEVICE_ERROR;
> > + }
> > +
> > + /* count capsule files */
> > + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
> > + EFI_CAPSULE_DIR,
> > + EFI_FILE_MODE_READ, 0));
> > + if (ret != EFI_SUCCESS) {
> > + *num = 0;
> > + return EFI_SUCCESS;
> > + }
> > +
> > + dirent_size = 256;
> > + dirent = malloc(dirent_size);
> > + if (!dirent)
> > + return EFI_OUT_OF_RESOURCES;
> > +
> > + count = 0;
> > + while (1) {
> > + tmp_size = dirent_size;
> > + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
> > + if (ret == EFI_BUFFER_TOO_SMALL) {
> > + dirent = realloc(dirent, tmp_size);
> > + if (!dirent) {
> > + ret = EFI_OUT_OF_RESOURCES;
> > + goto err;
> > + }
> > + dirent_size = tmp_size;
> > + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
> > + }
> > + if (ret != EFI_SUCCESS)
> > + goto err;
> > + if (!tmp_size)
> > + break;
> > +
> > + if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
> > + u16_strcmp(dirent->file_name, L".") &&
> > + u16_strcmp(dirent->file_name, L".."))
> > + count++;
> > + }
> > +
> > + ret = EFI_CALL((*dirh->setpos)(dirh, 0));
> > + if (ret != EFI_SUCCESS)
> > + goto err;
> > +
> > + /* make a list */
> > + tmp_files = malloc(count * sizeof(*files));
> > + if (!tmp_files) {
> > + ret = EFI_OUT_OF_RESOURCES;
> > + goto err;
> > + }
> > +
> > + count = 0;
> > + while (1) {
> > + tmp_size = dirent_size;
> > + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent));
> > + if (ret != EFI_SUCCESS)
> > + goto err;
> > + if (!tmp_size)
> > + break;
> > +
> > + if (!(dirent->attribute & EFI_FILE_DIRECTORY) &&
> > + u16_strcmp(dirent->file_name, L".") &&
> > + u16_strcmp(dirent->file_name, L".."))
> > + tmp_files[count++] = u16_strdup(dirent->file_name);
> > + }
> > + /* ignore an error */
> > + EFI_CALL((*dirh->close)(dirh));
> > +
> > + /* in ascii order */
> > + /* FIXME: u16 version of strcasecmp */
> > + qsort(tmp_files, count, sizeof(*tmp_files),
> > + (int (*)(const void *, const void *))strcasecmp);
> > + *files = tmp_files;
> > + *num = count;
> > + ret = EFI_SUCCESS;
> > +err:
> > + free(dirent);
> > +
> > + return ret;
> > +}
> > +
> > +/*
> > + * Read in a capsule file
> > + */
> > +static efi_status_t efi_capsule_read_file(u16 *filename,
> > + struct efi_capsule_header **capsule)
> > +{
> > + struct efi_file_handle *dirh, *fh;
> > + struct efi_file_info *file_info = NULL;
> > + struct efi_capsule_header *buf = NULL;
> > + efi_uintn_t size;
> > + efi_status_t ret;
> > +
> > + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
> > + EFI_CAPSULE_DIR,
> > + EFI_FILE_MODE_READ, 0));
> > + if (ret != EFI_SUCCESS)
> > + return ret;
> > + ret = EFI_CALL((*dirh->open)(dirh, &fh, filename,
> > + EFI_FILE_MODE_READ, 0));
> > + /* ignore an error */
> > + EFI_CALL((*dirh->close)(dirh));
> > + if (ret != EFI_SUCCESS)
> > + return ret;
> > +
> > + /* file size */
> > + size = 0;
> > + ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
> > + &size, file_info));
> > + if (ret == EFI_BUFFER_TOO_SMALL) {
> > + file_info = malloc(size);
> > + if (!file_info) {
> > + ret = EFI_OUT_OF_RESOURCES;
> > + goto err;
> > + }
> > + ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid,
> > + &size, file_info));
> > + }
> > + if (ret != EFI_SUCCESS)
> > + goto err;
> > + size = file_info->file_size;
> > + free(file_info);
> > + buf = malloc(size);
> > + if (!buf) {
> > + ret = EFI_OUT_OF_RESOURCES;
> > + goto err;
> > + }
> > +
> > + /* fetch data */
> > + ret = EFI_CALL((*fh->read)(fh, &size, buf));
> > + if (ret == EFI_SUCCESS) {
> > + if (size >= buf->capsule_image_size) {
> > + *capsule = buf;
> > + } else {
> > + free(buf);
> > + ret = EFI_INVALID_PARAMETER;
> > + }
> > + } else {
> > + free(buf);
> > + }
> > +err:
> > + EFI_CALL((*fh->close)(fh));
> > +
> > + return ret;
> > +}
> > +
> > +static efi_status_t efi_capsule_delete_file(u16 *filename)
> > +{
> > + struct efi_file_handle *dirh, *fh;
> > + efi_status_t ret;
> > +
> > + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh,
> > + EFI_CAPSULE_DIR,
> > + EFI_FILE_MODE_READ, 0));
> > + if (ret != EFI_SUCCESS)
> > + return ret;
> > + ret = EFI_CALL((*dirh->open)(dirh, &fh, filename,
> > + EFI_FILE_MODE_READ, 0));
> > + /* ignore an error */
> > + EFI_CALL((*dirh->close)(dirh));
> > +
> > + ret = EFI_CALL((*fh->delete)(fh));
> > +
> > + return ret;
> > +}
> > +
> > +static void efi_capsule_scan_done(void)
> > +{
> > + EFI_CALL((*bootdev_root->close)(bootdev_root));
> > + bootdev_root = NULL;
> > +}
> > +
> > +efi_status_t __weak arch_efi_load_capsule_drivers(void)
> > +{
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/*
> > + * Launch all the capsules in system at boot time
> > + *
> > + * Called by efi init code
> > + */
>
> Where are the function descriptions?
Okay.
Thanks,
-Takahiro Akashi
> https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#function-documentation
>
> Best regards
>
> Heinrich
>
> > +efi_status_t efi_launch_capsules(void)
> > +{
> > + u64 os_indications;
> > + efi_uintn_t size;
> > + struct efi_capsule_header *capsule = NULL;
> > + u16 **files;
> > + int nfiles, num, i;
> > + char variable_name[12];
> > + u16 variable_name16[12], *p;
> > + efi_status_t ret;
> > +
> > + size = sizeof(os_indications);
> > + ret = EFI_CALL(efi_get_variable(L"OsIndications",
> > + &efi_global_variable_guid,
> > + NULL, &size, &os_indications));
> > + if (ret != EFI_SUCCESS ||
> > + !(os_indications
> > + & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED))
> > + return EFI_SUCCESS;
> > +
> > + num = get_last_capsule();
> > +
> > + /* Load capsule drivers */
> > + ret = arch_efi_load_capsule_drivers();
> > + if (ret != EFI_SUCCESS)
> > + return ret;
> > +
> > + /*
> > + * Find capsules on disk.
> > + * All the capsules are collected at the beginning because
> > + * capsule files will be removed instantly.
> > + */
> > + nfiles = 0;
> > + files = NULL;
> > + ret = efi_capsule_scan_dir(&files, &nfiles);
> > + if (ret != EFI_SUCCESS)
> > + return ret;
> > + if (!nfiles)
> > + return EFI_SUCCESS;
> > +
> > + /* Launch capsules */
> > + for (i = 0, ++num; i < nfiles; i++, num++) {
> > + EFI_PRINT("capsule from %ls ...\n", files[i]);
> > + if (num > 0xffff)
> > + num = 0;
> > + ret = efi_capsule_read_file(files[i], &capsule);
> > + if (ret == EFI_SUCCESS) {
> > + ret = EFI_CALL(efi_update_capsule(&capsule, 1, 0));
> > + if (ret != EFI_SUCCESS)
> > + printf("EFI Capsule update failed at %ls\n",
> > + files[i]);
> > +
> > + free(capsule);
> > + } else {
> > + printf("EFI: reading capsule failed: %ls\n",
> > + files[i]);
> > + }
> > + /* create CapsuleXXXX */
> > + set_capsule_result(num, capsule, ret);
> > +
> > + /* delete a capsule either in case of success or failure */
> > + ret = efi_capsule_delete_file(files[i]);
> > + if (ret != EFI_SUCCESS)
> > + printf("EFI: deleting a capsule file failed: %ls\n",
> > + files[i]);
> > + }
> > + efi_capsule_scan_done();
> > +
> > + for (i = 0; i < nfiles; i++)
> > + free(files[i]);
> > + free(files);
> > +
> > + /* CapsuleMax */
> > + p = variable_name16;
> > + utf8_utf16_strncpy(&p, "CapsuleFFFF", 11);
> > + EFI_CALL(efi_set_variable(L"CapsuleMax", &efi_guid_capsule_report,
> > + EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > + EFI_VARIABLE_RUNTIME_ACCESS,
> > + 22, variable_name16));
> > +
> > + /* CapsuleLast */
> > + sprintf(variable_name, "Capsule%04X", num - 1);
> > + p = variable_name16;
> > + utf8_utf16_strncpy(&p, variable_name, 11);
> > + EFI_CALL(efi_set_variable(L"CapsuleLast", &efi_guid_capsule_report,
> > + EFI_VARIABLE_NON_VOLATILE |
> > + EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > + EFI_VARIABLE_RUNTIME_ACCESS,
> > + 22, variable_name16));
> > +
> > + return ret;
> > +}
> > +#endif /* CONFIG_EFI_CAPSULE_ON_DISK */
> > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
> > index 8fe378bbfdfc..bb759976102a 100644
> > --- a/lib/efi_loader/efi_setup.c
> > +++ b/lib/efi_loader/efi_setup.c
> > @@ -129,6 +129,10 @@ static efi_status_t efi_init_os_indications(void)
> > #ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
> > os_indications_supported |=
> > EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED;
> > +#endif
> > +#ifdef CONFIG_EFI_CAPSULE_ON_DISK
> > + os_indications_supported |=
> > + EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
> > #endif
> > return EFI_CALL(efi_set_variable(L"OsIndicationsSupported",
> > &efi_global_variable_guid,
> > @@ -239,6 +243,11 @@ efi_status_t efi_init_obj_list(void)
> > if (ret != EFI_SUCCESS)
> > goto out;
> >
> > +#if defined(CONFIG_EFI_CAPSULE_ON_DISK) && \
> > + !defined(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)
> > + /* Execute capsules after reboot */
> > + ret = efi_launch_capsules();
> > +#endif
> > out:
> > efi_obj_list_initialized = ret;
> > return ret;
> >
>
next prev parent reply other threads:[~2020-04-28 0:28 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-27 9:48 [PATCH 00/10] efi_loader: add capsule update support AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 01/10] efi_loader: disk: add efi_disk_is_system_part() AKASHI Takahiro
2020-04-27 19:57 ` Heinrich Schuchardt
2020-04-27 23:54 ` AKASHI Takahiro
2020-05-01 7:06 ` Heinrich Schuchardt
2020-05-05 22:33 ` Heinrich Schuchardt
2020-04-27 9:48 ` [PATCH 02/10] efi_loader: add option to initialise EFI subsystem early AKASHI Takahiro
2020-04-27 20:09 ` Heinrich Schuchardt
2020-04-28 0:16 ` AKASHI Takahiro
2020-05-17 7:29 ` Heinrich Schuchardt
2020-05-18 1:43 ` AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 03/10] efi_loader: define UpdateCapsule api AKASHI Takahiro
2020-05-17 8:02 ` Heinrich Schuchardt
2020-05-18 1:34 ` AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 04/10] efi_loader: capsule: add capsule_on_disk support AKASHI Takahiro
2020-04-27 20:28 ` Heinrich Schuchardt
2020-04-28 0:28 ` AKASHI Takahiro [this message]
2020-04-30 12:52 ` Sughosh Ganu
2020-04-30 19:51 ` Heinrich Schuchardt
2020-05-07 2:50 ` AKASHI Takahiro
2020-05-07 12:05 ` Sughosh Ganu
2020-04-27 9:48 ` [PATCH 05/10] efi_loader: capsule: add memory range capsule definitions AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 06/10] efi_loader: capsule: support firmware update AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 07/10] efi_loader: add simple firmware management protocol for FIT image AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 08/10] cmd: add "efidebug capsule" command AKASHI Takahiro
2020-04-30 12:38 ` Sughosh Ganu
2020-05-07 1:58 ` AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 09/10] tools: add mkeficapsule command for UEFI capsule update test AKASHI Takahiro
2020-04-27 20:15 ` Heinrich Schuchardt
2020-04-28 1:52 ` AKASHI Takahiro
2020-04-27 9:48 ` [PATCH 10/10] test/py: add a test for efi firmware update capsule AKASHI Takahiro
2020-04-27 20:33 ` [PATCH 00/10] efi_loader: add capsule update support Heinrich Schuchardt
2020-04-27 23:45 ` AKASHI Takahiro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200428002803.GD16947@laputa \
--to=takahiro.akashi@linaro.org \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox