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 * Note: It looks like uefisecapp is quite picky about how the memory passed to 226 * it is structured and aligned. In particular the request/response setup used 227 * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory, 228 * accepts separate buffers/addresses for the request and response parts, in 229 * practice, however, it seems to expect them to be both part of a larger 230 * contiguous block. We initially allocated separate buffers for the request 231 * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to 232 * either not write any response to the response buffer or outright crash the 233 * device. Therefore, we now allocate a single contiguous block of DMA memory 234 * for both and properly align the data using the macros below. In particular, 235 * request and response structs are aligned at 8 byte (via __reqdata_offs()), 236 * following the driver that this has been reverse-engineered from. 237 */ 238 #define qcuefi_buf_align_fields(fields...) \ 239 ({ \ 240 size_t __len = 0; \ 241 fields \ 242 __len; \ 243 }) 244 245 #define __field_impl(size, align, offset) \ 246 ({ \ 247 size_t *__offset = (offset); \ 248 size_t __aligned; \ 249 \ 250 __aligned = ALIGN(__len, align); \ 251 __len = __aligned + (size); \ 252 \ 253 if (__offset) \ 254 *__offset = __aligned; \ 255 }); 256 257 #define __array_offs(type, count, offset) \ 258 __field_impl(sizeof(type) * (count), __alignof__(type), offset) 259 260 #define __array_offs_aligned(type, count, align, offset) \ 261 __field_impl(sizeof(type) * (count), align, offset) 262 263 #define __reqdata_offs(size, offset) \ 264 __array_offs_aligned(u8, size, 8, offset) 265 266 #define __array(type, count) __array_offs(type, count, NULL) 267 #define __field_offs(type, offset) __array_offs(type, 1, offset) 268 #define __field(type) __array_offs(type, 1, NULL) 269 270 /* -- UEFI app interface. --------------------------------------------------- */ 271 272 struct qcuefi_client { 273 struct qseecom_client *client; 274 struct efivars efivars; 275 }; 276 277 static struct device *qcuefi_dev(struct qcuefi_client *qcuefi) 278 { 279 return &qcuefi->client->aux_dev.dev; 280 } 281 282 static efi_status_t qsee_uefi_status_to_efi(u32 status) 283 { 284 u64 category = status & 0xf0000000; 285 u64 code = status & 0x0fffffff; 286 287 return category << (BITS_PER_LONG - 32) | code; 288 } 289 290 static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name, 291 const efi_guid_t *guid, u32 *attributes, 292 unsigned long *data_size, void *data) 293 { 294 struct qsee_req_uefi_get_variable *req_data; 295 struct qsee_rsp_uefi_get_variable *rsp_data; 296 unsigned long buffer_size = *data_size; 297 efi_status_t efi_status = EFI_SUCCESS; 298 unsigned long name_length; 299 dma_addr_t cmd_buf_dma; 300 size_t cmd_buf_size; 301 void *cmd_buf; 302 size_t guid_offs; 303 size_t name_offs; 304 size_t req_size; 305 size_t rsp_size; 306 size_t req_offs; 307 size_t rsp_offs; 308 ssize_t status; 309 310 if (!name || !guid) 311 return EFI_INVALID_PARAMETER; 312 313 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1; 314 if (name_length > QSEE_MAX_NAME_LEN) 315 return EFI_INVALID_PARAMETER; 316 317 if (buffer_size && !data) 318 return EFI_INVALID_PARAMETER; 319 320 req_size = qcuefi_buf_align_fields( 321 __field(*req_data) 322 __array_offs(*name, name_length, &name_offs) 323 __field_offs(*guid, &guid_offs) 324 ); 325 326 rsp_size = qcuefi_buf_align_fields( 327 __field(*rsp_data) 328 __array(u8, buffer_size) 329 ); 330 331 cmd_buf_size = qcuefi_buf_align_fields( 332 __reqdata_offs(req_size, &req_offs) 333 __reqdata_offs(rsp_size, &rsp_offs) 334 ); 335 336 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); 337 if (!cmd_buf) { 338 efi_status = EFI_OUT_OF_RESOURCES; 339 goto out; 340 } 341 342 req_data = cmd_buf + req_offs; 343 rsp_data = cmd_buf + rsp_offs; 344 345 req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE; 346 req_data->data_size = buffer_size; 347 req_data->name_offset = name_offs; 348 req_data->name_size = name_length * sizeof(*name); 349 req_data->guid_offset = guid_offs; 350 req_data->guid_size = sizeof(*guid); 351 req_data->length = req_size; 352 353 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); 354 if (status < 0) { 355 efi_status = EFI_INVALID_PARAMETER; 356 goto out_free; 357 } 358 359 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 360 361 status = qcom_qseecom_app_send(qcuefi->client, 362 cmd_buf_dma + req_offs, req_size, 363 cmd_buf_dma + rsp_offs, rsp_size); 364 if (status) { 365 efi_status = EFI_DEVICE_ERROR; 366 goto out_free; 367 } 368 369 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_VARIABLE) { 370 efi_status = EFI_DEVICE_ERROR; 371 goto out_free; 372 } 373 374 if (rsp_data->length < sizeof(*rsp_data)) { 375 efi_status = EFI_DEVICE_ERROR; 376 goto out_free; 377 } 378 379 if (rsp_data->status) { 380 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 381 __func__, rsp_data->status); 382 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 383 384 /* Update size and attributes in case buffer is too small. */ 385 if (efi_status == EFI_BUFFER_TOO_SMALL) { 386 *data_size = rsp_data->data_size; 387 if (attributes) 388 *attributes = rsp_data->attributes; 389 } 390 391 goto out_free; 392 } 393 394 if (rsp_data->length > rsp_size) { 395 efi_status = EFI_DEVICE_ERROR; 396 goto out_free; 397 } 398 399 if (rsp_data->data_offset + rsp_data->data_size > rsp_data->length) { 400 efi_status = EFI_DEVICE_ERROR; 401 goto out_free; 402 } 403 404 /* 405 * Note: We need to set attributes and data size even if the buffer is 406 * too small and we won't copy any data. This is described in spec, so 407 * that callers can either allocate a buffer properly (with two calls 408 * to this function) or just read back attributes withouth having to 409 * deal with that. 410 * 411 * Specifically: 412 * - If we have a buffer size of zero and no buffer, just return the 413 * attributes, required size, and indicate success. 414 * - If the buffer size is nonzero but too small, indicate that as an 415 * error. 416 * - Otherwise, we are good to copy the data. 417 * 418 * Note that we have already ensured above that the buffer pointer is 419 * non-NULL if its size is nonzero. 420 */ 421 *data_size = rsp_data->data_size; 422 if (attributes) 423 *attributes = rsp_data->attributes; 424 425 if (buffer_size == 0 && !data) { 426 efi_status = EFI_SUCCESS; 427 goto out_free; 428 } 429 430 if (buffer_size < rsp_data->data_size) { 431 efi_status = EFI_BUFFER_TOO_SMALL; 432 goto out_free; 433 } 434 435 memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size); 436 437 out_free: 438 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); 439 out: 440 return efi_status; 441 } 442 443 static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const efi_char16_t *name, 444 const efi_guid_t *guid, u32 attributes, 445 unsigned long data_size, const void *data) 446 { 447 struct qsee_req_uefi_set_variable *req_data; 448 struct qsee_rsp_uefi_set_variable *rsp_data; 449 efi_status_t efi_status = EFI_SUCCESS; 450 unsigned long name_length; 451 dma_addr_t cmd_buf_dma; 452 size_t cmd_buf_size; 453 void *cmd_buf; 454 size_t name_offs; 455 size_t guid_offs; 456 size_t data_offs; 457 size_t req_size; 458 size_t req_offs; 459 size_t rsp_offs; 460 ssize_t status; 461 462 if (!name || !guid) 463 return EFI_INVALID_PARAMETER; 464 465 name_length = ucs2_strnlen(name, QSEE_MAX_NAME_LEN) + 1; 466 if (name_length > QSEE_MAX_NAME_LEN) 467 return EFI_INVALID_PARAMETER; 468 469 /* 470 * Make sure we have some data if data_size is nonzero. Note that using 471 * a size of zero is a valid use-case described in spec and deletes the 472 * variable. 473 */ 474 if (data_size && !data) 475 return EFI_INVALID_PARAMETER; 476 477 req_size = qcuefi_buf_align_fields( 478 __field(*req_data) 479 __array_offs(*name, name_length, &name_offs) 480 __field_offs(*guid, &guid_offs) 481 __array_offs(u8, data_size, &data_offs) 482 ); 483 484 cmd_buf_size = qcuefi_buf_align_fields( 485 __reqdata_offs(req_size, &req_offs) 486 __reqdata_offs(sizeof(*rsp_data), &rsp_offs) 487 ); 488 489 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); 490 if (!cmd_buf) { 491 efi_status = EFI_OUT_OF_RESOURCES; 492 goto out; 493 } 494 495 req_data = cmd_buf + req_offs; 496 rsp_data = cmd_buf + rsp_offs; 497 498 req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE; 499 req_data->attributes = attributes; 500 req_data->name_offset = name_offs; 501 req_data->name_size = name_length * sizeof(*name); 502 req_data->guid_offset = guid_offs; 503 req_data->guid_size = sizeof(*guid); 504 req_data->data_offset = data_offs; 505 req_data->data_size = data_size; 506 req_data->length = req_size; 507 508 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, name_length); 509 if (status < 0) { 510 efi_status = EFI_INVALID_PARAMETER; 511 goto out_free; 512 } 513 514 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 515 516 if (data_size) 517 memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size); 518 519 status = qcom_qseecom_app_send(qcuefi->client, 520 cmd_buf_dma + req_offs, req_size, 521 cmd_buf_dma + rsp_offs, sizeof(*rsp_data)); 522 if (status) { 523 efi_status = EFI_DEVICE_ERROR; 524 goto out_free; 525 } 526 527 if (rsp_data->command_id != QSEE_CMD_UEFI_SET_VARIABLE) { 528 efi_status = EFI_DEVICE_ERROR; 529 goto out_free; 530 } 531 532 if (rsp_data->length != sizeof(*rsp_data)) { 533 efi_status = EFI_DEVICE_ERROR; 534 goto out_free; 535 } 536 537 if (rsp_data->status) { 538 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 539 __func__, rsp_data->status); 540 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 541 } 542 543 out_free: 544 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); 545 out: 546 return efi_status; 547 } 548 549 static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, 550 unsigned long *name_size, efi_char16_t *name, 551 efi_guid_t *guid) 552 { 553 struct qsee_req_uefi_get_next_variable *req_data; 554 struct qsee_rsp_uefi_get_next_variable *rsp_data; 555 efi_status_t efi_status = EFI_SUCCESS; 556 dma_addr_t cmd_buf_dma; 557 size_t cmd_buf_size; 558 void *cmd_buf; 559 size_t guid_offs; 560 size_t name_offs; 561 size_t req_size; 562 size_t rsp_size; 563 size_t req_offs; 564 size_t rsp_offs; 565 ssize_t status; 566 567 if (!name_size || !name || !guid) 568 return EFI_INVALID_PARAMETER; 569 570 if (*name_size == 0) 571 return EFI_INVALID_PARAMETER; 572 573 req_size = qcuefi_buf_align_fields( 574 __field(*req_data) 575 __field_offs(*guid, &guid_offs) 576 __array_offs(*name, *name_size / sizeof(*name), &name_offs) 577 ); 578 579 rsp_size = qcuefi_buf_align_fields( 580 __field(*rsp_data) 581 __field(*guid) 582 __array(*name, *name_size / sizeof(*name)) 583 ); 584 585 cmd_buf_size = qcuefi_buf_align_fields( 586 __reqdata_offs(req_size, &req_offs) 587 __reqdata_offs(rsp_size, &rsp_offs) 588 ); 589 590 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); 591 if (!cmd_buf) { 592 efi_status = EFI_OUT_OF_RESOURCES; 593 goto out; 594 } 595 596 req_data = cmd_buf + req_offs; 597 rsp_data = cmd_buf + rsp_offs; 598 599 req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE; 600 req_data->guid_offset = guid_offs; 601 req_data->guid_size = sizeof(*guid); 602 req_data->name_offset = name_offs; 603 req_data->name_size = *name_size; 604 req_data->length = req_size; 605 606 memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); 607 status = ucs2_strscpy(((void *)req_data) + req_data->name_offset, name, 608 *name_size / sizeof(*name)); 609 if (status < 0) { 610 efi_status = EFI_INVALID_PARAMETER; 611 goto out_free; 612 } 613 614 status = qcom_qseecom_app_send(qcuefi->client, 615 cmd_buf_dma + req_offs, req_size, 616 cmd_buf_dma + rsp_offs, rsp_size); 617 if (status) { 618 efi_status = EFI_DEVICE_ERROR; 619 goto out_free; 620 } 621 622 if (rsp_data->command_id != QSEE_CMD_UEFI_GET_NEXT_VARIABLE) { 623 efi_status = EFI_DEVICE_ERROR; 624 goto out_free; 625 } 626 627 if (rsp_data->length < sizeof(*rsp_data)) { 628 efi_status = EFI_DEVICE_ERROR; 629 goto out_free; 630 } 631 632 if (rsp_data->status) { 633 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 634 __func__, rsp_data->status); 635 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 636 637 /* 638 * If the buffer to hold the name is too small, update the 639 * name_size with the required size, so that callers can 640 * reallocate it accordingly. 641 */ 642 if (efi_status == EFI_BUFFER_TOO_SMALL) 643 *name_size = rsp_data->name_size; 644 645 goto out_free; 646 } 647 648 if (rsp_data->length > rsp_size) { 649 efi_status = EFI_DEVICE_ERROR; 650 goto out_free; 651 } 652 653 if (rsp_data->name_offset + rsp_data->name_size > rsp_data->length) { 654 efi_status = EFI_DEVICE_ERROR; 655 goto out_free; 656 } 657 658 if (rsp_data->guid_offset + rsp_data->guid_size > rsp_data->length) { 659 efi_status = EFI_DEVICE_ERROR; 660 goto out_free; 661 } 662 663 if (rsp_data->name_size > *name_size) { 664 *name_size = rsp_data->name_size; 665 efi_status = EFI_BUFFER_TOO_SMALL; 666 goto out_free; 667 } 668 669 if (rsp_data->guid_size != sizeof(*guid)) { 670 efi_status = EFI_DEVICE_ERROR; 671 goto out_free; 672 } 673 674 memcpy(guid, ((void *)rsp_data) + rsp_data->guid_offset, rsp_data->guid_size); 675 status = ucs2_strscpy(name, ((void *)rsp_data) + rsp_data->name_offset, 676 rsp_data->name_size / sizeof(*name)); 677 *name_size = rsp_data->name_size; 678 679 if (status < 0) { 680 /* 681 * Return EFI_DEVICE_ERROR here because the buffer size should 682 * have already been validated above, causing this function to 683 * bail with EFI_BUFFER_TOO_SMALL. 684 */ 685 efi_status = EFI_DEVICE_ERROR; 686 } 687 688 out_free: 689 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); 690 out: 691 return efi_status; 692 } 693 694 static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, u32 attr, 695 u64 *storage_space, u64 *remaining_space, 696 u64 *max_variable_size) 697 { 698 struct qsee_req_uefi_query_variable_info *req_data; 699 struct qsee_rsp_uefi_query_variable_info *rsp_data; 700 efi_status_t efi_status = EFI_SUCCESS; 701 dma_addr_t cmd_buf_dma; 702 size_t cmd_buf_size; 703 void *cmd_buf; 704 size_t req_offs; 705 size_t rsp_offs; 706 int status; 707 708 cmd_buf_size = qcuefi_buf_align_fields( 709 __reqdata_offs(sizeof(*req_data), &req_offs) 710 __reqdata_offs(sizeof(*rsp_data), &rsp_offs) 711 ); 712 713 cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); 714 if (!cmd_buf) { 715 efi_status = EFI_OUT_OF_RESOURCES; 716 goto out; 717 } 718 719 req_data = cmd_buf + req_offs; 720 rsp_data = cmd_buf + rsp_offs; 721 722 req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO; 723 req_data->attributes = attr; 724 req_data->length = sizeof(*req_data); 725 726 status = qcom_qseecom_app_send(qcuefi->client, 727 cmd_buf_dma + req_offs, sizeof(*req_data), 728 cmd_buf_dma + rsp_offs, sizeof(*rsp_data)); 729 if (status) { 730 efi_status = EFI_DEVICE_ERROR; 731 goto out_free; 732 } 733 734 if (rsp_data->command_id != QSEE_CMD_UEFI_QUERY_VARIABLE_INFO) { 735 efi_status = EFI_DEVICE_ERROR; 736 goto out_free; 737 } 738 739 if (rsp_data->length != sizeof(*rsp_data)) { 740 efi_status = EFI_DEVICE_ERROR; 741 goto out_free; 742 } 743 744 if (rsp_data->status) { 745 dev_dbg(qcuefi_dev(qcuefi), "%s: uefisecapp error: 0x%x\n", 746 __func__, rsp_data->status); 747 efi_status = qsee_uefi_status_to_efi(rsp_data->status); 748 goto out_free; 749 } 750 751 if (storage_space) 752 *storage_space = rsp_data->storage_space; 753 754 if (remaining_space) 755 *remaining_space = rsp_data->remaining_space; 756 757 if (max_variable_size) 758 *max_variable_size = rsp_data->max_variable_size; 759 760 out_free: 761 qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); 762 out: 763 return efi_status; 764 } 765 766 /* -- Global efivar interface. ---------------------------------------------- */ 767 768 static struct qcuefi_client *__qcuefi; 769 static DEFINE_MUTEX(__qcuefi_lock); 770 771 static int qcuefi_set_reference(struct qcuefi_client *qcuefi) 772 { 773 mutex_lock(&__qcuefi_lock); 774 775 if (qcuefi && __qcuefi) { 776 mutex_unlock(&__qcuefi_lock); 777 return -EEXIST; 778 } 779 780 __qcuefi = qcuefi; 781 782 mutex_unlock(&__qcuefi_lock); 783 return 0; 784 } 785 786 static struct qcuefi_client *qcuefi_acquire(void) 787 { 788 mutex_lock(&__qcuefi_lock); 789 return __qcuefi; 790 } 791 792 static void qcuefi_release(void) 793 { 794 mutex_unlock(&__qcuefi_lock); 795 } 796 797 static efi_status_t qcuefi_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr, 798 unsigned long *data_size, void *data) 799 { 800 struct qcuefi_client *qcuefi; 801 efi_status_t status; 802 803 qcuefi = qcuefi_acquire(); 804 if (!qcuefi) 805 return EFI_NOT_READY; 806 807 status = qsee_uefi_get_variable(qcuefi, name, vendor, attr, data_size, data); 808 809 qcuefi_release(); 810 return status; 811 } 812 813 static efi_status_t qcuefi_set_variable(efi_char16_t *name, efi_guid_t *vendor, 814 u32 attr, unsigned long data_size, void *data) 815 { 816 struct qcuefi_client *qcuefi; 817 efi_status_t status; 818 819 qcuefi = qcuefi_acquire(); 820 if (!qcuefi) 821 return EFI_NOT_READY; 822 823 status = qsee_uefi_set_variable(qcuefi, name, vendor, attr, data_size, data); 824 825 qcuefi_release(); 826 return status; 827 } 828 829 static efi_status_t qcuefi_get_next_variable(unsigned long *name_size, efi_char16_t *name, 830 efi_guid_t *vendor) 831 { 832 struct qcuefi_client *qcuefi; 833 efi_status_t status; 834 835 qcuefi = qcuefi_acquire(); 836 if (!qcuefi) 837 return EFI_NOT_READY; 838 839 status = qsee_uefi_get_next_variable(qcuefi, name_size, name, vendor); 840 841 qcuefi_release(); 842 return status; 843 } 844 845 static efi_status_t qcuefi_query_variable_info(u32 attr, u64 *storage_space, u64 *remaining_space, 846 u64 *max_variable_size) 847 { 848 struct qcuefi_client *qcuefi; 849 efi_status_t status; 850 851 qcuefi = qcuefi_acquire(); 852 if (!qcuefi) 853 return EFI_NOT_READY; 854 855 status = qsee_uefi_query_variable_info(qcuefi, attr, storage_space, remaining_space, 856 max_variable_size); 857 858 qcuefi_release(); 859 return status; 860 } 861 862 static const struct efivar_operations qcom_efivar_ops = { 863 .get_variable = qcuefi_get_variable, 864 .set_variable = qcuefi_set_variable, 865 .get_next_variable = qcuefi_get_next_variable, 866 .query_variable_info = qcuefi_query_variable_info, 867 }; 868 869 /* -- Driver setup. --------------------------------------------------------- */ 870 871 static int qcom_uefisecapp_probe(struct auxiliary_device *aux_dev, 872 const struct auxiliary_device_id *aux_dev_id) 873 { 874 struct qcuefi_client *qcuefi; 875 int status; 876 877 qcuefi = devm_kzalloc(&aux_dev->dev, sizeof(*qcuefi), GFP_KERNEL); 878 if (!qcuefi) 879 return -ENOMEM; 880 881 qcuefi->client = container_of(aux_dev, struct qseecom_client, aux_dev); 882 883 auxiliary_set_drvdata(aux_dev, qcuefi); 884 status = qcuefi_set_reference(qcuefi); 885 if (status) 886 return status; 887 888 status = efivars_register(&qcuefi->efivars, &qcom_efivar_ops); 889 if (status) 890 qcuefi_set_reference(NULL); 891 892 return status; 893 } 894 895 static void qcom_uefisecapp_remove(struct auxiliary_device *aux_dev) 896 { 897 struct qcuefi_client *qcuefi = auxiliary_get_drvdata(aux_dev); 898 899 efivars_unregister(&qcuefi->efivars); 900 qcuefi_set_reference(NULL); 901 } 902 903 static const struct auxiliary_device_id qcom_uefisecapp_id_table[] = { 904 { .name = "qcom_qseecom.uefisecapp" }, 905 {} 906 }; 907 MODULE_DEVICE_TABLE(auxiliary, qcom_uefisecapp_id_table); 908 909 static struct auxiliary_driver qcom_uefisecapp_driver = { 910 .probe = qcom_uefisecapp_probe, 911 .remove = qcom_uefisecapp_remove, 912 .id_table = qcom_uefisecapp_id_table, 913 .driver = { 914 .name = "qcom_qseecom_uefisecapp", 915 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 916 }, 917 }; 918 module_auxiliary_driver(qcom_uefisecapp_driver); 919 920 MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); 921 MODULE_DESCRIPTION("Client driver for Qualcomm SEE UEFI Secure App"); 922 MODULE_LICENSE("GPL"); 923