UpdateCapsule() must return EFI_INVALID_PARAMETER in a number of cases,
listed by the UEFI specification and tested by the SCT. Add a common
function to do that.

This fixes SCT UpdateCapsule_Conf failures.

Reviewed-by: Grant Likely <grant.lik...@arm.com>
Signed-off-by: Vincent Stehlé <vincent.ste...@arm.com>
Cc: Heinrich Schuchardt <xypron.g...@gmx.de>
Cc: Alexander Graf <ag...@csgraf.de>
---
 include/efi_loader.h         | 24 ++++++++++++++++++++++++
 lib/efi_loader/efi_capsule.c |  8 ++++----
 lib/efi_loader/efi_runtime.c |  8 ++++++++
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 0a9c82a257e..426d1c72d7d 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -910,6 +910,30 @@ extern const struct efi_firmware_management_protocol 
efi_fmp_fit;
 extern const struct efi_firmware_management_protocol efi_fmp_raw;
 
 /* Capsule update */
+static inline efi_status_t
+efi_valid_update_capsule_params(struct efi_capsule_header
+                                               **capsule_header_array,
+                               efi_uintn_t capsule_count,
+                               u64 scatter_gather_list)
+{
+       u32 flags;
+
+       if (!capsule_count)
+               return EFI_INVALID_PARAMETER;
+
+       flags = capsule_header_array[0]->flags;
+
+       if (((flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) &&
+            !scatter_gather_list) ||
+           ((flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) &&
+            !(flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)) ||
+           ((flags & CAPSULE_FLAGS_INITIATE_RESET) &&
+            !(flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET)))
+               return EFI_INVALID_PARAMETER;
+
+       return EFI_SUCCESS;
+}
+
 efi_status_t EFIAPI efi_update_capsule(
                struct efi_capsule_header **capsule_header_array,
                efi_uintn_t capsule_count,
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 60309d4a07d..380cfd70290 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -442,12 +442,12 @@ efi_status_t EFIAPI efi_update_capsule(
        EFI_ENTRY("%p, %zu, %llu\n", capsule_header_array, capsule_count,
                  scatter_gather_list);
 
-       if (!capsule_count) {
-               ret = EFI_INVALID_PARAMETER;
+       ret = efi_valid_update_capsule_params(capsule_header_array,
+                                             capsule_count,
+                                             scatter_gather_list);
+       if (ret != EFI_SUCCESS)
                goto out;
-       }
 
-       ret = EFI_SUCCESS;
        for (i = 0, capsule = *capsule_header_array; i < capsule_count;
             i++, capsule = *(++capsule_header_array)) {
                /* sanity check */
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 93a695fc27e..449ad8b9f36 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -467,6 +467,14 @@ efi_status_t __efi_runtime EFIAPI 
efi_update_capsule_unsupported(
                        efi_uintn_t capsule_count,
                        u64 scatter_gather_list)
 {
+       efi_status_t ret;
+
+       ret = efi_valid_update_capsule_params(capsule_header_array,
+                                             capsule_count,
+                                             scatter_gather_list);
+       if (ret != EFI_SUCCESS)
+               return ret;
+
        return EFI_UNSUPPORTED;
 }
 
-- 
2.30.2

Reply via email to