Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #include <linux/vmalloc.h> |
2 | #include <linux/module.h> | |
3 | #include <linux/fs.h> | |
4 | #include <linux/mm.h> | |
5 | #include <linux/slab.h> | |
6 | #include <asm/uaccess.h> | |
7 | ||
8 | static int do_mod_firmware_load(const char *fn, char **fp) | |
9 | { | |
10 | struct file* filp; | |
11 | long l; | |
12 | char *dp; | |
13 | loff_t pos; | |
14 | ||
15 | filp = filp_open(fn, 0, 0); | |
16 | if (IS_ERR(filp)) | |
17 | { | |
18 | printk(KERN_INFO "Unable to load '%s'.\n", fn); | |
19 | return 0; | |
20 | } | |
21 | l = filp->f_dentry->d_inode->i_size; | |
22 | if (l <= 0 || l > 131072) | |
23 | { | |
24 | printk(KERN_INFO "Invalid firmware '%s'\n", fn); | |
25 | filp_close(filp, current->files); | |
26 | return 0; | |
27 | } | |
28 | dp = vmalloc(l); | |
29 | if (dp == NULL) | |
30 | { | |
31 | printk(KERN_INFO "Out of memory loading '%s'.\n", fn); | |
32 | filp_close(filp, current->files); | |
33 | return 0; | |
34 | } | |
35 | pos = 0; | |
36 | if (vfs_read(filp, dp, l, &pos) != l) | |
37 | { | |
38 | printk(KERN_INFO "Failed to read '%s'.\n", fn); | |
39 | vfree(dp); | |
40 | filp_close(filp, current->files); | |
41 | return 0; | |
42 | } | |
43 | filp_close(filp, current->files); | |
44 | *fp = dp; | |
45 | return (int) l; | |
46 | } | |
47 | ||
48 | /** | |
49 | * mod_firmware_load - load sound driver firmware | |
50 | * @fn: filename | |
51 | * @fp: return for the buffer. | |
52 | * | |
53 | * Load the firmware for a sound module (up to 128K) into a buffer. | |
54 | * The buffer is returned in *fp. It is allocated with vmalloc so is | |
55 | * virtually linear and not DMAable. The caller should free it with | |
56 | * vfree when finished. | |
57 | * | |
58 | * The length of the buffer is returned on a successful load, the | |
59 | * value zero on a failure. | |
60 | * | |
61 | * Caution: This API is not recommended. Firmware should be loaded via | |
62 | * an ioctl call and a setup application. This function may disappear | |
63 | * in future. | |
64 | */ | |
65 | ||
66 | int mod_firmware_load(const char *fn, char **fp) | |
67 | { | |
68 | int r; | |
69 | mm_segment_t fs = get_fs(); | |
70 | ||
71 | set_fs(get_ds()); | |
72 | r = do_mod_firmware_load(fn, fp); | |
73 | set_fs(fs); | |
74 | return r; | |
75 | } | |
76 |