fdt_overlay.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  1. /*
  2. * libfdt - Flat Device Tree manipulation
  3. * Copyright (C) 2016 Free Electrons
  4. * Copyright (C) 2016 NextThing Co.
  5. *
  6. * libfdt is dual licensed: you can use it either under the terms of
  7. * the GPL, or the BSD license, at your option.
  8. *
  9. * a) This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public
  20. * License along with this library; if not, write to the Free
  21. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  22. * MA 02110-1301 USA
  23. *
  24. * Alternatively,
  25. *
  26. * b) Redistribution and use in source and binary forms, with or
  27. * without modification, are permitted provided that the following
  28. * conditions are met:
  29. *
  30. * 1. Redistributions of source code must retain the above
  31. * copyright notice, this list of conditions and the following
  32. * disclaimer.
  33. * 2. Redistributions in binary form must reproduce the above
  34. * copyright notice, this list of conditions and the following
  35. * disclaimer in the documentation and/or other materials
  36. * provided with the distribution.
  37. *
  38. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  39. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  40. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  41. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  42. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  43. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  48. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  49. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  50. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  51. */
  52. #include "libfdt_env.h"
  53. #include <fdt.h>
  54. #include <libfdt.h>
  55. #include "libfdt_internal.h"
  56. /**
  57. * overlay_get_target_phandle - retrieves the target phandle of a fragment
  58. * @fdto: pointer to the device tree overlay blob
  59. * @fragment: node offset of the fragment in the overlay
  60. *
  61. * overlay_get_target_phandle() retrieves the target phandle of an
  62. * overlay fragment when that fragment uses a phandle (target
  63. * property) instead of a path (target-path property).
  64. *
  65. * returns:
  66. * the phandle pointed by the target property
  67. * 0, if the phandle was not found
  68. * -1, if the phandle was malformed
  69. */
  70. static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
  71. {
  72. const fdt32_t *val;
  73. int len;
  74. val = fdt_getprop(fdto, fragment, "target", &len);
  75. if (!val)
  76. return 0;
  77. if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
  78. return (uint32_t)-1;
  79. return fdt32_to_cpu(*val);
  80. }
  81. /**
  82. * overlay_get_target - retrieves the offset of a fragment's target
  83. * @fdt: Base device tree blob
  84. * @fdto: Device tree overlay blob
  85. * @fragment: node offset of the fragment in the overlay
  86. * @pathp: pointer which receives the path of the target (or NULL)
  87. *
  88. * overlay_get_target() retrieves the target offset in the base
  89. * device tree of a fragment, no matter how the actual targetting is
  90. * done (through a phandle or a path)
  91. *
  92. * returns:
  93. * the targetted node offset in the base device tree
  94. * Negative error code on error
  95. */
  96. static int overlay_get_target(const void *fdt, const void *fdto,
  97. int fragment, char const **pathp)
  98. {
  99. uint32_t phandle;
  100. const char *path = NULL;
  101. int path_len = 0, ret;
  102. /* Try first to do a phandle based lookup */
  103. phandle = overlay_get_target_phandle(fdto, fragment);
  104. if (phandle == (uint32_t)-1)
  105. return -FDT_ERR_BADPHANDLE;
  106. /* no phandle, try path */
  107. if (!phandle) {
  108. /* And then a path based lookup */
  109. path = fdt_getprop(fdto, fragment, "target-path", &path_len);
  110. if (path)
  111. ret = fdt_path_offset(fdt, path);
  112. else
  113. ret = path_len;
  114. } else
  115. ret = fdt_node_offset_by_phandle(fdt, phandle);
  116. /*
  117. * If we haven't found either a target or a
  118. * target-path property in a node that contains a
  119. * __overlay__ subnode (we wouldn't be called
  120. * otherwise), consider it a improperly written
  121. * overlay
  122. */
  123. if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
  124. ret = -FDT_ERR_BADOVERLAY;
  125. /* return on error */
  126. if (ret < 0)
  127. return ret;
  128. /* return pointer to path (if available) */
  129. if (pathp)
  130. *pathp = path ? path : NULL;
  131. return ret;
  132. }
  133. /**
  134. * overlay_phandle_add_offset - Increases a phandle by an offset
  135. * @fdt: Base device tree blob
  136. * @node: Device tree overlay blob
  137. * @name: Name of the property to modify (phandle or linux,phandle)
  138. * @delta: offset to apply
  139. *
  140. * overlay_phandle_add_offset() increments a node phandle by a given
  141. * offset.
  142. *
  143. * returns:
  144. * 0 on success.
  145. * Negative error code on error
  146. */
  147. static int overlay_phandle_add_offset(void *fdt, int node,
  148. const char *name, uint32_t delta)
  149. {
  150. const fdt32_t *val;
  151. uint32_t adj_val;
  152. int len;
  153. val = fdt_getprop(fdt, node, name, &len);
  154. if (!val)
  155. return len;
  156. if (len != sizeof(*val))
  157. return -FDT_ERR_BADPHANDLE;
  158. adj_val = fdt32_to_cpu(*val);
  159. if ((adj_val + delta) < adj_val)
  160. return -FDT_ERR_NOPHANDLES;
  161. adj_val += delta;
  162. if (adj_val == (uint32_t)-1)
  163. return -FDT_ERR_NOPHANDLES;
  164. return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
  165. }
  166. /**
  167. * overlay_adjust_node_phandles - Offsets the phandles of a node
  168. * @fdto: Device tree overlay blob
  169. * @node: Offset of the node we want to adjust
  170. * @delta: Offset to shift the phandles of
  171. *
  172. * overlay_adjust_node_phandles() adds a constant to all the phandles
  173. * of a given node. This is mainly use as part of the overlay
  174. * application process, when we want to update all the overlay
  175. * phandles to not conflict with the overlays of the base device tree.
  176. *
  177. * returns:
  178. * 0 on success
  179. * Negative error code on failure
  180. */
  181. static int overlay_adjust_node_phandles(void *fdto, int node,
  182. uint32_t delta)
  183. {
  184. int child;
  185. int ret;
  186. ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
  187. if (ret && ret != -FDT_ERR_NOTFOUND)
  188. return ret;
  189. ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
  190. if (ret && ret != -FDT_ERR_NOTFOUND)
  191. return ret;
  192. fdt_for_each_subnode(child, fdto, node) {
  193. ret = overlay_adjust_node_phandles(fdto, child, delta);
  194. if (ret)
  195. return ret;
  196. }
  197. return 0;
  198. }
  199. /**
  200. * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
  201. * @fdto: Device tree overlay blob
  202. * @delta: Offset to shift the phandles of
  203. *
  204. * overlay_adjust_local_phandles() adds a constant to all the
  205. * phandles of an overlay. This is mainly use as part of the overlay
  206. * application process, when we want to update all the overlay
  207. * phandles to not conflict with the overlays of the base device tree.
  208. *
  209. * returns:
  210. * 0 on success
  211. * Negative error code on failure
  212. */
  213. static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
  214. {
  215. /*
  216. * Start adjusting the phandles from the overlay root
  217. */
  218. return overlay_adjust_node_phandles(fdto, 0, delta);
  219. }
  220. /**
  221. * overlay_update_local_node_references - Adjust the overlay references
  222. * @fdto: Device tree overlay blob
  223. * @tree_node: Node offset of the node to operate on
  224. * @fixup_node: Node offset of the matching local fixups node
  225. * @delta: Offset to shift the phandles of
  226. *
  227. * overlay_update_local_nodes_references() update the phandles
  228. * pointing to a node within the device tree overlay by adding a
  229. * constant delta.
  230. *
  231. * This is mainly used as part of a device tree application process,
  232. * where you want the device tree overlays phandles to not conflict
  233. * with the ones from the base device tree before merging them.
  234. *
  235. * returns:
  236. * 0 on success
  237. * Negative error code on failure
  238. */
  239. static int overlay_update_local_node_references(void *fdto,
  240. int tree_node,
  241. int fixup_node,
  242. uint32_t delta)
  243. {
  244. int fixup_prop;
  245. int fixup_child;
  246. int ret;
  247. fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
  248. const fdt32_t *fixup_val;
  249. const char *tree_val;
  250. const char *name;
  251. int fixup_len;
  252. int tree_len;
  253. int i;
  254. fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
  255. &name, &fixup_len);
  256. if (!fixup_val)
  257. return fixup_len;
  258. if (fixup_len % sizeof(uint32_t))
  259. return -FDT_ERR_BADOVERLAY;
  260. tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
  261. if (!tree_val) {
  262. if (tree_len == -FDT_ERR_NOTFOUND)
  263. return -FDT_ERR_BADOVERLAY;
  264. return tree_len;
  265. }
  266. for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
  267. fdt32_t adj_val;
  268. uint32_t poffset;
  269. poffset = fdt32_to_cpu(fixup_val[i]);
  270. /*
  271. * phandles to fixup can be unaligned.
  272. *
  273. * Use a memcpy for the architectures that do
  274. * not support unaligned accesses.
  275. */
  276. memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
  277. adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
  278. ret = fdt_setprop_inplace_namelen_partial(fdto,
  279. tree_node,
  280. name,
  281. strlen(name),
  282. poffset,
  283. &adj_val,
  284. sizeof(adj_val));
  285. if (ret == -FDT_ERR_NOSPACE)
  286. return -FDT_ERR_BADOVERLAY;
  287. if (ret)
  288. return ret;
  289. }
  290. }
  291. fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
  292. const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
  293. NULL);
  294. int tree_child;
  295. tree_child = fdt_subnode_offset(fdto, tree_node,
  296. fixup_child_name);
  297. if (tree_child == -FDT_ERR_NOTFOUND)
  298. return -FDT_ERR_BADOVERLAY;
  299. if (tree_child < 0)
  300. return tree_child;
  301. ret = overlay_update_local_node_references(fdto,
  302. tree_child,
  303. fixup_child,
  304. delta);
  305. if (ret)
  306. return ret;
  307. }
  308. return 0;
  309. }
  310. /**
  311. * overlay_update_local_references - Adjust the overlay references
  312. * @fdto: Device tree overlay blob
  313. * @delta: Offset to shift the phandles of
  314. *
  315. * overlay_update_local_references() update all the phandles pointing
  316. * to a node within the device tree overlay by adding a constant
  317. * delta to not conflict with the base overlay.
  318. *
  319. * This is mainly used as part of a device tree application process,
  320. * where you want the device tree overlays phandles to not conflict
  321. * with the ones from the base device tree before merging them.
  322. *
  323. * returns:
  324. * 0 on success
  325. * Negative error code on failure
  326. */
  327. static int overlay_update_local_references(void *fdto, uint32_t delta)
  328. {
  329. int fixups;
  330. fixups = fdt_path_offset(fdto, "/__local_fixups__");
  331. if (fixups < 0) {
  332. /* There's no local phandles to adjust, bail out */
  333. if (fixups == -FDT_ERR_NOTFOUND)
  334. return 0;
  335. return fixups;
  336. }
  337. /*
  338. * Update our local references from the root of the tree
  339. */
  340. return overlay_update_local_node_references(fdto, 0, fixups,
  341. delta);
  342. }
  343. /**
  344. * overlay_fixup_one_phandle - Set an overlay phandle to the base one
  345. * @fdt: Base Device Tree blob
  346. * @fdto: Device tree overlay blob
  347. * @symbols_off: Node offset of the symbols node in the base device tree
  348. * @path: Path to a node holding a phandle in the overlay
  349. * @path_len: number of path characters to consider
  350. * @name: Name of the property holding the phandle reference in the overlay
  351. * @name_len: number of name characters to consider
  352. * @poffset: Offset within the overlay property where the phandle is stored
  353. * @label: Label of the node referenced by the phandle
  354. *
  355. * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
  356. * a node in the base device tree.
  357. *
  358. * This is part of the device tree overlay application process, when
  359. * you want all the phandles in the overlay to point to the actual
  360. * base dt nodes.
  361. *
  362. * returns:
  363. * 0 on success
  364. * Negative error code on failure
  365. */
  366. static int overlay_fixup_one_phandle(void *fdt, void *fdto,
  367. int symbols_off,
  368. const char *path, uint32_t path_len,
  369. const char *name, uint32_t name_len,
  370. int poffset, const char *label)
  371. {
  372. const char *symbol_path;
  373. uint32_t phandle;
  374. fdt32_t phandle_prop;
  375. int symbol_off, fixup_off;
  376. int prop_len;
  377. if (symbols_off < 0)
  378. return symbols_off;
  379. symbol_path = fdt_getprop(fdt, symbols_off, label,
  380. &prop_len);
  381. if (!symbol_path)
  382. return prop_len;
  383. symbol_off = fdt_path_offset(fdt, symbol_path);
  384. if (symbol_off < 0)
  385. return symbol_off;
  386. phandle = fdt_get_phandle(fdt, symbol_off);
  387. if (!phandle)
  388. return -FDT_ERR_NOTFOUND;
  389. fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
  390. if (fixup_off == -FDT_ERR_NOTFOUND)
  391. return -FDT_ERR_BADOVERLAY;
  392. if (fixup_off < 0)
  393. return fixup_off;
  394. phandle_prop = cpu_to_fdt32(phandle);
  395. return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
  396. name, name_len, poffset,
  397. &phandle_prop,
  398. sizeof(phandle_prop));
  399. };
  400. /**
  401. * overlay_fixup_phandle - Set an overlay phandle to the base one
  402. * @fdt: Base Device Tree blob
  403. * @fdto: Device tree overlay blob
  404. * @symbols_off: Node offset of the symbols node in the base device tree
  405. * @property: Property offset in the overlay holding the list of fixups
  406. *
  407. * overlay_fixup_phandle() resolves all the overlay phandles pointed
  408. * to in a __fixups__ property, and updates them to match the phandles
  409. * in use in the base device tree.
  410. *
  411. * This is part of the device tree overlay application process, when
  412. * you want all the phandles in the overlay to point to the actual
  413. * base dt nodes.
  414. *
  415. * returns:
  416. * 0 on success
  417. * Negative error code on failure
  418. */
  419. static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
  420. int property)
  421. {
  422. const char *value;
  423. const char *label;
  424. int len;
  425. value = fdt_getprop_by_offset(fdto, property,
  426. &label, &len);
  427. if (!value) {
  428. if (len == -FDT_ERR_NOTFOUND)
  429. return -FDT_ERR_INTERNAL;
  430. return len;
  431. }
  432. do {
  433. const char *path, *name, *fixup_end;
  434. const char *fixup_str = value;
  435. uint32_t path_len, name_len;
  436. uint32_t fixup_len;
  437. char *sep, *endptr;
  438. int poffset, ret;
  439. fixup_end = memchr(value, '\0', len);
  440. if (!fixup_end)
  441. return -FDT_ERR_BADOVERLAY;
  442. fixup_len = fixup_end - fixup_str;
  443. len -= fixup_len + 1;
  444. value += fixup_len + 1;
  445. path = fixup_str;
  446. sep = memchr(fixup_str, ':', fixup_len);
  447. if (!sep || *sep != ':')
  448. return -FDT_ERR_BADOVERLAY;
  449. path_len = sep - path;
  450. if (path_len == (fixup_len - 1))
  451. return -FDT_ERR_BADOVERLAY;
  452. fixup_len -= path_len + 1;
  453. name = sep + 1;
  454. sep = memchr(name, ':', fixup_len);
  455. if (!sep || *sep != ':')
  456. return -FDT_ERR_BADOVERLAY;
  457. name_len = sep - name;
  458. if (!name_len)
  459. return -FDT_ERR_BADOVERLAY;
  460. poffset = strtoul(sep + 1, &endptr, 10);
  461. if ((*endptr != '\0') || (endptr <= (sep + 1)))
  462. return -FDT_ERR_BADOVERLAY;
  463. ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
  464. path, path_len, name, name_len,
  465. poffset, label);
  466. if (ret)
  467. return ret;
  468. } while (len > 0);
  469. return 0;
  470. }
  471. /**
  472. * overlay_fixup_phandles - Resolve the overlay phandles to the base
  473. * device tree
  474. * @fdt: Base Device Tree blob
  475. * @fdto: Device tree overlay blob
  476. *
  477. * overlay_fixup_phandles() resolves all the overlay phandles pointing
  478. * to nodes in the base device tree.
  479. *
  480. * This is one of the steps of the device tree overlay application
  481. * process, when you want all the phandles in the overlay to point to
  482. * the actual base dt nodes.
  483. *
  484. * returns:
  485. * 0 on success
  486. * Negative error code on failure
  487. */
  488. static int overlay_fixup_phandles(void *fdt, void *fdto)
  489. {
  490. int fixups_off, symbols_off;
  491. int property;
  492. /* We can have overlays without any fixups */
  493. fixups_off = fdt_path_offset(fdto, "/__fixups__");
  494. if (fixups_off == -FDT_ERR_NOTFOUND)
  495. return 0; /* nothing to do */
  496. if (fixups_off < 0)
  497. return fixups_off;
  498. /* And base DTs without symbols */
  499. symbols_off = fdt_path_offset(fdt, "/__symbols__");
  500. if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
  501. return symbols_off;
  502. fdt_for_each_property_offset(property, fdto, fixups_off) {
  503. int ret;
  504. ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
  505. if (ret)
  506. return ret;
  507. }
  508. return 0;
  509. }
  510. /**
  511. * overlay_apply_node - Merges a node into the base device tree
  512. * @fdt: Base Device Tree blob
  513. * @target: Node offset in the base device tree to apply the fragment to
  514. * @fdto: Device tree overlay blob
  515. * @node: Node offset in the overlay holding the changes to merge
  516. *
  517. * overlay_apply_node() merges a node into a target base device tree
  518. * node pointed.
  519. *
  520. * This is part of the final step in the device tree overlay
  521. * application process, when all the phandles have been adjusted and
  522. * resolved and you just have to merge overlay into the base device
  523. * tree.
  524. *
  525. * returns:
  526. * 0 on success
  527. * Negative error code on failure
  528. */
  529. static int overlay_apply_node(void *fdt, int target,
  530. void *fdto, int node)
  531. {
  532. int property;
  533. int subnode;
  534. fdt_for_each_property_offset(property, fdto, node) {
  535. const char *name;
  536. const void *prop;
  537. int prop_len;
  538. int ret;
  539. prop = fdt_getprop_by_offset(fdto, property, &name,
  540. &prop_len);
  541. if (prop_len == -FDT_ERR_NOTFOUND)
  542. return -FDT_ERR_INTERNAL;
  543. if (prop_len < 0)
  544. return prop_len;
  545. ret = fdt_setprop(fdt, target, name, prop, prop_len);
  546. if (ret)
  547. return ret;
  548. }
  549. fdt_for_each_subnode(subnode, fdto, node) {
  550. const char *name = fdt_get_name(fdto, subnode, NULL);
  551. int nnode;
  552. int ret;
  553. nnode = fdt_add_subnode(fdt, target, name);
  554. if (nnode == -FDT_ERR_EXISTS) {
  555. nnode = fdt_subnode_offset(fdt, target, name);
  556. if (nnode == -FDT_ERR_NOTFOUND)
  557. return -FDT_ERR_INTERNAL;
  558. }
  559. if (nnode < 0)
  560. return nnode;
  561. ret = overlay_apply_node(fdt, nnode, fdto, subnode);
  562. if (ret)
  563. return ret;
  564. }
  565. return 0;
  566. }
  567. /**
  568. * overlay_merge - Merge an overlay into its base device tree
  569. * @fdt: Base Device Tree blob
  570. * @fdto: Device tree overlay blob
  571. *
  572. * overlay_merge() merges an overlay into its base device tree.
  573. *
  574. * This is the next to last step in the device tree overlay application
  575. * process, when all the phandles have been adjusted and resolved and
  576. * you just have to merge overlay into the base device tree.
  577. *
  578. * returns:
  579. * 0 on success
  580. * Negative error code on failure
  581. */
  582. static int overlay_merge(void *fdt, void *fdto)
  583. {
  584. int fragment;
  585. fdt_for_each_subnode(fragment, fdto, 0) {
  586. int overlay;
  587. int target;
  588. int ret;
  589. /*
  590. * Each fragments will have an __overlay__ node. If
  591. * they don't, it's not supposed to be merged
  592. */
  593. overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
  594. if (overlay == -FDT_ERR_NOTFOUND)
  595. continue;
  596. if (overlay < 0)
  597. return overlay;
  598. target = overlay_get_target(fdt, fdto, fragment, NULL);
  599. if (target < 0)
  600. return target;
  601. ret = overlay_apply_node(fdt, target, fdto, overlay);
  602. if (ret)
  603. return ret;
  604. }
  605. return 0;
  606. }
  607. static int get_path_len(const void *fdt, int nodeoffset)
  608. {
  609. int len = 0, namelen;
  610. const char *name;
  611. FDT_CHECK_HEADER(fdt);
  612. for (;;) {
  613. name = fdt_get_name(fdt, nodeoffset, &namelen);
  614. if (!name)
  615. return namelen;
  616. /* root? we're done */
  617. if (namelen == 0)
  618. break;
  619. nodeoffset = fdt_parent_offset(fdt, nodeoffset);
  620. if (nodeoffset < 0)
  621. return nodeoffset;
  622. len += namelen + 1;
  623. }
  624. /* in case of root pretend it's "/" */
  625. if (len == 0)
  626. len++;
  627. return len;
  628. }
  629. /**
  630. * overlay_symbol_update - Update the symbols of base tree after a merge
  631. * @fdt: Base Device Tree blob
  632. * @fdto: Device tree overlay blob
  633. *
  634. * overlay_symbol_update() updates the symbols of the base tree with the
  635. * symbols of the applied overlay
  636. *
  637. * This is the last step in the device tree overlay application
  638. * process, allowing the reference of overlay symbols by subsequent
  639. * overlay operations.
  640. *
  641. * returns:
  642. * 0 on success
  643. * Negative error code on failure
  644. */
  645. static int overlay_symbol_update(void *fdt, void *fdto)
  646. {
  647. int root_sym, ov_sym, prop, path_len, fragment, target;
  648. int len, frag_name_len, ret, rel_path_len;
  649. const char *s, *e;
  650. const char *path;
  651. const char *name;
  652. const char *frag_name;
  653. const char *rel_path;
  654. const char *target_path;
  655. char *buf;
  656. void *p;
  657. ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
  658. /* if no overlay symbols exist no problem */
  659. if (ov_sym < 0)
  660. return 0;
  661. root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
  662. /* it no root symbols exist we should create them */
  663. if (root_sym == -FDT_ERR_NOTFOUND)
  664. root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
  665. /* any error is fatal now */
  666. if (root_sym < 0)
  667. return root_sym;
  668. /* iterate over each overlay symbol */
  669. fdt_for_each_property_offset(prop, fdto, ov_sym) {
  670. path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
  671. if (!path)
  672. return path_len;
  673. /* verify it's a string property (terminated by a single \0) */
  674. if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
  675. return -FDT_ERR_BADVALUE;
  676. /* keep end marker to avoid strlen() */
  677. e = path + path_len;
  678. /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
  679. if (*path != '/')
  680. return -FDT_ERR_BADVALUE;
  681. /* get fragment name first */
  682. s = strchr(path + 1, '/');
  683. if (!s)
  684. return -FDT_ERR_BADOVERLAY;
  685. frag_name = path + 1;
  686. frag_name_len = s - path - 1;
  687. /* verify format; safe since "s" lies in \0 terminated prop */
  688. len = sizeof("/__overlay__/") - 1;
  689. if ((e - s) < len || memcmp(s, "/__overlay__/", len))
  690. return -FDT_ERR_BADOVERLAY;
  691. rel_path = s + len;
  692. rel_path_len = e - rel_path;
  693. /* find the fragment index in which the symbol lies */
  694. ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
  695. frag_name_len);
  696. /* not found? */
  697. if (ret < 0)
  698. return -FDT_ERR_BADOVERLAY;
  699. fragment = ret;
  700. /* an __overlay__ subnode must exist */
  701. ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
  702. if (ret < 0)
  703. return -FDT_ERR_BADOVERLAY;
  704. /* get the target of the fragment */
  705. ret = overlay_get_target(fdt, fdto, fragment, &target_path);
  706. if (ret < 0)
  707. return ret;
  708. target = ret;
  709. /* if we have a target path use */
  710. if (!target_path) {
  711. ret = get_path_len(fdt, target);
  712. if (ret < 0)
  713. return ret;
  714. len = ret;
  715. } else {
  716. len = strlen(target_path);
  717. }
  718. ret = fdt_setprop_placeholder(fdt, root_sym, name,
  719. len + (len > 1) + rel_path_len + 1, &p);
  720. if (ret < 0)
  721. return ret;
  722. if (!target_path) {
  723. /* again in case setprop_placeholder changed it */
  724. ret = overlay_get_target(fdt, fdto, fragment, &target_path);
  725. if (ret < 0)
  726. return ret;
  727. target = ret;
  728. }
  729. buf = p;
  730. if (len > 1) { /* target is not root */
  731. if (!target_path) {
  732. ret = fdt_get_path(fdt, target, buf, len + 1);
  733. if (ret < 0)
  734. return ret;
  735. } else
  736. memcpy(buf, target_path, len + 1);
  737. } else
  738. len--;
  739. buf[len] = '/';
  740. memcpy(buf + len + 1, rel_path, rel_path_len);
  741. buf[len + 1 + rel_path_len] = '\0';
  742. }
  743. return 0;
  744. }
  745. int fdt_overlay_apply(void *fdt, void *fdto)
  746. {
  747. uint32_t delta = fdt_get_max_phandle(fdt);
  748. int ret;
  749. FDT_CHECK_HEADER(fdt);
  750. FDT_CHECK_HEADER(fdto);
  751. ret = overlay_adjust_local_phandles(fdto, delta);
  752. if (ret)
  753. goto err;
  754. ret = overlay_update_local_references(fdto, delta);
  755. if (ret)
  756. goto err;
  757. ret = overlay_fixup_phandles(fdt, fdto);
  758. if (ret)
  759. goto err;
  760. ret = overlay_merge(fdt, fdto);
  761. if (ret)
  762. goto err;
  763. ret = overlay_symbol_update(fdt, fdto);
  764. if (ret)
  765. goto err;
  766. /*
  767. * The overlay has been damaged, erase its magic.
  768. */
  769. fdt_set_magic(fdto, ~0);
  770. return 0;
  771. err:
  772. /*
  773. * The overlay might have been damaged, erase its magic.
  774. */
  775. fdt_set_magic(fdto, ~0);
  776. /*
  777. * The base device tree might have been damaged, erase its
  778. * magic.
  779. */
  780. fdt_set_magic(fdt, ~0);
  781. return ret;
  782. }