int main(int argc, char **argv) { libusb_context *c; libusb_device_handle *h; int offset = 0, size = 0; char action; NEXT; if (!argc) usage(); action = **argv; NEXT; switch(action) { case 'b': if (argc) usage(); break; case 'e': case 'r': case 'w': if (argc!=2) usage(); offset = strtoul(argv[0], NULL, 0); size = strtoul(argv[1], NULL, 0); break; case 'v': case 'V': printf("rkflashtool version %d.%d\n", RKFLASHTOOL_VER_MAJOR, RKFLASHTOOL_VER_MINOR); exit(0); break; default: usage(); } if (libusb_init(&c)) fatal("cannot init libusb\n"); libusb_set_debug(c, 3); if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x290a))) if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x281a))) if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x300a))) if (!(h = libusb_open_device_with_vid_pid(c, 0x2207, 0x310b))) fatal("cannot open device\n"); if (libusb_kernel_driver_active(h, 0) == 1) { info("kernel driver active\n"); if (!libusb_detach_kernel_driver(h, 0)) info("driver detached\n"); } if (libusb_claim_interface(h, 0)<0) fatal("cannot claim interface\n"); info("interface claimed\n"); send_cmd(h, 2, 0x80, 0x00060000, 0x00000000, 0x00); /* INIT */ recv_res(h, 1); usleep(20*1000); switch(action) { case 'b': info("rebooting device...\n"); send_cmd(h, 2, 0x00, 0x0006ff00, 0x00000000, 0x00); recv_res(h, 1); break; case 'r': while (size>0) { if (offset % RKFT_DISPLAY == 0) info("reading flash memory at offset 0x%08x\r", offset); send_cmd(h, 2, 0x80, 0x000a1400, offset, RKFT_OFF_INCR); recv_buf(h, 1, RKFT_BLOCKSIZE); recv_res(h, 1); /* check for write() errors to catch disk-full, no-perms, etc. */ if (write(1, buf, RKFT_BLOCKSIZE) < 0) fatal("error writing buffer to stdout: %s\n", strerror(errno)); offset += RKFT_OFF_INCR; size -= RKFT_OFF_INCR; } fprintf(stderr, "\n"); break; case 'w': while (size>0) { if (offset % RKFT_DISPLAY == 0) info("writing flash memory at offset 0x%08x\r", offset); memset(buf, 0, RKFT_BLOCKSIZE); /* we ignore here read() errors and pad up to given size */ if (read(0, buf, RKFT_BLOCKSIZE) < 0) {}; send_cmd(h, 2, 0x80, 0x000a1500, offset, RKFT_OFF_INCR); send_buf(h, 2, RKFT_BLOCKSIZE); recv_res(h, 1); offset += RKFT_OFF_INCR; size -= RKFT_OFF_INCR; } fprintf(stderr, "\n"); break; case 'e': memset(buf, RKFT_FILLBYTE, RKFT_BLOCKSIZE); while (size>0) { if (offset % RKFT_DISPLAY == 0) info("erasing flash memory at offset 0x%08x\r", offset); send_cmd(h, 2, 0x80, 0x000a1500, offset, RKFT_OFF_INCR); send_buf(h, 2, RKFT_BLOCKSIZE); recv_res(h, 1); offset += RKFT_OFF_INCR; size -= RKFT_OFF_INCR; } fprintf(stderr, "\n"); break; default: break; } libusb_release_interface(h, 0); libusb_close(h); libusb_exit(c); return 0; }
int main(int argc, char **argv) { const struct t_pid *ppid = pidtab; int offset = 0, size = 0; char action; info("rkflashtool v%d.%d\n", RKFLASHTOOL_VERSION_MAJOR, RKFLASHTOOL_VERSION_MINOR); NEXT; if (!argc) usage(); action = **argv; NEXT; switch(action) { case 'b': case 'l': if (argc) usage(); break; case 'e': case 'r': case 'w': case 'm': case 'i': if (argc != 2) usage(); offset = strtoul(argv[0], NULL, 0); size = strtoul(argv[1], NULL, 0); break; case 'p': if (argc) usage(); offset = 0; size = 1024; break; default: usage(); } /* Initialize libusb */ if (libusb_init(&c)) fatal("cannot init libusb\n"); libusb_set_debug(c, 3); /* Detect connected RockChip device */ while ( !h && ppid->pid) { h = libusb_open_device_with_vid_pid(c, 0x2207, ppid->pid); if (h) { info("Detected %s...\n", ppid->name); break; } ppid++; } if (!h) fatal("cannot open device\n"); /* Connect to device */ if (libusb_kernel_driver_active(h, 0) == 1) { info("kernel driver active\n"); if (!libusb_detach_kernel_driver(h, 0)) info("driver detached\n"); } if (libusb_claim_interface(h, 0) < 0) fatal("cannot claim interface\n"); info("interface claimed\n"); /* Initialize bootloader interface */ send_cmd(RKFT_CMD_TESTUNITREADY, 0, 0); recv_res(); usleep(20*1000); /* Check and execute command */ switch(action) { case 'b': /* Reboot device */ info("rebooting device...\n"); send_cmd(RKFT_CMD_RESETDEVICE, 0, 0); recv_res(); break; case 'r': /* Read FLASH */ while (size > 0) { info("reading flash memory at offset 0x%08x\n", offset); send_cmd(RKFT_CMD_READLBA, offset, RKFT_OFF_INCR); recv_buf(RKFT_BLOCKSIZE); recv_res(); if (write(1, buf, RKFT_BLOCKSIZE) <= 0) fatal("Write error! Disk full?\n"); offset += RKFT_OFF_INCR; size -= RKFT_OFF_INCR; } break; case 'w': /* Write FLASH */ while (size > 0) { info("writing flash memory at offset 0x%08x\n", offset); if (read(0, buf, RKFT_BLOCKSIZE) <= 0) fatal("premature end-of-file reached.\n"); send_cmd(RKFT_CMD_WRITELBA, offset, RKFT_OFF_INCR); send_buf(RKFT_BLOCKSIZE); recv_res(); offset += RKFT_OFF_INCR; size -= RKFT_OFF_INCR; } break; case 'p': /* Retreive parameters */ { uint32_t *p = (uint32_t*)buf+1; info("reading parameters at offset 0x%08x\n", offset); send_cmd(RKFT_CMD_READLBA, offset, RKFT_OFF_INCR); recv_buf(RKFT_BLOCKSIZE); recv_res(); size = *p; info("size: 0x%08x\n", size); if (write(1, &buf[8], size) <= 0) fatal("Write error! Disk full?\n"); } break; case 'l': /* Retreive flashinfo */ { info("reading parameters at offset 0x%08x\n", offset); send_cmd(RKFT_CMD_READFLASHINFO, offset, RKFT_OFF_INCR); recv_buf(RKFT_FLASHINFO_SIZE); recv_res(); if (write(1, buf, RKFT_FLASHINFO_SIZE) <= 0) fatal("Write error! Disk full?\n"); } break; case 'm': /* Read RAM */ while (size > 0) { int sizeRead = size > RKFT_MEM_INCR ? RKFT_MEM_INCR : size; info("reading memory at offset 0x%08x size %x\n", offset, sizeRead); send_cmd(RKFT_CMD_READSDRAM, offset-0x60000000, sizeRead); recv_buf(sizeRead); recv_res(); if (write(1, buf, sizeRead) <= 0) fatal("Write error! Disk full?\n"); offset += sizeRead; size -= sizeRead; } break; case 'i': /* Read IDB */ while (size > 0) { int sizeRead = size > RKFT_IDB_INCR ? RKFT_IDB_INCR : size; info("reading IDB flash memory at offset 0x%08x\n", offset); send_cmd(RKFT_CMD_READSECTOR, offset, sizeRead); recv_buf(RKFT_IDB_BLOCKSIZE * sizeRead); recv_res(); if (write(1, buf, RKFT_IDB_BLOCKSIZE * sizeRead) <= 0) fatal("Write error! Disk full?\n"); offset += sizeRead; size -= sizeRead; } break; case 'e': /* Erase flash */ memset(buf, 0xff, RKFT_BLOCKSIZE); while (size > 0) { info("erasing flash memory at offset 0x%08x\n", offset); send_cmd(RKFT_CMD_WRITELBA, offset, RKFT_OFF_INCR); send_buf(RKFT_BLOCKSIZE); recv_res(); offset += RKFT_OFF_INCR; size -= RKFT_OFF_INCR; } break; default: break; } /* Disconnect and close all interfaces */ libusb_release_interface(h, 0); libusb_close(h); libusb_exit(c); return 0; }