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
