image.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. /*
  2. * (C) Copyright 2008 Semihalf
  3. *
  4. * (C) Copyright 2000-2006
  5. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #define DEBUG
  26. #ifndef USE_HOSTCC
  27. #include <common.h>
  28. #include <watchdog.h>
  29. #ifdef CONFIG_SHOW_BOOT_PROGRESS
  30. #include <status_led.h>
  31. #endif
  32. #ifdef CONFIG_HAS_DATAFLASH
  33. #include <dataflash.h>
  34. #endif
  35. #ifdef CONFIG_LOGBUFFER
  36. #include <logbuff.h>
  37. #endif
  38. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
  39. #include <rtc.h>
  40. #endif
  41. #if defined(CONFIG_FIT)
  42. #include <fdt.h>
  43. #include <libfdt.h>
  44. #include <fdt_support.h>
  45. #endif
  46. #ifdef CONFIG_CMD_BDI
  47. extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  48. #endif
  49. DECLARE_GLOBAL_DATA_PTR;
  50. static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
  51. int argc, char *argv[],
  52. ulong rd_addr, uint8_t arch, int verify);
  53. #else
  54. #include "mkimage.h"
  55. #endif /* !USE_HOSTCC*/
  56. #include <image.h>
  57. typedef struct table_entry {
  58. int id; /* as defined in image.h */
  59. char *sname; /* short (input) name */
  60. char *lname; /* long (output) name */
  61. } table_entry_t;
  62. static table_entry_t uimage_arch[] = {
  63. { IH_ARCH_INVALID, NULL, "Invalid ARCH", },
  64. { IH_ARCH_ALPHA, "alpha", "Alpha", },
  65. { IH_ARCH_ARM, "arm", "ARM", },
  66. { IH_ARCH_I386, "x86", "Intel x86", },
  67. { IH_ARCH_IA64, "ia64", "IA64", },
  68. { IH_ARCH_M68K, "m68k", "M68K", },
  69. { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", },
  70. { IH_ARCH_MIPS, "mips", "MIPS", },
  71. { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
  72. { IH_ARCH_NIOS, "nios", "NIOS", },
  73. { IH_ARCH_NIOS2, "nios2", "NIOS II", },
  74. { IH_ARCH_PPC, "ppc", "PowerPC", },
  75. { IH_ARCH_S390, "s390", "IBM S390", },
  76. { IH_ARCH_SH, "sh", "SuperH", },
  77. { IH_ARCH_SPARC, "sparc", "SPARC", },
  78. { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", },
  79. { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", },
  80. { IH_ARCH_AVR32, "avr32", "AVR32", },
  81. { -1, "", "", },
  82. };
  83. static table_entry_t uimage_os[] = {
  84. { IH_OS_INVALID, NULL, "Invalid OS", },
  85. #if defined(CONFIG_ARTOS) || defined(USE_HOSTCC)
  86. { IH_OS_ARTOS, "artos", "ARTOS", },
  87. #endif
  88. { IH_OS_LINUX, "linux", "Linux", },
  89. #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
  90. { IH_OS_LYNXOS, "lynxos", "LynxOS", },
  91. #endif
  92. { IH_OS_NETBSD, "netbsd", "NetBSD", },
  93. { IH_OS_RTEMS, "rtems", "RTEMS", },
  94. { IH_OS_U_BOOT, "u-boot", "U-Boot", },
  95. #if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC)
  96. { IH_OS_QNX, "qnx", "QNX", },
  97. { IH_OS_VXWORKS, "vxworks", "VxWorks", },
  98. #endif
  99. #ifdef USE_HOSTCC
  100. { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", },
  101. { IH_OS_DELL, "dell", "Dell", },
  102. { IH_OS_ESIX, "esix", "Esix", },
  103. { IH_OS_FREEBSD, "freebsd", "FreeBSD", },
  104. { IH_OS_IRIX, "irix", "Irix", },
  105. { IH_OS_NCR, "ncr", "NCR", },
  106. { IH_OS_OPENBSD, "openbsd", "OpenBSD", },
  107. { IH_OS_PSOS, "psos", "pSOS", },
  108. { IH_OS_SCO, "sco", "SCO", },
  109. { IH_OS_SOLARIS, "solaris", "Solaris", },
  110. { IH_OS_SVR4, "svr4", "SVR4", },
  111. #endif
  112. { -1, "", "", },
  113. };
  114. static table_entry_t uimage_type[] = {
  115. { IH_TYPE_INVALID, NULL, "Invalid Image", },
  116. { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", },
  117. { IH_TYPE_FIRMWARE, "firmware", "Firmware", },
  118. { IH_TYPE_KERNEL, "kernel", "Kernel Image", },
  119. { IH_TYPE_MULTI, "multi", "Multi-File Image", },
  120. { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", },
  121. { IH_TYPE_SCRIPT, "script", "Script", },
  122. { IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
  123. { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", },
  124. { -1, "", "", },
  125. };
  126. static table_entry_t uimage_comp[] = {
  127. { IH_COMP_NONE, "none", "uncompressed", },
  128. { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", },
  129. { IH_COMP_GZIP, "gzip", "gzip compressed", },
  130. { -1, "", "", },
  131. };
  132. unsigned long crc32 (unsigned long, const unsigned char *, unsigned int);
  133. static void genimg_print_size (uint32_t size);
  134. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  135. static void genimg_print_time (time_t timestamp);
  136. #endif
  137. /*****************************************************************************/
  138. /* Legacy format routines */
  139. /*****************************************************************************/
  140. int image_check_hcrc (image_header_t *hdr)
  141. {
  142. ulong hcrc;
  143. ulong len = image_get_header_size ();
  144. image_header_t header;
  145. /* Copy header so we can blank CRC field for re-calculation */
  146. memmove (&header, (char *)hdr, image_get_header_size ());
  147. image_set_hcrc (&header, 0);
  148. hcrc = crc32 (0, (unsigned char *)&header, len);
  149. return (hcrc == image_get_hcrc (hdr));
  150. }
  151. int image_check_dcrc (image_header_t *hdr)
  152. {
  153. ulong data = image_get_data (hdr);
  154. ulong len = image_get_data_size (hdr);
  155. ulong dcrc = crc32 (0, (unsigned char *)data, len);
  156. return (dcrc == image_get_dcrc (hdr));
  157. }
  158. #ifndef USE_HOSTCC
  159. int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz)
  160. {
  161. ulong dcrc = 0;
  162. ulong len = image_get_data_size (hdr);
  163. ulong data = image_get_data (hdr);
  164. #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  165. ulong cdata = data;
  166. ulong edata = cdata + len;
  167. while (cdata < edata) {
  168. ulong chunk = edata - cdata;
  169. if (chunk > chunksz)
  170. chunk = chunksz;
  171. dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk);
  172. cdata += chunk;
  173. WATCHDOG_RESET ();
  174. }
  175. #else
  176. dcrc = crc32 (0, (unsigned char *)data, len);
  177. #endif
  178. return (dcrc == image_get_dcrc (hdr));
  179. }
  180. #endif /* !USE_HOSTCC */
  181. /**
  182. * image_multi_count - get component (sub-image) count
  183. * @hdr: pointer to the header of the multi component image
  184. *
  185. * image_multi_count() returns number of components in a multi
  186. * component image.
  187. *
  188. * Note: no checking of the image type is done, caller must pass
  189. * a valid multi component image.
  190. *
  191. * returns:
  192. * number of components
  193. */
  194. ulong image_multi_count (image_header_t *hdr)
  195. {
  196. ulong i, count = 0;
  197. uint32_t *size;
  198. /* get start of the image payload, which in case of multi
  199. * component images that points to a table of component sizes */
  200. size = (uint32_t *)image_get_data (hdr);
  201. /* count non empty slots */
  202. for (i = 0; size[i]; ++i)
  203. count++;
  204. return count;
  205. }
  206. /**
  207. * image_multi_getimg - get component data address and size
  208. * @hdr: pointer to the header of the multi component image
  209. * @idx: index of the requested component
  210. * @data: pointer to a ulong variable, will hold component data address
  211. * @len: pointer to a ulong variable, will hold component size
  212. *
  213. * image_multi_getimg() returns size and data address for the requested
  214. * component in a multi component image.
  215. *
  216. * Note: no checking of the image type is done, caller must pass
  217. * a valid multi component image.
  218. *
  219. * returns:
  220. * data address and size of the component, if idx is valid
  221. * 0 in data and len, if idx is out of range
  222. */
  223. void image_multi_getimg (image_header_t *hdr, ulong idx,
  224. ulong *data, ulong *len)
  225. {
  226. int i;
  227. uint32_t *size;
  228. ulong offset, tail, count, img_data;
  229. /* get number of component */
  230. count = image_multi_count (hdr);
  231. /* get start of the image payload, which in case of multi
  232. * component images that points to a table of component sizes */
  233. size = (uint32_t *)image_get_data (hdr);
  234. /* get address of the proper component data start, which means
  235. * skipping sizes table (add 1 for last, null entry) */
  236. img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t);
  237. if (idx < count) {
  238. *len = uimage_to_cpu (size[idx]);
  239. offset = 0;
  240. tail = 0;
  241. /* go over all indices preceding requested component idx */
  242. for (i = 0; i < idx; i++) {
  243. /* add up i-th component size */
  244. offset += uimage_to_cpu (size[i]);
  245. /* add up alignment for i-th component */
  246. tail += (4 - uimage_to_cpu (size[i]) % 4);
  247. }
  248. /* calculate idx-th component data address */
  249. *data = img_data + offset + tail;
  250. } else {
  251. *len = 0;
  252. *data = 0;
  253. }
  254. }
  255. static void image_print_type (image_header_t *hdr)
  256. {
  257. const char *os, *arch, *type, *comp;
  258. os = genimg_get_os_name (image_get_os (hdr));
  259. arch = genimg_get_arch_name (image_get_arch (hdr));
  260. type = genimg_get_type_name (image_get_type (hdr));
  261. comp = genimg_get_comp_name (image_get_comp (hdr));
  262. printf ("%s %s %s (%s)\n", arch, os, type, comp);
  263. }
  264. static void __image_print_contents (image_header_t *hdr, const char *p)
  265. {
  266. printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr));
  267. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  268. printf ("%sCreated: ", p);
  269. genimg_print_time ((time_t)image_get_time (hdr));
  270. #endif
  271. printf ("%sImage Type: ", p);
  272. image_print_type (hdr);
  273. printf ("%sData Size: ", p);
  274. genimg_print_size (image_get_data_size (hdr));
  275. printf ("%sLoad Address: %08x\n", p, image_get_load (hdr));
  276. printf ("%sEntry Point: %08x\n", p, image_get_ep (hdr));
  277. if (image_check_type (hdr, IH_TYPE_MULTI) ||
  278. image_check_type (hdr, IH_TYPE_SCRIPT)) {
  279. int i;
  280. ulong data, len;
  281. ulong count = image_multi_count (hdr);
  282. printf ("%sContents:\n", p);
  283. for (i = 0; i < count; i++) {
  284. image_multi_getimg (hdr, i, &data, &len);
  285. printf ("%s Image %d: ", p, i);
  286. genimg_print_size (len);
  287. if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) {
  288. /*
  289. * the user may need to know offsets
  290. * if planning to do something with
  291. * multiple files
  292. */
  293. printf ("%s Offset = 0x%08lx\n", p, data);
  294. }
  295. }
  296. }
  297. }
  298. inline void image_print_contents (image_header_t *hdr)
  299. {
  300. __image_print_contents (hdr, " ");
  301. }
  302. inline void image_print_contents_noindent (image_header_t *hdr)
  303. {
  304. __image_print_contents (hdr, "");
  305. }
  306. #ifndef USE_HOSTCC
  307. /**
  308. * image_get_ramdisk - get and verify ramdisk image
  309. * @cmdtp: command table pointer
  310. * @flag: command flag
  311. * @argc: command argument count
  312. * @argv: command argument list
  313. * @rd_addr: ramdisk image start address
  314. * @arch: expected ramdisk architecture
  315. * @verify: checksum verification flag
  316. *
  317. * image_get_ramdisk() returns a pointer to the verified ramdisk image
  318. * header. Routine receives image start address and expected architecture
  319. * flag. Verification done covers data and header integrity and os/type/arch
  320. * fields checking.
  321. *
  322. * If dataflash support is enabled routine checks for dataflash addresses
  323. * and handles required dataflash reads.
  324. *
  325. * returns:
  326. * pointer to a ramdisk image header, if image was found and valid
  327. * otherwise, return NULL
  328. */
  329. static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
  330. int argc, char *argv[],
  331. ulong rd_addr, uint8_t arch, int verify)
  332. {
  333. image_header_t *rd_hdr;
  334. show_boot_progress (9);
  335. rd_hdr = (image_header_t *)rd_addr;
  336. if (!image_check_magic (rd_hdr)) {
  337. puts ("Bad Magic Number\n");
  338. show_boot_progress (-10);
  339. return NULL;
  340. }
  341. if (!image_check_hcrc (rd_hdr)) {
  342. puts ("Bad Header Checksum\n");
  343. show_boot_progress (-11);
  344. return NULL;
  345. }
  346. show_boot_progress (10);
  347. image_print_contents (rd_hdr);
  348. if (verify) {
  349. puts(" Verifying Checksum ... ");
  350. if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) {
  351. puts ("Bad Data CRC\n");
  352. show_boot_progress (-12);
  353. return NULL;
  354. }
  355. puts("OK\n");
  356. }
  357. show_boot_progress (11);
  358. if (!image_check_os (rd_hdr, IH_OS_LINUX) ||
  359. !image_check_arch (rd_hdr, arch) ||
  360. !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) {
  361. printf ("No Linux %s Ramdisk Image\n",
  362. genimg_get_arch_name(arch));
  363. show_boot_progress (-13);
  364. return NULL;
  365. }
  366. return rd_hdr;
  367. }
  368. #endif /* !USE_HOSTCC */
  369. /*****************************************************************************/
  370. /* Shared dual-format routines */
  371. /*****************************************************************************/
  372. #ifndef USE_HOSTCC
  373. int getenv_verify (void)
  374. {
  375. char *s = getenv ("verify");
  376. return (s && (*s == 'n')) ? 0 : 1;
  377. }
  378. int getenv_autostart (void)
  379. {
  380. char *s = getenv ("autostart");
  381. return (s && (*s == 'n')) ? 0 : 1;
  382. }
  383. ulong getenv_bootm_low(void)
  384. {
  385. char *s = getenv ("bootm_low");
  386. if (s) {
  387. ulong tmp = simple_strtoul (s, NULL, 16);
  388. return tmp;
  389. }
  390. #ifdef CFG_SDRAM_BASE
  391. return CFG_SDRAM_BASE;
  392. #else
  393. return 0;
  394. #endif
  395. }
  396. ulong getenv_bootm_size(void)
  397. {
  398. char *s = getenv ("bootm_size");
  399. if (s) {
  400. ulong tmp = simple_strtoul (s, NULL, 16);
  401. return tmp;
  402. }
  403. return gd->bd->bi_memsize;
  404. }
  405. void memmove_wd (void *to, void *from, size_t len, ulong chunksz)
  406. {
  407. #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  408. while (len > 0) {
  409. size_t tail = (len > chunksz) ? chunksz : len;
  410. WATCHDOG_RESET ();
  411. memmove (to, from, tail);
  412. to += tail;
  413. from += tail;
  414. len -= tail;
  415. }
  416. #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
  417. memmove (to, from, len);
  418. #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
  419. }
  420. #endif /* !USE_HOSTCC */
  421. static void genimg_print_size (uint32_t size)
  422. {
  423. #ifndef USE_HOSTCC
  424. printf ("%d Bytes = ", size);
  425. print_size (size, "\n");
  426. #else
  427. printf ("%d Bytes = %.2f kB = %.2f MB\n",
  428. size, (double)size / 1.024e3,
  429. (double)size / 1.048576e6);
  430. #endif
  431. }
  432. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  433. static void genimg_print_time (time_t timestamp)
  434. {
  435. #ifndef USE_HOSTCC
  436. struct rtc_time tm;
  437. to_tm (timestamp, &tm);
  438. printf ("%4d-%02d-%02d %2d:%02d:%02d UTC\n",
  439. tm.tm_year, tm.tm_mon, tm.tm_mday,
  440. tm.tm_hour, tm.tm_min, tm.tm_sec);
  441. #else
  442. printf ("%s", ctime(&timestamp));
  443. #endif
  444. }
  445. #endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */
  446. /**
  447. * get_table_entry_name - translate entry id to long name
  448. * @table: pointer to a translation table for entries of a specific type
  449. * @msg: message to be returned when translation fails
  450. * @id: entry id to be translated
  451. *
  452. * get_table_entry_name() will go over translation table trying to find
  453. * entry that matches given id. If matching entry is found, its long
  454. * name is returned to the caller.
  455. *
  456. * returns:
  457. * long entry name if translation succeeds
  458. * msg otherwise
  459. */
  460. static char *get_table_entry_name (table_entry_t *table, char *msg, int id)
  461. {
  462. for (; table->id >= 0; ++table) {
  463. if (table->id == id)
  464. return (table->lname);
  465. }
  466. return (msg);
  467. }
  468. const char *genimg_get_os_name (uint8_t os)
  469. {
  470. return (get_table_entry_name (uimage_os, "Unknown OS", os));
  471. }
  472. const char *genimg_get_arch_name (uint8_t arch)
  473. {
  474. return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch));
  475. }
  476. const char *genimg_get_type_name (uint8_t type)
  477. {
  478. return (get_table_entry_name (uimage_type, "Unknown Image", type));
  479. }
  480. const char *genimg_get_comp_name (uint8_t comp)
  481. {
  482. return (get_table_entry_name (uimage_comp, "Unknown Compression", comp));
  483. }
  484. /**
  485. * get_table_entry_id - translate short entry name to id
  486. * @table: pointer to a translation table for entries of a specific type
  487. * @table_name: to be used in case of error
  488. * @name: entry short name to be translated
  489. *
  490. * get_table_entry_id() will go over translation table trying to find
  491. * entry that matches given short name. If matching entry is found,
  492. * its id returned to the caller.
  493. *
  494. * returns:
  495. * entry id if translation succeeds
  496. * -1 otherwise
  497. */
  498. static int get_table_entry_id (table_entry_t *table,
  499. const char *table_name, const char *name)
  500. {
  501. table_entry_t *t;
  502. #ifdef USE_HOSTCC
  503. int first = 1;
  504. for (t = table; t->id >= 0; ++t) {
  505. if (t->sname && strcasecmp(t->sname, name) == 0)
  506. return (t->id);
  507. }
  508. fprintf (stderr, "\nInvalid %s Type - valid names are", table_name);
  509. for (t = table; t->id >= 0; ++t) {
  510. if (t->sname == NULL)
  511. continue;
  512. fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname);
  513. first = 0;
  514. }
  515. fprintf (stderr, "\n");
  516. #else
  517. for (t = table; t->id >= 0; ++t) {
  518. if (t->sname && strcmp(t->sname, name) == 0)
  519. return (t->id);
  520. }
  521. debug ("Invalid %s Type: %s\n", table_name, name);
  522. #endif /* USE_HOSTCC */
  523. return (-1);
  524. }
  525. int genimg_get_os_id (const char *name)
  526. {
  527. return (get_table_entry_id (uimage_os, "OS", name));
  528. }
  529. int genimg_get_arch_id (const char *name)
  530. {
  531. return (get_table_entry_id (uimage_arch, "CPU", name));
  532. }
  533. int genimg_get_type_id (const char *name)
  534. {
  535. return (get_table_entry_id (uimage_type, "Image", name));
  536. }
  537. int genimg_get_comp_id (const char *name)
  538. {
  539. return (get_table_entry_id (uimage_comp, "Compression", name));
  540. }
  541. #ifndef USE_HOSTCC
  542. /**
  543. * genimg_get_format - get image format type
  544. * @img_addr: image start address
  545. *
  546. * genimg_get_format() checks whether provided address points to a valid
  547. * legacy or FIT image.
  548. *
  549. * New uImage format and FDT blob are based on a libfdt. FDT blob
  550. * may be passed directly or embedded in a FIT image. In both situations
  551. * genimg_get_format() must be able to dectect libfdt header.
  552. *
  553. * returns:
  554. * image format type or IMAGE_FORMAT_INVALID if no image is present
  555. */
  556. int genimg_get_format (void *img_addr)
  557. {
  558. ulong format = IMAGE_FORMAT_INVALID;
  559. image_header_t *hdr;
  560. #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
  561. char *fit_hdr;
  562. #endif
  563. hdr = (image_header_t *)img_addr;
  564. if (image_check_magic(hdr))
  565. format = IMAGE_FORMAT_LEGACY;
  566. #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
  567. else {
  568. fit_hdr = (char *)img_addr;
  569. if (fdt_check_header (fit_hdr) == 0)
  570. format = IMAGE_FORMAT_FIT;
  571. }
  572. #endif
  573. return format;
  574. }
  575. /**
  576. * genimg_get_image - get image from special storage (if necessary)
  577. * @img_addr: image start address
  578. *
  579. * genimg_get_image() checks if provided image start adddress is located
  580. * in a dataflash storage. If so, image is moved to a system RAM memory.
  581. *
  582. * returns:
  583. * image start address after possible relocation from special storage
  584. */
  585. ulong genimg_get_image (ulong img_addr)
  586. {
  587. ulong ram_addr = img_addr;
  588. #ifdef CONFIG_HAS_DATAFLASH
  589. ulong h_size, d_size;
  590. if (addr_dataflash (img_addr)){
  591. /* ger RAM address */
  592. ram_addr = CFG_LOAD_ADDR;
  593. /* get header size */
  594. h_size = image_get_header_size ();
  595. #if defined(CONFIG_FIT)
  596. if (sizeof(struct fdt_header) > h_size)
  597. h_size = sizeof(struct fdt_header);
  598. #endif
  599. /* read in header */
  600. debug (" Reading image header from dataflash address "
  601. "%08lx to RAM address %08lx\n", img_addr, ram_addr);
  602. read_dataflash (img_addr, h_size, (char *)ram_addr);
  603. /* get data size */
  604. switch (genimg_get_format ((void *)ram_addr)) {
  605. case IMAGE_FORMAT_LEGACY:
  606. d_size = image_get_data_size ((image_header_t *)ram_addr);
  607. debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n",
  608. ram_addr, d_size);
  609. break;
  610. #if defined(CONFIG_FIT)
  611. case IMAGE_FORMAT_FIT:
  612. d_size = fdt_totalsize((void *)ram_addr) - h_size;
  613. debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n",
  614. ram_addr, d_size);
  615. break;
  616. #endif
  617. default:
  618. printf (" No valid image found at 0x%08lx\n", img_addr);
  619. return ram_addr;
  620. }
  621. /* read in image data */
  622. debug (" Reading image remaining data from dataflash address "
  623. "%08lx to RAM address %08lx\n", img_addr + h_size,
  624. ram_addr + h_size);
  625. read_dataflash (img_addr + h_size, d_size,
  626. (char *)(ram_addr + h_size));
  627. }
  628. #endif /* CONFIG_HAS_DATAFLASH */
  629. return ram_addr;
  630. }
  631. /**
  632. * boot_get_ramdisk - main ramdisk handling routine
  633. * @cmdtp: command table pointer
  634. * @flag: command flag
  635. * @argc: command argument count
  636. * @argv: command argument list
  637. * @images: pointer to the bootm images structure
  638. * @arch: expected ramdisk architecture
  639. * @rd_start: pointer to a ulong variable, will hold ramdisk start address
  640. * @rd_end: pointer to a ulong variable, will hold ramdisk end
  641. *
  642. * boot_get_ramdisk() is responsible for finding a valid ramdisk image.
  643. * Curently supported are the following ramdisk sources:
  644. * - multicomponent kernel/ramdisk image,
  645. * - commandline provided address of decicated ramdisk image.
  646. *
  647. * returns:
  648. * rd_start and rd_end are set to ramdisk start/end addresses if
  649. * ramdisk image is found and valid
  650. * rd_start and rd_end are set to 0 if no ramdisk exists
  651. * return 1 if ramdisk image is found but corrupted
  652. */
  653. int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
  654. bootm_headers_t *images, uint8_t arch,
  655. ulong *rd_start, ulong *rd_end)
  656. {
  657. ulong rd_addr, rd_load;
  658. ulong rd_data, rd_len;
  659. image_header_t *rd_hdr;
  660. #if defined(CONFIG_FIT)
  661. void *fit_hdr;
  662. const char *fit_uname_config = NULL;
  663. const char *fit_uname_ramdisk = NULL;
  664. ulong default_addr;
  665. #endif
  666. /*
  667. * Look for a '-' which indicates to ignore the
  668. * ramdisk argument
  669. */
  670. if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) {
  671. debug ("## Skipping init Ramdisk\n");
  672. rd_len = rd_data = 0;
  673. } else if (argc >= 3) {
  674. #if defined(CONFIG_FIT)
  675. /*
  676. * If the init ramdisk comes from the FIT image and the FIT image
  677. * address is omitted in the command line argument, try to use
  678. * os FIT image address or default load address.
  679. */
  680. if (images->fit_uname_os)
  681. default_addr = (ulong)images->fit_hdr_os;
  682. else
  683. default_addr = load_addr;
  684. if (fit_parse_conf (argv[2], default_addr,
  685. &rd_addr, &fit_uname_config)) {
  686. debug ("* ramdisk: config '%s' from image at 0x%08lx\n",
  687. fit_uname_config, rd_addr);
  688. } else if (fit_parse_subimage (argv[2], default_addr,
  689. &rd_addr, &fit_uname_ramdisk)) {
  690. debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n",
  691. fit_uname_ramdisk, rd_addr);
  692. } else
  693. #endif
  694. {
  695. rd_addr = simple_strtoul(argv[2], NULL, 16);
  696. debug ("* ramdisk: cmdline image address = 0x%08lx\n",
  697. rd_addr);
  698. }
  699. /* copy from dataflash if needed */
  700. printf ("## Loading init Ramdisk Image at %08lx ...\n",
  701. rd_addr);
  702. rd_addr = genimg_get_image (rd_addr);
  703. /*
  704. * Check if there is an initrd image at the
  705. * address provided in the second bootm argument
  706. * check image type, for FIT images get FIT node.
  707. */
  708. switch (genimg_get_format ((void *)rd_addr)) {
  709. case IMAGE_FORMAT_LEGACY:
  710. debug ("* ramdisk: legacy format image\n");
  711. rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv,
  712. rd_addr, arch, images->verify);
  713. if (rd_hdr == NULL) {
  714. *rd_start = 0;
  715. *rd_end = 0;
  716. return 1;
  717. }
  718. rd_data = image_get_data (rd_hdr);
  719. rd_len = image_get_data_size (rd_hdr);
  720. rd_load = image_get_load (rd_hdr);
  721. break;
  722. #if defined(CONFIG_FIT)
  723. case IMAGE_FORMAT_FIT:
  724. fit_hdr = (void *)rd_addr;
  725. debug ("* ramdisk: FIT format image\n");
  726. fit_unsupported_reset ("ramdisk");
  727. return 1;
  728. #endif
  729. default:
  730. printf ("Wrong Image Format for %s command\n",
  731. cmdtp->name);
  732. rd_data = rd_len = 0;
  733. }
  734. #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
  735. /*
  736. * We need to copy the ramdisk to SRAM to let Linux boot
  737. */
  738. if (rd_data) {
  739. memmove ((void *)rd_load, (uchar *)rd_data, rd_len);
  740. rd_data = rd_load;
  741. }
  742. #endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
  743. } else if (images->legacy_hdr_valid &&
  744. image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) {
  745. /*
  746. * Now check if we have a legacy mult-component image,
  747. * get second entry data start address and len.
  748. */
  749. show_boot_progress (13);
  750. printf ("## Loading init Ramdisk from multi component "
  751. "Image at %08lx ...\n",
  752. (ulong)images->legacy_hdr_os);
  753. image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len);
  754. } else {
  755. /*
  756. * no initrd image
  757. */
  758. show_boot_progress (14);
  759. rd_len = rd_data = 0;
  760. }
  761. if (!rd_data) {
  762. debug ("## No init Ramdisk\n");
  763. *rd_start = 0;
  764. *rd_end = 0;
  765. } else {
  766. *rd_start = rd_data;
  767. *rd_end = rd_data + rd_len;
  768. }
  769. debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
  770. *rd_start, *rd_end);
  771. return 0;
  772. }
  773. #if defined(CONFIG_PPC) || defined(CONFIG_M68K)
  774. /**
  775. * boot_ramdisk_high - relocate init ramdisk
  776. * @lmb: pointer to lmb handle, will be used for memory mgmt
  777. * @rd_data: ramdisk data start address
  778. * @rd_len: ramdisk data length
  779. * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
  780. * start address (after possible relocation)
  781. * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
  782. * end address (after possible relocation)
  783. *
  784. * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement
  785. * variable and if requested ramdisk data is moved to a specified location.
  786. *
  787. * Initrd_start and initrd_end are set to final (after relocation) ramdisk
  788. * start/end addresses if ramdisk image start and len were provided,
  789. * otherwise set initrd_start and initrd_end set to zeros.
  790. *
  791. * returns:
  792. * 0 - success
  793. * -1 - failure
  794. */
  795. int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len,
  796. ulong *initrd_start, ulong *initrd_end)
  797. {
  798. char *s;
  799. ulong initrd_high;
  800. int initrd_copy_to_ram = 1;
  801. if ((s = getenv ("initrd_high")) != NULL) {
  802. /* a value of "no" or a similar string will act like 0,
  803. * turning the "load high" feature off. This is intentional.
  804. */
  805. initrd_high = simple_strtoul (s, NULL, 16);
  806. if (initrd_high == ~0)
  807. initrd_copy_to_ram = 0;
  808. } else {
  809. /* not set, no restrictions to load high */
  810. initrd_high = ~0;
  811. }
  812. debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
  813. initrd_high, initrd_copy_to_ram);
  814. if (rd_data) {
  815. if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */
  816. debug (" in-place initrd\n");
  817. *initrd_start = rd_data;
  818. *initrd_end = rd_data + rd_len;
  819. lmb_reserve(lmb, rd_data, rd_len);
  820. } else {
  821. if (initrd_high)
  822. *initrd_start = lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high);
  823. else
  824. *initrd_start = lmb_alloc (lmb, rd_len, 0x1000);
  825. if (*initrd_start == 0) {
  826. puts ("ramdisk - allocation error\n");
  827. goto error;
  828. }
  829. show_boot_progress (12);
  830. *initrd_end = *initrd_start + rd_len;
  831. printf (" Loading Ramdisk to %08lx, end %08lx ... ",
  832. *initrd_start, *initrd_end);
  833. memmove_wd ((void *)*initrd_start,
  834. (void *)rd_data, rd_len, CHUNKSZ);
  835. puts ("OK\n");
  836. }
  837. } else {
  838. *initrd_start = 0;
  839. *initrd_end = 0;
  840. }
  841. debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
  842. *initrd_start, *initrd_end);
  843. return 0;
  844. error:
  845. return -1;
  846. }
  847. /**
  848. * boot_get_cmdline - allocate and initialize kernel cmdline
  849. * @lmb: pointer to lmb handle, will be used for memory mgmt
  850. * @cmd_start: pointer to a ulong variable, will hold cmdline start
  851. * @cmd_end: pointer to a ulong variable, will hold cmdline end
  852. * @bootmap_base: ulong variable, holds offset in physical memory to
  853. * base of bootmap
  854. *
  855. * boot_get_cmdline() allocates space for kernel command line below
  856. * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt
  857. * variable is present its contents is copied to allocated kernel
  858. * command line.
  859. *
  860. * returns:
  861. * 0 - success
  862. * -1 - failure
  863. */
  864. int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end,
  865. ulong bootmap_base)
  866. {
  867. char *cmdline;
  868. char *s;
  869. cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf,
  870. CFG_BOOTMAPSZ + bootmap_base);
  871. if (cmdline == NULL)
  872. return -1;
  873. if ((s = getenv("bootargs")) == NULL)
  874. s = "";
  875. strcpy(cmdline, s);
  876. *cmd_start = (ulong) & cmdline[0];
  877. *cmd_end = *cmd_start + strlen(cmdline);
  878. debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
  879. return 0;
  880. }
  881. /**
  882. * boot_get_kbd - allocate and initialize kernel copy of board info
  883. * @lmb: pointer to lmb handle, will be used for memory mgmt
  884. * @kbd: double pointer to board info data
  885. * @bootmap_base: ulong variable, holds offset in physical memory to
  886. * base of bootmap
  887. *
  888. * boot_get_kbd() allocates space for kernel copy of board info data below
  889. * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with
  890. * the current u-boot board info data.
  891. *
  892. * returns:
  893. * 0 - success
  894. * -1 - failure
  895. */
  896. int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base)
  897. {
  898. *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
  899. CFG_BOOTMAPSZ + bootmap_base);
  900. if (*kbd == NULL)
  901. return -1;
  902. **kbd = *(gd->bd);
  903. debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd);
  904. #if defined(DEBUG) && defined(CONFIG_CMD_BDI)
  905. do_bdinfo(NULL, 0, 0, NULL);
  906. #endif
  907. return 0;
  908. }
  909. #endif /* CONFIG_PPC || CONFIG_M68K */
  910. #if defined(CONFIG_FIT)
  911. /*****************************************************************************/
  912. /* New uImage format routines */
  913. /*****************************************************************************/
  914. static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr,
  915. ulong *addr, const char **name)
  916. {
  917. const char *sep;
  918. *addr = addr_curr;
  919. *name = NULL;
  920. sep = strchr (spec, sepc);
  921. if (sep) {
  922. if (sep - spec > 0)
  923. *addr = simple_strtoul (spec, NULL, 16);
  924. *name = sep + 1;
  925. return 1;
  926. }
  927. return 0;
  928. }
  929. /**
  930. * fit_parse_conf - parse FIT configuration spec
  931. * @spec: input string, containing configuration spec
  932. * @add_curr: current image address (to be used as a possible default)
  933. * @addr: pointer to a ulong variable, will hold FIT image address of a given
  934. * configuration
  935. * @conf_name double pointer to a char, will hold pointer to a configuration
  936. * unit name
  937. *
  938. * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
  939. * where <addr> is a FIT image address that contains configuration
  940. * with a <conf> unit name.
  941. *
  942. * Address part is optional, and if omitted default add_curr will
  943. * be used instead.
  944. *
  945. * returns:
  946. * 1 if spec is a valid configuration string,
  947. * addr and conf_name are set accordingly
  948. * 0 otherwise
  949. */
  950. inline int fit_parse_conf (const char *spec, ulong addr_curr,
  951. ulong *addr, const char **conf_name)
  952. {
  953. return fit_parse_spec (spec, '#', addr_curr, addr, conf_name);
  954. }
  955. /**
  956. * fit_parse_subimage - parse FIT subimage spec
  957. * @spec: input string, containing subimage spec
  958. * @add_curr: current image address (to be used as a possible default)
  959. * @addr: pointer to a ulong variable, will hold FIT image address of a given
  960. * subimage
  961. * @image_name: double pointer to a char, will hold pointer to a subimage name
  962. *
  963. * fit_parse_subimage() expects subimage spec in the for of
  964. * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
  965. * subimage with a <subimg> unit name.
  966. *
  967. * Address part is optional, and if omitted default add_curr will
  968. * be used instead.
  969. *
  970. * returns:
  971. * 1 if spec is a valid subimage string,
  972. * addr and image_name are set accordingly
  973. * 0 otherwise
  974. */
  975. inline int fit_parse_subimage (const char *spec, ulong addr_curr,
  976. ulong *addr, const char **image_name)
  977. {
  978. return fit_parse_spec (spec, ':', addr_curr, addr, image_name);
  979. }
  980. #endif /* CONFIG_FIT */
  981. #endif /* !USE_HOSTCC */