kwbimage.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * (C) Copyright 2008
  3. * Marvell Semiconductor <www.marvell.com>
  4. * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. */
  24. /* Required to obtain the getline prototype from stdio.h */
  25. #define _GNU_SOURCE
  26. #include "mkimage.h"
  27. #include <image.h>
  28. #include "kwbimage.h"
  29. /*
  30. * Supported commands for configuration file
  31. */
  32. static table_entry_t kwbimage_cmds[] = {
  33. {CMD_BOOT_FROM, "BOOT_FROM", "boot command", },
  34. {CMD_NAND_ECC_MODE, "NAND_ECC_MODE", "NAND mode", },
  35. {CMD_NAND_PAGE_SIZE, "NAND_PAGE_SIZE", "NAND size", },
  36. {CMD_SATA_PIO_MODE, "SATA_PIO_MODE", "SATA mode", },
  37. {CMD_DDR_INIT_DELAY, "DDR_INIT_DELAY", "DDR init dly", },
  38. {CMD_DATA, "DATA", "Reg Write Data", },
  39. {CMD_INVALID, "", "", },
  40. };
  41. /*
  42. * Supported Boot options for configuration file
  43. */
  44. static table_entry_t kwbimage_bootops[] = {
  45. {IBR_HDR_SPI_ID, "spi", "SPI Flash", },
  46. {IBR_HDR_NAND_ID, "nand", "NAND Flash", },
  47. {IBR_HDR_SATA_ID, "sata", "Sata port", },
  48. {IBR_HDR_PEX_ID, "pex", "PCIe port", },
  49. {IBR_HDR_UART_ID, "uart", "Serial port", },
  50. {-1, "", "Invalid", },
  51. };
  52. /*
  53. * Supported NAND ecc options configuration file
  54. */
  55. static table_entry_t kwbimage_eccmodes[] = {
  56. {IBR_HDR_ECC_DEFAULT, "default", "Default mode", },
  57. {IBR_HDR_ECC_FORCED_HAMMING, "hamming", "Hamming mode", },
  58. {IBR_HDR_ECC_FORCED_RS, "rs", "RS mode", },
  59. {IBR_HDR_ECC_DISABLED, "disabled", "ECC Disabled", },
  60. {-1, "", "", },
  61. };
  62. static struct kwb_header kwbimage_header;
  63. static int datacmd_cnt = 0;
  64. static char * fname = "Unknown";
  65. static int lineno = -1;
  66. /*
  67. * Report Error if xflag is set in addition to default
  68. */
  69. static int kwbimage_check_params (struct mkimage_params *params)
  70. {
  71. if (!strlen (params->imagename)) {
  72. printf ("Error:%s - Configuration file not specified, "
  73. "it is needed for kwbimage generation\n",
  74. params->cmdname);
  75. return CFG_INVALID;
  76. }
  77. return ((params->dflag && (params->fflag || params->lflag)) ||
  78. (params->fflag && (params->dflag || params->lflag)) ||
  79. (params->lflag && (params->dflag || params->fflag)) ||
  80. (params->xflag) || !(strlen (params->imagename)));
  81. }
  82. static uint32_t check_get_hexval (char *token)
  83. {
  84. uint32_t hexval;
  85. if (!sscanf (token, "%x", &hexval)) {
  86. printf ("Error:%s[%d] - Invalid hex data(%s)\n", fname,
  87. lineno, token);
  88. exit (EXIT_FAILURE);
  89. }
  90. return hexval;
  91. }
  92. /*
  93. * Generates 8 bit checksum
  94. */
  95. static uint8_t kwbimage_checksum8 (void *start, uint32_t len, uint8_t csum)
  96. {
  97. register uint8_t sum = csum;
  98. volatile uint8_t *p = (volatile uint8_t *)start;
  99. /* check len and return zero checksum if invalid */
  100. if (!len)
  101. return 0;
  102. do {
  103. sum += *p;
  104. p++;
  105. } while (--len);
  106. return (sum);
  107. }
  108. /*
  109. * Generates 32 bit checksum
  110. */
  111. static uint32_t kwbimage_checksum32 (uint32_t *start, uint32_t len, uint32_t csum)
  112. {
  113. register uint32_t sum = csum;
  114. volatile uint32_t *p = start;
  115. /* check len and return zero checksum if invalid */
  116. if (!len)
  117. return 0;
  118. if (len % sizeof(uint32_t)) {
  119. printf ("Error:%s[%d] - length is not in multiple of %zu\n",
  120. __FUNCTION__, len, sizeof(uint32_t));
  121. return 0;
  122. }
  123. do {
  124. sum += *p;
  125. p++;
  126. len -= sizeof(uint32_t);
  127. } while (len > 0);
  128. return (sum);
  129. }
  130. static void kwbimage_check_cfgdata (char *token, enum kwbimage_cmd cmdsw,
  131. struct kwb_header *kwbhdr)
  132. {
  133. bhr_t *mhdr = &kwbhdr->kwb_hdr;
  134. extbhr_t *exthdr = &kwbhdr->kwb_exthdr;
  135. int i;
  136. switch (cmdsw) {
  137. case CMD_BOOT_FROM:
  138. i = get_table_entry_id (kwbimage_bootops,
  139. "Kwbimage boot option", token);
  140. if (i < 0)
  141. goto INVL_DATA;
  142. mhdr->blockid = i;
  143. printf ("Preparing kirkwood boot image to boot "
  144. "from %s\n", token);
  145. break;
  146. case CMD_NAND_ECC_MODE:
  147. i = get_table_entry_id (kwbimage_eccmodes,
  148. "NAND ecc mode", token);
  149. if (i < 0)
  150. goto INVL_DATA;
  151. mhdr->nandeccmode = i;
  152. printf ("Nand ECC mode = %s\n", token);
  153. break;
  154. case CMD_NAND_PAGE_SIZE:
  155. mhdr->nandpagesize =
  156. (uint16_t) check_get_hexval (token);
  157. printf ("Nand page size = 0x%x\n", mhdr->nandpagesize);
  158. break;
  159. case CMD_SATA_PIO_MODE:
  160. mhdr->satapiomode =
  161. (uint8_t) check_get_hexval (token);
  162. printf ("Sata PIO mode = 0x%x\n",
  163. mhdr->satapiomode);
  164. break;
  165. case CMD_DDR_INIT_DELAY:
  166. mhdr->ddrinitdelay =
  167. (uint16_t) check_get_hexval (token);
  168. printf ("DDR init delay = %d msec\n", mhdr->ddrinitdelay);
  169. break;
  170. case CMD_DATA:
  171. exthdr->rcfg[datacmd_cnt].raddr =
  172. check_get_hexval (token);
  173. break;
  174. case CMD_INVALID:
  175. goto INVL_DATA;
  176. default:
  177. goto INVL_DATA;
  178. }
  179. return;
  180. INVL_DATA:
  181. printf ("Error:%s[%d] - Invalid data\n", fname, lineno);
  182. exit (EXIT_FAILURE);
  183. }
  184. /*
  185. * this function sets the kwbimage header by-
  186. * 1. Abstracting input command line arguments data
  187. * 2. parses the kwbimage configuration file and update extebded header data
  188. * 3. calculates header, extended header and image checksums
  189. */
  190. static void kwdimage_set_ext_header (struct kwb_header *kwbhdr, char* name) {
  191. bhr_t *mhdr = &kwbhdr->kwb_hdr;
  192. extbhr_t *exthdr = &kwbhdr->kwb_exthdr;
  193. FILE *fd = NULL;
  194. int j;
  195. char *line = NULL;
  196. char * token, *saveptr1, *saveptr2;
  197. size_t len = 0;
  198. enum kwbimage_cmd cmd;
  199. fname = name;
  200. /* set dram register offset */
  201. exthdr->dramregsoffs = (intptr_t)&exthdr->rcfg - (intptr_t)mhdr;
  202. if ((fd = fopen (name, "r")) == 0) {
  203. printf ("Error:%s - Can't open\n", fname);
  204. exit (EXIT_FAILURE);
  205. }
  206. /* Simple kwimage.cfg file parser */
  207. lineno=0;
  208. while ((getline (&line, &len, fd)) > 0) {
  209. lineno++;
  210. token = strtok_r (line, "\r\n", &saveptr1);
  211. /* drop all lines with zero tokens (= empty lines) */
  212. if (token == NULL)
  213. continue;
  214. for (j = 0, cmd = CMD_INVALID, line = token; ; line = NULL) {
  215. token = strtok_r (line, " \t", &saveptr2);
  216. if (token == NULL)
  217. break;
  218. /* Drop all text starting with '#' as comments */
  219. if (token[0] == '#')
  220. break;
  221. /* Process rest as valid config command line */
  222. switch (j) {
  223. case CFG_COMMAND:
  224. cmd = get_table_entry_id (kwbimage_cmds,
  225. "Kwbimage command", token);
  226. if (cmd == CMD_INVALID)
  227. goto INVL_CMD;
  228. break;
  229. case CFG_DATA0:
  230. kwbimage_check_cfgdata (token, cmd, kwbhdr);
  231. break;
  232. case CFG_DATA1:
  233. if (cmd != CMD_DATA)
  234. goto INVL_CMD;
  235. exthdr->rcfg[datacmd_cnt].rdata =
  236. check_get_hexval (token);
  237. if (datacmd_cnt > KWBIMAGE_MAX_CONFIG ) {
  238. printf ("Error:%s[%d] - Found more "
  239. "than max(%zd) allowed "
  240. "data configurations\n",
  241. fname, lineno,
  242. KWBIMAGE_MAX_CONFIG);
  243. exit (EXIT_FAILURE);
  244. } else
  245. datacmd_cnt++;
  246. break;
  247. default:
  248. goto INVL_CMD;
  249. }
  250. j++;
  251. }
  252. }
  253. if (line)
  254. free (line);
  255. fclose (fd);
  256. return;
  257. /*
  258. * Invalid Command error reporring
  259. *
  260. * command CMD_DATA needs three strings on a line
  261. * whereas other commands need only two.
  262. *
  263. * if more than two/three (as per command type) are observed,
  264. * then error will be reported
  265. */
  266. INVL_CMD:
  267. printf ("Error:%s[%d] - Invalid command\n", fname, lineno);
  268. exit (EXIT_FAILURE);
  269. }
  270. static void kwbimage_set_header (void *ptr, struct stat *sbuf, int ifd,
  271. struct mkimage_params *params)
  272. {
  273. struct kwb_header *hdr = (struct kwb_header *)ptr;
  274. bhr_t *mhdr = &hdr->kwb_hdr;
  275. extbhr_t *exthdr = &hdr->kwb_exthdr;
  276. uint32_t checksum;
  277. int size;
  278. /* Build and add image checksum header */
  279. checksum = kwbimage_checksum32 ((uint32_t *)ptr, sbuf->st_size, 0);
  280. size = write (ifd, &checksum, sizeof(uint32_t));
  281. if (size != sizeof(uint32_t)) {
  282. printf ("Error:%s - Checksum write %d bytes %s\n",
  283. params->cmdname, size, params->imagefile);
  284. exit (EXIT_FAILURE);
  285. }
  286. sbuf->st_size += sizeof(uint32_t);
  287. mhdr->blocksize = sbuf->st_size - sizeof(struct kwb_header);
  288. mhdr->srcaddr = sizeof(struct kwb_header);
  289. mhdr->destaddr= params->addr;
  290. mhdr->execaddr =params->ep;
  291. mhdr->ext = 0x1; /* header extension appended */
  292. kwdimage_set_ext_header (hdr, params->imagename);
  293. /* calculate checksums */
  294. mhdr->checkSum = kwbimage_checksum8 ((void *)mhdr, sizeof(bhr_t), 0);
  295. exthdr->checkSum = kwbimage_checksum8 ((void *)exthdr,
  296. sizeof(extbhr_t), 0);
  297. }
  298. static int kwbimage_verify_header (unsigned char *ptr, int image_size,
  299. struct mkimage_params *params)
  300. {
  301. struct kwb_header *hdr = (struct kwb_header *)ptr;
  302. bhr_t *mhdr = &hdr->kwb_hdr;
  303. extbhr_t *exthdr = &hdr->kwb_exthdr;
  304. uint8_t calc_hdrcsum;
  305. uint8_t calc_exthdrcsum;
  306. calc_hdrcsum = kwbimage_checksum8 ((void *)mhdr,
  307. sizeof(bhr_t) - sizeof(uint8_t), 0);
  308. if (calc_hdrcsum != mhdr->checkSum)
  309. return -FDT_ERR_BADSTRUCTURE; /* mhdr csum not matched */
  310. calc_exthdrcsum = kwbimage_checksum8 ((void *)exthdr,
  311. sizeof(extbhr_t) - sizeof(uint8_t), 0);
  312. if (calc_exthdrcsum != exthdr->checkSum)
  313. return -FDT_ERR_BADSTRUCTURE; /* exthdr csum not matched */
  314. return 0;
  315. }
  316. static void kwbimage_print_header (const void *ptr)
  317. {
  318. struct kwb_header *hdr = (struct kwb_header *) ptr;
  319. bhr_t *mhdr = &hdr->kwb_hdr;
  320. char *name = get_table_entry_name (kwbimage_bootops,
  321. "Kwbimage boot option",
  322. (int) mhdr->blockid);
  323. printf ("Image Type: Kirkwood Boot from %s Image\n", name);
  324. printf ("Data Size: ");
  325. genimg_print_size (mhdr->blocksize - sizeof(uint32_t));
  326. printf ("Load Address: %08x\n", mhdr->destaddr);
  327. printf ("Entry Point: %08x\n", mhdr->execaddr);
  328. }
  329. static int kwbimage_check_image_types (uint8_t type)
  330. {
  331. if (type == IH_TYPE_KWBIMAGE)
  332. return EXIT_SUCCESS;
  333. else
  334. return EXIT_FAILURE;
  335. }
  336. /*
  337. * kwbimage type parameters definition
  338. */
  339. static struct image_type_params kwbimage_params = {
  340. .name = "Kirkwood Boot Image support",
  341. .header_size = sizeof(struct kwb_header),
  342. .hdr = (void*)&kwbimage_header,
  343. .check_image_type = kwbimage_check_image_types,
  344. .verify_header = kwbimage_verify_header,
  345. .print_header = kwbimage_print_header,
  346. .set_header = kwbimage_set_header,
  347. .check_params = kwbimage_check_params,
  348. };
  349. void init_kwb_image_type (void)
  350. {
  351. mkimage_register (&kwbimage_params);
  352. }