fdt_overlay.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  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. * @fdt: Base Device Tree blob
  269. * @fdto: Device tree overlay blob
  270. * @symbols_off: Node offset of the symbols node in the base device tree
  271. * @path: Path to a node holding a phandle in the overlay
  272. * @path_len: number of path characters to consider
  273. * @name: Name of the property holding the phandle reference in the overlay
  274. * @name_len: number of name characters to consider
  275. * @poffset: Offset within the overlay property where the phandle is stored
  276. * @phandle: Phandle referencing the node
  277. *
  278. * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
  279. * a node in the base device tree.
  280. *
  281. * This is part of the device tree overlay application process, when
  282. * you want all the phandles in the overlay to point to the actual
  283. * base dt nodes.
  284. *
  285. * returns:
  286. * 0 on success
  287. * Negative error code on failure
  288. */
  289. static int overlay_fixup_one_phandle(void *fdt, void *fdto,
  290. int symbols_off,
  291. const char *path, uint32_t path_len,
  292. const char *name, uint32_t name_len,
  293. int poffset, uint32_t phandle)
  294. {
  295. fdt32_t phandle_prop;
  296. int fixup_off;
  297. if (symbols_off < 0)
  298. return symbols_off;
  299. fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
  300. if (fixup_off == -FDT_ERR_NOTFOUND)
  301. return -FDT_ERR_BADOVERLAY;
  302. if (fixup_off < 0)
  303. return fixup_off;
  304. phandle_prop = cpu_to_fdt32(phandle);
  305. return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
  306. name, name_len, poffset,
  307. &phandle_prop,
  308. sizeof(phandle_prop));
  309. };
  310. /**
  311. * overlay_fixup_phandle - Set an overlay phandle to the base one
  312. * @fdt: Base Device Tree blob
  313. * @fdto: Device tree overlay blob
  314. * @symbols_off: Node offset of the symbols node in the base device tree
  315. * @property: Property offset in the overlay holding the list of fixups
  316. *
  317. * overlay_fixup_phandle() resolves all the overlay phandles pointed
  318. * to in a __fixups__ property, and updates them to match the phandles
  319. * in use in the base device tree.
  320. *
  321. * This is part of the device tree overlay application process, when
  322. * you want all the phandles in the overlay to point to the actual
  323. * base dt nodes.
  324. *
  325. * returns:
  326. * 0 on success
  327. * Negative error code on failure
  328. */
  329. static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
  330. int property)
  331. {
  332. const char *value;
  333. const char *label;
  334. int len;
  335. const char *symbol_path;
  336. int prop_len;
  337. int symbol_off;
  338. uint32_t phandle;
  339. value = fdt_getprop_by_offset(fdto, property,
  340. &label, &len);
  341. if (!value) {
  342. if (len == -FDT_ERR_NOTFOUND)
  343. return -FDT_ERR_INTERNAL;
  344. return len;
  345. }
  346. symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
  347. if (!symbol_path)
  348. return prop_len;
  349. symbol_off = fdt_path_offset(fdt, symbol_path);
  350. if (symbol_off < 0)
  351. return symbol_off;
  352. phandle = fdt_get_phandle(fdt, symbol_off);
  353. if (!phandle)
  354. return -FDT_ERR_NOTFOUND;
  355. do {
  356. const char *path, *name, *fixup_end;
  357. const char *fixup_str = value;
  358. uint32_t path_len, name_len;
  359. uint32_t fixup_len;
  360. char *sep, *endptr;
  361. int poffset, ret;
  362. fixup_end = memchr(value, '\0', len);
  363. if (!fixup_end)
  364. return -FDT_ERR_BADOVERLAY;
  365. fixup_len = fixup_end - fixup_str;
  366. len -= fixup_len + 1;
  367. value += fixup_len + 1;
  368. path = fixup_str;
  369. sep = memchr(fixup_str, ':', fixup_len);
  370. if (!sep || *sep != ':')
  371. return -FDT_ERR_BADOVERLAY;
  372. path_len = sep - path;
  373. if (path_len == (fixup_len - 1))
  374. return -FDT_ERR_BADOVERLAY;
  375. fixup_len -= path_len + 1;
  376. name = sep + 1;
  377. sep = memchr(name, ':', fixup_len);
  378. if (!sep || *sep != ':')
  379. return -FDT_ERR_BADOVERLAY;
  380. name_len = sep - name;
  381. if (!name_len)
  382. return -FDT_ERR_BADOVERLAY;
  383. poffset = strtoul(sep + 1, &endptr, 10);
  384. if ((*endptr != '\0') || (endptr <= (sep + 1)))
  385. return -FDT_ERR_BADOVERLAY;
  386. ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
  387. path, path_len, name, name_len,
  388. poffset, phandle);
  389. if (ret)
  390. return ret;
  391. } while (len > 0);
  392. return 0;
  393. }
  394. /**
  395. * overlay_fixup_phandles - Resolve the overlay phandles to the base
  396. * device tree
  397. * @fdt: Base Device Tree blob
  398. * @fdto: Device tree overlay blob
  399. *
  400. * overlay_fixup_phandles() resolves all the overlay phandles pointing
  401. * to nodes in the base device tree.
  402. *
  403. * This is one of the steps of the device tree overlay application
  404. * process, when you want all the phandles in the overlay to point to
  405. * the actual base dt nodes.
  406. *
  407. * returns:
  408. * 0 on success
  409. * Negative error code on failure
  410. */
  411. static int overlay_fixup_phandles(void *fdt, void *fdto)
  412. {
  413. int fixups_off, symbols_off;
  414. int property;
  415. /* We can have overlays without any fixups */
  416. fixups_off = fdt_path_offset(fdto, "/__fixups__");
  417. if (fixups_off == -FDT_ERR_NOTFOUND)
  418. return 0; /* nothing to do */
  419. if (fixups_off < 0)
  420. return fixups_off;
  421. /* And base DTs without symbols */
  422. symbols_off = fdt_path_offset(fdt, "/__symbols__");
  423. if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
  424. return symbols_off;
  425. fdt_for_each_property_offset(property, fdto, fixups_off) {
  426. int ret;
  427. ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
  428. if (ret)
  429. return ret;
  430. }
  431. return 0;
  432. }
  433. /**
  434. * overlay_adjust_local_conflicting_phandle: Changes a phandle value
  435. * @fdto: Device tree overlay
  436. * @node: The node the phandle is set for
  437. * @fdt_phandle: The new value for the phandle
  438. *
  439. * returns:
  440. * 0 on success
  441. * Negative error code on failure
  442. */
  443. static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
  444. uint32_t fdt_phandle)
  445. {
  446. const fdt32_t *php;
  447. int len, ret;
  448. php = fdt_getprop(fdto, node, "phandle", &len);
  449. if (php && len == sizeof(*php)) {
  450. ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
  451. if (ret)
  452. return ret;
  453. }
  454. php = fdt_getprop(fdto, node, "linux,phandle", &len);
  455. if (php && len == sizeof(*php)) {
  456. ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
  457. if (ret)
  458. return ret;
  459. }
  460. return 0;
  461. }
  462. /**
  463. * overlay_update_node_conflicting_references - Recursively replace phandle values
  464. * @fdto: Device tree overlay blob
  465. * @tree_node: Node to recurse into
  466. * @fixup_node: Node offset of the matching local fixups node
  467. * @fdt_phandle: Value to replace phandles with
  468. * @fdto_phandle: Value to be replaced
  469. *
  470. * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
  471. *
  472. * returns:
  473. * 0 on success
  474. * Negative error code on failure
  475. */
  476. static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
  477. int fixup_node,
  478. uint32_t fdt_phandle,
  479. uint32_t fdto_phandle)
  480. {
  481. int fixup_prop;
  482. int fixup_child;
  483. int ret;
  484. fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
  485. const fdt32_t *fixup_val;
  486. const char *name;
  487. char *tree_val;
  488. int fixup_len;
  489. int tree_len;
  490. int i;
  491. fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
  492. &name, &fixup_len);
  493. if (!fixup_val)
  494. return fixup_len;
  495. if (fixup_len % sizeof(uint32_t))
  496. return -FDT_ERR_BADOVERLAY;
  497. fixup_len /= sizeof(uint32_t);
  498. tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
  499. if (!tree_val) {
  500. if (tree_len == -FDT_ERR_NOTFOUND)
  501. return -FDT_ERR_BADOVERLAY;
  502. return tree_len;
  503. }
  504. for (i = 0; i < fixup_len; i++) {
  505. fdt32_t *refp;
  506. uint32_t valp;
  507. refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
  508. valp = fdt32_ld(refp);
  509. if (valp == fdto_phandle)
  510. fdt32_st(refp, fdt_phandle);
  511. }
  512. }
  513. fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
  514. const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
  515. int tree_child;
  516. tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
  517. if (tree_child == -FDT_ERR_NOTFOUND)
  518. return -FDT_ERR_BADOVERLAY;
  519. if (tree_child < 0)
  520. return tree_child;
  521. ret = overlay_update_node_conflicting_references(fdto, tree_child,
  522. fixup_child,
  523. fdt_phandle,
  524. fdto_phandle);
  525. if (ret)
  526. return ret;
  527. }
  528. return 0;
  529. }
  530. /**
  531. * overlay_update_local_conflicting_references - Recursively replace phandle values
  532. * @fdto: Device tree overlay blob
  533. * @fdt_phandle: Value to replace phandles with
  534. * @fdto_phandle: Value to be replaced
  535. *
  536. * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
  537. *
  538. * returns:
  539. * 0 on success
  540. * Negative error code on failure
  541. */
  542. static int overlay_update_local_conflicting_references(void *fdto,
  543. uint32_t fdt_phandle,
  544. uint32_t fdto_phandle)
  545. {
  546. int fixups;
  547. fixups = fdt_path_offset(fdto, "/__local_fixups__");
  548. if (fixups == -FDT_ERR_NOTFOUND)
  549. return 0;
  550. if (fixups < 0)
  551. return fixups;
  552. return overlay_update_node_conflicting_references(fdto, 0, fixups,
  553. fdt_phandle,
  554. fdto_phandle);
  555. }
  556. /**
  557. * overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
  558. * @fdt: Base Device tree blob
  559. * @fdtnode: Node in fdt that is checked for an overwrite
  560. * @fdto: Device tree overlay blob
  561. * @fdtonode: Node in fdto matching @fdtnode
  562. *
  563. * returns:
  564. * 0 on success
  565. * Negative error code on failure
  566. */
  567. static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
  568. void *fdto, int fdtonode)
  569. {
  570. uint32_t fdt_phandle, fdto_phandle;
  571. int fdtochild;
  572. fdt_phandle = fdt_get_phandle(fdt, fdtnode);
  573. fdto_phandle = fdt_get_phandle(fdto, fdtonode);
  574. if (fdt_phandle && fdto_phandle) {
  575. int ret;
  576. ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
  577. fdt_phandle);
  578. if (ret)
  579. return ret;
  580. ret = overlay_update_local_conflicting_references(fdto,
  581. fdt_phandle,
  582. fdto_phandle);
  583. if (ret)
  584. return ret;
  585. }
  586. fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
  587. const char *name = fdt_get_name(fdto, fdtochild, NULL);
  588. int fdtchild;
  589. int ret;
  590. fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
  591. if (fdtchild == -FDT_ERR_NOTFOUND)
  592. /*
  593. * no further overwrites possible here as this node is
  594. * new
  595. */
  596. continue;
  597. ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
  598. fdto, fdtochild);
  599. if (ret)
  600. return ret;
  601. }
  602. return 0;
  603. }
  604. /**
  605. * overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
  606. * @fdt: Base Device Tree blob
  607. * @fdto: Device tree overlay blob
  608. *
  609. * Checks recursively if applying fdto overwrites phandle values in the base
  610. * dtb. When such a phandle is found, the fdto is changed to use the fdt's
  611. * phandle value to not break references in the base.
  612. *
  613. * returns:
  614. * 0 on success
  615. * Negative error code on failure
  616. */
  617. static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
  618. {
  619. int fragment;
  620. fdt_for_each_subnode(fragment, fdto, 0) {
  621. int overlay;
  622. int target;
  623. int ret;
  624. overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
  625. if (overlay == -FDT_ERR_NOTFOUND)
  626. continue;
  627. if (overlay < 0)
  628. return overlay;
  629. target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
  630. if (target == -FDT_ERR_NOTFOUND)
  631. /*
  632. * The subtree doesn't exist in the base, so nothing
  633. * will be overwritten.
  634. */
  635. continue;
  636. else if (target < 0)
  637. return target;
  638. ret = overlay_prevent_phandle_overwrite_node(fdt, target,
  639. fdto, overlay);
  640. if (ret)
  641. return ret;
  642. }
  643. return 0;
  644. }
  645. /**
  646. * overlay_apply_node - Merges a node into the base device tree
  647. * @fdt: Base Device Tree blob
  648. * @target: Node offset in the base device tree to apply the fragment to
  649. * @fdto: Device tree overlay blob
  650. * @node: Node offset in the overlay holding the changes to merge
  651. *
  652. * overlay_apply_node() merges a node into a target base device tree
  653. * node pointed.
  654. *
  655. * This is part of the final step in the device tree overlay
  656. * application process, when all the phandles have been adjusted and
  657. * resolved and you just have to merge overlay into the base device
  658. * tree.
  659. *
  660. * returns:
  661. * 0 on success
  662. * Negative error code on failure
  663. */
  664. static int overlay_apply_node(void *fdt, int target,
  665. void *fdto, int node)
  666. {
  667. int property;
  668. int subnode;
  669. fdt_for_each_property_offset(property, fdto, node) {
  670. const char *name;
  671. const void *prop;
  672. int prop_len;
  673. int ret;
  674. prop = fdt_getprop_by_offset(fdto, property, &name,
  675. &prop_len);
  676. if (prop_len == -FDT_ERR_NOTFOUND)
  677. return -FDT_ERR_INTERNAL;
  678. if (prop_len < 0)
  679. return prop_len;
  680. ret = fdt_setprop(fdt, target, name, prop, prop_len);
  681. if (ret)
  682. return ret;
  683. }
  684. fdt_for_each_subnode(subnode, fdto, node) {
  685. const char *name = fdt_get_name(fdto, subnode, NULL);
  686. int nnode;
  687. int ret;
  688. nnode = fdt_add_subnode(fdt, target, name);
  689. if (nnode == -FDT_ERR_EXISTS) {
  690. nnode = fdt_subnode_offset(fdt, target, name);
  691. if (nnode == -FDT_ERR_NOTFOUND)
  692. return -FDT_ERR_INTERNAL;
  693. }
  694. if (nnode < 0)
  695. return nnode;
  696. ret = overlay_apply_node(fdt, nnode, fdto, subnode);
  697. if (ret)
  698. return ret;
  699. }
  700. return 0;
  701. }
  702. /**
  703. * overlay_merge - Merge an overlay into its base device tree
  704. * @fdt: Base Device Tree blob
  705. * @fdto: Device tree overlay blob
  706. *
  707. * overlay_merge() merges an overlay into its base device tree.
  708. *
  709. * This is the next to last step in the device tree overlay application
  710. * process, when all the phandles have been adjusted and resolved and
  711. * you just have to merge overlay into the base device tree.
  712. *
  713. * returns:
  714. * 0 on success
  715. * Negative error code on failure
  716. */
  717. static int overlay_merge(void *fdt, void *fdto)
  718. {
  719. int fragment;
  720. fdt_for_each_subnode(fragment, fdto, 0) {
  721. int overlay;
  722. int target;
  723. int ret;
  724. /*
  725. * Each fragments will have an __overlay__ node. If
  726. * they don't, it's not supposed to be merged
  727. */
  728. overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
  729. if (overlay == -FDT_ERR_NOTFOUND)
  730. continue;
  731. if (overlay < 0)
  732. return overlay;
  733. target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
  734. if (target < 0)
  735. return target;
  736. ret = overlay_apply_node(fdt, target, fdto, overlay);
  737. if (ret)
  738. return ret;
  739. }
  740. return 0;
  741. }
  742. static int get_path_len(const void *fdt, int nodeoffset)
  743. {
  744. int len = 0, namelen;
  745. const char *name;
  746. FDT_RO_PROBE(fdt);
  747. for (;;) {
  748. name = fdt_get_name(fdt, nodeoffset, &namelen);
  749. if (!name)
  750. return namelen;
  751. /* root? we're done */
  752. if (namelen == 0)
  753. break;
  754. nodeoffset = fdt_parent_offset(fdt, nodeoffset);
  755. if (nodeoffset < 0)
  756. return nodeoffset;
  757. len += namelen + 1;
  758. }
  759. /* in case of root pretend it's "/" */
  760. if (len == 0)
  761. len++;
  762. return len;
  763. }
  764. /**
  765. * overlay_symbol_update - Update the symbols of base tree after a merge
  766. * @fdt: Base Device Tree blob
  767. * @fdto: Device tree overlay blob
  768. *
  769. * overlay_symbol_update() updates the symbols of the base tree with the
  770. * symbols of the applied overlay
  771. *
  772. * This is the last step in the device tree overlay application
  773. * process, allowing the reference of overlay symbols by subsequent
  774. * overlay operations.
  775. *
  776. * returns:
  777. * 0 on success
  778. * Negative error code on failure
  779. */
  780. static int overlay_symbol_update(void *fdt, void *fdto)
  781. {
  782. int root_sym, ov_sym, prop, path_len, fragment, target;
  783. int len, frag_name_len, ret, rel_path_len;
  784. const char *s, *e;
  785. const char *path;
  786. const char *name;
  787. const char *frag_name;
  788. const char *rel_path;
  789. const char *target_path;
  790. char *buf;
  791. void *p;
  792. ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
  793. /* if no overlay symbols exist no problem */
  794. if (ov_sym < 0)
  795. return 0;
  796. root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
  797. /* it no root symbols exist we should create them */
  798. if (root_sym == -FDT_ERR_NOTFOUND)
  799. root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
  800. /* any error is fatal now */
  801. if (root_sym < 0)
  802. return root_sym;
  803. /* iterate over each overlay symbol */
  804. fdt_for_each_property_offset(prop, fdto, ov_sym) {
  805. path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
  806. if (!path)
  807. return path_len;
  808. /* verify it's a string property (terminated by a single \0) */
  809. if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
  810. return -FDT_ERR_BADVALUE;
  811. /* keep end marker to avoid strlen() */
  812. e = path + path_len;
  813. if (*path != '/')
  814. return -FDT_ERR_BADVALUE;
  815. /* get fragment name first */
  816. s = strchr(path + 1, '/');
  817. if (!s) {
  818. /* Symbol refers to something that won't end
  819. * up in the target tree */
  820. continue;
  821. }
  822. frag_name = path + 1;
  823. frag_name_len = s - path - 1;
  824. /* verify format; safe since "s" lies in \0 terminated prop */
  825. len = sizeof("/__overlay__/") - 1;
  826. if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
  827. /* /<fragment-name>/__overlay__/<relative-subnode-path> */
  828. rel_path = s + len;
  829. rel_path_len = e - rel_path - 1;
  830. } else if ((e - s) == len
  831. && (memcmp(s, "/__overlay__", len - 1) == 0)) {
  832. /* /<fragment-name>/__overlay__ */
  833. rel_path = "";
  834. rel_path_len = 0;
  835. } else {
  836. /* Symbol refers to something that won't end
  837. * up in the target tree */
  838. continue;
  839. }
  840. /* find the fragment index in which the symbol lies */
  841. ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
  842. frag_name_len);
  843. /* not found? */
  844. if (ret < 0)
  845. return -FDT_ERR_BADOVERLAY;
  846. fragment = ret;
  847. /* an __overlay__ subnode must exist */
  848. ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
  849. if (ret < 0)
  850. return -FDT_ERR_BADOVERLAY;
  851. /* get the target of the fragment */
  852. ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
  853. if (ret < 0)
  854. return ret;
  855. target = ret;
  856. /* if we have a target path use */
  857. if (!target_path) {
  858. ret = get_path_len(fdt, target);
  859. if (ret < 0)
  860. return ret;
  861. len = ret;
  862. } else {
  863. len = strlen(target_path);
  864. }
  865. ret = fdt_setprop_placeholder(fdt, root_sym, name,
  866. len + (len > 1) + rel_path_len + 1, &p);
  867. if (ret < 0)
  868. return ret;
  869. if (!target_path) {
  870. /* again in case setprop_placeholder changed it */
  871. ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
  872. if (ret < 0)
  873. return ret;
  874. target = ret;
  875. }
  876. buf = p;
  877. if (len > 1) { /* target is not root */
  878. if (!target_path) {
  879. ret = fdt_get_path(fdt, target, buf, len + 1);
  880. if (ret < 0)
  881. return ret;
  882. } else
  883. memcpy(buf, target_path, len + 1);
  884. } else
  885. len--;
  886. buf[len] = '/';
  887. memcpy(buf + len + 1, rel_path, rel_path_len);
  888. buf[len + 1 + rel_path_len] = '\0';
  889. }
  890. return 0;
  891. }
  892. int fdt_overlay_apply(void *fdt, void *fdto)
  893. {
  894. uint32_t delta;
  895. int ret;
  896. FDT_RO_PROBE(fdt);
  897. FDT_RO_PROBE(fdto);
  898. ret = fdt_find_max_phandle(fdt, &delta);
  899. if (ret)
  900. goto err;
  901. /* Increase all phandles in the fdto by delta */
  902. ret = overlay_adjust_local_phandles(fdto, delta);
  903. if (ret)
  904. goto err;
  905. /* Adapt the phandle values in fdto to the above increase */
  906. ret = overlay_update_local_references(fdto, delta);
  907. if (ret)
  908. goto err;
  909. /* Update fdto's phandles using symbols from fdt */
  910. ret = overlay_fixup_phandles(fdt, fdto);
  911. if (ret)
  912. goto err;
  913. /* Don't overwrite phandles in fdt */
  914. ret = overlay_prevent_phandle_overwrite(fdt, fdto);
  915. if (ret)
  916. goto err;
  917. ret = overlay_merge(fdt, fdto);
  918. if (ret)
  919. goto err;
  920. ret = overlay_symbol_update(fdt, fdto);
  921. if (ret)
  922. goto err;
  923. /*
  924. * The overlay has been damaged, erase its magic.
  925. */
  926. fdt_set_magic(fdto, ~0);
  927. return 0;
  928. err:
  929. /*
  930. * The overlay might have been damaged, erase its magic.
  931. */
  932. fdt_set_magic(fdto, ~0);
  933. /*
  934. * The base device tree might have been damaged, erase its
  935. * magic.
  936. */
  937. fdt_set_magic(fdt, ~0);
  938. return ret;
  939. }