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/sizes.h> 17 #include <linux/slab.h> 18 #include <linux/types.h> 19 #include <linux/ucs2_string.h> 20 21 #include <linux/firmware/qcom/qcom_qseecom.h> 22 #include <linux/firmware/qcom/qcom_scm.h> 23 #include <linux/firmware/qcom/qcom_tzmem.h> 24 25 /* -- Qualcomm "uefisecapp" interface definitions. -------------------------- */ 26 27 /* Maximum length of name string with null-terminator */ 28 #define QSEE_MAX_NAME_LEN 1024 29 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) 35 36 /** 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. 49 */ 50 struct qsee_req_uefi_get_variable { 51 u32 command_id; 52 u32 length; 53 u32 name_offset; 54 u32 name_size; 55 u32 guid_offset; 56 u32 guid_size; 57 u32 data_size; 58 } __packed; 59 60 /** 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 64 * returned data. 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 68 * stored, in bytes. 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. 72 */ 73 struct qsee_rsp_uefi_get_variable { 74 u32 command_id; 75 u32 length; 76 u32 status; 77 u32 attributes; 78 u32 data_offset; 79 u32 data_size; 80 } __packed; 81 82 /** 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. 98 * 99 */ 100 struct qsee_req_uefi_set_variable { 101 u32 command_id; 102 u32 length; 103 u32 name_offset; 104 u32 name_size; 105 u32 guid_offset; 106 u32 guid_size; 107 u32 attributes; 108 u32 data_offset; 109 u32 data_size; 110 } __packed; 111 112 /** 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 116 * bytes. 117 * @status: Status of this command. 118 * @_unknown1: Unknown response field. 119 * @_unknown2: Unknown response field. 120 */ 121 struct qsee_rsp_uefi_set_variable { 122 u32 command_id; 123 u32 length; 124 u32 status; 125 u32 _unknown1; 126 u32 _unknown2; 127 } __packed; 128 129 /** 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. 143 */ 144 struct qsee_req_uefi_get_next_variable { 145 u32 command_id; 146 u32 length; 147 u32 guid_offset; 148 u32 guid_size; 149 u32 name_offset; 150 u32 name_size; 151 } __packed; 152 153 /** 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. 168 */ 169 struct qsee_rsp_uefi_get_next_variable { 170 u32 command_id; 171 u32 length; 172 u32 status; 173 u32 guid_offset; 174 u32 guid_size; 175 u32 name_offset; 176 u32 name_size; 177 } __packed; 178 179 /** 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 185 * bytes. 186 * @attributes: The storage attributes to query the info for. 187 */ 188 struct qsee_req_uefi_query_variable_info { 189 u32 command_id; 190 u32 length; 191 u32 attributes; 192 } __packed; 193 194 /** 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 200 * struct in bytes. 201 * @status: Status of this command. 202 * @_pad: Padding. 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. 206 */ 207 struct qsee_rsp_uefi_query_variable_info { 208 u32 command_id; 209 u32 length; 210 u32 status; 211 u32 _pad; 212 u64 storage_space; 213 u64 remaining_space; 214 u64 max_variable_size; 215 } __packed; 216 217 /* -- Alignment helpers ----------------------------------------------------- */ 218 219 /* 220 * Helper macro to ensure proper alignment of types (fields and arrays) when 221 * stored in some (contiguous) buffer. 222 * 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. 227 * 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. 240 */ 241 #define qcuefi_buf_align_fields(fields...) \ 242 ({ \ 243 size_t __len = 0; \ 244 fields \ 245 __len; \ 246 }) 247 248 #define __field_impl(size, align, offset) \ 249 ({ \ 250 size_t *__offset = (offset); \ 251 size_t __aligned; \ 252 \ 253 __aligned = ALIGN(__len, align); \ 254 __len = __aligned + (size); \ 255 \ 256 if (__offset) \ 257 *__offset = __aligned; \ 258 }); 259 260 #define __array_offs(type, count, offset) \ 261 __field_impl(sizeof(type) * (count), __alignof__(type), offset) 262 263 #define __array_offs_aligned(type, count, align, offset) \ 264 __field_impl(sizeof(type) * (count), align, offset) 265 266 #define __reqdata_offs(size, offset) \ 267 __array_offs_aligned(u8, size, 8, offset) 268 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) 272 273 /* -- UEFI app interface. --------------------------------------------------- */ 274 275 struct qcuefi_client { 276 struct qseecom_client *client; 277 struct efivars efivars; 278 struct qcom_tzmem_pool *mempool; 279 }; 280 281 static struct device *qcuefi_dev(struct qcuefi_client *qcuefi) 282 { 283 return &qcuefi->client->aux_dev.dev; 284 } 285 286 static efi_status_t qsee_uefi_status_to_efi(u32 status) 287 { 288 u64 category = status & 0xf0000000; 289 u64 code = status & 0x0fffffff; 290 291 return category << (BITS_PER_LONG - 32) | code; 292 } 293 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) 297 { 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; 304 size_t cmd_buf_size; 305 size_t guid_offs; 306 size_t name_offs; 307 size_t req_size; 308 size_t rsp_size; 309 size_t req_offs; 310 size_t rsp_offs; 311 ssize_t status; 312 313 if (!name || !guid) 314 return EFI_INVALID_PARAMETER; 315 316 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1; 317 if (name_length > QSEE_MAX_NAME_LEN) 318 return EFI_INVALID_PARAMETER; 319 320 if (buffer_size && !data) 321 return EFI_INVALID_PARAMETER; 322 323 req_size = qcuefi_buf_align_fields( 324 __field(*req_data) 325 __array_offs(*name, name_length, &name_offs) 326 __field_offs(*guid, &guid_offs) 327 ); 328 329 rsp_size = qcuefi_buf_align_fields( 330 __field(*rsp_data) 331 __array(u8, buffer_size) 332 ); 333 334 cmd_buf_size = qcuefi_buf_align_fields( 335 __reqdata_offs(req_size, &req_offs) 336 __reqdata_offs(rsp_size, &rsp_offs) 337 ); 338 339 cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL); 340 if (!cmd_buf) 341 return EFI_OUT_OF_RESOURCES; 342 343 req_data = cmd_buf + req_offs; 344 rsp_data = cmd_buf + rsp_offs; 345 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; 353 354 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); 355 if (status < 0) 356 return EFI_INVALID_PARAMETER; 357 358 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 359 360 status = qcom_qseecom_app_send(qcuefi->client, 361 cmd_buf + req_offs, req_size, 362 cmd_buf + rsp_offs, rsp_size); 363 if (status) 364 return EFI_DEVICE_ERROR; 365 366 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) 367 return EFI_DEVICE_ERROR; 368 369 if (rsp_data->length < sizeof(*rsp_data)) 370 return EFI_DEVICE_ERROR; 371 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); 376 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; 380 if (attributes) 381 *attributes = rsp_data->attributes; 382 } 383 384 return qsee_uefi_status_to_efi(rsp_data->status); 385 } 386 387 if (rsp_data->length > rsp_size) 388 return EFI_DEVICE_ERROR; 389 390 if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) 391 return EFI_DEVICE_ERROR; 392 393 /* 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 398 * deal with that. 399 * 400 * Specifically: 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 404 * error. 405 * - Otherwise, we are good to copy the data. 406 * 407 * Note that we have already ensured above that the buffer pointer is 408 * non-NULL if its size is nonzero. 409 */ 410 *data_size = rsp_data->data_size; 411 if (attributes) 412 *attributes = rsp_data->attributes; 413 414 if (buffer_size == 0 && !data) 415 return EFI_SUCCESS; 416 417 if (buffer_size < rsp_data->data_size) 418 return EFI_BUFFER_TOO_SMALL; 419 420 memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size); 421 422 return EFI_SUCCESS; 423 } 424 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) 428 { 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; 433 size_t cmd_buf_size; 434 size_t name_offs; 435 size_t guid_offs; 436 size_t data_offs; 437 size_t req_size; 438 size_t req_offs; 439 size_t rsp_offs; 440 ssize_t status; 441 442 if (!name || !guid) 443 return EFI_INVALID_PARAMETER; 444 445 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1; 446 if (name_length > QSEE_MAX_NAME_LEN) 447 return EFI_INVALID_PARAMETER; 448 449 /* 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 452 * variable. 453 */ 454 if (data_size && !data) 455 return EFI_INVALID_PARAMETER; 456 457 req_size = qcuefi_buf_align_fields( 458 __field(*req_data) 459 __array_offs(*name, name_length, &name_offs) 460 __field_offs(*guid, &guid_offs) 461 __array_offs(u8, data_size, &data_offs) 462 ); 463 464 cmd_buf_size = qcuefi_buf_align_fields( 465 __reqdata_offs(req_size, &req_offs) 466 __reqdata_offs(sizeof(*rsp_data), &rsp_offs) 467 ); 468 469 cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL); 470 if (!cmd_buf) 471 return EFI_OUT_OF_RESOURCES; 472 473 req_data = cmd_buf + req_offs; 474 rsp_data = cmd_buf + rsp_offs; 475 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; 485 486 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); 487 if (status < 0) 488 return EFI_INVALID_PARAMETER; 489 490 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 491 492 if (data_size) 493 memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size); 494 495 status = qcom_qseecom_app_send(qcuefi->client, 496 cmd_buf + req_offs, req_size, 497 cmd_buf + rsp_offs, sizeof(*rsp_data)); 498 if (status) 499 return EFI_DEVICE_ERROR; 500 501 if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) 502 return EFI_DEVICE_ERROR; 503 504 if (rsp_data->length != sizeof(*rsp_data)) 505 return EFI_DEVICE_ERROR; 506 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); 511 } 512 513 return EFI_SUCCESS; 514 } 515 516 static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, 517 unsigned long *name_size, efi_char16_t *name, 518 efi_guid_t *guid) 519 { 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; 524 size_t cmd_buf_size; 525 size_t guid_offs; 526 size_t name_offs; 527 size_t req_size; 528 size_t rsp_size; 529 size_t req_offs; 530 size_t rsp_offs; 531 ssize_t status; 532 533 if (!name_size || !name || !guid) 534 return EFI_INVALID_PARAMETER; 535 536 if (*name_size == 0) 537 return EFI_INVALID_PARAMETER; 538 539 req_size = qcuefi_buf_align_fields( 540 __field(*req_data) 541 __field_offs(*guid, &guid_offs) 542 __array_offs(*name, *name_size / sizeof(*name), &name_offs) 543 ); 544 545 rsp_size = qcuefi_buf_align_fields( 546 __field(*rsp_data) 547 __field(*guid) 548 __array(*name, *name_size / sizeof(*name)) 549 ); 550 551 cmd_buf_size = qcuefi_buf_align_fields( 552 __reqdata_offs(req_size, &req_offs) 553 __reqdata_offs(rsp_size, &rsp_offs) 554 ); 555 556 cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL); 557 if (!cmd_buf) 558 return EFI_OUT_OF_RESOURCES; 559 560 req_data = cmd_buf + req_offs; 561 rsp_data = cmd_buf + rsp_offs; 562 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; 569 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)); 573 if (status < 0) 574 return EFI_INVALID_PARAMETER; 575 576 status = qcom_qseecom_app_send(qcuefi->client, 577 cmd_buf + req_offs, req_size, 578 cmd_buf + rsp_offs, rsp_size); 579 if (status) 580 return EFI_DEVICE_ERROR; 581 582 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) 583 return EFI_DEVICE_ERROR; 584 585 if (rsp_data->length < sizeof(*rsp_data)) 586 return EFI_DEVICE_ERROR; 587 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); 592 593 /* 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. 597 */ 598 if (efi_status == EFI_BUFFER_TOO_SMALL) 599 *name_size = rsp_data->name_size; 600 601 return efi_status; 602 } 603 604 if (rsp_data->length > rsp_size) 605 return EFI_DEVICE_ERROR; 606 607 if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) 608 return EFI_DEVICE_ERROR; 609 610 if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) 611 return EFI_DEVICE_ERROR; 612 613 if (rsp_data->name_size > *name_size) { 614 *name_size = rsp_data->name_size; 615 return EFI_BUFFER_TOO_SMALL; 616 } 617 618 if (rsp_data->guid_size != sizeof(*guid)) 619 return EFI_DEVICE_ERROR; 620 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; 625 626 if (status < 0) 627 /* 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. 631 */ 632 return EFI_DEVICE_ERROR; 633 634 return EFI_SUCCESS; 635 } 636 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) 640 { 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; 644 size_t cmd_buf_size; 645 size_t req_offs; 646 size_t rsp_offs; 647 int status; 648 649 cmd_buf_size = qcuefi_buf_align_fields( 650 __reqdata_offs(sizeof(*req_data), &req_offs) 651 __reqdata_offs(sizeof(*rsp_data), &rsp_offs) 652 ); 653 654 cmd_buf = qcom_tzmem_alloc(qcuefi->mempool, cmd_buf_size, GFP_KERNEL); 655 if (!cmd_buf) 656 return EFI_OUT_OF_RESOURCES; 657 658 req_data = cmd_buf + req_offs; 659 rsp_data = cmd_buf + rsp_offs; 660 661 req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO; 662 req_data->attributes = attr; 663 req_data->length = sizeof(*req_data); 664 665 status = qcom_qseecom_app_send(qcuefi->client, 666 cmd_buf + req_offs, sizeof(*req_data), 667 cmd_buf + rsp_offs, sizeof(*rsp_data)); 668 if (status) 669 return EFI_DEVICE_ERROR; 670 671 if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) 672 return EFI_DEVICE_ERROR; 673 674 if (rsp_data->length != sizeof(*rsp_data)) 675 return EFI_DEVICE_ERROR; 676 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); 681 } 682 683 if (storage_space) 684 *storage_space = rsp_data->storage_space; 685 686 if (remaining_space) 687 *remaining_space = rsp_data->remaining_space; 688 689 if (max_variable_size) 690 *max_variable_size = rsp_data->max_variable_size; 691 692 return EFI_SUCCESS; 693 } 694 695 /* -- Global efivar interface. ---------------------------------------------- */ 696 697 static struct qcuefi_client *__qcuefi; 698 static DEFINE_MUTEX(__qcuefi_lock); 699 700 static int qcuefi_set_reference(struct qcuefi_client *qcuefi) 701 { 702 mutex_lock(&__qcuefi_lock); 703 704 if (qcuefi && __qcuefi) { 705 mutex_unlock(&__qcuefi_lock); 706 return -EEXIST; 707 } 708 709 __qcuefi = qcuefi; 710 711 mutex_unlock(&__qcuefi_lock); 712 return 0; 713 } 714 715 static struct qcuefi_client *qcuefi_acquire(void) 716 { 717 mutex_lock(&__qcuefi_lock); 718 if (!__qcuefi) { 719 mutex_unlock(&__qcuefi_lock); 720 return NULL; 721 } 722 return __qcuefi; 723 } 724 725 static void qcuefi_release(void) 726 { 727 mutex_unlock(&__qcuefi_lock); 728 } 729 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) 732 { 733 struct qcuefi_client *qcuefi; 734 efi_status_t status; 735 736 qcuefi = qcuefi_acquire(); 737 if (!qcuefi) 738 return EFI_NOT_READY; 739 740 status = qsee_uefi_get_variable(qcuefi, name, vendor, attr, data_size, data); 741 742 qcuefi_release(); 743 return status; 744 } 745 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) 748 { 749 struct qcuefi_client *qcuefi; 750 efi_status_t status; 751 752 qcuefi = qcuefi_acquire(); 753 if (!qcuefi) 754 return EFI_NOT_READY; 755 756 status = qsee_uefi_set_variable(qcuefi, name, vendor, attr, data_size, data); 757 758 qcuefi_release(); 759 return status; 760 } 761 762 static efi_status_t qcuefi_get_next_variable(unsigned long *name_size, efi_char16_t *name, 763 efi_guid_t *vendor) 764 { 765 struct qcuefi_client *qcuefi; 766 efi_status_t status; 767 768 qcuefi = qcuefi_acquire(); 769 if (!qcuefi) 770 return EFI_NOT_READY; 771 772 status = qsee_uefi_get_next_variable(qcuefi, name_size, name, vendor); 773 774 qcuefi_release(); 775 return status; 776 } 777 778 static efi_status_t qcuefi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space, 779 u64 *max_variable_size) 780 { 781 struct qcuefi_client *qcuefi; 782 efi_status_t status; 783 784 qcuefi = qcuefi_acquire(); 785 if (!qcuefi) 786 return EFI_NOT_READY; 787 788 status = qsee_uefi_query_variable_info(qcuefi, attr, storage_space, remaining_space, 789 max_variable_size); 790 791 qcuefi_release(); 792 return status; 793 } 794 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, 800 }; 801 802 /* -- Driver setup. --------------------------------------------------------- */ 803 804 static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev, 805 const struct auxiliary_device_id *aux_dev_id) 806 { 807 struct qcom_tzmem_pool_config pool_config; 808 struct qcuefi_client *qcuefi; 809 int status; 810 811 qcuefi = devm_kzalloc(&aux_dev->dev, sizeof(*qcuefi), GFP_KERNEL); 812 if (!qcuefi) 813 return -ENOMEM; 814 815 qcuefi->client = container_of(aux_dev, struct qseecom_client, aux_dev); 816 817 auxiliary_set_drvdata(aux_dev, qcuefi); 818 status = qcuefi_set_reference(qcuefi); 819 if (status) 820 return status; 821 822 status = efivars_register(&qcuefi->efivars, &qcom_efivar_ops); 823 if (status) 824 qcuefi_set_reference(NULL); 825 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; 831 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); 835 836 return status; 837 } 838 839 static void qcom_uefisecapp_remove(struct auxiliary_device *aux_dev) 840 { 841 struct qcuefi_client *qcuefi = auxiliary_get_drvdata(aux_dev); 842 843 efivars_unregister(&qcuefi->efivars); 844 qcuefi_set_reference(NULL); 845 } 846 847 static const struct auxiliary_device_id qcom_uefisecapp_id_table[] = { 848 { .name = "qcom_qseecom.uefisecapp" }, 849 {} 850 }; 851 MODULE_DEVICE_TABLE(auxiliary, qcom_uefisecapp_id_table); 852 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, 857 .driver = { 858 .name = "qcom_qseecom_uefisecapp", 859 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 860 }, 861 }; 862 module_auxiliary_driver(qcom_uefisecapp_driver); 863 864 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 865 MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App"); 866 MODULE_LICENSE("GPL"); 867