// SPDX-License-Identifier: GPL-2.0-or-later /* * Client driver for Qualcomm UEFI Secure Application (qcom.tz.uefisecapp). * Provides access to UEFI variables on platforms where they are secured by the * aforementioned Secure Execution Environment (SEE) application. * * Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
*/
/** * struct qsee_req_uefi_get_variable - Request for GetVariable command. * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_GET_VARIABLE. * @length: Length of the request in bytes, including this struct and any * parameters (name, GUID) stored after it as well as any padding * thereof for alignment. * @name_offset: Offset from the start of this struct to where the variable * name is stored (as utf-16 string), in bytes. * @name_size: Size of the name parameter in bytes, including null-terminator. * @guid_offset: Offset from the start of this struct to where the GUID * parameter is stored, in bytes. * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t). * @data_size: Size of the output buffer, in bytes.
*/ struct qsee_req_uefi_get_variable {
u32 command_id;
u32 length;
u32 name_offset;
u32 name_size;
u32 guid_offset;
u32 guid_size;
u32 data_size;
} __packed;
/** * struct qsee_rsp_uefi_get_variable - Response for GetVariable command. * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_GET_VARIABLE. * @length: Length of the response in bytes, including this struct and the * returned data. * @status: Status of this command. * @attributes: EFI variable attributes. * @data_offset: Offset from the start of this struct to where the data is * stored, in bytes. * @data_size: Size of the returned data, in bytes. In case status indicates * that the buffer is too small, this will be the size required * to store the EFI variable data.
*/ struct qsee_rsp_uefi_get_variable {
u32 command_id;
u32 length;
u32 status;
u32 attributes;
u32 data_offset;
u32 data_size;
} __packed;
/** * struct qsee_req_uefi_set_variable - Request for the SetVariable command. * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_SET_VARIABLE. * @length: Length of the request in bytes, including this struct and any * parameters (name, GUID, data) stored after it as well as any * padding thereof required for alignment. * @name_offset: Offset from the start of this struct to where the variable * name is stored (as utf-16 string), in bytes. * @name_size: Size of the name parameter in bytes, including null-terminator. * @guid_offset: Offset from the start of this struct to where the GUID * parameter is stored, in bytes. * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t). * @attributes: The EFI variable attributes to set for this variable. * @data_offset: Offset from the start of this struct to where the EFI variable * data is stored, in bytes. * @data_size: Size of EFI variable data, in bytes. *
*/ struct qsee_req_uefi_set_variable {
u32 command_id;
u32 length;
u32 name_offset;
u32 name_size;
u32 guid_offset;
u32 guid_size;
u32 attributes;
u32 data_offset;
u32 data_size;
} __packed;
/** * struct qsee_rsp_uefi_set_variable - Response for the SetVariable command. * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_SET_VARIABLE. * @length: The length of this response, i.e. the size of this struct in * bytes. * @status: Status of this command. * @_unknown1: Unknown response field. * @_unknown2: Unknown response field.
*/ struct qsee_rsp_uefi_set_variable {
u32 command_id;
u32 length;
u32 status;
u32 _unknown1;
u32 _unknown2;
} __packed;
/** * struct qsee_req_uefi_get_next_variable - Request for the * GetNextVariableName command. * @command_id: The ID of the command. Must be * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE. * @length: Length of the request in bytes, including this struct and any * parameters (name, GUID) stored after it as well as any padding * thereof for alignment. * @guid_offset: Offset from the start of this struct to where the GUID * parameter is stored, in bytes. * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t). * @name_offset: Offset from the start of this struct to where the variable * name is stored (as utf-16 string), in bytes. * @name_size: Size of the name parameter in bytes, including null-terminator.
*/ struct qsee_req_uefi_get_next_variable {
u32 command_id;
u32 length;
u32 guid_offset;
u32 guid_size;
u32 name_offset;
u32 name_size;
} __packed;
/** * struct qsee_rsp_uefi_get_next_variable - Response for the * GetNextVariableName command. * @command_id: The ID of the command. Should be * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE. * @length: Length of the response in bytes, including this struct and any * parameters (name, GUID) stored after it as well as any padding * thereof for alignment. * @status: Status of this command. * @guid_offset: Offset from the start of this struct to where the GUID * parameter is stored, in bytes. * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t). * @name_offset: Offset from the start of this struct to where the variable * name is stored (as utf-16 string), in bytes. * @name_size: Size of the name parameter in bytes, including null-terminator.
*/ struct qsee_rsp_uefi_get_next_variable {
u32 command_id;
u32 length;
u32 status;
u32 guid_offset;
u32 guid_size;
u32 name_offset;
u32 name_size;
} __packed;
/** * struct qsee_req_uefi_query_variable_info - Response for the * GetNextVariableName command. * @command_id: The ID of the command. Must be * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO. * @length: The length of this request, i.e. the size of this struct in * bytes. * @attributes: The storage attributes to query the info for.
*/ struct qsee_req_uefi_query_variable_info {
u32 command_id;
u32 length;
u32 attributes;
} __packed;
/** * struct qsee_rsp_uefi_query_variable_info - Response for the * GetNextVariableName command. * @command_id: The ID of the command. Must be * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO. * @length: The length of this response, i.e. the size of this * struct in bytes. * @status: Status of this command. * @_pad: Padding. * @storage_space: Full storage space size, in bytes. * @remaining_space: Free storage space available, in bytes. * @max_variable_size: Maximum variable data size, in bytes.
*/ struct qsee_rsp_uefi_query_variable_info {
u32 command_id;
u32 length;
u32 status;
u32 _pad;
u64 storage_space;
u64 remaining_space;
u64 max_variable_size;
} __packed;
/* * Helper macro to ensure proper alignment of types (fields and arrays) when * stored in some (contiguous) buffer. * * Note: The driver from which this one has been reverse-engineered expects an * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t, * however, has an alignment of 4 byte (32 bits). So far, this seems to work * fine here. See also the comment on the typedef of efi_guid_t. * * Note: It looks like uefisecapp is quite picky about how the memory passed to * it is structured and aligned. In particular the request/response setup used * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory, * accepts separate buffers/addresses for the request and response parts, in * practice, however, it seems to expect them to be both part of a larger * contiguous block. We initially allocated separate buffers for the request * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to * either not write any response to the response buffer or outright crash the * device. Therefore, we now allocate a single contiguous block of DMA memory * for both and properly align the data using the macros below. In particular, * request and response structs are aligned at 8 byte (via __reqdata_offs()), * following the driver that this has been reverse-engineered from.
*/ #define qcuefi_buf_align_fields(fields...) \
({ \
size_t __len = 0; \
fields \
__len; \
})
/* Update size and attributes in case buffer is too small. */ if (efi_status == EFI_BUFFER_TOO_SMALL) {
*data_size = rsp_data->data_size; if (attributes)
*attributes = rsp_data->attributes;
}
if (rsp_data->length > rsp_size) return EFI_DEVICE_ERROR;
if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) return EFI_DEVICE_ERROR;
/* * Note: We need to set attributes and data size even if the buffer is * too small and we won't copy any data. This is described in spec, so * that callers can either allocate a buffer properly (with two calls * to this function) or just read back attributes withouth having to * deal with that. * * Specifically: * - If we have a buffer size of zero and no buffer, just return the * attributes, required size, and indicate success. * - If the buffer size is nonzero but too small, indicate that as an * error. * - Otherwise, we are good to copy the data. * * Note that we have already ensured above that the buffer pointer is * non-NULL if its size is nonzero.
*/
*data_size = rsp_data->data_size; if (attributes)
*attributes = rsp_data->attributes;
if (buffer_size == 0 && !data) return EFI_SUCCESS;
if (buffer_size < rsp_data->data_size) return EFI_BUFFER_TOO_SMALL;
/* * Make sure we have some data if data_size is nonzero. Note that using * a size of zero is a valid use-case described in spec and deletes the * variable.
*/ if (data_size && !data) return EFI_INVALID_PARAMETER;
/* * If the buffer to hold the name is too small, update the * name_size with the required size, so that callers can * reallocate it accordingly.
*/ if (efi_status == EFI_BUFFER_TOO_SMALL)
*name_size = rsp_data->name_size;
return efi_status;
}
if (rsp_data->length > rsp_size) return EFI_DEVICE_ERROR;
if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) return EFI_DEVICE_ERROR;
if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) return EFI_DEVICE_ERROR;
if (status < 0) /* * Return EFI_DEVICE_ERROR here because the buffer size should * have already been validated above, causing this function to * bail with EFI_BUFFER_TOO_SMALL.
*/ return EFI_DEVICE_ERROR;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.