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