]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - lib/test_firmware.c
Merge branch 'i2c/for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[mirror_ubuntu-jammy-kernel.git] / lib / test_firmware.c
CommitLineData
09c434b8 1// SPDX-License-Identifier: GPL-2.0-only
0a8adf58
KC
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>
eb910947 16#include <linux/completion.h>
0a8adf58
KC
17#include <linux/firmware.h>
18#include <linux/device.h>
19#include <linux/fs.h>
20#include <linux/miscdevice.h>
7feebfa4 21#include <linux/sizes.h>
0a8adf58
KC
22#include <linux/slab.h>
23#include <linux/uaccess.h>
c92316bf
LR
24#include <linux/delay.h>
25#include <linux/kthread.h>
514c6032 26#include <linux/vmalloc.h>
548193cb 27#include <linux/efi_embedded_fw.h>
c92316bf 28
baaabecf
KC
29MODULE_IMPORT_NS(TEST_FIRMWARE);
30
c92316bf
LR
31#define TEST_FIRMWARE_NAME "test-firmware.bin"
32#define TEST_FIRMWARE_NUM_REQS 4
7feebfa4 33#define TEST_FIRMWARE_BUF_SIZE SZ_1K
0a8adf58
KC
34
35static DEFINE_MUTEX(test_fw_mutex);
36static const struct firmware *test_firmware;
37
c92316bf
LR
38struct test_batched_req {
39 u8 idx;
40 int rc;
41 bool sent;
42 const struct firmware *fw;
43 const char *name;
44 struct completion completion;
45 struct task_struct *task;
46 struct device *dev;
47};
48
49/**
50 * test_config - represents configuration for the test for different triggers
51 *
52 * @name: the name of the firmware file to look for
7feebfa4
SB
53 * @into_buf: when the into_buf is used if this is true
54 * request_firmware_into_buf() will be used instead.
5d90e05c
SB
55 * @buf_size: size of buf to allocate when into_buf is true
56 * @file_offset: file offset to request when calling request_firmware_into_buf
57 * @partial: partial read opt when calling request_firmware_into_buf
c92316bf
LR
58 * @sync_direct: when the sync trigger is used if this is true
59 * request_firmware_direct() will be used instead.
60 * @send_uevent: whether or not to send a uevent for async requests
61 * @num_requests: number of requests to try per test case. This is trigger
62 * specific.
63 * @reqs: stores all requests information
64 * @read_fw_idx: index of thread from which we want to read firmware results
65 * from through the read_fw trigger.
66 * @test_result: a test may use this to collect the result from the call
67 * of the request_firmware*() calls used in their tests. In order of
68 * priority we always keep first any setup error. If no setup errors were
69 * found then we move on to the first error encountered while running the
70 * API. Note that for async calls this typically will be a successful
71 * result (0) unless of course you've used bogus parameters, or the system
72 * is out of memory. In the async case the callback is expected to do a
73 * bit more homework to figure out what happened, unfortunately the only
74 * information passed today on error is the fact that no firmware was
75 * found so we can only assume -ENOENT on async calls if the firmware is
76 * NULL.
77 *
78 * Errors you can expect:
79 *
80 * API specific:
81 *
82 * 0: success for sync, for async it means request was sent
83 * -EINVAL: invalid parameters or request
84 * -ENOENT: files not found
85 *
86 * System environment:
87 *
88 * -ENOMEM: memory pressure on system
89 * -ENODEV: out of number of devices to test
90 * -EINVAL: an unexpected error has occurred
91 * @req_firmware: if @sync_direct is true this is set to
92 * request_firmware_direct(), otherwise request_firmware()
93 */
94struct test_config {
95 char *name;
7feebfa4 96 bool into_buf;
5d90e05c
SB
97 size_t buf_size;
98 size_t file_offset;
99 bool partial;
c92316bf
LR
100 bool sync_direct;
101 bool send_uevent;
102 u8 num_requests;
103 u8 read_fw_idx;
104
105 /*
106 * These below don't belong her but we'll move them once we create
107 * a struct fw_test_device and stuff the misc_dev under there later.
108 */
109 struct test_batched_req *reqs;
110 int test_result;
111 int (*req_firmware)(const struct firmware **fw, const char *name,
112 struct device *device);
113};
114
76f8ab1b 115static struct test_config *test_fw_config;
c92316bf 116
0a8adf58
KC
117static ssize_t test_fw_misc_read(struct file *f, char __user *buf,
118 size_t size, loff_t *offset)
119{
120 ssize_t rc = 0;
121
122 mutex_lock(&test_fw_mutex);
123 if (test_firmware)
124 rc = simple_read_from_buffer(buf, size, offset,
125 test_firmware->data,
126 test_firmware->size);
127 mutex_unlock(&test_fw_mutex);
128 return rc;
129}
130
131static const struct file_operations test_fw_fops = {
132 .owner = THIS_MODULE,
133 .read = test_fw_misc_read,
134};
135
c92316bf
LR
136static void __test_release_all_firmware(void)
137{
138 struct test_batched_req *req;
139 u8 i;
140
141 if (!test_fw_config->reqs)
142 return;
143
144 for (i = 0; i < test_fw_config->num_requests; i++) {
145 req = &test_fw_config->reqs[i];
146 if (req->fw)
147 release_firmware(req->fw);
148 }
149
150 vfree(test_fw_config->reqs);
151 test_fw_config->reqs = NULL;
152}
153
154static void test_release_all_firmware(void)
155{
156 mutex_lock(&test_fw_mutex);
157 __test_release_all_firmware();
158 mutex_unlock(&test_fw_mutex);
159}
160
161
162static void __test_firmware_config_free(void)
163{
164 __test_release_all_firmware();
165 kfree_const(test_fw_config->name);
166 test_fw_config->name = NULL;
167}
168
169/*
170 * XXX: move to kstrncpy() once merged.
171 *
172 * Users should use kfree_const() when freeing these.
173 */
174static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
175{
176 *dst = kstrndup(name, count, gfp);
177 if (!*dst)
178 return -ENOSPC;
179 return count;
180}
181
182static int __test_firmware_config_init(void)
183{
184 int ret;
185
186 ret = __kstrncpy(&test_fw_config->name, TEST_FIRMWARE_NAME,
187 strlen(TEST_FIRMWARE_NAME), GFP_KERNEL);
188 if (ret < 0)
189 goto out;
190
191 test_fw_config->num_requests = TEST_FIRMWARE_NUM_REQS;
192 test_fw_config->send_uevent = true;
7feebfa4 193 test_fw_config->into_buf = false;
5d90e05c
SB
194 test_fw_config->buf_size = TEST_FIRMWARE_BUF_SIZE;
195 test_fw_config->file_offset = 0;
196 test_fw_config->partial = false;
c92316bf
LR
197 test_fw_config->sync_direct = false;
198 test_fw_config->req_firmware = request_firmware;
199 test_fw_config->test_result = 0;
200 test_fw_config->reqs = NULL;
201
202 return 0;
203
204out:
205 __test_firmware_config_free();
206 return ret;
207}
208
209static ssize_t reset_store(struct device *dev,
210 struct device_attribute *attr,
211 const char *buf, size_t count)
212{
213 int ret;
214
215 mutex_lock(&test_fw_mutex);
216
217 __test_firmware_config_free();
218
219 ret = __test_firmware_config_init();
220 if (ret < 0) {
221 ret = -ENOMEM;
222 pr_err("could not alloc settings for config trigger: %d\n",
223 ret);
224 goto out;
225 }
226
227 pr_info("reset\n");
228 ret = count;
229
230out:
231 mutex_unlock(&test_fw_mutex);
232
233 return ret;
234}
235static DEVICE_ATTR_WO(reset);
236
237static ssize_t config_show(struct device *dev,
238 struct device_attribute *attr,
239 char *buf)
240{
241 int len = 0;
242
243 mutex_lock(&test_fw_mutex);
244
bd17cc5a 245 len += scnprintf(buf, PAGE_SIZE - len,
c92316bf
LR
246 "Custom trigger configuration for: %s\n",
247 dev_name(dev));
248
249 if (test_fw_config->name)
5d90e05c 250 len += scnprintf(buf + len, PAGE_SIZE - len,
c92316bf
LR
251 "name:\t%s\n",
252 test_fw_config->name);
253 else
5d90e05c 254 len += scnprintf(buf + len, PAGE_SIZE - len,
c92316bf
LR
255 "name:\tEMTPY\n");
256
5d90e05c 257 len += scnprintf(buf + len, PAGE_SIZE - len,
c92316bf
LR
258 "num_requests:\t%u\n", test_fw_config->num_requests);
259
5d90e05c 260 len += scnprintf(buf + len, PAGE_SIZE - len,
c92316bf
LR
261 "send_uevent:\t\t%s\n",
262 test_fw_config->send_uevent ?
263 "FW_ACTION_HOTPLUG" :
264 "FW_ACTION_NOHOTPLUG");
5d90e05c 265 len += scnprintf(buf + len, PAGE_SIZE - len,
7feebfa4
SB
266 "into_buf:\t\t%s\n",
267 test_fw_config->into_buf ? "true" : "false");
5d90e05c
SB
268 len += scnprintf(buf + len, PAGE_SIZE - len,
269 "buf_size:\t%zu\n", test_fw_config->buf_size);
270 len += scnprintf(buf + len, PAGE_SIZE - len,
271 "file_offset:\t%zu\n", test_fw_config->file_offset);
272 len += scnprintf(buf + len, PAGE_SIZE - len,
273 "partial:\t\t%s\n",
274 test_fw_config->partial ? "true" : "false");
275 len += scnprintf(buf + len, PAGE_SIZE - len,
c92316bf
LR
276 "sync_direct:\t\t%s\n",
277 test_fw_config->sync_direct ? "true" : "false");
5d90e05c 278 len += scnprintf(buf + len, PAGE_SIZE - len,
c92316bf
LR
279 "read_fw_idx:\t%u\n", test_fw_config->read_fw_idx);
280
281 mutex_unlock(&test_fw_mutex);
282
283 return len;
284}
285static DEVICE_ATTR_RO(config);
286
287static ssize_t config_name_store(struct device *dev,
288 struct device_attribute *attr,
289 const char *buf, size_t count)
290{
291 int ret;
292
293 mutex_lock(&test_fw_mutex);
294 kfree_const(test_fw_config->name);
295 ret = __kstrncpy(&test_fw_config->name, buf, count, GFP_KERNEL);
296 mutex_unlock(&test_fw_mutex);
297
298 return ret;
299}
300
301/*
302 * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE.
303 */
304static ssize_t config_test_show_str(char *dst,
305 char *src)
306{
307 int len;
308
309 mutex_lock(&test_fw_mutex);
310 len = snprintf(dst, PAGE_SIZE, "%s\n", src);
311 mutex_unlock(&test_fw_mutex);
312
313 return len;
314}
315
316static int test_dev_config_update_bool(const char *buf, size_t size,
317 bool *cfg)
318{
319 int ret;
320
321 mutex_lock(&test_fw_mutex);
322 if (strtobool(buf, cfg) < 0)
323 ret = -EINVAL;
324 else
325 ret = size;
326 mutex_unlock(&test_fw_mutex);
327
328 return ret;
329}
330
55623260 331static ssize_t test_dev_config_show_bool(char *buf, bool val)
c92316bf 332{
c92316bf
LR
333 return snprintf(buf, PAGE_SIZE, "%d\n", val);
334}
335
5d90e05c
SB
336static int test_dev_config_update_size_t(const char *buf,
337 size_t size,
338 size_t *cfg)
339{
340 int ret;
341 long new;
342
343 ret = kstrtol(buf, 10, &new);
344 if (ret)
345 return ret;
346
347 mutex_lock(&test_fw_mutex);
348 *(size_t *)cfg = new;
349 mutex_unlock(&test_fw_mutex);
350
351 /* Always return full write size even if we didn't consume all */
352 return size;
353}
354
355static ssize_t test_dev_config_show_size_t(char *buf, size_t val)
356{
357 return snprintf(buf, PAGE_SIZE, "%zu\n", val);
358}
359
55623260 360static ssize_t test_dev_config_show_int(char *buf, int val)
c92316bf 361{
c92316bf
LR
362 return snprintf(buf, PAGE_SIZE, "%d\n", val);
363}
364
365static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
366{
367 int ret;
368 long new;
369
370 ret = kstrtol(buf, 10, &new);
371 if (ret)
372 return ret;
373
374 if (new > U8_MAX)
375 return -EINVAL;
376
377 mutex_lock(&test_fw_mutex);
378 *(u8 *)cfg = new;
379 mutex_unlock(&test_fw_mutex);
380
381 /* Always return full write size even if we didn't consume all */
382 return size;
383}
384
55623260 385static ssize_t test_dev_config_show_u8(char *buf, u8 val)
c92316bf 386{
c92316bf
LR
387 return snprintf(buf, PAGE_SIZE, "%u\n", val);
388}
389
390static ssize_t config_name_show(struct device *dev,
391 struct device_attribute *attr,
392 char *buf)
393{
394 return config_test_show_str(buf, test_fw_config->name);
395}
b6b996b6 396static DEVICE_ATTR_RW(config_name);
c92316bf
LR
397
398static ssize_t config_num_requests_store(struct device *dev,
399 struct device_attribute *attr,
400 const char *buf, size_t count)
401{
402 int rc;
403
404 mutex_lock(&test_fw_mutex);
405 if (test_fw_config->reqs) {
406 pr_err("Must call release_all_firmware prior to changing config\n");
407 rc = -EINVAL;
a5e19233 408 mutex_unlock(&test_fw_mutex);
c92316bf
LR
409 goto out;
410 }
411 mutex_unlock(&test_fw_mutex);
412
413 rc = test_dev_config_update_u8(buf, count,
414 &test_fw_config->num_requests);
415
416out:
417 return rc;
418}
419
420static ssize_t config_num_requests_show(struct device *dev,
421 struct device_attribute *attr,
422 char *buf)
423{
424 return test_dev_config_show_u8(buf, test_fw_config->num_requests);
425}
b6b996b6 426static DEVICE_ATTR_RW(config_num_requests);
c92316bf 427
7feebfa4
SB
428static ssize_t config_into_buf_store(struct device *dev,
429 struct device_attribute *attr,
430 const char *buf, size_t count)
431{
432 return test_dev_config_update_bool(buf,
433 count,
434 &test_fw_config->into_buf);
435}
436
437static ssize_t config_into_buf_show(struct device *dev,
438 struct device_attribute *attr,
439 char *buf)
440{
441 return test_dev_config_show_bool(buf, test_fw_config->into_buf);
442}
443static DEVICE_ATTR_RW(config_into_buf);
444
5d90e05c
SB
445static ssize_t config_buf_size_store(struct device *dev,
446 struct device_attribute *attr,
447 const char *buf, size_t count)
448{
449 int rc;
450
451 mutex_lock(&test_fw_mutex);
452 if (test_fw_config->reqs) {
453 pr_err("Must call release_all_firmware prior to changing config\n");
454 rc = -EINVAL;
455 mutex_unlock(&test_fw_mutex);
456 goto out;
457 }
458 mutex_unlock(&test_fw_mutex);
459
460 rc = test_dev_config_update_size_t(buf, count,
461 &test_fw_config->buf_size);
462
463out:
464 return rc;
465}
466
467static ssize_t config_buf_size_show(struct device *dev,
468 struct device_attribute *attr,
469 char *buf)
470{
471 return test_dev_config_show_size_t(buf, test_fw_config->buf_size);
472}
473static DEVICE_ATTR_RW(config_buf_size);
474
475static ssize_t config_file_offset_store(struct device *dev,
476 struct device_attribute *attr,
477 const char *buf, size_t count)
478{
479 int rc;
480
481 mutex_lock(&test_fw_mutex);
482 if (test_fw_config->reqs) {
483 pr_err("Must call release_all_firmware prior to changing config\n");
484 rc = -EINVAL;
485 mutex_unlock(&test_fw_mutex);
486 goto out;
487 }
488 mutex_unlock(&test_fw_mutex);
489
490 rc = test_dev_config_update_size_t(buf, count,
491 &test_fw_config->file_offset);
492
493out:
494 return rc;
495}
496
497static ssize_t config_file_offset_show(struct device *dev,
498 struct device_attribute *attr,
499 char *buf)
500{
501 return test_dev_config_show_size_t(buf, test_fw_config->file_offset);
502}
503static DEVICE_ATTR_RW(config_file_offset);
504
505static ssize_t config_partial_store(struct device *dev,
506 struct device_attribute *attr,
507 const char *buf, size_t count)
508{
509 return test_dev_config_update_bool(buf,
510 count,
511 &test_fw_config->partial);
512}
513
514static ssize_t config_partial_show(struct device *dev,
515 struct device_attribute *attr,
516 char *buf)
517{
518 return test_dev_config_show_bool(buf, test_fw_config->partial);
519}
520static DEVICE_ATTR_RW(config_partial);
521
c92316bf
LR
522static ssize_t config_sync_direct_store(struct device *dev,
523 struct device_attribute *attr,
524 const char *buf, size_t count)
525{
526 int rc = test_dev_config_update_bool(buf, count,
527 &test_fw_config->sync_direct);
528
529 if (rc == count)
530 test_fw_config->req_firmware = test_fw_config->sync_direct ?
531 request_firmware_direct :
532 request_firmware;
533 return rc;
534}
535
536static ssize_t config_sync_direct_show(struct device *dev,
537 struct device_attribute *attr,
538 char *buf)
539{
540 return test_dev_config_show_bool(buf, test_fw_config->sync_direct);
541}
b6b996b6 542static DEVICE_ATTR_RW(config_sync_direct);
c92316bf
LR
543
544static ssize_t config_send_uevent_store(struct device *dev,
545 struct device_attribute *attr,
546 const char *buf, size_t count)
547{
548 return test_dev_config_update_bool(buf, count,
549 &test_fw_config->send_uevent);
550}
551
552static ssize_t config_send_uevent_show(struct device *dev,
553 struct device_attribute *attr,
554 char *buf)
555{
556 return test_dev_config_show_bool(buf, test_fw_config->send_uevent);
557}
b6b996b6 558static DEVICE_ATTR_RW(config_send_uevent);
c92316bf
LR
559
560static ssize_t config_read_fw_idx_store(struct device *dev,
561 struct device_attribute *attr,
562 const char *buf, size_t count)
563{
564 return test_dev_config_update_u8(buf, count,
565 &test_fw_config->read_fw_idx);
566}
567
568static ssize_t config_read_fw_idx_show(struct device *dev,
569 struct device_attribute *attr,
570 char *buf)
571{
572 return test_dev_config_show_u8(buf, test_fw_config->read_fw_idx);
573}
b6b996b6 574static DEVICE_ATTR_RW(config_read_fw_idx);
c92316bf
LR
575
576
0a8adf58
KC
577static ssize_t trigger_request_store(struct device *dev,
578 struct device_attribute *attr,
579 const char *buf, size_t count)
580{
581 int rc;
582 char *name;
583
be4a1326 584 name = kstrndup(buf, count, GFP_KERNEL);
0a8adf58
KC
585 if (!name)
586 return -ENOSPC;
0a8adf58
KC
587
588 pr_info("loading '%s'\n", name);
589
590 mutex_lock(&test_fw_mutex);
591 release_firmware(test_firmware);
592 test_firmware = NULL;
593 rc = request_firmware(&test_firmware, name, dev);
47e0bbb7 594 if (rc) {
0a8adf58 595 pr_info("load of '%s' failed: %d\n", name, rc);
47e0bbb7
BN
596 goto out;
597 }
598 pr_info("loaded: %zu\n", test_firmware->size);
599 rc = count;
600
601out:
0a8adf58
KC
602 mutex_unlock(&test_fw_mutex);
603
604 kfree(name);
605
47e0bbb7 606 return rc;
0a8adf58
KC
607}
608static DEVICE_ATTR_WO(trigger_request);
609
548193cb 610#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
baaabecf
KC
611extern struct list_head efi_embedded_fw_list;
612extern bool efi_embedded_fw_checked;
613
548193cb
HG
614static ssize_t trigger_request_platform_store(struct device *dev,
615 struct device_attribute *attr,
616 const char *buf, size_t count)
617{
618 static const u8 test_data[] = {
619 0x55, 0xaa, 0x55, 0xaa, 0x01, 0x02, 0x03, 0x04,
620 0x55, 0xaa, 0x55, 0xaa, 0x05, 0x06, 0x07, 0x08,
621 0x55, 0xaa, 0x55, 0xaa, 0x10, 0x20, 0x30, 0x40,
622 0x55, 0xaa, 0x55, 0xaa, 0x50, 0x60, 0x70, 0x80
623 };
624 struct efi_embedded_fw efi_embedded_fw;
625 const struct firmware *firmware = NULL;
baaabecf 626 bool saved_efi_embedded_fw_checked;
548193cb
HG
627 char *name;
628 int rc;
629
630 name = kstrndup(buf, count, GFP_KERNEL);
631 if (!name)
632 return -ENOSPC;
633
634 pr_info("inserting test platform fw '%s'\n", name);
635 efi_embedded_fw.name = name;
636 efi_embedded_fw.data = (void *)test_data;
637 efi_embedded_fw.length = sizeof(test_data);
638 list_add(&efi_embedded_fw.list, &efi_embedded_fw_list);
baaabecf
KC
639 saved_efi_embedded_fw_checked = efi_embedded_fw_checked;
640 efi_embedded_fw_checked = true;
548193cb
HG
641
642 pr_info("loading '%s'\n", name);
643 rc = firmware_request_platform(&firmware, name, dev);
644 if (rc) {
645 pr_info("load of '%s' failed: %d\n", name, rc);
646 goto out;
647 }
648 if (firmware->size != sizeof(test_data) ||
649 memcmp(firmware->data, test_data, sizeof(test_data)) != 0) {
650 pr_info("firmware contents mismatch for '%s'\n", name);
651 rc = -EINVAL;
652 goto out;
653 }
654 pr_info("loaded: %zu\n", firmware->size);
655 rc = count;
656
657out:
baaabecf 658 efi_embedded_fw_checked = saved_efi_embedded_fw_checked;
548193cb
HG
659 release_firmware(firmware);
660 list_del(&efi_embedded_fw.list);
661 kfree(name);
662
663 return rc;
664}
665static DEVICE_ATTR_WO(trigger_request_platform);
666#endif
667
eb910947
BN
668static DECLARE_COMPLETION(async_fw_done);
669
670static void trigger_async_request_cb(const struct firmware *fw, void *context)
671{
672 test_firmware = fw;
673 complete(&async_fw_done);
674}
675
676static ssize_t trigger_async_request_store(struct device *dev,
677 struct device_attribute *attr,
678 const char *buf, size_t count)
679{
680 int rc;
681 char *name;
682
683 name = kstrndup(buf, count, GFP_KERNEL);
684 if (!name)
685 return -ENOSPC;
686
687 pr_info("loading '%s'\n", name);
688
689 mutex_lock(&test_fw_mutex);
690 release_firmware(test_firmware);
691 test_firmware = NULL;
692 rc = request_firmware_nowait(THIS_MODULE, 1, name, dev, GFP_KERNEL,
693 NULL, trigger_async_request_cb);
694 if (rc) {
695 pr_info("async load of '%s' failed: %d\n", name, rc);
696 kfree(name);
697 goto out;
698 }
699 /* Free 'name' ASAP, to test for race conditions */
700 kfree(name);
701
702 wait_for_completion(&async_fw_done);
703
704 if (test_firmware) {
705 pr_info("loaded: %zu\n", test_firmware->size);
706 rc = count;
707 } else {
708 pr_err("failed to async load firmware\n");
7feebfa4 709 rc = -ENOMEM;
eb910947
BN
710 }
711
712out:
713 mutex_unlock(&test_fw_mutex);
714
715 return rc;
716}
717static DEVICE_ATTR_WO(trigger_async_request);
718
061132d2
LR
719static ssize_t trigger_custom_fallback_store(struct device *dev,
720 struct device_attribute *attr,
721 const char *buf, size_t count)
722{
723 int rc;
724 char *name;
725
726 name = kstrndup(buf, count, GFP_KERNEL);
727 if (!name)
728 return -ENOSPC;
729
730 pr_info("loading '%s' using custom fallback mechanism\n", name);
731
732 mutex_lock(&test_fw_mutex);
733 release_firmware(test_firmware);
734 test_firmware = NULL;
735 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, name,
736 dev, GFP_KERNEL, NULL,
737 trigger_async_request_cb);
738 if (rc) {
739 pr_info("async load of '%s' failed: %d\n", name, rc);
740 kfree(name);
741 goto out;
742 }
743 /* Free 'name' ASAP, to test for race conditions */
744 kfree(name);
745
746 wait_for_completion(&async_fw_done);
747
748 if (test_firmware) {
749 pr_info("loaded: %zu\n", test_firmware->size);
750 rc = count;
751 } else {
752 pr_err("failed to async load firmware\n");
753 rc = -ENODEV;
754 }
755
756out:
757 mutex_unlock(&test_fw_mutex);
758
759 return rc;
760}
761static DEVICE_ATTR_WO(trigger_custom_fallback);
762
c92316bf
LR
763static int test_fw_run_batch_request(void *data)
764{
765 struct test_batched_req *req = data;
766
767 if (!req) {
768 test_fw_config->test_result = -EINVAL;
769 return -EINVAL;
770 }
771
7feebfa4
SB
772 if (test_fw_config->into_buf) {
773 void *test_buf;
774
775 test_buf = kzalloc(TEST_FIRMWARE_BUF_SIZE, GFP_KERNEL);
776 if (!test_buf)
777 return -ENOSPC;
778
5d90e05c
SB
779 if (test_fw_config->partial)
780 req->rc = request_partial_firmware_into_buf
781 (&req->fw,
782 req->name,
783 req->dev,
784 test_buf,
785 test_fw_config->buf_size,
786 test_fw_config->file_offset);
787 else
788 req->rc = request_firmware_into_buf
789 (&req->fw,
790 req->name,
791 req->dev,
792 test_buf,
793 test_fw_config->buf_size);
7feebfa4
SB
794 if (!req->fw)
795 kfree(test_buf);
796 } else {
797 req->rc = test_fw_config->req_firmware(&req->fw,
798 req->name,
799 req->dev);
800 }
801
c92316bf
LR
802 if (req->rc) {
803 pr_info("#%u: batched sync load failed: %d\n",
804 req->idx, req->rc);
805 if (!test_fw_config->test_result)
806 test_fw_config->test_result = req->rc;
807 } else if (req->fw) {
808 req->sent = true;
809 pr_info("#%u: batched sync loaded %zu\n",
810 req->idx, req->fw->size);
811 }
812 complete(&req->completion);
813
814 req->task = NULL;
815
816 return 0;
817}
818
819/*
820 * We use a kthread as otherwise the kernel serializes all our sync requests
821 * and we would not be able to mimic batched requests on a sync call. Batched
822 * requests on a sync call can for instance happen on a device driver when
823 * multiple cards are used and firmware loading happens outside of probe.
824 */
825static ssize_t trigger_batched_requests_store(struct device *dev,
826 struct device_attribute *attr,
827 const char *buf, size_t count)
828{
829 struct test_batched_req *req;
830 int rc;
831 u8 i;
832
833 mutex_lock(&test_fw_mutex);
834
fad953ce
KC
835 test_fw_config->reqs =
836 vzalloc(array3_size(sizeof(struct test_batched_req),
837 test_fw_config->num_requests, 2));
c92316bf
LR
838 if (!test_fw_config->reqs) {
839 rc = -ENOMEM;
840 goto out_unlock;
841 }
842
843 pr_info("batched sync firmware loading '%s' %u times\n",
844 test_fw_config->name, test_fw_config->num_requests);
845
846 for (i = 0; i < test_fw_config->num_requests; i++) {
847 req = &test_fw_config->reqs[i];
c92316bf
LR
848 req->fw = NULL;
849 req->idx = i;
850 req->name = test_fw_config->name;
851 req->dev = dev;
852 init_completion(&req->completion);
853 req->task = kthread_run(test_fw_run_batch_request, req,
854 "%s-%u", KBUILD_MODNAME, req->idx);
855 if (!req->task || IS_ERR(req->task)) {
856 pr_err("Setting up thread %u failed\n", req->idx);
857 req->task = NULL;
858 rc = -ENOMEM;
859 goto out_bail;
860 }
861 }
862
863 rc = count;
864
865 /*
866 * We require an explicit release to enable more time and delay of
867 * calling release_firmware() to improve our chances of forcing a
868 * batched request. If we instead called release_firmware() right away
869 * then we might miss on an opportunity of having a successful firmware
870 * request pass on the opportunity to be come a batched request.
871 */
872
873out_bail:
874 for (i = 0; i < test_fw_config->num_requests; i++) {
875 req = &test_fw_config->reqs[i];
876 if (req->task || req->sent)
877 wait_for_completion(&req->completion);
878 }
879
880 /* Override any worker error if we had a general setup error */
881 if (rc < 0)
882 test_fw_config->test_result = rc;
883
884out_unlock:
885 mutex_unlock(&test_fw_mutex);
886
887 return rc;
888}
889static DEVICE_ATTR_WO(trigger_batched_requests);
890
891/*
892 * We wait for each callback to return with the lock held, no need to lock here
893 */
894static void trigger_batched_cb(const struct firmware *fw, void *context)
895{
896 struct test_batched_req *req = context;
897
898 if (!req) {
899 test_fw_config->test_result = -EINVAL;
900 return;
901 }
902
903 /* forces *some* batched requests to queue up */
904 if (!req->idx)
905 ssleep(2);
906
907 req->fw = fw;
908
909 /*
910 * Unfortunately the firmware API gives us nothing other than a null FW
911 * if the firmware was not found on async requests. Best we can do is
912 * just assume -ENOENT. A better API would pass the actual return
913 * value to the callback.
914 */
915 if (!fw && !test_fw_config->test_result)
916 test_fw_config->test_result = -ENOENT;
917
918 complete(&req->completion);
919}
920
921static
922ssize_t trigger_batched_requests_async_store(struct device *dev,
923 struct device_attribute *attr,
924 const char *buf, size_t count)
925{
926 struct test_batched_req *req;
927 bool send_uevent;
928 int rc;
929 u8 i;
930
931 mutex_lock(&test_fw_mutex);
932
fad953ce
KC
933 test_fw_config->reqs =
934 vzalloc(array3_size(sizeof(struct test_batched_req),
935 test_fw_config->num_requests, 2));
c92316bf
LR
936 if (!test_fw_config->reqs) {
937 rc = -ENOMEM;
938 goto out;
939 }
940
941 pr_info("batched loading '%s' custom fallback mechanism %u times\n",
942 test_fw_config->name, test_fw_config->num_requests);
943
944 send_uevent = test_fw_config->send_uevent ? FW_ACTION_HOTPLUG :
945 FW_ACTION_NOHOTPLUG;
946
947 for (i = 0; i < test_fw_config->num_requests; i++) {
948 req = &test_fw_config->reqs[i];
c92316bf
LR
949 req->name = test_fw_config->name;
950 req->fw = NULL;
951 req->idx = i;
952 init_completion(&req->completion);
953 rc = request_firmware_nowait(THIS_MODULE, send_uevent,
954 req->name,
955 dev, GFP_KERNEL, req,
956 trigger_batched_cb);
957 if (rc) {
958 pr_info("#%u: batched async load failed setup: %d\n",
959 i, rc);
960 req->rc = rc;
961 goto out_bail;
962 } else
963 req->sent = true;
964 }
965
966 rc = count;
967
968out_bail:
969
970 /*
971 * We require an explicit release to enable more time and delay of
972 * calling release_firmware() to improve our chances of forcing a
973 * batched request. If we instead called release_firmware() right away
974 * then we might miss on an opportunity of having a successful firmware
975 * request pass on the opportunity to be come a batched request.
976 */
977
978 for (i = 0; i < test_fw_config->num_requests; i++) {
979 req = &test_fw_config->reqs[i];
980 if (req->sent)
981 wait_for_completion(&req->completion);
982 }
983
984 /* Override any worker error if we had a general setup error */
985 if (rc < 0)
986 test_fw_config->test_result = rc;
987
988out:
989 mutex_unlock(&test_fw_mutex);
990
991 return rc;
992}
993static DEVICE_ATTR_WO(trigger_batched_requests_async);
994
995static ssize_t test_result_show(struct device *dev,
996 struct device_attribute *attr,
997 char *buf)
998{
999 return test_dev_config_show_int(buf, test_fw_config->test_result);
1000}
1001static DEVICE_ATTR_RO(test_result);
1002
1003static ssize_t release_all_firmware_store(struct device *dev,
1004 struct device_attribute *attr,
1005 const char *buf, size_t count)
1006{
1007 test_release_all_firmware();
1008 return count;
1009}
1010static DEVICE_ATTR_WO(release_all_firmware);
1011
1012static ssize_t read_firmware_show(struct device *dev,
1013 struct device_attribute *attr,
1014 char *buf)
1015{
1016 struct test_batched_req *req;
1017 u8 idx;
1018 ssize_t rc = 0;
1019
1020 mutex_lock(&test_fw_mutex);
1021
1022 idx = test_fw_config->read_fw_idx;
1023 if (idx >= test_fw_config->num_requests) {
1024 rc = -ERANGE;
1025 goto out;
1026 }
1027
1028 if (!test_fw_config->reqs) {
1029 rc = -EINVAL;
1030 goto out;
1031 }
1032
1033 req = &test_fw_config->reqs[idx];
1034 if (!req->fw) {
1035 pr_err("#%u: failed to async load firmware\n", idx);
1036 rc = -ENOENT;
1037 goto out;
1038 }
1039
1040 pr_info("#%u: loaded %zu\n", idx, req->fw->size);
1041
1042 if (req->fw->size > PAGE_SIZE) {
1043 pr_err("Testing interface must use PAGE_SIZE firmware for now\n");
1044 rc = -EINVAL;
8bb0a886 1045 goto out;
c92316bf
LR
1046 }
1047 memcpy(buf, req->fw->data, req->fw->size);
1048
1049 rc = req->fw->size;
1050out:
1051 mutex_unlock(&test_fw_mutex);
1052
1053 return rc;
1054}
1055static DEVICE_ATTR_RO(read_firmware);
1056
083a93b0
LR
1057#define TEST_FW_DEV_ATTR(name) &dev_attr_##name.attr
1058
1059static struct attribute *test_dev_attrs[] = {
c92316bf
LR
1060 TEST_FW_DEV_ATTR(reset),
1061
1062 TEST_FW_DEV_ATTR(config),
1063 TEST_FW_DEV_ATTR(config_name),
1064 TEST_FW_DEV_ATTR(config_num_requests),
7feebfa4 1065 TEST_FW_DEV_ATTR(config_into_buf),
5d90e05c
SB
1066 TEST_FW_DEV_ATTR(config_buf_size),
1067 TEST_FW_DEV_ATTR(config_file_offset),
1068 TEST_FW_DEV_ATTR(config_partial),
c92316bf
LR
1069 TEST_FW_DEV_ATTR(config_sync_direct),
1070 TEST_FW_DEV_ATTR(config_send_uevent),
1071 TEST_FW_DEV_ATTR(config_read_fw_idx),
1072
1073 /* These don't use the config at all - they could be ported! */
083a93b0
LR
1074 TEST_FW_DEV_ATTR(trigger_request),
1075 TEST_FW_DEV_ATTR(trigger_async_request),
061132d2 1076 TEST_FW_DEV_ATTR(trigger_custom_fallback),
548193cb
HG
1077#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
1078 TEST_FW_DEV_ATTR(trigger_request_platform),
1079#endif
c92316bf
LR
1080
1081 /* These use the config and can use the test_result */
1082 TEST_FW_DEV_ATTR(trigger_batched_requests),
1083 TEST_FW_DEV_ATTR(trigger_batched_requests_async),
1084
1085 TEST_FW_DEV_ATTR(release_all_firmware),
1086 TEST_FW_DEV_ATTR(test_result),
1087 TEST_FW_DEV_ATTR(read_firmware),
083a93b0
LR
1088 NULL,
1089};
1090
1091ATTRIBUTE_GROUPS(test_dev);
1092
67fd553c
LR
1093static struct miscdevice test_fw_misc_device = {
1094 .minor = MISC_DYNAMIC_MINOR,
1095 .name = "test_firmware",
1096 .fops = &test_fw_fops,
083a93b0 1097 .groups = test_dev_groups,
67fd553c
LR
1098};
1099
0a8adf58
KC
1100static int __init test_firmware_init(void)
1101{
1102 int rc;
1103
c92316bf
LR
1104 test_fw_config = kzalloc(sizeof(struct test_config), GFP_KERNEL);
1105 if (!test_fw_config)
1106 return -ENOMEM;
1107
1108 rc = __test_firmware_config_init();
d4fddac5
WW
1109 if (rc) {
1110 kfree(test_fw_config);
1111 pr_err("could not init firmware test config: %d\n", rc);
c92316bf 1112 return rc;
d4fddac5 1113 }
c92316bf 1114
0a8adf58
KC
1115 rc = misc_register(&test_fw_misc_device);
1116 if (rc) {
c92316bf 1117 kfree(test_fw_config);
0a8adf58
KC
1118 pr_err("could not register misc device: %d\n", rc);
1119 return rc;
1120 }
eb910947 1121
0a8adf58
KC
1122 pr_warn("interface ready\n");
1123
1124 return 0;
0a8adf58
KC
1125}
1126
1127module_init(test_firmware_init);
1128
1129static void __exit test_firmware_exit(void)
1130{
c92316bf 1131 mutex_lock(&test_fw_mutex);
0a8adf58 1132 release_firmware(test_firmware);
0a8adf58 1133 misc_deregister(&test_fw_misc_device);
c92316bf
LR
1134 __test_firmware_config_free();
1135 kfree(test_fw_config);
1136 mutex_unlock(&test_fw_mutex);
1137
0a8adf58
KC
1138 pr_warn("removed interface\n");
1139}
1140
1141module_exit(test_firmware_exit);
1142
1143MODULE_AUTHOR("Kees Cook <keescook@chromium.org>");
1144MODULE_LICENSE("GPL");