static void parse_file(char *input, struct file_ops_t **op, char **file) { char *pos; *op = GetFileOps("bin"); pos = strchr(input, ':'); if (pos != NULL) { pos[0] = '\0'; *op = GetFileOps(input); *file = &pos[1]; } else { *file = input; } }
int main(int argc, char** argv) { struct ols_boot_t *ob; struct ols_t *ols; uint8_t *bin_buf; uint8_t *bin_buf_tmp; uint32_t bin_buf_size; uint16_t vid = OLS_VID; uint16_t pid = OLS_PID; int error = 0; int ret; int i; uint16_t pages; int debug = 0; // aguments struct file_ops_t *fo; char *file_write = NULL; char *file_read = NULL; uint8_t cmd = 0; char *port = NULL; uint8_t device = 0; uint16_t page_limit = 0; uint32_t max_addr = 0; // getopt int opt; fo = GetFileOps("HEX"); // parse args while ((opt = getopt(argc, argv, "WRVETSnr:w:v:p:t:P:f:hd")) != -1) { switch (opt) { case 'd': debug = 1; break; case 'h': usage(); exit(1); break; case 'R': cmd |= CMD_READ; break; case 'W': cmd |= CMD_WRITE; break; case 'E': cmd |= CMD_ERASE; break; case 'V': cmd |= CMD_VERIFY; break; case 'T': cmd |= CMD_RESET; break; case 'S': cmd |= CMD_SELFTEST; break; case 'l': page_limit = atoi(optarg); break; case 'v': // vid vid = (uint16_t)strtol(optarg, NULL, 0); break; case 'p': // pid pid = (uint16_t)strtol(optarg, NULL, 0); break; case 'P': if (port != NULL) { fprintf(stderr, "Two ports ?!\n"); exit(-1); } port = strdup(optarg); break; case 'r': // readfile if (file_read != NULL) { fprintf(stderr, "Two files?\n"); exit(-1); } file_read = strdup(optarg); break; case 'w': // readfile if (file_write != NULL) { fprintf(stderr, "Two files?\n"); exit(-1); } file_write = strdup(optarg); break; case 't': fo = GetFileOps(optarg); if (fo == NULL) { fprintf(stderr, "Unknown type \n"); exit(-1); } break; case 'n': device |= DEV_SWITCH; break; case 'f': if (device & (DEV_APP | DEV_BOOT)) { fprintf(stderr, "Two devices ??\n"); exit(-1); } if (strncasecmp(optarg, "APP", 3) == 0) { device |= DEV_APP; } else if (strncasecmp(optarg, "BOOT", 4) == 0) { device |= DEV_BOOT; } else { fprintf(stderr, "Unknown device specified\n"); exit(-1); } break; } } // check parameters if ((cmd & CMD_READ) && (file_read == NULL)) { fprintf(stderr, "Read command but no file ? \n"); error = 1; } if ((cmd & CMD_WRITE) && (file_write == NULL)) { fprintf(stderr, "Write command but no file ? \n"); error = 1; } if ((cmd & CMD_VERIFY) && (file_write == NULL)) { fprintf(stderr, "Verify command but no file ? \n"); error = 1; } if ((device & DEV_APP) || device & DEV_SWITCH) { if (port == NULL) { fprintf(stderr, "Missing serial port \n"); error = 1; } } if ((device & 3) == 0) { fprintf(stderr, "No device specified\n"); error = 1; } /* if (cmd == 0) { fprintf(stderr, "Missing command\n"); error = 1; } */ if ((error)) { usage(); exit(1); } // execute commands // Working with APP or switch to bootloader first if ((device & DEV_APP) || (device & DEV_SWITCH)) { ols = OLS_Init(port, 921600); if (ols == NULL) { fprintf(stderr, "Unable to initialise OLS\n"); exit(-1); } if (debug) { ols->verbose = 1; } bin_buf_size = ols->flash->pages * ols->flash->page_size; if (device & DEV_SWITCH) { if (device & DEV_BOOT) { OLS_EnterBootloader(ols); OLS_Deinit(ols); // wait for device to appear sleep(2); } else { fprintf(stderr, "Not switching to bootloader.\n"); device &= ~DEV_SWITCH; } } } // Initialize bootloader if (device & DEV_BOOT) { ob = BOOT_Init(vid, pid, debug); if (ob == NULL) { exit(1); } // 2 times, first might fail for reason unknown for (i = 0; i < 2; i++) { ret = BOOT_Version(ob); if (ret) { exit(1); } } bin_buf_size = OLS_FLASH_TOTSIZE; } // allocate buffers bin_buf = malloc(bin_buf_size); bin_buf_tmp = malloc(bin_buf_size); if ((bin_buf == NULL) || (bin_buf_tmp == NULL)) { fprintf(stderr, "Error allocating memory \n"); exit(1); } if (cmd & CMD_SELFTEST) { if (device & DEV_APP) { ret = OLS_RunSelftest(ols); if (ret) { exit(1); } } } if (cmd & CMD_READ) { printf("Reading flash \n"); memset(bin_buf, 0xff, bin_buf_size); if (device & DEV_APP) { int i; if (page_limit != 0) { pages = page_limit; } else { pages = ols->flash->pages; } pages = (pages > ols->flash->pages) ? ols->flash->pages : pages; for (i = 0; i < pages; i ++) { // read i-th page into buffer ret = OLS_FlashRead(ols, i, bin_buf + (ols->flash->page_size * i)); if (ret) { exit(1); } if ((i % 32) == 0) { printf("."); fflush(stdout); } } printf("\n"); } else { // reads whole flash (inc bootloader) ret = BOOT_Read(ob, 0x0000, bin_buf, bin_buf_size); if (ret) { exit(1); } } printf("Writing file '%s'\n", file_read); fo->WriteFile(file_read, bin_buf, bin_buf_size); } // JaWi: first read the entire data file before going to erase/write stuff. // This way, we're fairly sure we can leave the device in a workable state if (cmd & CMD_WRITE) { printf("Reading file '%s'\n", file_write); memset(bin_buf_tmp, 0xff, bin_buf_size); max_addr = fo->ReadFile(file_write, bin_buf, bin_buf_size); if (max_addr == 0) { // error reading fprintf(stderr, "Error reading file - skipping write\n"); exit(1); } } // writing implies erase if ((cmd & CMD_ERASE) || (cmd & CMD_WRITE)) { printf("Erasing flash ...\n"); if (device & DEV_APP) { // erase spi flash, bulk erase ret = OLS_FlashErase(ols); if (ret) { exit(1); } } else { // erases flash (this is done internally by bootloader) ret = BOOT_Erase(ob); if (ret) { exit(1); } } } if (cmd & CMD_WRITE) { if ((max_addr != 0) && (device & DEV_APP)) { int i; // determine number of pages (round up) if (page_limit != 0) { pages = page_limit; } else { pages = (max_addr + ols->flash->page_size - 1) / ols->flash->page_size; } pages = (pages > ols->flash->pages) ? ols->flash->pages : pages; printf("Will write %d pages \n", pages); for (i = 0; i < pages; i ++) { ret = OLS_FlashWrite(ols, i, bin_buf + (ols->flash->page_size * i)); if (ret) { exit(1); } if ((i % 32) == 0) { printf("."); fflush(stdout); } } printf("\n"); } else if ((max_addr != 0) && (device & DEV_BOOT)) { int size; // we write only application size = ((max_addr - OLS_FLASH_ADDR) > OLS_FLASH_SIZE)? OLS_FLASH_SIZE : max_addr - OLS_FLASH_ADDR; printf("Writing flash ... (0x%04x - 0x%04x) \n", OLS_FLASH_ADDR, size + OLS_FLASH_ADDR); ret = BOOT_Write(ob, OLS_FLASH_ADDR, &bin_buf[OLS_FLASH_ADDR], size); if (ret) { exit(1); } } } if (cmd & CMD_VERIFY) { // read the whole flash memset(bin_buf_tmp, 0xff, bin_buf_size); memset(bin_buf, 0xff, bin_buf_size); max_addr = fo->ReadFile(file_write, bin_buf_tmp, bin_buf_size); if (max_addr == 0) { // error reading fprintf(stderr, "Error reading file - skipping verify\n"); } if ((max_addr != 0) && (device & DEV_APP)) { int i; printf("Checking flash ...\n"); if (page_limit != 0) { pages = page_limit; } else { pages = (max_addr + ols->flash->page_size - 1) / ols->flash->page_size; } pages = (pages > ols->flash->pages) ? ols->flash->pages : pages; for (i = 0; i < pages; i ++) { uint32_t off; off = ols->flash->page_size * i; // read i-th page into buffer ret = OLS_FlashRead(ols, i, bin_buf + off); if (ret) { exit(1); } if ((i % 32) == 0) { printf("."); fflush(stdout); } } printf("\n"); // compare page by page if (memverify(bin_buf_tmp, bin_buf, max_addr, 0, debug)) { printf("Verify error\n"); } else { printf("Verify OK\n"); } } else if ((max_addr != 0) && (device & DEV_BOOT)) { int size; ret = BOOT_Read(ob, 0x0000, bin_buf, OLS_FLASH_TOTSIZE); if (ret) { exit(1); } // compare only application size = ((max_addr - OLS_FLASH_ADDR) > OLS_FLASH_SIZE)? OLS_FLASH_SIZE : max_addr - OLS_FLASH_ADDR; printf("Checking flash ... (0x%04x - 0x%04x)\n", OLS_FLASH_ADDR, size + OLS_FLASH_ADDR); if (memverify(&bin_buf_tmp[OLS_FLASH_ADDR], &bin_buf[OLS_FLASH_ADDR], size, OLS_FLASH_ADDR, debug) == 0) { printf("Verified OK! :)\n"); } else { printf("Verify failed :(\n"); } } } if (cmd & CMD_RESET) { if (device & DEV_APP) { printf("Reseting to normal mode \n"); OLS_EnterRunMode(ols); } else { printf("Reseting device \n"); BOOT_Reset(ob); } } if (device & DEV_APP) { OLS_Deinit(ols); } else { BOOT_Deinit(ob); } // free allocated memory free(bin_buf_tmp); free(bin_buf); return 0; }