diff mbox series

[v2] efi_loader: Allow capsule update on-disk without checking OsIndications

Message ID 20210629125520.36856-1-ilias.apalodimas@linaro.org
State New
Headers show
Series [v2] efi_loader: Allow capsule update on-disk without checking OsIndications | expand

Commit Message

Ilias Apalodimas June 29, 2021, 12:55 p.m. UTC
Although U-Boot supports capsule update on-disk, it's lack of support for
SetVariable at runtime prevents applications like fwupd from using it.

In order to perform the capsule update on-disk the spec says that the OS
must copy the capsule to the \EFI\UpdateCapsule directory and set a bit in
the OsIndications variable.  The firmware then checks for the
EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit in OsIndications
variable, which is set by submitter to trigger processing of the capsule
on next reboot.

Let's add a config option which ignores the bit checking in OsIndications
and just rely on the capsule being present (which breaks the EFI spec).
Since U-Boot deletes the capsule while processing it, we won't end up
running it multiple times.

Note that this is allowed for all capsules.  In the future once,
authenticated capsules is fully supported, we can limit the functionality
to those only.

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

---
changes since v1:
- explicitly state in the Kconfig that this breaks the EFI spec.

 lib/efi_loader/Kconfig       | 10 ++++++++++
 lib/efi_loader/efi_capsule.c | 36 ++++++++++++++++++++++++++++--------
 2 files changed, 38 insertions(+), 8 deletions(-)

-- 
2.32.0.rc0
diff mbox series

Patch

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 684adfb62379..9c4d4b41e450 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -137,6 +137,16 @@  config EFI_CAPSULE_ON_DISK
 	  under a specific directory on UEFI system partition instead of
 	  via UpdateCapsule API.
 
+config EFI_IGNORE_OSINDICATIONS
+	bool "Ignore OsIndications for CapsuleUpdate on-disk"
+	depends on EFI_CAPSULE_ON_DISK
+	default n
+	help
+	  There are boards were we can't support SetVariable at runtime.
+	  Select this option if you want to use capsule-on-disk feature,
+	  without setting the OsIndications bit. Note that enabling this
+	  breaks conformance to the EFI spec and CapsuleUpdate on-disk.
+
 config EFI_CAPSULE_ON_DISK_EARLY
 	bool "Initiate capsule-on-disk at U-Boot boottime"
 	depends on EFI_CAPSULE_ON_DISK
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index d7136035d8f9..50bed32bfb3b 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -948,6 +948,33 @@  efi_status_t __weak efi_load_capsule_drivers(void)
 	return ret;
 }
 
+/**
+ * check_run_capsules - Check whether capsule update should run
+ *
+ * The spec says OsIndications must be set in order to run the capsule update
+ * on-disk.  Since U-Boot doesn't support runtime SetVariable, allow capsules to
+ * run explicitly if CONFIG_EFI_IGNORE_OSINDICATIONS is selected
+ */
+static bool check_run_capsules(void)
+{
+	u64 os_indications;
+	efi_uintn_t size;
+	efi_status_t ret;
+
+	if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS))
+		return true;
+
+	size = sizeof(os_indications);
+	ret = efi_get_variable_int(L"OsIndications", &efi_global_variable_guid,
+				   NULL, &size, &os_indications, NULL);
+	if (ret == EFI_SUCCESS &&
+	    (os_indications
+	      & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED))
+		return true;
+
+	return false;
+}
+
 /**
  * efi_launch_capsule - launch capsules
  *
@@ -958,20 +985,13 @@  efi_status_t __weak efi_load_capsule_drivers(void)
  */
 efi_status_t efi_launch_capsules(void)
 {
-	u64 os_indications;
-	efi_uintn_t size;
 	struct efi_capsule_header *capsule = NULL;
 	u16 **files;
 	unsigned int nfiles, index, i;
 	u16 variable_name16[12];
 	efi_status_t ret;
 
-	size = sizeof(os_indications);
-	ret = efi_get_variable_int(L"OsIndications", &efi_global_variable_guid,
-				   NULL, &size, &os_indications, NULL);
-	if (ret != EFI_SUCCESS ||
-	    !(os_indications
-	      & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED))
+	if (!check_run_capsules())
 		return EFI_SUCCESS;
 
 	index = get_last_capsule();