fork download
  1. /*
  2.  
  3.  Pirate-Loader for Bootloader v4
  4.  
  5.  Version : 1.0.2
  6.  
  7.  Changelog:
  8.  +2010-06-28 - Made HEX parser case-insensative
  9.  
  10.   + 2010-02-04 - Changed polling interval to 10ms on Windows select wrapper, suggested by Michal (robots)
  11.  
  12.   + 2010-02-04 - Added sleep(0) between write instructions, patch submitted by kbulgrien
  13.  
  14.   + 2010-01-22 - Added loader version number to the console output and source code
  15.  
  16.   + 2010-01-19 - Fixed BigEndian incompatibility
  17.   - Added programming simulate switch ( --simulate ) for data verification
  18.  
  19.   + 2010-01-18 - Initial release
  20.  
  21.  
  22.  Building:
  23.  
  24.   UNIX family systems:
  25.  
  26.   gcc pirate-loader.c -o pirate-loader
  27.  
  28.   WINDOWS:
  29.  
  30.   cl pirate-loader.c /DWIN32=1
  31.  
  32.  
  33.  Usage:
  34.  
  35.   Run ./pirate-loader --help for more information on usage and possible switches
  36.  
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <memory.h>
  42. #include <fcntl.h>
  43. #include <errno.h>
  44.  
  45. #define PIRATE_LOADER_VERSION "1.0.2"
  46.  
  47. #define STR_EXPAND(tok) #tok
  48. #define OS_NAME(tok) STR_EXPAND(tok)
  49.  
  50.  
  51. #ifdef WIN32
  52. #include <windows.h>
  53. #include <time.h>
  54.  
  55. #define O_NOCTTY 0
  56. #define O_NDELAY 0
  57. #define B115200 115200
  58.  
  59. #define OS WINDOWS
  60.  
  61. int write(int fd, const void* buf, int len)
  62. {
  63. HANDLE hCom = (HANDLE)fd;
  64. int res = 0;
  65. unsigned long bwritten = 0;
  66.  
  67.  
  68. res = WriteFile(hCom, buf, len, &bwritten, NULL);
  69.  
  70. if( res == FALSE ) {
  71. return -1;
  72. } else {
  73. return bwritten;
  74. }
  75. }
  76.  
  77. int read(int fd, void* buf, int len)
  78. {
  79. HANDLE hCom = (HANDLE)fd;
  80. int res = 0;
  81. unsigned long bread = 0;
  82.  
  83. res = ReadFile(hCom, buf, len, &bread, NULL);
  84.  
  85. if( res == FALSE ) {
  86. return -1;
  87. } else {
  88. return bread;
  89. }
  90. }
  91.  
  92. int close(int fd)
  93. {
  94. HANDLE hCom = (HANDLE)fd;
  95.  
  96. CloseHandle(hCom);
  97. return 0;
  98. }
  99.  
  100. int open(const char* path, unsigned long flags)
  101. {
  102. static char full_path[32] = {0};
  103.  
  104. HANDLE hCom = NULL;
  105.  
  106. if( path[0] != '\\' ) {
  107. _snprintf(full_path, sizeof(full_path) - 1, "\\\\.\\%s", path);
  108. path = full_path;
  109. }
  110.  
  111. hCom = CreateFileA(path, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  112.  
  113. if( !hCom || hCom == INVALID_HANDLE_VALUE ) {
  114. return -1;
  115. } else {
  116. return (int)hCom;
  117. }
  118. }
  119.  
  120. int __stdcall select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfs, const struct timeval* timeout)
  121. {
  122. time_t maxtc = time(0) + (timeout->tv_sec);
  123. COMSTAT cs = {0};
  124. unsigned long dwErrors = 0;
  125.  
  126. if( readfds->fd_count != 1 ) {
  127. return -1;
  128. }
  129.  
  130. while( time(0) <= maxtc )
  131. { //only one file supported
  132. if( ClearCommError( (HANDLE)readfds->fd_array[0], 0, &cs) != TRUE ){
  133. return -1;
  134. }
  135.  
  136. if( cs.cbInQue > 0 ) {
  137. return 1;
  138. }
  139.  
  140. Sleep(10);
  141. }
  142. return 0;
  143. }
  144.  
  145. unsigned int sleep(unsigned int sec)
  146. {
  147. Sleep(sec * 1000);
  148.  
  149. return 0;
  150. }
  151.  
  152. #else
  153. #include <unistd.h>
  154. #include <termios.h>
  155. #include <sys/select.h>
  156. #include <sys/types.h>
  157. #include <sys/time.h>
  158. #endif
  159.  
  160. /* macro definitions */
  161.  
  162. #if !defined OS
  163. #define OS UNKNOWN
  164. #endif
  165.  
  166. #define BOOTLOADER_HELLO_STR "\xC1"
  167. #define BOOTLOADER_OK 0x4B
  168. #define BOOTLOADER_PLACEMENT 1
  169.  
  170. #define PIC_FLASHSIZE 0xAC00
  171.  
  172. #define PIC_NUM_PAGES 512
  173. #define PIC_NUM_ROWS_IN_PAGE 8
  174. #define PIC_NUM_WORDS_IN_ROW 64
  175.  
  176. #define PIC_WORD_SIZE (3)
  177. #define PIC_ROW_SIZE (PIC_NUM_WORDS_IN_ROW * PIC_WORD_SIZE)
  178. #define PIC_PAGE_SIZE (PIC_NUM_ROWS_IN_PAGE * PIC_ROW_SIZE)
  179.  
  180.  
  181. #define PIC_ROW_ADDR(p,r) (((p) * PIC_PAGE_SIZE) + ((r) * PIC_ROW_SIZE))
  182. #define PIC_WORD_ADDR(p,r,w) (PIC_ROW_ADDR(p,r) + ((w) * PIC_WORD_SIZE))
  183. #define PIC_PAGE_ADDR(p) (PIC_PAGE_SIZE * (p))
  184.  
  185. #define PAYLOAD_OFFSET 5
  186. #define HEADER_LENGTH PAYLOAD_OFFSET
  187. #define LENGTH_OFFSET 4
  188. #define COMMAND_OFFSET 3
  189.  
  190. /* type definitions */
  191.  
  192. typedef unsigned char uint8;
  193. typedef unsigned short uint16;
  194. typedef unsigned long uint32;
  195.  
  196. /* global settings, command line arguments */
  197.  
  198. uint8 g_verbose = 0;
  199. uint8 g_hello_only = 0;
  200. uint8 g_simulate = 0;
  201. const char* g_device_path = NULL;
  202. const char* g_hexfile_path = NULL;
  203.  
  204. /* functions */
  205.  
  206. int readWithTimeout(int fd, uint8* out, int length, int timeout)
  207. {
  208. fd_set fds;
  209. struct timeval tv = {timeout, 0};
  210. int res = -1;
  211. int got = 0;
  212.  
  213. do {
  214.  
  215. FD_ZERO(&fds);
  216. FD_SET(fd, &fds);
  217.  
  218. res = select(fd + 1, &fds, NULL, NULL, &tv);
  219.  
  220. if( res > 0 ) {
  221. res = read(fd, out, length);
  222. if( res > 0 ) {
  223. length -= res;
  224. got += res;
  225. out += res;
  226. } else {
  227. break;
  228. }
  229. } else {
  230. return res;
  231. }
  232. } while( length > 0);
  233.  
  234. return got;
  235. }
  236.  
  237. unsigned char hexdec(const char* pc)
  238. { unsigned char temp;
  239.  
  240. if(pc[0]>='a'){
  241. temp=pc[0]-'a'+10;
  242. }else if(pc[0] >= 'A'){
  243. temp=pc[0]-'A'+10;
  244. }else{
  245. temp=pc[0] - '0';
  246. }
  247. temp=temp<<4;
  248.  
  249. if(pc[1]>='a'){
  250. temp|=pc[1]-'a'+10;
  251. }else if(pc[1] >= 'A'){
  252. temp|=pc[1]-'A'+10;
  253. }else{
  254. temp|=pc[1] - '0';
  255. }
  256.  
  257. return(temp & 0x0FF);
  258.  
  259.  
  260. //return (((pc[0] >= 'A') ? ( pc[0] - 'A' + 10 ) : ( pc[0] - '0' ) ) << 4 |
  261. // ((pc[1] >= 'A') ? ( pc[1] - 'A' + 10 ) : ( pc[1] - '0' ) )) & 0x0FF;
  262.  
  263. }
  264.  
  265. void dumpHex(uint8* buf, uint32 len)
  266. {
  267. uint32 i=0;
  268.  
  269. for(i=0; i<len; i++){
  270. printf("%02X ", buf[i]);
  271. }
  272. putchar('\n');
  273. }
  274.  
  275. int readHEX(const char* file, uint8* bout, unsigned long max_length, uint8* pages_used)
  276. {
  277. static const uint32 HEX_DATA_OFFSET = 4;
  278. uint8 linebin[256] = {0};
  279. uint8* data = (linebin + HEX_DATA_OFFSET);
  280. uint8 hex_crc, hex_type, hex_len;
  281. uint32 hex_addr;
  282. uint32 hex_base_addr = 0;
  283. uint32 hex_words = 0;
  284.  
  285. uint32 f_addr = 0;
  286. uint32 o_addr = 0;
  287.  
  288. uint32 num_words = 0;
  289.  
  290. char line[512] = {0};
  291. char *pc;
  292. char *pline = line + 1;
  293. int res = 0;
  294. int binlen = 0;
  295. int line_no = 0;
  296. int i = 0;
  297.  
  298. FILE* fp = fopen(file, "rb");
  299.  
  300. if( !fp ) {
  301. return -1;
  302. }
  303.  
  304. while( !feof(fp) && fgets(line, sizeof(line) - 1, fp) )
  305. {
  306. line_no++;
  307.  
  308. if( line[0] != ':' ) {
  309. break;
  310. }
  311.  
  312. res = strlen(pline);
  313. pc = pline + res - 1;
  314.  
  315. while( pc > pline && *pc <= ' ' ) {
  316. *pc-- = 0;
  317. res--;
  318. }
  319.  
  320. if( res & 0x01 || res > 512 || res < 10) {
  321. fprintf(stderr, "Incorrect number of characters on line %d:%d\n", line_no, res);
  322. return -1;
  323. }
  324.  
  325. hex_crc = 0;
  326.  
  327. for( pc = pline, i = 0; i<res; i+=2, pc+=2 ) {
  328. linebin[i >> 1] = hexdec(pc);
  329. hex_crc += linebin[i >> 1];
  330. }
  331.  
  332. binlen = res / 2;
  333.  
  334. if( hex_crc != 0 ) {
  335. fprintf(stderr, "Checksum does not match, line %d\n", line_no);
  336. return -1;
  337. }
  338.  
  339. hex_addr = (linebin[1] << 8) | linebin[2];
  340. hex_len = linebin[0];
  341. hex_type = linebin[3];
  342.  
  343. if( binlen - (1 + 2 + 1 + hex_len + 1) != 0 ) {
  344. fprintf(stderr, "Incorrect number of bytes, line %d\n", line_no);
  345. return -1;
  346. }
  347.  
  348. if( hex_type == 0x00 )
  349. {
  350. f_addr = (hex_base_addr | (hex_addr)) / 2; //PCU
  351.  
  352. if( hex_len % 4 ) {
  353. fprintf(stderr, "Misaligned data, line %d\n", line_no);
  354. return -1;
  355. } else if( f_addr >= PIC_FLASHSIZE ) {
  356. fprintf(stderr, "Current record address is higher than maximum allowed, line %d\n", line_no);
  357. return -1;
  358. }
  359.  
  360. hex_words = hex_len / 4;
  361. o_addr = (f_addr / 2) * PIC_WORD_SIZE; //BYTES
  362.  
  363. for( i=0; i<hex_words; i++)
  364. {
  365. bout[o_addr + 0] = data[(i*4) + 2];
  366. bout[o_addr + 1] = data[(i*4) + 0];
  367. bout[o_addr + 2] = data[(i*4) + 1];
  368.  
  369. pages_used[ (o_addr / PIC_PAGE_SIZE) ] = 1;
  370.  
  371. o_addr += PIC_WORD_SIZE;
  372. num_words ++;
  373. }
  374.  
  375. } else if ( hex_type == 0x04 && hex_len == 2) {
  376. hex_base_addr = (linebin[4] << 24) | (linebin[5] << 16);
  377. } else if ( hex_type == 0x01 ) {
  378. break; //EOF
  379. } else {
  380. fprintf(stderr, "Unsupported record type %02x, line %d\n", hex_type, line_no);
  381. return -1;
  382. }
  383.  
  384. }
  385.  
  386. fclose(fp);
  387. return num_words;
  388. }
  389.  
  390. uint8 makeCrc(uint8* buf, uint32 len)
  391. {
  392. uint8 crc = 0, i = 0;
  393.  
  394. for(i=0; i<len; i++){
  395. crc -= *buf++;
  396. }
  397.  
  398. return crc;
  399. }
  400.  
  401. int sendCommandAndWaitForResponse(int fd, uint8 *command)
  402. {
  403. uint8 response[4] = {0};
  404. int res = 0;
  405.  
  406. res = write(fd, command, HEADER_LENGTH + command[LENGTH_OFFSET]);
  407.  
  408. if( res <= 0 ) {
  409. puts("ERROR");
  410. return -1;
  411. }
  412.  
  413. res = readWithTimeout(fd, response, 1, 5);
  414. if( res != 1 ) {
  415. puts("ERROR");
  416. return -1;
  417. } else if ( response[0] != BOOTLOADER_OK ) {
  418. printf("ERROR [%02x]\n", response[0]);
  419. return -1;
  420. } else {
  421. return 0;
  422. }
  423. }
  424.  
  425.  
  426. int sendFirmware(int fd, uint8* data, uint8* pages_used)
  427. {
  428. uint32 u_addr;
  429.  
  430.  
  431. uint32 page = 0;
  432. uint32 done = 0;
  433. uint32 row = 0;
  434. uint8 command[256] = {0};
  435.  
  436.  
  437. for( page=0; page<PIC_NUM_PAGES; page++)
  438. {
  439.  
  440. u_addr = page * ( PIC_NUM_WORDS_IN_ROW * 2 * PIC_NUM_ROWS_IN_PAGE );
  441.  
  442. if( pages_used[page] != 1 ) {
  443. if( g_verbose && u_addr < PIC_FLASHSIZE) {
  444. fprintf(stdout, "Skipping page %ld [ %06lx ], not used\n", page, u_addr);
  445. }
  446. continue;
  447. }
  448.  
  449. if( u_addr >= PIC_FLASHSIZE ) {
  450. fprintf(stderr, "Address out of flash\n");
  451. return -1;
  452. }
  453.  
  454. //erase page
  455. command[0] = (u_addr & 0x00FF0000) >> 16;
  456. command[1] = (u_addr & 0x0000FF00) >> 8;
  457. command[2] = (u_addr & 0x000000FF) >> 0;
  458. command[COMMAND_OFFSET] = 0x01; //erase command
  459. command[LENGTH_OFFSET ] = 0x01; //1 byte, CRC
  460. command[PAYLOAD_OFFSET] = makeCrc(command, 5);
  461.  
  462. if( g_verbose ) {
  463. dumpHex(command, HEADER_LENGTH + command[LENGTH_OFFSET]);
  464. }
  465.  
  466. printf("Erasing page %ld, %04lx...", page, u_addr);
  467.  
  468. if( g_simulate == 0 && sendCommandAndWaitForResponse(fd, command) < 0 ) {
  469. return -1;
  470. }
  471.  
  472. puts("OK");
  473.  
  474. //write 8 rows
  475. for( row = 0; row < PIC_NUM_ROWS_IN_PAGE; row ++, u_addr += (PIC_NUM_WORDS_IN_ROW * 2))
  476. {
  477. command[0] = (u_addr & 0x00FF0000) >> 16;
  478. command[1] = (u_addr & 0x0000FF00) >> 8;
  479. command[2] = (u_addr & 0x000000FF) >> 0;
  480. command[COMMAND_OFFSET] = 0x02; //write command
  481. command[LENGTH_OFFSET ] = PIC_ROW_SIZE + 0x01; //DATA_LENGTH + CRC
  482.  
  483. memcpy(&command[PAYLOAD_OFFSET], &data[PIC_ROW_ADDR(page, row)], PIC_ROW_SIZE);
  484.  
  485. command[PAYLOAD_OFFSET + PIC_ROW_SIZE] = makeCrc(command, HEADER_LENGTH + PIC_ROW_SIZE);
  486.  
  487. printf("Writing page %ld row %ld, %04lx...", page, row + page*PIC_NUM_ROWS_IN_PAGE, u_addr);
  488.  
  489. if( g_simulate == 0 && sendCommandAndWaitForResponse(fd, command) < 0 ) {
  490. return -1;
  491. }
  492.  
  493. puts("OK");
  494.  
  495. sleep(0);
  496.  
  497. if( g_verbose ) {
  498. dumpHex(command, HEADER_LENGTH + command[LENGTH_OFFSET]);
  499. }
  500. done += PIC_ROW_SIZE;
  501. }
  502. }
  503.  
  504. return done;
  505. }
  506.  
  507. void fixJumps(uint8* bin_buff, uint8* pages_used)
  508. {
  509. uint32 iGotoUserAppAdress = 0;
  510. uint32 iGotoUserAppAdressB3 = 0, iIter = 0;
  511. uint32 iBLAddress = 0;
  512.  
  513. iBLAddress = ( PIC_FLASHSIZE - (BOOTLOADER_PLACEMENT * PIC_NUM_ROWS_IN_PAGE * PIC_NUM_WORDS_IN_ROW * 2)); //PCU
  514. iGotoUserAppAdress = iBLAddress - 4;
  515. iGotoUserAppAdressB3 = (iGotoUserAppAdress / 2) * 3;
  516.  
  517. for ( iIter = 0; iIter < 6; iIter++ ) {
  518. bin_buff[ iGotoUserAppAdressB3 + iIter ] = bin_buff[ iIter ];
  519. }
  520.  
  521. pages_used[ (iGotoUserAppAdressB3 / PIC_PAGE_SIZE) ] = 1;
  522.  
  523. bin_buff[0] = 0x04;
  524. bin_buff[1] = ( (iBLAddress & 0x0000FE) );
  525. bin_buff[2] = ( (iBLAddress & 0x00FF00) >> 8 );
  526. bin_buff[3] = 0x00;
  527. bin_buff[4] = ( (iBLAddress & 0x7F0000) >> 16 );
  528. bin_buff[5] = 0x00;
  529. }
  530.  
  531. /* non-firmware functions */
  532.  
  533. int configurePort(int fd, unsigned long baudrate)
  534. {
  535. #ifdef WIN32
  536. DCB dcb = {0};
  537. HANDLE hCom = (HANDLE)fd;
  538.  
  539. dcb.DCBlength = sizeof(dcb);
  540.  
  541. dcb.BaudRate = baudrate;
  542. dcb.ByteSize = 8;
  543. dcb.Parity = NOPARITY;
  544. dcb.StopBits = ONESTOPBIT;
  545.  
  546. if( !SetCommState(hCom, &dcb) ){
  547. return -1;
  548. }
  549.  
  550. return (int)hCom;
  551. #else
  552. struct termios g_new_tio;
  553.  
  554. memset(&g_new_tio, 0x00 , sizeof(g_new_tio));
  555. cfmakeraw(&g_new_tio);
  556.  
  557. g_new_tio.c_cflag |= (CS8 | CLOCAL | CREAD);
  558. g_new_tio.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
  559. g_new_tio.c_oflag = 0;
  560. g_new_tio.c_lflag = 0;
  561.  
  562.  
  563. g_new_tio.c_cc[VTIME] = 0;
  564. g_new_tio.c_cc[VMIN] = 1;
  565.  
  566. cfsetispeed (&g_new_tio, baudrate);
  567. cfsetospeed (&g_new_tio, baudrate);
  568.  
  569. tcflush(fd, TCIOFLUSH);
  570.  
  571. return tcsetattr(fd, TCSANOW, &g_new_tio);
  572. #endif
  573. }
  574.  
  575. int openPort(const char* dev, unsigned long flags)
  576. {
  577. return open(dev, O_RDWR | O_NOCTTY | O_NDELAY | flags);
  578. }
  579.  
  580. int parseCommandLine(int argc, const char** argv)
  581. {
  582. int i = 0;
  583.  
  584. for(i=1; i<argc; i++)
  585. {
  586.  
  587. if( !strncmp(argv[i], "--hex=", 6) ) {
  588. g_hexfile_path = argv[i] + 6;
  589. } else if ( !strncmp(argv[i], "--dev=", 6) ) {
  590. g_device_path = argv[i] + 6;
  591. } else if ( !strcmp(argv[i], "--verbose") ) {
  592. g_verbose = 1;
  593. } else if ( !strcmp(argv[i], "--hello") ) {
  594. g_hello_only = 1;
  595. } else if ( !strcmp(argv[i], "--simulate") ) {
  596. g_simulate = 1;
  597. } else if ( !strcmp(argv[i], "--help") ) {
  598. argc = 1; //that's not pretty, but it works :)
  599. break;
  600. } else {
  601. fprintf(stderr, "Unknown parameter %s, please use pirate-loader --help for usage\n", argv[i]);
  602. return -1;
  603. }
  604. }
  605.  
  606. if( argc == 1 )
  607. {
  608. //print usage
  609. puts("pirate-loader usage:\n");
  610. puts(" ./pirate-loader --dev=/path/to/device --hello");
  611. puts(" ./pirate-loader --dev=/path/to/device --hex=/path/to/hexfile.hex [ --verbose");
  612. puts(" ./pirate-loader --simulate --hex=/path/to/hexfile.hex [ --verbose");
  613. puts("");
  614.  
  615. return 0;
  616. }
  617.  
  618. return 1;
  619. }
  620.  
  621. /* entry point */
  622.  
  623. int main (int argc, const char** argv)
  624. {
  625. int dev_fd = -1, res = -1;
  626. uint8 buffer[256] = {0};
  627. uint8 pages_used[PIC_NUM_PAGES] = {0};
  628. uint8* bin_buff = NULL;
  629.  
  630.  
  631. puts("+++++++++++++++++++++++++++++++++++++++++++");
  632. puts(" Pirate-Loader for BP with Bootloader v4+ ");
  633. puts(" Loader version: " PIRATE_LOADER_VERSION " OS: " OS_NAME(OS));
  634. puts("+++++++++++++++++++++++++++++++++++++++++++\n");
  635.  
  636. if( (res = parseCommandLine(argc, argv)) < 0 ) {
  637. return -1;
  638. } else if( res == 0 ) {
  639. return 0;
  640. }
  641.  
  642. if( !g_hello_only ) {
  643.  
  644. if( !g_hexfile_path ) {
  645. fprintf(stderr, "Please specify hexfile path --hex=/path/to/hexfile.hex\n");
  646. return -1;
  647. }
  648.  
  649. bin_buff = (uint8*)malloc(256 << 10); //256kB
  650. if( !bin_buff ) {
  651. fprintf(stderr, "Could not allocate 256kB buffer\n");
  652. goto Error;
  653. }
  654.  
  655. //fill the buffer with 0xFF
  656. memset(bin_buff, 0xFFFFFFFF, (256 << 10));
  657.  
  658. printf("Parsing HEX file [%s]\n", g_hexfile_path);
  659.  
  660. res = readHEX(g_hexfile_path, bin_buff, (256 << 8), pages_used);
  661. if( res <= 0 || res > PIC_FLASHSIZE ) {
  662. fprintf(stderr, "Could not load HEX file, result=%d\n", res);
  663. goto Error;
  664. }
  665.  
  666. printf("Found %d words (%d bytes)\n", res, res * 3);
  667.  
  668. printf("Fixing bootloader/userprogram jumps\n");
  669. fixJumps(bin_buff, pages_used);
  670. }
  671.  
  672. if( g_simulate ) {
  673. sendFirmware(dev_fd, bin_buff, pages_used);
  674. goto Finished;
  675. }
  676.  
  677. if( !g_device_path ) {
  678. fprintf(stderr, "Please specify serial device path --dev=/dev/...\n");
  679. return -1;
  680. }
  681.  
  682. printf("Opening serial device %s...", g_device_path);
  683.  
  684. dev_fd = openPort(g_device_path, 0);
  685.  
  686. if( dev_fd < 0 ) {
  687. puts("ERROR");
  688. fprintf(stderr, "Could not open %s\n", g_device_path);
  689. goto Error;
  690. }
  691. puts("OK");
  692.  
  693. printf("Configuring serial port settings...");
  694.  
  695. if( configurePort(dev_fd, B115200) < 0 ) {
  696. puts("ERROR");
  697. fprintf(stderr, "Could not configure device, errno=%d\n", errno);
  698. goto Error;
  699. }
  700. puts("OK");
  701.  
  702. printf("Sending Hello to the Bootloader...");
  703.  
  704. //send HELLO
  705. res = write(dev_fd, BOOTLOADER_HELLO_STR, 1);
  706.  
  707. res = readWithTimeout(dev_fd, buffer, 4, 3);
  708.  
  709. if( res != 4 || buffer[3] != BOOTLOADER_OK ) {
  710. puts("ERROR");
  711. fprintf(stderr, "No reply from the bootloader, or invalid reply received: %d\n", res);
  712. fprintf(stderr, "Please make sure that PGND and PGC are connected, replug the devide and try again\n");
  713. goto Error;
  714. }
  715. puts("OK\n"); //extra LF for spacing
  716.  
  717. printf("Device ID: %s [%02x]\n", (buffer[0] == 0xD4) ? "PIC24FJ64GA002" : "UNKNOWN", buffer[0]);
  718. printf("Bootloader version: %d,%02d\n", buffer[1], buffer[2]);
  719.  
  720. if( buffer[0] != 0xD4 ) {
  721. fprintf(stderr, "Unsupported device (%02x:UNKNOWN), only 0xD4 PIC24FJ64GA002 is supported\n", buffer[0]);
  722. goto Error;
  723. }
  724.  
  725. if( !g_hello_only ) {
  726.  
  727. res = sendFirmware(dev_fd, bin_buff, pages_used);
  728.  
  729. if( res > 0 ) {
  730. puts("\nFirmware updated successfully :)!");
  731. printf("Use screen %s 115200 to verify\n", g_device_path);
  732. } else {
  733. puts("\nError updating firmware :(");
  734. goto Error;
  735. }
  736.  
  737. }
  738.  
  739. Finished:
  740. if( bin_buff ) {
  741. free( bin_buff );
  742. }
  743. close(dev_fd);
  744. return 0;
  745.  
  746. Error:
  747. if( bin_buff ) {
  748. free( bin_buff );
  749. }
  750. if( dev_fd >= 0 ) {
  751. close(dev_fd);
  752. }
  753. return -1;
  754. }
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
+++++++++++++++++++++++++++++++++++++++++++
  Pirate-Loader for BP with Bootloader v4+  
  Loader version: 1.0.2  OS: UNKNOWN
+++++++++++++++++++++++++++++++++++++++++++

pirate-loader usage:

 ./pirate-loader --dev=/path/to/device --hello
 ./pirate-loader --dev=/path/to/device --hex=/path/to/hexfile.hex [ --verbose
 ./pirate-loader --simulate --hex=/path/to/hexfile.hex [ --verbose