fdt_overlay.c 28 KB

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