image-fit.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662
  1. /*
  2. * Copyright (c) 2013, Google Inc.
  3. *
  4. * (C) Copyright 2008 Semihalf
  5. *
  6. * (C) Copyright 2000-2006
  7. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #ifdef USE_HOSTCC
  12. #include "mkimage.h"
  13. #include <image.h>
  14. #include <time.h>
  15. #else
  16. #include <common.h>
  17. #include <errno.h>
  18. #include <asm/io.h>
  19. DECLARE_GLOBAL_DATA_PTR;
  20. #endif /* !USE_HOSTCC*/
  21. #include <bootstage.h>
  22. #include <sha1.h>
  23. #include <u-boot/crc.h>
  24. #include <u-boot/md5.h>
  25. /*****************************************************************************/
  26. /* New uImage format routines */
  27. /*****************************************************************************/
  28. #ifndef USE_HOSTCC
  29. static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
  30. ulong *addr, const char **name)
  31. {
  32. const char *sep;
  33. *addr = addr_curr;
  34. *name = NULL;
  35. sep = strchr(spec, sepc);
  36. if (sep) {
  37. if (sep - spec > 0)
  38. *addr = simple_strtoul(spec, NULL, 16);
  39. *name = sep + 1;
  40. return 1;
  41. }
  42. return 0;
  43. }
  44. /**
  45. * fit_parse_conf - parse FIT configuration spec
  46. * @spec: input string, containing configuration spec
  47. * @add_curr: current image address (to be used as a possible default)
  48. * @addr: pointer to a ulong variable, will hold FIT image address of a given
  49. * configuration
  50. * @conf_name double pointer to a char, will hold pointer to a configuration
  51. * unit name
  52. *
  53. * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>,
  54. * where <addr> is a FIT image address that contains configuration
  55. * with a <conf> unit name.
  56. *
  57. * Address part is optional, and if omitted default add_curr will
  58. * be used instead.
  59. *
  60. * returns:
  61. * 1 if spec is a valid configuration string,
  62. * addr and conf_name are set accordingly
  63. * 0 otherwise
  64. */
  65. int fit_parse_conf(const char *spec, ulong addr_curr,
  66. ulong *addr, const char **conf_name)
  67. {
  68. return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
  69. }
  70. /**
  71. * fit_parse_subimage - parse FIT subimage spec
  72. * @spec: input string, containing subimage spec
  73. * @add_curr: current image address (to be used as a possible default)
  74. * @addr: pointer to a ulong variable, will hold FIT image address of a given
  75. * subimage
  76. * @image_name: double pointer to a char, will hold pointer to a subimage name
  77. *
  78. * fit_parse_subimage() expects subimage spec in the form of
  79. * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
  80. * subimage with a <subimg> unit name.
  81. *
  82. * Address part is optional, and if omitted default add_curr will
  83. * be used instead.
  84. *
  85. * returns:
  86. * 1 if spec is a valid subimage string,
  87. * addr and image_name are set accordingly
  88. * 0 otherwise
  89. */
  90. int fit_parse_subimage(const char *spec, ulong addr_curr,
  91. ulong *addr, const char **image_name)
  92. {
  93. return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
  94. }
  95. #endif /* !USE_HOSTCC */
  96. static void fit_get_debug(const void *fit, int noffset,
  97. char *prop_name, int err)
  98. {
  99. debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
  100. prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
  101. fdt_strerror(err));
  102. }
  103. #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
  104. /**
  105. * fit_print_contents - prints out the contents of the FIT format image
  106. * @fit: pointer to the FIT format image header
  107. * @p: pointer to prefix string
  108. *
  109. * fit_print_contents() formats a multi line FIT image contents description.
  110. * The routine prints out FIT image properties (root node level) follwed by
  111. * the details of each component image.
  112. *
  113. * returns:
  114. * no returned results
  115. */
  116. void fit_print_contents(const void *fit)
  117. {
  118. char *desc;
  119. char *uname;
  120. int images_noffset;
  121. int confs_noffset;
  122. int noffset;
  123. int ndepth;
  124. int count = 0;
  125. int ret;
  126. const char *p;
  127. time_t timestamp;
  128. /* Indent string is defined in header image.h */
  129. p = IMAGE_INDENT_STRING;
  130. /* Root node properties */
  131. ret = fit_get_desc(fit, 0, &desc);
  132. printf("%sFIT description: ", p);
  133. if (ret)
  134. printf("unavailable\n");
  135. else
  136. printf("%s\n", desc);
  137. if (IMAGE_ENABLE_TIMESTAMP) {
  138. ret = fit_get_timestamp(fit, 0, &timestamp);
  139. printf("%sCreated: ", p);
  140. if (ret)
  141. printf("unavailable\n");
  142. else
  143. genimg_print_time(timestamp);
  144. }
  145. /* Find images parent node offset */
  146. images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
  147. if (images_noffset < 0) {
  148. printf("Can't find images parent node '%s' (%s)\n",
  149. FIT_IMAGES_PATH, fdt_strerror(images_noffset));
  150. return;
  151. }
  152. /* Process its subnodes, print out component images details */
  153. for (ndepth = 0, count = 0,
  154. noffset = fdt_next_node(fit, images_noffset, &ndepth);
  155. (noffset >= 0) && (ndepth > 0);
  156. noffset = fdt_next_node(fit, noffset, &ndepth)) {
  157. if (ndepth == 1) {
  158. /*
  159. * Direct child node of the images parent node,
  160. * i.e. component image node.
  161. */
  162. printf("%s Image %u (%s)\n", p, count++,
  163. fit_get_name(fit, noffset, NULL));
  164. fit_image_print(fit, noffset, p);
  165. }
  166. }
  167. /* Find configurations parent node offset */
  168. confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
  169. if (confs_noffset < 0) {
  170. debug("Can't get configurations parent node '%s' (%s)\n",
  171. FIT_CONFS_PATH, fdt_strerror(confs_noffset));
  172. return;
  173. }
  174. /* get default configuration unit name from default property */
  175. uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
  176. if (uname)
  177. printf("%s Default Configuration: '%s'\n", p, uname);
  178. /* Process its subnodes, print out configurations details */
  179. for (ndepth = 0, count = 0,
  180. noffset = fdt_next_node(fit, confs_noffset, &ndepth);
  181. (noffset >= 0) && (ndepth > 0);
  182. noffset = fdt_next_node(fit, noffset, &ndepth)) {
  183. if (ndepth == 1) {
  184. /*
  185. * Direct child node of the configurations parent node,
  186. * i.e. configuration node.
  187. */
  188. printf("%s Configuration %u (%s)\n", p, count++,
  189. fit_get_name(fit, noffset, NULL));
  190. fit_conf_print(fit, noffset, p);
  191. }
  192. }
  193. }
  194. /**
  195. * fit_image_print_data() - prints out the hash node details
  196. * @fit: pointer to the FIT format image header
  197. * @noffset: offset of the hash node
  198. * @p: pointer to prefix string
  199. * @type: Type of information to print ("hash" or "sign")
  200. *
  201. * fit_image_print_data() lists properies for the processed hash node
  202. *
  203. * This function avoid using puts() since it prints a newline on the host
  204. * but does not in U-Boot.
  205. *
  206. * returns:
  207. * no returned results
  208. */
  209. static void fit_image_print_data(const void *fit, int noffset, const char *p,
  210. const char *type)
  211. {
  212. const char *keyname;
  213. uint8_t *value;
  214. int value_len;
  215. char *algo;
  216. int required;
  217. int ret, i;
  218. debug("%s %s node: '%s'\n", p, type,
  219. fit_get_name(fit, noffset, NULL));
  220. printf("%s %s algo: ", p, type);
  221. if (fit_image_hash_get_algo(fit, noffset, &algo)) {
  222. printf("invalid/unsupported\n");
  223. return;
  224. }
  225. printf("%s", algo);
  226. keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
  227. required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
  228. if (keyname)
  229. printf(":%s", keyname);
  230. if (required)
  231. printf(" (required)");
  232. printf("\n");
  233. ret = fit_image_hash_get_value(fit, noffset, &value,
  234. &value_len);
  235. printf("%s %s value: ", p, type);
  236. if (ret) {
  237. printf("unavailable\n");
  238. } else {
  239. for (i = 0; i < value_len; i++)
  240. printf("%02x", value[i]);
  241. printf("\n");
  242. }
  243. debug("%s %s len: %d\n", p, type, value_len);
  244. /* Signatures have a time stamp */
  245. if (IMAGE_ENABLE_TIMESTAMP && keyname) {
  246. time_t timestamp;
  247. printf("%s Timestamp: ", p);
  248. if (fit_get_timestamp(fit, noffset, &timestamp))
  249. printf("unavailable\n");
  250. else
  251. genimg_print_time(timestamp);
  252. }
  253. }
  254. /**
  255. * fit_image_print_verification_data() - prints out the hash/signature details
  256. * @fit: pointer to the FIT format image header
  257. * @noffset: offset of the hash or signature node
  258. * @p: pointer to prefix string
  259. *
  260. * This lists properies for the processed hash node
  261. *
  262. * returns:
  263. * no returned results
  264. */
  265. static void fit_image_print_verification_data(const void *fit, int noffset,
  266. const char *p)
  267. {
  268. const char *name;
  269. /*
  270. * Check subnode name, must be equal to "hash" or "signature".
  271. * Multiple hash/signature nodes require unique unit node
  272. * names, e.g. hash@1, hash@2, signature@1, signature@2, etc.
  273. */
  274. name = fit_get_name(fit, noffset, NULL);
  275. if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
  276. fit_image_print_data(fit, noffset, p, "Hash");
  277. } else if (!strncmp(name, FIT_SIG_NODENAME,
  278. strlen(FIT_SIG_NODENAME))) {
  279. fit_image_print_data(fit, noffset, p, "Sign");
  280. }
  281. }
  282. /**
  283. * fit_image_print - prints out the FIT component image details
  284. * @fit: pointer to the FIT format image header
  285. * @image_noffset: offset of the component image node
  286. * @p: pointer to prefix string
  287. *
  288. * fit_image_print() lists all mandatory properies for the processed component
  289. * image. If present, hash nodes are printed out as well. Load
  290. * address for images of type firmware is also printed out. Since the load
  291. * address is not mandatory for firmware images, it will be output as
  292. * "unavailable" when not present.
  293. *
  294. * returns:
  295. * no returned results
  296. */
  297. void fit_image_print(const void *fit, int image_noffset, const char *p)
  298. {
  299. char *desc;
  300. uint8_t type, arch, os, comp;
  301. size_t size;
  302. ulong load, entry;
  303. const void *data;
  304. int noffset;
  305. int ndepth;
  306. int ret;
  307. /* Mandatory properties */
  308. ret = fit_get_desc(fit, image_noffset, &desc);
  309. printf("%s Description: ", p);
  310. if (ret)
  311. printf("unavailable\n");
  312. else
  313. printf("%s\n", desc);
  314. if (IMAGE_ENABLE_TIMESTAMP) {
  315. time_t timestamp;
  316. ret = fit_get_timestamp(fit, 0, &timestamp);
  317. printf("%s Created: ", p);
  318. if (ret)
  319. printf("unavailable\n");
  320. else
  321. genimg_print_time(timestamp);
  322. }
  323. fit_image_get_type(fit, image_noffset, &type);
  324. printf("%s Type: %s\n", p, genimg_get_type_name(type));
  325. fit_image_get_comp(fit, image_noffset, &comp);
  326. printf("%s Compression: %s\n", p, genimg_get_comp_name(comp));
  327. ret = fit_image_get_data(fit, image_noffset, &data, &size);
  328. #ifndef USE_HOSTCC
  329. printf("%s Data Start: ", p);
  330. if (ret) {
  331. printf("unavailable\n");
  332. } else {
  333. void *vdata = (void *)data;
  334. printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
  335. }
  336. #endif
  337. printf("%s Data Size: ", p);
  338. if (ret)
  339. printf("unavailable\n");
  340. else
  341. genimg_print_size(size);
  342. /* Remaining, type dependent properties */
  343. if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
  344. (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
  345. (type == IH_TYPE_FLATDT)) {
  346. fit_image_get_arch(fit, image_noffset, &arch);
  347. printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch));
  348. }
  349. if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
  350. fit_image_get_os(fit, image_noffset, &os);
  351. printf("%s OS: %s\n", p, genimg_get_os_name(os));
  352. }
  353. if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
  354. (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) {
  355. ret = fit_image_get_load(fit, image_noffset, &load);
  356. printf("%s Load Address: ", p);
  357. if (ret)
  358. printf("unavailable\n");
  359. else
  360. printf("0x%08lx\n", load);
  361. }
  362. if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
  363. (type == IH_TYPE_RAMDISK)) {
  364. fit_image_get_entry(fit, image_noffset, &entry);
  365. printf("%s Entry Point: ", p);
  366. if (ret)
  367. printf("unavailable\n");
  368. else
  369. printf("0x%08lx\n", entry);
  370. }
  371. /* Process all hash subnodes of the component image node */
  372. for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
  373. (noffset >= 0) && (ndepth > 0);
  374. noffset = fdt_next_node(fit, noffset, &ndepth)) {
  375. if (ndepth == 1) {
  376. /* Direct child node of the component image node */
  377. fit_image_print_verification_data(fit, noffset, p);
  378. }
  379. }
  380. }
  381. #endif
  382. /**
  383. * fit_get_desc - get node description property
  384. * @fit: pointer to the FIT format image header
  385. * @noffset: node offset
  386. * @desc: double pointer to the char, will hold pointer to the descrption
  387. *
  388. * fit_get_desc() reads description property from a given node, if
  389. * description is found pointer to it is returened in third call argument.
  390. *
  391. * returns:
  392. * 0, on success
  393. * -1, on failure
  394. */
  395. int fit_get_desc(const void *fit, int noffset, char **desc)
  396. {
  397. int len;
  398. *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
  399. if (*desc == NULL) {
  400. fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
  401. return -1;
  402. }
  403. return 0;
  404. }
  405. /**
  406. * fit_get_timestamp - get node timestamp property
  407. * @fit: pointer to the FIT format image header
  408. * @noffset: node offset
  409. * @timestamp: pointer to the time_t, will hold read timestamp
  410. *
  411. * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
  412. * is found and has a correct size its value is retured in third call
  413. * argument.
  414. *
  415. * returns:
  416. * 0, on success
  417. * -1, on property read failure
  418. * -2, on wrong timestamp size
  419. */
  420. int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
  421. {
  422. int len;
  423. const void *data;
  424. data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
  425. if (data == NULL) {
  426. fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
  427. return -1;
  428. }
  429. if (len != sizeof(uint32_t)) {
  430. debug("FIT timestamp with incorrect size of (%u)\n", len);
  431. return -2;
  432. }
  433. *timestamp = uimage_to_cpu(*((uint32_t *)data));
  434. return 0;
  435. }
  436. /**
  437. * fit_image_get_node - get node offset for component image of a given unit name
  438. * @fit: pointer to the FIT format image header
  439. * @image_uname: component image node unit name
  440. *
  441. * fit_image_get_node() finds a component image (withing the '/images'
  442. * node) of a provided unit name. If image is found its node offset is
  443. * returned to the caller.
  444. *
  445. * returns:
  446. * image node offset when found (>=0)
  447. * negative number on failure (FDT_ERR_* code)
  448. */
  449. int fit_image_get_node(const void *fit, const char *image_uname)
  450. {
  451. int noffset, images_noffset;
  452. images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
  453. if (images_noffset < 0) {
  454. debug("Can't find images parent node '%s' (%s)\n",
  455. FIT_IMAGES_PATH, fdt_strerror(images_noffset));
  456. return images_noffset;
  457. }
  458. noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
  459. if (noffset < 0) {
  460. debug("Can't get node offset for image unit name: '%s' (%s)\n",
  461. image_uname, fdt_strerror(noffset));
  462. }
  463. return noffset;
  464. }
  465. /**
  466. * fit_image_get_os - get os id for a given component image node
  467. * @fit: pointer to the FIT format image header
  468. * @noffset: component image node offset
  469. * @os: pointer to the uint8_t, will hold os numeric id
  470. *
  471. * fit_image_get_os() finds os property in a given component image node.
  472. * If the property is found, its (string) value is translated to the numeric
  473. * id which is returned to the caller.
  474. *
  475. * returns:
  476. * 0, on success
  477. * -1, on failure
  478. */
  479. int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
  480. {
  481. int len;
  482. const void *data;
  483. /* Get OS name from property data */
  484. data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
  485. if (data == NULL) {
  486. fit_get_debug(fit, noffset, FIT_OS_PROP, len);
  487. *os = -1;
  488. return -1;
  489. }
  490. /* Translate OS name to id */
  491. *os = genimg_get_os_id(data);
  492. return 0;
  493. }
  494. /**
  495. * fit_image_get_arch - get arch id for a given component image node
  496. * @fit: pointer to the FIT format image header
  497. * @noffset: component image node offset
  498. * @arch: pointer to the uint8_t, will hold arch numeric id
  499. *
  500. * fit_image_get_arch() finds arch property in a given component image node.
  501. * If the property is found, its (string) value is translated to the numeric
  502. * id which is returned to the caller.
  503. *
  504. * returns:
  505. * 0, on success
  506. * -1, on failure
  507. */
  508. int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
  509. {
  510. int len;
  511. const void *data;
  512. /* Get architecture name from property data */
  513. data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
  514. if (data == NULL) {
  515. fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
  516. *arch = -1;
  517. return -1;
  518. }
  519. /* Translate architecture name to id */
  520. *arch = genimg_get_arch_id(data);
  521. return 0;
  522. }
  523. /**
  524. * fit_image_get_type - get type id for a given component image node
  525. * @fit: pointer to the FIT format image header
  526. * @noffset: component image node offset
  527. * @type: pointer to the uint8_t, will hold type numeric id
  528. *
  529. * fit_image_get_type() finds type property in a given component image node.
  530. * If the property is found, its (string) value is translated to the numeric
  531. * id which is returned to the caller.
  532. *
  533. * returns:
  534. * 0, on success
  535. * -1, on failure
  536. */
  537. int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
  538. {
  539. int len;
  540. const void *data;
  541. /* Get image type name from property data */
  542. data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
  543. if (data == NULL) {
  544. fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
  545. *type = -1;
  546. return -1;
  547. }
  548. /* Translate image type name to id */
  549. *type = genimg_get_type_id(data);
  550. return 0;
  551. }
  552. /**
  553. * fit_image_get_comp - get comp id for a given component image node
  554. * @fit: pointer to the FIT format image header
  555. * @noffset: component image node offset
  556. * @comp: pointer to the uint8_t, will hold comp numeric id
  557. *
  558. * fit_image_get_comp() finds comp property in a given component image node.
  559. * If the property is found, its (string) value is translated to the numeric
  560. * id which is returned to the caller.
  561. *
  562. * returns:
  563. * 0, on success
  564. * -1, on failure
  565. */
  566. int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
  567. {
  568. int len;
  569. const void *data;
  570. /* Get compression name from property data */
  571. data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
  572. if (data == NULL) {
  573. fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
  574. *comp = -1;
  575. return -1;
  576. }
  577. /* Translate compression name to id */
  578. *comp = genimg_get_comp_id(data);
  579. return 0;
  580. }
  581. /**
  582. * fit_image_get_load() - get load addr property for given component image node
  583. * @fit: pointer to the FIT format image header
  584. * @noffset: component image node offset
  585. * @load: pointer to the uint32_t, will hold load address
  586. *
  587. * fit_image_get_load() finds load address property in a given component
  588. * image node. If the property is found, its value is returned to the caller.
  589. *
  590. * returns:
  591. * 0, on success
  592. * -1, on failure
  593. */
  594. int fit_image_get_load(const void *fit, int noffset, ulong *load)
  595. {
  596. int len;
  597. const uint32_t *data;
  598. data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len);
  599. if (data == NULL) {
  600. fit_get_debug(fit, noffset, FIT_LOAD_PROP, len);
  601. return -1;
  602. }
  603. *load = uimage_to_cpu(*data);
  604. return 0;
  605. }
  606. /**
  607. * fit_image_get_entry() - get entry point address property
  608. * @fit: pointer to the FIT format image header
  609. * @noffset: component image node offset
  610. * @entry: pointer to the uint32_t, will hold entry point address
  611. *
  612. * This gets the entry point address property for a given component image
  613. * node.
  614. *
  615. * fit_image_get_entry() finds entry point address property in a given
  616. * component image node. If the property is found, its value is returned
  617. * to the caller.
  618. *
  619. * returns:
  620. * 0, on success
  621. * -1, on failure
  622. */
  623. int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
  624. {
  625. int len;
  626. const uint32_t *data;
  627. data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len);
  628. if (data == NULL) {
  629. fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len);
  630. return -1;
  631. }
  632. *entry = uimage_to_cpu(*data);
  633. return 0;
  634. }
  635. /**
  636. * fit_image_get_data - get data property and its size for a given component image node
  637. * @fit: pointer to the FIT format image header
  638. * @noffset: component image node offset
  639. * @data: double pointer to void, will hold data property's data address
  640. * @size: pointer to size_t, will hold data property's data size
  641. *
  642. * fit_image_get_data() finds data property in a given component image node.
  643. * If the property is found its data start address and size are returned to
  644. * the caller.
  645. *
  646. * returns:
  647. * 0, on success
  648. * -1, on failure
  649. */
  650. int fit_image_get_data(const void *fit, int noffset,
  651. const void **data, size_t *size)
  652. {
  653. int len;
  654. *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
  655. if (*data == NULL) {
  656. fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
  657. *size = 0;
  658. return -1;
  659. }
  660. *size = len;
  661. return 0;
  662. }
  663. /**
  664. * fit_image_hash_get_algo - get hash algorithm name
  665. * @fit: pointer to the FIT format image header
  666. * @noffset: hash node offset
  667. * @algo: double pointer to char, will hold pointer to the algorithm name
  668. *
  669. * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
  670. * If the property is found its data start address is returned to the caller.
  671. *
  672. * returns:
  673. * 0, on success
  674. * -1, on failure
  675. */
  676. int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
  677. {
  678. int len;
  679. *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
  680. if (*algo == NULL) {
  681. fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
  682. return -1;
  683. }
  684. return 0;
  685. }
  686. /**
  687. * fit_image_hash_get_value - get hash value and length
  688. * @fit: pointer to the FIT format image header
  689. * @noffset: hash node offset
  690. * @value: double pointer to uint8_t, will hold address of a hash value data
  691. * @value_len: pointer to an int, will hold hash data length
  692. *
  693. * fit_image_hash_get_value() finds hash value property in a given hash node.
  694. * If the property is found its data start address and size are returned to
  695. * the caller.
  696. *
  697. * returns:
  698. * 0, on success
  699. * -1, on failure
  700. */
  701. int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
  702. int *value_len)
  703. {
  704. int len;
  705. *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
  706. if (*value == NULL) {
  707. fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
  708. *value_len = 0;
  709. return -1;
  710. }
  711. *value_len = len;
  712. return 0;
  713. }
  714. /**
  715. * fit_image_hash_get_ignore - get hash ignore flag
  716. * @fit: pointer to the FIT format image header
  717. * @noffset: hash node offset
  718. * @ignore: pointer to an int, will hold hash ignore flag
  719. *
  720. * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
  721. * If the property is found and non-zero, the hash algorithm is not verified by
  722. * u-boot automatically.
  723. *
  724. * returns:
  725. * 0, on ignore not found
  726. * value, on ignore found
  727. */
  728. static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
  729. {
  730. int len;
  731. int *value;
  732. value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
  733. if (value == NULL || len != sizeof(int))
  734. *ignore = 0;
  735. else
  736. *ignore = *value;
  737. return 0;
  738. }
  739. /**
  740. * fit_set_timestamp - set node timestamp property
  741. * @fit: pointer to the FIT format image header
  742. * @noffset: node offset
  743. * @timestamp: timestamp value to be set
  744. *
  745. * fit_set_timestamp() attempts to set timestamp property in the requested
  746. * node and returns operation status to the caller.
  747. *
  748. * returns:
  749. * 0, on success
  750. * -1, on property read failure
  751. */
  752. int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
  753. {
  754. uint32_t t;
  755. int ret;
  756. t = cpu_to_uimage(timestamp);
  757. ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
  758. sizeof(uint32_t));
  759. if (ret) {
  760. printf("Can't set '%s' property for '%s' node (%s)\n",
  761. FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
  762. fdt_strerror(ret));
  763. return -1;
  764. }
  765. return 0;
  766. }
  767. /**
  768. * calculate_hash - calculate and return hash for provided input data
  769. * @data: pointer to the input data
  770. * @data_len: data length
  771. * @algo: requested hash algorithm
  772. * @value: pointer to the char, will hold hash value data (caller must
  773. * allocate enough free space)
  774. * value_len: length of the calculated hash
  775. *
  776. * calculate_hash() computes input data hash according to the requested
  777. * algorithm.
  778. * Resulting hash value is placed in caller provided 'value' buffer, length
  779. * of the calculated hash is returned via value_len pointer argument.
  780. *
  781. * returns:
  782. * 0, on success
  783. * -1, when algo is unsupported
  784. */
  785. int calculate_hash(const void *data, int data_len, const char *algo,
  786. uint8_t *value, int *value_len)
  787. {
  788. if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) {
  789. *((uint32_t *)value) = crc32_wd(0, data, data_len,
  790. CHUNKSZ_CRC32);
  791. *((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
  792. *value_len = 4;
  793. } else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) {
  794. sha1_csum_wd((unsigned char *)data, data_len,
  795. (unsigned char *)value, CHUNKSZ_SHA1);
  796. *value_len = 20;
  797. } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
  798. md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
  799. *value_len = 16;
  800. } else {
  801. debug("Unsupported hash alogrithm\n");
  802. return -1;
  803. }
  804. return 0;
  805. }
  806. static int fit_image_check_hash(const void *fit, int noffset, const void *data,
  807. size_t size, char **err_msgp)
  808. {
  809. uint8_t value[FIT_MAX_HASH_LEN];
  810. int value_len;
  811. char *algo;
  812. uint8_t *fit_value;
  813. int fit_value_len;
  814. int ignore;
  815. *err_msgp = NULL;
  816. if (fit_image_hash_get_algo(fit, noffset, &algo)) {
  817. *err_msgp = "Can't get hash algo property";
  818. return -1;
  819. }
  820. printf("%s", algo);
  821. if (IMAGE_ENABLE_IGNORE) {
  822. fit_image_hash_get_ignore(fit, noffset, &ignore);
  823. if (ignore) {
  824. printf("-skipped ");
  825. return 0;
  826. }
  827. }
  828. if (fit_image_hash_get_value(fit, noffset, &fit_value,
  829. &fit_value_len)) {
  830. *err_msgp = "Can't get hash value property";
  831. return -1;
  832. }
  833. if (calculate_hash(data, size, algo, value, &value_len)) {
  834. *err_msgp = "Unsupported hash algorithm";
  835. return -1;
  836. }
  837. if (value_len != fit_value_len) {
  838. *err_msgp = "Bad hash value len";
  839. return -1;
  840. } else if (memcmp(value, fit_value, value_len) != 0) {
  841. *err_msgp = "Bad hash value";
  842. return -1;
  843. }
  844. return 0;
  845. }
  846. /**
  847. * fit_image_verify - verify data intergity
  848. * @fit: pointer to the FIT format image header
  849. * @image_noffset: component image node offset
  850. *
  851. * fit_image_verify() goes over component image hash nodes,
  852. * re-calculates each data hash and compares with the value stored in hash
  853. * node.
  854. *
  855. * returns:
  856. * 1, if all hashes are valid
  857. * 0, otherwise (or on error)
  858. */
  859. int fit_image_verify(const void *fit, int image_noffset)
  860. {
  861. const void *data;
  862. size_t size;
  863. int noffset = 0;
  864. char *err_msg = "";
  865. int verify_all = 1;
  866. int ret;
  867. /* Get image data and data length */
  868. if (fit_image_get_data(fit, image_noffset, &data, &size)) {
  869. err_msg = "Can't get image data/size";
  870. goto error;
  871. }
  872. /* Verify all required signatures */
  873. if (IMAGE_ENABLE_VERIFY &&
  874. fit_image_verify_required_sigs(fit, image_noffset, data, size,
  875. gd_fdt_blob(), &verify_all)) {
  876. err_msg = "Unable to verify required signature";
  877. goto error;
  878. }
  879. /* Process all hash subnodes of the component image node */
  880. for (noffset = fdt_first_subnode(fit, image_noffset);
  881. noffset >= 0;
  882. noffset = fdt_next_subnode(fit, noffset)) {
  883. const char *name = fit_get_name(fit, noffset, NULL);
  884. /*
  885. * Check subnode name, must be equal to "hash".
  886. * Multiple hash nodes require unique unit node
  887. * names, e.g. hash@1, hash@2, etc.
  888. */
  889. if (!strncmp(name, FIT_HASH_NODENAME,
  890. strlen(FIT_HASH_NODENAME))) {
  891. if (fit_image_check_hash(fit, noffset, data, size,
  892. &err_msg))
  893. goto error;
  894. puts("+ ");
  895. } else if (IMAGE_ENABLE_VERIFY && verify_all &&
  896. !strncmp(name, FIT_SIG_NODENAME,
  897. strlen(FIT_SIG_NODENAME))) {
  898. ret = fit_image_check_sig(fit, noffset, data,
  899. size, -1, &err_msg);
  900. if (ret)
  901. puts("- ");
  902. else
  903. puts("+ ");
  904. }
  905. }
  906. if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
  907. err_msg = "Corrupted or truncated tree";
  908. goto error;
  909. }
  910. return 1;
  911. error:
  912. printf(" error!\n%s for '%s' hash node in '%s' image node\n",
  913. err_msg, fit_get_name(fit, noffset, NULL),
  914. fit_get_name(fit, image_noffset, NULL));
  915. return 0;
  916. }
  917. /**
  918. * fit_all_image_verify - verify data intergity for all images
  919. * @fit: pointer to the FIT format image header
  920. *
  921. * fit_all_image_verify() goes over all images in the FIT and
  922. * for every images checks if all it's hashes are valid.
  923. *
  924. * returns:
  925. * 1, if all hashes of all images are valid
  926. * 0, otherwise (or on error)
  927. */
  928. int fit_all_image_verify(const void *fit)
  929. {
  930. int images_noffset;
  931. int noffset;
  932. int ndepth;
  933. int count;
  934. /* Find images parent node offset */
  935. images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
  936. if (images_noffset < 0) {
  937. printf("Can't find images parent node '%s' (%s)\n",
  938. FIT_IMAGES_PATH, fdt_strerror(images_noffset));
  939. return 0;
  940. }
  941. /* Process all image subnodes, check hashes for each */
  942. printf("## Checking hash(es) for FIT Image at %08lx ...\n",
  943. (ulong)fit);
  944. for (ndepth = 0, count = 0,
  945. noffset = fdt_next_node(fit, images_noffset, &ndepth);
  946. (noffset >= 0) && (ndepth > 0);
  947. noffset = fdt_next_node(fit, noffset, &ndepth)) {
  948. if (ndepth == 1) {
  949. /*
  950. * Direct child node of the images parent node,
  951. * i.e. component image node.
  952. */
  953. printf(" Hash(es) for Image %u (%s): ", count++,
  954. fit_get_name(fit, noffset, NULL));
  955. if (!fit_image_verify(fit, noffset))
  956. return 0;
  957. printf("\n");
  958. }
  959. }
  960. return 1;
  961. }
  962. /**
  963. * fit_image_check_os - check whether image node is of a given os type
  964. * @fit: pointer to the FIT format image header
  965. * @noffset: component image node offset
  966. * @os: requested image os
  967. *
  968. * fit_image_check_os() reads image os property and compares its numeric
  969. * id with the requested os. Comparison result is returned to the caller.
  970. *
  971. * returns:
  972. * 1 if image is of given os type
  973. * 0 otherwise (or on error)
  974. */
  975. int fit_image_check_os(const void *fit, int noffset, uint8_t os)
  976. {
  977. uint8_t image_os;
  978. if (fit_image_get_os(fit, noffset, &image_os))
  979. return 0;
  980. return (os == image_os);
  981. }
  982. /**
  983. * fit_image_check_arch - check whether image node is of a given arch
  984. * @fit: pointer to the FIT format image header
  985. * @noffset: component image node offset
  986. * @arch: requested imagearch
  987. *
  988. * fit_image_check_arch() reads image arch property and compares its numeric
  989. * id with the requested arch. Comparison result is returned to the caller.
  990. *
  991. * returns:
  992. * 1 if image is of given arch
  993. * 0 otherwise (or on error)
  994. */
  995. int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
  996. {
  997. uint8_t image_arch;
  998. if (fit_image_get_arch(fit, noffset, &image_arch))
  999. return 0;
  1000. return (arch == image_arch);
  1001. }
  1002. /**
  1003. * fit_image_check_type - check whether image node is of a given type
  1004. * @fit: pointer to the FIT format image header
  1005. * @noffset: component image node offset
  1006. * @type: requested image type
  1007. *
  1008. * fit_image_check_type() reads image type property and compares its numeric
  1009. * id with the requested type. Comparison result is returned to the caller.
  1010. *
  1011. * returns:
  1012. * 1 if image is of given type
  1013. * 0 otherwise (or on error)
  1014. */
  1015. int fit_image_check_type(const void *fit, int noffset, uint8_t type)
  1016. {
  1017. uint8_t image_type;
  1018. if (fit_image_get_type(fit, noffset, &image_type))
  1019. return 0;
  1020. return (type == image_type);
  1021. }
  1022. /**
  1023. * fit_image_check_comp - check whether image node uses given compression
  1024. * @fit: pointer to the FIT format image header
  1025. * @noffset: component image node offset
  1026. * @comp: requested image compression type
  1027. *
  1028. * fit_image_check_comp() reads image compression property and compares its
  1029. * numeric id with the requested compression type. Comparison result is
  1030. * returned to the caller.
  1031. *
  1032. * returns:
  1033. * 1 if image uses requested compression
  1034. * 0 otherwise (or on error)
  1035. */
  1036. int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
  1037. {
  1038. uint8_t image_comp;
  1039. if (fit_image_get_comp(fit, noffset, &image_comp))
  1040. return 0;
  1041. return (comp == image_comp);
  1042. }
  1043. /**
  1044. * fit_check_format - sanity check FIT image format
  1045. * @fit: pointer to the FIT format image header
  1046. *
  1047. * fit_check_format() runs a basic sanity FIT image verification.
  1048. * Routine checks for mandatory properties, nodes, etc.
  1049. *
  1050. * returns:
  1051. * 1, on success
  1052. * 0, on failure
  1053. */
  1054. int fit_check_format(const void *fit)
  1055. {
  1056. /* mandatory / node 'description' property */
  1057. if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
  1058. debug("Wrong FIT format: no description\n");
  1059. return 0;
  1060. }
  1061. if (IMAGE_ENABLE_TIMESTAMP) {
  1062. /* mandatory / node 'timestamp' property */
  1063. if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
  1064. debug("Wrong FIT format: no timestamp\n");
  1065. return 0;
  1066. }
  1067. }
  1068. /* mandatory subimages parent '/images' node */
  1069. if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
  1070. debug("Wrong FIT format: no images parent node\n");
  1071. return 0;
  1072. }
  1073. return 1;
  1074. }
  1075. /**
  1076. * fit_conf_find_compat
  1077. * @fit: pointer to the FIT format image header
  1078. * @fdt: pointer to the device tree to compare against
  1079. *
  1080. * fit_conf_find_compat() attempts to find the configuration whose fdt is the
  1081. * most compatible with the passed in device tree.
  1082. *
  1083. * Example:
  1084. *
  1085. * / o image-tree
  1086. * |-o images
  1087. * | |-o fdt@1
  1088. * | |-o fdt@2
  1089. * |
  1090. * |-o configurations
  1091. * |-o config@1
  1092. * | |-fdt = fdt@1
  1093. * |
  1094. * |-o config@2
  1095. * |-fdt = fdt@2
  1096. *
  1097. * / o U-Boot fdt
  1098. * |-compatible = "foo,bar", "bim,bam"
  1099. *
  1100. * / o kernel fdt1
  1101. * |-compatible = "foo,bar",
  1102. *
  1103. * / o kernel fdt2
  1104. * |-compatible = "bim,bam", "baz,biz"
  1105. *
  1106. * Configuration 1 would be picked because the first string in U-Boot's
  1107. * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
  1108. * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
  1109. *
  1110. * returns:
  1111. * offset to the configuration to use if one was found
  1112. * -1 otherwise
  1113. */
  1114. int fit_conf_find_compat(const void *fit, const void *fdt)
  1115. {
  1116. int ndepth = 0;
  1117. int noffset, confs_noffset, images_noffset;
  1118. const void *fdt_compat;
  1119. int fdt_compat_len;
  1120. int best_match_offset = 0;
  1121. int best_match_pos = 0;
  1122. confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
  1123. images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
  1124. if (confs_noffset < 0 || images_noffset < 0) {
  1125. debug("Can't find configurations or images nodes.\n");
  1126. return -1;
  1127. }
  1128. fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
  1129. if (!fdt_compat) {
  1130. debug("Fdt for comparison has no \"compatible\" property.\n");
  1131. return -1;
  1132. }
  1133. /*
  1134. * Loop over the configurations in the FIT image.
  1135. */
  1136. for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
  1137. (noffset >= 0) && (ndepth > 0);
  1138. noffset = fdt_next_node(fit, noffset, &ndepth)) {
  1139. const void *kfdt;
  1140. const char *kfdt_name;
  1141. int kfdt_noffset;
  1142. const char *cur_fdt_compat;
  1143. int len;
  1144. size_t size;
  1145. int i;
  1146. if (ndepth > 1)
  1147. continue;
  1148. kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
  1149. if (!kfdt_name) {
  1150. debug("No fdt property found.\n");
  1151. continue;
  1152. }
  1153. kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
  1154. kfdt_name);
  1155. if (kfdt_noffset < 0) {
  1156. debug("No image node named \"%s\" found.\n",
  1157. kfdt_name);
  1158. continue;
  1159. }
  1160. /*
  1161. * Get a pointer to this configuration's fdt.
  1162. */
  1163. if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
  1164. debug("Failed to get fdt \"%s\".\n", kfdt_name);
  1165. continue;
  1166. }
  1167. len = fdt_compat_len;
  1168. cur_fdt_compat = fdt_compat;
  1169. /*
  1170. * Look for a match for each U-Boot compatibility string in
  1171. * turn in this configuration's fdt.
  1172. */
  1173. for (i = 0; len > 0 &&
  1174. (!best_match_offset || best_match_pos > i); i++) {
  1175. int cur_len = strlen(cur_fdt_compat) + 1;
  1176. if (!fdt_node_check_compatible(kfdt, 0,
  1177. cur_fdt_compat)) {
  1178. best_match_offset = noffset;
  1179. best_match_pos = i;
  1180. break;
  1181. }
  1182. len -= cur_len;
  1183. cur_fdt_compat += cur_len;
  1184. }
  1185. }
  1186. if (!best_match_offset) {
  1187. debug("No match found.\n");
  1188. return -1;
  1189. }
  1190. return best_match_offset;
  1191. }
  1192. /**
  1193. * fit_conf_get_node - get node offset for configuration of a given unit name
  1194. * @fit: pointer to the FIT format image header
  1195. * @conf_uname: configuration node unit name
  1196. *
  1197. * fit_conf_get_node() finds a configuration (withing the '/configurations'
  1198. * parant node) of a provided unit name. If configuration is found its node
  1199. * offset is returned to the caller.
  1200. *
  1201. * When NULL is provided in second argument fit_conf_get_node() will search
  1202. * for a default configuration node instead. Default configuration node unit
  1203. * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
  1204. * node.
  1205. *
  1206. * returns:
  1207. * configuration node offset when found (>=0)
  1208. * negative number on failure (FDT_ERR_* code)
  1209. */
  1210. int fit_conf_get_node(const void *fit, const char *conf_uname)
  1211. {
  1212. int noffset, confs_noffset;
  1213. int len;
  1214. confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
  1215. if (confs_noffset < 0) {
  1216. debug("Can't find configurations parent node '%s' (%s)\n",
  1217. FIT_CONFS_PATH, fdt_strerror(confs_noffset));
  1218. return confs_noffset;
  1219. }
  1220. if (conf_uname == NULL) {
  1221. /* get configuration unit name from the default property */
  1222. debug("No configuration specified, trying default...\n");
  1223. conf_uname = (char *)fdt_getprop(fit, confs_noffset,
  1224. FIT_DEFAULT_PROP, &len);
  1225. if (conf_uname == NULL) {
  1226. fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
  1227. len);
  1228. return len;
  1229. }
  1230. debug("Found default configuration: '%s'\n", conf_uname);
  1231. }
  1232. noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
  1233. if (noffset < 0) {
  1234. debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
  1235. conf_uname, fdt_strerror(noffset));
  1236. }
  1237. return noffset;
  1238. }
  1239. int fit_conf_get_prop_node(const void *fit, int noffset,
  1240. const char *prop_name)
  1241. {
  1242. char *uname;
  1243. int len;
  1244. /* get kernel image unit name from configuration kernel property */
  1245. uname = (char *)fdt_getprop(fit, noffset, prop_name, &len);
  1246. if (uname == NULL)
  1247. return len;
  1248. return fit_image_get_node(fit, uname);
  1249. }
  1250. /**
  1251. * fit_conf_print - prints out the FIT configuration details
  1252. * @fit: pointer to the FIT format image header
  1253. * @noffset: offset of the configuration node
  1254. * @p: pointer to prefix string
  1255. *
  1256. * fit_conf_print() lists all mandatory properies for the processed
  1257. * configuration node.
  1258. *
  1259. * returns:
  1260. * no returned results
  1261. */
  1262. void fit_conf_print(const void *fit, int noffset, const char *p)
  1263. {
  1264. char *desc;
  1265. char *uname;
  1266. int ret;
  1267. /* Mandatory properties */
  1268. ret = fit_get_desc(fit, noffset, &desc);
  1269. printf("%s Description: ", p);
  1270. if (ret)
  1271. printf("unavailable\n");
  1272. else
  1273. printf("%s\n", desc);
  1274. uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
  1275. printf("%s Kernel: ", p);
  1276. if (uname == NULL)
  1277. printf("unavailable\n");
  1278. else
  1279. printf("%s\n", uname);
  1280. /* Optional properties */
  1281. uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
  1282. if (uname)
  1283. printf("%s Init Ramdisk: %s\n", p, uname);
  1284. uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
  1285. if (uname)
  1286. printf("%s FDT: %s\n", p, uname);
  1287. }
  1288. int fit_image_select(const void *fit, int rd_noffset, int verify)
  1289. {
  1290. fit_image_print(fit, rd_noffset, " ");
  1291. if (verify) {
  1292. puts(" Verifying Hash Integrity ... ");
  1293. if (!fit_image_verify(fit, rd_noffset)) {
  1294. puts("Bad Data Hash\n");
  1295. return -EACCES;
  1296. }
  1297. puts("OK\n");
  1298. }
  1299. return 0;
  1300. }
  1301. int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
  1302. ulong addr)
  1303. {
  1304. int cfg_noffset;
  1305. void *fit_hdr;
  1306. int noffset;
  1307. debug("* %s: using config '%s' from image at 0x%08lx\n",
  1308. prop_name, images->fit_uname_cfg, addr);
  1309. /* Check whether configuration has this property defined */
  1310. fit_hdr = map_sysmem(addr, 0);
  1311. cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
  1312. if (cfg_noffset < 0) {
  1313. debug("* %s: no such config\n", prop_name);
  1314. return -ENOENT;
  1315. }
  1316. noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
  1317. if (noffset < 0) {
  1318. debug("* %s: no '%s' in config\n", prop_name, prop_name);
  1319. return -ENOLINK;
  1320. }
  1321. return noffset;
  1322. }
  1323. int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr,
  1324. const char **fit_unamep, const char **fit_uname_configp,
  1325. int arch, int image_type, int bootstage_id,
  1326. enum fit_load_op load_op, ulong *datap, ulong *lenp)
  1327. {
  1328. int cfg_noffset, noffset;
  1329. const char *fit_uname;
  1330. const char *fit_uname_config;
  1331. const void *fit;
  1332. const void *buf;
  1333. size_t size;
  1334. int type_ok, os_ok;
  1335. ulong load, data, len;
  1336. int ret;
  1337. fit = map_sysmem(addr, 0);
  1338. fit_uname = fit_unamep ? *fit_unamep : NULL;
  1339. fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL;
  1340. printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
  1341. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
  1342. if (!fit_check_format(fit)) {
  1343. printf("Bad FIT %s image format!\n", prop_name);
  1344. bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
  1345. return -ENOEXEC;
  1346. }
  1347. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
  1348. if (fit_uname) {
  1349. /* get FIT component image node offset */
  1350. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME);
  1351. noffset = fit_image_get_node(fit, fit_uname);
  1352. } else {
  1353. /*
  1354. * no image node unit name, try to get config
  1355. * node first. If config unit node name is NULL
  1356. * fit_conf_get_node() will try to find default config node
  1357. */
  1358. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME);
  1359. if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) {
  1360. cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
  1361. } else {
  1362. cfg_noffset = fit_conf_get_node(fit,
  1363. fit_uname_config);
  1364. }
  1365. if (cfg_noffset < 0) {
  1366. puts("Could not find configuration node\n");
  1367. bootstage_error(bootstage_id +
  1368. BOOTSTAGE_SUB_NO_UNIT_NAME);
  1369. return -ENOENT;
  1370. }
  1371. fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
  1372. printf(" Using '%s' configuration\n", fit_uname_config);
  1373. if (image_type == IH_TYPE_KERNEL) {
  1374. /* Remember (and possibly verify) this config */
  1375. images->fit_uname_cfg = fit_uname_config;
  1376. if (IMAGE_ENABLE_VERIFY && images->verify) {
  1377. puts(" Verifying Hash Integrity ... ");
  1378. if (!fit_config_verify(fit, cfg_noffset)) {
  1379. puts("Bad Data Hash\n");
  1380. bootstage_error(bootstage_id +
  1381. BOOTSTAGE_SUB_HASH);
  1382. return -EACCES;
  1383. }
  1384. puts("OK\n");
  1385. }
  1386. bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
  1387. }
  1388. noffset = fit_conf_get_prop_node(fit, cfg_noffset,
  1389. prop_name);
  1390. fit_uname = fit_get_name(fit, noffset, NULL);
  1391. }
  1392. if (noffset < 0) {
  1393. puts("Could not find subimage node\n");
  1394. bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
  1395. return -ENOENT;
  1396. }
  1397. printf(" Trying '%s' %s subimage\n", fit_uname, prop_name);
  1398. ret = fit_image_select(fit, noffset, images->verify);
  1399. if (ret) {
  1400. bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
  1401. return ret;
  1402. }
  1403. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
  1404. if (!fit_image_check_target_arch(fit, noffset)) {
  1405. puts("Unsupported Architecture\n");
  1406. bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
  1407. return -ENOEXEC;
  1408. }
  1409. if (image_type == IH_TYPE_FLATDT &&
  1410. !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
  1411. puts("FDT image is compressed");
  1412. return -EPROTONOSUPPORT;
  1413. }
  1414. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
  1415. type_ok = fit_image_check_type(fit, noffset, image_type) ||
  1416. (image_type == IH_TYPE_KERNEL &&
  1417. fit_image_check_type(fit, noffset,
  1418. IH_TYPE_KERNEL_NOLOAD));
  1419. os_ok = image_type == IH_TYPE_FLATDT ||
  1420. fit_image_check_os(fit, noffset, IH_OS_LINUX);
  1421. if (!type_ok || !os_ok) {
  1422. printf("No Linux %s %s Image\n", genimg_get_arch_name(arch),
  1423. genimg_get_type_name(image_type));
  1424. bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
  1425. return -EIO;
  1426. }
  1427. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
  1428. /* get image data address and length */
  1429. if (fit_image_get_data(fit, noffset, &buf, &size)) {
  1430. printf("Could not find %s subimage data!\n", prop_name);
  1431. bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
  1432. return -ENOENT;
  1433. }
  1434. len = (ulong)size;
  1435. /* verify that image data is a proper FDT blob */
  1436. if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
  1437. puts("Subimage data is not a FDT");
  1438. return -ENOEXEC;
  1439. }
  1440. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
  1441. /*
  1442. * Work-around for eldk-4.2 which gives this warning if we try to
  1443. * case in the unmap_sysmem() call:
  1444. * warning: initialization discards qualifiers from pointer target type
  1445. */
  1446. {
  1447. void *vbuf = (void *)buf;
  1448. data = map_to_sysmem(vbuf);
  1449. }
  1450. if (load_op == FIT_LOAD_IGNORED) {
  1451. /* Don't load */
  1452. } else if (fit_image_get_load(fit, noffset, &load)) {
  1453. if (load_op == FIT_LOAD_REQUIRED) {
  1454. printf("Can't get %s subimage load address!\n",
  1455. prop_name);
  1456. bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD);
  1457. return -EBADF;
  1458. }
  1459. } else {
  1460. ulong image_start, image_end;
  1461. ulong load_end;
  1462. void *dst;
  1463. /*
  1464. * move image data to the load address,
  1465. * make sure we don't overwrite initial image
  1466. */
  1467. image_start = addr;
  1468. image_end = addr + fit_get_size(fit);
  1469. load_end = load + len;
  1470. if (image_type != IH_TYPE_KERNEL &&
  1471. load < image_end && load_end > image_start) {
  1472. printf("Error: %s overwritten\n", prop_name);
  1473. return -EXDEV;
  1474. }
  1475. printf(" Loading %s from 0x%08lx to 0x%08lx\n",
  1476. prop_name, data, load);
  1477. dst = map_sysmem(load, len);
  1478. memmove(dst, buf, len);
  1479. data = load;
  1480. }
  1481. bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
  1482. *datap = data;
  1483. *lenp = len;
  1484. if (fit_unamep)
  1485. *fit_unamep = (char *)fit_uname;
  1486. if (fit_uname_configp)
  1487. *fit_uname_configp = (char *)fit_uname_config;
  1488. return noffset;
  1489. }