image.c 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379
  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. #include <image.h>
  42. #if defined(CONFIG_FIT)
  43. #include <fdt.h>
  44. #include <libfdt.h>
  45. #include <fdt_support.h>
  46. #include <sha1.h>
  47. #endif
  48. #ifdef CONFIG_CMD_BDI
  49. extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  50. #endif
  51. DECLARE_GLOBAL_DATA_PTR;
  52. static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
  53. int argc, char *argv[],
  54. ulong rd_addr, uint8_t arch, int verify);
  55. #else
  56. #include "mkimage.h"
  57. #include <time.h>
  58. #include <image.h>
  59. #endif /* !USE_HOSTCC*/
  60. typedef struct table_entry {
  61. int id; /* as defined in image.h */
  62. char *sname; /* short (input) name */
  63. char *lname; /* long (output) name */
  64. } table_entry_t;
  65. static table_entry_t uimage_arch[] = {
  66. { IH_ARCH_INVALID, NULL, "Invalid ARCH", },
  67. { IH_ARCH_ALPHA, "alpha", "Alpha", },
  68. { IH_ARCH_ARM, "arm", "ARM", },
  69. { IH_ARCH_I386, "x86", "Intel x86", },
  70. { IH_ARCH_IA64, "ia64", "IA64", },
  71. { IH_ARCH_M68K, "m68k", "M68K", },
  72. { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", },
  73. { IH_ARCH_MIPS, "mips", "MIPS", },
  74. { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
  75. { IH_ARCH_NIOS, "nios", "NIOS", },
  76. { IH_ARCH_NIOS2, "nios2", "NIOS II", },
  77. { IH_ARCH_PPC, "ppc", "PowerPC", },
  78. { IH_ARCH_S390, "s390", "IBM S390", },
  79. { IH_ARCH_SH, "sh", "SuperH", },
  80. { IH_ARCH_SPARC, "sparc", "SPARC", },
  81. { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", },
  82. { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", },
  83. { IH_ARCH_AVR32, "avr32", "AVR32", },
  84. { -1, "", "", },
  85. };
  86. static table_entry_t uimage_os[] = {
  87. { IH_OS_INVALID, NULL, "Invalid OS", },
  88. #if defined(CONFIG_ARTOS) || defined(USE_HOSTCC)
  89. { IH_OS_ARTOS, "artos", "ARTOS", },
  90. #endif
  91. { IH_OS_LINUX, "linux", "Linux", },
  92. #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
  93. { IH_OS_LYNXOS, "lynxos", "LynxOS", },
  94. #endif
  95. { IH_OS_NETBSD, "netbsd", "NetBSD", },
  96. { IH_OS_RTEMS, "rtems", "RTEMS", },
  97. { IH_OS_U_BOOT, "u-boot", "U-Boot", },
  98. #if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC)
  99. { IH_OS_QNX, "qnx", "QNX", },
  100. { IH_OS_VXWORKS, "vxworks", "VxWorks", },
  101. #endif
  102. #ifdef USE_HOSTCC
  103. { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", },
  104. { IH_OS_DELL, "dell", "Dell", },
  105. { IH_OS_ESIX, "esix", "Esix", },
  106. { IH_OS_FREEBSD, "freebsd", "FreeBSD", },
  107. { IH_OS_IRIX, "irix", "Irix", },
  108. { IH_OS_NCR, "ncr", "NCR", },
  109. { IH_OS_OPENBSD, "openbsd", "OpenBSD", },
  110. { IH_OS_PSOS, "psos", "pSOS", },
  111. { IH_OS_SCO, "sco", "SCO", },
  112. { IH_OS_SOLARIS, "solaris", "Solaris", },
  113. { IH_OS_SVR4, "svr4", "SVR4", },
  114. #endif
  115. { -1, "", "", },
  116. };
  117. static table_entry_t uimage_type[] = {
  118. { IH_TYPE_INVALID, NULL, "Invalid Image", },
  119. { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", },
  120. { IH_TYPE_FIRMWARE, "firmware", "Firmware", },
  121. { IH_TYPE_KERNEL, "kernel", "Kernel Image", },
  122. { IH_TYPE_MULTI, "multi", "Multi-File Image", },
  123. { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", },
  124. { IH_TYPE_SCRIPT, "script", "Script", },
  125. { IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
  126. { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", },
  127. { -1, "", "", },
  128. };
  129. static table_entry_t uimage_comp[] = {
  130. { IH_COMP_NONE, "none", "uncompressed", },
  131. { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", },
  132. { IH_COMP_GZIP, "gzip", "gzip compressed", },
  133. { -1, "", "", },
  134. };
  135. unsigned long crc32 (unsigned long, const unsigned char *, unsigned int);
  136. static void genimg_print_size (uint32_t size);
  137. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  138. static void genimg_print_time (time_t timestamp);
  139. #endif
  140. /*****************************************************************************/
  141. /* Legacy format routines */
  142. /*****************************************************************************/
  143. int image_check_hcrc (image_header_t *hdr)
  144. {
  145. ulong hcrc;
  146. ulong len = image_get_header_size ();
  147. image_header_t header;
  148. /* Copy header so we can blank CRC field for re-calculation */
  149. memmove (&header, (char *)hdr, image_get_header_size ());
  150. image_set_hcrc (&header, 0);
  151. hcrc = crc32 (0, (unsigned char *)&header, len);
  152. return (hcrc == image_get_hcrc (hdr));
  153. }
  154. int image_check_dcrc (image_header_t *hdr)
  155. {
  156. ulong data = image_get_data (hdr);
  157. ulong len = image_get_data_size (hdr);
  158. ulong dcrc = crc32 (0, (unsigned char *)data, len);
  159. return (dcrc == image_get_dcrc (hdr));
  160. }
  161. #ifndef USE_HOSTCC
  162. int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz)
  163. {
  164. ulong dcrc = 0;
  165. ulong len = image_get_data_size (hdr);
  166. ulong data = image_get_data (hdr);
  167. #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  168. ulong cdata = data;
  169. ulong edata = cdata + len;
  170. while (cdata < edata) {
  171. ulong chunk = edata - cdata;
  172. if (chunk > chunksz)
  173. chunk = chunksz;
  174. dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk);
  175. cdata += chunk;
  176. WATCHDOG_RESET ();
  177. }
  178. #else
  179. dcrc = crc32 (0, (unsigned char *)data, len);
  180. #endif
  181. return (dcrc == image_get_dcrc (hdr));
  182. }
  183. #endif /* !USE_HOSTCC */
  184. /**
  185. * image_multi_count - get component (sub-image) count
  186. * @hdr: pointer to the header of the multi component image
  187. *
  188. * image_multi_count() returns number of components in a multi
  189. * component image.
  190. *
  191. * Note: no checking of the image type is done, caller must pass
  192. * a valid multi component image.
  193. *
  194. * returns:
  195. * number of components
  196. */
  197. ulong image_multi_count (image_header_t *hdr)
  198. {
  199. ulong i, count = 0;
  200. uint32_t *size;
  201. /* get start of the image payload, which in case of multi
  202. * component images that points to a table of component sizes */
  203. size = (uint32_t *)image_get_data (hdr);
  204. /* count non empty slots */
  205. for (i = 0; size[i]; ++i)
  206. count++;
  207. return count;
  208. }
  209. /**
  210. * image_multi_getimg - get component data address and size
  211. * @hdr: pointer to the header of the multi component image
  212. * @idx: index of the requested component
  213. * @data: pointer to a ulong variable, will hold component data address
  214. * @len: pointer to a ulong variable, will hold component size
  215. *
  216. * image_multi_getimg() returns size and data address for the requested
  217. * component in a multi component image.
  218. *
  219. * Note: no checking of the image type is done, caller must pass
  220. * a valid multi component image.
  221. *
  222. * returns:
  223. * data address and size of the component, if idx is valid
  224. * 0 in data and len, if idx is out of range
  225. */
  226. void image_multi_getimg (image_header_t *hdr, ulong idx,
  227. ulong *data, ulong *len)
  228. {
  229. int i;
  230. uint32_t *size;
  231. ulong offset, tail, count, img_data;
  232. /* get number of component */
  233. count = image_multi_count (hdr);
  234. /* get start of the image payload, which in case of multi
  235. * component images that points to a table of component sizes */
  236. size = (uint32_t *)image_get_data (hdr);
  237. /* get address of the proper component data start, which means
  238. * skipping sizes table (add 1 for last, null entry) */
  239. img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t);
  240. if (idx < count) {
  241. *len = uimage_to_cpu (size[idx]);
  242. offset = 0;
  243. tail = 0;
  244. /* go over all indices preceding requested component idx */
  245. for (i = 0; i < idx; i++) {
  246. /* add up i-th component size */
  247. offset += uimage_to_cpu (size[i]);
  248. /* add up alignment for i-th component */
  249. tail += (4 - uimage_to_cpu (size[i]) % 4);
  250. }
  251. /* calculate idx-th component data address */
  252. *data = img_data + offset + tail;
  253. } else {
  254. *len = 0;
  255. *data = 0;
  256. }
  257. }
  258. static void image_print_type (image_header_t *hdr)
  259. {
  260. const char *os, *arch, *type, *comp;
  261. os = genimg_get_os_name (image_get_os (hdr));
  262. arch = genimg_get_arch_name (image_get_arch (hdr));
  263. type = genimg_get_type_name (image_get_type (hdr));
  264. comp = genimg_get_comp_name (image_get_comp (hdr));
  265. printf ("%s %s %s (%s)\n", arch, os, type, comp);
  266. }
  267. /**
  268. * __image_print_contents - prints out the contents of the legacy format image
  269. * @hdr: pointer to the legacy format image header
  270. * @p: pointer to prefix string
  271. *
  272. * __image_print_contents() formats a multi line legacy image contents description.
  273. * The routine prints out all header fields followed by the size/offset data
  274. * for MULTI/SCRIPT images.
  275. *
  276. * returns:
  277. * no returned results
  278. */
  279. static void __image_print_contents (image_header_t *hdr, const char *p)
  280. {
  281. printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr));
  282. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  283. printf ("%sCreated: ", p);
  284. genimg_print_time ((time_t)image_get_time (hdr));
  285. #endif
  286. printf ("%sImage Type: ", p);
  287. image_print_type (hdr);
  288. printf ("%sData Size: ", p);
  289. genimg_print_size (image_get_data_size (hdr));
  290. printf ("%sLoad Address: %08x\n", p, image_get_load (hdr));
  291. printf ("%sEntry Point: %08x\n", p, image_get_ep (hdr));
  292. if (image_check_type (hdr, IH_TYPE_MULTI) ||
  293. image_check_type (hdr, IH_TYPE_SCRIPT)) {
  294. int i;
  295. ulong data, len;
  296. ulong count = image_multi_count (hdr);
  297. printf ("%sContents:\n", p);
  298. for (i = 0; i < count; i++) {
  299. image_multi_getimg (hdr, i, &data, &len);
  300. printf ("%s Image %d: ", p, i);
  301. genimg_print_size (len);
  302. if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) {
  303. /*
  304. * the user may need to know offsets
  305. * if planning to do something with
  306. * multiple files
  307. */
  308. printf ("%s Offset = 0x%08lx\n", p, data);
  309. }
  310. }
  311. }
  312. }
  313. inline void image_print_contents (image_header_t *hdr)
  314. {
  315. __image_print_contents (hdr, " ");
  316. }
  317. inline void image_print_contents_noindent (image_header_t *hdr)
  318. {
  319. __image_print_contents (hdr, "");
  320. }
  321. #ifndef USE_HOSTCC
  322. /**
  323. * image_get_ramdisk - get and verify ramdisk image
  324. * @cmdtp: command table pointer
  325. * @flag: command flag
  326. * @argc: command argument count
  327. * @argv: command argument list
  328. * @rd_addr: ramdisk image start address
  329. * @arch: expected ramdisk architecture
  330. * @verify: checksum verification flag
  331. *
  332. * image_get_ramdisk() returns a pointer to the verified ramdisk image
  333. * header. Routine receives image start address and expected architecture
  334. * flag. Verification done covers data and header integrity and os/type/arch
  335. * fields checking.
  336. *
  337. * If dataflash support is enabled routine checks for dataflash addresses
  338. * and handles required dataflash reads.
  339. *
  340. * returns:
  341. * pointer to a ramdisk image header, if image was found and valid
  342. * otherwise, return NULL
  343. */
  344. static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
  345. int argc, char *argv[],
  346. ulong rd_addr, uint8_t arch, int verify)
  347. {
  348. image_header_t *rd_hdr;
  349. show_boot_progress (9);
  350. rd_hdr = (image_header_t *)rd_addr;
  351. if (!image_check_magic (rd_hdr)) {
  352. puts ("Bad Magic Number\n");
  353. show_boot_progress (-10);
  354. return NULL;
  355. }
  356. if (!image_check_hcrc (rd_hdr)) {
  357. puts ("Bad Header Checksum\n");
  358. show_boot_progress (-11);
  359. return NULL;
  360. }
  361. show_boot_progress (10);
  362. image_print_contents (rd_hdr);
  363. if (verify) {
  364. puts(" Verifying Checksum ... ");
  365. if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) {
  366. puts ("Bad Data CRC\n");
  367. show_boot_progress (-12);
  368. return NULL;
  369. }
  370. puts("OK\n");
  371. }
  372. show_boot_progress (11);
  373. if (!image_check_os (rd_hdr, IH_OS_LINUX) ||
  374. !image_check_arch (rd_hdr, arch) ||
  375. !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) {
  376. printf ("No Linux %s Ramdisk Image\n",
  377. genimg_get_arch_name(arch));
  378. show_boot_progress (-13);
  379. return NULL;
  380. }
  381. return rd_hdr;
  382. }
  383. #endif /* !USE_HOSTCC */
  384. /*****************************************************************************/
  385. /* Shared dual-format routines */
  386. /*****************************************************************************/
  387. #ifndef USE_HOSTCC
  388. int getenv_verify (void)
  389. {
  390. char *s = getenv ("verify");
  391. return (s && (*s == 'n')) ? 0 : 1;
  392. }
  393. int getenv_autostart (void)
  394. {
  395. char *s = getenv ("autostart");
  396. return (s && (*s == 'n')) ? 0 : 1;
  397. }
  398. ulong getenv_bootm_low(void)
  399. {
  400. char *s = getenv ("bootm_low");
  401. if (s) {
  402. ulong tmp = simple_strtoul (s, NULL, 16);
  403. return tmp;
  404. }
  405. #ifdef CFG_SDRAM_BASE
  406. return CFG_SDRAM_BASE;
  407. #else
  408. return 0;
  409. #endif
  410. }
  411. ulong getenv_bootm_size(void)
  412. {
  413. char *s = getenv ("bootm_size");
  414. if (s) {
  415. ulong tmp = simple_strtoul (s, NULL, 16);
  416. return tmp;
  417. }
  418. return gd->bd->bi_memsize;
  419. }
  420. void memmove_wd (void *to, void *from, size_t len, ulong chunksz)
  421. {
  422. #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
  423. while (len > 0) {
  424. size_t tail = (len > chunksz) ? chunksz : len;
  425. WATCHDOG_RESET ();
  426. memmove (to, from, tail);
  427. to += tail;
  428. from += tail;
  429. len -= tail;
  430. }
  431. #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
  432. memmove (to, from, len);
  433. #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
  434. }
  435. #endif /* !USE_HOSTCC */
  436. static void genimg_print_size (uint32_t size)
  437. {
  438. #ifndef USE_HOSTCC
  439. printf ("%d Bytes = ", size);
  440. print_size (size, "\n");
  441. #else
  442. printf ("%d Bytes = %.2f kB = %.2f MB\n",
  443. size, (double)size / 1.024e3,
  444. (double)size / 1.048576e6);
  445. #endif
  446. }
  447. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  448. static void genimg_print_time (time_t timestamp)
  449. {
  450. #ifndef USE_HOSTCC
  451. struct rtc_time tm;
  452. to_tm (timestamp, &tm);
  453. printf ("%4d-%02d-%02d %2d:%02d:%02d UTC\n",
  454. tm.tm_year, tm.tm_mon, tm.tm_mday,
  455. tm.tm_hour, tm.tm_min, tm.tm_sec);
  456. #else
  457. printf ("%s", ctime(&timestamp));
  458. #endif
  459. }
  460. #endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */
  461. /**
  462. * get_table_entry_name - translate entry id to long name
  463. * @table: pointer to a translation table for entries of a specific type
  464. * @msg: message to be returned when translation fails
  465. * @id: entry id to be translated
  466. *
  467. * get_table_entry_name() will go over translation table trying to find
  468. * entry that matches given id. If matching entry is found, its long
  469. * name is returned to the caller.
  470. *
  471. * returns:
  472. * long entry name if translation succeeds
  473. * msg otherwise
  474. */
  475. static char *get_table_entry_name (table_entry_t *table, char *msg, int id)
  476. {
  477. for (; table->id >= 0; ++table) {
  478. if (table->id == id)
  479. return (table->lname);
  480. }
  481. return (msg);
  482. }
  483. const char *genimg_get_os_name (uint8_t os)
  484. {
  485. return (get_table_entry_name (uimage_os, "Unknown OS", os));
  486. }
  487. const char *genimg_get_arch_name (uint8_t arch)
  488. {
  489. return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch));
  490. }
  491. const char *genimg_get_type_name (uint8_t type)
  492. {
  493. return (get_table_entry_name (uimage_type, "Unknown Image", type));
  494. }
  495. const char *genimg_get_comp_name (uint8_t comp)
  496. {
  497. return (get_table_entry_name (uimage_comp, "Unknown Compression", comp));
  498. }
  499. /**
  500. * get_table_entry_id - translate short entry name to id
  501. * @table: pointer to a translation table for entries of a specific type
  502. * @table_name: to be used in case of error
  503. * @name: entry short name to be translated
  504. *
  505. * get_table_entry_id() will go over translation table trying to find
  506. * entry that matches given short name. If matching entry is found,
  507. * its id returned to the caller.
  508. *
  509. * returns:
  510. * entry id if translation succeeds
  511. * -1 otherwise
  512. */
  513. static int get_table_entry_id (table_entry_t *table,
  514. const char *table_name, const char *name)
  515. {
  516. table_entry_t *t;
  517. #ifdef USE_HOSTCC
  518. int first = 1;
  519. for (t = table; t->id >= 0; ++t) {
  520. if (t->sname && strcasecmp(t->sname, name) == 0)
  521. return (t->id);
  522. }
  523. fprintf (stderr, "\nInvalid %s Type - valid names are", table_name);
  524. for (t = table; t->id >= 0; ++t) {
  525. if (t->sname == NULL)
  526. continue;
  527. fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname);
  528. first = 0;
  529. }
  530. fprintf (stderr, "\n");
  531. #else
  532. for (t = table; t->id >= 0; ++t) {
  533. if (t->sname && strcmp(t->sname, name) == 0)
  534. return (t->id);
  535. }
  536. debug ("Invalid %s Type: %s\n", table_name, name);
  537. #endif /* USE_HOSTCC */
  538. return (-1);
  539. }
  540. int genimg_get_os_id (const char *name)
  541. {
  542. return (get_table_entry_id (uimage_os, "OS", name));
  543. }
  544. int genimg_get_arch_id (const char *name)
  545. {
  546. return (get_table_entry_id (uimage_arch, "CPU", name));
  547. }
  548. int genimg_get_type_id (const char *name)
  549. {
  550. return (get_table_entry_id (uimage_type, "Image", name));
  551. }
  552. int genimg_get_comp_id (const char *name)
  553. {
  554. return (get_table_entry_id (uimage_comp, "Compression", name));
  555. }
  556. #ifndef USE_HOSTCC
  557. /**
  558. * genimg_get_format - get image format type
  559. * @img_addr: image start address
  560. *
  561. * genimg_get_format() checks whether provided address points to a valid
  562. * legacy or FIT image.
  563. *
  564. * New uImage format and FDT blob are based on a libfdt. FDT blob
  565. * may be passed directly or embedded in a FIT image. In both situations
  566. * genimg_get_format() must be able to dectect libfdt header.
  567. *
  568. * returns:
  569. * image format type or IMAGE_FORMAT_INVALID if no image is present
  570. */
  571. int genimg_get_format (void *img_addr)
  572. {
  573. ulong format = IMAGE_FORMAT_INVALID;
  574. image_header_t *hdr;
  575. #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
  576. char *fit_hdr;
  577. #endif
  578. hdr = (image_header_t *)img_addr;
  579. if (image_check_magic(hdr))
  580. format = IMAGE_FORMAT_LEGACY;
  581. #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
  582. else {
  583. fit_hdr = (char *)img_addr;
  584. if (fdt_check_header (fit_hdr) == 0)
  585. format = IMAGE_FORMAT_FIT;
  586. }
  587. #endif
  588. return format;
  589. }
  590. /**
  591. * genimg_get_image - get image from special storage (if necessary)
  592. * @img_addr: image start address
  593. *
  594. * genimg_get_image() checks if provided image start adddress is located
  595. * in a dataflash storage. If so, image is moved to a system RAM memory.
  596. *
  597. * returns:
  598. * image start address after possible relocation from special storage
  599. */
  600. ulong genimg_get_image (ulong img_addr)
  601. {
  602. ulong ram_addr = img_addr;
  603. #ifdef CONFIG_HAS_DATAFLASH
  604. ulong h_size, d_size;
  605. if (addr_dataflash (img_addr)){
  606. /* ger RAM address */
  607. ram_addr = CFG_LOAD_ADDR;
  608. /* get header size */
  609. h_size = image_get_header_size ();
  610. #if defined(CONFIG_FIT)
  611. if (sizeof(struct fdt_header) > h_size)
  612. h_size = sizeof(struct fdt_header);
  613. #endif
  614. /* read in header */
  615. debug (" Reading image header from dataflash address "
  616. "%08lx to RAM address %08lx\n", img_addr, ram_addr);
  617. read_dataflash (img_addr, h_size, (char *)ram_addr);
  618. /* get data size */
  619. switch (genimg_get_format ((void *)ram_addr)) {
  620. case IMAGE_FORMAT_LEGACY:
  621. d_size = image_get_data_size ((image_header_t *)ram_addr);
  622. debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n",
  623. ram_addr, d_size);
  624. break;
  625. #if defined(CONFIG_FIT)
  626. case IMAGE_FORMAT_FIT:
  627. d_size = fit_get_size ((const void *)ram_addr) - h_size;
  628. debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n",
  629. ram_addr, d_size);
  630. break;
  631. #endif
  632. default:
  633. printf (" No valid image found at 0x%08lx\n", img_addr);
  634. return ram_addr;
  635. }
  636. /* read in image data */
  637. debug (" Reading image remaining data from dataflash address "
  638. "%08lx to RAM address %08lx\n", img_addr + h_size,
  639. ram_addr + h_size);
  640. read_dataflash (img_addr + h_size, d_size,
  641. (char *)(ram_addr + h_size));
  642. }
  643. #endif /* CONFIG_HAS_DATAFLASH */
  644. return ram_addr;
  645. }
  646. /**
  647. * boot_get_ramdisk - main ramdisk handling routine
  648. * @cmdtp: command table pointer
  649. * @flag: command flag
  650. * @argc: command argument count
  651. * @argv: command argument list
  652. * @images: pointer to the bootm images structure
  653. * @arch: expected ramdisk architecture
  654. * @rd_start: pointer to a ulong variable, will hold ramdisk start address
  655. * @rd_end: pointer to a ulong variable, will hold ramdisk end
  656. *
  657. * boot_get_ramdisk() is responsible for finding a valid ramdisk image.
  658. * Curently supported are the following ramdisk sources:
  659. * - multicomponent kernel/ramdisk image,
  660. * - commandline provided address of decicated ramdisk image.
  661. *
  662. * returns:
  663. * rd_start and rd_end are set to ramdisk start/end addresses if
  664. * ramdisk image is found and valid
  665. * rd_start and rd_end are set to 0 if no ramdisk exists
  666. * return 1 if ramdisk image is found but corrupted
  667. */
  668. int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
  669. bootm_headers_t *images, uint8_t arch,
  670. ulong *rd_start, ulong *rd_end)
  671. {
  672. ulong rd_addr, rd_load;
  673. ulong rd_data, rd_len;
  674. image_header_t *rd_hdr;
  675. #if defined(CONFIG_FIT)
  676. void *fit_hdr;
  677. const char *fit_uname_config = NULL;
  678. const char *fit_uname_ramdisk = NULL;
  679. ulong default_addr;
  680. #endif
  681. /*
  682. * Look for a '-' which indicates to ignore the
  683. * ramdisk argument
  684. */
  685. if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) {
  686. debug ("## Skipping init Ramdisk\n");
  687. rd_len = rd_data = 0;
  688. } else if (argc >= 3) {
  689. #if defined(CONFIG_FIT)
  690. /*
  691. * If the init ramdisk comes from the FIT image and the FIT image
  692. * address is omitted in the command line argument, try to use
  693. * os FIT image address or default load address.
  694. */
  695. if (images->fit_uname_os)
  696. default_addr = (ulong)images->fit_hdr_os;
  697. else
  698. default_addr = load_addr;
  699. if (fit_parse_conf (argv[2], default_addr,
  700. &rd_addr, &fit_uname_config)) {
  701. debug ("* ramdisk: config '%s' from image at 0x%08lx\n",
  702. fit_uname_config, rd_addr);
  703. } else if (fit_parse_subimage (argv[2], default_addr,
  704. &rd_addr, &fit_uname_ramdisk)) {
  705. debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n",
  706. fit_uname_ramdisk, rd_addr);
  707. } else
  708. #endif
  709. {
  710. rd_addr = simple_strtoul(argv[2], NULL, 16);
  711. debug ("* ramdisk: cmdline image address = 0x%08lx\n",
  712. rd_addr);
  713. }
  714. /* copy from dataflash if needed */
  715. printf ("## Loading init Ramdisk Image at %08lx ...\n",
  716. rd_addr);
  717. rd_addr = genimg_get_image (rd_addr);
  718. /*
  719. * Check if there is an initrd image at the
  720. * address provided in the second bootm argument
  721. * check image type, for FIT images get FIT node.
  722. */
  723. switch (genimg_get_format ((void *)rd_addr)) {
  724. case IMAGE_FORMAT_LEGACY:
  725. debug ("* ramdisk: legacy format image\n");
  726. rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv,
  727. rd_addr, arch, images->verify);
  728. if (rd_hdr == NULL) {
  729. *rd_start = 0;
  730. *rd_end = 0;
  731. return 1;
  732. }
  733. rd_data = image_get_data (rd_hdr);
  734. rd_len = image_get_data_size (rd_hdr);
  735. rd_load = image_get_load (rd_hdr);
  736. break;
  737. #if defined(CONFIG_FIT)
  738. case IMAGE_FORMAT_FIT:
  739. fit_hdr = (void *)rd_addr;
  740. debug ("* ramdisk: FIT format image\n");
  741. fit_unsupported_reset ("ramdisk");
  742. return 1;
  743. #endif
  744. default:
  745. printf ("Wrong Image Format for %s command\n",
  746. cmdtp->name);
  747. rd_data = rd_len = 0;
  748. }
  749. #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
  750. /*
  751. * We need to copy the ramdisk to SRAM to let Linux boot
  752. */
  753. if (rd_data) {
  754. memmove ((void *)rd_load, (uchar *)rd_data, rd_len);
  755. rd_data = rd_load;
  756. }
  757. #endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
  758. } else if (images->legacy_hdr_valid &&
  759. image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) {
  760. /*
  761. * Now check if we have a legacy mult-component image,
  762. * get second entry data start address and len.
  763. */
  764. show_boot_progress (13);
  765. printf ("## Loading init Ramdisk from multi component "
  766. "Image at %08lx ...\n",
  767. (ulong)images->legacy_hdr_os);
  768. image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len);
  769. } else {
  770. /*
  771. * no initrd image
  772. */
  773. show_boot_progress (14);
  774. rd_len = rd_data = 0;
  775. }
  776. if (!rd_data) {
  777. debug ("## No init Ramdisk\n");
  778. *rd_start = 0;
  779. *rd_end = 0;
  780. } else {
  781. *rd_start = rd_data;
  782. *rd_end = rd_data + rd_len;
  783. }
  784. debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
  785. *rd_start, *rd_end);
  786. return 0;
  787. }
  788. #if defined(CONFIG_PPC) || defined(CONFIG_M68K)
  789. /**
  790. * boot_ramdisk_high - relocate init ramdisk
  791. * @lmb: pointer to lmb handle, will be used for memory mgmt
  792. * @rd_data: ramdisk data start address
  793. * @rd_len: ramdisk data length
  794. * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
  795. * start address (after possible relocation)
  796. * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
  797. * end address (after possible relocation)
  798. *
  799. * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement
  800. * variable and if requested ramdisk data is moved to a specified location.
  801. *
  802. * Initrd_start and initrd_end are set to final (after relocation) ramdisk
  803. * start/end addresses if ramdisk image start and len were provided,
  804. * otherwise set initrd_start and initrd_end set to zeros.
  805. *
  806. * returns:
  807. * 0 - success
  808. * -1 - failure
  809. */
  810. int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len,
  811. ulong *initrd_start, ulong *initrd_end)
  812. {
  813. char *s;
  814. ulong initrd_high;
  815. int initrd_copy_to_ram = 1;
  816. if ((s = getenv ("initrd_high")) != NULL) {
  817. /* a value of "no" or a similar string will act like 0,
  818. * turning the "load high" feature off. This is intentional.
  819. */
  820. initrd_high = simple_strtoul (s, NULL, 16);
  821. if (initrd_high == ~0)
  822. initrd_copy_to_ram = 0;
  823. } else {
  824. /* not set, no restrictions to load high */
  825. initrd_high = ~0;
  826. }
  827. debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
  828. initrd_high, initrd_copy_to_ram);
  829. if (rd_data) {
  830. if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */
  831. debug (" in-place initrd\n");
  832. *initrd_start = rd_data;
  833. *initrd_end = rd_data + rd_len;
  834. lmb_reserve(lmb, rd_data, rd_len);
  835. } else {
  836. if (initrd_high)
  837. *initrd_start = lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high);
  838. else
  839. *initrd_start = lmb_alloc (lmb, rd_len, 0x1000);
  840. if (*initrd_start == 0) {
  841. puts ("ramdisk - allocation error\n");
  842. goto error;
  843. }
  844. show_boot_progress (12);
  845. *initrd_end = *initrd_start + rd_len;
  846. printf (" Loading Ramdisk to %08lx, end %08lx ... ",
  847. *initrd_start, *initrd_end);
  848. memmove_wd ((void *)*initrd_start,
  849. (void *)rd_data, rd_len, CHUNKSZ);
  850. puts ("OK\n");
  851. }
  852. } else {
  853. *initrd_start = 0;
  854. *initrd_end = 0;
  855. }
  856. debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
  857. *initrd_start, *initrd_end);
  858. return 0;
  859. error:
  860. return -1;
  861. }
  862. /**
  863. * boot_get_cmdline - allocate and initialize kernel cmdline
  864. * @lmb: pointer to lmb handle, will be used for memory mgmt
  865. * @cmd_start: pointer to a ulong variable, will hold cmdline start
  866. * @cmd_end: pointer to a ulong variable, will hold cmdline end
  867. * @bootmap_base: ulong variable, holds offset in physical memory to
  868. * base of bootmap
  869. *
  870. * boot_get_cmdline() allocates space for kernel command line below
  871. * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt
  872. * variable is present its contents is copied to allocated kernel
  873. * command line.
  874. *
  875. * returns:
  876. * 0 - success
  877. * -1 - failure
  878. */
  879. int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end,
  880. ulong bootmap_base)
  881. {
  882. char *cmdline;
  883. char *s;
  884. cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf,
  885. CFG_BOOTMAPSZ + bootmap_base);
  886. if (cmdline == NULL)
  887. return -1;
  888. if ((s = getenv("bootargs")) == NULL)
  889. s = "";
  890. strcpy(cmdline, s);
  891. *cmd_start = (ulong) & cmdline[0];
  892. *cmd_end = *cmd_start + strlen(cmdline);
  893. debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
  894. return 0;
  895. }
  896. /**
  897. * boot_get_kbd - allocate and initialize kernel copy of board info
  898. * @lmb: pointer to lmb handle, will be used for memory mgmt
  899. * @kbd: double pointer to board info data
  900. * @bootmap_base: ulong variable, holds offset in physical memory to
  901. * base of bootmap
  902. *
  903. * boot_get_kbd() allocates space for kernel copy of board info data below
  904. * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with
  905. * the current u-boot board info data.
  906. *
  907. * returns:
  908. * 0 - success
  909. * -1 - failure
  910. */
  911. int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base)
  912. {
  913. *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
  914. CFG_BOOTMAPSZ + bootmap_base);
  915. if (*kbd == NULL)
  916. return -1;
  917. **kbd = *(gd->bd);
  918. debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd);
  919. #if defined(DEBUG) && defined(CONFIG_CMD_BDI)
  920. do_bdinfo(NULL, 0, 0, NULL);
  921. #endif
  922. return 0;
  923. }
  924. #endif /* CONFIG_PPC || CONFIG_M68K */
  925. #endif /* !USE_HOSTCC */
  926. #if defined(CONFIG_FIT)
  927. /*****************************************************************************/
  928. /* New uImage format routines */
  929. /*****************************************************************************/
  930. #ifndef USE_HOSTCC
  931. static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr,
  932. ulong *addr, const char **name)
  933. {
  934. const char *sep;
  935. *addr = addr_curr;
  936. *name = NULL;
  937. sep = strchr (spec, sepc);
  938. if (sep) {
  939. if (sep - spec > 0)
  940. *addr = simple_strtoul (spec, NULL, 16);
  941. *name = sep + 1;
  942. return 1;
  943. }
  944. return 0;
  945. }
  946. /**
  947. * fit_parse_conf - parse FIT configuration spec
  948. * @spec: input string, containing configuration spec
  949. * @add_curr: current image address (to be used as a possible default)
  950. * @addr: pointer to a ulong variable, will hold FIT image address of a given
  951. * configuration
  952. * @conf_name double pointer to a char, will hold pointer to a configuration
  953. * unit name
  954. *
  955. * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
  956. * where <addr> is a FIT image address that contains configuration
  957. * with a <conf> unit name.
  958. *
  959. * Address part is optional, and if omitted default add_curr will
  960. * be used instead.
  961. *
  962. * returns:
  963. * 1 if spec is a valid configuration string,
  964. * addr and conf_name are set accordingly
  965. * 0 otherwise
  966. */
  967. inline int fit_parse_conf (const char *spec, ulong addr_curr,
  968. ulong *addr, const char **conf_name)
  969. {
  970. return fit_parse_spec (spec, '#', addr_curr, addr, conf_name);
  971. }
  972. /**
  973. * fit_parse_subimage - parse FIT subimage spec
  974. * @spec: input string, containing subimage spec
  975. * @add_curr: current image address (to be used as a possible default)
  976. * @addr: pointer to a ulong variable, will hold FIT image address of a given
  977. * subimage
  978. * @image_name: double pointer to a char, will hold pointer to a subimage name
  979. *
  980. * fit_parse_subimage() expects subimage spec in the for of
  981. * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
  982. * subimage with a <subimg> unit name.
  983. *
  984. * Address part is optional, and if omitted default add_curr will
  985. * be used instead.
  986. *
  987. * returns:
  988. * 1 if spec is a valid subimage string,
  989. * addr and image_name are set accordingly
  990. * 0 otherwise
  991. */
  992. inline int fit_parse_subimage (const char *spec, ulong addr_curr,
  993. ulong *addr, const char **image_name)
  994. {
  995. return fit_parse_spec (spec, ':', addr_curr, addr, image_name);
  996. }
  997. #endif /* !USE_HOSTCC */
  998. static void fit_get_debug (const void *fit, int noffset,
  999. char *prop_name, int err)
  1000. {
  1001. debug ("Can't get '%s' property from FIT 0x%08lx, "
  1002. "node: offset %d, name %s (%s)\n",
  1003. prop_name, (ulong)fit, noffset,
  1004. fit_get_name (fit, noffset, NULL),
  1005. fdt_strerror (err));
  1006. }
  1007. /**
  1008. * __fit_print_contents - prints out the contents of the FIT format image
  1009. * @fit: pointer to the FIT format image header
  1010. * @p: pointer to prefix string
  1011. *
  1012. * __fit_print_contents() formats a multi line FIT image contents description.
  1013. * The routine prints out FIT image properties (root node level) follwed by
  1014. * the details of each component image.
  1015. *
  1016. * returns:
  1017. * no returned results
  1018. */
  1019. static void __fit_print_contents (const void *fit, const char *p)
  1020. {
  1021. char *desc;
  1022. char *uname;
  1023. int images_noffset;
  1024. int confs_noffset;
  1025. int noffset;
  1026. int ndepth;
  1027. int count = 0;
  1028. int ret;
  1029. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  1030. time_t timestamp;
  1031. #endif
  1032. /* Root node properties */
  1033. ret = fit_get_desc (fit, 0, &desc);
  1034. printf ("%sFIT description: ", p);
  1035. if (ret)
  1036. printf ("unavailable\n");
  1037. else
  1038. printf ("%s\n", desc);
  1039. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  1040. ret = fit_get_timestamp (fit, 0, &timestamp);
  1041. printf ("%sCreated: ", p);
  1042. if (ret)
  1043. printf ("unavailable\n");
  1044. else
  1045. genimg_print_time (timestamp);
  1046. #endif
  1047. /* Find images parent node offset */
  1048. images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
  1049. if (images_noffset < 0) {
  1050. printf ("Can't find images parent node '%s' (%s)\n",
  1051. FIT_IMAGES_PATH, fdt_strerror (images_noffset));
  1052. return;
  1053. }
  1054. /* Process its subnodes, print out component images details */
  1055. for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth);
  1056. (noffset >= 0) && (ndepth > 0);
  1057. noffset = fdt_next_node (fit, noffset, &ndepth)) {
  1058. if (ndepth == 1) {
  1059. /*
  1060. * Direct child node of the images parent node,
  1061. * i.e. component image node.
  1062. */
  1063. printf ("%s Image %u (%s)\n", p, count++,
  1064. fit_get_name(fit, noffset, NULL));
  1065. fit_image_print (fit, noffset, p);
  1066. }
  1067. }
  1068. /* Find configurations parent node offset */
  1069. confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH);
  1070. if (confs_noffset < 0) {
  1071. debug ("Can't get configurations parent node '%s' (%s)\n",
  1072. FIT_CONFS_PATH, fdt_strerror (confs_noffset));
  1073. return;
  1074. }
  1075. /* get default configuration unit name from default property */
  1076. uname = (char *)fdt_getprop (fit, noffset, FIT_DEFAULT_PROP, NULL);
  1077. if (uname)
  1078. printf ("%s Default Configuration: '%s'\n", p, uname);
  1079. /* Process its subnodes, print out configurations details */
  1080. for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, confs_noffset, &ndepth);
  1081. (noffset >= 0) && (ndepth > 0);
  1082. noffset = fdt_next_node (fit, noffset, &ndepth)) {
  1083. if (ndepth == 1) {
  1084. /*
  1085. * Direct child node of the configurations parent node,
  1086. * i.e. configuration node.
  1087. */
  1088. printf ("%s Configuration %u (%s)\n", p, count++,
  1089. fit_get_name(fit, noffset, NULL));
  1090. fit_conf_print (fit, noffset, p);
  1091. }
  1092. }
  1093. }
  1094. inline void fit_print_contents (const void *fit)
  1095. {
  1096. __fit_print_contents (fit, " ");
  1097. }
  1098. inline void fit_print_contents_noindent (const void *fit)
  1099. {
  1100. __fit_print_contents (fit, "");
  1101. }
  1102. /**
  1103. * fit_image_print - prints out the FIT component image details
  1104. * @fit: pointer to the FIT format image header
  1105. * @image_noffset: offset of the component image node
  1106. * @p: pointer to prefix string
  1107. *
  1108. * fit_image_print() lists all mandatory properies for the processed component
  1109. * image. If present, hash nodes are printed out as well.
  1110. *
  1111. * returns:
  1112. * no returned results
  1113. */
  1114. void fit_image_print (const void *fit, int image_noffset, const char *p)
  1115. {
  1116. char *desc;
  1117. uint8_t type, arch, os, comp;
  1118. size_t size;
  1119. ulong load, entry;
  1120. const void *data;
  1121. int noffset;
  1122. int ndepth;
  1123. int ret;
  1124. /* Mandatory properties */
  1125. ret = fit_get_desc (fit, image_noffset, &desc);
  1126. printf ("%s Description: ", p);
  1127. if (ret)
  1128. printf ("unavailable\n");
  1129. else
  1130. printf ("%s\n", desc);
  1131. fit_image_get_type (fit, image_noffset, &type);
  1132. printf ("%s Type: %s\n", p, genimg_get_type_name (type));
  1133. fit_image_get_comp (fit, image_noffset, &comp);
  1134. printf ("%s Compression: %s\n", p, genimg_get_comp_name (comp));
  1135. ret = fit_image_get_data (fit, image_noffset, &data, &size);
  1136. #ifndef USE_HOSTCC
  1137. printf ("%s Data Start: ", p);
  1138. if (ret)
  1139. printf ("unavailable\n");
  1140. else
  1141. printf ("0x%08lx\n", (ulong)data);
  1142. #endif
  1143. printf ("%s Data Size: ", p);
  1144. if (ret)
  1145. printf ("unavailable\n");
  1146. else
  1147. genimg_print_size (size);
  1148. /* Remaining, type dependent properties */
  1149. if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
  1150. (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
  1151. (type == IH_TYPE_FLATDT)) {
  1152. fit_image_get_arch (fit, image_noffset, &arch);
  1153. printf ("%s Architecture: %s\n", p, genimg_get_arch_name (arch));
  1154. }
  1155. if (type == IH_TYPE_KERNEL) {
  1156. fit_image_get_os (fit, image_noffset, &os);
  1157. printf ("%s OS: %s\n", p, genimg_get_os_name (os));
  1158. }
  1159. if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) {
  1160. ret = fit_image_get_load (fit, image_noffset, &load);
  1161. printf ("%s Load Address: ", p);
  1162. if (ret)
  1163. printf ("unavailable\n");
  1164. else
  1165. printf ("0x%08lx\n", load);
  1166. fit_image_get_entry (fit, image_noffset, &entry);
  1167. printf ("%s Entry Point: ", p);
  1168. if (ret)
  1169. printf ("unavailable\n");
  1170. else
  1171. printf ("0x%08lx\n", entry);
  1172. }
  1173. /* Process all hash subnodes of the component image node */
  1174. for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth);
  1175. (noffset >= 0) && (ndepth > 0);
  1176. noffset = fdt_next_node (fit, noffset, &ndepth)) {
  1177. if (ndepth == 1) {
  1178. /* Direct child node of the component image node */
  1179. fit_image_print_hash (fit, noffset, p);
  1180. }
  1181. }
  1182. }
  1183. /**
  1184. * fit_image_print_hash - prints out the hash node details
  1185. * @fit: pointer to the FIT format image header
  1186. * @noffset: offset of the hash node
  1187. * @p: pointer to prefix string
  1188. *
  1189. * fit_image_print_hash() lists properies for the processed hash node
  1190. *
  1191. * returns:
  1192. * no returned results
  1193. */
  1194. void fit_image_print_hash (const void *fit, int noffset, const char *p)
  1195. {
  1196. char *algo;
  1197. uint8_t *value;
  1198. int value_len;
  1199. int i, ret;
  1200. /*
  1201. * Check subnode name, must be equal to "hash".
  1202. * Multiple hash nodes require unique unit node
  1203. * names, e.g. hash@1, hash@2, etc.
  1204. */
  1205. if (strncmp (fit_get_name(fit, noffset, NULL),
  1206. FIT_HASH_NODENAME,
  1207. strlen(FIT_HASH_NODENAME)) != 0)
  1208. return;
  1209. debug ("%s Hash node: '%s'\n", p,
  1210. fit_get_name (fit, noffset, NULL));
  1211. printf ("%s Hash algo: ", p);
  1212. if (fit_image_hash_get_algo (fit, noffset, &algo)) {
  1213. printf ("invalid/unsupported\n");
  1214. return;
  1215. }
  1216. printf ("%s\n", algo);
  1217. ret = fit_image_hash_get_value (fit, noffset, &value,
  1218. &value_len);
  1219. printf ("%s Hash value: ", p);
  1220. if (ret) {
  1221. printf ("unavailable\n");
  1222. } else {
  1223. for (i = 0; i < value_len; i++)
  1224. printf ("%02x", value[i]);
  1225. printf ("\n");
  1226. }
  1227. debug ("%s Hash len: %d\n", p, value_len);
  1228. }
  1229. /**
  1230. * fit_get_desc - get node description property
  1231. * @fit: pointer to the FIT format image header
  1232. * @noffset: node offset
  1233. * @desc: double pointer to the char, will hold pointer to the descrption
  1234. *
  1235. * fit_get_desc() reads description property from a given node, if
  1236. * description is found pointer to it is returened in third call argument.
  1237. *
  1238. * returns:
  1239. * 0, on success
  1240. * -1, on failure
  1241. */
  1242. int fit_get_desc (const void *fit, int noffset, char **desc)
  1243. {
  1244. int len;
  1245. *desc = (char *)fdt_getprop (fit, noffset, FIT_DESC_PROP, &len);
  1246. if (*desc == NULL) {
  1247. fit_get_debug (fit, noffset, FIT_DESC_PROP, len);
  1248. return -1;
  1249. }
  1250. return 0;
  1251. }
  1252. /**
  1253. * fit_get_timestamp - get node timestamp property
  1254. * @fit: pointer to the FIT format image header
  1255. * @noffset: node offset
  1256. * @timestamp: pointer to the time_t, will hold read timestamp
  1257. *
  1258. * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
  1259. * is found and has a correct size its value is retured in third call
  1260. * argument.
  1261. *
  1262. * returns:
  1263. * 0, on success
  1264. * -1, on property read failure
  1265. * -2, on wrong timestamp size
  1266. */
  1267. int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp)
  1268. {
  1269. int len;
  1270. const void *data;
  1271. data = fdt_getprop (fit, noffset, FIT_TIMESTAMP_PROP, &len);
  1272. if (data == NULL) {
  1273. fit_get_debug (fit, noffset, FIT_TIMESTAMP_PROP, len);
  1274. return -1;
  1275. }
  1276. if (len != sizeof (uint32_t)) {
  1277. debug ("FIT timestamp with incorrect size of (%u)\n", len);
  1278. return -2;
  1279. }
  1280. *timestamp = uimage_to_cpu (*((uint32_t *)data));
  1281. return 0;
  1282. }
  1283. /**
  1284. * fit_image_get_node - get node offset for component image of a given unit name
  1285. * @fit: pointer to the FIT format image header
  1286. * @image_uname: component image node unit name
  1287. *
  1288. * fit_image_get_node() finds a component image (withing the '/images'
  1289. * node) of a provided unit name. If image is found its node offset is
  1290. * returned to the caller.
  1291. *
  1292. * returns:
  1293. * image node offset when found (>=0)
  1294. * negative number on failure (FDT_ERR_* code)
  1295. */
  1296. int fit_image_get_node (const void *fit, const char *image_uname)
  1297. {
  1298. int noffset, images_noffset;
  1299. images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
  1300. if (images_noffset < 0) {
  1301. debug ("Can't find images parent node '%s' (%s)\n",
  1302. FIT_IMAGES_PATH, fdt_strerror (images_noffset));
  1303. return images_noffset;
  1304. }
  1305. noffset = fdt_subnode_offset (fit, images_noffset, image_uname);
  1306. if (noffset < 0) {
  1307. debug ("Can't get node offset for image unit name: '%s' (%s)\n",
  1308. image_uname, fdt_strerror (noffset));
  1309. }
  1310. return noffset;
  1311. }
  1312. /**
  1313. * fit_image_get_os - get os id for a given component image node
  1314. * @fit: pointer to the FIT format image header
  1315. * @noffset: component image node offset
  1316. * @os: pointer to the uint8_t, will hold os numeric id
  1317. *
  1318. * fit_image_get_os() finds os property in a given component image node.
  1319. * If the property is found, its (string) value is translated to the numeric
  1320. * id which is returned to the caller.
  1321. *
  1322. * returns:
  1323. * 0, on success
  1324. * -1, on failure
  1325. */
  1326. int fit_image_get_os (const void *fit, int noffset, uint8_t *os)
  1327. {
  1328. int len;
  1329. const void *data;
  1330. /* Get OS name from property data */
  1331. data = fdt_getprop (fit, noffset, FIT_OS_PROP, &len);
  1332. if (data == NULL) {
  1333. fit_get_debug (fit, noffset, FIT_OS_PROP, len);
  1334. *os = -1;
  1335. return -1;
  1336. }
  1337. /* Translate OS name to id */
  1338. *os = genimg_get_os_id (data);
  1339. return 0;
  1340. }
  1341. /**
  1342. * fit_image_get_arch - get arch id for a given component image node
  1343. * @fit: pointer to the FIT format image header
  1344. * @noffset: component image node offset
  1345. * @arch: pointer to the uint8_t, will hold arch numeric id
  1346. *
  1347. * fit_image_get_arch() finds arch property in a given component image node.
  1348. * If the property is found, its (string) value is translated to the numeric
  1349. * id which is returned to the caller.
  1350. *
  1351. * returns:
  1352. * 0, on success
  1353. * -1, on failure
  1354. */
  1355. int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch)
  1356. {
  1357. int len;
  1358. const void *data;
  1359. /* Get architecture name from property data */
  1360. data = fdt_getprop (fit, noffset, FIT_ARCH_PROP, &len);
  1361. if (data == NULL) {
  1362. fit_get_debug (fit, noffset, FIT_ARCH_PROP, len);
  1363. *arch = -1;
  1364. return -1;
  1365. }
  1366. /* Translate architecture name to id */
  1367. *arch = genimg_get_arch_id (data);
  1368. return 0;
  1369. }
  1370. /**
  1371. * fit_image_get_type - get type id for a given component image node
  1372. * @fit: pointer to the FIT format image header
  1373. * @noffset: component image node offset
  1374. * @type: pointer to the uint8_t, will hold type numeric id
  1375. *
  1376. * fit_image_get_type() finds type property in a given component image node.
  1377. * If the property is found, its (string) value is translated to the numeric
  1378. * id which is returned to the caller.
  1379. *
  1380. * returns:
  1381. * 0, on success
  1382. * -1, on failure
  1383. */
  1384. int fit_image_get_type (const void *fit, int noffset, uint8_t *type)
  1385. {
  1386. int len;
  1387. const void *data;
  1388. /* Get image type name from property data */
  1389. data = fdt_getprop (fit, noffset, FIT_TYPE_PROP, &len);
  1390. if (data == NULL) {
  1391. fit_get_debug (fit, noffset, FIT_TYPE_PROP, len);
  1392. *type = -1;
  1393. return -1;
  1394. }
  1395. /* Translate image type name to id */
  1396. *type = genimg_get_type_id (data);
  1397. return 0;
  1398. }
  1399. /**
  1400. * fit_image_get_comp - get comp id for a given component image node
  1401. * @fit: pointer to the FIT format image header
  1402. * @noffset: component image node offset
  1403. * @comp: pointer to the uint8_t, will hold comp numeric id
  1404. *
  1405. * fit_image_get_comp() finds comp property in a given component image node.
  1406. * If the property is found, its (string) value is translated to the numeric
  1407. * id which is returned to the caller.
  1408. *
  1409. * returns:
  1410. * 0, on success
  1411. * -1, on failure
  1412. */
  1413. int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp)
  1414. {
  1415. int len;
  1416. const void *data;
  1417. /* Get compression name from property data */
  1418. data = fdt_getprop (fit, noffset, FIT_COMP_PROP, &len);
  1419. if (data == NULL) {
  1420. fit_get_debug (fit, noffset, FIT_COMP_PROP, len);
  1421. *comp = -1;
  1422. return -1;
  1423. }
  1424. /* Translate compression name to id */
  1425. *comp = genimg_get_comp_id (data);
  1426. return 0;
  1427. }
  1428. /**
  1429. * fit_image_get_load - get load address property for a given component image node
  1430. * @fit: pointer to the FIT format image header
  1431. * @noffset: component image node offset
  1432. * @load: pointer to the uint32_t, will hold load address
  1433. *
  1434. * fit_image_get_load() finds load address property in a given component image node.
  1435. * If the property is found, its value is returned to the caller.
  1436. *
  1437. * returns:
  1438. * 0, on success
  1439. * -1, on failure
  1440. */
  1441. int fit_image_get_load (const void *fit, int noffset, ulong *load)
  1442. {
  1443. int len;
  1444. const uint32_t *data;
  1445. data = fdt_getprop (fit, noffset, FIT_LOAD_PROP, &len);
  1446. if (data == NULL) {
  1447. fit_get_debug (fit, noffset, FIT_LOAD_PROP, len);
  1448. return -1;
  1449. }
  1450. *load = uimage_to_cpu (*data);
  1451. return 0;
  1452. }
  1453. /**
  1454. * fit_image_get_entry - get entry point address property for a given component image node
  1455. * @fit: pointer to the FIT format image header
  1456. * @noffset: component image node offset
  1457. * @entry: pointer to the uint32_t, will hold entry point address
  1458. *
  1459. * fit_image_get_entry() finds entry point address property in a given component image node.
  1460. * If the property is found, its value is returned to the caller.
  1461. *
  1462. * returns:
  1463. * 0, on success
  1464. * -1, on failure
  1465. */
  1466. int fit_image_get_entry (const void *fit, int noffset, ulong *entry)
  1467. {
  1468. int len;
  1469. const uint32_t *data;
  1470. data = fdt_getprop (fit, noffset, FIT_ENTRY_PROP, &len);
  1471. if (data == NULL) {
  1472. fit_get_debug (fit, noffset, FIT_ENTRY_PROP, len);
  1473. return -1;
  1474. }
  1475. *entry = uimage_to_cpu (*data);
  1476. return 0;
  1477. }
  1478. /**
  1479. * fit_image_get_data - get data property and its size for a given component image node
  1480. * @fit: pointer to the FIT format image header
  1481. * @noffset: component image node offset
  1482. * @data: double pointer to void, will hold data property's data address
  1483. * @size: pointer to size_t, will hold data property's data size
  1484. *
  1485. * fit_image_get_data() finds data property in a given component image node.
  1486. * If the property is found its data start address and size are returned to
  1487. * the caller.
  1488. *
  1489. * returns:
  1490. * 0, on success
  1491. * -1, on failure
  1492. */
  1493. int fit_image_get_data (const void *fit, int noffset,
  1494. const void **data, size_t *size)
  1495. {
  1496. int len;
  1497. *data = fdt_getprop (fit, noffset, FIT_DATA_PROP, &len);
  1498. if (*data == NULL) {
  1499. fit_get_debug (fit, noffset, FIT_DATA_PROP, len);
  1500. *size = 0;
  1501. return -1;
  1502. }
  1503. *size = len;
  1504. return 0;
  1505. }
  1506. /**
  1507. * fit_image_hash_get_algo - get hash algorithm name
  1508. * @fit: pointer to the FIT format image header
  1509. * @noffset: hash node offset
  1510. * @algo: double pointer to char, will hold pointer to the algorithm name
  1511. *
  1512. * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
  1513. * If the property is found its data start address is returned to the caller.
  1514. *
  1515. * returns:
  1516. * 0, on success
  1517. * -1, on failure
  1518. */
  1519. int fit_image_hash_get_algo (const void *fit, int noffset, char **algo)
  1520. {
  1521. int len;
  1522. *algo = (char *)fdt_getprop (fit, noffset, FIT_ALGO_PROP, &len);
  1523. if (*algo == NULL) {
  1524. fit_get_debug (fit, noffset, FIT_ALGO_PROP, len);
  1525. return -1;
  1526. }
  1527. return 0;
  1528. }
  1529. /**
  1530. * fit_image_hash_get_value - get hash value and length
  1531. * @fit: pointer to the FIT format image header
  1532. * @noffset: hash node offset
  1533. * @value: double pointer to uint8_t, will hold address of a hash value data
  1534. * @value_len: pointer to an int, will hold hash data length
  1535. *
  1536. * fit_image_hash_get_value() finds hash value property in a given hash node.
  1537. * If the property is found its data start address and size are returned to
  1538. * the caller.
  1539. *
  1540. * returns:
  1541. * 0, on success
  1542. * -1, on failure
  1543. */
  1544. int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value,
  1545. int *value_len)
  1546. {
  1547. int len;
  1548. *value = (uint8_t *)fdt_getprop (fit, noffset, FIT_VALUE_PROP, &len);
  1549. if (*value == NULL) {
  1550. fit_get_debug (fit, noffset, FIT_VALUE_PROP, len);
  1551. *value_len = 0;
  1552. return -1;
  1553. }
  1554. *value_len = len;
  1555. return 0;
  1556. }
  1557. /**
  1558. * fit_set_timestamp - set node timestamp property
  1559. * @fit: pointer to the FIT format image header
  1560. * @noffset: node offset
  1561. * @timestamp: timestamp value to be set
  1562. *
  1563. * fit_set_timestamp() attempts to set timestamp property in the requested
  1564. * node and returns operation status to the caller.
  1565. *
  1566. * returns:
  1567. * 0, on success
  1568. * -1, on property read failure
  1569. */
  1570. int fit_set_timestamp (void *fit, int noffset, time_t timestamp)
  1571. {
  1572. uint32_t t;
  1573. int ret;
  1574. t = cpu_to_uimage (timestamp);
  1575. ret = fdt_setprop (fit, noffset, FIT_TIMESTAMP_PROP, &t,
  1576. sizeof (uint32_t));
  1577. if (ret) {
  1578. printf ("Can't set '%s' property for '%s' node (%s)\n",
  1579. FIT_TIMESTAMP_PROP, fit_get_name (fit, noffset, NULL),
  1580. fdt_strerror (ret));
  1581. return -1;
  1582. }
  1583. return 0;
  1584. }
  1585. /**
  1586. * calculate_hash - calculate and return hash for provided input data
  1587. * @data: pointer to the input data
  1588. * @data_len: data length
  1589. * @algo: requested hash algorithm
  1590. * @value: pointer to the char, will hold hash value data (caller must
  1591. * allocate enough free space)
  1592. * value_len: length of the calculated hash
  1593. *
  1594. * calculate_hash() computes input data hash according to the requested algorithm.
  1595. * Resulting hash value is placed in caller provided 'value' buffer, length
  1596. * of the calculated hash is returned via value_len pointer argument.
  1597. *
  1598. * returns:
  1599. * 0, on success
  1600. * -1, when algo is unsupported
  1601. */
  1602. static int calculate_hash (const void *data, int data_len, const char *algo,
  1603. uint8_t *value, int *value_len)
  1604. {
  1605. if (strcmp (algo, "crc32") == 0 ) {
  1606. *((uint32_t *)value) = crc32 (0, data, data_len);
  1607. *((uint32_t *)value) = cpu_to_uimage (*((uint32_t *)value));
  1608. *value_len = 4;
  1609. } else if (strcmp (algo, "sha1") == 0 ) {
  1610. sha1_csum ((unsigned char *) data, data_len,
  1611. (unsigned char *) value);
  1612. *value_len = 20;
  1613. } else if (strcmp (algo, "md5") == 0 ) {
  1614. printf ("MD5 not supported\n");
  1615. *value_len = 0;
  1616. } else {
  1617. debug ("Unsupported hash alogrithm\n");
  1618. return -1;
  1619. }
  1620. return 0;
  1621. }
  1622. #ifdef USE_HOSTCC
  1623. /**
  1624. * fit_set_hashes - process FIT component image nodes and calculate hashes
  1625. * @fit: pointer to the FIT format image header
  1626. *
  1627. * fit_set_hashes() adds hash values for all component images in the FIT blob.
  1628. * Hashes are calculated for all component images which have hash subnodes
  1629. * with algorithm property set to one of the supported hash algorithms.
  1630. *
  1631. * returns
  1632. * 0, on success
  1633. * libfdt error code, on failure
  1634. */
  1635. int fit_set_hashes (void *fit)
  1636. {
  1637. int images_noffset;
  1638. int noffset;
  1639. int ndepth;
  1640. int ret;
  1641. /* Find images parent node offset */
  1642. images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH);
  1643. if (images_noffset < 0) {
  1644. printf ("Can't find images parent node '%s' (%s)\n",
  1645. FIT_IMAGES_PATH, fdt_strerror (images_noffset));
  1646. return images_noffset;
  1647. }
  1648. /* Process its subnodes, print out component images details */
  1649. for (ndepth = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth);
  1650. (noffset >= 0) && (ndepth > 0);
  1651. noffset = fdt_next_node (fit, noffset, &ndepth)) {
  1652. if (ndepth == 1) {
  1653. /*
  1654. * Direct child node of the images parent node,
  1655. * i.e. component image node.
  1656. */
  1657. ret = fit_image_set_hashes (fit, noffset);
  1658. if (ret)
  1659. return ret;
  1660. }
  1661. }
  1662. return 0;
  1663. }
  1664. /**
  1665. * fit_image_set_hashes - calculate/set hashes for given component image node
  1666. * @fit: pointer to the FIT format image header
  1667. * @image_noffset: requested component image node
  1668. *
  1669. * fit_image_set_hashes() adds hash values for an component image node. All
  1670. * existing hash subnodes are checked, if algorithm property is set to one of
  1671. * the supported hash algorithms, hash value is computed and corresponding
  1672. * hash node property is set, for example:
  1673. *
  1674. * Input component image node structure:
  1675. *
  1676. * o image@1 (at image_noffset)
  1677. * | - data = [binary data]
  1678. * o hash@1
  1679. * |- algo = "sha1"
  1680. *
  1681. * Output component image node structure:
  1682. *
  1683. * o image@1 (at image_noffset)
  1684. * | - data = [binary data]
  1685. * o hash@1
  1686. * |- algo = "sha1"
  1687. * |- value = sha1(data)
  1688. *
  1689. * returns:
  1690. * 0 on sucess
  1691. * <0 on failure
  1692. */
  1693. int fit_image_set_hashes (void *fit, int image_noffset)
  1694. {
  1695. const void *data;
  1696. size_t size;
  1697. char *algo;
  1698. uint8_t value[FIT_MAX_HASH_LEN];
  1699. int value_len;
  1700. int noffset;
  1701. int ndepth;
  1702. /* Get image data and data length */
  1703. if (fit_image_get_data (fit, image_noffset, &data, &size)) {
  1704. printf ("Can't get image data/size\n");
  1705. return -1;
  1706. }
  1707. /* Process all hash subnodes of the component image node */
  1708. for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth);
  1709. (noffset >= 0) && (ndepth > 0);
  1710. noffset = fdt_next_node (fit, noffset, &ndepth)) {
  1711. if (ndepth == 1) {
  1712. /* Direct child node of the component image node */
  1713. /*
  1714. * Check subnode name, must be equal to "hash".
  1715. * Multiple hash nodes require unique unit node
  1716. * names, e.g. hash@1, hash@2, etc.
  1717. */
  1718. if (strncmp (fit_get_name(fit, noffset, NULL),
  1719. FIT_HASH_NODENAME,
  1720. strlen(FIT_HASH_NODENAME)) != 0) {
  1721. /* Not a hash subnode, skip it */
  1722. continue;
  1723. }
  1724. if (fit_image_hash_get_algo (fit, noffset, &algo)) {
  1725. printf ("Can't get hash algo property for "
  1726. "'%s' hash node in '%s' image node\n",
  1727. fit_get_name (fit, noffset, NULL),
  1728. fit_get_name (fit, image_noffset, NULL));
  1729. return -1;
  1730. }
  1731. if (calculate_hash (data, size, algo, value, &value_len)) {
  1732. printf ("Unsupported hash algorithm (%s) for "
  1733. "'%s' hash node in '%s' image node\n",
  1734. algo, fit_get_name (fit, noffset, NULL),
  1735. fit_get_name (fit, image_noffset, NULL));
  1736. return -1;
  1737. }
  1738. if (fit_image_hash_set_value (fit, noffset, value,
  1739. value_len)) {
  1740. printf ("Can't set hash value for "
  1741. "'%s' hash node in '%s' image node\n",
  1742. fit_get_name (fit, noffset, NULL),
  1743. fit_get_name (fit, image_noffset, NULL));
  1744. return -1;
  1745. }
  1746. }
  1747. }
  1748. return 0;
  1749. }
  1750. /**
  1751. * fit_image_hash_set_value - set hash value in requested has node
  1752. * @fit: pointer to the FIT format image header
  1753. * @noffset: hash node offset
  1754. * @value: hash value to be set
  1755. * @value_len: hash value length
  1756. *
  1757. * fit_image_hash_set_value() attempts to set hash value in a node at offset
  1758. * given and returns operation status to the caller.
  1759. *
  1760. * returns
  1761. * 0, on success
  1762. * -1, on failure
  1763. */
  1764. int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value,
  1765. int value_len)
  1766. {
  1767. int ret;
  1768. ret = fdt_setprop (fit, noffset, FIT_VALUE_PROP, value, value_len);
  1769. if (ret) {
  1770. printf ("Can't set hash '%s' property for '%s' node (%s)\n",
  1771. FIT_VALUE_PROP, fit_get_name (fit, noffset, NULL),
  1772. fdt_strerror (ret));
  1773. return -1;
  1774. }
  1775. return 0;
  1776. }
  1777. #endif /* USE_HOSTCC */
  1778. /**
  1779. * fit_image_check_hashes - verify data intergity
  1780. * @fit: pointer to the FIT format image header
  1781. * @image_noffset: component image node offset
  1782. *
  1783. * fit_image_check_hashes() goes over component image hash nodes,
  1784. * re-calculates each data hash and compares with the value stored in hash
  1785. * node.
  1786. *
  1787. * returns:
  1788. * 1, if all hashes are valid
  1789. * 0, otherwise (or on error)
  1790. */
  1791. int fit_image_check_hashes (const void *fit, int image_noffset)
  1792. {
  1793. const void *data;
  1794. size_t size;
  1795. char *algo;
  1796. uint8_t *fit_value;
  1797. int fit_value_len;
  1798. uint8_t value[FIT_MAX_HASH_LEN];
  1799. int value_len;
  1800. int noffset;
  1801. int ndepth;
  1802. char *err_msg = "";
  1803. /* Get image data and data length */
  1804. if (fit_image_get_data (fit, image_noffset, &data, &size)) {
  1805. printf ("Can't get image data/size\n");
  1806. return 0;
  1807. }
  1808. /* Process all hash subnodes of the component image node */
  1809. for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth);
  1810. (noffset >= 0) && (ndepth > 0);
  1811. noffset = fdt_next_node (fit, noffset, &ndepth)) {
  1812. if (ndepth == 1) {
  1813. /* Direct child node of the component image node */
  1814. /*
  1815. * Check subnode name, must be equal to "hash".
  1816. * Multiple hash nodes require unique unit node
  1817. * names, e.g. hash@1, hash@2, etc.
  1818. */
  1819. if (strncmp (fit_get_name(fit, noffset, NULL),
  1820. FIT_HASH_NODENAME,
  1821. strlen(FIT_HASH_NODENAME)) != 0)
  1822. continue;
  1823. if (fit_image_hash_get_algo (fit, noffset, &algo)) {
  1824. err_msg = "Can't get hash algo property";
  1825. goto error;
  1826. }
  1827. printf ("%s", algo);
  1828. if (fit_image_hash_get_value (fit, noffset, &fit_value,
  1829. &fit_value_len)) {
  1830. err_msg = "Can't get hash value property";
  1831. goto error;
  1832. }
  1833. if (calculate_hash (data, size, algo, value, &value_len)) {
  1834. err_msg = "Unsupported hash algorithm";
  1835. goto error;
  1836. }
  1837. if (value_len != fit_value_len) {
  1838. err_msg = "Bad hash value len";
  1839. goto error;
  1840. } else if (memcmp (value, fit_value, value_len) != 0) {
  1841. err_msg = "Bad hash value";
  1842. goto error;
  1843. }
  1844. printf ("+ ");
  1845. }
  1846. }
  1847. return 1;
  1848. error:
  1849. printf ("%s for '%s' hash node in '%s' image node\n",
  1850. err_msg, fit_get_name (fit, noffset, NULL),
  1851. fit_get_name (fit, image_noffset, NULL));
  1852. return 0;
  1853. }
  1854. /**
  1855. * fit_image_check_os - check whether image node is of a given os type
  1856. * @fit: pointer to the FIT format image header
  1857. * @noffset: component image node offset
  1858. * @os: requested image os
  1859. *
  1860. * fit_image_check_os() reads image os property and compares its numeric
  1861. * id with the requested os. Comparison result is returned to the caller.
  1862. *
  1863. * returns:
  1864. * 1 if image is of given os type
  1865. * 0 otherwise (or on error)
  1866. */
  1867. int fit_image_check_os (const void *fit, int noffset, uint8_t os)
  1868. {
  1869. uint8_t image_os;
  1870. if (fit_image_get_os (fit, noffset, &image_os))
  1871. return 0;
  1872. return (os == image_os);
  1873. }
  1874. /**
  1875. * fit_image_check_arch - check whether image node is of a given arch
  1876. * @fit: pointer to the FIT format image header
  1877. * @noffset: component image node offset
  1878. * @arch: requested imagearch
  1879. *
  1880. * fit_image_check_arch() reads image arch property and compares its numeric
  1881. * id with the requested arch. Comparison result is returned to the caller.
  1882. *
  1883. * returns:
  1884. * 1 if image is of given arch
  1885. * 0 otherwise (or on error)
  1886. */
  1887. int fit_image_check_arch (const void *fit, int noffset, uint8_t arch)
  1888. {
  1889. uint8_t image_arch;
  1890. if (fit_image_get_arch (fit, noffset, &image_arch))
  1891. return 0;
  1892. return (arch == image_arch);
  1893. }
  1894. /**
  1895. * fit_image_check_type - check whether image node is of a given type
  1896. * @fit: pointer to the FIT format image header
  1897. * @noffset: component image node offset
  1898. * @type: requested image type
  1899. *
  1900. * fit_image_check_type() reads image type property and compares its numeric
  1901. * id with the requested type. Comparison result is returned to the caller.
  1902. *
  1903. * returns:
  1904. * 1 if image is of given type
  1905. * 0 otherwise (or on error)
  1906. */
  1907. int fit_image_check_type (const void *fit, int noffset, uint8_t type)
  1908. {
  1909. uint8_t image_type;
  1910. if (fit_image_get_type (fit, noffset, &image_type))
  1911. return 0;
  1912. return (type == image_type);
  1913. }
  1914. /**
  1915. * fit_image_check_comp - check whether image node uses given compression
  1916. * @fit: pointer to the FIT format image header
  1917. * @noffset: component image node offset
  1918. * @comp: requested image compression type
  1919. *
  1920. * fit_image_check_comp() reads image compression property and compares its
  1921. * numeric id with the requested compression type. Comparison result is
  1922. * returned to the caller.
  1923. *
  1924. * returns:
  1925. * 1 if image uses requested compression
  1926. * 0 otherwise (or on error)
  1927. */
  1928. int fit_image_check_comp (const void *fit, int noffset, uint8_t comp)
  1929. {
  1930. uint8_t image_comp;
  1931. if (fit_image_get_comp (fit, noffset, &image_comp))
  1932. return 0;
  1933. return (comp == image_comp);
  1934. }
  1935. /**
  1936. * fit_check_format - sanity check FIT image format
  1937. * @fit: pointer to the FIT format image header
  1938. *
  1939. * fit_check_format() runs a basic sanity FIT image verification.
  1940. * Routine checks for mandatory properties, nodes, etc.
  1941. *
  1942. * returns:
  1943. * 1, on success
  1944. * 0, on failure
  1945. */
  1946. int fit_check_format (const void *fit)
  1947. {
  1948. /* mandatory / node 'description' property */
  1949. if (fdt_getprop (fit, 0, FIT_DESC_PROP, NULL) == NULL) {
  1950. debug ("Wrong FIT format: no description\n");
  1951. return 0;
  1952. }
  1953. #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
  1954. /* mandatory / node 'timestamp' property */
  1955. if (fdt_getprop (fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
  1956. debug ("Wrong FIT format: no description\n");
  1957. return 0;
  1958. }
  1959. #endif
  1960. /* mandatory subimages parent '/images' node */
  1961. if (fdt_path_offset (fit, FIT_IMAGES_PATH) < 0) {
  1962. debug ("Wrong FIT format: no images parent node\n");
  1963. return 0;
  1964. }
  1965. return 1;
  1966. }
  1967. /**
  1968. * fit_conf_get_node - get node offset for configuration of a given unit name
  1969. * @fit: pointer to the FIT format image header
  1970. * @conf_uname: configuration node unit name
  1971. *
  1972. * fit_conf_get_node() finds a configuration (withing the '/configurations'
  1973. * parant node) of a provided unit name. If configuration is found its node offset
  1974. * is returned to the caller.
  1975. *
  1976. * When NULL is provided in second argument fit_conf_get_node() will search
  1977. * for a default configuration node instead. Default configuration node unit name
  1978. * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node.
  1979. *
  1980. * returns:
  1981. * configuration node offset when found (>=0)
  1982. * negative number on failure (FDT_ERR_* code)
  1983. */
  1984. int fit_conf_get_node (const void *fit, const char *conf_uname)
  1985. {
  1986. int noffset, confs_noffset;
  1987. int len;
  1988. confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH);
  1989. if (confs_noffset < 0) {
  1990. debug ("Can't find configurations parent node '%s' (%s)\n",
  1991. FIT_CONFS_PATH, fdt_strerror (confs_noffset));
  1992. return confs_noffset;
  1993. }
  1994. if (conf_uname == NULL) {
  1995. /* get configuration unit name from the default property */
  1996. debug ("No configuration specified, trying default...\n");
  1997. conf_uname = (char *)fdt_getprop (fit, confs_noffset, FIT_DEFAULT_PROP, &len);
  1998. if (conf_uname == NULL) {
  1999. fit_get_debug (fit, confs_noffset, FIT_DEFAULT_PROP, len);
  2000. return len;
  2001. }
  2002. debug ("Found default configuration: '%s'\n", conf_uname);
  2003. }
  2004. noffset = fdt_subnode_offset (fit, confs_noffset, conf_uname);
  2005. if (noffset < 0) {
  2006. debug ("Can't get node offset for configuration unit name: '%s' (%s)\n",
  2007. conf_uname, fdt_strerror (noffset));
  2008. }
  2009. return noffset;
  2010. }
  2011. static int __fit_conf_get_prop_node (const void *fit, int noffset,
  2012. const char *prop_name)
  2013. {
  2014. char *uname;
  2015. int len;
  2016. /* get kernel image unit name from configuration kernel property */
  2017. uname = (char *)fdt_getprop (fit, noffset, prop_name, &len);
  2018. if (uname == NULL)
  2019. return len;
  2020. return fit_image_get_node (fit, uname);
  2021. }
  2022. /**
  2023. * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
  2024. * a given configuration
  2025. * @fit: pointer to the FIT format image header
  2026. * @noffset: configuration node offset
  2027. *
  2028. * fit_conf_get_kernel_node() retrives kernel image node unit name from
  2029. * configuration FIT_KERNEL_PROP property and translates it to the node
  2030. * offset.
  2031. *
  2032. * returns:
  2033. * image node offset when found (>=0)
  2034. * negative number on failure (FDT_ERR_* code)
  2035. */
  2036. int fit_conf_get_kernel_node (const void *fit, int noffset)
  2037. {
  2038. return __fit_conf_get_prop_node (fit, noffset, FIT_KERNEL_PROP);
  2039. }
  2040. /**
  2041. * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
  2042. * a given configuration
  2043. * @fit: pointer to the FIT format image header
  2044. * @noffset: configuration node offset
  2045. *
  2046. * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
  2047. * configuration FIT_KERNEL_PROP property and translates it to the node
  2048. * offset.
  2049. *
  2050. * returns:
  2051. * image node offset when found (>=0)
  2052. * negative number on failure (FDT_ERR_* code)
  2053. */
  2054. int fit_conf_get_ramdisk_node (const void *fit, int noffset)
  2055. {
  2056. return __fit_conf_get_prop_node (fit, noffset, FIT_RAMDISK_PROP);
  2057. }
  2058. /**
  2059. * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
  2060. * a given configuration
  2061. * @fit: pointer to the FIT format image header
  2062. * @noffset: configuration node offset
  2063. *
  2064. * fit_conf_get_fdt_node() retrives fdt image node unit name from
  2065. * configuration FIT_KERNEL_PROP property and translates it to the node
  2066. * offset.
  2067. *
  2068. * returns:
  2069. * image node offset when found (>=0)
  2070. * negative number on failure (FDT_ERR_* code)
  2071. */
  2072. int fit_conf_get_fdt_node (const void *fit, int noffset)
  2073. {
  2074. return __fit_conf_get_prop_node (fit, noffset, FIT_FDT_PROP);
  2075. }
  2076. /**
  2077. * fit_conf_print - prints out the FIT configuration details
  2078. * @fit: pointer to the FIT format image header
  2079. * @conf_noffset: offset of the configuration node
  2080. * @p: pointer to prefix string
  2081. *
  2082. * fit_conf_print() lists all mandatory properies for the processed
  2083. * configuration node.
  2084. *
  2085. * returns:
  2086. * no returned results
  2087. */
  2088. void fit_conf_print (const void *fit, int noffset, const char *p)
  2089. {
  2090. char *desc;
  2091. char *uname;
  2092. int ret;
  2093. /* Mandatory properties */
  2094. ret = fit_get_desc (fit, noffset, &desc);
  2095. printf ("%s Description: ", p);
  2096. if (ret)
  2097. printf ("unavailable\n");
  2098. else
  2099. printf ("%s\n", desc);
  2100. uname = (char *)fdt_getprop (fit, noffset, FIT_KERNEL_PROP, NULL);
  2101. printf ("%s Kernel: ", p);
  2102. if (uname == NULL)
  2103. printf ("unavailable\n");
  2104. else
  2105. printf ("%s\n", uname);
  2106. /* Optional properties */
  2107. uname = (char *)fdt_getprop (fit, noffset, FIT_RAMDISK_PROP, NULL);
  2108. if (uname)
  2109. printf ("%s Init Ramdisk: %s\n", p, uname);
  2110. uname = (char *)fdt_getprop (fit, noffset, FIT_FDT_PROP, NULL);
  2111. if (uname)
  2112. printf ("%s FDT: %s\n", p, uname);
  2113. }
  2114. #endif /* CONFIG_FIT */