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 = 0x2300, 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 * 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 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 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 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 */ 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 */ 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 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 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