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 return EFI_INVALID_PARAMETER; 330 331 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 332 333 status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size); 334 if (status) { 335 efi_status = EFI_DEVICE_ERROR; 336 goto out_free; 337 } 338 339 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) { 340 efi_status = EFI_DEVICE_ERROR; 341 goto out_free; 342 } 343 344 if (rsp_data->length < sizeof(*rsp_data)) { 345 efi_status = EFI_DEVICE_ERROR; 346 goto out_free; 347 } 348 349 if (rsp_data->status) { 350 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 351 __func__, rsp_data->status); 352 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 353 354 /* Update size and attributes in case buffer is too small. */ 355 if (efi_status == EFI_BUFFER_TOO_SMALL) { 356 *data_size = rsp_data->data_size; 357 if (attributes) 358 *attributes = rsp_data->attributes; 359 } 360 361 goto out_free; 362 } 363 364 if (rsp_data->length > rsp_size) { 365 efi_status = EFI_DEVICE_ERROR; 366 goto out_free; 367 } 368 369 if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) { 370 efi_status = EFI_DEVICE_ERROR; 371 goto out_free; 372 } 373 374 /* 375 * Note: We need to set attributes and data size even if the buffer is 376 * too small and we won't copy any data. This is described in spec, so 377 * that callers can either allocate a buffer properly (with two calls 378 * to this function) or just read back attributes withouth having to 379 * deal with that. 380 * 381 * Specifically: 382 * - If we have a buffer size of zero and no buffer, just return the 383 * attributes, required size, and indicate success. 384 * - If the buffer size is nonzero but too small, indicate that as an 385 * error. 386 * - Otherwise, we are good to copy the data. 387 * 388 * Note that we have already ensured above that the buffer pointer is 389 * non-NULL if its size is nonzero. 390 */ 391 *data_size = rsp_data->data_size; 392 if (attributes) 393 *attributes = rsp_data->attributes; 394 395 if (buffer_size == 0 && !data) { 396 efi_status = EFI_SUCCESS; 397 goto out_free; 398 } 399 400 if (buffer_size < rsp_data->data_size) { 401 efi_status = EFI_BUFFER_TOO_SMALL; 402 goto out_free; 403 } 404 405 memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size); 406 407 out_free: 408 kfree(rsp_data); 409 out_free_req: 410 kfree(req_data); 411 out: 412 return efi_status; 413 } 414 415 static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name, 416 const efi_guid_t *guid, u32 attributes, 417 unsigned long data_size, const void *data) 418 { 419 struct qsee_req_uefi_set_variable *req_data; 420 struct qsee_rsp_uefi_set_variable *rsp_data; 421 efi_status_t efi_status = EFI_SUCCESS; 422 unsigned long name_length; 423 size_t name_offs; 424 size_t guid_offs; 425 size_t data_offs; 426 size_t req_size; 427 ssize_t status; 428 429 if (!name || !guid) 430 return EFI_INVALID_PARAMETER; 431 432 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1; 433 if (name_length > QSEE_MAX_NAME_LEN) 434 return EFI_INVALID_PARAMETER; 435 436 /* 437 * Make sure we have some data if data_size is nonzero. Note that using 438 * a size of zero is a valid use-case described in spec and deletes the 439 * variable. 440 */ 441 if (data_size && !data) 442 return EFI_INVALID_PARAMETER; 443 444 req_size = qcuefi_buf_align_fields( 445 __field(*req_data) 446 __array_offs(*name, name_length, &name_offs) 447 __field_offs(*guid, &guid_offs) 448 __array_offs(u8, data_size, &data_offs) 449 ); 450 451 req_data = kzalloc(req_size, GFP_KERNEL); 452 if (!req_data) { 453 efi_status = EFI_OUT_OF_RESOURCES; 454 goto out; 455 } 456 457 rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL); 458 if (!rsp_data) { 459 efi_status = EFI_OUT_OF_RESOURCES; 460 goto out_free_req; 461 } 462 463 req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE; 464 req_data->attributes = attributes; 465 req_data->name_offset = name_offs; 466 req_data->name_size = name_length * sizeof(*name); 467 req_data->guid_offset = guid_offs; 468 req_data->guid_size = sizeof(*guid); 469 req_data->data_offset = data_offs; 470 req_data->data_size = data_size; 471 req_data->length = req_size; 472 473 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); 474 if (status < 0) 475 return EFI_INVALID_PARAMETER; 476 477 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 478 479 if (data_size) 480 memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size); 481 482 status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, 483 sizeof(*rsp_data)); 484 if (status) { 485 efi_status = EFI_DEVICE_ERROR; 486 goto out_free; 487 } 488 489 if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) { 490 efi_status = EFI_DEVICE_ERROR; 491 goto out_free; 492 } 493 494 if (rsp_data->length != sizeof(*rsp_data)) { 495 efi_status = EFI_DEVICE_ERROR; 496 goto out_free; 497 } 498 499 if (rsp_data->status) { 500 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 501 __func__, rsp_data->status); 502 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 503 } 504 505 out_free: 506 kfree(rsp_data); 507 out_free_req: 508 kfree(req_data); 509 out: 510 return efi_status; 511 } 512 513 static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, 514 unsigned long *name_size, efi_char16_t *name, 515 efi_guid_t *guid) 516 { 517 struct qsee_req_uefi_get_next_variable *req_data; 518 struct qsee_rsp_uefi_get_next_variable *rsp_data; 519 efi_status_t efi_status = EFI_SUCCESS; 520 size_t guid_offs; 521 size_t name_offs; 522 size_t req_size; 523 size_t rsp_size; 524 ssize_t status; 525 526 if (!name_size || !name || !guid) 527 return EFI_INVALID_PARAMETER; 528 529 if (*name_size == 0) 530 return EFI_INVALID_PARAMETER; 531 532 req_size = qcuefi_buf_align_fields( 533 __field(*req_data) 534 __field_offs(*guid, &guid_offs) 535 __array_offs(*name, *name_size / sizeof(*name), &name_offs) 536 ); 537 538 rsp_size = qcuefi_buf_align_fields( 539 __field(*rsp_data) 540 __field(*guid) 541 __array(*name, *name_size / sizeof(*name)) 542 ); 543 544 req_data = kzalloc(req_size, GFP_KERNEL); 545 if (!req_data) { 546 efi_status = EFI_OUT_OF_RESOURCES; 547 goto out; 548 } 549 550 rsp_data = kzalloc(rsp_size, GFP_KERNEL); 551 if (!rsp_data) { 552 efi_status = EFI_OUT_OF_RESOURCES; 553 goto out_free_req; 554 } 555 556 req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE; 557 req_data->guid_offset = guid_offs; 558 req_data->guid_size = sizeof(*guid); 559 req_data->name_offset = name_offs; 560 req_data->name_size = *name_size; 561 req_data->length = req_size; 562 563 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 564 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, 565 *name_size / sizeof(*name)); 566 if (status < 0) 567 return EFI_INVALID_PARAMETER; 568 569 status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size); 570 if (status) { 571 efi_status = EFI_DEVICE_ERROR; 572 goto out_free; 573 } 574 575 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) { 576 efi_status = EFI_DEVICE_ERROR; 577 goto out_free; 578 } 579 580 if (rsp_data->length < sizeof(*rsp_data)) { 581 efi_status = EFI_DEVICE_ERROR; 582 goto out_free; 583 } 584 585 if (rsp_data->status) { 586 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 587 __func__, rsp_data->status); 588 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 589 590 /* 591 * If the buffer to hold the name is too small, update the 592 * name_size with the required size, so that callers can 593 * reallocate it accordingly. 594 */ 595 if (efi_status == EFI_BUFFER_TOO_SMALL) 596 *name_size = rsp_data->name_size; 597 598 goto out_free; 599 } 600 601 if (rsp_data->length > rsp_size) { 602 efi_status = EFI_DEVICE_ERROR; 603 goto out_free; 604 } 605 606 if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) { 607 efi_status = EFI_DEVICE_ERROR; 608 goto out_free; 609 } 610 611 if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) { 612 efi_status = EFI_DEVICE_ERROR; 613 goto out_free; 614 } 615 616 if (rsp_data->name_size > *name_size) { 617 *name_size = rsp_data->name_size; 618 efi_status = EFI_BUFFER_TOO_SMALL; 619 goto out_free; 620 } 621 622 if (rsp_data->guid_size != sizeof(*guid)) { 623 efi_status = EFI_DEVICE_ERROR; 624 goto out_free; 625 } 626 627 memcpy(guid, ((void *)rsp_data) + rsp_data->guid_offset, rsp_data->guid_size); 628 status = ucs2_strscpy(name, ((void *)rsp_data) + rsp_data->name_offset, 629 rsp_data->name_size / sizeof(*name)); 630 *name_size = rsp_data->name_size; 631 632 if (status < 0) { 633 /* 634 * Return EFI_DEVICE_ERROR here because the buffer size should 635 * have already been validated above, causing this function to 636 * bail with EFI_BUFFER_TOO_SMALL. 637 */ 638 return EFI_DEVICE_ERROR; 639 } 640 641 out_free: 642 kfree(rsp_data); 643 out_free_req: 644 kfree(req_data); 645 out: 646 return efi_status; 647 } 648 649 static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, u32 attr, 650 u64 *storage_space, u64 *remaining_space, 651 u64 *max_variable_size) 652 { 653 struct qsee_req_uefi_query_variable_info *req_data; 654 struct qsee_rsp_uefi_query_variable_info *rsp_data; 655 efi_status_t efi_status = EFI_SUCCESS; 656 int status; 657 658 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL); 659 if (!req_data) { 660 efi_status = EFI_OUT_OF_RESOURCES; 661 goto out; 662 } 663 664 rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL); 665 if (!rsp_data) { 666 efi_status = EFI_OUT_OF_RESOURCES; 667 goto out_free_req; 668 } 669 670 req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO; 671 req_data->attributes = attr; 672 req_data->length = sizeof(*req_data); 673 674 status = qcom_qseecom_app_send(qcuefi->client, req_data, sizeof(*req_data), rsp_data, 675 sizeof(*rsp_data)); 676 if (status) { 677 efi_status = EFI_DEVICE_ERROR; 678 goto out_free; 679 } 680 681 if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) { 682 efi_status = EFI_DEVICE_ERROR; 683 goto out_free; 684 } 685 686 if (rsp_data->length != sizeof(*rsp_data)) { 687 efi_status = EFI_DEVICE_ERROR; 688 goto out_free; 689 } 690 691 if (rsp_data->status) { 692 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 693 __func__, rsp_data->status); 694 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 695 goto out_free; 696 } 697 698 if (storage_space) 699 *storage_space = rsp_data->storage_space; 700 701 if (remaining_space) 702 *remaining_space = rsp_data->remaining_space; 703 704 if (max_variable_size) 705 *max_variable_size = rsp_data->max_variable_size; 706 707 out_free: 708 kfree(rsp_data); 709 out_free_req: 710 kfree(req_data); 711 out: 712 return efi_status; 713 } 714 715 /* -- Global efivar interface. ---------------------------------------------- */ 716 717 static struct qcuefi_client *__qcuefi; 718 static DEFINE_MUTEX(__qcuefi_lock); 719 720 static int qcuefi_set_reference(struct qcuefi_client *qcuefi) 721 { 722 mutex_lock(&__qcuefi_lock); 723 724 if (qcuefi && __qcuefi) { 725 mutex_unlock(&__qcuefi_lock); 726 return -EEXIST; 727 } 728 729 __qcuefi = qcuefi; 730 731 mutex_unlock(&__qcuefi_lock); 732 return 0; 733 } 734 735 static struct qcuefi_client *qcuefi_acquire(void) 736 { 737 mutex_lock(&__qcuefi_lock); 738 return __qcuefi; 739 } 740 741 static void qcuefi_release(void) 742 { 743 mutex_unlock(&__qcuefi_lock); 744 } 745 746 static efi_status_t qcuefi_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr, 747 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_get_variable(qcuefi, name, vendor, attr, data_size, data); 757 758 qcuefi_release(); 759 return status; 760 } 761 762 static efi_status_t qcuefi_set_variable(efi_char16_t *name, efi_guid_t *vendor, 763 u32 attr, unsigned long data_size, void *data) 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_set_variable(qcuefi, name, vendor, attr, data_size, data); 773 774 qcuefi_release(); 775 return status; 776 } 777 778 static efi_status_t qcuefi_get_next_variable(unsigned long *name_size, efi_char16_t *name, 779 efi_guid_t *vendor) 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_get_next_variable(qcuefi, name_size, name, vendor); 789 790 qcuefi_release(); 791 return status; 792 } 793 794 static efi_status_t qcuefi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space, 795 u64 *max_variable_size) 796 { 797 struct qcuefi_client *qcuefi; 798 efi_status_t status; 799 800 qcuefi = qcuefi_acquire(); 801 if (!qcuefi) 802 return EFI_NOT_READY; 803 804 status = qsee_uefi_query_variable_info(qcuefi, attr, storage_space, remaining_space, 805 max_variable_size); 806 807 qcuefi_release(); 808 return status; 809 } 810 811 static const struct efivar_operations qcom_efivar_ops = { 812 .get_variable = qcuefi_get_variable, 813 .set_variable = qcuefi_set_variable, 814 .get_next_variable = qcuefi_get_next_variable, 815 .query_variable_info = qcuefi_query_variable_info, 816 }; 817 818 /* -- Driver setup. --------------------------------------------------------- */ 819 820 static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev, 821 const struct auxiliary_device_id *aux_dev_id) 822 { 823 struct qcuefi_client *qcuefi; 824 int status; 825 826 qcuefi = devm_kzalloc(&aux_dev->dev, sizeof(*qcuefi), GFP_KERNEL); 827 if (!qcuefi) 828 return -ENOMEM; 829 830 qcuefi->client = container_of(aux_dev, struct qseecom_client, aux_dev); 831 832 auxiliary_set_drvdata(aux_dev, qcuefi); 833 status = qcuefi_set_reference(qcuefi); 834 if (status) 835 return status; 836 837 status = efivars_register(&qcuefi->efivars, &qcom_efivar_ops); 838 if (status) 839 qcuefi_set_reference(NULL); 840 841 return status; 842 } 843 844 static void qcom_uefisecapp_remove(struct auxiliary_device *aux_dev) 845 { 846 struct qcuefi_client *qcuefi = auxiliary_get_drvdata(aux_dev); 847 848 efivars_unregister(&qcuefi->efivars); 849 qcuefi_set_reference(NULL); 850 } 851 852 static const struct auxiliary_device_id qcom_uefisecapp_id_table[] = { 853 { .name = "qcom_qseecom.uefisecapp" }, 854 {} 855 }; 856 MODULE_DEVICE_TABLE(auxiliary, qcom_uefisecapp_id_table); 857 858 static struct auxiliary_driver qcom_uefisecapp_driver = { 859 .probe = qcom_uefisecapp_probe, 860 .remove = qcom_uefisecapp_remove, 861 .id_table = qcom_uefisecapp_id_table, 862 .driver = { 863 .name = "qcom_qseecom_uefisecapp", 864 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 865 }, 866 }; 867 module_auxiliary_driver(qcom_uefisecapp_driver); 868 869 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 870 MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App"); 871 MODULE_LICENSE("GPL"); 872