87044d52322aa2ff9fd8d5654185585b9a1d9d3c
[releases.git] / sysfs_upload.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/firmware.h>
4 #include <linux/module.h>
5 #include <linux/slab.h>
6
7 #include "sysfs_upload.h"
8
9 /*
10  * Support for user-space to initiate a firmware upload to a device.
11  */
12
13 static const char * const fw_upload_prog_str[] = {
14         [FW_UPLOAD_PROG_IDLE]         = "idle",
15         [FW_UPLOAD_PROG_RECEIVING]    = "receiving",
16         [FW_UPLOAD_PROG_PREPARING]    = "preparing",
17         [FW_UPLOAD_PROG_TRANSFERRING] = "transferring",
18         [FW_UPLOAD_PROG_PROGRAMMING]  = "programming"
19 };
20
21 static const char * const fw_upload_err_str[] = {
22         [FW_UPLOAD_ERR_NONE]         = "none",
23         [FW_UPLOAD_ERR_HW_ERROR]     = "hw-error",
24         [FW_UPLOAD_ERR_TIMEOUT]      = "timeout",
25         [FW_UPLOAD_ERR_CANCELED]     = "user-abort",
26         [FW_UPLOAD_ERR_BUSY]         = "device-busy",
27         [FW_UPLOAD_ERR_INVALID_SIZE] = "invalid-file-size",
28         [FW_UPLOAD_ERR_RW_ERROR]     = "read-write-error",
29         [FW_UPLOAD_ERR_WEAROUT]      = "flash-wearout",
30 };
31
32 static const char *fw_upload_progress(struct device *dev,
33                                       enum fw_upload_prog prog)
34 {
35         const char *status = "unknown-status";
36
37         if (prog < FW_UPLOAD_PROG_MAX)
38                 status = fw_upload_prog_str[prog];
39         else
40                 dev_err(dev, "Invalid status during secure update: %d\n", prog);
41
42         return status;
43 }
44
45 static const char *fw_upload_error(struct device *dev,
46                                    enum fw_upload_err err_code)
47 {
48         const char *error = "unknown-error";
49
50         if (err_code < FW_UPLOAD_ERR_MAX)
51                 error = fw_upload_err_str[err_code];
52         else
53                 dev_err(dev, "Invalid error code during secure update: %d\n",
54                         err_code);
55
56         return error;
57 }
58
59 static ssize_t
60 status_show(struct device *dev, struct device_attribute *attr, char *buf)
61 {
62         struct fw_upload_priv *fwlp = to_fw_sysfs(dev)->fw_upload_priv;
63
64         return sysfs_emit(buf, "%s\n", fw_upload_progress(dev, fwlp->progress));
65 }
66 DEVICE_ATTR_RO(status);
67
68 static ssize_t
69 error_show(struct device *dev, struct device_attribute *attr, char *buf)
70 {
71         struct fw_upload_priv *fwlp = to_fw_sysfs(dev)->fw_upload_priv;
72         int ret;
73
74         mutex_lock(&fwlp->lock);
75
76         if (fwlp->progress != FW_UPLOAD_PROG_IDLE)
77                 ret = -EBUSY;
78         else if (!fwlp->err_code)
79                 ret = 0;
80         else
81                 ret = sysfs_emit(buf, "%s:%s\n",
82                                  fw_upload_progress(dev, fwlp->err_progress),
83                                  fw_upload_error(dev, fwlp->err_code));
84
85         mutex_unlock(&fwlp->lock);
86
87         return ret;
88 }
89 DEVICE_ATTR_RO(error);
90
91 static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
92                             const char *buf, size_t count)
93 {
94         struct fw_upload_priv *fwlp = to_fw_sysfs(dev)->fw_upload_priv;
95         int ret = count;
96         bool cancel;
97
98         if (kstrtobool(buf, &cancel) || !cancel)
99                 return -EINVAL;
100
101         mutex_lock(&fwlp->lock);
102         if (fwlp->progress == FW_UPLOAD_PROG_IDLE)
103                 ret = -ENODEV;
104
105         fwlp->ops->cancel(fwlp->fw_upload);
106         mutex_unlock(&fwlp->lock);
107
108         return ret;
109 }
110 DEVICE_ATTR_WO(cancel);
111
112 static ssize_t remaining_size_show(struct device *dev,
113                                    struct device_attribute *attr, char *buf)
114 {
115         struct fw_upload_priv *fwlp = to_fw_sysfs(dev)->fw_upload_priv;
116
117         return sysfs_emit(buf, "%u\n", fwlp->remaining_size);
118 }
119 DEVICE_ATTR_RO(remaining_size);
120
121 umode_t
122 fw_upload_is_visible(struct kobject *kobj, struct attribute *attr, int n)
123 {
124         static struct fw_sysfs *fw_sysfs;
125
126         fw_sysfs = to_fw_sysfs(kobj_to_dev(kobj));
127
128         if (fw_sysfs->fw_upload_priv || attr == &dev_attr_loading.attr)
129                 return attr->mode;
130
131         return 0;
132 }
133
134 static void fw_upload_update_progress(struct fw_upload_priv *fwlp,
135                                       enum fw_upload_prog new_progress)
136 {
137         mutex_lock(&fwlp->lock);
138         fwlp->progress = new_progress;
139         mutex_unlock(&fwlp->lock);
140 }
141
142 static void fw_upload_set_error(struct fw_upload_priv *fwlp,
143                                 enum fw_upload_err err_code)
144 {
145         mutex_lock(&fwlp->lock);
146         fwlp->err_progress = fwlp->progress;
147         fwlp->err_code = err_code;
148         mutex_unlock(&fwlp->lock);
149 }
150
151 static void fw_upload_prog_complete(struct fw_upload_priv *fwlp)
152 {
153         mutex_lock(&fwlp->lock);
154         fwlp->progress = FW_UPLOAD_PROG_IDLE;
155         mutex_unlock(&fwlp->lock);
156 }
157
158 static void fw_upload_main(struct work_struct *work)
159 {
160         struct fw_upload_priv *fwlp;
161         struct fw_sysfs *fw_sysfs;
162         u32 written = 0, offset = 0;
163         enum fw_upload_err ret;
164         struct device *fw_dev;
165         struct fw_upload *fwl;
166
167         fwlp = container_of(work, struct fw_upload_priv, work);
168         fwl = fwlp->fw_upload;
169         fw_sysfs = (struct fw_sysfs *)fwl->priv;
170         fw_dev = &fw_sysfs->dev;
171
172         fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_PREPARING);
173         ret = fwlp->ops->prepare(fwl, fwlp->data, fwlp->remaining_size);
174         if (ret != FW_UPLOAD_ERR_NONE) {
175                 fw_upload_set_error(fwlp, ret);
176                 goto putdev_exit;
177         }
178
179         fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_TRANSFERRING);
180         while (fwlp->remaining_size) {
181                 ret = fwlp->ops->write(fwl, fwlp->data, offset,
182                                         fwlp->remaining_size, &written);
183                 if (ret != FW_UPLOAD_ERR_NONE || !written) {
184                         if (ret == FW_UPLOAD_ERR_NONE) {
185                                 dev_warn(fw_dev, "write-op wrote zero data\n");
186                                 ret = FW_UPLOAD_ERR_RW_ERROR;
187                         }
188                         fw_upload_set_error(fwlp, ret);
189                         goto done;
190                 }
191
192                 fwlp->remaining_size -= written;
193                 offset += written;
194         }
195
196         fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_PROGRAMMING);
197         ret = fwlp->ops->poll_complete(fwl);
198         if (ret != FW_UPLOAD_ERR_NONE)
199                 fw_upload_set_error(fwlp, ret);
200
201 done:
202         if (fwlp->ops->cleanup)
203                 fwlp->ops->cleanup(fwl);
204
205 putdev_exit:
206         put_device(fw_dev->parent);
207
208         /*
209          * Note: fwlp->remaining_size is left unmodified here to provide
210          * additional information on errors. It will be reinitialized when
211          * the next firmeware upload begins.
212          */
213         mutex_lock(&fw_lock);
214         fw_free_paged_buf(fw_sysfs->fw_priv);
215         fw_state_init(fw_sysfs->fw_priv);
216         mutex_unlock(&fw_lock);
217         fwlp->data = NULL;
218         fw_upload_prog_complete(fwlp);
219 }
220
221 /*
222  * Start a worker thread to upload data to the parent driver.
223  * Must be called with fw_lock held.
224  */
225 int fw_upload_start(struct fw_sysfs *fw_sysfs)
226 {
227         struct fw_priv *fw_priv = fw_sysfs->fw_priv;
228         struct device *fw_dev = &fw_sysfs->dev;
229         struct fw_upload_priv *fwlp;
230
231         if (!fw_sysfs->fw_upload_priv)
232                 return 0;
233
234         if (!fw_priv->size) {
235                 fw_free_paged_buf(fw_priv);
236                 fw_state_init(fw_sysfs->fw_priv);
237                 return 0;
238         }
239
240         fwlp = fw_sysfs->fw_upload_priv;
241         mutex_lock(&fwlp->lock);
242
243         /* Do not interfere with an on-going fw_upload */
244         if (fwlp->progress != FW_UPLOAD_PROG_IDLE) {
245                 mutex_unlock(&fwlp->lock);
246                 return -EBUSY;
247         }
248
249         get_device(fw_dev->parent); /* released in fw_upload_main */
250
251         fwlp->progress = FW_UPLOAD_PROG_RECEIVING;
252         fwlp->err_code = 0;
253         fwlp->remaining_size = fw_priv->size;
254         fwlp->data = fw_priv->data;
255
256         pr_debug("%s: fw-%s fw_priv=%p data=%p size=%u\n",
257                  __func__, fw_priv->fw_name,
258                  fw_priv, fw_priv->data,
259                  (unsigned int)fw_priv->size);
260
261         queue_work(system_long_wq, &fwlp->work);
262         mutex_unlock(&fwlp->lock);
263
264         return 0;
265 }
266
267 /**
268  * firmware_upload_register() - register for the firmware upload sysfs API
269  * @module: kernel module of this device
270  * @parent: parent device instantiating firmware upload
271  * @name: firmware name to be associated with this device
272  * @ops: pointer to structure of firmware upload ops
273  * @dd_handle: pointer to parent driver private data
274  *
275  *      @name must be unique among all users of firmware upload. The firmware
276  *      sysfs files for this device will be found at /sys/class/firmware/@name.
277  *
278  *      Return: struct fw_upload pointer or ERR_PTR()
279  *
280  **/
281 struct fw_upload *
282 firmware_upload_register(struct module *module, struct device *parent,
283                          const char *name, const struct fw_upload_ops *ops,
284                          void *dd_handle)
285 {
286         u32 opt_flags = FW_OPT_NOCACHE;
287         struct fw_upload *fw_upload;
288         struct fw_upload_priv *fw_upload_priv;
289         struct fw_sysfs *fw_sysfs;
290         struct fw_priv *fw_priv;
291         struct device *fw_dev;
292         int ret;
293
294         if (!name || name[0] == '\0')
295                 return ERR_PTR(-EINVAL);
296
297         if (!ops || !ops->cancel || !ops->prepare ||
298             !ops->write || !ops->poll_complete) {
299                 dev_err(parent, "Attempt to register without all required ops\n");
300                 return ERR_PTR(-EINVAL);
301         }
302
303         if (!try_module_get(module))
304                 return ERR_PTR(-EFAULT);
305
306         fw_upload = kzalloc(sizeof(*fw_upload), GFP_KERNEL);
307         if (!fw_upload) {
308                 ret = -ENOMEM;
309                 goto exit_module_put;
310         }
311
312         fw_upload_priv = kzalloc(sizeof(*fw_upload_priv), GFP_KERNEL);
313         if (!fw_upload_priv) {
314                 ret = -ENOMEM;
315                 goto free_fw_upload;
316         }
317
318         fw_upload_priv->fw_upload = fw_upload;
319         fw_upload_priv->ops = ops;
320         mutex_init(&fw_upload_priv->lock);
321         fw_upload_priv->module = module;
322         fw_upload_priv->name = name;
323         fw_upload_priv->err_code = 0;
324         fw_upload_priv->progress = FW_UPLOAD_PROG_IDLE;
325         INIT_WORK(&fw_upload_priv->work, fw_upload_main);
326         fw_upload->dd_handle = dd_handle;
327
328         fw_sysfs = fw_create_instance(NULL, name, parent, opt_flags);
329         if (IS_ERR(fw_sysfs)) {
330                 ret = PTR_ERR(fw_sysfs);
331                 goto free_fw_upload_priv;
332         }
333         fw_upload->priv = fw_sysfs;
334         fw_sysfs->fw_upload_priv = fw_upload_priv;
335         fw_dev = &fw_sysfs->dev;
336
337         ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv,  NULL, 0, 0,
338                                    FW_OPT_NOCACHE);
339         if (ret != 0) {
340                 if (ret > 0)
341                         ret = -EINVAL;
342                 goto free_fw_sysfs;
343         }
344         fw_priv->is_paged_buf = true;
345         fw_sysfs->fw_priv = fw_priv;
346
347         ret = device_add(fw_dev);
348         if (ret) {
349                 dev_err(fw_dev, "%s: device_register failed\n", __func__);
350                 put_device(fw_dev);
351                 goto exit_module_put;
352         }
353
354         return fw_upload;
355
356 free_fw_sysfs:
357         kfree(fw_sysfs);
358
359 free_fw_upload_priv:
360         kfree(fw_upload_priv);
361
362 free_fw_upload:
363         kfree(fw_upload);
364
365 exit_module_put:
366         module_put(module);
367
368         return ERR_PTR(ret);
369 }
370 EXPORT_SYMBOL_GPL(firmware_upload_register);
371
372 /**
373  * firmware_upload_unregister() - Unregister firmware upload interface
374  * @fw_upload: pointer to struct fw_upload
375  **/
376 void firmware_upload_unregister(struct fw_upload *fw_upload)
377 {
378         struct fw_sysfs *fw_sysfs = fw_upload->priv;
379         struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv;
380
381         mutex_lock(&fw_upload_priv->lock);
382         if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) {
383                 mutex_unlock(&fw_upload_priv->lock);
384                 goto unregister;
385         }
386
387         fw_upload_priv->ops->cancel(fw_upload);
388         mutex_unlock(&fw_upload_priv->lock);
389
390         /* Ensure lower-level device-driver is finished */
391         flush_work(&fw_upload_priv->work);
392
393 unregister:
394         device_unregister(&fw_sysfs->dev);
395         module_put(fw_upload_priv->module);
396 }
397 EXPORT_SYMBOL_GPL(firmware_upload_unregister);