1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Client driver for Qualcomm UEFI Secure Application (qcom.tz.uefisecapp).
4 * Provides access to UEFI variables on platforms where they are secured by the
5 * aforementioned Secure Execution Environment (SEE) application.
7 * Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
10 #include <linux/efi.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
15 #include <linux/platform_device.h>
16 #include <linux/slab.h>
17 #include <linux/types.h>
18 #include <linux/ucs2_string.h>
20 #include <linux/firmware/qcom/qcom_qseecom.h>
22 /* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */
24 /* Maximum length of name string with null-terminator */
25 #define QSEE_MAX_NAME_LEN 1024
27 #define QSEE_CMD_UEFI(x) (0x8000 | (x))
28 #define QSEE_CMD_UEFI_GET_VARIABLE QSEE_CMD_UEFI(0)
29 #define QSEE_CMD_UEFI_SET_VARIABLE QSEE_CMD_UEFI(1)
30 #define QSEE_CMD_UEFI_GET_NEXT_VARIABLE QSEE_CMD_UEFI(2)
31 #define QSEE_CMD_UEFI_QUERY_VARIABLE_INFO QSEE_CMD_UEFI(3)
34 * struct qsee_req_uefi_get_variable - Request for GetVariable command.
35 * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_GET_VARIABLE.
36 * @length: Length of the request in bytes, including this struct and any
37 * parameters (name, GUID) stored after it as well as any padding
38 * thereof for alignment.
39 * @name_offset: Offset from the start of this struct to where the variable
40 * name is stored (as utf-16 string), in bytes.
41 * @name_size: Size of the name parameter in bytes, including null-terminator.
42 * @guid_offset: Offset from the start of this struct to where the GUID
43 * parameter is stored, in bytes.
44 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
45 * @data_size: Size of the output buffer, in bytes.
47 struct qsee_req_uefi_get_variable {
58 * struct qsee_rsp_uefi_get_variable - Response for GetVariable command.
59 * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_GET_VARIABLE.
60 * @length: Length of the response in bytes, including this struct and the
62 * @status: Status of this command.
63 * @attributes: EFI variable attributes.
64 * @data_offset: Offset from the start of this struct to where the data is
66 * @data_size: Size of the returned data, in bytes. In case status indicates
67 * that the buffer is too small, this will be the size required
68 * to store the EFI variable data.
70 struct qsee_rsp_uefi_get_variable {
80 * struct qsee_req_uefi_set_variable - Request for the SetVariable command.
81 * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_SET_VARIABLE.
82 * @length: Length of the request in bytes, including this struct and any
83 * parameters (name, GUID, data) stored after it as well as any
84 * padding thereof required for alignment.
85 * @name_offset: Offset from the start of this struct to where the variable
86 * name is stored (as utf-16 string), in bytes.
87 * @name_size: Size of the name parameter in bytes, including null-terminator.
88 * @guid_offset: Offset from the start of this struct to where the GUID
89 * parameter is stored, in bytes.
90 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
91 * @attributes: The EFI variable attributes to set for this variable.
92 * @data_offset: Offset from the start of this struct to where the EFI variable
93 * data is stored, in bytes.
94 * @data_size: Size of EFI variable data, in bytes.
97 struct qsee_req_uefi_set_variable {
110 * struct qsee_rsp_uefi_set_variable - Response for the SetVariable command.
111 * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_SET_VARIABLE.
112 * @length: The length of this response, i.e. the size of this struct in
114 * @status: Status of this command.
115 * @_unknown1: Unknown response field.
116 * @_unknown2: Unknown response field.
118 struct qsee_rsp_uefi_set_variable {
127 * struct qsee_req_uefi_get_next_variable - Request for the
128 * GetNextVariableName command.
129 * @command_id: The ID of the command. Must be
130 * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE.
131 * @length: Length of the request in bytes, including this struct and any
132 * parameters (name, GUID) stored after it as well as any padding
133 * thereof for alignment.
134 * @guid_offset: Offset from the start of this struct to where the GUID
135 * parameter is stored, in bytes.
136 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
137 * @name_offset: Offset from the start of this struct to where the variable
138 * name is stored (as utf-16 string), in bytes.
139 * @name_size: Size of the name parameter in bytes, including null-terminator.
141 struct qsee_req_uefi_get_next_variable {
151 * struct qsee_rsp_uefi_get_next_variable - Response for the
152 * GetNextVariableName command.
153 * @command_id: The ID of the command. Should be
154 * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE.
155 * @length: Length of the response in bytes, including this struct and any
156 * parameters (name, GUID) stored after it as well as any padding
157 * thereof for alignment.
158 * @status: Status of this command.
159 * @guid_offset: Offset from the start of this struct to where the GUID
160 * parameter is stored, in bytes.
161 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
162 * @name_offset: Offset from the start of this struct to where the variable
163 * name is stored (as utf-16 string), in bytes.
164 * @name_size: Size of the name parameter in bytes, including null-terminator.
166 struct qsee_rsp_uefi_get_next_variable {
177 * struct qsee_req_uefi_query_variable_info - Response for the
178 * GetNextVariableName command.
179 * @command_id: The ID of the command. Must be
180 * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO.
181 * @length: The length of this request, i.e. the size of this struct in
183 * @attributes: The storage attributes to query the info for.
185 struct qsee_req_uefi_query_variable_info {
192 * struct qsee_rsp_uefi_query_variable_info - Response for the
193 * GetNextVariableName command.
194 * @command_id: The ID of the command. Must be
195 * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO.
196 * @length: The length of this response, i.e. the size of this
198 * @status: Status of this command.
200 * @storage_space: Full storage space size, in bytes.
201 * @remaining_space: Free storage space available, in bytes.
202 * @max_variable_size: Maximum variable data size, in bytes.
204 struct qsee_rsp_uefi_query_variable_info {
211 u64 max_variable_size;
214 /* -- Alignment helpers ----------------------------------------------------- */
217 * Helper macro to ensure proper alignment of types (fields and arrays) when
218 * stored in some (contiguous) buffer.
220 * Note: The driver from which this one has been reverse-engineered expects an
221 * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
222 * however, has an alignment of 4 byte (32 bits). So far, this seems to work
223 * fine here. See also the comment on the typedef of efi_guid_t.
225 * Note: It looks like uefisecapp is quite picky about how the memory passed to
226 * it is structured and aligned. In particular the request/response setup used
227 * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory,
228 * accepts separate buffers/addresses for the request and response parts, in
229 * practice, however, it seems to expect them to be both part of a larger
230 * contiguous block. We initially allocated separate buffers for the request
231 * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to
232 * either not write any response to the response buffer or outright crash the
233 * device. Therefore, we now allocate a single contiguous block of DMA memory
234 * for both and properly align the data using the macros below. In particular,
235 * request and response structs are aligned at 8 byte (via __reqdata_offs()),
236 * following the driver that this has been reverse-engineered from.
238 #define qcuefi_buf_align_fields(fields...) \
245 #define __field_impl(size, align, offset) \
247 size_t *__offset = (offset); \
250 __aligned = ALIGN(__len, align); \
251 __len = __aligned + (size); \
254 *__offset = __aligned; \
257 #define __array_offs(type, count, offset) \
258 __field_impl(sizeof(type) * (count), __alignof__(type), offset)
260 #define __array_offs_aligned(type, count, align, offset) \
261 __field_impl(sizeof(type) * (count), align, offset)
263 #define __reqdata_offs(size, offset) \
264 __array_offs_aligned(u8, size, 8, offset)
266 #define __array(type, count) __array_offs(type, count, NULL)
267 #define __field_offs(type, offset) __array_offs(type, 1, offset)
268 #define __field(type) __array_offs(type, 1, NULL)
270 /* -- UEFI app interface. --------------------------------------------------- */
272 struct qcuefi_client {
273 struct qseecom_client *client;
274 struct efivars efivars;
277 static struct device *qcuefi_dev(struct qcuefi_client *qcuefi)
279 return &qcuefi->client->aux_dev.dev;
282 static efi_status_t qsee_uefi_status_to_efi(u32 status)
284 u64 category = status & 0xf0000000;
285 u64 code = status & 0x0fffffff;
287 return category << (BITS_PER_LONG - 32) | code;
290 static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
291 const efi_guid_t *guid, u32 *attributes,
292 unsigned long *data_size, void *data)
294 struct qsee_req_uefi_get_variable *req_data;
295 struct qsee_rsp_uefi_get_variable *rsp_data;
296 unsigned long buffer_size = *data_size;
297 efi_status_t efi_status = EFI_SUCCESS;
298 unsigned long name_length;
299 dma_addr_t cmd_buf_dma;
311 return EFI_INVALID_PARAMETER;
313 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1;
314 if (name_length > QSEE_MAX_NAME_LEN)
315 return EFI_INVALID_PARAMETER;
317 if (buffer_size && !data)
318 return EFI_INVALID_PARAMETER;
320 req_size = qcuefi_buf_align_fields(
322 __array_offs(*name, name_length, &name_offs)
323 __field_offs(*guid, &guid_offs)
326 rsp_size = qcuefi_buf_align_fields(
328 __array(u8, buffer_size)
331 cmd_buf_size = qcuefi_buf_align_fields(
332 __reqdata_offs(req_size, &req_offs)
333 __reqdata_offs(rsp_size, &rsp_offs)
336 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
338 efi_status = EFI_OUT_OF_RESOURCES;
342 req_data = cmd_buf + req_offs;
343 rsp_data = cmd_buf + rsp_offs;
345 req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE;
346 req_data->data_size = buffer_size;
347 req_data->name_offset = name_offs;
348 req_data->name_size = name_length * sizeof(*name);
349 req_data->guid_offset = guid_offs;
350 req_data->guid_size = sizeof(*guid);
351 req_data->length = req_size;
353 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
355 efi_status = EFI_INVALID_PARAMETER;
359 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
361 status = qcom_qseecom_app_send(qcuefi->client,
362 cmd_buf_dma + req_offs, req_size,
363 cmd_buf_dma + rsp_offs, rsp_size);
365 efi_status = EFI_DEVICE_ERROR;
369 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) {
370 efi_status = EFI_DEVICE_ERROR;
374 if (rsp_data->length < sizeof(*rsp_data)) {
375 efi_status = EFI_DEVICE_ERROR;
379 if (rsp_data->status) {
380 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
381 __func__, rsp_data->status);
382 efi_status = qsee_uefi_status_to_efi(rsp_data->status);
384 /* Update size and attributes in case buffer is too small. */
385 if (efi_status == EFI_BUFFER_TOO_SMALL) {
386 *data_size = rsp_data->data_size;
388 *attributes = rsp_data->attributes;
394 if (rsp_data->length > rsp_size) {
395 efi_status = EFI_DEVICE_ERROR;
399 if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) {
400 efi_status = EFI_DEVICE_ERROR;
405 * Note: We need to set attributes and data size even if the buffer is
406 * too small and we won't copy any data. This is described in spec, so
407 * that callers can either allocate a buffer properly (with two calls
408 * to this function) or just read back attributes withouth having to
412 * - If we have a buffer size of zero and no buffer, just return the
413 * attributes, required size, and indicate success.
414 * - If the buffer size is nonzero but too small, indicate that as an
416 * - Otherwise, we are good to copy the data.
418 * Note that we have already ensured above that the buffer pointer is
419 * non-NULL if its size is nonzero.
421 *data_size = rsp_data->data_size;
423 *attributes = rsp_data->attributes;
425 if (buffer_size == 0 && !data) {
426 efi_status = EFI_SUCCESS;
430 if (buffer_size < rsp_data->data_size) {
431 efi_status = EFI_BUFFER_TOO_SMALL;
435 memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
438 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
443 static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
444 const efi_guid_t *guid, u32 attributes,
445 unsigned long data_size, const void *data)
447 struct qsee_req_uefi_set_variable *req_data;
448 struct qsee_rsp_uefi_set_variable *rsp_data;
449 efi_status_t efi_status = EFI_SUCCESS;
450 unsigned long name_length;
451 dma_addr_t cmd_buf_dma;
463 return EFI_INVALID_PARAMETER;
465 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1;
466 if (name_length > QSEE_MAX_NAME_LEN)
467 return EFI_INVALID_PARAMETER;
470 * Make sure we have some data if data_size is nonzero. Note that using
471 * a size of zero is a valid use-case described in spec and deletes the
474 if (data_size && !data)
475 return EFI_INVALID_PARAMETER;
477 req_size = qcuefi_buf_align_fields(
479 __array_offs(*name, name_length, &name_offs)
480 __field_offs(*guid, &guid_offs)
481 __array_offs(u8, data_size, &data_offs)
484 cmd_buf_size = qcuefi_buf_align_fields(
485 __reqdata_offs(req_size, &req_offs)
486 __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
489 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
491 efi_status = EFI_OUT_OF_RESOURCES;
495 req_data = cmd_buf + req_offs;
496 rsp_data = cmd_buf + rsp_offs;
498 req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE;
499 req_data->attributes = attributes;
500 req_data->name_offset = name_offs;
501 req_data->name_size = name_length * sizeof(*name);
502 req_data->guid_offset = guid_offs;
503 req_data->guid_size = sizeof(*guid);
504 req_data->data_offset = data_offs;
505 req_data->data_size = data_size;
506 req_data->length = req_size;
508 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
510 efi_status = EFI_INVALID_PARAMETER;
514 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
517 memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size);
519 status = qcom_qseecom_app_send(qcuefi->client,
520 cmd_buf_dma + req_offs, req_size,
521 cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
523 efi_status = EFI_DEVICE_ERROR;
527 if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) {
528 efi_status = EFI_DEVICE_ERROR;
532 if (rsp_data->length != sizeof(*rsp_data)) {
533 efi_status = EFI_DEVICE_ERROR;
537 if (rsp_data->status) {
538 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
539 __func__, rsp_data->status);
540 efi_status = qsee_uefi_status_to_efi(rsp_data->status);
544 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
549 static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
550 unsigned long *name_size, efi_char16_t *name,
553 struct qsee_req_uefi_get_next_variable *req_data;
554 struct qsee_rsp_uefi_get_next_variable *rsp_data;
555 efi_status_t efi_status = EFI_SUCCESS;
556 dma_addr_t cmd_buf_dma;
567 if (!name_size || !name || !guid)
568 return EFI_INVALID_PARAMETER;
571 return EFI_INVALID_PARAMETER;
573 req_size = qcuefi_buf_align_fields(
575 __field_offs(*guid, &guid_offs)
576 __array_offs(*name, *name_size / sizeof(*name), &name_offs)
579 rsp_size = qcuefi_buf_align_fields(
582 __array(*name, *name_size / sizeof(*name))
585 cmd_buf_size = qcuefi_buf_align_fields(
586 __reqdata_offs(req_size, &req_offs)
587 __reqdata_offs(rsp_size, &rsp_offs)
590 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
592 efi_status = EFI_OUT_OF_RESOURCES;
596 req_data = cmd_buf + req_offs;
597 rsp_data = cmd_buf + rsp_offs;
599 req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE;
600 req_data->guid_offset = guid_offs;
601 req_data->guid_size = sizeof(*guid);
602 req_data->name_offset = name_offs;
603 req_data->name_size = *name_size;
604 req_data->length = req_size;
606 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
607 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name,
608 *name_size / sizeof(*name));
610 efi_status = EFI_INVALID_PARAMETER;
614 status = qcom_qseecom_app_send(qcuefi->client,
615 cmd_buf_dma + req_offs, req_size,
616 cmd_buf_dma + rsp_offs, rsp_size);
618 efi_status = EFI_DEVICE_ERROR;
622 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) {
623 efi_status = EFI_DEVICE_ERROR;
627 if (rsp_data->length < sizeof(*rsp_data)) {
628 efi_status = EFI_DEVICE_ERROR;
632 if (rsp_data->status) {
633 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
634 __func__, rsp_data->status);
635 efi_status = qsee_uefi_status_to_efi(rsp_data->status);
638 * If the buffer to hold the name is too small, update the
639 * name_size with the required size, so that callers can
640 * reallocate it accordingly.
642 if (efi_status == EFI_BUFFER_TOO_SMALL)
643 *name_size = rsp_data->name_size;
648 if (rsp_data->length > rsp_size) {
649 efi_status = EFI_DEVICE_ERROR;
653 if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) {
654 efi_status = EFI_DEVICE_ERROR;
658 if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) {
659 efi_status = EFI_DEVICE_ERROR;
663 if (rsp_data->name_size > *name_size) {
664 *name_size = rsp_data->name_size;
665 efi_status = EFI_BUFFER_TOO_SMALL;
669 if (rsp_data->guid_size != sizeof(*guid)) {
670 efi_status = EFI_DEVICE_ERROR;
674 memcpy(guid, ((void *)rsp_data) + rsp_data->guid_offset, rsp_data->guid_size);
675 status = ucs2_strscpy(name, ((void *)rsp_data) + rsp_data->name_offset,
676 rsp_data->name_size / sizeof(*name));
677 *name_size = rsp_data->name_size;
681 * Return EFI_DEVICE_ERROR here because the buffer size should
682 * have already been validated above, causing this function to
683 * bail with EFI_BUFFER_TOO_SMALL.
685 efi_status = EFI_DEVICE_ERROR;
689 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
694 static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, u32 attr,
695 u64 *storage_space, u64 *remaining_space,
696 u64 *max_variable_size)
698 struct qsee_req_uefi_query_variable_info *req_data;
699 struct qsee_rsp_uefi_query_variable_info *rsp_data;
700 efi_status_t efi_status = EFI_SUCCESS;
701 dma_addr_t cmd_buf_dma;
708 cmd_buf_size = qcuefi_buf_align_fields(
709 __reqdata_offs(sizeof(*req_data), &req_offs)
710 __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
713 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
715 efi_status = EFI_OUT_OF_RESOURCES;
719 req_data = cmd_buf + req_offs;
720 rsp_data = cmd_buf + rsp_offs;
722 req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO;
723 req_data->attributes = attr;
724 req_data->length = sizeof(*req_data);
726 status = qcom_qseecom_app_send(qcuefi->client,
727 cmd_buf_dma + req_offs, sizeof(*req_data),
728 cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
730 efi_status = EFI_DEVICE_ERROR;
734 if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) {
735 efi_status = EFI_DEVICE_ERROR;
739 if (rsp_data->length != sizeof(*rsp_data)) {
740 efi_status = EFI_DEVICE_ERROR;
744 if (rsp_data->status) {
745 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
746 __func__, rsp_data->status);
747 efi_status = qsee_uefi_status_to_efi(rsp_data->status);
752 *storage_space = rsp_data->storage_space;
755 *remaining_space = rsp_data->remaining_space;
757 if (max_variable_size)
758 *max_variable_size = rsp_data->max_variable_size;
761 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
766 /* -- Global efivar interface. ---------------------------------------------- */
768 static struct qcuefi_client *__qcuefi;
769 static DEFINE_MUTEX(__qcuefi_lock);
771 static int qcuefi_set_reference(struct qcuefi_client *qcuefi)
773 mutex_lock(&__qcuefi_lock);
775 if (qcuefi && __qcuefi) {
776 mutex_unlock(&__qcuefi_lock);
782 mutex_unlock(&__qcuefi_lock);
786 static struct qcuefi_client *qcuefi_acquire(void)
788 mutex_lock(&__qcuefi_lock);
792 static void qcuefi_release(void)
794 mutex_unlock(&__qcuefi_lock);
797 static efi_status_t qcuefi_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
798 unsigned long *data_size, void *data)
800 struct qcuefi_client *qcuefi;
803 qcuefi = qcuefi_acquire();
805 return EFI_NOT_READY;
807 status = qsee_uefi_get_variable(qcuefi, name, vendor, attr, data_size, data);
813 static efi_status_t qcuefi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
814 u32 attr, unsigned long data_size, void *data)
816 struct qcuefi_client *qcuefi;
819 qcuefi = qcuefi_acquire();
821 return EFI_NOT_READY;
823 status = qsee_uefi_set_variable(qcuefi, name, vendor, attr, data_size, data);
829 static efi_status_t qcuefi_get_next_variable(unsigned long *name_size, efi_char16_t *name,
832 struct qcuefi_client *qcuefi;
835 qcuefi = qcuefi_acquire();
837 return EFI_NOT_READY;
839 status = qsee_uefi_get_next_variable(qcuefi, name_size, name, vendor);
845 static efi_status_t qcuefi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space,
846 u64 *max_variable_size)
848 struct qcuefi_client *qcuefi;
851 qcuefi = qcuefi_acquire();
853 return EFI_NOT_READY;
855 status = qsee_uefi_query_variable_info(qcuefi, attr, storage_space, remaining_space,
862 static const struct efivar_operations qcom_efivar_ops = {
863 .get_variable = qcuefi_get_variable,
864 .set_variable = qcuefi_set_variable,
865 .get_next_variable = qcuefi_get_next_variable,
866 .query_variable_info = qcuefi_query_variable_info,
869 /* -- Driver setup. --------------------------------------------------------- */
871 static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
872 const struct auxiliary_device_id *aux_dev_id)
874 struct qcuefi_client *qcuefi;
877 qcuefi = devm_kzalloc(&aux_dev->dev, sizeof(*qcuefi), GFP_KERNEL);
881 qcuefi->client = container_of(aux_dev, struct qseecom_client, aux_dev);
883 auxiliary_set_drvdata(aux_dev, qcuefi);
884 status = qcuefi_set_reference(qcuefi);
888 status = efivars_register(&qcuefi->efivars, &qcom_efivar_ops);
890 qcuefi_set_reference(NULL);
895 static void qcom_uefisecapp_remove(struct auxiliary_device *aux_dev)
897 struct qcuefi_client *qcuefi = auxiliary_get_drvdata(aux_dev);
899 efivars_unregister(&qcuefi->efivars);
900 qcuefi_set_reference(NULL);
903 static const struct auxiliary_device_id qcom_uefisecapp_id_table[] = {
904 { .name = "qcom_qseecom.uefisecapp" },
907 MODULE_DEVICE_TABLE(auxiliary, qcom_uefisecapp_id_table);
909 static struct auxiliary_driver qcom_uefisecapp_driver = {
910 .probe = qcom_uefisecapp_probe,
911 .remove = qcom_uefisecapp_remove,
912 .id_table = qcom_uefisecapp_id_table,
914 .name = "qcom_qseecom_uefisecapp",
915 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
918 module_auxiliary_driver(qcom_uefisecapp_driver);
920 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
921 MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App");
922 MODULE_LICENSE("GPL");