Advertisement
Guest User

with sdr upload (untested)

a guest
Sep 18th, 2014
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.85 KB | None | 0 0
  1. /* rkflashtool - for RockChip based devices.
  2. * (RK2808, RK2818, RK2918, RK2928, RK3066, RK3068 and RK3188)
  3. *
  4. * Copyright (C) 2010-2014 by Ivo van Poorten, Fukaumi Naoki, Guenter Knauf,
  5. * Ulrich Prinz, Steve Wilson
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31. #include <stdint.h>
  32. #include <unistd.h>
  33. #include <string.h>
  34. #include <libusb-1.0/libusb.h>
  35.  
  36. /* hack to set binary mode for stdin / stdout on Windows */
  37. #ifdef _WIN32
  38. #include <fcntl.h>
  39. int _CRT_fmode = _O_BINARY;
  40. #endif
  41.  
  42. #include "version.h"
  43.  
  44. #define RKFT_BLOCKSIZE 0x4000 /* must be multiple of 512 */
  45. #define RKFT_IDB_BLOCKSIZE 0x210
  46. #define RKFT_IDB_INCR 0x20
  47. #define RKFT_MEM_INCR 0x80
  48. #define RKFT_OFF_INCR (RKFT_BLOCKSIZE>>9)
  49.  
  50. #define RKFT_CMD_TESTUNITREADY 0x80000600
  51. #define RKFT_CMD_READFLASHID 0x80000601
  52. #define RKFT_CMD_READFLASHINFO 0x8000061a
  53. #define RKFT_CMD_READCHIPINFO 0x8000061b
  54. #define RKFT_CMD_READEFUSE 0x80000620
  55.  
  56. #define RKFT_CMD_SETDEVICEINFO 0x00000602
  57. #define RKFT_CMD_ERASESYSTEMDISK 0x00000616
  58. #define RKFT_CMD_SETRESETFLASG 0x0000061e
  59. #define RKFT_CMD_RESETDEVICE 0x000006ff
  60.  
  61. #define RKFT_CMD_TESTBADBLOCK 0x80000a03
  62. #define RKFT_CMD_READSECTOR 0x80000a04
  63. #define RKFT_CMD_READLBA 0x80000a14
  64. #define RKFT_CMD_READSDRAM 0x80000a17
  65. #define RKFT_CMD_UNKNOWN1 0x80000a21
  66.  
  67. #define RKFT_CMD_WRITESECTOR 0x00000a05
  68. #define RKFT_CMD_ERASESECTORS 0x00000a06
  69. #define RKFT_CMD_UNKNOWN2 0x00000a0b
  70. #define RKFT_CMD_WRITELBA 0x00000a15
  71. #define RKFT_CMD_WRITESDRAM 0x00000a18
  72. #define RKFT_CMD_EXECUTESDRAM 0x00000a19
  73. #define RKFT_CMD_WRITEEFUSE 0x00000a1f
  74. #define RKFT_CMD_UNKNOWN3 0x00000a22
  75.  
  76. #define RKFT_CMD_WRITESPARE 0x80001007
  77. #define RKFT_CMD_READSPARE 0x80001008
  78.  
  79. #define RKFT_CMD_LOWERFORMAT 0x0000001c
  80. #define RKFT_CMD_WRITENKB 0x00000030
  81.  
  82. #define SETBE16(a, v) do { \
  83. ((uint8_t*)a)[1] = v & 0xff; \
  84. ((uint8_t*)a)[0] = (v>>8 ) & 0xff; \
  85. } while(0)
  86.  
  87. #define SETBE32(a, v) do { \
  88. ((uint8_t*)a)[3] = v & 0xff; \
  89. ((uint8_t*)a)[2] = (v>>8 ) & 0xff; \
  90. ((uint8_t*)a)[1] = (v>>16) & 0xff; \
  91. ((uint8_t*)a)[0] = (v>>24) & 0xff; \
  92. } while(0)
  93.  
  94. static const struct t_pid {
  95. const uint16_t pid;
  96. const char name[8];
  97. } pidtab[] = {
  98. { 0x281a, "RK2818" },
  99. { 0x290a, "RK2918" },
  100. { 0x292a, "RK2928" },
  101. { 0x292c, "RK3026" },
  102. { 0x300a, "RK3066" },
  103. { 0x300b, "RK3168" },
  104. { 0x310a, "RK3066B" },
  105. { 0x310b, "RK3188" },
  106. { 0x320a, "RK3288" },
  107. { 0, "" },
  108. };
  109.  
  110. static uint8_t cmd[31], res[13], buf[RKFT_BLOCKSIZE];
  111. static libusb_context *c;
  112. static libusb_device_handle *h = NULL;
  113. static int tmp;
  114.  
  115. static const char *const strings[2] = { "info", "fatal" };
  116.  
  117. static void info_and_fatal(const int s, char *f, ...) {
  118. va_list ap;
  119. va_start(ap,f);
  120. fprintf(stderr, "rkflashtool: %s: ", strings[s]);
  121. vfprintf(stderr, f, ap);
  122. va_end(ap);
  123. if (s) exit(s);
  124. }
  125.  
  126. #define info(...) info_and_fatal(0, __VA_ARGS__)
  127. #define fatal(...) info_and_fatal(1, __VA_ARGS__)
  128.  
  129. static void usage(void) {
  130. fatal("usage:\n"
  131. "\trkflashtool b \treboot device\n"
  132. "\trkflashtool i offset nsectors >outfile \tread IDBlocks\n"
  133. // "\trkflashtool j offset nsectors <infile \twrite IDBlocks\n"
  134. "\trkflashtool m offset nbytes >outfile \tread SDRAM\n"
  135. "\trkflashtool n offset nbytes <infile \twrite SDRAM\n"
  136. "\trkflashtool r partname >outfile \tread flash partition\n"
  137. "\trkflashtool w partname <infile \twrite flash partition\n"
  138. "\trkflashtool r offset nsectors >outfile \tread flash\n"
  139. "\trkflashtool w offset nsectors <infile \twrite flash\n"
  140. // "\trkflashtool f >outfile \tread fuses\n"
  141. // "\trkflashtool g <infile \twrite fuses\n"
  142. "\trkflashtool p >file \tfetch parameters\n"
  143. "\trkflashtool e partname \terase flash (fill with 0xff)\n"
  144. "\trkflashtool e offset nsectors \terase flash (fill with 0xff)\n"
  145. );
  146. }
  147.  
  148. static void send_cmd(uint32_t command, uint32_t offset, uint16_t nsectors) {
  149. long int r = random();
  150.  
  151. memset(cmd, 0 , 31);
  152. memcpy(cmd, "USBC", 4);
  153.  
  154. if (r) SETBE32(cmd+4, r);
  155. if (offset) SETBE32(cmd+17, offset);
  156. if (nsectors) SETBE16(cmd+22, nsectors);
  157. if (command) SETBE32(cmd+12, command);
  158.  
  159. libusb_bulk_transfer(h, 2|LIBUSB_ENDPOINT_OUT, cmd, sizeof(cmd), &tmp, 0);
  160. }
  161.  
  162. static void send_buf(unsigned int s) {
  163. libusb_bulk_transfer(h, 2|LIBUSB_ENDPOINT_OUT, buf, s, &tmp, 0);
  164. }
  165.  
  166. static void recv_res(void) {
  167. libusb_bulk_transfer(h, 1|LIBUSB_ENDPOINT_IN, res, sizeof(res), &tmp, 0);
  168. }
  169.  
  170. static void recv_buf(unsigned int s) {
  171. libusb_bulk_transfer(h, 1|LIBUSB_ENDPOINT_IN, buf, s, &tmp, 0);
  172. }
  173.  
  174. #define NEXT do { argc--;argv++; } while(0)
  175.  
  176. int main(int argc, char **argv) {
  177. const struct t_pid *ppid = pidtab;
  178. unsigned int offset = 0, size = 0;
  179. char action;
  180. char *partname = NULL;
  181.  
  182. info("rkflashtool v%d.%d\n", RKFLASHTOOL_VERSION_MAJOR,
  183. RKFLASHTOOL_VERSION_MINOR);
  184.  
  185. NEXT; if (!argc) usage();
  186.  
  187. action = **argv; NEXT;
  188.  
  189. switch(action) {
  190. case 'b':
  191. if (argc) usage();
  192. break;
  193. case 'e':
  194. case 'r':
  195. case 'w':
  196. if (argc < 1 || argc > 2) usage();
  197. if (argc == 1) {
  198. partname = argv[0];
  199. } else {
  200. offset = strtoul(argv[0], NULL, 0);
  201. size = strtoul(argv[1], NULL, 0);
  202. }
  203. break;
  204. case 'm':
  205. case 'n':
  206. case 'i':
  207. if (argc != 2) usage();
  208. offset = strtoul(argv[0], NULL, 0);
  209. size = strtoul(argv[1], NULL, 0);
  210. break;
  211. case 'p':
  212. if (argc) usage();
  213. offset = 0;
  214. size = 1024;
  215. break;
  216. default:
  217. usage();
  218. }
  219.  
  220. /* Initialize libusb */
  221.  
  222. if (libusb_init(&c)) fatal("cannot init libusb\n");
  223.  
  224. libusb_set_debug(c, 3);
  225.  
  226. /* Detect connected RockChip device */
  227.  
  228. while ( !h && ppid->pid) {
  229. h = libusb_open_device_with_vid_pid(c, 0x2207, ppid->pid);
  230. if (h) {
  231. info("Detected %s...\n", ppid->name);
  232. break;
  233. }
  234. ppid++;
  235. }
  236. if (!h) fatal("cannot open device\n");
  237.  
  238. /* Connect to device */
  239.  
  240. if (libusb_kernel_driver_active(h, 0) == 1) {
  241. info("kernel driver active\n");
  242. if (!libusb_detach_kernel_driver(h, 0))
  243. info("driver detached\n");
  244. }
  245.  
  246. if (libusb_claim_interface(h, 0) < 0)
  247. fatal("cannot claim interface\n");
  248. info("interface claimed\n");
  249.  
  250. /* Initialize bootloader interface */
  251.  
  252. send_cmd(RKFT_CMD_TESTUNITREADY, 0, 0);
  253. recv_res();
  254. usleep(20*1000);
  255.  
  256. /* Parse partition name */
  257. if (partname) {
  258. info("working with partition: %s\n", partname);
  259.  
  260. /* Read parameters */
  261. offset = 0;
  262. send_cmd(RKFT_CMD_READLBA, offset, RKFT_OFF_INCR);
  263. recv_buf(RKFT_BLOCKSIZE);
  264. recv_res();
  265.  
  266. uint32_t *p = (uint32_t*)buf+1;
  267. size = *p;
  268.  
  269. /* Search for mtdparts */
  270. const char *param = (const char *)&buf[8];
  271. const char *mtdparts = strstr(param, "mtdparts=");
  272. if (!mtdparts) {
  273. info("Error: 'mtdparts' not found in command line.\n");
  274. goto exit;
  275. }
  276.  
  277. /* Search for '(partition_name)' */
  278. char partexp[256];
  279. snprintf(partexp, 256, "(%s)", partname);
  280. char *par = strstr(mtdparts, partexp);
  281. if (!par) {
  282. info("Error: Partition '%s' not found.\n", partname);
  283. goto exit;
  284. }
  285.  
  286. /* Cut string by NULL-ing just before (partition_name) */
  287. par[0] = '\0';
  288.  
  289. /* Search for '@' sign */
  290. char *arob = strrchr(mtdparts, '@');
  291. if (!arob) {
  292. info("Error: Bad syntax in mtdparts.\n");
  293. goto exit;
  294. }
  295.  
  296. offset = strtoul(arob+1, NULL, 0);
  297. info("found offset: %#010x\n", offset);
  298.  
  299. /* Cut string by NULL-ing just before '@' sign */
  300. arob[0] = '\0';
  301.  
  302. /* Search for '-' sign (if last partition) */
  303. char *minus = strrchr(mtdparts, '-');
  304. if (minus) {
  305. size = UINT_MAX;
  306. info("partition extends up to the end of NAND.\n");
  307. goto action;
  308. }
  309.  
  310. /* Search for ',' sign */
  311. char *comma = strrchr(mtdparts, ',');
  312. if (comma) {
  313. size = strtoul(comma+1, NULL, 0);
  314. info("found size: %#010x\n", size);
  315. goto action;
  316. }
  317.  
  318. /* Search for ':' sign (if first partition) */
  319. char *colon = strrchr(mtdparts, ':');
  320. if (colon) {
  321. size = strtoul(colon+1, NULL, 0);
  322. info("found size: %#010x\n", size);
  323. goto action;
  324. }
  325.  
  326. /* Error: size not found! */
  327. info("Error: Bad syntax for partition size.\n");
  328. goto exit;
  329. }
  330.  
  331. action:
  332. /* Check and execute command */
  333.  
  334. switch(action) {
  335. case 'b': /* Reboot device */
  336. info("rebooting device...\n");
  337. send_cmd(RKFT_CMD_RESETDEVICE, 0, 0);
  338. recv_res();
  339. break;
  340. case 'r': /* Read FLASH */
  341. while (size > 0) {
  342. fprintf(stderr, "\rrkflashtool: info: "
  343. "reading flash memory at offset 0x%08x", offset);
  344.  
  345. send_cmd(RKFT_CMD_READLBA, offset, RKFT_OFF_INCR);
  346. recv_buf(RKFT_BLOCKSIZE);
  347. recv_res();
  348.  
  349. if (write(1, buf, RKFT_BLOCKSIZE) <= 0)
  350. fatal("Write error! Disk full?\n");
  351.  
  352. offset += RKFT_OFF_INCR;
  353. size -= RKFT_OFF_INCR;
  354. }
  355. fprintf(stderr, "... Done!\n");
  356. break;
  357. case 'w': /* Write FLASH */
  358. while (size > 0) {
  359. fprintf(stderr, "\rrkflashtool: info: "
  360. "writing flash memory at offset 0x%08x", offset);
  361.  
  362. if (read(0, buf, RKFT_BLOCKSIZE) <= 0) {
  363. fprintf(stderr, "... Done!\n");
  364. info("premature end-of-file reached.\n");
  365. goto exit;
  366. }
  367.  
  368. send_cmd(RKFT_CMD_WRITELBA, offset, RKFT_OFF_INCR);
  369. send_buf(RKFT_BLOCKSIZE);
  370. recv_res();
  371.  
  372. offset += RKFT_OFF_INCR;
  373. size -= RKFT_OFF_INCR;
  374. }
  375. fprintf(stderr, "... Done!\n");
  376. break;
  377. case 'p': /* Retreive parameters */
  378. {
  379. uint32_t *p = (uint32_t*)buf+1;
  380.  
  381. info("reading parameters at offset 0x%08x\n", offset);
  382.  
  383. send_cmd(RKFT_CMD_READLBA, offset, RKFT_OFF_INCR);
  384. recv_buf(RKFT_BLOCKSIZE);
  385. recv_res();
  386. size = *p;
  387. info("size: 0x%08x\n", size);
  388.  
  389. if (write(1, &buf[8], size) <= 0)
  390. fatal("Write error! Disk full?\n");
  391. }
  392. break;
  393. case 'm': /* Read RAM */
  394. while (size > 0) {
  395. int sizeRead = size > RKFT_MEM_INCR ? RKFT_MEM_INCR : size;
  396. info("reading memory at offset 0x%08x size %x\n", offset, sizeRead);
  397.  
  398. send_cmd(RKFT_CMD_READSDRAM, offset-0x60000000, sizeRead);
  399. recv_buf(sizeRead);
  400. recv_res();
  401.  
  402. if (write(1, buf, sizeRead) <= 0)
  403. fatal("Write error! Disk full?\n");
  404.  
  405. offset += sizeRead;
  406. size -= sizeRead;
  407. }
  408. break;
  409. case 'n': /* Write RAM */
  410. if (size == 0) size = 0xffffff;
  411. while (size > 0) {
  412. int sizeRead;
  413.  
  414. if ((sizeRead = read(0, buf, RKFT_BLOCKSIZE)) <= 0) {
  415. fprintf(stderr, "... Done!\n");
  416. goto exit;
  417. }
  418.  
  419. info("writing memory at offset 0x%08x size %x\n", offset, sizeRead);
  420.  
  421. send_cmd(RKFT_CMD_WRITESDRAM, offset-0x60000000, sizeRead);
  422. send_buf(RKFT_BLOCKSIZE);
  423. recv_res();
  424.  
  425. offset += sizeRead;
  426. // size -= sizeRead;
  427. }
  428. break;
  429. case 'i': /* Read IDB */
  430. while (size > 0) {
  431. int sizeRead = size > RKFT_IDB_INCR ? RKFT_IDB_INCR : size;
  432. info("reading IDB flash memory at offset 0x%08x\n", offset);
  433.  
  434. send_cmd(RKFT_CMD_READSECTOR, offset, sizeRead);
  435. recv_buf(RKFT_IDB_BLOCKSIZE * sizeRead);
  436. recv_res();
  437.  
  438. if (write(1, buf, RKFT_IDB_BLOCKSIZE * sizeRead) <= 0)
  439. fatal("Write error! Disk full?\n");
  440.  
  441. offset += sizeRead;
  442. size -= sizeRead;
  443. }
  444. break;
  445. case 'e': /* Erase flash */
  446. memset(buf, 0xff, RKFT_BLOCKSIZE);
  447. while (size > 0) {
  448. info("erasing flash memory at offset 0x%08x\n", offset);
  449.  
  450. send_cmd(RKFT_CMD_WRITELBA, offset, RKFT_OFF_INCR);
  451. send_buf(RKFT_BLOCKSIZE);
  452. recv_res();
  453.  
  454. offset += RKFT_OFF_INCR;
  455. size -= RKFT_OFF_INCR;
  456. }
  457. break;
  458. default:
  459. break;
  460. }
  461.  
  462. exit:
  463. /* Disconnect and close all interfaces */
  464.  
  465. libusb_release_interface(h, 0);
  466. libusb_close(h);
  467. libusb_exit(c);
  468. return 0;
  469. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement