Add the TEE-backed runtime GetVariable() implementation for the FF-A/MM
variable backend. The runtime path builds the MM request using EFI
runtime-safe memory helpers and uses the shared MM communication path
after ExitBootServices().

Reviewed-by: Simon Glass <[email protected]>
Signed-off-by: Harsimran Singh Tungal <[email protected]>
---
 lib/efi_loader/efi_variable_tee.c | 89 ++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_variable_tee.c 
b/lib/efi_loader/efi_variable_tee.c
index d04b8dc1376..89991fb72b2 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -988,6 +988,93 @@ out:
        return ret;
 }
 
+efi_status_t __efi_runtime EFIAPI
+efi_get_variable_int_runtime(u16 *variable_name, const efi_guid_t *vendor,
+                            u32 *attributes, efi_uintn_t *data_size, void 
*data)
+{
+       struct var_check_property var_property;
+       struct smm_variable_access *var_acc;
+       efi_uintn_t payload_size;
+       efi_uintn_t name_size;
+       efi_uintn_t tmp_dsize;
+       u8 *comm_buf = NULL;
+       efi_status_t ret, tmp;
+       u32 var_attr = 0;
+
+       if (!variable_name || !vendor || !data_size) {
+               ret = EFI_INVALID_PARAMETER;
+               return ret;
+       }
+
+       /* Check payload size */
+       name_size = u16_strsize(variable_name);
+       if (name_size > max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) {
+               ret = EFI_INVALID_PARAMETER;
+               return ret;
+       }
+
+       /* Trim output buffer size */
+       tmp_dsize = *data_size;
+       if (name_size + tmp_dsize >
+                       max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) {
+               tmp_dsize = max_payload_size -
+                               MM_VARIABLE_ACCESS_HEADER_SIZE -
+                               name_size;
+       }
+
+       /* Get communication buffer and initialize header */
+       payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + tmp_dsize;
+       comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
+                               SMM_VARIABLE_FUNCTION_GET_VARIABLE, &ret);
+       if (!comm_buf)
+               return ret;
+
+       /* Fill in contents */
+       efi_memcpy_runtime(&var_acc->guid, vendor, sizeof(var_acc->guid));
+       var_acc->data_size = tmp_dsize;
+       var_acc->name_size = name_size;
+       var_acc->attr = attributes ? *attributes : 0;
+       efi_memcpy_runtime(var_acc->name, variable_name, name_size);
+
+       /* Communicate */
+       ret = mm_communicate(comm_buf, payload_size);
+       if (ret != EFI_SUCCESS && ret != EFI_BUFFER_TOO_SMALL)
+               return ret;
+
+       /* Update with reported data size for trimmed case */
+       *data_size = var_acc->data_size;
+       if (attributes)
+               var_attr = var_acc->attr;
+
+       /* Copy the data if ret is EFI_SUCCESS  */
+       if (ret == EFI_SUCCESS) {
+               if (data)
+                       efi_memcpy_runtime(data, (u8 *)var_acc->name + 
var_acc->name_size,
+                                          var_acc->data_size);
+               else
+                       ret = EFI_INVALID_PARAMETER;
+       }
+
+       /*
+        * UEFI > 2.7 needs the attributes set even if the buffer is
+        * smaller
+        */
+       if (attributes) {
+               tmp = get_property_int_runtime(variable_name, name_size, vendor,
+                                              &var_property);
+               if (tmp != EFI_SUCCESS) {
+                       ret = tmp;
+                       return ret;
+               }
+               *attributes = var_attr;
+               if (var_property.property &
+                   VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
+                       *attributes |= EFI_VARIABLE_READ_ONLY;
+       }
+
+       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,
@@ -1253,7 +1340,7 @@ void efi_variables_boot_exit_notify(void)
        /* Update runtime service table */
        efi_runtime_services.query_variable_info =
                        efi_query_variable_info_runtime;
-       efi_runtime_services.get_variable = efi_get_variable_runtime;
+       efi_runtime_services.get_variable = efi_get_variable_int_runtime;
        efi_runtime_services.get_next_variable_name =
                        efi_get_next_variable_name_runtime;
        efi_runtime_services.set_variable = efi_set_variable_int_runtime;
-- 
2.34.1

Reply via email to