xref: /linux/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c (revision eb01fe7abbe2d0b38824d2a93fdb4cc3eaf2ccc1)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
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.
6  *
7  * Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
8  */
9 
10 #include <linux/efi.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/of.h>
15 #include <linux/platform_device.h>
16 #include <linux/slab.h>
17 #include <linux/types.h>
18 #include <linux/ucs2_string.h>
19 
20 #include <linux/firmware/qcom/qcom_qseecom.h>
21 
22 /* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */
23 
24 /* Maximum length of name string with null-terminator */
25 #define QSEE_MAX_NAME_LEN			1024
26 
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)
32 
33 /**
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.
46  */
47 struct qsee_req_uefi_get_variable {
48 	u32 command_id;
49 	u32 length;
50 	u32 name_offset;
51 	u32 name_size;
52 	u32 guid_offset;
53 	u32 guid_size;
54 	u32 data_size;
55 } __packed;
56 
57 /**
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
61  *               returned data.
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
65  *               stored, in bytes.
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.
69  */
70 struct qsee_rsp_uefi_get_variable {
71 	u32 command_id;
72 	u32 length;
73 	u32 status;
74 	u32 attributes;
75 	u32 data_offset;
76 	u32 data_size;
77 } __packed;
78 
79 /**
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.
95  *
96  */
97 struct qsee_req_uefi_set_variable {
98 	u32 command_id;
99 	u32 length;
100 	u32 name_offset;
101 	u32 name_size;
102 	u32 guid_offset;
103 	u32 guid_size;
104 	u32 attributes;
105 	u32 data_offset;
106 	u32 data_size;
107 } __packed;
108 
109 /**
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
113  *               bytes.
114  * @status:      Status of this command.
115  * @_unknown1:   Unknown response field.
116  * @_unknown2:   Unknown response field.
117  */
118 struct qsee_rsp_uefi_set_variable {
119 	u32 command_id;
120 	u32 length;
121 	u32 status;
122 	u32 _unknown1;
123 	u32 _unknown2;
124 } __packed;
125 
126 /**
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.
140  */
141 struct qsee_req_uefi_get_next_variable {
142 	u32 command_id;
143 	u32 length;
144 	u32 guid_offset;
145 	u32 guid_size;
146 	u32 name_offset;
147 	u32 name_size;
148 } __packed;
149 
150 /**
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.
165  */
166 struct qsee_rsp_uefi_get_next_variable {
167 	u32 command_id;
168 	u32 length;
169 	u32 status;
170 	u32 guid_offset;
171 	u32 guid_size;
172 	u32 name_offset;
173 	u32 name_size;
174 } __packed;
175 
176 /**
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
182  *              bytes.
183  * @attributes: The storage attributes to query the info for.
184  */
185 struct qsee_req_uefi_query_variable_info {
186 	u32 command_id;
187 	u32 length;
188 	u32 attributes;
189 } __packed;
190 
191 /**
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
197  *                     struct in bytes.
198  * @status:            Status of this command.
199  * @_pad:              Padding.
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.
203  */
204 struct qsee_rsp_uefi_query_variable_info {
205 	u32 command_id;
206 	u32 length;
207 	u32 status;
208 	u32 _pad;
209 	u64 storage_space;
210 	u64 remaining_space;
211 	u64 max_variable_size;
212 } __packed;
213 
214 /* -- Alignment helpers ----------------------------------------------------- */
215 
216 /*
217  * Helper macro to ensure proper alignment of types (fields and arrays) when
218  * stored in some (contiguous) buffer.
219  *
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.
224  */
225 #define qcuefi_buf_align_fields(fields...)					\
226 	({									\
227 		size_t __len = 0;						\
228 		fields								\
229 		__len;								\
230 	})
231 
232 #define __field_impl(size, align, offset)					\
233 	({									\
234 		size_t *__offset = (offset);					\
235 		size_t __aligned;						\
236 										\
237 		__aligned = ALIGN(__len, align);				\
238 		__len = __aligned + (size);					\
239 										\
240 		if (__offset)							\
241 			*__offset = __aligned;					\
242 	});
243 
244 #define __array_offs(type, count, offset)					\
245 	__field_impl(sizeof(type) * (count), __alignof__(type), offset)
246 
247 #define __array(type, count)		__array_offs(type, count, NULL)
248 #define __field_offs(type, offset)	__array_offs(type, 1, offset)
249 #define __field(type)			__array_offs(type, 1, NULL)
250 
251 /* -- UEFI app interface. --------------------------------------------------- */
252 
253 struct qcuefi_client {
254 	struct qseecom_client *client;
255 	struct efivars efivars;
256 };
257 
258 static struct device *qcuefi_dev(struct qcuefi_client *qcuefi)
259 {
260 	return &qcuefi->client->aux_dev.dev;
261 }
262 
263 static efi_status_t qsee_uefi_status_to_efi(u32 status)
264 {
265 	u64 category = status & 0xf0000000;
266 	u64 code = status & 0x0fffffff;
267 
268 	return category << (BITS_PER_LONG - 32) | code;
269 }
270 
271 static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
272 					   const efi_guid_t *guid, u32 *attributes,
273 					   unsigned long *data_size, void *data)
274 {
275 	struct qsee_req_uefi_get_variable *req_data;
276 	struct qsee_rsp_uefi_get_variable *rsp_data;
277 	unsigned long buffer_size = *data_size;
278 	efi_status_t efi_status = EFI_SUCCESS;
279 	unsigned long name_length;
280 	size_t guid_offs;
281 	size_t name_offs;
282 	size_t req_size;
283 	size_t rsp_size;
284 	ssize_t status;
285 
286 	if (!name || !guid)
287 		return EFI_INVALID_PARAMETER;
288 
289 	name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1;
290 	if (name_length > QSEE_MAX_NAME_LEN)
291 		return EFI_INVALID_PARAMETER;
292 
293 	if (buffer_size && !data)
294 		return EFI_INVALID_PARAMETER;
295 
296 	req_size = qcuefi_buf_align_fields(
297 		__field(*req_data)
298 		__array_offs(*name, name_length, &name_offs)
299 		__field_offs(*guid, &guid_offs)
300 	);
301 
302 	rsp_size = qcuefi_buf_align_fields(
303 		__field(*rsp_data)
304 		__array(u8, buffer_size)
305 	);
306 
307 	req_data = kzalloc(req_size, GFP_KERNEL);
308 	if (!req_data) {
309 		efi_status = EFI_OUT_OF_RESOURCES;
310 		goto out;
311 	}
312 
313 	rsp_data = kzalloc(rsp_size, GFP_KERNEL);
314 	if (!rsp_data) {
315 		efi_status = EFI_OUT_OF_RESOURCES;
316 		goto out_free_req;
317 	}
318 
319 	req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE;
320 	req_data->data_size = buffer_size;
321 	req_data->name_offset = name_offs;
322 	req_data->name_size = name_length * sizeof(*name);
323 	req_data->guid_offset = guid_offs;
324 	req_data->guid_size = sizeof(*guid);
325 	req_data->length = req_size;
326 
327 	status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
328 	if (status < 0) {
329 		efi_status = EFI_INVALID_PARAMETER;
330 		goto out_free;
331 	}
332 
333 	memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
334 
335 	status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
336 	if (status) {
337 		efi_status = EFI_DEVICE_ERROR;
338 		goto out_free;
339 	}
340 
341 	if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) {
342 		efi_status = EFI_DEVICE_ERROR;
343 		goto out_free;
344 	}
345 
346 	if (rsp_data->length < sizeof(*rsp_data)) {
347 		efi_status = EFI_DEVICE_ERROR;
348 		goto out_free;
349 	}
350 
351 	if (rsp_data->status) {
352 		dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
353 			__func__, rsp_data->status);
354 		efi_status = qsee_uefi_status_to_efi(rsp_data->status);
355 
356 		/* Update size and attributes in case buffer is too small. */
357 		if (efi_status == EFI_BUFFER_TOO_SMALL) {
358 			*data_size = rsp_data->data_size;
359 			if (attributes)
360 				*attributes = rsp_data->attributes;
361 		}
362 
363 		goto out_free;
364 	}
365 
366 	if (rsp_data->length > rsp_size) {
367 		efi_status = EFI_DEVICE_ERROR;
368 		goto out_free;
369 	}
370 
371 	if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) {
372 		efi_status = EFI_DEVICE_ERROR;
373 		goto out_free;
374 	}
375 
376 	/*
377 	 * Note: We need to set attributes and data size even if the buffer is
378 	 * too small and we won't copy any data. This is described in spec, so
379 	 * that callers can either allocate a buffer properly (with two calls
380 	 * to this function) or just read back attributes withouth having to
381 	 * deal with that.
382 	 *
383 	 * Specifically:
384 	 * - If we have a buffer size of zero and no buffer, just return the
385 	 *   attributes, required size, and indicate success.
386 	 * - If the buffer size is nonzero but too small, indicate that as an
387 	 *   error.
388 	 * - Otherwise, we are good to copy the data.
389 	 *
390 	 * Note that we have already ensured above that the buffer pointer is
391 	 * non-NULL if its size is nonzero.
392 	 */
393 	*data_size = rsp_data->data_size;
394 	if (attributes)
395 		*attributes = rsp_data->attributes;
396 
397 	if (buffer_size == 0 && !data) {
398 		efi_status = EFI_SUCCESS;
399 		goto out_free;
400 	}
401 
402 	if (buffer_size < rsp_data->data_size) {
403 		efi_status = EFI_BUFFER_TOO_SMALL;
404 		goto out_free;
405 	}
406 
407 	memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
408 
409 out_free:
410 	kfree(rsp_data);
411 out_free_req:
412 	kfree(req_data);
413 out:
414 	return efi_status;
415 }
416 
417 static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name,
418 					   const efi_guid_t *guid, u32 attributes,
419 					   unsigned long data_size, const void *data)
420 {
421 	struct qsee_req_uefi_set_variable *req_data;
422 	struct qsee_rsp_uefi_set_variable *rsp_data;
423 	efi_status_t efi_status = EFI_SUCCESS;
424 	unsigned long name_length;
425 	size_t name_offs;
426 	size_t guid_offs;
427 	size_t data_offs;
428 	size_t req_size;
429 	ssize_t status;
430 
431 	if (!name || !guid)
432 		return EFI_INVALID_PARAMETER;
433 
434 	name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1;
435 	if (name_length > QSEE_MAX_NAME_LEN)
436 		return EFI_INVALID_PARAMETER;
437 
438 	/*
439 	 * Make sure we have some data if data_size is nonzero. Note that using
440 	 * a size of zero is a valid use-case described in spec and deletes the
441 	 * variable.
442 	 */
443 	if (data_size && !data)
444 		return EFI_INVALID_PARAMETER;
445 
446 	req_size = qcuefi_buf_align_fields(
447 		__field(*req_data)
448 		__array_offs(*name, name_length, &name_offs)
449 		__field_offs(*guid, &guid_offs)
450 		__array_offs(u8, data_size, &data_offs)
451 	);
452 
453 	req_data = kzalloc(req_size, GFP_KERNEL);
454 	if (!req_data) {
455 		efi_status = EFI_OUT_OF_RESOURCES;
456 		goto out;
457 	}
458 
459 	rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
460 	if (!rsp_data) {
461 		efi_status = EFI_OUT_OF_RESOURCES;
462 		goto out_free_req;
463 	}
464 
465 	req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE;
466 	req_data->attributes = attributes;
467 	req_data->name_offset = name_offs;
468 	req_data->name_size = name_length * sizeof(*name);
469 	req_data->guid_offset = guid_offs;
470 	req_data->guid_size = sizeof(*guid);
471 	req_data->data_offset = data_offs;
472 	req_data->data_size = data_size;
473 	req_data->length = req_size;
474 
475 	status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length);
476 	if (status < 0) {
477 		efi_status = EFI_INVALID_PARAMETER;
478 		goto out_free;
479 	}
480 
481 	memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
482 
483 	if (data_size)
484 		memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size);
485 
486 	status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data,
487 				       sizeof(*rsp_data));
488 	if (status) {
489 		efi_status = EFI_DEVICE_ERROR;
490 		goto out_free;
491 	}
492 
493 	if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) {
494 		efi_status = EFI_DEVICE_ERROR;
495 		goto out_free;
496 	}
497 
498 	if (rsp_data->length != sizeof(*rsp_data)) {
499 		efi_status = EFI_DEVICE_ERROR;
500 		goto out_free;
501 	}
502 
503 	if (rsp_data->status) {
504 		dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
505 			__func__, rsp_data->status);
506 		efi_status = qsee_uefi_status_to_efi(rsp_data->status);
507 	}
508 
509 out_free:
510 	kfree(rsp_data);
511 out_free_req:
512 	kfree(req_data);
513 out:
514 	return efi_status;
515 }
516 
517 static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
518 						unsigned long *name_size, efi_char16_t *name,
519 						efi_guid_t *guid)
520 {
521 	struct qsee_req_uefi_get_next_variable *req_data;
522 	struct qsee_rsp_uefi_get_next_variable *rsp_data;
523 	efi_status_t efi_status = EFI_SUCCESS;
524 	size_t guid_offs;
525 	size_t name_offs;
526 	size_t req_size;
527 	size_t rsp_size;
528 	ssize_t status;
529 
530 	if (!name_size || !name || !guid)
531 		return EFI_INVALID_PARAMETER;
532 
533 	if (*name_size == 0)
534 		return EFI_INVALID_PARAMETER;
535 
536 	req_size = qcuefi_buf_align_fields(
537 		__field(*req_data)
538 		__field_offs(*guid, &guid_offs)
539 		__array_offs(*name, *name_size / sizeof(*name), &name_offs)
540 	);
541 
542 	rsp_size = qcuefi_buf_align_fields(
543 		__field(*rsp_data)
544 		__field(*guid)
545 		__array(*name, *name_size / sizeof(*name))
546 	);
547 
548 	req_data = kzalloc(req_size, GFP_KERNEL);
549 	if (!req_data) {
550 		efi_status = EFI_OUT_OF_RESOURCES;
551 		goto out;
552 	}
553 
554 	rsp_data = kzalloc(rsp_size, GFP_KERNEL);
555 	if (!rsp_data) {
556 		efi_status = EFI_OUT_OF_RESOURCES;
557 		goto out_free_req;
558 	}
559 
560 	req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE;
561 	req_data->guid_offset = guid_offs;
562 	req_data->guid_size = sizeof(*guid);
563 	req_data->name_offset = name_offs;
564 	req_data->name_size = *name_size;
565 	req_data->length = req_size;
566 
567 	memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
568 	status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name,
569 			      *name_size / sizeof(*name));
570 	if (status < 0) {
571 		efi_status = EFI_INVALID_PARAMETER;
572 		goto out_free;
573 	}
574 
575 	status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
576 	if (status) {
577 		efi_status = EFI_DEVICE_ERROR;
578 		goto out_free;
579 	}
580 
581 	if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) {
582 		efi_status = EFI_DEVICE_ERROR;
583 		goto out_free;
584 	}
585 
586 	if (rsp_data->length < sizeof(*rsp_data)) {
587 		efi_status = EFI_DEVICE_ERROR;
588 		goto out_free;
589 	}
590 
591 	if (rsp_data->status) {
592 		dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
593 			__func__, rsp_data->status);
594 		efi_status = qsee_uefi_status_to_efi(rsp_data->status);
595 
596 		/*
597 		 * If the buffer to hold the name is too small, update the
598 		 * name_size with the required size, so that callers can
599 		 * reallocate it accordingly.
600 		 */
601 		if (efi_status == EFI_BUFFER_TOO_SMALL)
602 			*name_size = rsp_data->name_size;
603 
604 		goto out_free;
605 	}
606 
607 	if (rsp_data->length > rsp_size) {
608 		efi_status = EFI_DEVICE_ERROR;
609 		goto out_free;
610 	}
611 
612 	if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) {
613 		efi_status = EFI_DEVICE_ERROR;
614 		goto out_free;
615 	}
616 
617 	if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) {
618 		efi_status = EFI_DEVICE_ERROR;
619 		goto out_free;
620 	}
621 
622 	if (rsp_data->name_size > *name_size) {
623 		*name_size = rsp_data->name_size;
624 		efi_status = EFI_BUFFER_TOO_SMALL;
625 		goto out_free;
626 	}
627 
628 	if (rsp_data->guid_size != sizeof(*guid)) {
629 		efi_status = EFI_DEVICE_ERROR;
630 		goto out_free;
631 	}
632 
633 	memcpy(guid, ((void *)rsp_data) + rsp_data->guid_offset, rsp_data->guid_size);
634 	status = ucs2_strscpy(name, ((void *)rsp_data) + rsp_data->name_offset,
635 			      rsp_data->name_size / sizeof(*name));
636 	*name_size = rsp_data->name_size;
637 
638 	if (status < 0) {
639 		/*
640 		 * Return EFI_DEVICE_ERROR here because the buffer size should
641 		 * have already been validated above, causing this function to
642 		 * bail with EFI_BUFFER_TOO_SMALL.
643 		 */
644 		efi_status = EFI_DEVICE_ERROR;
645 	}
646 
647 out_free:
648 	kfree(rsp_data);
649 out_free_req:
650 	kfree(req_data);
651 out:
652 	return efi_status;
653 }
654 
655 static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, u32 attr,
656 						  u64 *storage_space, u64 *remaining_space,
657 						  u64 *max_variable_size)
658 {
659 	struct qsee_req_uefi_query_variable_info *req_data;
660 	struct qsee_rsp_uefi_query_variable_info *rsp_data;
661 	efi_status_t efi_status = EFI_SUCCESS;
662 	int status;
663 
664 	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
665 	if (!req_data) {
666 		efi_status = EFI_OUT_OF_RESOURCES;
667 		goto out;
668 	}
669 
670 	rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
671 	if (!rsp_data) {
672 		efi_status = EFI_OUT_OF_RESOURCES;
673 		goto out_free_req;
674 	}
675 
676 	req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO;
677 	req_data->attributes = attr;
678 	req_data->length = sizeof(*req_data);
679 
680 	status = qcom_qseecom_app_send(qcuefi->client, req_data, sizeof(*req_data), rsp_data,
681 				       sizeof(*rsp_data));
682 	if (status) {
683 		efi_status = EFI_DEVICE_ERROR;
684 		goto out_free;
685 	}
686 
687 	if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) {
688 		efi_status = EFI_DEVICE_ERROR;
689 		goto out_free;
690 	}
691 
692 	if (rsp_data->length != sizeof(*rsp_data)) {
693 		efi_status = EFI_DEVICE_ERROR;
694 		goto out_free;
695 	}
696 
697 	if (rsp_data->status) {
698 		dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n",
699 			__func__, rsp_data->status);
700 		efi_status = qsee_uefi_status_to_efi(rsp_data->status);
701 		goto out_free;
702 	}
703 
704 	if (storage_space)
705 		*storage_space = rsp_data->storage_space;
706 
707 	if (remaining_space)
708 		*remaining_space = rsp_data->remaining_space;
709 
710 	if (max_variable_size)
711 		*max_variable_size = rsp_data->max_variable_size;
712 
713 out_free:
714 	kfree(rsp_data);
715 out_free_req:
716 	kfree(req_data);
717 out:
718 	return efi_status;
719 }
720 
721 /* -- Global efivar interface. ---------------------------------------------- */
722 
723 static struct qcuefi_client *__qcuefi;
724 static DEFINE_MUTEX(__qcuefi_lock);
725 
726 static int qcuefi_set_reference(struct qcuefi_client *qcuefi)
727 {
728 	mutex_lock(&__qcuefi_lock);
729 
730 	if (qcuefi && __qcuefi) {
731 		mutex_unlock(&__qcuefi_lock);
732 		return -EEXIST;
733 	}
734 
735 	__qcuefi = qcuefi;
736 
737 	mutex_unlock(&__qcuefi_lock);
738 	return 0;
739 }
740 
741 static struct qcuefi_client *qcuefi_acquire(void)
742 {
743 	mutex_lock(&__qcuefi_lock);
744 	return __qcuefi;
745 }
746 
747 static void qcuefi_release(void)
748 {
749 	mutex_unlock(&__qcuefi_lock);
750 }
751 
752 static efi_status_t qcuefi_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
753 					unsigned long *data_size, void *data)
754 {
755 	struct qcuefi_client *qcuefi;
756 	efi_status_t status;
757 
758 	qcuefi = qcuefi_acquire();
759 	if (!qcuefi)
760 		return EFI_NOT_READY;
761 
762 	status = qsee_uefi_get_variable(qcuefi, name, vendor, attr, data_size, data);
763 
764 	qcuefi_release();
765 	return status;
766 }
767 
768 static efi_status_t qcuefi_set_variable(efi_char16_t *name, efi_guid_t *vendor,
769 					u32 attr, unsigned long data_size, void *data)
770 {
771 	struct qcuefi_client *qcuefi;
772 	efi_status_t status;
773 
774 	qcuefi = qcuefi_acquire();
775 	if (!qcuefi)
776 		return EFI_NOT_READY;
777 
778 	status = qsee_uefi_set_variable(qcuefi, name, vendor, attr, data_size, data);
779 
780 	qcuefi_release();
781 	return status;
782 }
783 
784 static efi_status_t qcuefi_get_next_variable(unsigned long *name_size, efi_char16_t *name,
785 					     efi_guid_t *vendor)
786 {
787 	struct qcuefi_client *qcuefi;
788 	efi_status_t status;
789 
790 	qcuefi = qcuefi_acquire();
791 	if (!qcuefi)
792 		return EFI_NOT_READY;
793 
794 	status = qsee_uefi_get_next_variable(qcuefi, name_size, name, vendor);
795 
796 	qcuefi_release();
797 	return status;
798 }
799 
800 static efi_status_t qcuefi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space,
801 					       u64 *max_variable_size)
802 {
803 	struct qcuefi_client *qcuefi;
804 	efi_status_t status;
805 
806 	qcuefi = qcuefi_acquire();
807 	if (!qcuefi)
808 		return EFI_NOT_READY;
809 
810 	status = qsee_uefi_query_variable_info(qcuefi, attr, storage_space, remaining_space,
811 					       max_variable_size);
812 
813 	qcuefi_release();
814 	return status;
815 }
816 
817 static const struct efivar_operations qcom_efivar_ops = {
818 	.get_variable = qcuefi_get_variable,
819 	.set_variable = qcuefi_set_variable,
820 	.get_next_variable = qcuefi_get_next_variable,
821 	.query_variable_info = qcuefi_query_variable_info,
822 };
823 
824 /* -- Driver setup. --------------------------------------------------------- */
825 
826 static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev,
827 				 const struct auxiliary_device_id *aux_dev_id)
828 {
829 	struct qcuefi_client *qcuefi;
830 	int status;
831 
832 	qcuefi = devm_kzalloc(&aux_dev->dev, sizeof(*qcuefi), GFP_KERNEL);
833 	if (!qcuefi)
834 		return -ENOMEM;
835 
836 	qcuefi->client = container_of(aux_dev, struct qseecom_client, aux_dev);
837 
838 	auxiliary_set_drvdata(aux_dev, qcuefi);
839 	status = qcuefi_set_reference(qcuefi);
840 	if (status)
841 		return status;
842 
843 	status = efivars_register(&qcuefi->efivars, &qcom_efivar_ops);
844 	if (status)
845 		qcuefi_set_reference(NULL);
846 
847 	return status;
848 }
849 
850 static void qcom_uefisecapp_remove(struct auxiliary_device *aux_dev)
851 {
852 	struct qcuefi_client *qcuefi = auxiliary_get_drvdata(aux_dev);
853 
854 	efivars_unregister(&qcuefi->efivars);
855 	qcuefi_set_reference(NULL);
856 }
857 
858 static const struct auxiliary_device_id qcom_uefisecapp_id_table[] = {
859 	{ .name = "qcom_qseecom.uefisecapp" },
860 	{}
861 };
862 MODULE_DEVICE_TABLE(auxiliary, qcom_uefisecapp_id_table);
863 
864 static struct auxiliary_driver qcom_uefisecapp_driver = {
865 	.probe = qcom_uefisecapp_probe,
866 	.remove = qcom_uefisecapp_remove,
867 	.id_table = qcom_uefisecapp_id_table,
868 	.driver = {
869 		.name = "qcom_qseecom_uefisecapp",
870 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
871 	},
872 };
873 module_auxiliary_driver(qcom_uefisecapp_driver);
874 
875 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
876 MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App");
877 MODULE_LICENSE("GPL");
878