test_firmware.c (37391B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * This module provides an interface to trigger and test firmware loading. 4 * 5 * It is designed to be used for basic evaluation of the firmware loading 6 * subsystem (for example when validating firmware verification). It lacks 7 * any extra dependencies, and will not normally be loaded by the system 8 * unless explicitly requested by name. 9 */ 10 11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/printk.h> 16#include <linux/completion.h> 17#include <linux/firmware.h> 18#include <linux/device.h> 19#include <linux/fs.h> 20#include <linux/miscdevice.h> 21#include <linux/sizes.h> 22#include <linux/slab.h> 23#include <linux/uaccess.h> 24#include <linux/delay.h> 25#include <linux/kthread.h> 26#include <linux/vmalloc.h> 27#include <linux/efi_embedded_fw.h> 28 29MODULE_IMPORT_NS(TEST_FIRMWARE); 30 31#define TEST_FIRMWARE_NAME "test-firmware.bin" 32#define TEST_FIRMWARE_NUM_REQS 4 33#define TEST_FIRMWARE_BUF_SIZE SZ_1K 34#define TEST_UPLOAD_MAX_SIZE SZ_2K 35#define TEST_UPLOAD_BLK_SIZE 37 /* Avoid powers of two in testing */ 36 37static DEFINE_MUTEX(test_fw_mutex); 38static const struct firmware *test_firmware; 39static LIST_HEAD(test_upload_list); 40 41struct test_batched_req { 42 u8 idx; 43 int rc; 44 bool sent; 45 const struct firmware *fw; 46 const char *name; 47 struct completion completion; 48 struct task_struct *task; 49 struct device *dev; 50}; 51 52/** 53 * test_config - represents configuration for the test for different triggers 54 * 55 * @name: the name of the firmware file to look for 56 * @into_buf: when the into_buf is used if this is true 57 * request_firmware_into_buf() will be used instead. 58 * @buf_size: size of buf to allocate when into_buf is true 59 * @file_offset: file offset to request when calling request_firmware_into_buf 60 * @partial: partial read opt when calling request_firmware_into_buf 61 * @sync_direct: when the sync trigger is used if this is true 62 * request_firmware_direct() will be used instead. 63 * @send_uevent: whether or not to send a uevent for async requests 64 * @num_requests: number of requests to try per test case. This is trigger 65 * specific. 66 * @reqs: stores all requests information 67 * @read_fw_idx: index of thread from which we want to read firmware results 68 * from through the read_fw trigger. 69 * @upload_name: firmware name to be used with upload_read sysfs node 70 * @test_result: a test may use this to collect the result from the call 71 * of the request_firmware*() calls used in their tests. In order of 72 * priority we always keep first any setup error. If no setup errors were 73 * found then we move on to the first error encountered while running the 74 * API. Note that for async calls this typically will be a successful 75 * result (0) unless of course you've used bogus parameters, or the system 76 * is out of memory. In the async case the callback is expected to do a 77 * bit more homework to figure out what happened, unfortunately the only 78 * information passed today on error is the fact that no firmware was 79 * found so we can only assume -ENOENT on async calls if the firmware is 80 * NULL. 81 * 82 * Errors you can expect: 83 * 84 * API specific: 85 * 86 * 0: success for sync, for async it means request was sent 87 * -EINVAL: invalid parameters or request 88 * -ENOENT: files not found 89 * 90 * System environment: 91 * 92 * -ENOMEM: memory pressure on system 93 * -ENODEV: out of number of devices to test 94 * -EINVAL: an unexpected error has occurred 95 * @req_firmware: if @sync_direct is true this is set to 96 * request_firmware_direct(), otherwise request_firmware() 97 */ 98struct test_config { 99 char *name; 100 bool into_buf; 101 size_t buf_size; 102 size_t file_offset; 103 bool partial; 104 bool sync_direct; 105 bool send_uevent; 106 u8 num_requests; 107 u8 read_fw_idx; 108 char *upload_name; 109 110 /* 111 * These below don't belong her but we'll move them once we create 112 * a struct fw_test_device and stuff the misc_dev under there later. 113 */ 114 struct test_batched_req *reqs; 115 int test_result; 116 int (*req_firmware)(const struct firmware **fw, const char *name, 117 struct device *device); 118}; 119 120struct upload_inject_err { 121 const char *prog; 122 enum fw_upload_err err_code; 123}; 124 125struct test_firmware_upload { 126 char *name; 127 struct list_head node; 128 char *buf; 129 size_t size; 130 bool cancel_request; 131 struct upload_inject_err inject; 132 struct fw_upload *fwl; 133}; 134 135static struct test_config *test_fw_config; 136 137static struct test_firmware_upload *upload_lookup_name(const char *name) 138{ 139 struct test_firmware_upload *tst; 140 141 list_for_each_entry(tst, &test_upload_list, node) 142 if (strncmp(name, tst->name, strlen(tst->name)) == 0) 143 return tst; 144 145 return NULL; 146} 147 148static ssize_t test_fw_misc_read(struct file *f, char __user *buf, 149 size_t size, loff_t *offset) 150{ 151 ssize_t rc = 0; 152 153 mutex_lock(&test_fw_mutex); 154 if (test_firmware) 155 rc = simple_read_from_buffer(buf, size, offset, 156 test_firmware->data, 157 test_firmware->size); 158 mutex_unlock(&test_fw_mutex); 159 return rc; 160} 161 162static const struct file_operations test_fw_fops = { 163 .owner = THIS_MODULE, 164 .read = test_fw_misc_read, 165}; 166 167static void __test_release_all_firmware(void) 168{ 169 struct test_batched_req *req; 170 u8 i; 171 172 if (!test_fw_config->reqs) 173 return; 174 175 for (i = 0; i < test_fw_config->num_requests; i++) { 176 req = &test_fw_config->reqs[i]; 177 if (req->fw) 178 release_firmware(req->fw); 179 } 180 181 vfree(test_fw_config->reqs); 182 test_fw_config->reqs = NULL; 183} 184 185static void test_release_all_firmware(void) 186{ 187 mutex_lock(&test_fw_mutex); 188 __test_release_all_firmware(); 189 mutex_unlock(&test_fw_mutex); 190} 191 192 193static void __test_firmware_config_free(void) 194{ 195 __test_release_all_firmware(); 196 kfree_const(test_fw_config->name); 197 test_fw_config->name = NULL; 198} 199 200/* 201 * XXX: move to kstrncpy() once merged. 202 * 203 * Users should use kfree_const() when freeing these. 204 */ 205static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp) 206{ 207 *dst = kstrndup(name, count, gfp); 208 if (!*dst) 209 return -ENOSPC; 210 return count; 211} 212 213static int __test_firmware_config_init(void) 214{ 215 int ret; 216 217 ret = __kstrncpy(&test_fw_config->name, TEST_FIRMWARE_NAME, 218 strlen(TEST_FIRMWARE_NAME), GFP_KERNEL); 219 if (ret < 0) 220 goto out; 221 222 test_fw_config->num_requests = TEST_FIRMWARE_NUM_REQS; 223 test_fw_config->send_uevent = true; 224 test_fw_config->into_buf = false; 225 test_fw_config->buf_size = TEST_FIRMWARE_BUF_SIZE; 226 test_fw_config->file_offset = 0; 227 test_fw_config->partial = false; 228 test_fw_config->sync_direct = false; 229 test_fw_config->req_firmware = request_firmware; 230 test_fw_config->test_result = 0; 231 test_fw_config->reqs = NULL; 232 test_fw_config->upload_name = NULL; 233 234 return 0; 235 236out: 237 __test_firmware_config_free(); 238 return ret; 239} 240 241static ssize_t reset_store(struct device *dev, 242 struct device_attribute *attr, 243 const char *buf, size_t count) 244{ 245 int ret; 246 247 mutex_lock(&test_fw_mutex); 248 249 __test_firmware_config_free(); 250 251 ret = __test_firmware_config_init(); 252 if (ret < 0) { 253 ret = -ENOMEM; 254 pr_err("could not alloc settings for config trigger: %d\n", 255 ret); 256 goto out; 257 } 258 259 pr_info("reset\n"); 260 ret = count; 261 262out: 263 mutex_unlock(&test_fw_mutex); 264 265 return ret; 266} 267static DEVICE_ATTR_WO(reset); 268 269static ssize_t config_show(struct device *dev, 270 struct device_attribute *attr, 271 char *buf) 272{ 273 int len = 0; 274 275 mutex_lock(&test_fw_mutex); 276 277 len += scnprintf(buf, PAGE_SIZE - len, 278 "Custom trigger configuration for: %s\n", 279 dev_name(dev)); 280 281 if (test_fw_config->name) 282 len += scnprintf(buf + len, PAGE_SIZE - len, 283 "name:\t%s\n", 284 test_fw_config->name); 285 else 286 len += scnprintf(buf + len, PAGE_SIZE - len, 287 "name:\tEMTPY\n"); 288 289 len += scnprintf(buf + len, PAGE_SIZE - len, 290 "num_requests:\t%u\n", test_fw_config->num_requests); 291 292 len += scnprintf(buf + len, PAGE_SIZE - len, 293 "send_uevent:\t\t%s\n", 294 test_fw_config->send_uevent ? 295 "FW_ACTION_UEVENT" : 296 "FW_ACTION_NOUEVENT"); 297 len += scnprintf(buf + len, PAGE_SIZE - len, 298 "into_buf:\t\t%s\n", 299 test_fw_config->into_buf ? "true" : "false"); 300 len += scnprintf(buf + len, PAGE_SIZE - len, 301 "buf_size:\t%zu\n", test_fw_config->buf_size); 302 len += scnprintf(buf + len, PAGE_SIZE - len, 303 "file_offset:\t%zu\n", test_fw_config->file_offset); 304 len += scnprintf(buf + len, PAGE_SIZE - len, 305 "partial:\t\t%s\n", 306 test_fw_config->partial ? "true" : "false"); 307 len += scnprintf(buf + len, PAGE_SIZE - len, 308 "sync_direct:\t\t%s\n", 309 test_fw_config->sync_direct ? "true" : "false"); 310 len += scnprintf(buf + len, PAGE_SIZE - len, 311 "read_fw_idx:\t%u\n", test_fw_config->read_fw_idx); 312 if (test_fw_config->upload_name) 313 len += scnprintf(buf + len, PAGE_SIZE - len, 314 "upload_name:\t%s\n", 315 test_fw_config->upload_name); 316 else 317 len += scnprintf(buf + len, PAGE_SIZE - len, 318 "upload_name:\tEMTPY\n"); 319 320 mutex_unlock(&test_fw_mutex); 321 322 return len; 323} 324static DEVICE_ATTR_RO(config); 325 326static ssize_t config_name_store(struct device *dev, 327 struct device_attribute *attr, 328 const char *buf, size_t count) 329{ 330 int ret; 331 332 mutex_lock(&test_fw_mutex); 333 kfree_const(test_fw_config->name); 334 ret = __kstrncpy(&test_fw_config->name, buf, count, GFP_KERNEL); 335 mutex_unlock(&test_fw_mutex); 336 337 return ret; 338} 339 340/* 341 * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE. 342 */ 343static ssize_t config_test_show_str(char *dst, 344 char *src) 345{ 346 int len; 347 348 mutex_lock(&test_fw_mutex); 349 len = snprintf(dst, PAGE_SIZE, "%s\n", src); 350 mutex_unlock(&test_fw_mutex); 351 352 return len; 353} 354 355static int test_dev_config_update_bool(const char *buf, size_t size, 356 bool *cfg) 357{ 358 int ret; 359 360 mutex_lock(&test_fw_mutex); 361 if (strtobool(buf, cfg) < 0) 362 ret = -EINVAL; 363 else 364 ret = size; 365 mutex_unlock(&test_fw_mutex); 366 367 return ret; 368} 369 370static ssize_t test_dev_config_show_bool(char *buf, bool val) 371{ 372 return snprintf(buf, PAGE_SIZE, "%d\n", val); 373} 374 375static int test_dev_config_update_size_t(const char *buf, 376 size_t size, 377 size_t *cfg) 378{ 379 int ret; 380 long new; 381 382 ret = kstrtol(buf, 10, &new); 383 if (ret) 384 return ret; 385 386 mutex_lock(&test_fw_mutex); 387 *(size_t *)cfg = new; 388 mutex_unlock(&test_fw_mutex); 389 390 /* Always return full write size even if we didn't consume all */ 391 return size; 392} 393 394static ssize_t test_dev_config_show_size_t(char *buf, size_t val) 395{ 396 return snprintf(buf, PAGE_SIZE, "%zu\n", val); 397} 398 399static ssize_t test_dev_config_show_int(char *buf, int val) 400{ 401 return snprintf(buf, PAGE_SIZE, "%d\n", val); 402} 403 404static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) 405{ 406 u8 val; 407 int ret; 408 409 ret = kstrtou8(buf, 10, &val); 410 if (ret) 411 return ret; 412 413 mutex_lock(&test_fw_mutex); 414 *(u8 *)cfg = val; 415 mutex_unlock(&test_fw_mutex); 416 417 /* Always return full write size even if we didn't consume all */ 418 return size; 419} 420 421static ssize_t test_dev_config_show_u8(char *buf, u8 val) 422{ 423 return snprintf(buf, PAGE_SIZE, "%u\n", val); 424} 425 426static ssize_t config_name_show(struct device *dev, 427 struct device_attribute *attr, 428 char *buf) 429{ 430 return config_test_show_str(buf, test_fw_config->name); 431} 432static DEVICE_ATTR_RW(config_name); 433 434static ssize_t config_upload_name_store(struct device *dev, 435 struct device_attribute *attr, 436 const char *buf, size_t count) 437{ 438 struct test_firmware_upload *tst; 439 int ret = count; 440 441 mutex_lock(&test_fw_mutex); 442 tst = upload_lookup_name(buf); 443 if (tst) 444 test_fw_config->upload_name = tst->name; 445 else 446 ret = -EINVAL; 447 mutex_unlock(&test_fw_mutex); 448 449 return ret; 450} 451 452static ssize_t config_upload_name_show(struct device *dev, 453 struct device_attribute *attr, 454 char *buf) 455{ 456 return config_test_show_str(buf, test_fw_config->upload_name); 457} 458static DEVICE_ATTR_RW(config_upload_name); 459 460static ssize_t config_num_requests_store(struct device *dev, 461 struct device_attribute *attr, 462 const char *buf, size_t count) 463{ 464 int rc; 465 466 mutex_lock(&test_fw_mutex); 467 if (test_fw_config->reqs) { 468 pr_err("Must call release_all_firmware prior to changing config\n"); 469 rc = -EINVAL; 470 mutex_unlock(&test_fw_mutex); 471 goto out; 472 } 473 mutex_unlock(&test_fw_mutex); 474 475 rc = test_dev_config_update_u8(buf, count, 476 &test_fw_config->num_requests); 477 478out: 479 return rc; 480} 481 482static ssize_t config_num_requests_show(struct device *dev, 483 struct device_attribute *attr, 484 char *buf) 485{ 486 return test_dev_config_show_u8(buf, test_fw_config->num_requests); 487} 488static DEVICE_ATTR_RW(config_num_requests); 489 490static ssize_t config_into_buf_store(struct device *dev, 491 struct device_attribute *attr, 492 const char *buf, size_t count) 493{ 494 return test_dev_config_update_bool(buf, 495 count, 496 &test_fw_config->into_buf); 497} 498 499static ssize_t config_into_buf_show(struct device *dev, 500 struct device_attribute *attr, 501 char *buf) 502{ 503 return test_dev_config_show_bool(buf, test_fw_config->into_buf); 504} 505static DEVICE_ATTR_RW(config_into_buf); 506 507static ssize_t config_buf_size_store(struct device *dev, 508 struct device_attribute *attr, 509 const char *buf, size_t count) 510{ 511 int rc; 512 513 mutex_lock(&test_fw_mutex); 514 if (test_fw_config->reqs) { 515 pr_err("Must call release_all_firmware prior to changing config\n"); 516 rc = -EINVAL; 517 mutex_unlock(&test_fw_mutex); 518 goto out; 519 } 520 mutex_unlock(&test_fw_mutex); 521 522 rc = test_dev_config_update_size_t(buf, count, 523 &test_fw_config->buf_size); 524 525out: 526 return rc; 527} 528 529static ssize_t config_buf_size_show(struct device *dev, 530 struct device_attribute *attr, 531 char *buf) 532{ 533 return test_dev_config_show_size_t(buf, test_fw_config->buf_size); 534} 535static DEVICE_ATTR_RW(config_buf_size); 536 537static ssize_t config_file_offset_store(struct device *dev, 538 struct device_attribute *attr, 539 const char *buf, size_t count) 540{ 541 int rc; 542 543 mutex_lock(&test_fw_mutex); 544 if (test_fw_config->reqs) { 545 pr_err("Must call release_all_firmware prior to changing config\n"); 546 rc = -EINVAL; 547 mutex_unlock(&test_fw_mutex); 548 goto out; 549 } 550 mutex_unlock(&test_fw_mutex); 551 552 rc = test_dev_config_update_size_t(buf, count, 553 &test_fw_config->file_offset); 554 555out: 556 return rc; 557} 558 559static ssize_t config_file_offset_show(struct device *dev, 560 struct device_attribute *attr, 561 char *buf) 562{ 563 return test_dev_config_show_size_t(buf, test_fw_config->file_offset); 564} 565static DEVICE_ATTR_RW(config_file_offset); 566 567static ssize_t config_partial_store(struct device *dev, 568 struct device_attribute *attr, 569 const char *buf, size_t count) 570{ 571 return test_dev_config_update_bool(buf, 572 count, 573 &test_fw_config->partial); 574} 575 576static ssize_t config_partial_show(struct device *dev, 577 struct device_attribute *attr, 578 char *buf) 579{ 580 return test_dev_config_show_bool(buf, test_fw_config->partial); 581} 582static DEVICE_ATTR_RW(config_partial); 583 584static ssize_t config_sync_direct_store(struct device *dev, 585 struct device_attribute *attr, 586 const char *buf, size_t count) 587{ 588 int rc = test_dev_config_update_bool(buf, count, 589 &test_fw_config->sync_direct); 590 591 if (rc == count) 592 test_fw_config->req_firmware = test_fw_config->sync_direct ? 593 request_firmware_direct : 594 request_firmware; 595 return rc; 596} 597 598static ssize_t config_sync_direct_show(struct device *dev, 599 struct device_attribute *attr, 600 char *buf) 601{ 602 return test_dev_config_show_bool(buf, test_fw_config->sync_direct); 603} 604static DEVICE_ATTR_RW(config_sync_direct); 605 606static ssize_t config_send_uevent_store(struct device *dev, 607 struct device_attribute *attr, 608 const char *buf, size_t count) 609{ 610 return test_dev_config_update_bool(buf, count, 611 &test_fw_config->send_uevent); 612} 613 614static ssize_t config_send_uevent_show(struct device *dev, 615 struct device_attribute *attr, 616 char *buf) 617{ 618 return test_dev_config_show_bool(buf, test_fw_config->send_uevent); 619} 620static DEVICE_ATTR_RW(config_send_uevent); 621 622static ssize_t config_read_fw_idx_store(struct device *dev, 623 struct device_attribute *attr, 624 const char *buf, size_t count) 625{ 626 return test_dev_config_update_u8(buf, count, 627 &test_fw_config->read_fw_idx); 628} 629 630static ssize_t config_read_fw_idx_show(struct device *dev, 631 struct device_attribute *attr, 632 char *buf) 633{ 634 return test_dev_config_show_u8(buf, test_fw_config->read_fw_idx); 635} 636static DEVICE_ATTR_RW(config_read_fw_idx); 637 638 639static ssize_t trigger_request_store(struct device *dev, 640 struct device_attribute *attr, 641 const char *buf, size_t count) 642{ 643 int rc; 644 char *name; 645 646 name = kstrndup(buf, count, GFP_KERNEL); 647 if (!name) 648 return -ENOSPC; 649 650 pr_info("loading '%s'\n", name); 651 652 mutex_lock(&test_fw_mutex); 653 release_firmware(test_firmware); 654 test_firmware = NULL; 655 rc = request_firmware(&test_firmware, name, dev); 656 if (rc) { 657 pr_info("load of '%s' failed: %d\n", name, rc); 658 goto out; 659 } 660 pr_info("loaded: %zu\n", test_firmware->size); 661 rc = count; 662 663out: 664 mutex_unlock(&test_fw_mutex); 665 666 kfree(name); 667 668 return rc; 669} 670static DEVICE_ATTR_WO(trigger_request); 671 672#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE 673extern struct list_head efi_embedded_fw_list; 674extern bool efi_embedded_fw_checked; 675 676static ssize_t trigger_request_platform_store(struct device *dev, 677 struct device_attribute *attr, 678 const char *buf, size_t count) 679{ 680 static const u8 test_data[] = { 681 0x55, 0xaa, 0x55, 0xaa, 0x01, 0x02, 0x03, 0x04, 682 0x55, 0xaa, 0x55, 0xaa, 0x05, 0x06, 0x07, 0x08, 683 0x55, 0xaa, 0x55, 0xaa, 0x10, 0x20, 0x30, 0x40, 684 0x55, 0xaa, 0x55, 0xaa, 0x50, 0x60, 0x70, 0x80 685 }; 686 struct efi_embedded_fw efi_embedded_fw; 687 const struct firmware *firmware = NULL; 688 bool saved_efi_embedded_fw_checked; 689 char *name; 690 int rc; 691 692 name = kstrndup(buf, count, GFP_KERNEL); 693 if (!name) 694 return -ENOSPC; 695 696 pr_info("inserting test platform fw '%s'\n", name); 697 efi_embedded_fw.name = name; 698 efi_embedded_fw.data = (void *)test_data; 699 efi_embedded_fw.length = sizeof(test_data); 700 list_add(&efi_embedded_fw.list, &efi_embedded_fw_list); 701 saved_efi_embedded_fw_checked = efi_embedded_fw_checked; 702 efi_embedded_fw_checked = true; 703 704 pr_info("loading '%s'\n", name); 705 rc = firmware_request_platform(&firmware, name, dev); 706 if (rc) { 707 pr_info("load of '%s' failed: %d\n", name, rc); 708 goto out; 709 } 710 if (firmware->size != sizeof(test_data) || 711 memcmp(firmware->data, test_data, sizeof(test_data)) != 0) { 712 pr_info("firmware contents mismatch for '%s'\n", name); 713 rc = -EINVAL; 714 goto out; 715 } 716 pr_info("loaded: %zu\n", firmware->size); 717 rc = count; 718 719out: 720 efi_embedded_fw_checked = saved_efi_embedded_fw_checked; 721 release_firmware(firmware); 722 list_del(&efi_embedded_fw.list); 723 kfree(name); 724 725 return rc; 726} 727static DEVICE_ATTR_WO(trigger_request_platform); 728#endif 729 730static DECLARE_COMPLETION(async_fw_done); 731 732static void trigger_async_request_cb(const struct firmware *fw, void *context) 733{ 734 test_firmware = fw; 735 complete(&async_fw_done); 736} 737 738static ssize_t trigger_async_request_store(struct device *dev, 739 struct device_attribute *attr, 740 const char *buf, size_t count) 741{ 742 int rc; 743 char *name; 744 745 name = kstrndup(buf, count, GFP_KERNEL); 746 if (!name) 747 return -ENOSPC; 748 749 pr_info("loading '%s'\n", name); 750 751 mutex_lock(&test_fw_mutex); 752 release_firmware(test_firmware); 753 test_firmware = NULL; 754 rc = request_firmware_nowait(THIS_MODULE, 1, name, dev, GFP_KERNEL, 755 NULL, trigger_async_request_cb); 756 if (rc) { 757 pr_info("async load of '%s' failed: %d\n", name, rc); 758 kfree(name); 759 goto out; 760 } 761 /* Free 'name' ASAP, to test for race conditions */ 762 kfree(name); 763 764 wait_for_completion(&async_fw_done); 765 766 if (test_firmware) { 767 pr_info("loaded: %zu\n", test_firmware->size); 768 rc = count; 769 } else { 770 pr_err("failed to async load firmware\n"); 771 rc = -ENOMEM; 772 } 773 774out: 775 mutex_unlock(&test_fw_mutex); 776 777 return rc; 778} 779static DEVICE_ATTR_WO(trigger_async_request); 780 781static ssize_t trigger_custom_fallback_store(struct device *dev, 782 struct device_attribute *attr, 783 const char *buf, size_t count) 784{ 785 int rc; 786 char *name; 787 788 name = kstrndup(buf, count, GFP_KERNEL); 789 if (!name) 790 return -ENOSPC; 791 792 pr_info("loading '%s' using custom fallback mechanism\n", name); 793 794 mutex_lock(&test_fw_mutex); 795 release_firmware(test_firmware); 796 test_firmware = NULL; 797 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOUEVENT, name, 798 dev, GFP_KERNEL, NULL, 799 trigger_async_request_cb); 800 if (rc) { 801 pr_info("async load of '%s' failed: %d\n", name, rc); 802 kfree(name); 803 goto out; 804 } 805 /* Free 'name' ASAP, to test for race conditions */ 806 kfree(name); 807 808 wait_for_completion(&async_fw_done); 809 810 if (test_firmware) { 811 pr_info("loaded: %zu\n", test_firmware->size); 812 rc = count; 813 } else { 814 pr_err("failed to async load firmware\n"); 815 rc = -ENODEV; 816 } 817 818out: 819 mutex_unlock(&test_fw_mutex); 820 821 return rc; 822} 823static DEVICE_ATTR_WO(trigger_custom_fallback); 824 825static int test_fw_run_batch_request(void *data) 826{ 827 struct test_batched_req *req = data; 828 829 if (!req) { 830 test_fw_config->test_result = -EINVAL; 831 return -EINVAL; 832 } 833 834 if (test_fw_config->into_buf) { 835 void *test_buf; 836 837 test_buf = kzalloc(TEST_FIRMWARE_BUF_SIZE, GFP_KERNEL); 838 if (!test_buf) 839 return -ENOSPC; 840 841 if (test_fw_config->partial) 842 req->rc = request_partial_firmware_into_buf 843 (&req->fw, 844 req->name, 845 req->dev, 846 test_buf, 847 test_fw_config->buf_size, 848 test_fw_config->file_offset); 849 else 850 req->rc = request_firmware_into_buf 851 (&req->fw, 852 req->name, 853 req->dev, 854 test_buf, 855 test_fw_config->buf_size); 856 if (!req->fw) 857 kfree(test_buf); 858 } else { 859 req->rc = test_fw_config->req_firmware(&req->fw, 860 req->name, 861 req->dev); 862 } 863 864 if (req->rc) { 865 pr_info("#%u: batched sync load failed: %d\n", 866 req->idx, req->rc); 867 if (!test_fw_config->test_result) 868 test_fw_config->test_result = req->rc; 869 } else if (req->fw) { 870 req->sent = true; 871 pr_info("#%u: batched sync loaded %zu\n", 872 req->idx, req->fw->size); 873 } 874 complete(&req->completion); 875 876 req->task = NULL; 877 878 return 0; 879} 880 881/* 882 * We use a kthread as otherwise the kernel serializes all our sync requests 883 * and we would not be able to mimic batched requests on a sync call. Batched 884 * requests on a sync call can for instance happen on a device driver when 885 * multiple cards are used and firmware loading happens outside of probe. 886 */ 887static ssize_t trigger_batched_requests_store(struct device *dev, 888 struct device_attribute *attr, 889 const char *buf, size_t count) 890{ 891 struct test_batched_req *req; 892 int rc; 893 u8 i; 894 895 mutex_lock(&test_fw_mutex); 896 897 test_fw_config->reqs = 898 vzalloc(array3_size(sizeof(struct test_batched_req), 899 test_fw_config->num_requests, 2)); 900 if (!test_fw_config->reqs) { 901 rc = -ENOMEM; 902 goto out_unlock; 903 } 904 905 pr_info("batched sync firmware loading '%s' %u times\n", 906 test_fw_config->name, test_fw_config->num_requests); 907 908 for (i = 0; i < test_fw_config->num_requests; i++) { 909 req = &test_fw_config->reqs[i]; 910 req->fw = NULL; 911 req->idx = i; 912 req->name = test_fw_config->name; 913 req->dev = dev; 914 init_completion(&req->completion); 915 req->task = kthread_run(test_fw_run_batch_request, req, 916 "%s-%u", KBUILD_MODNAME, req->idx); 917 if (!req->task || IS_ERR(req->task)) { 918 pr_err("Setting up thread %u failed\n", req->idx); 919 req->task = NULL; 920 rc = -ENOMEM; 921 goto out_bail; 922 } 923 } 924 925 rc = count; 926 927 /* 928 * We require an explicit release to enable more time and delay of 929 * calling release_firmware() to improve our chances of forcing a 930 * batched request. If we instead called release_firmware() right away 931 * then we might miss on an opportunity of having a successful firmware 932 * request pass on the opportunity to be come a batched request. 933 */ 934 935out_bail: 936 for (i = 0; i < test_fw_config->num_requests; i++) { 937 req = &test_fw_config->reqs[i]; 938 if (req->task || req->sent) 939 wait_for_completion(&req->completion); 940 } 941 942 /* Override any worker error if we had a general setup error */ 943 if (rc < 0) 944 test_fw_config->test_result = rc; 945 946out_unlock: 947 mutex_unlock(&test_fw_mutex); 948 949 return rc; 950} 951static DEVICE_ATTR_WO(trigger_batched_requests); 952 953/* 954 * We wait for each callback to return with the lock held, no need to lock here 955 */ 956static void trigger_batched_cb(const struct firmware *fw, void *context) 957{ 958 struct test_batched_req *req = context; 959 960 if (!req) { 961 test_fw_config->test_result = -EINVAL; 962 return; 963 } 964 965 /* forces *some* batched requests to queue up */ 966 if (!req->idx) 967 ssleep(2); 968 969 req->fw = fw; 970 971 /* 972 * Unfortunately the firmware API gives us nothing other than a null FW 973 * if the firmware was not found on async requests. Best we can do is 974 * just assume -ENOENT. A better API would pass the actual return 975 * value to the callback. 976 */ 977 if (!fw && !test_fw_config->test_result) 978 test_fw_config->test_result = -ENOENT; 979 980 complete(&req->completion); 981} 982 983static 984ssize_t trigger_batched_requests_async_store(struct device *dev, 985 struct device_attribute *attr, 986 const char *buf, size_t count) 987{ 988 struct test_batched_req *req; 989 bool send_uevent; 990 int rc; 991 u8 i; 992 993 mutex_lock(&test_fw_mutex); 994 995 test_fw_config->reqs = 996 vzalloc(array3_size(sizeof(struct test_batched_req), 997 test_fw_config->num_requests, 2)); 998 if (!test_fw_config->reqs) { 999 rc = -ENOMEM; 1000 goto out; 1001 } 1002 1003 pr_info("batched loading '%s' custom fallback mechanism %u times\n", 1004 test_fw_config->name, test_fw_config->num_requests); 1005 1006 send_uevent = test_fw_config->send_uevent ? FW_ACTION_UEVENT : 1007 FW_ACTION_NOUEVENT; 1008 1009 for (i = 0; i < test_fw_config->num_requests; i++) { 1010 req = &test_fw_config->reqs[i]; 1011 req->name = test_fw_config->name; 1012 req->fw = NULL; 1013 req->idx = i; 1014 init_completion(&req->completion); 1015 rc = request_firmware_nowait(THIS_MODULE, send_uevent, 1016 req->name, 1017 dev, GFP_KERNEL, req, 1018 trigger_batched_cb); 1019 if (rc) { 1020 pr_info("#%u: batched async load failed setup: %d\n", 1021 i, rc); 1022 req->rc = rc; 1023 goto out_bail; 1024 } else 1025 req->sent = true; 1026 } 1027 1028 rc = count; 1029 1030out_bail: 1031 1032 /* 1033 * We require an explicit release to enable more time and delay of 1034 * calling release_firmware() to improve our chances of forcing a 1035 * batched request. If we instead called release_firmware() right away 1036 * then we might miss on an opportunity of having a successful firmware 1037 * request pass on the opportunity to be come a batched request. 1038 */ 1039 1040 for (i = 0; i < test_fw_config->num_requests; i++) { 1041 req = &test_fw_config->reqs[i]; 1042 if (req->sent) 1043 wait_for_completion(&req->completion); 1044 } 1045 1046 /* Override any worker error if we had a general setup error */ 1047 if (rc < 0) 1048 test_fw_config->test_result = rc; 1049 1050out: 1051 mutex_unlock(&test_fw_mutex); 1052 1053 return rc; 1054} 1055static DEVICE_ATTR_WO(trigger_batched_requests_async); 1056 1057static void upload_release(struct test_firmware_upload *tst) 1058{ 1059 firmware_upload_unregister(tst->fwl); 1060 kfree(tst->buf); 1061 kfree(tst->name); 1062 kfree(tst); 1063} 1064 1065static void upload_release_all(void) 1066{ 1067 struct test_firmware_upload *tst, *tmp; 1068 1069 list_for_each_entry_safe(tst, tmp, &test_upload_list, node) { 1070 list_del(&tst->node); 1071 upload_release(tst); 1072 } 1073 test_fw_config->upload_name = NULL; 1074} 1075 1076/* 1077 * This table is replicated from .../firmware_loader/sysfs_upload.c 1078 * and needs to be kept in sync. 1079 */ 1080static const char * const fw_upload_err_str[] = { 1081 [FW_UPLOAD_ERR_NONE] = "none", 1082 [FW_UPLOAD_ERR_HW_ERROR] = "hw-error", 1083 [FW_UPLOAD_ERR_TIMEOUT] = "timeout", 1084 [FW_UPLOAD_ERR_CANCELED] = "user-abort", 1085 [FW_UPLOAD_ERR_BUSY] = "device-busy", 1086 [FW_UPLOAD_ERR_INVALID_SIZE] = "invalid-file-size", 1087 [FW_UPLOAD_ERR_RW_ERROR] = "read-write-error", 1088 [FW_UPLOAD_ERR_WEAROUT] = "flash-wearout", 1089}; 1090 1091static void upload_err_inject_error(struct test_firmware_upload *tst, 1092 const u8 *p, const char *prog) 1093{ 1094 enum fw_upload_err err; 1095 1096 for (err = FW_UPLOAD_ERR_NONE + 1; err < FW_UPLOAD_ERR_MAX; err++) { 1097 if (strncmp(p, fw_upload_err_str[err], 1098 strlen(fw_upload_err_str[err])) == 0) { 1099 tst->inject.prog = prog; 1100 tst->inject.err_code = err; 1101 return; 1102 } 1103 } 1104} 1105 1106static void upload_err_inject_prog(struct test_firmware_upload *tst, 1107 const u8 *p) 1108{ 1109 static const char * const progs[] = { 1110 "preparing:", "transferring:", "programming:" 1111 }; 1112 int i; 1113 1114 for (i = 0; i < ARRAY_SIZE(progs); i++) { 1115 if (strncmp(p, progs[i], strlen(progs[i])) == 0) { 1116 upload_err_inject_error(tst, p + strlen(progs[i]), 1117 progs[i]); 1118 return; 1119 } 1120 } 1121} 1122 1123#define FIVE_MINUTES_MS (5 * 60 * 1000) 1124static enum fw_upload_err 1125fw_upload_wait_on_cancel(struct test_firmware_upload *tst) 1126{ 1127 int ms_delay; 1128 1129 for (ms_delay = 0; ms_delay < FIVE_MINUTES_MS; ms_delay += 100) { 1130 msleep(100); 1131 if (tst->cancel_request) 1132 return FW_UPLOAD_ERR_CANCELED; 1133 } 1134 return FW_UPLOAD_ERR_NONE; 1135} 1136 1137static enum fw_upload_err test_fw_upload_prepare(struct fw_upload *fwl, 1138 const u8 *data, u32 size) 1139{ 1140 struct test_firmware_upload *tst = fwl->dd_handle; 1141 enum fw_upload_err ret = FW_UPLOAD_ERR_NONE; 1142 const char *progress = "preparing:"; 1143 1144 tst->cancel_request = false; 1145 1146 if (!size || size > TEST_UPLOAD_MAX_SIZE) { 1147 ret = FW_UPLOAD_ERR_INVALID_SIZE; 1148 goto err_out; 1149 } 1150 1151 if (strncmp(data, "inject:", strlen("inject:")) == 0) 1152 upload_err_inject_prog(tst, data + strlen("inject:")); 1153 1154 memset(tst->buf, 0, TEST_UPLOAD_MAX_SIZE); 1155 tst->size = size; 1156 1157 if (tst->inject.err_code == FW_UPLOAD_ERR_NONE || 1158 strncmp(tst->inject.prog, progress, strlen(progress)) != 0) 1159 return FW_UPLOAD_ERR_NONE; 1160 1161 if (tst->inject.err_code == FW_UPLOAD_ERR_CANCELED) 1162 ret = fw_upload_wait_on_cancel(tst); 1163 else 1164 ret = tst->inject.err_code; 1165 1166err_out: 1167 /* 1168 * The cleanup op only executes if the prepare op succeeds. 1169 * If the prepare op fails, it must do it's own clean-up. 1170 */ 1171 tst->inject.err_code = FW_UPLOAD_ERR_NONE; 1172 tst->inject.prog = NULL; 1173 1174 return ret; 1175} 1176 1177static enum fw_upload_err test_fw_upload_write(struct fw_upload *fwl, 1178 const u8 *data, u32 offset, 1179 u32 size, u32 *written) 1180{ 1181 struct test_firmware_upload *tst = fwl->dd_handle; 1182 const char *progress = "transferring:"; 1183 u32 blk_size; 1184 1185 if (tst->cancel_request) 1186 return FW_UPLOAD_ERR_CANCELED; 1187 1188 blk_size = min_t(u32, TEST_UPLOAD_BLK_SIZE, size); 1189 memcpy(tst->buf + offset, data + offset, blk_size); 1190 1191 *written = blk_size; 1192 1193 if (tst->inject.err_code == FW_UPLOAD_ERR_NONE || 1194 strncmp(tst->inject.prog, progress, strlen(progress)) != 0) 1195 return FW_UPLOAD_ERR_NONE; 1196 1197 if (tst->inject.err_code == FW_UPLOAD_ERR_CANCELED) 1198 return fw_upload_wait_on_cancel(tst); 1199 1200 return tst->inject.err_code; 1201} 1202 1203static enum fw_upload_err test_fw_upload_complete(struct fw_upload *fwl) 1204{ 1205 struct test_firmware_upload *tst = fwl->dd_handle; 1206 const char *progress = "programming:"; 1207 1208 if (tst->cancel_request) 1209 return FW_UPLOAD_ERR_CANCELED; 1210 1211 if (tst->inject.err_code == FW_UPLOAD_ERR_NONE || 1212 strncmp(tst->inject.prog, progress, strlen(progress)) != 0) 1213 return FW_UPLOAD_ERR_NONE; 1214 1215 if (tst->inject.err_code == FW_UPLOAD_ERR_CANCELED) 1216 return fw_upload_wait_on_cancel(tst); 1217 1218 return tst->inject.err_code; 1219} 1220 1221static void test_fw_upload_cancel(struct fw_upload *fwl) 1222{ 1223 struct test_firmware_upload *tst = fwl->dd_handle; 1224 1225 tst->cancel_request = true; 1226} 1227 1228static void test_fw_cleanup(struct fw_upload *fwl) 1229{ 1230 struct test_firmware_upload *tst = fwl->dd_handle; 1231 1232 tst->inject.err_code = FW_UPLOAD_ERR_NONE; 1233 tst->inject.prog = NULL; 1234} 1235 1236static const struct fw_upload_ops upload_test_ops = { 1237 .prepare = test_fw_upload_prepare, 1238 .write = test_fw_upload_write, 1239 .poll_complete = test_fw_upload_complete, 1240 .cancel = test_fw_upload_cancel, 1241 .cleanup = test_fw_cleanup 1242}; 1243 1244static ssize_t upload_register_store(struct device *dev, 1245 struct device_attribute *attr, 1246 const char *buf, size_t count) 1247{ 1248 struct test_firmware_upload *tst; 1249 struct fw_upload *fwl; 1250 char *name; 1251 int ret; 1252 1253 name = kstrndup(buf, count, GFP_KERNEL); 1254 if (!name) 1255 return -ENOMEM; 1256 1257 mutex_lock(&test_fw_mutex); 1258 tst = upload_lookup_name(name); 1259 if (tst) { 1260 ret = -EEXIST; 1261 goto free_name; 1262 } 1263 1264 tst = kzalloc(sizeof(*tst), GFP_KERNEL); 1265 if (!tst) { 1266 ret = -ENOMEM; 1267 goto free_name; 1268 } 1269 1270 tst->name = name; 1271 tst->buf = kzalloc(TEST_UPLOAD_MAX_SIZE, GFP_KERNEL); 1272 if (!tst->buf) { 1273 ret = -ENOMEM; 1274 goto free_tst; 1275 } 1276 1277 fwl = firmware_upload_register(THIS_MODULE, dev, tst->name, 1278 &upload_test_ops, tst); 1279 if (IS_ERR(fwl)) { 1280 ret = PTR_ERR(fwl); 1281 goto free_buf; 1282 } 1283 1284 tst->fwl = fwl; 1285 list_add_tail(&tst->node, &test_upload_list); 1286 mutex_unlock(&test_fw_mutex); 1287 return count; 1288 1289free_buf: 1290 kfree(tst->buf); 1291 1292free_tst: 1293 kfree(tst); 1294 1295free_name: 1296 mutex_unlock(&test_fw_mutex); 1297 kfree(name); 1298 1299 return ret; 1300} 1301static DEVICE_ATTR_WO(upload_register); 1302 1303static ssize_t upload_unregister_store(struct device *dev, 1304 struct device_attribute *attr, 1305 const char *buf, size_t count) 1306{ 1307 struct test_firmware_upload *tst; 1308 int ret = count; 1309 1310 mutex_lock(&test_fw_mutex); 1311 tst = upload_lookup_name(buf); 1312 if (!tst) { 1313 ret = -EINVAL; 1314 goto out; 1315 } 1316 1317 if (test_fw_config->upload_name == tst->name) 1318 test_fw_config->upload_name = NULL; 1319 1320 list_del(&tst->node); 1321 upload_release(tst); 1322 1323out: 1324 mutex_unlock(&test_fw_mutex); 1325 return ret; 1326} 1327static DEVICE_ATTR_WO(upload_unregister); 1328 1329static ssize_t test_result_show(struct device *dev, 1330 struct device_attribute *attr, 1331 char *buf) 1332{ 1333 return test_dev_config_show_int(buf, test_fw_config->test_result); 1334} 1335static DEVICE_ATTR_RO(test_result); 1336 1337static ssize_t release_all_firmware_store(struct device *dev, 1338 struct device_attribute *attr, 1339 const char *buf, size_t count) 1340{ 1341 test_release_all_firmware(); 1342 return count; 1343} 1344static DEVICE_ATTR_WO(release_all_firmware); 1345 1346static ssize_t read_firmware_show(struct device *dev, 1347 struct device_attribute *attr, 1348 char *buf) 1349{ 1350 struct test_batched_req *req; 1351 u8 idx; 1352 ssize_t rc = 0; 1353 1354 mutex_lock(&test_fw_mutex); 1355 1356 idx = test_fw_config->read_fw_idx; 1357 if (idx >= test_fw_config->num_requests) { 1358 rc = -ERANGE; 1359 goto out; 1360 } 1361 1362 if (!test_fw_config->reqs) { 1363 rc = -EINVAL; 1364 goto out; 1365 } 1366 1367 req = &test_fw_config->reqs[idx]; 1368 if (!req->fw) { 1369 pr_err("#%u: failed to async load firmware\n", idx); 1370 rc = -ENOENT; 1371 goto out; 1372 } 1373 1374 pr_info("#%u: loaded %zu\n", idx, req->fw->size); 1375 1376 if (req->fw->size > PAGE_SIZE) { 1377 pr_err("Testing interface must use PAGE_SIZE firmware for now\n"); 1378 rc = -EINVAL; 1379 goto out; 1380 } 1381 memcpy(buf, req->fw->data, req->fw->size); 1382 1383 rc = req->fw->size; 1384out: 1385 mutex_unlock(&test_fw_mutex); 1386 1387 return rc; 1388} 1389static DEVICE_ATTR_RO(read_firmware); 1390 1391static ssize_t upload_read_show(struct device *dev, 1392 struct device_attribute *attr, 1393 char *buf) 1394{ 1395 struct test_firmware_upload *tst = NULL; 1396 struct test_firmware_upload *tst_iter; 1397 int ret = -EINVAL; 1398 1399 if (!test_fw_config->upload_name) { 1400 pr_err("Set config_upload_name before using upload_read\n"); 1401 return -EINVAL; 1402 } 1403 1404 mutex_lock(&test_fw_mutex); 1405 list_for_each_entry(tst_iter, &test_upload_list, node) 1406 if (tst_iter->name == test_fw_config->upload_name) { 1407 tst = tst_iter; 1408 break; 1409 } 1410 1411 if (!tst) { 1412 pr_err("Firmware name not found: %s\n", 1413 test_fw_config->upload_name); 1414 goto out; 1415 } 1416 1417 if (tst->size > PAGE_SIZE) { 1418 pr_err("Testing interface must use PAGE_SIZE firmware for now\n"); 1419 goto out; 1420 } 1421 1422 memcpy(buf, tst->buf, tst->size); 1423 ret = tst->size; 1424out: 1425 mutex_unlock(&test_fw_mutex); 1426 return ret; 1427} 1428static DEVICE_ATTR_RO(upload_read); 1429 1430#define TEST_FW_DEV_ATTR(name) &dev_attr_##name.attr 1431 1432static struct attribute *test_dev_attrs[] = { 1433 TEST_FW_DEV_ATTR(reset), 1434 1435 TEST_FW_DEV_ATTR(config), 1436 TEST_FW_DEV_ATTR(config_name), 1437 TEST_FW_DEV_ATTR(config_num_requests), 1438 TEST_FW_DEV_ATTR(config_into_buf), 1439 TEST_FW_DEV_ATTR(config_buf_size), 1440 TEST_FW_DEV_ATTR(config_file_offset), 1441 TEST_FW_DEV_ATTR(config_partial), 1442 TEST_FW_DEV_ATTR(config_sync_direct), 1443 TEST_FW_DEV_ATTR(config_send_uevent), 1444 TEST_FW_DEV_ATTR(config_read_fw_idx), 1445 TEST_FW_DEV_ATTR(config_upload_name), 1446 1447 /* These don't use the config at all - they could be ported! */ 1448 TEST_FW_DEV_ATTR(trigger_request), 1449 TEST_FW_DEV_ATTR(trigger_async_request), 1450 TEST_FW_DEV_ATTR(trigger_custom_fallback), 1451#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE 1452 TEST_FW_DEV_ATTR(trigger_request_platform), 1453#endif 1454 1455 /* These use the config and can use the test_result */ 1456 TEST_FW_DEV_ATTR(trigger_batched_requests), 1457 TEST_FW_DEV_ATTR(trigger_batched_requests_async), 1458 1459 TEST_FW_DEV_ATTR(release_all_firmware), 1460 TEST_FW_DEV_ATTR(test_result), 1461 TEST_FW_DEV_ATTR(read_firmware), 1462 TEST_FW_DEV_ATTR(upload_read), 1463 TEST_FW_DEV_ATTR(upload_register), 1464 TEST_FW_DEV_ATTR(upload_unregister), 1465 NULL, 1466}; 1467 1468ATTRIBUTE_GROUPS(test_dev); 1469 1470static struct miscdevice test_fw_misc_device = { 1471 .minor = MISC_DYNAMIC_MINOR, 1472 .name = "test_firmware", 1473 .fops = &test_fw_fops, 1474 .groups = test_dev_groups, 1475}; 1476 1477static int __init test_firmware_init(void) 1478{ 1479 int rc; 1480 1481 test_fw_config = kzalloc(sizeof(struct test_config), GFP_KERNEL); 1482 if (!test_fw_config) 1483 return -ENOMEM; 1484 1485 rc = __test_firmware_config_init(); 1486 if (rc) { 1487 kfree(test_fw_config); 1488 pr_err("could not init firmware test config: %d\n", rc); 1489 return rc; 1490 } 1491 1492 rc = misc_register(&test_fw_misc_device); 1493 if (rc) { 1494 kfree(test_fw_config); 1495 pr_err("could not register misc device: %d\n", rc); 1496 return rc; 1497 } 1498 1499 pr_warn("interface ready\n"); 1500 1501 return 0; 1502} 1503 1504module_init(test_firmware_init); 1505 1506static void __exit test_firmware_exit(void) 1507{ 1508 mutex_lock(&test_fw_mutex); 1509 release_firmware(test_firmware); 1510 misc_deregister(&test_fw_misc_device); 1511 upload_release_all(); 1512 __test_firmware_config_free(); 1513 kfree(test_fw_config); 1514 mutex_unlock(&test_fw_mutex); 1515 1516 pr_warn("removed interface\n"); 1517} 1518 1519module_exit(test_firmware_exit); 1520 1521MODULE_AUTHOR("Kees Cook <keescook@chromium.org>"); 1522MODULE_LICENSE("GPL");