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/sizes.h>
17 #include <linux/slab.h>
18 #include <linux/types.h>
19 #include <linux/ucs2_string.h>
21 #include <linux/firmware/qcom/qcom_qseecom.h>
22 #include <linux/firmware/qcom/qcom_scm.h>
23 #include <linux/firmware/qcom/qcom_tzmem.h>
25 /* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */
27 /* Maximum length of name string with null-terminator */
28 #define QSEE_MAX_NAME_LEN 1024
30 #define QSEE_CMD_UEFI(x) (0x8000 | (x))
31 #define QSEE_CMD_UEFI_GET_VARIABLE QSEE_CMD_UEFI(0)
32 #define QSEE_CMD_UEFI_SET_VARIABLE QSEE_CMD_UEFI(1)
33 #define QSEE_CMD_UEFI_GET_NEXT_VARIABLE QSEE_CMD_UEFI(2)
34 #define QSEE_CMD_UEFI_QUERY_VARIABLE_INFO QSEE_CMD_UEFI(3)
37 * struct qsee_req_uefi_get_variable - Request for GetVariable command.
38 * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_GET_VARIABLE.
39 * @length: Length of the request in bytes, including this struct and any
40 * parameters (name, GUID) stored after it as well as any padding
41 * thereof for alignment.
42 * @name_offset: Offset from the start of this struct to where the variable
43 * name is stored (as utf-16 string), in bytes.
44 * @name_size: Size of the name parameter in bytes, including null-terminator.
45 * @guid_offset: Offset from the start of this struct to where the GUID
46 * parameter is stored, in bytes.
47 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
48 * @data_size: Size of the output buffer, in bytes.
50 struct qsee_req_uefi_get_variable
{
61 * struct qsee_rsp_uefi_get_variable - Response for GetVariable command.
62 * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_GET_VARIABLE.
63 * @length: Length of the response in bytes, including this struct and the
65 * @status: Status of this command.
66 * @attributes: EFI variable attributes.
67 * @data_offset: Offset from the start of this struct to where the data is
69 * @data_size: Size of the returned data, in bytes. In case status indicates
70 * that the buffer is too small, this will be the size required
71 * to store the EFI variable data.
73 struct qsee_rsp_uefi_get_variable
{
83 * struct qsee_req_uefi_set_variable - Request for the SetVariable command.
84 * @command_id: The ID of the command. Must be %QSEE_CMD_UEFI_SET_VARIABLE.
85 * @length: Length of the request in bytes, including this struct and any
86 * parameters (name, GUID, data) stored after it as well as any
87 * padding thereof required for alignment.
88 * @name_offset: Offset from the start of this struct to where the variable
89 * name is stored (as utf-16 string), in bytes.
90 * @name_size: Size of the name parameter in bytes, including null-terminator.
91 * @guid_offset: Offset from the start of this struct to where the GUID
92 * parameter is stored, in bytes.
93 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
94 * @attributes: The EFI variable attributes to set for this variable.
95 * @data_offset: Offset from the start of this struct to where the EFI variable
96 * data is stored, in bytes.
97 * @data_size: Size of EFI variable data, in bytes.
100 struct qsee_req_uefi_set_variable
{
113 * struct qsee_rsp_uefi_set_variable - Response for the SetVariable command.
114 * @command_id: The ID of the command. Should be %QSEE_CMD_UEFI_SET_VARIABLE.
115 * @length: The length of this response, i.e. the size of this struct in
117 * @status: Status of this command.
118 * @_unknown1: Unknown response field.
119 * @_unknown2: Unknown response field.
121 struct qsee_rsp_uefi_set_variable
{
130 * struct qsee_req_uefi_get_next_variable - Request for the
131 * GetNextVariableName command.
132 * @command_id: The ID of the command. Must be
133 * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE.
134 * @length: Length of the request in bytes, including this struct and any
135 * parameters (name, GUID) stored after it as well as any padding
136 * thereof for alignment.
137 * @guid_offset: Offset from the start of this struct to where the GUID
138 * parameter is stored, in bytes.
139 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
140 * @name_offset: Offset from the start of this struct to where the variable
141 * name is stored (as utf-16 string), in bytes.
142 * @name_size: Size of the name parameter in bytes, including null-terminator.
144 struct qsee_req_uefi_get_next_variable
{
154 * struct qsee_rsp_uefi_get_next_variable - Response for the
155 * GetNextVariableName command.
156 * @command_id: The ID of the command. Should be
157 * %QSEE_CMD_UEFI_GET_NEXT_VARIABLE.
158 * @length: Length of the response in bytes, including this struct and any
159 * parameters (name, GUID) stored after it as well as any padding
160 * thereof for alignment.
161 * @status: Status of this command.
162 * @guid_offset: Offset from the start of this struct to where the GUID
163 * parameter is stored, in bytes.
164 * @guid_size: Size of the GUID parameter in bytes, i.e. sizeof(efi_guid_t).
165 * @name_offset: Offset from the start of this struct to where the variable
166 * name is stored (as utf-16 string), in bytes.
167 * @name_size: Size of the name parameter in bytes, including null-terminator.
169 struct qsee_rsp_uefi_get_next_variable
{
180 * struct qsee_req_uefi_query_variable_info - Response for the
181 * GetNextVariableName command.
182 * @command_id: The ID of the command. Must be
183 * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO.
184 * @length: The length of this request, i.e. the size of this struct in
186 * @attributes: The storage attributes to query the info for.
188 struct qsee_req_uefi_query_variable_info
{
195 * struct qsee_rsp_uefi_query_variable_info - Response for the
196 * GetNextVariableName command.
197 * @command_id: The ID of the command. Must be
198 * %QSEE_CMD_UEFI_QUERY_VARIABLE_INFO.
199 * @length: The length of this response, i.e. the size of this
201 * @status: Status of this command.
203 * @storage_space: Full storage space size, in bytes.
204 * @remaining_space: Free storage space available, in bytes.
205 * @max_variable_size: Maximum variable data size, in bytes.
207 struct qsee_rsp_uefi_query_variable_info
{
214 u64 max_variable_size
;
217 /* -- Alignment helpers ----------------------------------------------------- */
220 * Helper macro to ensure proper alignment of types (fields and arrays) when
221 * stored in some (contiguous) buffer.
223 * Note: The driver from which this one has been reverse-engineered expects an
224 * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
225 * however, has an alignment of 4 byte (32 bits). So far, this seems to work
226 * fine here. See also the comment on the typedef of efi_guid_t.
228 * Note: It looks like uefisecapp is quite picky about how the memory passed to
229 * it is structured and aligned. In particular the request/response setup used
230 * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory,
231 * accepts separate buffers/addresses for the request and response parts, in
232 * practice, however, it seems to expect them to be both part of a larger
233 * contiguous block. We initially allocated separate buffers for the request
234 * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to
235 * either not write any response to the response buffer or outright crash the
236 * device. Therefore, we now allocate a single contiguous block of DMA memory
237 * for both and properly align the data using the macros below. In particular,
238 * request and response structs are aligned at 8 byte (via __reqdata_offs()),
239 * following the driver that this has been reverse-engineered from.
241 #define qcuefi_buf_align_fields(fields...) \
248 #define __field_impl(size, align, offset) \
250 size_t *__offset = (offset); \
253 __aligned = ALIGN(__len, align); \
254 __len = __aligned + (size); \
257 *__offset = __aligned; \
260 #define __array_offs(type, count, offset) \
261 __field_impl(sizeof(type) * (count), __alignof__(type), offset)
263 #define __array_offs_aligned(type, count, align, offset) \
264 __field_impl(sizeof(type) * (count), align, offset)
266 #define __reqdata_offs(size, offset) \
267 __array_offs_aligned(u8, size, 8, offset)
269 #define __array(type, count) __array_offs(type, count, NULL)
270 #define __field_offs(type, offset) __array_offs(type, 1, offset)
271 #define __field(type) __array_offs(type, 1, NULL)
273 /* -- UEFI app interface. --------------------------------------------------- */
275 struct qcuefi_client
{
276 struct qseecom_client
*client
;
277 struct efivars efivars
;
278 struct qcom_tzmem_pool
*mempool
;
281 static struct device
*qcuefi_dev(struct qcuefi_client
*qcuefi
)
283 return &qcuefi
->client
->aux_dev
.dev
;
286 static efi_status_t
qsee_uefi_status_to_efi(u32 status
)
288 u64 category
= status
& 0xf0000000;
289 u64 code
= status
& 0x0fffffff;
291 return category
<< (BITS_PER_LONG
- 32) | code
;
294 static efi_status_t
qsee_uefi_get_variable(struct qcuefi_client
*qcuefi
, const efi_char16_t
*name
,
295 const efi_guid_t
*guid
, u32
*attributes
,
296 unsigned long *data_size
, void *data
)
298 struct qsee_req_uefi_get_variable
*req_data
;
299 struct qsee_rsp_uefi_get_variable
*rsp_data
;
300 void *cmd_buf
__free(qcom_tzmem
) = NULL
;
301 unsigned long buffer_size
= *data_size
;
302 unsigned long name_length
;
303 efi_status_t efi_status
;
314 return EFI_INVALID_PARAMETER
;
316 name_length
= ucs2_strnlen(name
, QSEE_MAX_NAME_LEN
) + 1;
317 if (name_length
> QSEE_MAX_NAME_LEN
)
318 return EFI_INVALID_PARAMETER
;
320 if (buffer_size
&& !data
)
321 return EFI_INVALID_PARAMETER
;
323 req_size
= qcuefi_buf_align_fields(
325 __array_offs(*name
, name_length
, &name_offs
)
326 __field_offs(*guid
, &guid_offs
)
329 rsp_size
= qcuefi_buf_align_fields(
331 __array(u8
, buffer_size
)
334 cmd_buf_size
= qcuefi_buf_align_fields(
335 __reqdata_offs(req_size
, &req_offs
)
336 __reqdata_offs(rsp_size
, &rsp_offs
)
339 cmd_buf
= qcom_tzmem_alloc(qcuefi
->mempool
, cmd_buf_size
, GFP_KERNEL
);
341 return EFI_OUT_OF_RESOURCES
;
343 req_data
= cmd_buf
+ req_offs
;
344 rsp_data
= cmd_buf
+ rsp_offs
;
346 req_data
->command_id
= QSEE_CMD_UEFI_GET_VARIABLE
;
347 req_data
->data_size
= buffer_size
;
348 req_data
->name_offset
= name_offs
;
349 req_data
->name_size
= name_length
* sizeof(*name
);
350 req_data
->guid_offset
= guid_offs
;
351 req_data
->guid_size
= sizeof(*guid
);
352 req_data
->length
= req_size
;
354 status
= ucs2_strscpy(((void *)req_data
) + req_data
->name_offset
, name
, name_length
);
356 return EFI_INVALID_PARAMETER
;
358 memcpy(((void *)req_data
) + req_data
->guid_offset
, guid
, req_data
->guid_size
);
360 status
= qcom_qseecom_app_send(qcuefi
->client
,
361 cmd_buf
+ req_offs
, req_size
,
362 cmd_buf
+ rsp_offs
, rsp_size
);
364 return EFI_DEVICE_ERROR
;
366 if (rsp_data
->command_id
!= QSEE_CMD_UEFI_GET_VARIABLE
)
367 return EFI_DEVICE_ERROR
;
369 if (rsp_data
->length
< sizeof(*rsp_data
))
370 return EFI_DEVICE_ERROR
;
372 if (rsp_data
->status
) {
373 dev_dbg(qcuefi_dev(qcuefi
), "%s: uefisecapp error: 0x%x\n",
374 __func__
, rsp_data
->status
);
375 efi_status
= qsee_uefi_status_to_efi(rsp_data
->status
);
377 /* Update size and attributes in case buffer is too small. */
378 if (efi_status
== EFI_BUFFER_TOO_SMALL
) {
379 *data_size
= rsp_data
->data_size
;
381 *attributes
= rsp_data
->attributes
;
384 return qsee_uefi_status_to_efi(rsp_data
->status
);
387 if (rsp_data
->length
> rsp_size
)
388 return EFI_DEVICE_ERROR
;
390 if (rsp_data
->data_offset
+ rsp_data
->data_size
> rsp_data
->length
)
391 return EFI_DEVICE_ERROR
;
394 * Note: We need to set attributes and data size even if the buffer is
395 * too small and we won't copy any data. This is described in spec, so
396 * that callers can either allocate a buffer properly (with two calls
397 * to this function) or just read back attributes withouth having to
401 * - If we have a buffer size of zero and no buffer, just return the
402 * attributes, required size, and indicate success.
403 * - If the buffer size is nonzero but too small, indicate that as an
405 * - Otherwise, we are good to copy the data.
407 * Note that we have already ensured above that the buffer pointer is
408 * non-NULL if its size is nonzero.
410 *data_size
= rsp_data
->data_size
;
412 *attributes
= rsp_data
->attributes
;
414 if (buffer_size
== 0 && !data
)
417 if (buffer_size
< rsp_data
->data_size
)
418 return EFI_BUFFER_TOO_SMALL
;
420 memcpy(data
, ((void *)rsp_data
) + rsp_data
->data_offset
, rsp_data
->data_size
);
425 static efi_status_t
qsee_uefi_set_variable(struct qcuefi_client
*qcuefi
, const efi_char16_t
*name
,
426 const efi_guid_t
*guid
, u32 attributes
,
427 unsigned long data_size
, const void *data
)
429 struct qsee_req_uefi_set_variable
*req_data
;
430 struct qsee_rsp_uefi_set_variable
*rsp_data
;
431 void *cmd_buf
__free(qcom_tzmem
) = NULL
;
432 unsigned long name_length
;
443 return EFI_INVALID_PARAMETER
;
445 name_length
= ucs2_strnlen(name
, QSEE_MAX_NAME_LEN
) + 1;
446 if (name_length
> QSEE_MAX_NAME_LEN
)
447 return EFI_INVALID_PARAMETER
;
450 * Make sure we have some data if data_size is nonzero. Note that using
451 * a size of zero is a valid use-case described in spec and deletes the
454 if (data_size
&& !data
)
455 return EFI_INVALID_PARAMETER
;
457 req_size
= qcuefi_buf_align_fields(
459 __array_offs(*name
, name_length
, &name_offs
)
460 __field_offs(*guid
, &guid_offs
)
461 __array_offs(u8
, data_size
, &data_offs
)
464 cmd_buf_size
= qcuefi_buf_align_fields(
465 __reqdata_offs(req_size
, &req_offs
)
466 __reqdata_offs(sizeof(*rsp_data
), &rsp_offs
)
469 cmd_buf
= qcom_tzmem_alloc(qcuefi
->mempool
, cmd_buf_size
, GFP_KERNEL
);
471 return EFI_OUT_OF_RESOURCES
;
473 req_data
= cmd_buf
+ req_offs
;
474 rsp_data
= cmd_buf
+ rsp_offs
;
476 req_data
->command_id
= QSEE_CMD_UEFI_SET_VARIABLE
;
477 req_data
->attributes
= attributes
;
478 req_data
->name_offset
= name_offs
;
479 req_data
->name_size
= name_length
* sizeof(*name
);
480 req_data
->guid_offset
= guid_offs
;
481 req_data
->guid_size
= sizeof(*guid
);
482 req_data
->data_offset
= data_offs
;
483 req_data
->data_size
= data_size
;
484 req_data
->length
= req_size
;
486 status
= ucs2_strscpy(((void *)req_data
) + req_data
->name_offset
, name
, name_length
);
488 return EFI_INVALID_PARAMETER
;
490 memcpy(((void *)req_data
) + req_data
->guid_offset
, guid
, req_data
->guid_size
);
493 memcpy(((void *)req_data
) + req_data
->data_offset
, data
, req_data
->data_size
);
495 status
= qcom_qseecom_app_send(qcuefi
->client
,
496 cmd_buf
+ req_offs
, req_size
,
497 cmd_buf
+ rsp_offs
, sizeof(*rsp_data
));
499 return EFI_DEVICE_ERROR
;
501 if (rsp_data
->command_id
!= QSEE_CMD_UEFI_SET_VARIABLE
)
502 return EFI_DEVICE_ERROR
;
504 if (rsp_data
->length
!= sizeof(*rsp_data
))
505 return EFI_DEVICE_ERROR
;
507 if (rsp_data
->status
) {
508 dev_dbg(qcuefi_dev(qcuefi
), "%s: uefisecapp error: 0x%x\n",
509 __func__
, rsp_data
->status
);
510 return qsee_uefi_status_to_efi(rsp_data
->status
);
516 static efi_status_t
qsee_uefi_get_next_variable(struct qcuefi_client
*qcuefi
,
517 unsigned long *name_size
, efi_char16_t
*name
,
520 struct qsee_req_uefi_get_next_variable
*req_data
;
521 struct qsee_rsp_uefi_get_next_variable
*rsp_data
;
522 void *cmd_buf
__free(qcom_tzmem
) = NULL
;
523 efi_status_t efi_status
;
533 if (!name_size
|| !name
|| !guid
)
534 return EFI_INVALID_PARAMETER
;
537 return EFI_INVALID_PARAMETER
;
539 req_size
= qcuefi_buf_align_fields(
541 __field_offs(*guid
, &guid_offs
)
542 __array_offs(*name
, *name_size
/ sizeof(*name
), &name_offs
)
545 rsp_size
= qcuefi_buf_align_fields(
548 __array(*name
, *name_size
/ sizeof(*name
))
551 cmd_buf_size
= qcuefi_buf_align_fields(
552 __reqdata_offs(req_size
, &req_offs
)
553 __reqdata_offs(rsp_size
, &rsp_offs
)
556 cmd_buf
= qcom_tzmem_alloc(qcuefi
->mempool
, cmd_buf_size
, GFP_KERNEL
);
558 return EFI_OUT_OF_RESOURCES
;
560 req_data
= cmd_buf
+ req_offs
;
561 rsp_data
= cmd_buf
+ rsp_offs
;
563 req_data
->command_id
= QSEE_CMD_UEFI_GET_NEXT_VARIABLE
;
564 req_data
->guid_offset
= guid_offs
;
565 req_data
->guid_size
= sizeof(*guid
);
566 req_data
->name_offset
= name_offs
;
567 req_data
->name_size
= *name_size
;
568 req_data
->length
= req_size
;
570 memcpy(((void *)req_data
) + req_data
->guid_offset
, guid
, req_data
->guid_size
);
571 status
= ucs2_strscpy(((void *)req_data
) + req_data
->name_offset
, name
,
572 *name_size
/ sizeof(*name
));
574 return EFI_INVALID_PARAMETER
;
576 status
= qcom_qseecom_app_send(qcuefi
->client
,
577 cmd_buf
+ req_offs
, req_size
,
578 cmd_buf
+ rsp_offs
, rsp_size
);
580 return EFI_DEVICE_ERROR
;
582 if (rsp_data
->command_id
!= QSEE_CMD_UEFI_GET_NEXT_VARIABLE
)
583 return EFI_DEVICE_ERROR
;
585 if (rsp_data
->length
< sizeof(*rsp_data
))
586 return EFI_DEVICE_ERROR
;
588 if (rsp_data
->status
) {
589 dev_dbg(qcuefi_dev(qcuefi
), "%s: uefisecapp error: 0x%x\n",
590 __func__
, rsp_data
->status
);
591 efi_status
= qsee_uefi_status_to_efi(rsp_data
->status
);
594 * If the buffer to hold the name is too small, update the
595 * name_size with the required size, so that callers can
596 * reallocate it accordingly.
598 if (efi_status
== EFI_BUFFER_TOO_SMALL
)
599 *name_size
= rsp_data
->name_size
;
604 if (rsp_data
->length
> rsp_size
)
605 return EFI_DEVICE_ERROR
;
607 if (rsp_data
->name_offset
+ rsp_data
->name_size
> rsp_data
->length
)
608 return EFI_DEVICE_ERROR
;
610 if (rsp_data
->guid_offset
+ rsp_data
->guid_size
> rsp_data
->length
)
611 return EFI_DEVICE_ERROR
;
613 if (rsp_data
->name_size
> *name_size
) {
614 *name_size
= rsp_data
->name_size
;
615 return EFI_BUFFER_TOO_SMALL
;
618 if (rsp_data
->guid_size
!= sizeof(*guid
))
619 return EFI_DEVICE_ERROR
;
621 memcpy(guid
, ((void *)rsp_data
) + rsp_data
->guid_offset
, rsp_data
->guid_size
);
622 status
= ucs2_strscpy(name
, ((void *)rsp_data
) + rsp_data
->name_offset
,
623 rsp_data
->name_size
/ sizeof(*name
));
624 *name_size
= rsp_data
->name_size
;
628 * Return EFI_DEVICE_ERROR here because the buffer size should
629 * have already been validated above, causing this function to
630 * bail with EFI_BUFFER_TOO_SMALL.
632 return EFI_DEVICE_ERROR
;
637 static efi_status_t
qsee_uefi_query_variable_info(struct qcuefi_client
*qcuefi
, u32 attr
,
638 u64
*storage_space
, u64
*remaining_space
,
639 u64
*max_variable_size
)
641 struct qsee_req_uefi_query_variable_info
*req_data
;
642 struct qsee_rsp_uefi_query_variable_info
*rsp_data
;
643 void *cmd_buf
__free(qcom_tzmem
) = NULL
;
649 cmd_buf_size
= qcuefi_buf_align_fields(
650 __reqdata_offs(sizeof(*req_data
), &req_offs
)
651 __reqdata_offs(sizeof(*rsp_data
), &rsp_offs
)
654 cmd_buf
= qcom_tzmem_alloc(qcuefi
->mempool
, cmd_buf_size
, GFP_KERNEL
);
656 return EFI_OUT_OF_RESOURCES
;
658 req_data
= cmd_buf
+ req_offs
;
659 rsp_data
= cmd_buf
+ rsp_offs
;
661 req_data
->command_id
= QSEE_CMD_UEFI_QUERY_VARIABLE_INFO
;
662 req_data
->attributes
= attr
;
663 req_data
->length
= sizeof(*req_data
);
665 status
= qcom_qseecom_app_send(qcuefi
->client
,
666 cmd_buf
+ req_offs
, sizeof(*req_data
),
667 cmd_buf
+ rsp_offs
, sizeof(*rsp_data
));
669 return EFI_DEVICE_ERROR
;
671 if (rsp_data
->command_id
!= QSEE_CMD_UEFI_QUERY_VARIABLE_INFO
)
672 return EFI_DEVICE_ERROR
;
674 if (rsp_data
->length
!= sizeof(*rsp_data
))
675 return EFI_DEVICE_ERROR
;
677 if (rsp_data
->status
) {
678 dev_dbg(qcuefi_dev(qcuefi
), "%s: uefisecapp error: 0x%x\n",
679 __func__
, rsp_data
->status
);
680 return qsee_uefi_status_to_efi(rsp_data
->status
);
684 *storage_space
= rsp_data
->storage_space
;
687 *remaining_space
= rsp_data
->remaining_space
;
689 if (max_variable_size
)
690 *max_variable_size
= rsp_data
->max_variable_size
;
695 /* -- Global efivar interface. ---------------------------------------------- */
697 static struct qcuefi_client
*__qcuefi
;
698 static DEFINE_MUTEX(__qcuefi_lock
);
700 static int qcuefi_set_reference(struct qcuefi_client
*qcuefi
)
702 mutex_lock(&__qcuefi_lock
);
704 if (qcuefi
&& __qcuefi
) {
705 mutex_unlock(&__qcuefi_lock
);
711 mutex_unlock(&__qcuefi_lock
);
715 static struct qcuefi_client
*qcuefi_acquire(void)
717 mutex_lock(&__qcuefi_lock
);
719 mutex_unlock(&__qcuefi_lock
);
725 static void qcuefi_release(void)
727 mutex_unlock(&__qcuefi_lock
);
730 static efi_status_t
qcuefi_get_variable(efi_char16_t
*name
, efi_guid_t
*vendor
, u32
*attr
,
731 unsigned long *data_size
, void *data
)
733 struct qcuefi_client
*qcuefi
;
736 qcuefi
= qcuefi_acquire();
738 return EFI_NOT_READY
;
740 status
= qsee_uefi_get_variable(qcuefi
, name
, vendor
, attr
, data_size
, data
);
746 static efi_status_t
qcuefi_set_variable(efi_char16_t
*name
, efi_guid_t
*vendor
,
747 u32 attr
, unsigned long data_size
, void *data
)
749 struct qcuefi_client
*qcuefi
;
752 qcuefi
= qcuefi_acquire();
754 return EFI_NOT_READY
;
756 status
= qsee_uefi_set_variable(qcuefi
, name
, vendor
, attr
, data_size
, data
);
762 static efi_status_t
qcuefi_get_next_variable(unsigned long *name_size
, efi_char16_t
*name
,
765 struct qcuefi_client
*qcuefi
;
768 qcuefi
= qcuefi_acquire();
770 return EFI_NOT_READY
;
772 status
= qsee_uefi_get_next_variable(qcuefi
, name_size
, name
, vendor
);
778 static efi_status_t
qcuefi_query_variable_info(u32 attr
, u64
*storage_space
, u64
*remaining_space
,
779 u64
*max_variable_size
)
781 struct qcuefi_client
*qcuefi
;
784 qcuefi
= qcuefi_acquire();
786 return EFI_NOT_READY
;
788 status
= qsee_uefi_query_variable_info(qcuefi
, attr
, storage_space
, remaining_space
,
795 static const struct efivar_operations qcom_efivar_ops
= {
796 .get_variable
= qcuefi_get_variable
,
797 .set_variable
= qcuefi_set_variable
,
798 .get_next_variable
= qcuefi_get_next_variable
,
799 .query_variable_info
= qcuefi_query_variable_info
,
802 /* -- Driver setup. --------------------------------------------------------- */
804 static int qcom_uefisecapp_probe(struct auxiliary_device
*aux_dev
,
805 const struct auxiliary_device_id
*aux_dev_id
)
807 struct qcom_tzmem_pool_config pool_config
;
808 struct qcuefi_client
*qcuefi
;
811 qcuefi
= devm_kzalloc(&aux_dev
->dev
, sizeof(*qcuefi
), GFP_KERNEL
);
815 qcuefi
->client
= container_of(aux_dev
, struct qseecom_client
, aux_dev
);
817 auxiliary_set_drvdata(aux_dev
, qcuefi
);
818 status
= qcuefi_set_reference(qcuefi
);
822 status
= efivars_register(&qcuefi
->efivars
, &qcom_efivar_ops
);
824 qcuefi_set_reference(NULL
);
826 memset(&pool_config
, 0, sizeof(pool_config
));
827 pool_config
.initial_size
= SZ_4K
;
828 pool_config
.policy
= QCOM_TZMEM_POLICY_MULTIPLIER
;
829 pool_config
.increment
= 2;
830 pool_config
.max_size
= SZ_256K
;
832 qcuefi
->mempool
= devm_qcom_tzmem_pool_new(&aux_dev
->dev
, &pool_config
);
833 if (IS_ERR(qcuefi
->mempool
))
834 return PTR_ERR(qcuefi
->mempool
);
839 static void qcom_uefisecapp_remove(struct auxiliary_device
*aux_dev
)
841 struct qcuefi_client
*qcuefi
= auxiliary_get_drvdata(aux_dev
);
843 efivars_unregister(&qcuefi
->efivars
);
844 qcuefi_set_reference(NULL
);
847 static const struct auxiliary_device_id qcom_uefisecapp_id_table
[] = {
848 { .name
= "qcom_qseecom.uefisecapp" },
851 MODULE_DEVICE_TABLE(auxiliary
, qcom_uefisecapp_id_table
);
853 static struct auxiliary_driver qcom_uefisecapp_driver
= {
854 .probe
= qcom_uefisecapp_probe
,
855 .remove
= qcom_uefisecapp_remove
,
856 .id_table
= qcom_uefisecapp_id_table
,
858 .name
= "qcom_qseecom_uefisecapp",
859 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
862 module_auxiliary_driver(qcom_uefisecapp_driver
);
864 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
865 MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App");
866 MODULE_LICENSE("GPL");