You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

937 lines
25 KiB

  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <sys/socket.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <termios.h>
  11. #include <sys/time.h>
  12. #include "multiboot.h"
  13. #include "optarg.h"
  14. #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
  15. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  16. #define MEMTYPE_EPROM 1
  17. #define SERIAL_BAUDRATE B115200
  18. #define SERIAL_TIMEOUT 1000
  19. #define SERIAL_TIMEOUT_SYNC 5
  20. #define MSGTYPE_SYNC 0x00 /* trigger { MSGTYPE_ERROR_RSP, 1, ERROR_UNKNOWN_COMMAND } */
  21. #define MSGTYPE_VERSION_REQ 0x01 /* no payload */
  22. #define MSGTYPE_PAGESIZE_REQ 0x02 /* no payload */
  23. #define MSGTYPE_CONFIG_REQ 0x03 /* eprom_type(1), pagesize(1), reset_polarity(1) */
  24. #define MSGTYPE_PROGMODE_REQ 0x04 /* progmode(1) */
  25. #define MSGTYPE_SETADDRESS_REQ 0x05 /* address(3) msb first */
  26. #define MSGTYPE_WRITE_REQ 0x06 /* data(0-pagesize) */
  27. #define MSGTYPE_READ_REQ 0x07 /* length(1) */
  28. #define MSGTYPE_ERROR_RSP 0x80 /* error_code(1) */
  29. #define MSGTYPE_VERSION_RSP 0x81 /* version(?) */
  30. #define MSGTYPE_PAGESIZE_RSP 0x82 /* pagesize(1) */
  31. #define MSGTYPE_CONFIG_RSP 0x83 /* no payload */
  32. #define MSGTYPE_PROGMODE_RSP 0x84 /* no payload */
  33. #define MSGTYPE_SETADDRESS_RSP 0x85 /* no payload */
  34. #define MSGTYPE_WRITE_RSP 0x86 /* no payload */
  35. #define MSGTYPE_READ_RSP 0x87 /* data(0-pagesize) */
  36. #define SUCCESS 0x00
  37. #define ERROR_UNKNOWN_COMMAND 0x01 /* unknown message type */
  38. #define ERROR_NOT_SUPPORTED 0x02 /* command not supported */
  39. #define ERROR_INVALID_MODE 0x03 /* invalid progmode */
  40. #define ERROR_INVALID_PARAMETER 0x04 /* invalid parameter in request */
  41. #define ERROR_INVALID_ADDRESS 0x05 /* write outside of configured region */
  42. #define RESET_POLARITY_LOW 0x00 /* low active reset */
  43. #define RESET_POLARITY_HIGH 0x01 /* high active reset */
  44. #define EPROM_TYPE_2K 0x02 /* 2716 */
  45. #define EPROM_TYPE_4K 0x04 /* 2732 */
  46. #define EPROM_TYPE_8K 0x08 /* 2764 */
  47. #define EPROM_TYPE_16K 0x10 /* 27128 */
  48. #define EPROM_TYPE_32K 0x20 /* 27256 */
  49. #define EPROM_TYPE_64K 0x40 /* 27512 */
  50. #define EPROM_TYPE_128K 0x80 /* 27010 */
  51. #define PROGMODE_DISABLED 0x00 /* target running, no write access to RAM */
  52. #define PROGMODE_ENABLED 0x01 /* target reset, write access to RAM */
  53. struct multiboot_ops eprog_ops;
  54. struct eprog_privdata
  55. {
  56. char * device;
  57. struct termios oldtio;
  58. int fd;
  59. uint8_t version[32];
  60. uint8_t pagesize_max;
  61. uint8_t eprom_type;
  62. uint8_t pagesize;
  63. int reset_polarity;
  64. uint8_t progmode;
  65. };
  66. struct eprog_type
  67. {
  68. const char name[8];
  69. uint8_t eprom_type;
  70. uint8_t pagesize;
  71. };
  72. static struct eprog_type eprom_types[] =
  73. {
  74. { "2716", EPROM_TYPE_2K, 0xFF },
  75. { "2732", EPROM_TYPE_4K, 0xFF },
  76. { "2764", EPROM_TYPE_8K, 0xFF },
  77. { "2864", EPROM_TYPE_8K, 0x40 },
  78. { "27128", EPROM_TYPE_16K, 0xFF },
  79. { "27256", EPROM_TYPE_32K, 0xFF },
  80. { "27512", EPROM_TYPE_64K, 0xFF },
  81. { "27010", EPROM_TYPE_128K, 0xFF },
  82. };
  83. static struct option eprog_optargs[] =
  84. {
  85. { "device", 1, 0, 'd' }, /* [ -d <device> ] */
  86. { "reset", 1, 0, 'x' }, /* [ -x <reset polarity> ] */
  87. { "type", 1, 0, 't' }, /* [ -t <type> ] */
  88. };
  89. /* *************************************************************************
  90. * eprog_optarg_cb
  91. * ************************************************************************* */
  92. static int eprog_optarg_cb(int val, const char *arg, void *privdata)
  93. {
  94. struct eprog_privdata *p_prog = (struct eprog_privdata *)privdata;
  95. switch (val)
  96. {
  97. case 'd': /* device */
  98. if (p_prog->device != NULL)
  99. {
  100. fprintf(stderr, "invalid device: '%s'\n", arg);
  101. return -1;
  102. }
  103. p_prog->device = strdup(optarg);
  104. if (p_prog->device == NULL)
  105. {
  106. perror("strdup()");
  107. return -1;
  108. }
  109. break;
  110. case 'x':
  111. if (strcasecmp(arg, "high") == 0)
  112. {
  113. p_prog->reset_polarity = RESET_POLARITY_HIGH;
  114. }
  115. else if (strcasecmp(arg, "low") == 0)
  116. {
  117. p_prog->reset_polarity = RESET_POLARITY_LOW;
  118. }
  119. else
  120. {
  121. fprintf(stderr, "invalid reset polarity: '%s'\n", arg);
  122. return -1;
  123. }
  124. break;
  125. case 't':
  126. {
  127. unsigned int i;
  128. if (p_prog->eprom_type != 0)
  129. {
  130. fprintf(stderr, "invalid EPROM type: '%s'\n", arg);
  131. return -1;
  132. }
  133. for (i = 0; i < ARRAY_SIZE(eprom_types); i++)
  134. {
  135. if (strcmp(arg, eprom_types[i].name) == 0)
  136. {
  137. p_prog->eprom_type = eprom_types[i].eprom_type;
  138. p_prog->pagesize = eprom_types[i].pagesize;
  139. }
  140. }
  141. if (p_prog->eprom_type == 0)
  142. {
  143. fprintf(stderr, "invalid EPROM type: '%s'\n", arg);
  144. return -1;
  145. }
  146. }
  147. break;
  148. case 'h':
  149. case '?': /* error */
  150. fprintf(stderr, "Usage: eprom_sim [options]\n"
  151. " -d <device> - selects eprom_sim device\n"
  152. " -x <reset polarity> - select 'high' or 'low' active reset\n"
  153. " -t <type> - selects EPROM type (2716 - 27010)\n"
  154. " -r eprom:<file> - reads EPROM to file (.bin | .hex | -)\n"
  155. " -w eprom:<file> - write EPROM from file (.bin | .hex)\n"
  156. " -p <0|1|2> - progress bar mode\n"
  157. "\n"
  158. "Example: eprom_sim -d /dev/ttyUSB0 -t 2764 -r high -w eprom:data.hex\n"
  159. "\n");
  160. return -1;
  161. default:
  162. return 1;
  163. }
  164. return 0;
  165. } /* eprog_optarg_cb */
  166. /* *************************************************************************
  167. * eprog_alloc
  168. * ************************************************************************* */
  169. static struct multiboot * eprog_alloc(void)
  170. {
  171. struct multiboot * mboot = malloc(sizeof(struct multiboot));
  172. if (mboot == NULL)
  173. {
  174. return NULL;
  175. }
  176. memset(mboot, 0x00, sizeof(struct multiboot));
  177. mboot->ops= &eprog_ops;
  178. struct eprog_privdata *p_prog = malloc(sizeof(struct eprog_privdata));
  179. if (p_prog == NULL)
  180. {
  181. free(mboot);
  182. return NULL;
  183. }
  184. memset(p_prog, 0x00, sizeof(struct eprog_privdata));
  185. p_prog->device = NULL;
  186. optarg_register(eprog_optargs, ARRAY_SIZE(eprog_optargs),
  187. eprog_optarg_cb, (void *)p_prog);
  188. mboot->privdata = p_prog;
  189. return mboot;
  190. } /* eprog_alloc */
  191. /* *************************************************************************
  192. * eprog_free
  193. * ************************************************************************* */
  194. static void eprog_free(struct multiboot *mboot)
  195. {
  196. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  197. if (p_prog->device != NULL)
  198. {
  199. free(p_prog->device);
  200. }
  201. free(p_prog);
  202. free(mboot);
  203. } /* eprog_free */
  204. /* *************************************************************************
  205. * eprog_get_memtype
  206. * ************************************************************************* */
  207. static int eprog_get_memtype(struct multiboot *mboot,
  208. const char *memname)
  209. {
  210. /* unused parameter */
  211. (void)mboot;
  212. if (strcmp(memname, "eprom") == 0)
  213. {
  214. return MEMTYPE_EPROM;
  215. }
  216. return -1;
  217. } /* eprog_get_memtype */
  218. /* *************************************************************************
  219. * eprog_get_memsize
  220. * ************************************************************************* */
  221. static int eprog_get_memsize(struct multiboot *mboot,
  222. int memtype)
  223. {
  224. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  225. if (memtype != MEMTYPE_EPROM)
  226. {
  227. return 0;
  228. }
  229. return p_prog->eprom_type * 1024;
  230. } /* eprog_get_memsize */
  231. /* *************************************************************************
  232. * eprog_close_device
  233. * ************************************************************************* */
  234. static void eprog_close_device(struct eprog_privdata *p_prog)
  235. {
  236. /* delay close() / tcsetattr() */
  237. usleep(100000);
  238. tcsetattr(p_prog->fd, TCSANOW, &p_prog->oldtio);
  239. close(p_prog->fd);
  240. } /* eprog_close_device */
  241. /* *************************************************************************
  242. * eprog_open_device
  243. * ************************************************************************* */
  244. static int eprog_open_device(struct eprog_privdata *p_prog)
  245. {
  246. p_prog->fd = open(p_prog->device, O_RDWR | O_NOCTTY | O_CLOEXEC);
  247. if (p_prog->fd < 0)
  248. {
  249. perror("open()");
  250. return -1;
  251. }
  252. if (tcgetattr(p_prog->fd, &p_prog->oldtio) < 0)
  253. {
  254. perror("tcgetattr(oldtio)");
  255. close(p_prog->fd);
  256. return -1;
  257. }
  258. struct termios newtio;
  259. memset(&newtio, 0, sizeof(newtio));
  260. newtio.c_iflag |= IGNBRK;
  261. newtio.c_cflag |= SERIAL_BAUDRATE | CS8 | CLOCAL | CREAD;
  262. newtio.c_cc[VMIN] = 1;
  263. newtio.c_cc[VTIME] = 0;
  264. int err = tcsetattr(p_prog->fd, TCSANOW, &newtio);
  265. if (err < 0)
  266. {
  267. perror("tcsetattr(newtio)");
  268. close(p_prog->fd);
  269. return -1;
  270. }
  271. return 0;
  272. } /* eprog_open_device */
  273. /* *************************************************************************
  274. * eprog_serial_read
  275. * ************************************************************************* */
  276. static int eprog_serial_read(int fd, void * data, int size, unsigned int timeout_ms)
  277. {
  278. int pos = 0;
  279. while (1)
  280. {
  281. fd_set fdset;
  282. struct timeval timeout;
  283. struct timeval * p_timeout = NULL;
  284. FD_ZERO(&fdset);
  285. FD_SET(fd, &fdset);
  286. if (timeout_ms != 0)
  287. {
  288. p_timeout = &timeout;
  289. timeout.tv_sec = timeout_ms / 1000;
  290. timeout.tv_usec = (timeout_ms % 1000) * 1000;
  291. }
  292. int ret = select(fd +1, &fdset, NULL, NULL, p_timeout);
  293. if (ret == -1)
  294. {
  295. perror("select");
  296. return -1;
  297. }
  298. else if (ret == 0)
  299. {
  300. break;
  301. }
  302. else if (FD_ISSET(fd, &fdset))
  303. {
  304. int len = read(fd, data + pos, size - pos);
  305. if (len < 0)
  306. {
  307. return -1;
  308. }
  309. else
  310. {
  311. pos += len;
  312. if (pos == size)
  313. {
  314. break;
  315. }
  316. }
  317. }
  318. }
  319. return pos;
  320. } /* eprog_serial_read */
  321. /* *************************************************************************
  322. * eprog_recv
  323. * ************************************************************************* */
  324. static int eprog_recv(int fd, uint8_t msgtype, uint8_t * data, uint8_t length)
  325. {
  326. uint8_t header[2];
  327. uint8_t dummy[64];
  328. int ret = eprog_serial_read(fd, header, sizeof(header), SERIAL_TIMEOUT);
  329. if (ret < (int)sizeof(header))
  330. {
  331. fprintf(stderr, "short read from device (header)\n");
  332. return -1;
  333. }
  334. uint8_t pos = 0;
  335. uint8_t msgsize = header[1];
  336. while (msgsize > 0)
  337. {
  338. if ((data != NULL) && (pos < length))
  339. {
  340. uint8_t readsize = MIN(msgsize, length - pos);
  341. ret = eprog_serial_read(fd, &data[pos], readsize, SERIAL_TIMEOUT);
  342. if (ret <= 0)
  343. {
  344. fprintf(stderr, "short read from device (payload)\n");
  345. return -1;
  346. }
  347. pos += ret;
  348. }
  349. else
  350. {
  351. uint8_t readsize = MIN(msgsize, sizeof(dummy));
  352. ret = eprog_serial_read(fd, &dummy, readsize, SERIAL_TIMEOUT);
  353. if (ret <= 0)
  354. {
  355. fprintf(stderr, "short read from device (dummy)\n");
  356. return -1;
  357. }
  358. }
  359. msgsize -= ret;
  360. }
  361. if (header[0] != msgtype)
  362. {
  363. if ((header[0] == MSGTYPE_ERROR_RSP) && (header[1] == 1))
  364. {
  365. uint8_t error_code = (data != NULL) ? data[0] : dummy[0];
  366. fprintf(stderr, "expected msgtype 0x%x received ERROR_RSP error_code 0x%x\n",
  367. msgtype, error_code);
  368. }
  369. else
  370. {
  371. fprintf(stderr, "wrong msgtype received (0x%x != 0x%x)\n",
  372. header[0], msgtype);
  373. }
  374. return -1;
  375. }
  376. return pos;
  377. } /* eprog_recv */
  378. /* *************************************************************************
  379. * eprog_sync
  380. * ************************************************************************* */
  381. static int eprog_sync(struct eprog_privdata *p_prog)
  382. {
  383. int sync_count = 255;
  384. while (sync_count > 0)
  385. {
  386. /* send only MSGTYPE, no request length! */
  387. uint8_t request[] = { MSGTYPE_SYNC };
  388. uint8_t response[3];
  389. int ret = write(p_prog->fd, request, sizeof(request));
  390. if (ret <= 0)
  391. {
  392. return ret;
  393. }
  394. ret = eprog_serial_read(p_prog->fd, response, sizeof(response), SERIAL_TIMEOUT_SYNC);
  395. if ((ret == sizeof(response)) &&
  396. (response[0] == MSGTYPE_ERROR_RSP) &&
  397. (response[1] == 1) &&
  398. (response[2] == ERROR_UNKNOWN_COMMAND)
  399. )
  400. {
  401. return 0;
  402. }
  403. sync_count--;
  404. }
  405. return -1;
  406. } /* eprog_sync */
  407. /* *************************************************************************
  408. * eprog_get_version
  409. * ************************************************************************* */
  410. static int eprog_get_version(struct eprog_privdata *p_prog,
  411. uint8_t *version, uint8_t length)
  412. {
  413. uint8_t request[] = { MSGTYPE_VERSION_REQ, 0 };
  414. int ret = write(p_prog->fd, request, sizeof(request));
  415. if (ret <= 0)
  416. {
  417. return ret;
  418. }
  419. ret = eprog_recv(p_prog->fd, MSGTYPE_VERSION_RSP, version, length);
  420. if (ret <= 0)
  421. {
  422. return -1;
  423. }
  424. if (ret < length)
  425. {
  426. version[ret] = '\0';
  427. }
  428. else
  429. {
  430. version[length -1] = '\0';
  431. }
  432. return 0;
  433. } /* eprog_get_version */
  434. /* *************************************************************************
  435. * eprog_get_pagesize
  436. * ************************************************************************* */
  437. static int eprog_get_pagesize(struct eprog_privdata *p_prog,
  438. uint8_t *pagesize)
  439. {
  440. uint8_t request[] = { MSGTYPE_PAGESIZE_REQ, 0 };
  441. uint8_t response[1];
  442. int ret = write(p_prog->fd, request, sizeof(request));
  443. if (ret <= 0)
  444. {
  445. return ret;
  446. }
  447. ret = eprog_recv(p_prog->fd, MSGTYPE_PAGESIZE_RSP, response, sizeof(response));
  448. if (ret != sizeof(response))
  449. {
  450. return -1;
  451. }
  452. *pagesize = response[0];
  453. return 0;
  454. } /* eprog_get_pagesize */
  455. /* *************************************************************************
  456. * eprog_set_config
  457. * ************************************************************************* */
  458. static int eprog_set_config(struct eprog_privdata *p_prog,
  459. uint8_t eprom_type,
  460. uint8_t pagesize,
  461. uint8_t reset_polarity)
  462. {
  463. uint8_t request[] = { MSGTYPE_CONFIG_REQ, 3, eprom_type, pagesize, reset_polarity };
  464. int ret = write(p_prog->fd, request, sizeof(request));
  465. if (ret <= 0)
  466. {
  467. return ret;
  468. }
  469. ret = eprog_recv(p_prog->fd, MSGTYPE_CONFIG_RSP, NULL, 0);
  470. if (ret < 0)
  471. {
  472. return ret;
  473. }
  474. return 0;
  475. } /* eprog_set_config */
  476. /* *************************************************************************
  477. * eprog_set_progmode
  478. * ************************************************************************* */
  479. static int eprog_set_progmode(struct eprog_privdata *p_prog,
  480. uint8_t progmode)
  481. {
  482. uint8_t request[] = { MSGTYPE_PROGMODE_REQ, 1, progmode };
  483. int ret = write(p_prog->fd, request, sizeof(request));
  484. if (ret <= 0)
  485. {
  486. return ret;
  487. }
  488. ret = eprog_recv(p_prog->fd, MSGTYPE_PROGMODE_RSP, NULL, 0);
  489. if (ret < 0)
  490. {
  491. return ret;
  492. }
  493. return 0;
  494. } /* eprog_set_progmode */
  495. /* *************************************************************************
  496. * eprog_set_address
  497. * ************************************************************************* */
  498. static int eprog_set_address(struct eprog_privdata *p_prog,
  499. uint32_t address)
  500. {
  501. uint8_t request[] = { MSGTYPE_SETADDRESS_REQ, 3,
  502. (address >> 16) & 0xFF,
  503. (address >> 8) & 0xFF,
  504. (address >> 0) & 0xFF };
  505. int ret = write(p_prog->fd, request, sizeof(request));
  506. if (ret <= 0)
  507. {
  508. return ret;
  509. }
  510. ret = eprog_recv(p_prog->fd, MSGTYPE_SETADDRESS_RSP, NULL, 0);
  511. if (ret < 0)
  512. {
  513. return ret;
  514. }
  515. return 0;
  516. } /* eprog_set_address */
  517. /* *************************************************************************
  518. * eprog_read_data
  519. * ************************************************************************* */
  520. static int eprog_read_data(struct eprog_privdata *p_prog,
  521. uint8_t * data,
  522. uint8_t length)
  523. {
  524. uint8_t request[] = { MSGTYPE_READ_REQ, 1, length };
  525. int ret = write(p_prog->fd, request, sizeof(request));
  526. if (ret <= 0)
  527. {
  528. return ret;
  529. }
  530. ret = eprog_recv(p_prog->fd, MSGTYPE_READ_RSP, data, length);
  531. if (ret < 0)
  532. {
  533. return ret;
  534. }
  535. return 0;
  536. } /* eprog_read_data */
  537. /* *************************************************************************
  538. * eprog_write_data
  539. * ************************************************************************* */
  540. static int eprog_write_data(struct eprog_privdata *p_prog,
  541. const uint8_t * data,
  542. uint8_t length)
  543. {
  544. uint8_t request[] = { MSGTYPE_WRITE_REQ, length };
  545. int ret = write(p_prog->fd, request, sizeof(request));
  546. if (ret <= 0)
  547. {
  548. return ret;
  549. }
  550. ret = write(p_prog->fd, data, length);
  551. if (ret <= 0)
  552. {
  553. return ret;
  554. }
  555. ret = eprog_recv(p_prog->fd, MSGTYPE_WRITE_RSP, NULL, 0);
  556. if (ret < 0)
  557. {
  558. return ret;
  559. }
  560. return 0;
  561. } /* eprog_write_data */
  562. /* *************************************************************************
  563. * eprog_close
  564. * ************************************************************************* */
  565. static int eprog_close(struct multiboot *mboot)
  566. {
  567. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  568. if (p_prog->progmode == PROGMODE_ENABLED)
  569. {
  570. eprog_set_progmode(p_prog, PROGMODE_DISABLED);
  571. }
  572. eprog_close_device(p_prog);
  573. return 0;
  574. } /* eprog_close */
  575. /* *************************************************************************
  576. * eprog_open
  577. * ************************************************************************* */
  578. static int eprog_open(struct multiboot *mboot)
  579. {
  580. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  581. if (p_prog->device == NULL)
  582. {
  583. fprintf(stderr, "abort: no device given\n");
  584. return -1;
  585. }
  586. if (p_prog->eprom_type == 0)
  587. {
  588. fprintf(stderr, "abort: no EPROM type given\n");
  589. return -1;
  590. }
  591. if (eprog_open_device(p_prog) < 0)
  592. {
  593. return -1;
  594. }
  595. if (eprog_sync(p_prog) < 0)
  596. {
  597. fprintf(stderr, "failed to sync\n");
  598. eprog_close_device(p_prog);
  599. return -1;
  600. }
  601. if (eprog_get_version(p_prog, p_prog->version, sizeof(p_prog->version)) < 0)
  602. {
  603. fprintf(stderr, "failed to get version\n");
  604. eprog_close_device(p_prog);
  605. return -1;
  606. }
  607. if ((eprog_get_pagesize(p_prog, &p_prog->pagesize_max) < 0) ||
  608. (p_prog->pagesize_max == 0)
  609. )
  610. {
  611. fprintf(stderr, "failed to get pagesize\n");
  612. eprog_close_device(p_prog);
  613. return -1;
  614. }
  615. p_prog->pagesize = MIN(p_prog->pagesize, p_prog->pagesize_max);
  616. if (eprog_set_config(p_prog, p_prog->eprom_type, p_prog->pagesize, p_prog->reset_polarity) < 0)
  617. {
  618. fprintf(stderr, "failed to set configuration\n");
  619. eprog_close_device(p_prog);
  620. return -1;
  621. }
  622. if (eprog_set_progmode(p_prog, PROGMODE_ENABLED) < 0)
  623. {
  624. fprintf(stderr, "failed to enter progmode\n");
  625. eprog_close_device(p_prog);
  626. return -1;
  627. }
  628. p_prog->progmode = PROGMODE_ENABLED;
  629. printf("device : %-16s\n",
  630. p_prog->device);
  631. printf("version : %-32s\n",
  632. p_prog->version);
  633. printf("reset polarity : %-4s\n",
  634. p_prog->reset_polarity ? "high" : "low");
  635. printf("EPROM size : 0x%05x (%d)\n",
  636. p_prog->eprom_type * 1024,
  637. p_prog->eprom_type * 1024);
  638. return 0;
  639. } /* eprog_open */
  640. /* *************************************************************************
  641. * eprog_read
  642. * ************************************************************************* */
  643. static int eprog_read(struct multiboot *mboot,
  644. struct databuf *dbuf, int memtype)
  645. {
  646. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  647. char *progress_msg = "reading EPROM";
  648. /* unused parameter */
  649. (void)memtype;
  650. uint32_t pos = 0;
  651. uint32_t size = p_prog->eprom_type * 1024;
  652. if (eprog_set_address(p_prog, pos) < 0)
  653. {
  654. fprintf(stderr, "failed to set address\n");
  655. return -1;
  656. }
  657. while (pos < size)
  658. {
  659. mboot->progress_cb(progress_msg, pos, size);
  660. uint8_t len = MIN(p_prog->pagesize_max, size - pos);
  661. if (eprog_read_data(p_prog, dbuf->data + pos, len))
  662. {
  663. mboot->progress_cb(progress_msg, -1, -1);
  664. return -1;
  665. }
  666. pos += len;
  667. }
  668. dbuf->length = pos;
  669. mboot->progress_cb(progress_msg, pos, size);
  670. return 0;
  671. } /* eprog_read */
  672. /* *************************************************************************
  673. * eprog_write
  674. * ************************************************************************* */
  675. static int eprog_write(struct multiboot *mboot,
  676. struct databuf *dbuf,
  677. int memtype)
  678. {
  679. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  680. char *progress_msg = "writing EPROM";
  681. /* unused parameter */
  682. (void)memtype;
  683. uint32_t pos = 0;
  684. if (eprog_set_address(p_prog, pos) < 0)
  685. {
  686. fprintf(stderr, "failed to set address\n");
  687. return -1;
  688. }
  689. while (pos < dbuf->length)
  690. {
  691. mboot->progress_cb(progress_msg, pos, dbuf->length);
  692. uint8_t len = MIN(p_prog->pagesize, dbuf->length - pos);
  693. if (eprog_write_data(p_prog, dbuf->data + pos, len))
  694. {
  695. mboot->progress_cb(progress_msg, -1, -1);
  696. return -1;
  697. }
  698. pos += len;
  699. }
  700. mboot->progress_cb(progress_msg, pos, dbuf->length);
  701. return 0;
  702. } /* eprog_write */
  703. /* *************************************************************************
  704. * eprog_verify
  705. * ************************************************************************* */
  706. static int eprog_verify(struct multiboot *mboot,
  707. struct databuf *dbuf, int memtype)
  708. {
  709. struct eprog_privdata *p_prog = (struct eprog_privdata *)mboot->privdata;
  710. char *progress_msg = "verifing EPROM";
  711. /* unused parameter */
  712. (void)memtype;
  713. uint32_t pos = 0;
  714. uint8_t comp[256];
  715. if (eprog_set_address(p_prog, pos) < 0)
  716. {
  717. fprintf(stderr, "failed to set address\n");
  718. return -1;
  719. }
  720. while (pos < dbuf->length)
  721. {
  722. mboot->progress_cb(progress_msg, pos, dbuf->length);
  723. uint8_t len = MIN(p_prog->pagesize, dbuf->length - pos);
  724. if (eprog_read_data(p_prog, comp, len))
  725. {
  726. mboot->progress_cb(progress_msg, -1, -1);
  727. return -1;
  728. }
  729. if (memcmp(comp, dbuf->data + pos, len) != 0x00)
  730. {
  731. mboot->progress_cb(progress_msg, -1, -1);
  732. fprintf(stderr, "verify failed at pos 0x%04x!!\n", pos);
  733. return -1;
  734. }
  735. pos += len;
  736. }
  737. dbuf->length = pos;
  738. mboot->progress_cb(progress_msg, pos, dbuf->length);
  739. return 0;
  740. } /* eprog_verify */
  741. struct multiboot_ops eprog_ops =
  742. {
  743. .exec_name = "eprom_prog",
  744. .alloc = eprog_alloc,
  745. .free = eprog_free,
  746. .get_memtype = eprog_get_memtype,
  747. .get_memsize = eprog_get_memsize,
  748. .open = eprog_open,
  749. .close = eprog_close,
  750. .read = eprog_read,
  751. .write = eprog_write,
  752. .verify = eprog_verify,
  753. };