Lines Matching +full:firmware +full:- +full:name
1 // SPDX-License-Identifier: GPL-2.0-only
3 * This module provides an interface to trigger and test firmware loading.
5 * It is designed to be used for basic evaluation of the firmware loading
6 * subsystem (for example when validating firmware verification). It lacks
8 * unless explicitly requested by name.
17 #include <linux/firmware.h>
32 #define TEST_FIRMWARE_NAME "test-firmware.bin"
37 static const struct firmware *test_firmware;
43 const struct firmware *fw;
44 const char *name; member
52 * test_config - represents configuration for the test for different triggers
54 * @name: the name of the firmware file to look for
66 * @read_fw_idx: index of thread from which we want to read firmware results
76 * information passed today on error is the fact that no firmware was
77 * found so we can only assume -ENOENT on async calls if the firmware is
85 * -EINVAL: invalid parameters or request
86 * -ENOENT: files not found
90 * -ENOMEM: memory pressure on system
91 * -ENODEV: out of number of devices to test
92 * -EINVAL: an unexpected error has occurred
97 char *name; member
113 int (*req_firmware)(const struct firmware **fw, const char *name,
127 test_firmware->data, in test_fw_misc_read()
128 test_firmware->size); in test_fw_misc_read()
143 if (!test_fw_config->reqs) in __test_release_all_firmware()
146 for (i = 0; i < test_fw_config->num_requests; i++) { in __test_release_all_firmware()
147 req = &test_fw_config->reqs[i]; in __test_release_all_firmware()
148 if (req->fw) { in __test_release_all_firmware()
149 if (req->fw_buf) { in __test_release_all_firmware()
150 kfree_const(req->fw_buf); in __test_release_all_firmware()
151 req->fw_buf = NULL; in __test_release_all_firmware()
153 release_firmware(req->fw); in __test_release_all_firmware()
154 req->fw = NULL; in __test_release_all_firmware()
158 vfree(test_fw_config->reqs); in __test_release_all_firmware()
159 test_fw_config->reqs = NULL; in __test_release_all_firmware()
173 kfree_const(test_fw_config->name); in __test_firmware_config_free()
174 test_fw_config->name = NULL; in __test_firmware_config_free()
182 static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp) in __kstrncpy() argument
184 *dst = kstrndup(name, count, gfp); in __kstrncpy()
186 return -ENOMEM; in __kstrncpy()
194 ret = __kstrncpy(&test_fw_config->name, TEST_FIRMWARE_NAME, in __test_firmware_config_init()
199 test_fw_config->num_requests = TEST_FIRMWARE_NUM_REQS; in __test_firmware_config_init()
200 test_fw_config->send_uevent = true; in __test_firmware_config_init()
201 test_fw_config->into_buf = false; in __test_firmware_config_init()
202 test_fw_config->buf_size = TEST_FIRMWARE_BUF_SIZE; in __test_firmware_config_init()
203 test_fw_config->file_offset = 0; in __test_firmware_config_init()
204 test_fw_config->partial = false; in __test_firmware_config_init()
205 test_fw_config->sync_direct = false; in __test_firmware_config_init()
206 test_fw_config->req_firmware = request_firmware; in __test_firmware_config_init()
207 test_fw_config->test_result = 0; in __test_firmware_config_init()
208 test_fw_config->reqs = NULL; in __test_firmware_config_init()
229 ret = -ENOMEM; in reset_store()
253 len += scnprintf(buf, PAGE_SIZE - len, in config_show()
257 if (test_fw_config->name) in config_show()
258 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
259 "name:\t%s\n", in config_show()
260 test_fw_config->name); in config_show()
262 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
263 "name:\tEMTPY\n"); in config_show()
265 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
266 "num_requests:\t%u\n", test_fw_config->num_requests); in config_show()
268 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
270 test_fw_config->send_uevent ? in config_show()
273 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
275 test_fw_config->into_buf ? "true" : "false"); in config_show()
276 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
277 "buf_size:\t%zu\n", test_fw_config->buf_size); in config_show()
278 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
279 "file_offset:\t%zu\n", test_fw_config->file_offset); in config_show()
280 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
282 test_fw_config->partial ? "true" : "false"); in config_show()
283 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
285 test_fw_config->sync_direct ? "true" : "false"); in config_show()
286 len += scnprintf(buf + len, PAGE_SIZE - len, in config_show()
287 "read_fw_idx:\t%u\n", test_fw_config->read_fw_idx); in config_show()
302 kfree_const(test_fw_config->name); in config_name_store()
303 ret = __kstrncpy(&test_fw_config->name, buf, count, GFP_KERNEL); in config_name_store()
330 ret = -EINVAL; in __test_dev_config_update_bool()
417 return config_test_show_str(buf, test_fw_config->name); in config_name_show()
428 if (test_fw_config->reqs) { in config_num_requests_store()
430 rc = -EINVAL; in config_num_requests_store()
436 &test_fw_config->num_requests); in config_num_requests_store()
447 return test_dev_config_show_u8(buf, test_fw_config->num_requests); in config_num_requests_show()
457 &test_fw_config->into_buf); in config_into_buf_store()
464 return test_dev_config_show_bool(buf, test_fw_config->into_buf); in config_into_buf_show()
475 if (test_fw_config->reqs) { in config_buf_size_store()
477 rc = -EINVAL; in config_buf_size_store()
483 &test_fw_config->buf_size); in config_buf_size_store()
494 return test_dev_config_show_size_t(buf, test_fw_config->buf_size); in config_buf_size_show()
505 if (test_fw_config->reqs) { in config_file_offset_store()
507 rc = -EINVAL; in config_file_offset_store()
513 &test_fw_config->file_offset); in config_file_offset_store()
524 return test_dev_config_show_size_t(buf, test_fw_config->file_offset); in config_file_offset_show()
534 &test_fw_config->partial); in config_partial_store()
541 return test_dev_config_show_bool(buf, test_fw_config->partial); in config_partial_show()
550 &test_fw_config->sync_direct); in config_sync_direct_store()
553 test_fw_config->req_firmware = test_fw_config->sync_direct ? in config_sync_direct_store()
563 return test_dev_config_show_bool(buf, test_fw_config->sync_direct); in config_sync_direct_show()
572 &test_fw_config->send_uevent); in config_send_uevent_store()
579 return test_dev_config_show_bool(buf, test_fw_config->send_uevent); in config_send_uevent_show()
588 &test_fw_config->read_fw_idx); in config_read_fw_idx_store()
595 return test_dev_config_show_u8(buf, test_fw_config->read_fw_idx); in config_read_fw_idx_show()
605 char *name; in trigger_request_store() local
607 name = kstrndup(buf, count, GFP_KERNEL); in trigger_request_store()
608 if (!name) in trigger_request_store()
609 return -ENOMEM; in trigger_request_store()
611 pr_info("loading '%s'\n", name); in trigger_request_store()
615 if (test_fw_config->reqs) in trigger_request_store()
618 rc = request_firmware(&test_firmware, name, dev); in trigger_request_store()
620 pr_info("load of '%s' failed: %d\n", name, rc); in trigger_request_store()
623 pr_info("loaded: %zu\n", test_firmware->size); in trigger_request_store()
629 kfree(name); in trigger_request_store()
650 const struct firmware *firmware = NULL; in trigger_request_platform_store() local
652 char *name; in trigger_request_platform_store() local
655 name = kstrndup(buf, count, GFP_KERNEL); in trigger_request_platform_store()
656 if (!name) in trigger_request_platform_store()
657 return -ENOMEM; in trigger_request_platform_store()
659 pr_info("inserting test platform fw '%s'\n", name); in trigger_request_platform_store()
660 efi_embedded_fw.name = name; in trigger_request_platform_store()
667 pr_info("loading '%s'\n", name); in trigger_request_platform_store()
668 rc = firmware_request_platform(&firmware, name, dev); in trigger_request_platform_store()
670 pr_info("load of '%s' failed: %d\n", name, rc); in trigger_request_platform_store()
673 if (firmware->size != sizeof(test_data) || in trigger_request_platform_store()
674 memcmp(firmware->data, test_data, sizeof(test_data)) != 0) { in trigger_request_platform_store()
675 pr_info("firmware contents mismatch for '%s'\n", name); in trigger_request_platform_store()
676 rc = -EINVAL; in trigger_request_platform_store()
679 pr_info("loaded: %zu\n", firmware->size); in trigger_request_platform_store()
684 release_firmware(firmware); in trigger_request_platform_store()
686 kfree(name); in trigger_request_platform_store()
695 static void trigger_async_request_cb(const struct firmware *fw, void *context) in trigger_async_request_cb()
706 char *name; in trigger_async_request_store() local
708 name = kstrndup(buf, count, GFP_KERNEL); in trigger_async_request_store()
709 if (!name) in trigger_async_request_store()
710 return -ENOMEM; in trigger_async_request_store()
712 pr_info("loading '%s'\n", name); in trigger_async_request_store()
717 if (test_fw_config->reqs) in trigger_async_request_store()
719 rc = request_firmware_nowait(THIS_MODULE, 1, name, dev, GFP_KERNEL, in trigger_async_request_store()
722 pr_info("async load of '%s' failed: %d\n", name, rc); in trigger_async_request_store()
723 kfree(name); in trigger_async_request_store()
726 /* Free 'name' ASAP, to test for race conditions */ in trigger_async_request_store()
727 kfree(name); in trigger_async_request_store()
732 pr_info("loaded: %zu\n", test_firmware->size); in trigger_async_request_store()
735 pr_err("failed to async load firmware\n"); in trigger_async_request_store()
736 rc = -ENOMEM; in trigger_async_request_store()
751 char *name; in trigger_custom_fallback_store() local
753 name = kstrndup(buf, count, GFP_KERNEL); in trigger_custom_fallback_store()
754 if (!name) in trigger_custom_fallback_store()
755 return -ENOMEM; in trigger_custom_fallback_store()
757 pr_info("loading '%s' using custom fallback mechanism\n", name); in trigger_custom_fallback_store()
761 if (test_fw_config->reqs) in trigger_custom_fallback_store()
764 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, name, in trigger_custom_fallback_store()
768 pr_info("async load of '%s' failed: %d\n", name, rc); in trigger_custom_fallback_store()
769 kfree(name); in trigger_custom_fallback_store()
772 /* Free 'name' ASAP, to test for race conditions */ in trigger_custom_fallback_store()
773 kfree(name); in trigger_custom_fallback_store()
778 pr_info("loaded: %zu\n", test_firmware->size); in trigger_custom_fallback_store()
781 pr_err("failed to async load firmware\n"); in trigger_custom_fallback_store()
782 rc = -ENODEV; in trigger_custom_fallback_store()
797 test_fw_config->test_result = -EINVAL; in test_fw_run_batch_request()
798 return -EINVAL; in test_fw_run_batch_request()
801 if (test_fw_config->into_buf) { in test_fw_run_batch_request()
806 return -ENOMEM; in test_fw_run_batch_request()
808 if (test_fw_config->partial) in test_fw_run_batch_request()
809 req->rc = request_partial_firmware_into_buf in test_fw_run_batch_request()
810 (&req->fw, in test_fw_run_batch_request()
811 req->name, in test_fw_run_batch_request()
812 req->dev, in test_fw_run_batch_request()
814 test_fw_config->buf_size, in test_fw_run_batch_request()
815 test_fw_config->file_offset); in test_fw_run_batch_request()
817 req->rc = request_firmware_into_buf in test_fw_run_batch_request()
818 (&req->fw, in test_fw_run_batch_request()
819 req->name, in test_fw_run_batch_request()
820 req->dev, in test_fw_run_batch_request()
822 test_fw_config->buf_size); in test_fw_run_batch_request()
823 if (!req->fw) in test_fw_run_batch_request()
826 req->fw_buf = test_buf; in test_fw_run_batch_request()
828 req->rc = test_fw_config->req_firmware(&req->fw, in test_fw_run_batch_request()
829 req->name, in test_fw_run_batch_request()
830 req->dev); in test_fw_run_batch_request()
833 if (req->rc) { in test_fw_run_batch_request()
835 req->idx, req->rc); in test_fw_run_batch_request()
836 if (!test_fw_config->test_result) in test_fw_run_batch_request()
837 test_fw_config->test_result = req->rc; in test_fw_run_batch_request()
838 } else if (req->fw) { in test_fw_run_batch_request()
839 req->sent = true; in test_fw_run_batch_request()
841 req->idx, req->fw->size); in test_fw_run_batch_request()
843 complete(&req->completion); in test_fw_run_batch_request()
845 req->task = NULL; in test_fw_run_batch_request()
854 * multiple cards are used and firmware loading happens outside of probe.
866 if (test_fw_config->reqs) { in trigger_batched_requests_store()
867 rc = -EBUSY; in trigger_batched_requests_store()
871 test_fw_config->reqs = in trigger_batched_requests_store()
873 test_fw_config->num_requests, 2)); in trigger_batched_requests_store()
874 if (!test_fw_config->reqs) { in trigger_batched_requests_store()
875 rc = -ENOMEM; in trigger_batched_requests_store()
879 pr_info("batched sync firmware loading '%s' %u times\n", in trigger_batched_requests_store()
880 test_fw_config->name, test_fw_config->num_requests); in trigger_batched_requests_store()
882 for (i = 0; i < test_fw_config->num_requests; i++) { in trigger_batched_requests_store()
883 req = &test_fw_config->reqs[i]; in trigger_batched_requests_store()
884 req->fw = NULL; in trigger_batched_requests_store()
885 req->idx = i; in trigger_batched_requests_store()
886 req->name = test_fw_config->name; in trigger_batched_requests_store()
887 req->fw_buf = NULL; in trigger_batched_requests_store()
888 req->dev = dev; in trigger_batched_requests_store()
889 init_completion(&req->completion); in trigger_batched_requests_store()
890 req->task = kthread_run(test_fw_run_batch_request, req, in trigger_batched_requests_store()
891 "%s-%u", KBUILD_MODNAME, req->idx); in trigger_batched_requests_store()
892 if (!req->task || IS_ERR(req->task)) { in trigger_batched_requests_store()
893 pr_err("Setting up thread %u failed\n", req->idx); in trigger_batched_requests_store()
894 req->task = NULL; in trigger_batched_requests_store()
895 rc = -ENOMEM; in trigger_batched_requests_store()
906 * then we might miss on an opportunity of having a successful firmware in trigger_batched_requests_store()
911 for (i = 0; i < test_fw_config->num_requests; i++) { in trigger_batched_requests_store()
912 req = &test_fw_config->reqs[i]; in trigger_batched_requests_store()
913 if (req->task || req->sent) in trigger_batched_requests_store()
914 wait_for_completion(&req->completion); in trigger_batched_requests_store()
919 test_fw_config->test_result = rc; in trigger_batched_requests_store()
931 static void trigger_batched_cb(const struct firmware *fw, void *context) in trigger_batched_cb()
936 test_fw_config->test_result = -EINVAL; in trigger_batched_cb()
941 if (!req->idx) in trigger_batched_cb()
944 req->fw = fw; in trigger_batched_cb()
947 * Unfortunately the firmware API gives us nothing other than a null FW in trigger_batched_cb()
948 * if the firmware was not found on async requests. Best we can do is in trigger_batched_cb()
949 * just assume -ENOENT. A better API would pass the actual return in trigger_batched_cb()
952 if (!fw && !test_fw_config->test_result) in trigger_batched_cb()
953 test_fw_config->test_result = -ENOENT; in trigger_batched_cb()
955 complete(&req->completion); in trigger_batched_cb()
970 if (test_fw_config->reqs) { in trigger_batched_requests_async_store()
971 rc = -EBUSY; in trigger_batched_requests_async_store()
975 test_fw_config->reqs = in trigger_batched_requests_async_store()
977 test_fw_config->num_requests, 2)); in trigger_batched_requests_async_store()
978 if (!test_fw_config->reqs) { in trigger_batched_requests_async_store()
979 rc = -ENOMEM; in trigger_batched_requests_async_store()
984 test_fw_config->name, test_fw_config->num_requests); in trigger_batched_requests_async_store()
986 send_uevent = test_fw_config->send_uevent ? FW_ACTION_HOTPLUG : in trigger_batched_requests_async_store()
989 for (i = 0; i < test_fw_config->num_requests; i++) { in trigger_batched_requests_async_store()
990 req = &test_fw_config->reqs[i]; in trigger_batched_requests_async_store()
991 req->name = test_fw_config->name; in trigger_batched_requests_async_store()
992 req->fw_buf = NULL; in trigger_batched_requests_async_store()
993 req->fw = NULL; in trigger_batched_requests_async_store()
994 req->idx = i; in trigger_batched_requests_async_store()
995 init_completion(&req->completion); in trigger_batched_requests_async_store()
997 req->name, in trigger_batched_requests_async_store()
1003 req->rc = rc; in trigger_batched_requests_async_store()
1006 req->sent = true; in trigger_batched_requests_async_store()
1017 * then we might miss on an opportunity of having a successful firmware in trigger_batched_requests_async_store()
1021 for (i = 0; i < test_fw_config->num_requests; i++) { in trigger_batched_requests_async_store()
1022 req = &test_fw_config->reqs[i]; in trigger_batched_requests_async_store()
1023 if (req->sent) in trigger_batched_requests_async_store()
1024 wait_for_completion(&req->completion); in trigger_batched_requests_async_store()
1029 test_fw_config->test_result = rc; in trigger_batched_requests_async_store()
1042 return test_dev_config_show_int(buf, test_fw_config->test_result); in test_result_show()
1065 idx = test_fw_config->read_fw_idx; in read_firmware_show()
1066 if (idx >= test_fw_config->num_requests) { in read_firmware_show()
1067 rc = -ERANGE; in read_firmware_show()
1071 if (!test_fw_config->reqs) { in read_firmware_show()
1072 rc = -EINVAL; in read_firmware_show()
1076 req = &test_fw_config->reqs[idx]; in read_firmware_show()
1077 if (!req->fw) { in read_firmware_show()
1078 pr_err("#%u: failed to async load firmware\n", idx); in read_firmware_show()
1079 rc = -ENOENT; in read_firmware_show()
1083 pr_info("#%u: loaded %zu\n", idx, req->fw->size); in read_firmware_show()
1085 if (req->fw->size > PAGE_SIZE) { in read_firmware_show()
1086 pr_err("Testing interface must use PAGE_SIZE firmware for now\n"); in read_firmware_show()
1087 rc = -EINVAL; in read_firmware_show()
1090 memcpy(buf, req->fw->data, req->fw->size); in read_firmware_show()
1092 rc = req->fw->size; in read_firmware_show()
1100 #define TEST_FW_DEV_ATTR(name) &dev_attr_##name.attr argument
1116 /* These don't use the config at all - they could be ported! */
1138 .name = "test_firmware",
1149 return -ENOMEM; in test_firmware_init()
1154 pr_err("could not init firmware test config: %d\n", rc); in test_firmware_init()