chknvm2.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. * system header files;
  10. *--------------------------------------------------------------------*/
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <memory.h>
  15. #include <fcntl.h>
  16. #include <errno.h>
  17. /*====================================================================*
  18. * custom header files;
  19. *--------------------------------------------------------------------*/
  20. #include "../tools/getoptv.h"
  21. #include "../tools/memory.h"
  22. #include "../tools/flags.h"
  23. #include "../tools/error.h"
  24. #include "../tools/files.h"
  25. #include "../ram/sdram.h"
  26. #include "../nvm/nvm.h"
  27. /*====================================================================*
  28. * custom source files;
  29. *--------------------------------------------------------------------*/
  30. #ifndef MAKEFILE
  31. #include "../tools/getoptv.c"
  32. #include "../tools/putoptv.c"
  33. #include "../tools/version.c"
  34. #include "../tools/checksum32.c"
  35. #include "../tools/strfbits.c"
  36. #include "../tools/error.c"
  37. #endif
  38. #ifndef MAKEFILE
  39. #include "../nvm/nvm.c"
  40. #include "../nvm/nvmpeek.c"
  41. #include "../nvm/lightning_nvm_peek.c"
  42. #include "../nvm/panther_nvm_peek.c"
  43. #include "../nvm/panther_nvm_manifest.c"
  44. #include "../nvm/panther_nvm_revision.c"
  45. #endif
  46. /*====================================================================*
  47. * program constants;
  48. *--------------------------------------------------------------------*/
  49. #define HARDWARE 0
  50. #define SOFTWARE 1
  51. #define VER 2
  52. #define REV 3
  53. #define BUILD 6
  54. #define DATE 7
  55. /*====================================================================*
  56. *
  57. * unsigned string2vector (char ** vector, length, char * string, char c);
  58. *
  59. * convert string to a vector and return vector count; split string
  60. * on character (c);
  61. *
  62. * Contributor(s):
  63. * Charles Maier <cmaier@qca.qualcomm.com>
  64. *
  65. *--------------------------------------------------------------------*/
  66. static unsigned string2vector (char ** vector, char * string, char c)
  67. {
  68. char ** origin = vector;
  69. for (* vector++ = string; * string; string++)
  70. {
  71. if (* string == c)
  72. {
  73. * string++ = (char) (0);
  74. * vector++ = string--;
  75. }
  76. }
  77. * vector = (char *) (0);
  78. return ((unsigned) (vector - origin));
  79. }
  80. /*====================================================================*
  81. *
  82. * void firmware (char const * filename, unsigned module, char const * memory, unsigned offset, flag_t flags);
  83. *
  84. * locate and display information stored in a firmware image; this
  85. * legacy method has changed in current firmware releases;
  86. *
  87. * Contributor(s):
  88. * Charles Maier <cmaier@qca.qualcomm.com>
  89. *
  90. *--------------------------------------------------------------------*/
  91. static void firmware (char const * filename, unsigned module, char const * memory, unsigned offset, flag_t flags)
  92. {
  93. if (_anyset (flags, NVM_REVISION))
  94. {
  95. if (_anyset (flags, NVM_VERBOSE))
  96. {
  97. printf ("%s (%d) ", filename, module);
  98. }
  99. if ((* memory > 0x20) && (* memory < 0x7f))
  100. {
  101. printf ("%s\n", memory);
  102. }
  103. else
  104. {
  105. printf ("%s\n", memory + offset);
  106. }
  107. return;
  108. }
  109. if (_anyset (flags, NVM_IDENTITY))
  110. {
  111. char * vector [16];
  112. char buffer [256];
  113. if ((* memory > 0x20) && (* memory < 0x7f))
  114. {
  115. strncpy (buffer, memory, sizeof (buffer));
  116. }
  117. else
  118. {
  119. strncpy (buffer, memory + offset, sizeof (buffer));
  120. }
  121. string2vector (vector, buffer, '-');
  122. printf ("%s ", vector [HARDWARE]);
  123. printf ("%04d ", atoi (vector [BUILD]));
  124. printf ("%s ", vector [DATE]);
  125. printf ("%s.", vector [VER]);
  126. printf ("%s ", vector [REV]);
  127. printf ("%s (%d)\n", filename, module);
  128. return;
  129. }
  130. return;
  131. }
  132. /*====================================================================*
  133. *
  134. * signed nvmimage2 (void const * memory, size_t extent, char const * filename, flag_t flags)
  135. *
  136. * verify a firmware image chain stored in memory; return 0 on
  137. * success or -1 on error;
  138. *
  139. *
  140. * Contributor(s):
  141. * Charles Maier <cmaier@qca.qualcomm.com>
  142. *
  143. *--------------------------------------------------------------------*/
  144. static signed nvmimage2 (void const * memory, size_t extent, char const * filename, flag_t flags)
  145. {
  146. struct lightning_nvm_header * header;
  147. unsigned module = 0;
  148. uint32_t offset = 0;
  149. do
  150. {
  151. header = (struct lightning_nvm_header *) ((char *) (memory) + offset);
  152. if (LE32TOH (header->HEADERVERSION) != 0x60000000)
  153. {
  154. if (_allclr (flags, NVM_SILENCE))
  155. {
  156. error (0, errno, NVM_HDR_VERSION, filename, module);
  157. }
  158. return (- 1);
  159. }
  160. if (checksum32 (header, sizeof (* header), 0))
  161. {
  162. if (_allclr (flags, NVM_SILENCE))
  163. {
  164. error (0, errno, NVM_HDR_CHECKSUM, filename, module);
  165. }
  166. return (- 1);
  167. }
  168. offset += sizeof (* header);
  169. extent -= sizeof (* header);
  170. if (_anyset (flags, NVM_VERBOSE))
  171. {
  172. printf ("------- %s (%d) -------\n", filename, module);
  173. lightning_nvm_peek (header);
  174. }
  175. if (LE32TOH (header->IMAGETYPE) == NVM_IMAGE_FIRMWARE)
  176. {
  177. firmware (filename, module, (char *) (memory) + offset, 0x70, flags);
  178. }
  179. if (checksum32 ((char *) (memory) + offset, LE32TOH (header->IMAGELENGTH), header->IMAGECHECKSUM))
  180. {
  181. if (_allclr (flags, NVM_SILENCE))
  182. {
  183. error (0, errno, NVM_IMG_CHECKSUM, filename, module);
  184. }
  185. return (- 1);
  186. }
  187. offset += LE32TOH (header->IMAGELENGTH);
  188. extent -= LE32TOH (header->IMAGELENGTH);
  189. module++;
  190. }
  191. while (header->NEXTHEADER);
  192. if (extent)
  193. {
  194. if (_allclr (flags, NVM_SILENCE))
  195. {
  196. error (0, errno, NVM_HDR_LINK, filename, module);
  197. }
  198. }
  199. return ((signed) (extent));
  200. }
  201. /*====================================================================*
  202. *
  203. * signed panther_nvm_chain (void const * memory, size_t extent, char const * filename, flag_t flags)
  204. *
  205. * verify a firmware image chain stored in memory; return 0 on
  206. * success or -1 on error;
  207. *
  208. * Contributor(s):
  209. * Charles Maier <cmaier@qca.qualcomm.com>
  210. *
  211. *--------------------------------------------------------------------*/
  212. static signed panther_nvm_chain (void const * memory, size_t extent, char const * filename, flag_t flags)
  213. {
  214. struct panther_nvm_header * header;
  215. unsigned module = 0;
  216. uint32_t origin = ~ 0;
  217. uint32_t offset = 0;
  218. uint32_t length = 0;
  219. do
  220. {
  221. header = (struct panther_nvm_header *) ((char *) (memory) + offset);
  222. if (LE16TOH (header->MajorVersion) != 1)
  223. {
  224. if (_allclr (flags, NVM_SILENCE))
  225. {
  226. error (0, errno, NVM_HDR_VERSION, filename, module);
  227. }
  228. return (- 1);
  229. }
  230. if (LE16TOH (header->MinorVersion) != 1)
  231. {
  232. if (_allclr (flags, NVM_SILENCE))
  233. {
  234. error (0, errno, NVM_HDR_VERSION, filename, module);
  235. }
  236. return (- 1);
  237. }
  238. if (LE32TOH (header->PrevHeader) != origin)
  239. {
  240. if (_allclr (flags, NVM_SILENCE))
  241. {
  242. error (0, errno, NVM_HDR_LINK, filename, module);
  243. }
  244. return (- 1);
  245. }
  246. if (checksum32 (header, sizeof (* header), 0))
  247. {
  248. if (_allclr (flags, NVM_SILENCE))
  249. {
  250. error (0, 0, NVM_HDR_CHECKSUM, filename, module);
  251. }
  252. return (- 1);
  253. }
  254. origin = offset;
  255. offset += sizeof (* header);
  256. extent -= sizeof (* header);
  257. length = LE32TOH (header->ImageLength);
  258. if (_anyset (flags, NVM_VERBOSE))
  259. {
  260. printf ("------- %s (%d) -------\n", filename, module);
  261. panther_nvm_peek (header);
  262. }
  263. if (LE32TOH (header->ImageType) == NVM_IMAGE_MANIFEST)
  264. {
  265. if (_anyset (flags, NVM_MANIFEST))
  266. {
  267. printf ("------- %s (%d) -------\n", filename, module);
  268. panther_nvm_manifest ((char *) (memory) + offset, length);
  269. return (0);
  270. }
  271. if (_anyset (flags, NVM_REVISION))
  272. {
  273. panther_nvm_revision ((char *) (memory) + offset, length);
  274. return (0);
  275. }
  276. }
  277. if (checksum32 ((char *) (memory) + offset, length, header->ImageChecksum))
  278. {
  279. if (_allclr (flags, NVM_SILENCE))
  280. {
  281. error (0, errno, NVM_IMG_CHECKSUM, filename, module);
  282. }
  283. return (- 1);
  284. }
  285. offset += length;
  286. extent -= length;
  287. module++;
  288. }
  289. while (~ header->NextHeader);
  290. if (extent)
  291. {
  292. if (_allclr (flags, NVM_SILENCE))
  293. {
  294. error (0, errno, NVM_HDR_LINK, filename, module);
  295. }
  296. }
  297. return (0);
  298. }
  299. /*====================================================================*
  300. *
  301. * signed chknvm (char const * filename, flag_t flags);
  302. *
  303. * read .nvm file into memory and validate it;
  304. *
  305. *
  306. * Contributor(s):
  307. * Charles Maier <cmaier@qca.qualcomm.com>
  308. *
  309. *--------------------------------------------------------------------*/
  310. static signed chknvm (char const * filename, flag_t flags)
  311. {
  312. void * memory = (void *) (0);
  313. signed extent = 0;
  314. signed status = 0;
  315. signed fd;
  316. if ((fd = open (filename, O_BINARY | O_RDONLY)) == - 1)
  317. {
  318. if (_allclr (flags, NVM_SILENCE))
  319. {
  320. error (0, errno, FILE_CANTOPEN, filename);
  321. }
  322. return (- 1);
  323. }
  324. if ((extent = lseek (fd, 0, SEEK_END)) == - 1)
  325. {
  326. if (_allclr (flags, NVM_SILENCE))
  327. {
  328. error (0, errno, FILE_CANTSIZE, filename);
  329. }
  330. return (- 1);
  331. }
  332. if (! (memory = malloc (extent)))
  333. {
  334. if (_allclr (flags, NVM_SILENCE))
  335. {
  336. error (0, errno, FILE_CANTLOAD, filename);
  337. }
  338. return (- 1);
  339. }
  340. if (lseek (fd, 0, SEEK_SET))
  341. {
  342. if (_allclr (flags, NVM_SILENCE))
  343. {
  344. error (0, errno, FILE_CANTLOAD, filename);
  345. }
  346. return (- 1);
  347. }
  348. if (read (fd, memory, extent) != extent)
  349. {
  350. if (_allclr (flags, NVM_SILENCE))
  351. {
  352. error (0, errno, FILE_CANTREAD, filename);
  353. }
  354. return (- 1);
  355. }
  356. close (fd);
  357. if (LE32TOH (* (uint32_t *) (memory)) == 0x60000000)
  358. {
  359. status = nvmimage2 (memory, extent, filename, flags);
  360. }
  361. else
  362. {
  363. status = panther_nvm_chain (memory, extent, filename, flags);
  364. }
  365. free (memory);
  366. return (status);
  367. }
  368. /*====================================================================*
  369. *
  370. * int main (int argc, char const * argv []);
  371. *
  372. * Contributor(s):
  373. * Charles Maier <cmaier@qca.qualcomm.com>
  374. *
  375. *--------------------------------------------------------------------*/
  376. int main (int argc, char const * argv [])
  377. {
  378. static char const * optv [] =
  379. {
  380. "imqrv",
  381. "file [file] [...]",
  382. "Qualcomm Atheros PLC Image File Validator",
  383. "i\tprint firmware identity string",
  384. "m\tdisplay manifest",
  385. "q\tsuppress messages",
  386. "r\tprint firmware revision string",
  387. "v\tverbose messages",
  388. (char const *) (0)
  389. };
  390. flag_t flags = (flag_t) (0);
  391. signed state = 0;
  392. signed c;
  393. optind = 1;
  394. while (~ (c = getoptv (argc, argv, optv)))
  395. {
  396. switch ((char) (c))
  397. {
  398. case 'i':
  399. _setbits (flags, NVM_IDENTITY);
  400. break;
  401. case 'm':
  402. _setbits (flags, NVM_MANIFEST);
  403. break;
  404. case 'r':
  405. _setbits (flags, NVM_REVISION);
  406. break;
  407. case 'q':
  408. _setbits (flags, NVM_SILENCE);
  409. break;
  410. case 'v':
  411. _setbits (flags, NVM_VERBOSE);
  412. break;
  413. default:
  414. break;
  415. }
  416. }
  417. argc -= optind;
  418. argv += optind;
  419. while ((argc) && (* argv))
  420. {
  421. if (chknvm (* argv, flags))
  422. {
  423. state = 1;
  424. }
  425. else if (_allclr (flags, (NVM_VERBOSE | NVM_SILENCE | NVM_MANIFEST | NVM_REVISION | NVM_IDENTITY)))
  426. {
  427. printf ("%s looks good\n", * argv);
  428. }
  429. argc--;
  430. argv++;
  431. }
  432. return (state);
  433. }