image-fit.c 44 KB

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