Add the TEE-backed runtime GetNextVariableName() implementation for the
FF-A/MM variable backend. The runtime path uses EFI runtime-safe memory
helpers and the shared MM communication path so variable enumeration can
continue after ExitBootServices().

Reviewed-by: Simon Glass <[email protected]>
Signed-off-by: Harsimran Singh Tungal <[email protected]>

---
Changelog:
===============

v6:

Ilias:

- Restore OP-TEE runtime callbacks when FF-A runtime mode is disabled
- Rename FF-A GetNextVariableName runtime handler with _ffa_runtime suffix

v4:

Ilias:

- Split the runtime GetNextVariableName() support out of the combined
  runtime variable-services patch.

v3:

Ilias:

- Rename TEE/FF-A runtime handlers to private *_int_runtime names

Simon:

- Add EFIAPI to the runtime GetNextVariableName() helper
---
 lib/efi_loader/efi_variable_tee.c | 68 ++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_variable_tee.c 
b/lib/efi_loader/efi_variable_tee.c
index 7e8049e177c..b078ccce20e 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -1007,6 +1007,68 @@ efi_get_variable_ffa_runtime(u16 *variable_name, const 
efi_guid_t *vendor,
        return ret;
 }
 
+efi_status_t __efi_runtime EFIAPI
+efi_get_next_variable_name_ffa_runtime(efi_uintn_t *variable_name_size,
+                                      u16 *variable_name, efi_guid_t *guid)
+{
+       struct smm_variable_getnext *var_getnext;
+       efi_uintn_t payload_size;
+       efi_uintn_t out_name_size;
+       efi_uintn_t in_name_size;
+       u8 *comm_buf = NULL;
+       efi_status_t ret;
+
+       if (!variable_name_size || !variable_name || !guid) {
+               ret = EFI_INVALID_PARAMETER;
+               return ret;
+       }
+
+       out_name_size = *variable_name_size;
+       in_name_size = u16_strsize(variable_name);
+
+       if (out_name_size < in_name_size) {
+               ret = EFI_INVALID_PARAMETER;
+               return ret;
+       }
+
+       if (in_name_size > max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) 
{
+               ret = EFI_INVALID_PARAMETER;
+               return ret;
+       }
+
+       /* Trim output buffer size */
+       if (out_name_size > max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE)
+               out_name_size = max_payload_size - 
MM_VARIABLE_GET_NEXT_HEADER_SIZE;
+
+       payload_size = MM_VARIABLE_GET_NEXT_HEADER_SIZE + out_name_size;
+       comm_buf = setup_mm_hdr((void **)&var_getnext, payload_size,
+                               SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME,
+                               &ret);
+       if (!comm_buf)
+               return ret;
+
+       /* Fill in contents */
+       efi_memcpy_runtime(&var_getnext->guid, guid, sizeof(*guid));
+       var_getnext->name_size = out_name_size;
+       efi_memcpy_runtime(var_getnext->name, variable_name, in_name_size);
+       efi_memset_runtime((u8 *)var_getnext->name + in_name_size, 0x0,
+                          out_name_size - in_name_size);
+
+       /* Communicate */
+       ret = mm_communicate(comm_buf, payload_size);
+       if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
+               /* Update with reported data size for trimmed case */
+               *variable_name_size = var_getnext->name_size;
+       }
+       if (ret != EFI_SUCCESS)
+               return ret;
+
+       efi_memcpy_runtime(guid, &var_getnext->guid, sizeof(*guid));
+       efi_memcpy_runtime(variable_name, var_getnext->name, 
var_getnext->name_size);
+
+       return ret;
+}
+
 efi_status_t efi_set_variable_int(const u16 *variable_name,
                                  const efi_guid_t *vendor, u32 attributes,
                                  efi_uintn_t data_size, const void *data,
@@ -1322,15 +1384,17 @@ void efi_variables_boot_exit_notify(void)
        /* Update runtime service table */
        if (IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)) {
                efi_runtime_services.get_variable = 
efi_get_variable_ffa_runtime;
+               efi_runtime_services.get_next_variable_name =
+                               efi_get_next_variable_name_ffa_runtime;
                efi_runtime_services.set_variable = 
efi_set_variable_ffa_runtime;
        } else {
                efi_runtime_services.get_variable = efi_get_variable_runtime;
+               efi_runtime_services.get_next_variable_name =
+                               efi_get_next_variable_name_runtime;
                efi_runtime_services.set_variable = efi_set_variable_runtime;
        }
        efi_runtime_services.query_variable_info =
                        efi_query_variable_info_runtime;
-       efi_runtime_services.get_next_variable_name =
-                       efi_get_next_variable_name_runtime;
        efi_update_table_header_crc32(&efi_runtime_services.hdr);
 
        /* Record that ExitBootServices() has been called */
-- 
2.43.0

Reply via email to