fdt_overlay.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
  2. /*
  3. * libfdt - Flat Device Tree manipulation
  4. * Copyright (C) 2016 Free Electrons
  5. * Copyright (C) 2016 NextThing Co.
  6. */
  7. #include "libfdt_env.h"
  8. #include <fdt.h>
  9. #include <libfdt.h>
  10. #include "libfdt_internal.h"
  11. /**
  12. * overlay_get_target_phandle - retrieves the target phandle of a fragment
  13. * @fdto: pointer to the device tree overlay blob
  14. * @fragment: node offset of the fragment in the overlay
  15. *
  16. * overlay_get_target_phandle() retrieves the target phandle of an
  17. * overlay fragment when that fragment uses a phandle (target
  18. * property) instead of a path (target-path property).
  19. *
  20. * returns:
  21. * the phandle pointed by the target property
  22. * 0, if the phandle was not found
  23. * -1, if the phandle was malformed
  24. */
  25. static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
  26. {
  27. const fdt32_t *val;
  28. int len;
  29. val = fdt_getprop(fdto, fragment, "target", &len);
  30. if (!val)
  31. return 0;
  32. if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
  33. return (uint32_t)-1;
  34. return fdt32_to_cpu(*val);
  35. }
  36. int fdt_overlay_target_offset(const void *fdt, const void *fdto,
  37. int fragment_offset, char const **pathp)
  38. {
  39. uint32_t phandle;
  40. const char *path = NULL;
  41. int path_len = 0, ret;
  42. /* Try first to do a phandle based lookup */
  43. phandle = overlay_get_target_phandle(fdto, fragment_offset);
  44. if (phandle == (uint32_t)-1)
  45. return -FDT_ERR_BADPHANDLE;
  46. /* no phandle, try path */
  47. if (!phandle) {
  48. /* And then a path based lookup */
  49. path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
  50. if (path)
  51. ret = fdt_path_offset(fdt, path);
  52. else
  53. ret = path_len;
  54. } else
  55. ret = fdt_node_offset_by_phandle(fdt, phandle);
  56. /*
  57. * If we haven't found either a target or a
  58. * target-path property in a node that contains a
  59. * __overlay__ subnode (we wouldn't be called
  60. * otherwise), consider it a improperly written
  61. * overlay
  62. */
  63. if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
  64. ret = -FDT_ERR_BADOVERLAY;
  65. /* return on error */
  66. if (ret < 0)
  67. return ret;
  68. /* return pointer to path (if available) */
  69. if (pathp)
  70. *pathp = path ? path : NULL;
  71. return ret;
  72. }
  73. /**
  74. * overlay_phandle_add_offset - Increases a phandle by an offset
  75. * @fdt: Base device tree blob
  76. * @node: Device tree overlay blob
  77. * @name: Name of the property to modify (phandle or linux,phandle)
  78. * @delta: offset to apply
  79. *
  80. * overlay_phandle_add_offset() increments a node phandle by a given
  81. * offset.
  82. *
  83. * returns:
  84. * 0 on success.
  85. * Negative error code on error
  86. */
  87. static int overlay_phandle_add_offset(void *fdt, int node,
  88. const char *name, uint32_t delta)
  89. {
  90. fdt32_t *valp, val;
  91. int len;
  92. valp = fdt_getprop_w(fdt, node, name, &len);
  93. if (!valp)
  94. return len;
  95. if (len != sizeof(val))
  96. return -FDT_ERR_BADPHANDLE;
  97. val = fdt32_ld(valp);
  98. if (val + delta < val || val + delta == (uint32_t)-1)
  99. return -FDT_ERR_NOPHANDLES;
  100. fdt32_st(valp, val + delta);
  101. return 0;
  102. }
  103. /**
  104. * overlay_adjust_node_phandles - Offsets the phandles of a node
  105. * @fdto: Device tree overlay blob
  106. * @node: Offset of the node we want to adjust
  107. * @delta: Offset to shift the phandles of
  108. *
  109. * overlay_adjust_node_phandles() adds a constant to all the phandles
  110. * of a given node. This is mainly use as part of the overlay
  111. * application process, when we want to update all the overlay
  112. * phandles to not conflict with the overlays of the base device tree.
  113. *
  114. * returns:
  115. * 0 on success
  116. * Negative error code on failure
  117. */
  118. static int overlay_adjust_node_phandles(void *fdto, int node,
  119. uint32_t delta)
  120. {
  121. int child;
  122. int ret;
  123. ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
  124. if (ret && ret != -FDT_ERR_NOTFOUND)
  125. return ret;
  126. ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
  127. if (ret && ret != -FDT_ERR_NOTFOUND)
  128. return ret;
  129. fdt_for_each_subnode(child, fdto, node) {
  130. ret = overlay_adjust_node_phandles(fdto, child, delta);
  131. if (ret)
  132. return ret;
  133. }
  134. return 0;
  135. }
  136. /**
  137. * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
  138. * @fdto: Device tree overlay blob
  139. * @delta: Offset to shift the phandles of
  140. *
  141. * overlay_adjust_local_phandles() adds a constant to all the
  142. * phandles of an overlay. This is mainly use as part of the overlay
  143. * application process, when we want to update all the overlay
  144. * phandles to not conflict with the overlays of the base device tree.
  145. *
  146. * returns:
  147. * 0 on success
  148. * Negative error code on failure
  149. */
  150. static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
  151. {
  152. /*
  153. * Start adjusting the phandles from the overlay root
  154. */
  155. return overlay_adjust_node_phandles(fdto, 0, delta);
  156. }
  157. /**
  158. * overlay_update_local_node_references - Adjust the overlay references
  159. * @fdto: Device tree overlay blob
  160. * @tree_node: Node offset of the node to operate on
  161. * @fixup_node: Node offset of the matching local fixups node
  162. * @delta: Offset to shift the phandles of
  163. *
  164. * overlay_update_local_nodes_references() update the phandles
  165. * pointing to a node within the device tree overlay by adding a
  166. * constant delta.
  167. *
  168. * This is mainly used as part of a device tree application process,
  169. * where you want the device tree overlays phandles to not conflict
  170. * with the ones from the base device tree before merging them.
  171. *
  172. * returns:
  173. * 0 on success
  174. * Negative error code on failure
  175. */
  176. static int overlay_update_local_node_references(void *fdto,
  177. int tree_node,
  178. int fixup_node,
  179. uint32_t delta)
  180. {
  181. int fixup_prop;
  182. int fixup_child;
  183. int ret;
  184. fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
  185. const fdt32_t *fixup_val;
  186. const char *name;
  187. char *tree_val;
  188. int fixup_len;
  189. int tree_len;
  190. int i;
  191. fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
  192. &name, &fixup_len);
  193. if (!fixup_val)
  194. return fixup_len;
  195. if (fixup_len % sizeof(uint32_t))
  196. return -FDT_ERR_BADOVERLAY;
  197. fixup_len /= sizeof(uint32_t);
  198. tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
  199. if (!tree_val) {
  200. if (tree_len == -FDT_ERR_NOTFOUND)
  201. return -FDT_ERR_BADOVERLAY;
  202. return tree_len;
  203. }
  204. for (i = 0; i < fixup_len; i++) {
  205. fdt32_t *refp;
  206. refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
  207. /*
  208. * phandles to fixup can be unaligned, so use
  209. * fdt32_{ld,st}() to read/write them.
  210. */
  211. fdt32_st(refp, fdt32_ld(refp) + delta);
  212. }
  213. }
  214. fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
  215. const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
  216. NULL);
  217. int tree_child;
  218. tree_child = fdt_subnode_offset(fdto, tree_node,
  219. fixup_child_name);
  220. if (tree_child == -FDT_ERR_NOTFOUND)
  221. return -FDT_ERR_BADOVERLAY;
  222. if (tree_child < 0)
  223. return tree_child;
  224. ret = overlay_update_local_node_references(fdto,
  225. tree_child,
  226. fixup_child,
  227. delta);
  228. if (ret)
  229. return ret;
  230. }
  231. return 0;
  232. }
  233. /**
  234. * overlay_update_local_references - Adjust the overlay references
  235. * @fdto: Device tree overlay blob
  236. * @delta: Offset to shift the phandles of
  237. *
  238. * overlay_update_local_references() update all the phandles pointing
  239. * to a node within the device tree overlay by adding a constant
  240. * delta to not conflict with the base overlay.
  241. *
  242. * This is mainly used as part of a device tree application process,
  243. * where you want the device tree overlays phandles to not conflict
  244. * with the ones from the base device tree before merging them.
  245. *
  246. * returns:
  247. * 0 on success
  248. * Negative error code on failure
  249. */
  250. static int overlay_update_local_references(void *fdto, uint32_t delta)
  251. {
  252. int fixups;
  253. fixups = fdt_path_offset(fdto, "/__local_fixups__");
  254. if (fixups < 0) {
  255. /* There's no local phandles to adjust, bail out */
  256. if (fixups == -FDT_ERR_NOTFOUND)
  257. return 0;
  258. return fixups;
  259. }
  260. /*
  261. * Update our local references from the root of the tree
  262. */
  263. return overlay_update_local_node_references(fdto, 0, fixups,
  264. delta);
  265. }
  266. /**
  267. * overlay_fixup_one_phandle - Set an overlay phandle to the base one
  268. * @fdto: Device tree overlay blob
  269. * @symbols_off: Node offset of the symbols node in the base device tree
  270. * @path: Path to a node holding a phandle in the overlay
  271. * @path_len: number of path characters to consider
  272. * @name: Name of the property holding the phandle reference in the overlay
  273. * @name_len: number of name characters to consider
  274. * @poffset: Offset within the overlay property where the phandle is stored
  275. * @phandle: Phandle referencing the node
  276. *
  277. * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
  278. * a node in the base device tree.
  279. *
  280. * This is part of the device tree overlay application process, when
  281. * you want all the phandles in the overlay to point to the actual
  282. * base dt nodes.
  283. *
  284. * returns:
  285. * 0 on success
  286. * Negative error code on failure
  287. */
  288. static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
  289. const char *path, uint32_t path_len,
  290. const char *name, uint32_t name_len,
  291. int poffset, uint32_t phandle)
  292. {
  293. fdt32_t phandle_prop;
  294. int fixup_off;
  295. if (symbols_off < 0)
  296. return symbols_off;
  297. fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
  298. if (fixup_off == -FDT_ERR_NOTFOUND)
  299. return -FDT_ERR_BADOVERLAY;
  300. if (fixup_off < 0)
  301. return fixup_off;
  302. phandle_prop = cpu_to_fdt32(phandle);
  303. return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
  304. name, name_len, poffset,
  305. &phandle_prop,
  306. sizeof(phandle_prop));
  307. }
  308. /**
  309. * overlay_fixup_phandle - Set an overlay phandle to the base one
  310. * @fdt: Base Device Tree blob
  311. * @fdto: Device tree overlay blob
  312. * @symbols_off: Node offset of the symbols node in the base device tree
  313. * @property: Property offset in the overlay holding the list of fixups
  314. *
  315. * overlay_fixup_phandle() resolves all the overlay phandles pointed
  316. * to in a __fixups__ property, and updates them to match the phandles
  317. * in use in the base device tree.
  318. *
  319. * This is part of the device tree overlay application process, when
  320. * you want all the phandles in the overlay to point to the actual
  321. * base dt nodes.
  322. *
  323. * returns:
  324. * 0 on success
  325. * Negative error code on failure
  326. */
  327. static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
  328. int property)
  329. {
  330. const char *value;
  331. const char *label;
  332. int len;
  333. const char *symbol_path;
  334. int prop_len;
  335. int symbol_off;
  336. uint32_t phandle;
  337. value = fdt_getprop_by_offset(fdto, property,
  338. &label, &len);
  339. if (!value) {
  340. if (len == -FDT_ERR_NOTFOUND)
  341. return -FDT_ERR_INTERNAL;
  342. return len;
  343. }
  344. symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
  345. if (!symbol_path)
  346. return prop_len;
  347. symbol_off = fdt_path_offset(fdt, symbol_path);
  348. if (symbol_off < 0)
  349. return symbol_off;
  350. phandle = fdt_get_phandle(fdt, symbol_off);
  351. if (!phandle)
  352. return -FDT_ERR_NOTFOUND;
  353. do {
  354. const char *path, *name, *fixup_end;
  355. const char *fixup_str = value;
  356. uint32_t path_len, name_len;
  357. uint32_t fixup_len;
  358. const char *sep;
  359. char *endptr;
  360. int poffset, ret;
  361. fixup_end = memchr(value, '\0', len);
  362. if (!fixup_end)
  363. return -FDT_ERR_BADOVERLAY;
  364. fixup_len = fixup_end - fixup_str;
  365. len -= fixup_len + 1;
  366. value += fixup_len + 1;
  367. path = fixup_str;
  368. sep = memchr(fixup_str, ':', fixup_len);
  369. if (!sep || *sep != ':')
  370. return -FDT_ERR_BADOVERLAY;
  371. path_len = sep - path;
  372. if (path_len == (fixup_len - 1))
  373. return -FDT_ERR_BADOVERLAY;
  374. fixup_len -= path_len + 1;
  375. name = sep + 1;
  376. sep = memchr(name, ':', fixup_len);
  377. if (!sep || *sep != ':')
  378. return -FDT_ERR_BADOVERLAY;
  379. name_len = sep - name;
  380. if (!name_len)
  381. return -FDT_ERR_BADOVERLAY;
  382. poffset = strtoul(sep + 1, &endptr, 10);
  383. if ((*endptr != '\0') || (endptr <= (sep + 1)))
  384. return -FDT_ERR_BADOVERLAY;
  385. ret = overlay_fixup_one_phandle(fdto, symbols_off,
  386. path, path_len, name, name_len,
  387. poffset, phandle);
  388. if (ret)
  389. return ret;
  390. } while (len > 0);
  391. return 0;
  392. }
  393. /**
  394. * overlay_fixup_phandles - Resolve the overlay phandles to the base
  395. * device tree
  396. * @fdt: Base Device Tree blob
  397. * @fdto: Device tree overlay blob
  398. *
  399. * overlay_fixup_phandles() resolves all the overlay phandles pointing
  400. * to nodes in the base device tree.
  401. *
  402. * This is one of the steps of the device tree overlay application
  403. * process, when you want all the phandles in the overlay to point to
  404. * the actual base dt nodes.
  405. *
  406. * returns:
  407. * 0 on success
  408. * Negative error code on failure
  409. */
  410. static int overlay_fixup_phandles(void *fdt, void *fdto)
  411. {
  412. int fixups_off, symbols_off;
  413. int property;
  414. /* We can have overlays without any fixups */
  415. fixups_off = fdt_path_offset(fdto, "/__fixups__");
  416. if (fixups_off == -FDT_ERR_NOTFOUND)
  417. return 0; /* nothing to do */
  418. if (fixups_off < 0)
  419. return fixups_off;
  420. /* And base DTs without symbols */
  421. symbols_off = fdt_path_offset(fdt, "/__symbols__");
  422. if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
  423. return symbols_off;
  424. fdt_for_each_property_offset(property, fdto, fixups_off) {
  425. int ret;
  426. ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
  427. if (ret)
  428. return ret;
  429. }
  430. return 0;
  431. }
  432. /**
  433. * overlay_adjust_local_conflicting_phandle: Changes a phandle value
  434. * @fdto: Device tree overlay
  435. * @node: The node the phandle is set for
  436. * @fdt_phandle: The new value for the phandle
  437. *
  438. * returns:
  439. * 0 on success
  440. * Negative error code on failure
  441. */
  442. static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
  443. uint32_t fdt_phandle)
  444. {
  445. const fdt32_t *php;
  446. int len, ret;
  447. php = fdt_getprop(fdto, node, "phandle", &len);
  448. if (php && len == sizeof(*php)) {
  449. ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
  450. if (ret)
  451. return ret;
  452. }
  453. php = fdt_getprop(fdto, node, "linux,phandle", &len);
  454. if (php && len == sizeof(*php)) {
  455. ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
  456. if (ret)
  457. return ret;
  458. }
  459. return 0;
  460. }
  461. /**
  462. * overlay_update_node_conflicting_references - Recursively replace phandle values
  463. * @fdto: Device tree overlay blob
  464. * @tree_node: Node to recurse into
  465. * @fixup_node: Node offset of the matching local fixups node
  466. * @fdt_phandle: Value to replace phandles with
  467. * @fdto_phandle: Value to be replaced
  468. *
  469. * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
  470. *
  471. * returns:
  472. * 0 on success
  473. * Negative error code on failure
  474. */
  475. static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
  476. int fixup_node,
  477. uint32_t fdt_phandle,
  478. uint32_t fdto_phandle)
  479. {
  480. int fixup_prop;
  481. int fixup_child;
  482. int ret;
  483. fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
  484. const fdt32_t *fixup_val;
  485. const char *name;
  486. char *tree_val;
  487. int fixup_len;
  488. int tree_len;
  489. int i;
  490. fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
  491. &name, &fixup_len);
  492. if (!fixup_val)
  493. return fixup_len;
  494. if (fixup_len % sizeof(uint32_t))
  495. return -FDT_ERR_BADOVERLAY;
  496. fixup_len /= sizeof(uint32_t);
  497. tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
  498. if (!tree_val) {
  499. if (tree_len == -FDT_ERR_NOTFOUND)
  500. return -FDT_ERR_BADOVERLAY;
  501. return tree_len;
  502. }
  503. for (i = 0; i < fixup_len; i++) {
  504. fdt32_t *refp;
  505. uint32_t valp;
  506. refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
  507. valp = fdt32_ld(refp);
  508. if (valp == fdto_phandle)
  509. fdt32_st(refp, fdt_phandle);
  510. }
  511. }
  512. fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
  513. const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
  514. int tree_child;
  515. tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
  516. if (tree_child == -FDT_ERR_NOTFOUND)
  517. return -FDT_ERR_BADOVERLAY;
  518. if (tree_child < 0)
  519. return tree_child;
  520. ret = overlay_update_node_conflicting_references(fdto, tree_child,
  521. fixup_child,
  522. fdt_phandle,
  523. fdto_phandle);
  524. if (ret)
  525. return ret;
  526. }
  527. return 0;
  528. }
  529. /**
  530. * overlay_update_local_conflicting_references - Recursively replace phandle values
  531. * @fdto: Device tree overlay blob
  532. * @fdt_phandle: Value to replace phandles with
  533. * @fdto_phandle: Value to be replaced
  534. *
  535. * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
  536. *
  537. * returns:
  538. * 0 on success
  539. * Negative error code on failure
  540. */
  541. static int overlay_update_local_conflicting_references(void *fdto,
  542. uint32_t fdt_phandle,
  543. uint32_t fdto_phandle)
  544. {
  545. int fixups;
  546. fixups = fdt_path_offset(fdto, "/__local_fixups__");
  547. if (fixups == -FDT_ERR_NOTFOUND)
  548. return 0;
  549. if (fixups < 0)
  550. return fixups;
  551. return overlay_update_node_conflicting_references(fdto, 0, fixups,
  552. fdt_phandle,
  553. fdto_phandle);
  554. }
  555. /**
  556. * overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
  557. * @fdt: Base Device tree blob
  558. * @fdtnode: Node in fdt that is checked for an overwrite
  559. * @fdto: Device tree overlay blob
  560. * @fdtonode: Node in fdto matching @fdtnode
  561. *
  562. * returns:
  563. * 0 on success
  564. * Negative error code on failure
  565. */
  566. static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
  567. void *fdto, int fdtonode)
  568. {
  569. uint32_t fdt_phandle, fdto_phandle;
  570. int fdtochild;
  571. fdt_phandle = fdt_get_phandle(fdt, fdtnode);
  572. fdto_phandle = fdt_get_phandle(fdto, fdtonode);
  573. if (fdt_phandle && fdto_phandle) {
  574. int ret;
  575. ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
  576. fdt_phandle);
  577. if (ret)
  578. return ret;
  579. ret = overlay_update_local_conflicting_references(fdto,
  580. fdt_phandle,
  581. fdto_phandle);
  582. if (ret)
  583. return ret;
  584. }
  585. fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
  586. const char *name = fdt_get_name(fdto, fdtochild, NULL);
  587. int fdtchild;
  588. int ret;
  589. fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
  590. if (fdtchild == -FDT_ERR_NOTFOUND)
  591. /*
  592. * no further overwrites possible here as this node is
  593. * new
  594. */
  595. continue;
  596. ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
  597. fdto, fdtochild);
  598. if (ret)
  599. return ret;
  600. }
  601. return 0;
  602. }
  603. /**
  604. * overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
  605. * @fdt: Base Device Tree blob
  606. * @fdto: Device tree overlay blob
  607. *
  608. * Checks recursively if applying fdto overwrites phandle values in the base
  609. * dtb. When such a phandle is found, the fdto is changed to use the fdt's
  610. * phandle value to not break references in the base.
  611. *
  612. * returns:
  613. * 0 on success
  614. * Negative error code on failure
  615. */
  616. static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
  617. {
  618. int fragment;
  619. fdt_for_each_subnode(fragment, fdto, 0) {
  620. int overlay;
  621. int target;
  622. int ret;
  623. overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
  624. if (overlay == -FDT_ERR_NOTFOUND)
  625. continue;
  626. if (overlay < 0)
  627. return overlay;
  628. target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
  629. if (target == -FDT_ERR_NOTFOUND)
  630. /*
  631. * The subtree doesn't exist in the base, so nothing
  632. * will be overwritten.
  633. */
  634. continue;
  635. else if (target < 0)
  636. return target;
  637. ret = overlay_prevent_phandle_overwrite_node(fdt, target,
  638. fdto, overlay);
  639. if (ret)
  640. return ret;
  641. }
  642. return 0;
  643. }
  644. /**
  645. * overlay_apply_node - Merges a node into the base device tree
  646. * @fdt: Base Device Tree blob
  647. * @target: Node offset in the base device tree to apply the fragment to
  648. * @fdto: Device tree overlay blob
  649. * @node: Node offset in the overlay holding the changes to merge
  650. *
  651. * overlay_apply_node() merges a node into a target base device tree
  652. * node pointed.
  653. *
  654. * This is part of the final step in the device tree overlay
  655. * application process, when all the phandles have been adjusted and
  656. * resolved and you just have to merge overlay into the base device
  657. * tree.
  658. *
  659. * returns:
  660. * 0 on success
  661. * Negative error code on failure
  662. */
  663. static int overlay_apply_node(void *fdt, int target,
  664. void *fdto, int node)
  665. {
  666. int property;
  667. int subnode;
  668. fdt_for_each_property_offset(property, fdto, node) {
  669. const char *name;
  670. const void *prop;
  671. int prop_len;
  672. int ret;
  673. prop = fdt_getprop_by_offset(fdto, property, &name,
  674. &prop_len);
  675. if (prop_len == -FDT_ERR_NOTFOUND)
  676. return -FDT_ERR_INTERNAL;
  677. if (prop_len < 0)
  678. return prop_len;
  679. ret = fdt_setprop(fdt, target, name, prop, prop_len);
  680. if (ret)
  681. return ret;
  682. }
  683. fdt_for_each_subnode(subnode, fdto, node) {
  684. const char *name = fdt_get_name(fdto, subnode, NULL);
  685. int nnode;
  686. int ret;
  687. nnode = fdt_add_subnode(fdt, target, name);
  688. if (nnode == -FDT_ERR_EXISTS) {
  689. nnode = fdt_subnode_offset(fdt, target, name);
  690. if (nnode == -FDT_ERR_NOTFOUND)
  691. return -FDT_ERR_INTERNAL;
  692. }
  693. if (nnode < 0)
  694. return nnode;
  695. ret = overlay_apply_node(fdt, nnode, fdto, subnode);
  696. if (ret)
  697. return ret;
  698. }
  699. return 0;
  700. }
  701. /**
  702. * overlay_merge - Merge an overlay into its base device tree
  703. * @fdt: Base Device Tree blob
  704. * @fdto: Device tree overlay blob
  705. *
  706. * overlay_merge() merges an overlay into its base device tree.
  707. *
  708. * This is the next to last step in the device tree overlay application
  709. * process, when all the phandles have been adjusted and resolved and
  710. * you just have to merge overlay into the base device tree.
  711. *
  712. * returns:
  713. * 0 on success
  714. * Negative error code on failure
  715. */
  716. static int overlay_merge(void *fdt, void *fdto)
  717. {
  718. int fragment;
  719. fdt_for_each_subnode(fragment, fdto, 0) {
  720. int overlay;
  721. int target;
  722. int ret;
  723. /*
  724. * Each fragments will have an __overlay__ node. If
  725. * they don't, it's not supposed to be merged
  726. */
  727. overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
  728. if (overlay == -FDT_ERR_NOTFOUND)
  729. continue;
  730. if (overlay < 0)
  731. return overlay;
  732. target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
  733. if (target < 0)
  734. return target;
  735. ret = overlay_apply_node(fdt, target, fdto, overlay);
  736. if (ret)
  737. return ret;
  738. }
  739. return 0;
  740. }
  741. static int get_path_len(const void *fdt, int nodeoffset)
  742. {
  743. int len = 0, namelen;
  744. const char *name;
  745. FDT_RO_PROBE(fdt);
  746. for (;;) {
  747. name = fdt_get_name(fdt, nodeoffset, &namelen);
  748. if (!name)
  749. return namelen;
  750. /* root? we're done */
  751. if (namelen == 0)
  752. break;
  753. nodeoffset = fdt_parent_offset(fdt, nodeoffset);
  754. if (nodeoffset < 0)
  755. return nodeoffset;
  756. len += namelen + 1;
  757. }
  758. /* in case of root pretend it's "/" */
  759. if (len == 0)
  760. len++;
  761. return len;
  762. }
  763. /**
  764. * overlay_symbol_update - Update the symbols of base tree after a merge
  765. * @fdt: Base Device Tree blob
  766. * @fdto: Device tree overlay blob
  767. *
  768. * overlay_symbol_update() updates the symbols of the base tree with the
  769. * symbols of the applied overlay
  770. *
  771. * This is the last step in the device tree overlay application
  772. * process, allowing the reference of overlay symbols by subsequent
  773. * overlay operations.
  774. *
  775. * returns:
  776. * 0 on success
  777. * Negative error code on failure
  778. */
  779. static int overlay_symbol_update(void *fdt, void *fdto)
  780. {
  781. int root_sym, ov_sym, prop, path_len, fragment, target;
  782. int len, frag_name_len, ret, rel_path_len;
  783. const char *s, *e;
  784. const char *path;
  785. const char *name;
  786. const char *frag_name;
  787. const char *rel_path;
  788. const char *target_path;
  789. char *buf;
  790. void *p;
  791. ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
  792. /* if no overlay symbols exist no problem */
  793. if (ov_sym < 0)
  794. return 0;
  795. root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
  796. /* it no root symbols exist we should create them */
  797. if (root_sym == -FDT_ERR_NOTFOUND)
  798. root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
  799. /* any error is fatal now */
  800. if (root_sym < 0)
  801. return root_sym;
  802. /* iterate over each overlay symbol */
  803. fdt_for_each_property_offset(prop, fdto, ov_sym) {
  804. path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
  805. if (!path)
  806. return path_len;
  807. /* verify it's a string property (terminated by a single \0) */
  808. if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
  809. return -FDT_ERR_BADVALUE;
  810. /* keep end marker to avoid strlen() */
  811. e = path + path_len;
  812. if (*path != '/')
  813. return -FDT_ERR_BADVALUE;
  814. /* get fragment name first */
  815. s = strchr(path + 1, '/');
  816. if (!s) {
  817. /* Symbol refers to something that won't end
  818. * up in the target tree */
  819. continue;
  820. }
  821. frag_name = path + 1;
  822. frag_name_len = s - path - 1;
  823. /* verify format; safe since "s" lies in \0 terminated prop */
  824. len = sizeof("/__overlay__/") - 1;
  825. if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
  826. /* /<fragment-name>/__overlay__/<relative-subnode-path> */
  827. rel_path = s + len;
  828. rel_path_len = e - rel_path - 1;
  829. } else if ((e - s) == len
  830. && (memcmp(s, "/__overlay__", len - 1) == 0)) {
  831. /* /<fragment-name>/__overlay__ */
  832. rel_path = "";
  833. rel_path_len = 0;
  834. } else {
  835. /* Symbol refers to something that won't end
  836. * up in the target tree */
  837. continue;
  838. }
  839. /* find the fragment index in which the symbol lies */
  840. ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
  841. frag_name_len);
  842. /* not found? */
  843. if (ret < 0)
  844. return -FDT_ERR_BADOVERLAY;
  845. fragment = ret;
  846. /* an __overlay__ subnode must exist */
  847. ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
  848. if (ret < 0)
  849. return -FDT_ERR_BADOVERLAY;
  850. /* get the target of the fragment */
  851. ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
  852. if (ret < 0)
  853. return ret;
  854. target = ret;
  855. /* if we have a target path use */
  856. if (!target_path) {
  857. ret = get_path_len(fdt, target);
  858. if (ret < 0)
  859. return ret;
  860. len = ret;
  861. } else {
  862. len = strlen(target_path);
  863. }
  864. ret = fdt_setprop_placeholder(fdt, root_sym, name,
  865. len + (len > 1) + rel_path_len + 1, &p);
  866. if (ret < 0)
  867. return ret;
  868. if (!target_path) {
  869. /* again in case setprop_placeholder changed it */
  870. ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
  871. if (ret < 0)
  872. return ret;
  873. target = ret;
  874. }
  875. buf = p;
  876. if (len > 1) { /* target is not root */
  877. if (!target_path) {
  878. ret = fdt_get_path(fdt, target, buf, len + 1);
  879. if (ret < 0)
  880. return ret;
  881. } else
  882. memcpy(buf, target_path, len + 1);
  883. } else
  884. len--;
  885. buf[len] = '/';
  886. memcpy(buf + len + 1, rel_path, rel_path_len);
  887. buf[len + 1 + rel_path_len] = '\0';
  888. }
  889. return 0;
  890. }
  891. int fdt_overlay_apply(void *fdt, void *fdto)
  892. {
  893. uint32_t delta;
  894. int ret;
  895. FDT_RO_PROBE(fdt);
  896. FDT_RO_PROBE(fdto);
  897. ret = fdt_find_max_phandle(fdt, &delta);
  898. if (ret)
  899. goto err;
  900. /* Increase all phandles in the fdto by delta */
  901. ret = overlay_adjust_local_phandles(fdto, delta);
  902. if (ret)
  903. goto err;
  904. /* Adapt the phandle values in fdto to the above increase */
  905. ret = overlay_update_local_references(fdto, delta);
  906. if (ret)
  907. goto err;
  908. /* Update fdto's phandles using symbols from fdt */
  909. ret = overlay_fixup_phandles(fdt, fdto);
  910. if (ret)
  911. goto err;
  912. /* Don't overwrite phandles in fdt */
  913. ret = overlay_prevent_phandle_overwrite(fdt, fdto);
  914. if (ret)
  915. goto err;
  916. ret = overlay_merge(fdt, fdto);
  917. if (ret)
  918. goto err;
  919. ret = overlay_symbol_update(fdt, fdto);
  920. if (ret)
  921. goto err;
  922. /*
  923. * The overlay has been damaged, erase its magic.
  924. */
  925. fdt_set_magic(fdto, ~0);
  926. return 0;
  927. err:
  928. /*
  929. * The overlay might have been damaged, erase its magic.
  930. */
  931. fdt_set_magic(fdto, ~0);
  932. /*
  933. * The base device tree might have been damaged, erase its
  934. * magic.
  935. */
  936. fdt_set_magic(fdt, ~0);
  937. return ret;
  938. }