static int do_fwsplit(const char* filename) { int rc; int fd; struct stat st; fw_t fw; unsigned char* addr; INFO("Firmware file: '%s'\n", filename); rc = stat(filename, &st); if (rc) { ERROR("Couldn't stat() file '%s': %s\n", filename, strerror(errno)); return -2; } if (st.st_size < sizeof(header_t) + sizeof(signature_t)) { ERROR("File '%s' is too short\n", filename); return -3; } fd = open(filename, O_RDONLY); if (fd < 0) { ERROR("Couldn't open file '%s': %s\n", filename, strerror(errno)); return -4; } addr=(unsigned char*)mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { ERROR("Failed mmaping memory for file '%s'\n", filename); close(fd); return -5; } // parse & validate fw rc = fw_parse(addr, st.st_size, &fw); if (rc) { ERROR("Invalid firmware file '%s'!\n", filename); munmap(addr, st.st_size); close(fd); return -6; } if (strlen(prefix) == 0) { strncpy(prefix, fw.version, sizeof(prefix)); } fw_split(&fw, prefix); munmap(addr, st.st_size); close(fd); return 0; }
int softing_load_app_fw(const char *file, struct softing *card) { const struct firmware *fw; const uint8_t *mem, *end, *dat; int ret, j; uint16_t type, len; uint32_t addr, start_addr = 0; unsigned int sum, rx_sum; int8_t type_end = 0, type_entrypoint = 0; ret = reject_firmware(&fw, file, &card->pdev->dev); if (ret) { dev_alert(&card->pdev->dev, "reject_firmware(%s) got %i\n", file, ret); return ret; } dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n", file, (unsigned long)fw->size); /* parse the firmware */ mem = fw->data; end = &mem[fw->size]; /* look for header record */ ret = fw_parse(&mem, &type, &addr, &len, &dat); if (ret) goto failed; ret = -EINVAL; if (type != 0xffff) { dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n", type); goto failed; } if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) { dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n", len, dat); goto failed; } /* ok, we had a header */ while (mem < end) { ret = fw_parse(&mem, &type, &addr, &len, &dat); if (ret) goto failed; if (type == 3) { /* start address */ start_addr = addr; type_entrypoint = 1; continue; } else if (type == 1) { /* eof */ type_end = 1; break; } else if (type != 0) { dev_alert(&card->pdev->dev, "unknown record type 0x%04x\n", type); ret = -EINVAL; goto failed; } /* regualar data */ for (sum = 0, j = 0; j < len; ++j) sum += dat[j]; /* work in 16bit (target) */ sum &= 0xffff; memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len); iowrite32(card->pdat->app.offs + card->pdat->app.addr, &card->dpram[DPRAM_COMMAND + 2]); iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]); iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]); iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]); ret = softing_bootloader_command(card, 1, "loading app."); if (ret < 0) goto failed; /* verify checksum */ rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]); if (rx_sum != sum) { dev_alert(&card->pdev->dev, "SRAM seems to be damaged" ", wanted 0x%04x, got 0x%04x\n", sum, rx_sum); ret = -EIO; goto failed; } } if (!type_end || !type_entrypoint) goto failed; /* start application in card */ iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]); iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]); ret = softing_bootloader_command(card, 3, "start app."); if (ret < 0) goto failed; ret = 0; failed: release_firmware(fw); if (ret < 0) dev_info(&card->pdev->dev, "firmware %s failed\n", file); return ret; }
int softing_load_fw(const char *file, struct softing *card, __iomem uint8_t *dpram, unsigned int size, int offset) { const struct firmware *fw; int ret; const uint8_t *mem, *end, *dat; uint16_t type, len; uint32_t addr; uint8_t *buf = NULL, *new_buf; int buflen = 0; int8_t type_end = 0; ret = reject_firmware(&fw, file, &card->pdev->dev); if (ret < 0) return ret; dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes" ", offset %c0x%04x\n", card->pdat->name, file, (unsigned int)fw->size, (offset >= 0) ? '+' : '-', (unsigned int)abs(offset)); /* parse the firmware */ mem = fw->data; end = &mem[fw->size]; /* look for header record */ ret = fw_parse(&mem, &type, &addr, &len, &dat); if (ret < 0) goto failed; if (type != 0xffff) goto failed; if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) { ret = -EINVAL; goto failed; } /* ok, we had a header */ while (mem < end) { ret = fw_parse(&mem, &type, &addr, &len, &dat); if (ret < 0) goto failed; if (type == 3) { /* start address, not used here */ continue; } else if (type == 1) { /* eof */ type_end = 1; break; } else if (type != 0) { ret = -EINVAL; goto failed; } if ((addr + len + offset) > size) goto failed; memcpy_toio(&dpram[addr + offset], dat, len); /* be sure to flush caches from IO space */ mb(); if (len > buflen) { /* align buflen */ buflen = (len + (1024-1)) & ~(1024-1); new_buf = krealloc(buf, buflen, GFP_KERNEL); if (!new_buf) { ret = -ENOMEM; goto failed; } buf = new_buf; } /* verify record data */ memcpy_fromio(buf, &dpram[addr + offset], len); if (memcmp(buf, dat, len)) { /* is not ok */ dev_alert(&card->pdev->dev, "DPRAM readback failed\n"); ret = -EIO; goto failed; } } if (!type_end) /* no end record seen */ goto failed; ret = 0; failed: kfree(buf); release_firmware(fw); if (ret < 0) dev_info(&card->pdev->dev, "firmware %s failed\n", file); return ret; }
int softing_load_fw(const char *file, struct softing *card, __iomem uint8_t *dpram, unsigned int size, int offset) { const struct firmware *fw; int ret; const uint8_t *mem, *end, *dat; uint16_t type, len; uint32_t addr; uint8_t *buf = NULL; int buflen = 0; int8_t type_end = 0; ret = request_firmware(&fw, file, &card->pdev->dev); if (ret < 0) return ret; dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes" ", offset %c0x%04x\n", card->pdat->name, file, (unsigned int)fw->size, (offset >= 0) ? '+' : '-', (unsigned int)abs(offset)); mem = fw->data; end = &mem[fw->size]; ret = fw_parse(&mem, &type, &addr, &len, &dat); if (ret < 0) goto failed; if (type != 0xffff) goto failed; if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) { ret = -EINVAL; goto failed; } while (mem < end) { ret = fw_parse(&mem, &type, &addr, &len, &dat); if (ret < 0) goto failed; if (type == 3) { continue; } else if (type == 1) { type_end = 1; break; } else if (type != 0) { ret = -EINVAL; goto failed; } if ((addr + len + offset) > size) goto failed; memcpy_toio(&dpram[addr + offset], dat, len); mb(); if (len > buflen) { buflen = (len + (1024-1)) & ~(1024-1); buf = krealloc(buf, buflen, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto failed; } } memcpy_fromio(buf, &dpram[addr + offset], len); if (memcmp(buf, dat, len)) { dev_alert(&card->pdev->dev, "DPRAM readback failed\n"); ret = -EIO; goto failed; } } if (!type_end) goto failed; ret = 0; failed: kfree(buf); release_firmware(fw); if (ret < 0) dev_info(&card->pdev->dev, "firmware %s failed\n", file); return ret; }