1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <linux/array_size.h>
4 #include <linux/build_bug.h>
5 #include <linux/dev_printk.h>
6 #include <linux/err.h>
7 #include <linux/errno.h>
8 #include <linux/netlink.h>
9 #include <linux/slab.h>
10 #include <linux/string.h>
11
12 #include "core.h"
13 #include "flash.h"
14 #include "fw.h"
15
16 #define ZL3073X_FW_ERR_PFX "FW load failed: "
17 #define ZL3073X_FW_ERR_MSG(_extack, _msg, ...) \
18 NL_SET_ERR_MSG_FMT_MOD((_extack), ZL3073X_FW_ERR_PFX _msg, \
19 ## __VA_ARGS__)
20
21 enum zl3073x_flash_type {
22 ZL3073X_FLASH_TYPE_NONE = 0,
23 ZL3073X_FLASH_TYPE_SECTORS,
24 ZL3073X_FLASH_TYPE_PAGE,
25 ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
26 };
27
28 struct zl3073x_fw_component_info {
29 const char *name;
30 size_t max_size;
31 enum zl3073x_flash_type flash_type;
32 u32 load_addr;
33 u32 dest_page;
34 u32 copy_page;
35 };
36
37 static const struct zl3073x_fw_component_info component_info[] = {
38 [ZL_FW_COMPONENT_UTIL] = {
39 .name = "utility",
40 .max_size = 0x4000,
41 .load_addr = 0x20000000,
42 .flash_type = ZL3073X_FLASH_TYPE_NONE,
43 },
44 [ZL_FW_COMPONENT_FW1] = {
45 .name = "firmware1",
46 .max_size = 0x35000,
47 .load_addr = 0x20002000,
48 .flash_type = ZL3073X_FLASH_TYPE_SECTORS,
49 .dest_page = 0x020,
50 },
51 [ZL_FW_COMPONENT_FW2] = {
52 .name = "firmware2",
53 .max_size = 0x0040,
54 .load_addr = 0x20000000,
55 .flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
56 .dest_page = 0x3e0,
57 .copy_page = 0x000,
58 },
59 [ZL_FW_COMPONENT_FW3] = {
60 .name = "firmware3",
61 .max_size = 0x0248,
62 .load_addr = 0x20000400,
63 .flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
64 .dest_page = 0x3e4,
65 .copy_page = 0x004,
66 },
67 [ZL_FW_COMPONENT_CFG0] = {
68 .name = "config0",
69 .max_size = 0x1000,
70 .load_addr = 0x20000000,
71 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
72 .dest_page = 0x3d0,
73 },
74 [ZL_FW_COMPONENT_CFG1] = {
75 .name = "config1",
76 .max_size = 0x1000,
77 .load_addr = 0x20000000,
78 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
79 .dest_page = 0x3c0,
80 },
81 [ZL_FW_COMPONENT_CFG2] = {
82 .name = "config2",
83 .max_size = 0x1000,
84 .load_addr = 0x20000000,
85 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
86 .dest_page = 0x3b0,
87 },
88 [ZL_FW_COMPONENT_CFG3] = {
89 .name = "config3",
90 .max_size = 0x1000,
91 .load_addr = 0x20000000,
92 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
93 .dest_page = 0x3a0,
94 },
95 [ZL_FW_COMPONENT_CFG4] = {
96 .name = "config4",
97 .max_size = 0x1000,
98 .load_addr = 0x20000000,
99 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
100 .dest_page = 0x390,
101 },
102 [ZL_FW_COMPONENT_CFG5] = {
103 .name = "config5",
104 .max_size = 0x1000,
105 .load_addr = 0x20000000,
106 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
107 .dest_page = 0x380,
108 },
109 [ZL_FW_COMPONENT_CFG6] = {
110 .name = "config6",
111 .max_size = 0x1000,
112 .load_addr = 0x20000000,
113 .flash_type = ZL3073X_FLASH_TYPE_PAGE,
114 .dest_page = 0x370,
115 },
116 };
117
118 /* Sanity check */
119 static_assert(ARRAY_SIZE(component_info) == ZL_FW_NUM_COMPONENTS);
120
121 /**
122 * zl3073x_fw_component_alloc - Alloc structure to hold firmware component
123 * @size: size of buffer to store data
124 *
125 * Return: pointer to allocated component structure or NULL on error.
126 */
127 static struct zl3073x_fw_component *
zl3073x_fw_component_alloc(size_t size)128 zl3073x_fw_component_alloc(size_t size)
129 {
130 struct zl3073x_fw_component *comp;
131
132 comp = kzalloc(sizeof(*comp), GFP_KERNEL);
133 if (!comp)
134 return NULL;
135
136 comp->size = size;
137 comp->data = kzalloc(size, GFP_KERNEL);
138 if (!comp->data) {
139 kfree(comp);
140 return NULL;
141 }
142
143 return comp;
144 }
145
146 /**
147 * zl3073x_fw_component_free - Free allocated component structure
148 * @comp: pointer to allocated component
149 */
150 static void
zl3073x_fw_component_free(struct zl3073x_fw_component * comp)151 zl3073x_fw_component_free(struct zl3073x_fw_component *comp)
152 {
153 if (comp)
154 kfree(comp->data);
155
156 kfree(comp);
157 }
158
159 /**
160 * zl3073x_fw_component_id_get - Get ID for firmware component name
161 * @name: input firmware component name
162 *
163 * Return:
164 * - ZL3073X_FW_COMPONENT_* ID for known component name
165 * - ZL3073X_FW_COMPONENT_INVALID if the given name is unknown
166 */
167 static enum zl3073x_fw_component_id
zl3073x_fw_component_id_get(const char * name)168 zl3073x_fw_component_id_get(const char *name)
169 {
170 enum zl3073x_fw_component_id id;
171
172 for (id = 0; id < ZL_FW_NUM_COMPONENTS; id++)
173 if (!strcasecmp(name, component_info[id].name))
174 return id;
175
176 return ZL_FW_COMPONENT_INVALID;
177 }
178
179 /**
180 * zl3073x_fw_component_load - Load component from firmware source
181 * @zldev: zl3073x device structure
182 * @pcomp: pointer to loaded component
183 * @psrc: data pointer to load component from
184 * @psize: remaining bytes in buffer
185 * @extack: netlink extack pointer to report errors
186 *
187 * The function allocates single firmware component and loads the data from
188 * the buffer specified by @psrc and @psize. Pointer to allocated component
189 * is stored in output @pcomp. Source data pointer @psrc and remaining bytes
190 * @psize are updated accordingly.
191 *
192 * Return:
193 * * 1 when component was allocated and loaded
194 * * 0 when there is no component to load
195 * * <0 on error
196 */
197 static ssize_t
zl3073x_fw_component_load(struct zl3073x_dev * zldev,struct zl3073x_fw_component ** pcomp,const char ** psrc,size_t * psize,struct netlink_ext_ack * extack)198 zl3073x_fw_component_load(struct zl3073x_dev *zldev,
199 struct zl3073x_fw_component **pcomp,
200 const char **psrc, size_t *psize,
201 struct netlink_ext_ack *extack)
202 {
203 const struct zl3073x_fw_component_info *info;
204 struct zl3073x_fw_component *comp = NULL;
205 struct device *dev = zldev->dev;
206 enum zl3073x_fw_component_id id;
207 char buf[32], name[16];
208 u32 count, size, *dest;
209 int pos, rc;
210
211 /* Fetch image name and size from input */
212 strscpy(buf, *psrc, min(sizeof(buf), *psize));
213 rc = sscanf(buf, "%15s %u %n", name, &count, &pos);
214 if (!rc) {
215 /* No more data */
216 return 0;
217 } else if (rc == 1 || count > U32_MAX / sizeof(u32)) {
218 ZL3073X_FW_ERR_MSG(extack, "invalid component size");
219 return -EINVAL;
220 }
221 *psrc += pos;
222 *psize -= pos;
223
224 dev_dbg(dev, "Firmware component '%s' found\n", name);
225
226 id = zl3073x_fw_component_id_get(name);
227 if (id == ZL_FW_COMPONENT_INVALID) {
228 ZL3073X_FW_ERR_MSG(extack, "unknown component type '%s'", name);
229 return -EINVAL;
230 }
231
232 info = &component_info[id];
233 size = count * sizeof(u32); /* get size in bytes */
234
235 /* Check image size validity */
236 if (size > component_info[id].max_size) {
237 ZL3073X_FW_ERR_MSG(extack,
238 "[%s] component is too big (%u bytes)\n",
239 info->name, size);
240 return -EINVAL;
241 }
242
243 dev_dbg(dev, "Indicated component image size: %u bytes\n", size);
244
245 /* Alloc component */
246 comp = zl3073x_fw_component_alloc(size);
247 if (!comp) {
248 ZL3073X_FW_ERR_MSG(extack, "failed to alloc memory");
249 return -ENOMEM;
250 }
251 comp->id = id;
252
253 /* Load component data from firmware source */
254 for (dest = comp->data; count; count--, dest++) {
255 strscpy(buf, *psrc, min(sizeof(buf), *psize));
256 rc = sscanf(buf, "%x %n", dest, &pos);
257 if (!rc)
258 goto err_data;
259
260 *psrc += pos;
261 *psize -= pos;
262 }
263
264 *pcomp = comp;
265
266 return 1;
267
268 err_data:
269 ZL3073X_FW_ERR_MSG(extack, "[%s] invalid or missing data", info->name);
270
271 zl3073x_fw_component_free(comp);
272
273 return -ENODATA;
274 }
275
276 /**
277 * zl3073x_fw_free - Free allocated firmware
278 * @fw: firmware pointer
279 *
280 * The function frees existing firmware allocated by @zl3073x_fw_load.
281 */
zl3073x_fw_free(struct zl3073x_fw * fw)282 void zl3073x_fw_free(struct zl3073x_fw *fw)
283 {
284 size_t i;
285
286 if (!fw)
287 return;
288
289 for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++)
290 zl3073x_fw_component_free(fw->component[i]);
291
292 kfree(fw);
293 }
294
295 /**
296 * zl3073x_fw_load - Load all components from source
297 * @zldev: zl3073x device structure
298 * @data: source buffer pointer
299 * @size: size of source buffer
300 * @extack: netlink extack pointer to report errors
301 *
302 * The functions allocate firmware structure and loads all components from
303 * the given buffer specified by @data and @size.
304 *
305 * Return: pointer to firmware on success, error pointer on error
306 */
zl3073x_fw_load(struct zl3073x_dev * zldev,const char * data,size_t size,struct netlink_ext_ack * extack)307 struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data,
308 size_t size, struct netlink_ext_ack *extack)
309 {
310 struct zl3073x_fw_component *comp;
311 enum zl3073x_fw_component_id id;
312 struct zl3073x_fw *fw;
313 ssize_t rc;
314
315 /* Allocate firmware structure */
316 fw = kzalloc(sizeof(*fw), GFP_KERNEL);
317 if (!fw)
318 return ERR_PTR(-ENOMEM);
319
320 do {
321 /* Load single component */
322 rc = zl3073x_fw_component_load(zldev, &comp, &data, &size,
323 extack);
324 if (rc <= 0)
325 /* Everything was read or error occurred */
326 break;
327
328 id = comp->id;
329
330 /* Report error if the given component is present twice
331 * or more.
332 */
333 if (fw->component[id]) {
334 ZL3073X_FW_ERR_MSG(extack,
335 "duplicate component '%s' detected",
336 component_info[id].name);
337 zl3073x_fw_component_free(comp);
338 rc = -EINVAL;
339 break;
340 }
341
342 fw->component[id] = comp;
343 } while (true);
344
345 if (rc) {
346 /* Free allocated firmware in case of error */
347 zl3073x_fw_free(fw);
348 return ERR_PTR(rc);
349 }
350
351 return fw;
352 }
353
354 /**
355 * zl3073x_flash_bundle_flash - Flash all components
356 * @zldev: zl3073x device structure
357 * @components: pointer to components array
358 * @extack: netlink extack pointer to report errors
359 *
360 * Returns 0 in case of success or negative number otherwise.
361 */
362 static int
zl3073x_fw_component_flash(struct zl3073x_dev * zldev,struct zl3073x_fw_component * comp,struct netlink_ext_ack * extack)363 zl3073x_fw_component_flash(struct zl3073x_dev *zldev,
364 struct zl3073x_fw_component *comp,
365 struct netlink_ext_ack *extack)
366 {
367 const struct zl3073x_fw_component_info *info;
368 int rc;
369
370 info = &component_info[comp->id];
371
372 switch (info->flash_type) {
373 case ZL3073X_FLASH_TYPE_NONE:
374 /* Non-flashable component - used for utility */
375 return 0;
376 case ZL3073X_FLASH_TYPE_SECTORS:
377 rc = zl3073x_flash_sectors(zldev, info->name, info->dest_page,
378 info->load_addr, comp->data,
379 comp->size, extack);
380 break;
381 case ZL3073X_FLASH_TYPE_PAGE:
382 rc = zl3073x_flash_page(zldev, info->name, info->dest_page,
383 info->load_addr, comp->data, comp->size,
384 extack);
385 break;
386 case ZL3073X_FLASH_TYPE_PAGE_AND_COPY:
387 rc = zl3073x_flash_page(zldev, info->name, info->dest_page,
388 info->load_addr, comp->data, comp->size,
389 extack);
390 if (!rc)
391 rc = zl3073x_flash_page_copy(zldev, info->name,
392 info->dest_page,
393 info->copy_page, extack);
394 break;
395 }
396 if (rc)
397 ZL3073X_FW_ERR_MSG(extack, "Failed to flash component '%s'",
398 info->name);
399
400 return rc;
401 }
402
zl3073x_fw_flash(struct zl3073x_dev * zldev,struct zl3073x_fw * zlfw,struct netlink_ext_ack * extack)403 int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw,
404 struct netlink_ext_ack *extack)
405 {
406 int i, rc = 0;
407
408 for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++) {
409 if (!zlfw->component[i])
410 continue; /* Component is not present */
411
412 rc = zl3073x_fw_component_flash(zldev, zlfw->component[i],
413 extack);
414 if (rc)
415 break;
416 }
417
418 return rc;
419 }
420