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.
 
 

321 lines
8.7 KiB

  1. /***************************************************************************
  2. * Copyright (C) 10/2010 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License, *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <getopt.h>
  24. #include "filedata.h"
  25. #include "list.h"
  26. #include "multiboot.h"
  27. #include "optarg.h"
  28. #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
  29. #define ACTION_READ 0x01
  30. #define ACTION_WRITE 0x02
  31. struct mboot_action {
  32. struct list_head list;
  33. char *filename;
  34. int memtype;
  35. int mode;
  36. };
  37. static LIST_HEAD(action_list);
  38. static struct option main_optargs[] = {
  39. {"help", 0, 0, 'h'}, /* [ -h ] */
  40. {"progress", 1, 0, 'p'}, /* [ -p <0|1|2> ] */
  41. {"read", 1, 0, 'r'}, /* [ -r <flash|eeprom>:<file.hex> ] */
  42. {"write", 1, 0, 'w'}, /* [ -w <flash|eeprom>:<file.hex> ] */
  43. {"no-verify", 0, 0, 'n'}, /* [ -n ] */
  44. {0, 0, 0, 0}
  45. };
  46. static void progress_mode0_cb(const char *msg, int pos, int size)
  47. {
  48. /* no progress output */
  49. }
  50. static void progress_mode1_cb(const char *msg, int pos, int size)
  51. {
  52. if (pos != -1 && size != -1) {
  53. char stars[50];
  54. int i;
  55. int count = (pos * sizeof(stars) / size);
  56. for (i = 0; i < sizeof(stars); i++)
  57. stars[i] = (i < count) ? '*' : ' ';
  58. printf("%-15s: [%s] (%d)\r", msg, stars, pos);
  59. }
  60. if (pos == size)
  61. printf("\n");
  62. }
  63. static void progress_mode2_cb(const char *msg, int pos, int size)
  64. {
  65. static int old_count;
  66. if (pos != -1 && size != -1) {
  67. if (pos == 0) {
  68. old_count = 0;
  69. printf("%-15s: [", msg);
  70. } else if (pos <=size) {
  71. int i;
  72. int count = (pos * 50 / size);
  73. for (i = old_count; i < count; i++)
  74. printf("*");
  75. old_count = count;
  76. if (pos == size) {
  77. printf("] (%d)\n", pos);
  78. }
  79. }
  80. }
  81. }
  82. static int add_action(struct multiboot *mboot, int mode, const char *arg)
  83. {
  84. struct mboot_action *action = malloc(sizeof(struct mboot_action));
  85. if (action == NULL) {
  86. perror("malloc()");
  87. return -1;
  88. }
  89. char *argcopy = strdup(arg);
  90. if (argcopy == NULL) {
  91. perror("strdup()");
  92. free(action);
  93. return -1;
  94. }
  95. char *tok = strtok(argcopy, ":");
  96. if (tok == NULL) {
  97. fprintf(stderr, "invalid argument: '%s'\n", arg);
  98. free(argcopy);
  99. free(action);
  100. return -1;
  101. }
  102. action->memtype = mboot->ops->get_memtype(mboot, tok);
  103. if (action->memtype == -1) {
  104. fprintf(stderr, "invalid memtype: '%s'\n", tok);
  105. free(argcopy);
  106. free(action);
  107. return -1;
  108. }
  109. tok = strtok(NULL, ":");
  110. if (tok == NULL) {
  111. fprintf(stderr, "invalid argument: '%s'\n", arg);
  112. free(argcopy);
  113. free(action);
  114. return -1;
  115. }
  116. action->filename = strdup(tok);
  117. if (action->filename == NULL) {
  118. perror("strdup()");
  119. free(argcopy);
  120. free(action);
  121. return -1;
  122. }
  123. action->mode = mode;
  124. list_add_tail(&action->list, &action_list);
  125. free(argcopy);
  126. return 0;
  127. }
  128. static int main_optarg_cb(int val, const char *arg, void *privdata)
  129. {
  130. struct multiboot *mboot = (struct multiboot *)privdata;
  131. switch (val) {
  132. case 'r': /* read */
  133. {
  134. if (add_action(mboot, ACTION_READ, arg) < 0)
  135. return -1;
  136. }
  137. break;
  138. case 'w': /* write */
  139. {
  140. if (add_action(mboot, ACTION_WRITE, arg) < 0)
  141. return -1;
  142. }
  143. break;
  144. case 'n': /* no verify after write */
  145. mboot->verify = 0;
  146. break;
  147. case 'p':
  148. {
  149. switch (*arg) {
  150. case '0':
  151. mboot->progress_cb = progress_mode0_cb;
  152. break;
  153. case '1':
  154. mboot->progress_cb = progress_mode1_cb;
  155. break;
  156. case '2':
  157. mboot->progress_cb = progress_mode2_cb;
  158. break;
  159. default:
  160. fprintf(stderr, "invalid progress bar mode: '%s'\n", arg);
  161. return -1;
  162. }
  163. }
  164. break;
  165. }
  166. return 0;
  167. }
  168. int main(int argc, char *argv[])
  169. {
  170. struct multiboot *mboot;
  171. char *progname = strrchr(argv[0], '/');
  172. progname = (progname != NULL) ? (progname +1) : argv[0];
  173. if (strcmp(progname, "twiboot") == 0) {
  174. mboot = twi_ops.alloc();
  175. } else if (strcmp(progname, "mpmboot") == 0) {
  176. mboot = mpm_ops.alloc();
  177. } else {
  178. fprintf(stderr, "invalid progname, use 'twiboot' or 'mpmboot'\n");
  179. return -1;
  180. }
  181. if (mboot == NULL)
  182. return -1;
  183. mboot->verify = 1;
  184. mboot->progress_cb = progress_mode1_cb;
  185. optarg_register(main_optargs, ARRAY_SIZE(main_optargs), main_optarg_cb, (void *)mboot);
  186. int abort = optarg_parse(argc, argv);
  187. if (abort == -1 || mboot->ops->open(mboot) != 0)
  188. return -1;
  189. setbuf(stdout, NULL);
  190. struct mboot_action *action, *tmp;
  191. list_for_each_entry(action, &action_list, list) {
  192. abort = 1;
  193. if (action->mode == ACTION_READ) {
  194. int memsize = mboot->ops->get_memsize(mboot, action->memtype);
  195. if (memsize == 0)
  196. break;
  197. struct databuf *dbuf = dbuf_alloc(memsize);
  198. if (dbuf == NULL)
  199. break;
  200. int result = mboot->ops->read(mboot, dbuf, action->memtype);
  201. if (result != 0) {
  202. fprintf(stderr, "failed to read from device\n");
  203. dbuf_free(dbuf);
  204. break;
  205. }
  206. result = file_write(action->filename, dbuf);
  207. if (result != 0) {
  208. fprintf(stderr, "failed to write file '%s'\n", action->filename);
  209. dbuf_free(dbuf);
  210. break;
  211. }
  212. dbuf_free(dbuf);
  213. abort = 0;
  214. } else if (action->mode == ACTION_WRITE) {
  215. unsigned int size;
  216. int result;
  217. result = file_getsize(action->filename, &size);
  218. if (result != 0)
  219. break;
  220. struct databuf *dbuf = dbuf_alloc(size);
  221. if (dbuf == NULL)
  222. break;
  223. result = file_read(action->filename, dbuf);
  224. if (result != 0) {
  225. fprintf(stderr, "failed to read file '%s'\n", action->filename);
  226. dbuf_free(dbuf);
  227. break;
  228. }
  229. int memsize = mboot->ops->get_memsize(mboot, action->memtype);
  230. if (memsize == 0) {
  231. fprintf(stderr, "invalid memsize: 0x%04x > 0x%04x\n", dbuf->length, memsize);
  232. dbuf_free(dbuf);
  233. break;
  234. }
  235. result = mboot->ops->write(mboot, dbuf, action->memtype);
  236. if (result != 0) {
  237. fprintf(stderr, "failed to write to device\n");
  238. dbuf_free(dbuf);
  239. break;
  240. }
  241. if (mboot->verify) {
  242. result = mboot->ops->verify(mboot, dbuf, action->memtype);
  243. if (result != 0) {
  244. fprintf(stderr, "failed to verify\n");
  245. dbuf_free(dbuf);
  246. break;
  247. }
  248. }
  249. dbuf_free(dbuf);
  250. abort = 0;
  251. }
  252. }
  253. list_for_each_entry_safe(action, tmp, &action_list, list) {
  254. free(action->filename);
  255. free(action);
  256. }
  257. mboot->ops->close(mboot);
  258. mboot->ops->free(mboot);
  259. optarg_free();
  260. return abort;
  261. }