blob: 2d12db593bdde1b7c1641ece3a8f9b497e59ff5b [file] [log] [blame]
Andrew Geissler9347dd42023-03-03 12:38:41 -06001From b3762b6c5a56bf594bc5cb63d145e8efd86e106e Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Jaxson Han <jaxson.han@arm.com>
3Date: Tue, 28 Dec 2021 17:02:17 +0800
4Subject: [PATCH] common: Introduce the libfdt
5
6We introduce libfdt (v1.6.1) [1] to boot-wrapper, so we can dynamically
7add the firmware node.
8
9According to [2]: The libfdt is GPL/BSD dual-licensed which means it can
10be used either under the terms of GPL, or under the terms of BSD.
11We choose BSD because the boot-wrapper is under BSD.
12
13[1]: https://github.com/dgibson/dtc/tree/v1.6.1/libfdt
14[2]: https://github.com/dgibson/dtc/blob/v1.6.1/README.license
15
16Issue-Id: SCM-3814
17Upstream-Status: Inappropriate [other]
18 Implementation pending further discussion
19Signed-off-by: Jaxson Han <jaxson.han@arm.com>
20Change-Id: Iec2f469053c8ac0ed38838c597b21a42bdf67b38
21---
22 common/libfdt/README.license | 56 +
23 common/libfdt/fdt.c | 335 +++++
24 common/libfdt/fdt_addresses.c | 101 ++
25 common/libfdt/fdt_check.c | 93 ++
26 common/libfdt/fdt_empty_tree.c | 38 +
27 common/libfdt/fdt_overlay.c | 882 +++++++++++++
28 common/libfdt/fdt_ro.c | 859 +++++++++++++
29 common/libfdt/fdt_rw.c | 500 +++++++
30 common/libfdt/fdt_strerror.c | 59 +
31 common/libfdt/fdt_sw.c | 384 ++++++
32 common/libfdt/fdt_wip.c | 94 ++
33 common/libfdt/libfdt_internal.h | 192 +++
34 include/fdt.h | 66 +
35 include/libfdt.h | 2147 +++++++++++++++++++++++++++++++
36 include/libfdt_env.h | 95 ++
37 15 files changed, 5901 insertions(+)
38 create mode 100644 common/libfdt/README.license
39 create mode 100644 common/libfdt/fdt.c
40 create mode 100644 common/libfdt/fdt_addresses.c
41 create mode 100644 common/libfdt/fdt_check.c
42 create mode 100644 common/libfdt/fdt_empty_tree.c
43 create mode 100644 common/libfdt/fdt_overlay.c
44 create mode 100644 common/libfdt/fdt_ro.c
45 create mode 100644 common/libfdt/fdt_rw.c
46 create mode 100644 common/libfdt/fdt_strerror.c
47 create mode 100644 common/libfdt/fdt_sw.c
48 create mode 100644 common/libfdt/fdt_wip.c
49 create mode 100644 common/libfdt/libfdt_internal.h
50 create mode 100644 include/fdt.h
51 create mode 100644 include/libfdt.h
52 create mode 100644 include/libfdt_env.h
53
54diff --git a/common/libfdt/README.license b/common/libfdt/README.license
55new file mode 100644
56index 0000000..102b004
57--- /dev/null
58+++ b/common/libfdt/README.license
59@@ -0,0 +1,56 @@
60+Licensing and contribution policy of dtc and libfdt
61+===================================================
62+
63+This dtc package contains two pieces of software: dtc itself, and
64+libfdt which comprises the files in the libfdt/ subdirectory. These
65+two pieces of software, although closely related, are quite distinct.
66+dtc does not incorporate or rely on libfdt for its operation, nor vice
67+versa. It is important that these two pieces of software have
68+different license conditions.
69+
70+As SPDX license tags in each source file attest, dtc is licensed
71+under the GNU GPL. The full text of the GPL can be found in the file
72+entitled 'GPL' which should be included in this package. dtc code,
73+therefore, may not be incorporated into works which do not have a GPL
74+compatible license.
75+
76+libfdt, however, is GPL/BSD dual-licensed. That is, it may be used
77+either under the terms of the GPL, or under the terms of the 2-clause
78+BSD license (aka the ISC license). The full terms of that license can
79+be found are in the file entitled 'BSD-2-Clause'. This is, in
80+practice, equivalent to being BSD licensed, since the terms of the BSD
81+license are strictly more permissive than the GPL.
82+
83+I made the decision to license libfdt in this way because I want to
84+encourage widespread and correct usage of flattened device trees,
85+including by proprietary or otherwise GPL-incompatible firmware or
86+tools. Allowing libfdt to be used under the terms of the BSD license
87+makes that it easier for vendors or authors of such software to do so.
88+
89+This does mean that libfdt code could be "stolen" - say, included in a
90+proprietary fimware and extended without contributing those extensions
91+back to the libfdt mainline. While I hope that doesn't happen, I
92+believe the goal of allowing libfdt to be widely used is more
93+important than avoiding that. libfdt is quite small, and hardly
94+rocket science; so the incentive for such impolite behaviour is small,
95+and the inconvenience caused thereby is not dire.
96+
97+Licenses such as the LGPL which would allow code to be used in non-GPL
98+software, but also require contributions to be returned were
99+considered. However, libfdt is designed to be used in firmwares and
100+other environments with unusual technical constraints. It's difficult
101+to anticipate all possible changes which might be needed to meld
102+libfdt into such environments and so difficult to suitably word a
103+license that puts the boundary between what is and isn't permitted in
104+the intended place. Again, I judged encouraging widespread use of
105+libfdt by keeping the license terms simple and familiar to be the more
106+important goal.
107+
108+**IMPORTANT** It's intended that all of libfdt as released remain
109+permissively licensed this way. Therefore only contributions which
110+are released under these terms can be merged into the libfdt mainline.
111+
112+
113+David Gibson <david@gibson.dropbear.id.au>
114+(principal original author of dtc and libfdt)
115+2 November 2007
116diff --git a/common/libfdt/fdt.c b/common/libfdt/fdt.c
117new file mode 100644
118index 0000000..9fe7cf4
119--- /dev/null
120+++ b/common/libfdt/fdt.c
121@@ -0,0 +1,335 @@
122+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
123+/*
124+ * libfdt - Flat Device Tree manipulation
125+ * Copyright (C) 2006 David Gibson, IBM Corporation.
126+ */
127+#include "libfdt_env.h"
128+
129+#include <fdt.h>
130+#include <libfdt.h>
131+
132+#include "libfdt_internal.h"
133+
134+/*
135+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
136+ * that the given buffer contains what appears to be a flattened
137+ * device tree with sane information in its header.
138+ */
139+int32_t fdt_ro_probe_(const void *fdt)
140+{
141+ uint32_t totalsize = fdt_totalsize(fdt);
142+
143+ if (can_assume(VALID_DTB))
144+ return totalsize;
145+
146+ /* The device tree must be at an 8-byte aligned address */
147+ if ((uintptr_t)fdt & 7)
148+ return -FDT_ERR_ALIGNMENT;
149+
150+ if (fdt_magic(fdt) == FDT_MAGIC) {
151+ /* Complete tree */
152+ if (!can_assume(LATEST)) {
153+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
154+ return -FDT_ERR_BADVERSION;
155+ if (fdt_last_comp_version(fdt) >
156+ FDT_LAST_SUPPORTED_VERSION)
157+ return -FDT_ERR_BADVERSION;
158+ }
159+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
160+ /* Unfinished sequential-write blob */
161+ if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
162+ return -FDT_ERR_BADSTATE;
163+ } else {
164+ return -FDT_ERR_BADMAGIC;
165+ }
166+
167+ if (totalsize < INT32_MAX)
168+ return totalsize;
169+ else
170+ return -FDT_ERR_TRUNCATED;
171+}
172+
173+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
174+{
175+ return (off >= hdrsize) && (off <= totalsize);
176+}
177+
178+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
179+ uint32_t base, uint32_t size)
180+{
181+ if (!check_off_(hdrsize, totalsize, base))
182+ return 0; /* block start out of bounds */
183+ if ((base + size) < base)
184+ return 0; /* overflow */
185+ if (!check_off_(hdrsize, totalsize, base + size))
186+ return 0; /* block end out of bounds */
187+ return 1;
188+}
189+
190+size_t fdt_header_size_(uint32_t version)
191+{
192+ if (version <= 1)
193+ return FDT_V1_SIZE;
194+ else if (version <= 2)
195+ return FDT_V2_SIZE;
196+ else if (version <= 3)
197+ return FDT_V3_SIZE;
198+ else if (version <= 16)
199+ return FDT_V16_SIZE;
200+ else
201+ return FDT_V17_SIZE;
202+}
203+
204+size_t fdt_header_size(const void *fdt)
205+{
206+ return can_assume(LATEST) ? FDT_V17_SIZE :
207+ fdt_header_size_(fdt_version(fdt));
208+}
209+
210+int fdt_check_header(const void *fdt)
211+{
212+ size_t hdrsize;
213+
214+ /* The device tree must be at an 8-byte aligned address */
215+ if ((uintptr_t)fdt & 7)
216+ return -FDT_ERR_ALIGNMENT;
217+
218+ if (fdt_magic(fdt) != FDT_MAGIC)
219+ return -FDT_ERR_BADMAGIC;
220+ if (!can_assume(LATEST)) {
221+ if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
222+ || (fdt_last_comp_version(fdt) >
223+ FDT_LAST_SUPPORTED_VERSION))
224+ return -FDT_ERR_BADVERSION;
225+ if (fdt_version(fdt) < fdt_last_comp_version(fdt))
226+ return -FDT_ERR_BADVERSION;
227+ }
228+ hdrsize = fdt_header_size(fdt);
229+ if (!can_assume(VALID_DTB)) {
230+
231+ if ((fdt_totalsize(fdt) < hdrsize)
232+ || (fdt_totalsize(fdt) > INT_MAX))
233+ return -FDT_ERR_TRUNCATED;
234+
235+ /* Bounds check memrsv block */
236+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
237+ fdt_off_mem_rsvmap(fdt)))
238+ return -FDT_ERR_TRUNCATED;
239+ }
240+
241+ if (!can_assume(VALID_DTB)) {
242+ /* Bounds check structure block */
243+ if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
244+ if (!check_off_(hdrsize, fdt_totalsize(fdt),
245+ fdt_off_dt_struct(fdt)))
246+ return -FDT_ERR_TRUNCATED;
247+ } else {
248+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
249+ fdt_off_dt_struct(fdt),
250+ fdt_size_dt_struct(fdt)))
251+ return -FDT_ERR_TRUNCATED;
252+ }
253+
254+ /* Bounds check strings block */
255+ if (!check_block_(hdrsize, fdt_totalsize(fdt),
256+ fdt_off_dt_strings(fdt),
257+ fdt_size_dt_strings(fdt)))
258+ return -FDT_ERR_TRUNCATED;
259+ }
260+
261+ return 0;
262+}
263+
264+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
265+{
266+ unsigned int uoffset = offset;
267+ unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
268+
269+ if (offset < 0)
270+ return NULL;
271+
272+ if (!can_assume(VALID_INPUT))
273+ if ((absoffset < uoffset)
274+ || ((absoffset + len) < absoffset)
275+ || (absoffset + len) > fdt_totalsize(fdt))
276+ return NULL;
277+
278+ if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
279+ if (((uoffset + len) < uoffset)
280+ || ((offset + len) > fdt_size_dt_struct(fdt)))
281+ return NULL;
282+
283+ return fdt_offset_ptr_(fdt, offset);
284+}
285+
286+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
287+{
288+ const fdt32_t *tagp, *lenp;
289+ uint32_t tag;
290+ int offset = startoffset;
291+ const char *p;
292+
293+ *nextoffset = -FDT_ERR_TRUNCATED;
294+ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
295+ if (!can_assume(VALID_DTB) && !tagp)
296+ return FDT_END; /* premature end */
297+ tag = fdt32_to_cpu(*tagp);
298+ offset += FDT_TAGSIZE;
299+
300+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
301+ switch (tag) {
302+ case FDT_BEGIN_NODE:
303+ /* skip name */
304+ do {
305+ p = fdt_offset_ptr(fdt, offset++, 1);
306+ } while (p && (*p != '\0'));
307+ if (!can_assume(VALID_DTB) && !p)
308+ return FDT_END; /* premature end */
309+ break;
310+
311+ case FDT_PROP:
312+ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
313+ if (!can_assume(VALID_DTB) && !lenp)
314+ return FDT_END; /* premature end */
315+ /* skip-name offset, length and value */
316+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
317+ + fdt32_to_cpu(*lenp);
318+ if (!can_assume(LATEST) &&
319+ fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
320+ ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
321+ offset += 4;
322+ break;
323+
324+ case FDT_END:
325+ case FDT_END_NODE:
326+ case FDT_NOP:
327+ break;
328+
329+ default:
330+ return FDT_END;
331+ }
332+
333+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
334+ return FDT_END; /* premature end */
335+
336+ *nextoffset = FDT_TAGALIGN(offset);
337+ return tag;
338+}
339+
340+int fdt_check_node_offset_(const void *fdt, int offset)
341+{
342+ if (!can_assume(VALID_INPUT)
343+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
344+ return -FDT_ERR_BADOFFSET;
345+
346+ if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
347+ return -FDT_ERR_BADOFFSET;
348+
349+ return offset;
350+}
351+
352+int fdt_check_prop_offset_(const void *fdt, int offset)
353+{
354+ if (!can_assume(VALID_INPUT)
355+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
356+ return -FDT_ERR_BADOFFSET;
357+
358+ if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
359+ return -FDT_ERR_BADOFFSET;
360+
361+ return offset;
362+}
363+
364+int fdt_next_node(const void *fdt, int offset, int *depth)
365+{
366+ int nextoffset = 0;
367+ uint32_t tag;
368+
369+ if (offset >= 0)
370+ if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
371+ return nextoffset;
372+
373+ do {
374+ offset = nextoffset;
375+ tag = fdt_next_tag(fdt, offset, &nextoffset);
376+
377+ switch (tag) {
378+ case FDT_PROP:
379+ case FDT_NOP:
380+ break;
381+
382+ case FDT_BEGIN_NODE:
383+ if (depth)
384+ (*depth)++;
385+ break;
386+
387+ case FDT_END_NODE:
388+ if (depth && ((--(*depth)) < 0))
389+ return nextoffset;
390+ break;
391+
392+ case FDT_END:
393+ if ((nextoffset >= 0)
394+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
395+ return -FDT_ERR_NOTFOUND;
396+ else
397+ return nextoffset;
398+ }
399+ } while (tag != FDT_BEGIN_NODE);
400+
401+ return offset;
402+}
403+
404+int fdt_first_subnode(const void *fdt, int offset)
405+{
406+ int depth = 0;
407+
408+ offset = fdt_next_node(fdt, offset, &depth);
409+ if (offset < 0 || depth != 1)
410+ return -FDT_ERR_NOTFOUND;
411+
412+ return offset;
413+}
414+
415+int fdt_next_subnode(const void *fdt, int offset)
416+{
417+ int depth = 1;
418+
419+ /*
420+ * With respect to the parent, the depth of the next subnode will be
421+ * the same as the last.
422+ */
423+ do {
424+ offset = fdt_next_node(fdt, offset, &depth);
425+ if (offset < 0 || depth < 1)
426+ return -FDT_ERR_NOTFOUND;
427+ } while (depth > 1);
428+
429+ return offset;
430+}
431+
432+const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
433+{
434+ int len = strlen(s) + 1;
435+ const char *last = strtab + tabsize - len;
436+ const char *p;
437+
438+ for (p = strtab; p <= last; p++)
439+ if (memcmp(p, s, len) == 0)
440+ return p;
441+ return NULL;
442+}
443+
444+int fdt_move(const void *fdt, void *buf, int bufsize)
445+{
446+ if (!can_assume(VALID_INPUT) && bufsize < 0)
447+ return -FDT_ERR_NOSPACE;
448+
449+ FDT_RO_PROBE(fdt);
450+
451+ if (fdt_totalsize(fdt) > (unsigned int)bufsize)
452+ return -FDT_ERR_NOSPACE;
453+
454+ memmove(buf, fdt, fdt_totalsize(fdt));
455+ return 0;
456+}
457diff --git a/common/libfdt/fdt_addresses.c b/common/libfdt/fdt_addresses.c
458new file mode 100644
459index 0000000..9a82cd0
460--- /dev/null
461+++ b/common/libfdt/fdt_addresses.c
462@@ -0,0 +1,101 @@
463+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
464+/*
465+ * libfdt - Flat Device Tree manipulation
466+ * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
467+ * Copyright (C) 2018 embedded brains GmbH
468+ */
469+#include "libfdt_env.h"
470+
471+#include <fdt.h>
472+#include <libfdt.h>
473+
474+#include "libfdt_internal.h"
475+
476+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
477+{
478+ const fdt32_t *c;
479+ uint32_t val;
480+ int len;
481+
482+ c = fdt_getprop(fdt, nodeoffset, name, &len);
483+ if (!c)
484+ return len;
485+
486+ if (len != sizeof(*c))
487+ return -FDT_ERR_BADNCELLS;
488+
489+ val = fdt32_to_cpu(*c);
490+ if (val > FDT_MAX_NCELLS)
491+ return -FDT_ERR_BADNCELLS;
492+
493+ return (int)val;
494+}
495+
496+int fdt_address_cells(const void *fdt, int nodeoffset)
497+{
498+ int val;
499+
500+ val = fdt_cells(fdt, nodeoffset, "#address-cells");
501+ if (val == 0)
502+ return -FDT_ERR_BADNCELLS;
503+ if (val == -FDT_ERR_NOTFOUND)
504+ return 2;
505+ return val;
506+}
507+
508+int fdt_size_cells(const void *fdt, int nodeoffset)
509+{
510+ int val;
511+
512+ val = fdt_cells(fdt, nodeoffset, "#size-cells");
513+ if (val == -FDT_ERR_NOTFOUND)
514+ return 1;
515+ return val;
516+}
517+
518+/* This function assumes that [address|size]_cells is 1 or 2 */
519+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
520+ const char *name, uint64_t addr, uint64_t size)
521+{
522+ int addr_cells, size_cells, ret;
523+ uint8_t data[sizeof(fdt64_t) * 2], *prop;
524+
525+ ret = fdt_address_cells(fdt, parent);
526+ if (ret < 0)
527+ return ret;
528+ addr_cells = ret;
529+
530+ ret = fdt_size_cells(fdt, parent);
531+ if (ret < 0)
532+ return ret;
533+ size_cells = ret;
534+
535+ /* check validity of address */
536+ prop = data;
537+ if (addr_cells == 1) {
538+ if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
539+ return -FDT_ERR_BADVALUE;
540+
541+ fdt32_st(prop, (uint32_t)addr);
542+ } else if (addr_cells == 2) {
543+ fdt64_st(prop, addr);
544+ } else {
545+ return -FDT_ERR_BADNCELLS;
546+ }
547+
548+ /* check validity of size */
549+ prop += addr_cells * sizeof(fdt32_t);
550+ if (size_cells == 1) {
551+ if (size > UINT32_MAX)
552+ return -FDT_ERR_BADVALUE;
553+
554+ fdt32_st(prop, (uint32_t)size);
555+ } else if (size_cells == 2) {
556+ fdt64_st(prop, size);
557+ } else {
558+ return -FDT_ERR_BADNCELLS;
559+ }
560+
561+ return fdt_appendprop(fdt, nodeoffset, name, data,
562+ (addr_cells + size_cells) * sizeof(fdt32_t));
563+}
564diff --git a/common/libfdt/fdt_check.c b/common/libfdt/fdt_check.c
565new file mode 100644
566index 0000000..fa410a8
567--- /dev/null
568+++ b/common/libfdt/fdt_check.c
569@@ -0,0 +1,93 @@
570+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
571+/*
572+ * libfdt - Flat Device Tree manipulation
573+ * Copyright (C) 2006 David Gibson, IBM Corporation.
574+ */
575+#include "libfdt_env.h"
576+
577+#include <fdt.h>
578+#include <libfdt.h>
579+
580+#include "libfdt_internal.h"
581+
582+int fdt_check_full(const void *fdt, size_t bufsize)
583+{
584+ int err;
585+ int num_memrsv;
586+ int offset, nextoffset = 0;
587+ uint32_t tag;
588+ unsigned int depth = 0;
589+ const void *prop;
590+ const char *propname;
591+ bool expect_end = false;
592+
593+ if (bufsize < FDT_V1_SIZE)
594+ return -FDT_ERR_TRUNCATED;
595+ if (bufsize < fdt_header_size(fdt))
596+ return -FDT_ERR_TRUNCATED;
597+ err = fdt_check_header(fdt);
598+ if (err != 0)
599+ return err;
600+ if (bufsize < fdt_totalsize(fdt))
601+ return -FDT_ERR_TRUNCATED;
602+
603+ num_memrsv = fdt_num_mem_rsv(fdt);
604+ if (num_memrsv < 0)
605+ return num_memrsv;
606+
607+ while (1) {
608+ offset = nextoffset;
609+ tag = fdt_next_tag(fdt, offset, &nextoffset);
610+
611+ if (nextoffset < 0)
612+ return nextoffset;
613+
614+ /* If we see two root nodes, something is wrong */
615+ if (expect_end && tag != FDT_END)
616+ return -FDT_ERR_BADSTRUCTURE;
617+
618+ switch (tag) {
619+ case FDT_NOP:
620+ break;
621+
622+ case FDT_END:
623+ if (depth != 0)
624+ return -FDT_ERR_BADSTRUCTURE;
625+ return 0;
626+
627+ case FDT_BEGIN_NODE:
628+ depth++;
629+ if (depth > INT_MAX)
630+ return -FDT_ERR_BADSTRUCTURE;
631+
632+ /* The root node must have an empty name */
633+ if (depth == 1) {
634+ const char *name;
635+ int len;
636+
637+ name = fdt_get_name(fdt, offset, &len);
638+ if (*name || len)
639+ return -FDT_ERR_BADSTRUCTURE;
640+ }
641+ break;
642+
643+ case FDT_END_NODE:
644+ if (depth == 0)
645+ return -FDT_ERR_BADSTRUCTURE;
646+ depth--;
647+ if (depth == 0)
648+ expect_end = true;
649+ break;
650+
651+ case FDT_PROP:
652+ prop = fdt_getprop_by_offset(fdt, offset, &propname,
653+ &err);
654+ if (!prop)
655+ return err;
656+ break;
657+
658+ default:
659+ return -FDT_ERR_INTERNAL;
660+ }
661+ }
662+}
663diff --git a/common/libfdt/fdt_empty_tree.c b/common/libfdt/fdt_empty_tree.c
664new file mode 100644
665index 0000000..49d54d4
666--- /dev/null
667+++ b/common/libfdt/fdt_empty_tree.c
668@@ -0,0 +1,38 @@
669+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
670+/*
671+ * libfdt - Flat Device Tree manipulation
672+ * Copyright (C) 2012 David Gibson, IBM Corporation.
673+ */
674+#include "libfdt_env.h"
675+
676+#include <fdt.h>
677+#include <libfdt.h>
678+
679+#include "libfdt_internal.h"
680+
681+int fdt_create_empty_tree(void *buf, int bufsize)
682+{
683+ int err;
684+
685+ err = fdt_create(buf, bufsize);
686+ if (err)
687+ return err;
688+
689+ err = fdt_finish_reservemap(buf);
690+ if (err)
691+ return err;
692+
693+ err = fdt_begin_node(buf, "");
694+ if (err)
695+ return err;
696+
697+ err = fdt_end_node(buf);
698+ if (err)
699+ return err;
700+
701+ err = fdt_finish(buf);
702+ if (err)
703+ return err;
704+
705+ return fdt_open_into(buf, buf, bufsize);
706+}
707diff --git a/common/libfdt/fdt_overlay.c b/common/libfdt/fdt_overlay.c
708new file mode 100644
709index 0000000..d217e79
710--- /dev/null
711+++ b/common/libfdt/fdt_overlay.c
712@@ -0,0 +1,882 @@
713+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
714+/*
715+ * libfdt - Flat Device Tree manipulation
716+ * Copyright (C) 2016 Free Electrons
717+ * Copyright (C) 2016 NextThing Co.
718+ */
719+#include "libfdt_env.h"
720+
721+#include <fdt.h>
722+#include <libfdt.h>
723+
724+#include "libfdt_internal.h"
725+
726+/**
727+ * overlay_get_target_phandle - retrieves the target phandle of a fragment
728+ * @fdto: pointer to the device tree overlay blob
729+ * @fragment: node offset of the fragment in the overlay
730+ *
731+ * overlay_get_target_phandle() retrieves the target phandle of an
732+ * overlay fragment when that fragment uses a phandle (target
733+ * property) instead of a path (target-path property).
734+ *
735+ * returns:
736+ * the phandle pointed by the target property
737+ * 0, if the phandle was not found
738+ * -1, if the phandle was malformed
739+ */
740+static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
741+{
742+ const fdt32_t *val;
743+ int len;
744+
745+ val = fdt_getprop(fdto, fragment, "target", &len);
746+ if (!val)
747+ return 0;
748+
749+ if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
750+ return (uint32_t)-1;
751+
752+ return fdt32_to_cpu(*val);
753+}
754+
755+/**
756+ * overlay_get_target - retrieves the offset of a fragment's target
757+ * @fdt: Base device tree blob
758+ * @fdto: Device tree overlay blob
759+ * @fragment: node offset of the fragment in the overlay
760+ * @pathp: pointer which receives the path of the target (or NULL)
761+ *
762+ * overlay_get_target() retrieves the target offset in the base
763+ * device tree of a fragment, no matter how the actual targeting is
764+ * done (through a phandle or a path)
765+ *
766+ * returns:
767+ * the targeted node offset in the base device tree
768+ * Negative error code on error
769+ */
770+static int overlay_get_target(const void *fdt, const void *fdto,
771+ int fragment, char const **pathp)
772+{
773+ uint32_t phandle;
774+ const char *path = NULL;
775+ int path_len = 0, ret;
776+
777+ /* Try first to do a phandle based lookup */
778+ phandle = overlay_get_target_phandle(fdto, fragment);
779+ if (phandle == (uint32_t)-1)
780+ return -FDT_ERR_BADPHANDLE;
781+
782+ /* no phandle, try path */
783+ if (!phandle) {
784+ /* And then a path based lookup */
785+ path = fdt_getprop(fdto, fragment, "target-path", &path_len);
786+ if (path)
787+ ret = fdt_path_offset(fdt, path);
788+ else
789+ ret = path_len;
790+ } else
791+ ret = fdt_node_offset_by_phandle(fdt, phandle);
792+
793+ /*
794+ * If we haven't found either a target or a
795+ * target-path property in a node that contains a
796+ * __overlay__ subnode (we wouldn't be called
797+ * otherwise), consider it a improperly written
798+ * overlay
799+ */
800+ if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
801+ ret = -FDT_ERR_BADOVERLAY;
802+
803+ /* return on error */
804+ if (ret < 0)
805+ return ret;
806+
807+ /* return pointer to path (if available) */
808+ if (pathp)
809+ *pathp = path ? path : NULL;
810+
811+ return ret;
812+}
813+
814+/**
815+ * overlay_phandle_add_offset - Increases a phandle by an offset
816+ * @fdt: Base device tree blob
817+ * @node: Device tree overlay blob
818+ * @name: Name of the property to modify (phandle or linux,phandle)
819+ * @delta: offset to apply
820+ *
821+ * overlay_phandle_add_offset() increments a node phandle by a given
822+ * offset.
823+ *
824+ * returns:
825+ * 0 on success.
826+ * Negative error code on error
827+ */
828+static int overlay_phandle_add_offset(void *fdt, int node,
829+ const char *name, uint32_t delta)
830+{
831+ const fdt32_t *val;
832+ uint32_t adj_val;
833+ int len;
834+
835+ val = fdt_getprop(fdt, node, name, &len);
836+ if (!val)
837+ return len;
838+
839+ if (len != sizeof(*val))
840+ return -FDT_ERR_BADPHANDLE;
841+
842+ adj_val = fdt32_to_cpu(*val);
843+ if ((adj_val + delta) < adj_val)
844+ return -FDT_ERR_NOPHANDLES;
845+
846+ adj_val += delta;
847+ if (adj_val == (uint32_t)-1)
848+ return -FDT_ERR_NOPHANDLES;
849+
850+ return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
851+}
852+
853+/**
854+ * overlay_adjust_node_phandles - Offsets the phandles of a node
855+ * @fdto: Device tree overlay blob
856+ * @node: Offset of the node we want to adjust
857+ * @delta: Offset to shift the phandles of
858+ *
859+ * overlay_adjust_node_phandles() adds a constant to all the phandles
860+ * of a given node. This is mainly use as part of the overlay
861+ * application process, when we want to update all the overlay
862+ * phandles to not conflict with the overlays of the base device tree.
863+ *
864+ * returns:
865+ * 0 on success
866+ * Negative error code on failure
867+ */
868+static int overlay_adjust_node_phandles(void *fdto, int node,
869+ uint32_t delta)
870+{
871+ int child;
872+ int ret;
873+
874+ ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
875+ if (ret && ret != -FDT_ERR_NOTFOUND)
876+ return ret;
877+
878+ ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
879+ if (ret && ret != -FDT_ERR_NOTFOUND)
880+ return ret;
881+
882+ fdt_for_each_subnode(child, fdto, node) {
883+ ret = overlay_adjust_node_phandles(fdto, child, delta);
884+ if (ret)
885+ return ret;
886+ }
887+
888+ return 0;
889+}
890+
891+/**
892+ * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
893+ * @fdto: Device tree overlay blob
894+ * @delta: Offset to shift the phandles of
895+ *
896+ * overlay_adjust_local_phandles() adds a constant to all the
897+ * phandles of an overlay. This is mainly use as part of the overlay
898+ * application process, when we want to update all the overlay
899+ * phandles to not conflict with the overlays of the base device tree.
900+ *
901+ * returns:
902+ * 0 on success
903+ * Negative error code on failure
904+ */
905+static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
906+{
907+ /*
908+ * Start adjusting the phandles from the overlay root
909+ */
910+ return overlay_adjust_node_phandles(fdto, 0, delta);
911+}
912+
913+/**
914+ * overlay_update_local_node_references - Adjust the overlay references
915+ * @fdto: Device tree overlay blob
916+ * @tree_node: Node offset of the node to operate on
917+ * @fixup_node: Node offset of the matching local fixups node
918+ * @delta: Offset to shift the phandles of
919+ *
920+ * overlay_update_local_nodes_references() update the phandles
921+ * pointing to a node within the device tree overlay by adding a
922+ * constant delta.
923+ *
924+ * This is mainly used as part of a device tree application process,
925+ * where you want the device tree overlays phandles to not conflict
926+ * with the ones from the base device tree before merging them.
927+ *
928+ * returns:
929+ * 0 on success
930+ * Negative error code on failure
931+ */
932+static int overlay_update_local_node_references(void *fdto,
933+ int tree_node,
934+ int fixup_node,
935+ uint32_t delta)
936+{
937+ int fixup_prop;
938+ int fixup_child;
939+ int ret;
940+
941+ fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
942+ const fdt32_t *fixup_val;
943+ const char *tree_val;
944+ const char *name;
945+ int fixup_len;
946+ int tree_len;
947+ int i;
948+
949+ fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
950+ &name, &fixup_len);
951+ if (!fixup_val)
952+ return fixup_len;
953+
954+ if (fixup_len % sizeof(uint32_t))
955+ return -FDT_ERR_BADOVERLAY;
956+ fixup_len /= sizeof(uint32_t);
957+
958+ tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
959+ if (!tree_val) {
960+ if (tree_len == -FDT_ERR_NOTFOUND)
961+ return -FDT_ERR_BADOVERLAY;
962+
963+ return tree_len;
964+ }
965+
966+ for (i = 0; i < fixup_len; i++) {
967+ fdt32_t adj_val;
968+ uint32_t poffset;
969+
970+ poffset = fdt32_to_cpu(fixup_val[i]);
971+
972+ /*
973+ * phandles to fixup can be unaligned.
974+ *
975+ * Use a memcpy for the architectures that do
976+ * not support unaligned accesses.
977+ */
978+ memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
979+
980+ adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
981+
982+ ret = fdt_setprop_inplace_namelen_partial(fdto,
983+ tree_node,
984+ name,
985+ strlen(name),
986+ poffset,
987+ &adj_val,
988+ sizeof(adj_val));
989+ if (ret == -FDT_ERR_NOSPACE)
990+ return -FDT_ERR_BADOVERLAY;
991+
992+ if (ret)
993+ return ret;
994+ }
995+ }
996+
997+ fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
998+ const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
999+ NULL);
1000+ int tree_child;
1001+
1002+ tree_child = fdt_subnode_offset(fdto, tree_node,
1003+ fixup_child_name);
1004+ if (tree_child == -FDT_ERR_NOTFOUND)
1005+ return -FDT_ERR_BADOVERLAY;
1006+ if (tree_child < 0)
1007+ return tree_child;
1008+
1009+ ret = overlay_update_local_node_references(fdto,
1010+ tree_child,
1011+ fixup_child,
1012+ delta);
1013+ if (ret)
1014+ return ret;
1015+ }
1016+
1017+ return 0;
1018+}
1019+
1020+/**
1021+ * overlay_update_local_references - Adjust the overlay references
1022+ * @fdto: Device tree overlay blob
1023+ * @delta: Offset to shift the phandles of
1024+ *
1025+ * overlay_update_local_references() update all the phandles pointing
1026+ * to a node within the device tree overlay by adding a constant
1027+ * delta to not conflict with the base overlay.
1028+ *
1029+ * This is mainly used as part of a device tree application process,
1030+ * where you want the device tree overlays phandles to not conflict
1031+ * with the ones from the base device tree before merging them.
1032+ *
1033+ * returns:
1034+ * 0 on success
1035+ * Negative error code on failure
1036+ */
1037+static int overlay_update_local_references(void *fdto, uint32_t delta)
1038+{
1039+ int fixups;
1040+
1041+ fixups = fdt_path_offset(fdto, "/__local_fixups__");
1042+ if (fixups < 0) {
1043+ /* There's no local phandles to adjust, bail out */
1044+ if (fixups == -FDT_ERR_NOTFOUND)
1045+ return 0;
1046+
1047+ return fixups;
1048+ }
1049+
1050+ /*
1051+ * Update our local references from the root of the tree
1052+ */
1053+ return overlay_update_local_node_references(fdto, 0, fixups,
1054+ delta);
1055+}
1056+
1057+/**
1058+ * overlay_fixup_one_phandle - Set an overlay phandle to the base one
1059+ * @fdt: Base Device Tree blob
1060+ * @fdto: Device tree overlay blob
1061+ * @symbols_off: Node offset of the symbols node in the base device tree
1062+ * @path: Path to a node holding a phandle in the overlay
1063+ * @path_len: number of path characters to consider
1064+ * @name: Name of the property holding the phandle reference in the overlay
1065+ * @name_len: number of name characters to consider
1066+ * @poffset: Offset within the overlay property where the phandle is stored
1067+ * @label: Label of the node referenced by the phandle
1068+ *
1069+ * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
1070+ * a node in the base device tree.
1071+ *
1072+ * This is part of the device tree overlay application process, when
1073+ * you want all the phandles in the overlay to point to the actual
1074+ * base dt nodes.
1075+ *
1076+ * returns:
1077+ * 0 on success
1078+ * Negative error code on failure
1079+ */
1080+static int overlay_fixup_one_phandle(void *fdt, void *fdto,
1081+ int symbols_off,
1082+ const char *path, uint32_t path_len,
1083+ const char *name, uint32_t name_len,
1084+ int poffset, const char *label)
1085+{
1086+ const char *symbol_path;
1087+ uint32_t phandle;
1088+ fdt32_t phandle_prop;
1089+ int symbol_off, fixup_off;
1090+ int prop_len;
1091+
1092+ if (symbols_off < 0)
1093+ return symbols_off;
1094+
1095+ symbol_path = fdt_getprop(fdt, symbols_off, label,
1096+ &prop_len);
1097+ if (!symbol_path)
1098+ return prop_len;
1099+
1100+ symbol_off = fdt_path_offset(fdt, symbol_path);
1101+ if (symbol_off < 0)
1102+ return symbol_off;
1103+
1104+ phandle = fdt_get_phandle(fdt, symbol_off);
1105+ if (!phandle)
1106+ return -FDT_ERR_NOTFOUND;
1107+
1108+ fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
1109+ if (fixup_off == -FDT_ERR_NOTFOUND)
1110+ return -FDT_ERR_BADOVERLAY;
1111+ if (fixup_off < 0)
1112+ return fixup_off;
1113+
1114+ phandle_prop = cpu_to_fdt32(phandle);
1115+ return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
1116+ name, name_len, poffset,
1117+ &phandle_prop,
1118+ sizeof(phandle_prop));
1119+};
1120+
1121+/**
1122+ * overlay_fixup_phandle - Set an overlay phandle to the base one
1123+ * @fdt: Base Device Tree blob
1124+ * @fdto: Device tree overlay blob
1125+ * @symbols_off: Node offset of the symbols node in the base device tree
1126+ * @property: Property offset in the overlay holding the list of fixups
1127+ *
1128+ * overlay_fixup_phandle() resolves all the overlay phandles pointed
1129+ * to in a __fixups__ property, and updates them to match the phandles
1130+ * in use in the base device tree.
1131+ *
1132+ * This is part of the device tree overlay application process, when
1133+ * you want all the phandles in the overlay to point to the actual
1134+ * base dt nodes.
1135+ *
1136+ * returns:
1137+ * 0 on success
1138+ * Negative error code on failure
1139+ */
1140+static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
1141+ int property)
1142+{
1143+ const char *value;
1144+ const char *label;
1145+ int len;
1146+
1147+ value = fdt_getprop_by_offset(fdto, property,
1148+ &label, &len);
1149+ if (!value) {
1150+ if (len == -FDT_ERR_NOTFOUND)
1151+ return -FDT_ERR_INTERNAL;
1152+
1153+ return len;
1154+ }
1155+
1156+ do {
1157+ const char *path, *name, *fixup_end;
1158+ const char *fixup_str = value;
1159+ uint32_t path_len, name_len;
1160+ uint32_t fixup_len;
1161+ char *sep, *endptr;
1162+ int poffset, ret;
1163+
1164+ fixup_end = memchr(value, '\0', len);
1165+ if (!fixup_end)
1166+ return -FDT_ERR_BADOVERLAY;
1167+ fixup_len = fixup_end - fixup_str;
1168+
1169+ len -= fixup_len + 1;
1170+ value += fixup_len + 1;
1171+
1172+ path = fixup_str;
1173+ sep = memchr(fixup_str, ':', fixup_len);
1174+ if (!sep || *sep != ':')
1175+ return -FDT_ERR_BADOVERLAY;
1176+
1177+ path_len = sep - path;
1178+ if (path_len == (fixup_len - 1))
1179+ return -FDT_ERR_BADOVERLAY;
1180+
1181+ fixup_len -= path_len + 1;
1182+ name = sep + 1;
1183+ sep = memchr(name, ':', fixup_len);
1184+ if (!sep || *sep != ':')
1185+ return -FDT_ERR_BADOVERLAY;
1186+
1187+ name_len = sep - name;
1188+ if (!name_len)
1189+ return -FDT_ERR_BADOVERLAY;
1190+
1191+ poffset = strtoul(sep + 1, &endptr, 10);
1192+ if ((*endptr != '\0') || (endptr <= (sep + 1)))
1193+ return -FDT_ERR_BADOVERLAY;
1194+
1195+ ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
1196+ path, path_len, name, name_len,
1197+ poffset, label);
1198+ if (ret)
1199+ return ret;
1200+ } while (len > 0);
1201+
1202+ return 0;
1203+}
1204+
1205+/**
1206+ * overlay_fixup_phandles - Resolve the overlay phandles to the base
1207+ * device tree
1208+ * @fdt: Base Device Tree blob
1209+ * @fdto: Device tree overlay blob
1210+ *
1211+ * overlay_fixup_phandles() resolves all the overlay phandles pointing
1212+ * to nodes in the base device tree.
1213+ *
1214+ * This is one of the steps of the device tree overlay application
1215+ * process, when you want all the phandles in the overlay to point to
1216+ * the actual base dt nodes.
1217+ *
1218+ * returns:
1219+ * 0 on success
1220+ * Negative error code on failure
1221+ */
1222+static int overlay_fixup_phandles(void *fdt, void *fdto)
1223+{
1224+ int fixups_off, symbols_off;
1225+ int property;
1226+
1227+ /* We can have overlays without any fixups */
1228+ fixups_off = fdt_path_offset(fdto, "/__fixups__");
1229+ if (fixups_off == -FDT_ERR_NOTFOUND)
1230+ return 0; /* nothing to do */
1231+ if (fixups_off < 0)
1232+ return fixups_off;
1233+
1234+ /* And base DTs without symbols */
1235+ symbols_off = fdt_path_offset(fdt, "/__symbols__");
1236+ if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
1237+ return symbols_off;
1238+
1239+ fdt_for_each_property_offset(property, fdto, fixups_off) {
1240+ int ret;
1241+
1242+ ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
1243+ if (ret)
1244+ return ret;
1245+ }
1246+
1247+ return 0;
1248+}
1249+
1250+/**
1251+ * overlay_apply_node - Merges a node into the base device tree
1252+ * @fdt: Base Device Tree blob
1253+ * @target: Node offset in the base device tree to apply the fragment to
1254+ * @fdto: Device tree overlay blob
1255+ * @node: Node offset in the overlay holding the changes to merge
1256+ *
1257+ * overlay_apply_node() merges a node into a target base device tree
1258+ * node pointed.
1259+ *
1260+ * This is part of the final step in the device tree overlay
1261+ * application process, when all the phandles have been adjusted and
1262+ * resolved and you just have to merge overlay into the base device
1263+ * tree.
1264+ *
1265+ * returns:
1266+ * 0 on success
1267+ * Negative error code on failure
1268+ */
1269+static int overlay_apply_node(void *fdt, int target,
1270+ void *fdto, int node)
1271+{
1272+ int property;
1273+ int subnode;
1274+
1275+ fdt_for_each_property_offset(property, fdto, node) {
1276+ const char *name;
1277+ const void *prop;
1278+ int prop_len;
1279+ int ret;
1280+
1281+ prop = fdt_getprop_by_offset(fdto, property, &name,
1282+ &prop_len);
1283+ if (prop_len == -FDT_ERR_NOTFOUND)
1284+ return -FDT_ERR_INTERNAL;
1285+ if (prop_len < 0)
1286+ return prop_len;
1287+
1288+ ret = fdt_setprop(fdt, target, name, prop, prop_len);
1289+ if (ret)
1290+ return ret;
1291+ }
1292+
1293+ fdt_for_each_subnode(subnode, fdto, node) {
1294+ const char *name = fdt_get_name(fdto, subnode, NULL);
1295+ int nnode;
1296+ int ret;
1297+
1298+ nnode = fdt_add_subnode(fdt, target, name);
1299+ if (nnode == -FDT_ERR_EXISTS) {
1300+ nnode = fdt_subnode_offset(fdt, target, name);
1301+ if (nnode == -FDT_ERR_NOTFOUND)
1302+ return -FDT_ERR_INTERNAL;
1303+ }
1304+
1305+ if (nnode < 0)
1306+ return nnode;
1307+
1308+ ret = overlay_apply_node(fdt, nnode, fdto, subnode);
1309+ if (ret)
1310+ return ret;
1311+ }
1312+
1313+ return 0;
1314+}
1315+
1316+/**
1317+ * overlay_merge - Merge an overlay into its base device tree
1318+ * @fdt: Base Device Tree blob
1319+ * @fdto: Device tree overlay blob
1320+ *
1321+ * overlay_merge() merges an overlay into its base device tree.
1322+ *
1323+ * This is the next to last step in the device tree overlay application
1324+ * process, when all the phandles have been adjusted and resolved and
1325+ * you just have to merge overlay into the base device tree.
1326+ *
1327+ * returns:
1328+ * 0 on success
1329+ * Negative error code on failure
1330+ */
1331+static int overlay_merge(void *fdt, void *fdto)
1332+{
1333+ int fragment;
1334+
1335+ fdt_for_each_subnode(fragment, fdto, 0) {
1336+ int overlay;
1337+ int target;
1338+ int ret;
1339+
1340+ /*
1341+ * Each fragments will have an __overlay__ node. If
1342+ * they don't, it's not supposed to be merged
1343+ */
1344+ overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
1345+ if (overlay == -FDT_ERR_NOTFOUND)
1346+ continue;
1347+
1348+ if (overlay < 0)
1349+ return overlay;
1350+
1351+ target = overlay_get_target(fdt, fdto, fragment, NULL);
1352+ if (target < 0)
1353+ return target;
1354+
1355+ ret = overlay_apply_node(fdt, target, fdto, overlay);
1356+ if (ret)
1357+ return ret;
1358+ }
1359+
1360+ return 0;
1361+}
1362+
1363+static int get_path_len(const void *fdt, int nodeoffset)
1364+{
1365+ int len = 0, namelen;
1366+ const char *name;
1367+
1368+ FDT_RO_PROBE(fdt);
1369+
1370+ for (;;) {
1371+ name = fdt_get_name(fdt, nodeoffset, &namelen);
1372+ if (!name)
1373+ return namelen;
1374+
1375+ /* root? we're done */
1376+ if (namelen == 0)
1377+ break;
1378+
1379+ nodeoffset = fdt_parent_offset(fdt, nodeoffset);
1380+ if (nodeoffset < 0)
1381+ return nodeoffset;
1382+ len += namelen + 1;
1383+ }
1384+
1385+ /* in case of root pretend it's "/" */
1386+ if (len == 0)
1387+ len++;
1388+ return len;
1389+}
1390+
1391+/**
1392+ * overlay_symbol_update - Update the symbols of base tree after a merge
1393+ * @fdt: Base Device Tree blob
1394+ * @fdto: Device tree overlay blob
1395+ *
1396+ * overlay_symbol_update() updates the symbols of the base tree with the
1397+ * symbols of the applied overlay
1398+ *
1399+ * This is the last step in the device tree overlay application
1400+ * process, allowing the reference of overlay symbols by subsequent
1401+ * overlay operations.
1402+ *
1403+ * returns:
1404+ * 0 on success
1405+ * Negative error code on failure
1406+ */
1407+static int overlay_symbol_update(void *fdt, void *fdto)
1408+{
1409+ int root_sym, ov_sym, prop, path_len, fragment, target;
1410+ int len, frag_name_len, ret, rel_path_len;
1411+ const char *s, *e;
1412+ const char *path;
1413+ const char *name;
1414+ const char *frag_name;
1415+ const char *rel_path;
1416+ const char *target_path;
1417+ char *buf;
1418+ void *p;
1419+
1420+ ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
1421+
1422+ /* if no overlay symbols exist no problem */
1423+ if (ov_sym < 0)
1424+ return 0;
1425+
1426+ root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
1427+
1428+ /* it no root symbols exist we should create them */
1429+ if (root_sym == -FDT_ERR_NOTFOUND)
1430+ root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
1431+
1432+ /* any error is fatal now */
1433+ if (root_sym < 0)
1434+ return root_sym;
1435+
1436+ /* iterate over each overlay symbol */
1437+ fdt_for_each_property_offset(prop, fdto, ov_sym) {
1438+ path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
1439+ if (!path)
1440+ return path_len;
1441+
1442+ /* verify it's a string property (terminated by a single \0) */
1443+ if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
1444+ return -FDT_ERR_BADVALUE;
1445+
1446+ /* keep end marker to avoid strlen() */
1447+ e = path + path_len;
1448+
1449+ if (*path != '/')
1450+ return -FDT_ERR_BADVALUE;
1451+
1452+ /* get fragment name first */
1453+ s = strchr(path + 1, '/');
1454+ if (!s) {
1455+ /* Symbol refers to something that won't end
1456+ * up in the target tree */
1457+ continue;
1458+ }
1459+
1460+ frag_name = path + 1;
1461+ frag_name_len = s - path - 1;
1462+
1463+ /* verify format; safe since "s" lies in \0 terminated prop */
1464+ len = sizeof("/__overlay__/") - 1;
1465+ if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
1466+ /* /<fragment-name>/__overlay__/<relative-subnode-path> */
1467+ rel_path = s + len;
1468+ rel_path_len = e - rel_path - 1;
1469+ } else if ((e - s) == len
1470+ && (memcmp(s, "/__overlay__", len - 1) == 0)) {
1471+ /* /<fragment-name>/__overlay__ */
1472+ rel_path = "";
1473+ rel_path_len = 0;
1474+ } else {
1475+ /* Symbol refers to something that won't end
1476+ * up in the target tree */
1477+ continue;
1478+ }
1479+
1480+ /* find the fragment index in which the symbol lies */
1481+ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
1482+ frag_name_len);
1483+ /* not found? */
1484+ if (ret < 0)
1485+ return -FDT_ERR_BADOVERLAY;
1486+ fragment = ret;
1487+
1488+ /* an __overlay__ subnode must exist */
1489+ ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
1490+ if (ret < 0)
1491+ return -FDT_ERR_BADOVERLAY;
1492+
1493+ /* get the target of the fragment */
1494+ ret = overlay_get_target(fdt, fdto, fragment, &target_path);
1495+ if (ret < 0)
1496+ return ret;
1497+ target = ret;
1498+
1499+ /* if we have a target path use */
1500+ if (!target_path) {
1501+ ret = get_path_len(fdt, target);
1502+ if (ret < 0)
1503+ return ret;
1504+ len = ret;
1505+ } else {
1506+ len = strlen(target_path);
1507+ }
1508+
1509+ ret = fdt_setprop_placeholder(fdt, root_sym, name,
1510+ len + (len > 1) + rel_path_len + 1, &p);
1511+ if (ret < 0)
1512+ return ret;
1513+
1514+ if (!target_path) {
1515+ /* again in case setprop_placeholder changed it */
1516+ ret = overlay_get_target(fdt, fdto, fragment, &target_path);
1517+ if (ret < 0)
1518+ return ret;
1519+ target = ret;
1520+ }
1521+
1522+ buf = p;
1523+ if (len > 1) { /* target is not root */
1524+ if (!target_path) {
1525+ ret = fdt_get_path(fdt, target, buf, len + 1);
1526+ if (ret < 0)
1527+ return ret;
1528+ } else
1529+ memcpy(buf, target_path, len + 1);
1530+
1531+ } else
1532+ len--;
1533+
1534+ buf[len] = '/';
1535+ memcpy(buf + len + 1, rel_path, rel_path_len);
1536+ buf[len + 1 + rel_path_len] = '\0';
1537+ }
1538+
1539+ return 0;
1540+}
1541+
1542+int fdt_overlay_apply(void *fdt, void *fdto)
1543+{
1544+ uint32_t delta;
1545+ int ret;
1546+
1547+ FDT_RO_PROBE(fdt);
1548+ FDT_RO_PROBE(fdto);
1549+
1550+ ret = fdt_find_max_phandle(fdt, &delta);
1551+ if (ret)
1552+ goto err;
1553+
1554+ ret = overlay_adjust_local_phandles(fdto, delta);
1555+ if (ret)
1556+ goto err;
1557+
1558+ ret = overlay_update_local_references(fdto, delta);
1559+ if (ret)
1560+ goto err;
1561+
1562+ ret = overlay_fixup_phandles(fdt, fdto);
1563+ if (ret)
1564+ goto err;
1565+
1566+ ret = overlay_merge(fdt, fdto);
1567+ if (ret)
1568+ goto err;
1569+
1570+ ret = overlay_symbol_update(fdt, fdto);
1571+ if (ret)
1572+ goto err;
1573+
1574+ /*
1575+ * The overlay has been damaged, erase its magic.
1576+ */
1577+ fdt_set_magic(fdto, ~0);
1578+
1579+ return 0;
1580+
1581+err:
1582+ /*
1583+ * The overlay might have been damaged, erase its magic.
1584+ */
1585+ fdt_set_magic(fdto, ~0);
1586+
1587+ /*
1588+ * The base device tree might have been damaged, erase its
1589+ * magic.
1590+ */
1591+ fdt_set_magic(fdt, ~0);
1592+
1593+ return ret;
1594+}
1595diff --git a/common/libfdt/fdt_ro.c b/common/libfdt/fdt_ro.c
1596new file mode 100644
1597index 0000000..17584da
1598--- /dev/null
1599+++ b/common/libfdt/fdt_ro.c
1600@@ -0,0 +1,859 @@
1601+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
1602+/*
1603+ * libfdt - Flat Device Tree manipulation
1604+ * Copyright (C) 2006 David Gibson, IBM Corporation.
1605+ */
1606+#include "libfdt_env.h"
1607+
1608+#include <fdt.h>
1609+#include <libfdt.h>
1610+
1611+#include "libfdt_internal.h"
1612+
1613+static int fdt_nodename_eq_(const void *fdt, int offset,
1614+ const char *s, int len)
1615+{
1616+ int olen;
1617+ const char *p = fdt_get_name(fdt, offset, &olen);
1618+
1619+ if (!p || olen < len)
1620+ /* short match */
1621+ return 0;
1622+
1623+ if (memcmp(p, s, len) != 0)
1624+ return 0;
1625+
1626+ if (p[len] == '\0')
1627+ return 1;
1628+ else if (!memchr(s, '@', len) && (p[len] == '@'))
1629+ return 1;
1630+ else
1631+ return 0;
1632+}
1633+
1634+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
1635+{
1636+ int32_t totalsize;
1637+ uint32_t absoffset;
1638+ size_t len;
1639+ int err;
1640+ const char *s, *n;
1641+
1642+ if (can_assume(VALID_INPUT)) {
1643+ s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
1644+
1645+ if (lenp)
1646+ *lenp = strlen(s);
1647+ return s;
1648+ }
1649+ totalsize = fdt_ro_probe_(fdt);
1650+ err = totalsize;
1651+ if (totalsize < 0)
1652+ goto fail;
1653+
1654+ err = -FDT_ERR_BADOFFSET;
1655+ absoffset = stroffset + fdt_off_dt_strings(fdt);
1656+ if (absoffset >= (unsigned)totalsize)
1657+ goto fail;
1658+ len = totalsize - absoffset;
1659+
1660+ if (fdt_magic(fdt) == FDT_MAGIC) {
1661+ if (stroffset < 0)
1662+ goto fail;
1663+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
1664+ if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
1665+ goto fail;
1666+ if ((fdt_size_dt_strings(fdt) - stroffset) < len)
1667+ len = fdt_size_dt_strings(fdt) - stroffset;
1668+ }
1669+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
1670+ unsigned int sw_stroffset = -stroffset;
1671+
1672+ if ((stroffset >= 0) ||
1673+ (sw_stroffset > fdt_size_dt_strings(fdt)))
1674+ goto fail;
1675+ if (sw_stroffset < len)
1676+ len = sw_stroffset;
1677+ } else {
1678+ err = -FDT_ERR_INTERNAL;
1679+ goto fail;
1680+ }
1681+
1682+ s = (const char *)fdt + absoffset;
1683+ n = memchr(s, '\0', len);
1684+ if (!n) {
1685+ /* missing terminating NULL */
1686+ err = -FDT_ERR_TRUNCATED;
1687+ goto fail;
1688+ }
1689+
1690+ if (lenp)
1691+ *lenp = n - s;
1692+ return s;
1693+
1694+fail:
1695+ if (lenp)
1696+ *lenp = err;
1697+ return NULL;
1698+}
1699+
1700+const char *fdt_string(const void *fdt, int stroffset)
1701+{
1702+ return fdt_get_string(fdt, stroffset, NULL);
1703+}
1704+
1705+static int fdt_string_eq_(const void *fdt, int stroffset,
1706+ const char *s, int len)
1707+{
1708+ int slen;
1709+ const char *p = fdt_get_string(fdt, stroffset, &slen);
1710+
1711+ return p && (slen == len) && (memcmp(p, s, len) == 0);
1712+}
1713+
1714+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
1715+{
1716+ uint32_t max = 0;
1717+ int offset = -1;
1718+
1719+ while (true) {
1720+ uint32_t value;
1721+
1722+ offset = fdt_next_node(fdt, offset, NULL);
1723+ if (offset < 0) {
1724+ if (offset == -FDT_ERR_NOTFOUND)
1725+ break;
1726+
1727+ return offset;
1728+ }
1729+
1730+ value = fdt_get_phandle(fdt, offset);
1731+
1732+ if (value > max)
1733+ max = value;
1734+ }
1735+
1736+ if (phandle)
1737+ *phandle = max;
1738+
1739+ return 0;
1740+}
1741+
1742+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
1743+{
1744+ uint32_t max;
1745+ int err;
1746+
1747+ err = fdt_find_max_phandle(fdt, &max);
1748+ if (err < 0)
1749+ return err;
1750+
1751+ if (max == FDT_MAX_PHANDLE)
1752+ return -FDT_ERR_NOPHANDLES;
1753+
1754+ if (phandle)
1755+ *phandle = max + 1;
1756+
1757+ return 0;
1758+}
1759+
1760+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
1761+{
1762+ unsigned int offset = n * sizeof(struct fdt_reserve_entry);
1763+ unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
1764+
1765+ if (!can_assume(VALID_INPUT)) {
1766+ if (absoffset < fdt_off_mem_rsvmap(fdt))
1767+ return NULL;
1768+ if (absoffset > fdt_totalsize(fdt) -
1769+ sizeof(struct fdt_reserve_entry))
1770+ return NULL;
1771+ }
1772+ return fdt_mem_rsv_(fdt, n);
1773+}
1774+
1775+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
1776+{
1777+ const struct fdt_reserve_entry *re;
1778+
1779+ FDT_RO_PROBE(fdt);
1780+ re = fdt_mem_rsv(fdt, n);
1781+ if (!can_assume(VALID_INPUT) && !re)
1782+ return -FDT_ERR_BADOFFSET;
1783+
1784+ *address = fdt64_ld_(&re->address);
1785+ *size = fdt64_ld_(&re->size);
1786+ return 0;
1787+}
1788+
1789+int fdt_num_mem_rsv(const void *fdt)
1790+{
1791+ int i;
1792+ const struct fdt_reserve_entry *re;
1793+
1794+ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
1795+ if (fdt64_ld_(&re->size) == 0)
1796+ return i;
1797+ }
1798+ return -FDT_ERR_TRUNCATED;
1799+}
1800+
1801+static int nextprop_(const void *fdt, int offset)
1802+{
1803+ uint32_t tag;
1804+ int nextoffset;
1805+
1806+ do {
1807+ tag = fdt_next_tag(fdt, offset, &nextoffset);
1808+
1809+ switch (tag) {
1810+ case FDT_END:
1811+ if (nextoffset >= 0)
1812+ return -FDT_ERR_BADSTRUCTURE;
1813+ else
1814+ return nextoffset;
1815+
1816+ case FDT_PROP:
1817+ return offset;
1818+ }
1819+ offset = nextoffset;
1820+ } while (tag == FDT_NOP);
1821+
1822+ return -FDT_ERR_NOTFOUND;
1823+}
1824+
1825+int fdt_subnode_offset_namelen(const void *fdt, int offset,
1826+ const char *name, int namelen)
1827+{
1828+ int depth;
1829+
1830+ FDT_RO_PROBE(fdt);
1831+
1832+ for (depth = 0;
1833+ (offset >= 0) && (depth >= 0);
1834+ offset = fdt_next_node(fdt, offset, &depth))
1835+ if ((depth == 1)
1836+ && fdt_nodename_eq_(fdt, offset, name, namelen))
1837+ return offset;
1838+
1839+ if (depth < 0)
1840+ return -FDT_ERR_NOTFOUND;
1841+ return offset; /* error */
1842+}
1843+
1844+int fdt_subnode_offset(const void *fdt, int parentoffset,
1845+ const char *name)
1846+{
1847+ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
1848+}
1849+
1850+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
1851+{
1852+ const char *end = path + namelen;
1853+ const char *p = path;
1854+ int offset = 0;
1855+
1856+ FDT_RO_PROBE(fdt);
1857+
1858+ /* see if we have an alias */
1859+ if (*path != '/') {
1860+ const char *q = memchr(path, '/', end - p);
1861+
1862+ if (!q)
1863+ q = end;
1864+
1865+ p = fdt_get_alias_namelen(fdt, p, q - p);
1866+ if (!p)
1867+ return -FDT_ERR_BADPATH;
1868+ offset = fdt_path_offset(fdt, p);
1869+
1870+ p = q;
1871+ }
1872+
1873+ while (p < end) {
1874+ const char *q;
1875+
1876+ while (*p == '/') {
1877+ p++;
1878+ if (p == end)
1879+ return offset;
1880+ }
1881+ q = memchr(p, '/', end - p);
1882+ if (! q)
1883+ q = end;
1884+
1885+ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
1886+ if (offset < 0)
1887+ return offset;
1888+
1889+ p = q;
1890+ }
1891+
1892+ return offset;
1893+}
1894+
1895+int fdt_path_offset(const void *fdt, const char *path)
1896+{
1897+ return fdt_path_offset_namelen(fdt, path, strlen(path));
1898+}
1899+
1900+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
1901+{
1902+ const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
1903+ const char *nameptr;
1904+ int err;
1905+
1906+ if (((err = fdt_ro_probe_(fdt)) < 0)
1907+ || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
1908+ goto fail;
1909+
1910+ nameptr = nh->name;
1911+
1912+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
1913+ /*
1914+ * For old FDT versions, match the naming conventions of V16:
1915+ * give only the leaf name (after all /). The actual tree
1916+ * contents are loosely checked.
1917+ */
1918+ const char *leaf;
1919+ leaf = strrchr(nameptr, '/');
1920+ if (leaf == NULL) {
1921+ err = -FDT_ERR_BADSTRUCTURE;
1922+ goto fail;
1923+ }
1924+ nameptr = leaf+1;
1925+ }
1926+
1927+ if (len)
1928+ *len = strlen(nameptr);
1929+
1930+ return nameptr;
1931+
1932+ fail:
1933+ if (len)
1934+ *len = err;
1935+ return NULL;
1936+}
1937+
1938+int fdt_first_property_offset(const void *fdt, int nodeoffset)
1939+{
1940+ int offset;
1941+
1942+ if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
1943+ return offset;
1944+
1945+ return nextprop_(fdt, offset);
1946+}
1947+
1948+int fdt_next_property_offset(const void *fdt, int offset)
1949+{
1950+ if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
1951+ return offset;
1952+
1953+ return nextprop_(fdt, offset);
1954+}
1955+
1956+static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
1957+ int offset,
1958+ int *lenp)
1959+{
1960+ int err;
1961+ const struct fdt_property *prop;
1962+
1963+ if (!can_assume(VALID_INPUT) &&
1964+ (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
1965+ if (lenp)
1966+ *lenp = err;
1967+ return NULL;
1968+ }
1969+
1970+ prop = fdt_offset_ptr_(fdt, offset);
1971+
1972+ if (lenp)
1973+ *lenp = fdt32_ld_(&prop->len);
1974+
1975+ return prop;
1976+}
1977+
1978+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
1979+ int offset,
1980+ int *lenp)
1981+{
1982+ /* Prior to version 16, properties may need realignment
1983+ * and this API does not work. fdt_getprop_*() will, however. */
1984+
1985+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
1986+ if (lenp)
1987+ *lenp = -FDT_ERR_BADVERSION;
1988+ return NULL;
1989+ }
1990+
1991+ return fdt_get_property_by_offset_(fdt, offset, lenp);
1992+}
1993+
1994+static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
1995+ int offset,
1996+ const char *name,
1997+ int namelen,
1998+ int *lenp,
1999+ int *poffset)
2000+{
2001+ for (offset = fdt_first_property_offset(fdt, offset);
2002+ (offset >= 0);
2003+ (offset = fdt_next_property_offset(fdt, offset))) {
2004+ const struct fdt_property *prop;
2005+
2006+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
2007+ if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
2008+ offset = -FDT_ERR_INTERNAL;
2009+ break;
2010+ }
2011+ if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
2012+ name, namelen)) {
2013+ if (poffset)
2014+ *poffset = offset;
2015+ return prop;
2016+ }
2017+ }
2018+
2019+ if (lenp)
2020+ *lenp = offset;
2021+ return NULL;
2022+}
2023+
2024+
2025+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
2026+ int offset,
2027+ const char *name,
2028+ int namelen, int *lenp)
2029+{
2030+ /* Prior to version 16, properties may need realignment
2031+ * and this API does not work. fdt_getprop_*() will, however. */
2032+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
2033+ if (lenp)
2034+ *lenp = -FDT_ERR_BADVERSION;
2035+ return NULL;
2036+ }
2037+
2038+ return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
2039+ NULL);
2040+}
2041+
2042+
2043+const struct fdt_property *fdt_get_property(const void *fdt,
2044+ int nodeoffset,
2045+ const char *name, int *lenp)
2046+{
2047+ return fdt_get_property_namelen(fdt, nodeoffset, name,
2048+ strlen(name), lenp);
2049+}
2050+
2051+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
2052+ const char *name, int namelen, int *lenp)
2053+{
2054+ int poffset;
2055+ const struct fdt_property *prop;
2056+
2057+ prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
2058+ &poffset);
2059+ if (!prop)
2060+ return NULL;
2061+
2062+ /* Handle realignment */
2063+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
2064+ (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
2065+ return prop->data + 4;
2066+ return prop->data;
2067+}
2068+
2069+const void *fdt_getprop_by_offset(const void *fdt, int offset,
2070+ const char **namep, int *lenp)
2071+{
2072+ const struct fdt_property *prop;
2073+
2074+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
2075+ if (!prop)
2076+ return NULL;
2077+ if (namep) {
2078+ const char *name;
2079+ int namelen;
2080+
2081+ if (!can_assume(VALID_INPUT)) {
2082+ name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
2083+ &namelen);
2084+ if (!name) {
2085+ if (lenp)
2086+ *lenp = namelen;
2087+ return NULL;
2088+ }
2089+ *namep = name;
2090+ } else {
2091+ *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
2092+ }
2093+ }
2094+
2095+ /* Handle realignment */
2096+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
2097+ (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
2098+ return prop->data + 4;
2099+ return prop->data;
2100+}
2101+
2102+const void *fdt_getprop(const void *fdt, int nodeoffset,
2103+ const char *name, int *lenp)
2104+{
2105+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
2106+}
2107+
2108+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
2109+{
2110+ const fdt32_t *php;
2111+ int len;
2112+
2113+ /* FIXME: This is a bit sub-optimal, since we potentially scan
2114+ * over all the properties twice. */
2115+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
2116+ if (!php || (len != sizeof(*php))) {
2117+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
2118+ if (!php || (len != sizeof(*php)))
2119+ return 0;
2120+ }
2121+
2122+ return fdt32_ld_(php);
2123+}
2124+
2125+const char *fdt_get_alias_namelen(const void *fdt,
2126+ const char *name, int namelen)
2127+{
2128+ int aliasoffset;
2129+
2130+ aliasoffset = fdt_path_offset(fdt, "/aliases");
2131+ if (aliasoffset < 0)
2132+ return NULL;
2133+
2134+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
2135+}
2136+
2137+const char *fdt_get_alias(const void *fdt, const char *name)
2138+{
2139+ return fdt_get_alias_namelen(fdt, name, strlen(name));
2140+}
2141+
2142+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
2143+{
2144+ int pdepth = 0, p = 0;
2145+ int offset, depth, namelen;
2146+ const char *name;
2147+
2148+ FDT_RO_PROBE(fdt);
2149+
2150+ if (buflen < 2)
2151+ return -FDT_ERR_NOSPACE;
2152+
2153+ for (offset = 0, depth = 0;
2154+ (offset >= 0) && (offset <= nodeoffset);
2155+ offset = fdt_next_node(fdt, offset, &depth)) {
2156+ while (pdepth > depth) {
2157+ do {
2158+ p--;
2159+ } while (buf[p-1] != '/');
2160+ pdepth--;
2161+ }
2162+
2163+ if (pdepth >= depth) {
2164+ name = fdt_get_name(fdt, offset, &namelen);
2165+ if (!name)
2166+ return namelen;
2167+ if ((p + namelen + 1) <= buflen) {
2168+ memcpy(buf + p, name, namelen);
2169+ p += namelen;
2170+ buf[p++] = '/';
2171+ pdepth++;
2172+ }
2173+ }
2174+
2175+ if (offset == nodeoffset) {
2176+ if (pdepth < (depth + 1))
2177+ return -FDT_ERR_NOSPACE;
2178+
2179+ if (p > 1) /* special case so that root path is "/", not "" */
2180+ p--;
2181+ buf[p] = '\0';
2182+ return 0;
2183+ }
2184+ }
2185+
2186+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
2187+ return -FDT_ERR_BADOFFSET;
2188+ else if (offset == -FDT_ERR_BADOFFSET)
2189+ return -FDT_ERR_BADSTRUCTURE;
2190+
2191+ return offset; /* error from fdt_next_node() */
2192+}
2193+
2194+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
2195+ int supernodedepth, int *nodedepth)
2196+{
2197+ int offset, depth;
2198+ int supernodeoffset = -FDT_ERR_INTERNAL;
2199+
2200+ FDT_RO_PROBE(fdt);
2201+
2202+ if (supernodedepth < 0)
2203+ return -FDT_ERR_NOTFOUND;
2204+
2205+ for (offset = 0, depth = 0;
2206+ (offset >= 0) && (offset <= nodeoffset);
2207+ offset = fdt_next_node(fdt, offset, &depth)) {
2208+ if (depth == supernodedepth)
2209+ supernodeoffset = offset;
2210+
2211+ if (offset == nodeoffset) {
2212+ if (nodedepth)
2213+ *nodedepth = depth;
2214+
2215+ if (supernodedepth > depth)
2216+ return -FDT_ERR_NOTFOUND;
2217+ else
2218+ return supernodeoffset;
2219+ }
2220+ }
2221+
2222+ if (!can_assume(VALID_INPUT)) {
2223+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
2224+ return -FDT_ERR_BADOFFSET;
2225+ else if (offset == -FDT_ERR_BADOFFSET)
2226+ return -FDT_ERR_BADSTRUCTURE;
2227+ }
2228+
2229+ return offset; /* error from fdt_next_node() */
2230+}
2231+
2232+int fdt_node_depth(const void *fdt, int nodeoffset)
2233+{
2234+ int nodedepth;
2235+ int err;
2236+
2237+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
2238+ if (err)
2239+ return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
2240+ -FDT_ERR_INTERNAL;
2241+ return nodedepth;
2242+}
2243+
2244+int fdt_parent_offset(const void *fdt, int nodeoffset)
2245+{
2246+ int nodedepth = fdt_node_depth(fdt, nodeoffset);
2247+
2248+ if (nodedepth < 0)
2249+ return nodedepth;
2250+ return fdt_supernode_atdepth_offset(fdt, nodeoffset,
2251+ nodedepth - 1, NULL);
2252+}
2253+
2254+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
2255+ const char *propname,
2256+ const void *propval, int proplen)
2257+{
2258+ int offset;
2259+ const void *val;
2260+ int len;
2261+
2262+ FDT_RO_PROBE(fdt);
2263+
2264+ /* FIXME: The algorithm here is pretty horrible: we scan each
2265+ * property of a node in fdt_getprop(), then if that didn't
2266+ * find what we want, we scan over them again making our way
2267+ * to the next node. Still it's the easiest to implement
2268+ * approach; performance can come later. */
2269+ for (offset = fdt_next_node(fdt, startoffset, NULL);
2270+ offset >= 0;
2271+ offset = fdt_next_node(fdt, offset, NULL)) {
2272+ val = fdt_getprop(fdt, offset, propname, &len);
2273+ if (val && (len == proplen)
2274+ && (memcmp(val, propval, len) == 0))
2275+ return offset;
2276+ }
2277+
2278+ return offset; /* error from fdt_next_node() */
2279+}
2280+
2281+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
2282+{
2283+ int offset;
2284+
2285+ if ((phandle == 0) || (phandle == ~0U))
2286+ return -FDT_ERR_BADPHANDLE;
2287+
2288+ FDT_RO_PROBE(fdt);
2289+
2290+ /* FIXME: The algorithm here is pretty horrible: we
2291+ * potentially scan each property of a node in
2292+ * fdt_get_phandle(), then if that didn't find what
2293+ * we want, we scan over them again making our way to the next
2294+ * node. Still it's the easiest to implement approach;
2295+ * performance can come later. */
2296+ for (offset = fdt_next_node(fdt, -1, NULL);
2297+ offset >= 0;
2298+ offset = fdt_next_node(fdt, offset, NULL)) {
2299+ if (fdt_get_phandle(fdt, offset) == phandle)
2300+ return offset;
2301+ }
2302+
2303+ return offset; /* error from fdt_next_node() */
2304+}
2305+
2306+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
2307+{
2308+ int len = strlen(str);
2309+ const char *p;
2310+
2311+ while (listlen >= len) {
2312+ if (memcmp(str, strlist, len+1) == 0)
2313+ return 1;
2314+ p = memchr(strlist, '\0', listlen);
2315+ if (!p)
2316+ return 0; /* malformed strlist.. */
2317+ listlen -= (p-strlist) + 1;
2318+ strlist = p + 1;
2319+ }
2320+ return 0;
2321+}
2322+
2323+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
2324+{
2325+ const char *list, *end;
2326+ int length, count = 0;
2327+
2328+ list = fdt_getprop(fdt, nodeoffset, property, &length);
2329+ if (!list)
2330+ return length;
2331+
2332+ end = list + length;
2333+
2334+ while (list < end) {
2335+ length = strnlen(list, end - list) + 1;
2336+
2337+ /* Abort if the last string isn't properly NUL-terminated. */
2338+ if (list + length > end)
2339+ return -FDT_ERR_BADVALUE;
2340+
2341+ list += length;
2342+ count++;
2343+ }
2344+
2345+ return count;
2346+}
2347+
2348+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
2349+ const char *string)
2350+{
2351+ int length, len, idx = 0;
2352+ const char *list, *end;
2353+
2354+ list = fdt_getprop(fdt, nodeoffset, property, &length);
2355+ if (!list)
2356+ return length;
2357+
2358+ len = strlen(string) + 1;
2359+ end = list + length;
2360+
2361+ while (list < end) {
2362+ length = strnlen(list, end - list) + 1;
2363+
2364+ /* Abort if the last string isn't properly NUL-terminated. */
2365+ if (list + length > end)
2366+ return -FDT_ERR_BADVALUE;
2367+
2368+ if (length == len && memcmp(list, string, length) == 0)
2369+ return idx;
2370+
2371+ list += length;
2372+ idx++;
2373+ }
2374+
2375+ return -FDT_ERR_NOTFOUND;
2376+}
2377+
2378+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
2379+ const char *property, int idx,
2380+ int *lenp)
2381+{
2382+ const char *list, *end;
2383+ int length;
2384+
2385+ list = fdt_getprop(fdt, nodeoffset, property, &length);
2386+ if (!list) {
2387+ if (lenp)
2388+ *lenp = length;
2389+
2390+ return NULL;
2391+ }
2392+
2393+ end = list + length;
2394+
2395+ while (list < end) {
2396+ length = strnlen(list, end - list) + 1;
2397+
2398+ /* Abort if the last string isn't properly NUL-terminated. */
2399+ if (list + length > end) {
2400+ if (lenp)
2401+ *lenp = -FDT_ERR_BADVALUE;
2402+
2403+ return NULL;
2404+ }
2405+
2406+ if (idx == 0) {
2407+ if (lenp)
2408+ *lenp = length - 1;
2409+
2410+ return list;
2411+ }
2412+
2413+ list += length;
2414+ idx--;
2415+ }
2416+
2417+ if (lenp)
2418+ *lenp = -FDT_ERR_NOTFOUND;
2419+
2420+ return NULL;
2421+}
2422+
2423+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
2424+ const char *compatible)
2425+{
2426+ const void *prop;
2427+ int len;
2428+
2429+ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
2430+ if (!prop)
2431+ return len;
2432+
2433+ return !fdt_stringlist_contains(prop, len, compatible);
2434+}
2435+
2436+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
2437+ const char *compatible)
2438+{
2439+ int offset, err;
2440+
2441+ FDT_RO_PROBE(fdt);
2442+
2443+ /* FIXME: The algorithm here is pretty horrible: we scan each
2444+ * property of a node in fdt_node_check_compatible(), then if
2445+ * that didn't find what we want, we scan over them again
2446+ * making our way to the next node. Still it's the easiest to
2447+ * implement approach; performance can come later. */
2448+ for (offset = fdt_next_node(fdt, startoffset, NULL);
2449+ offset >= 0;
2450+ offset = fdt_next_node(fdt, offset, NULL)) {
2451+ err = fdt_node_check_compatible(fdt, offset, compatible);
2452+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
2453+ return err;
2454+ else if (err == 0)
2455+ return offset;
2456+ }
2457+
2458+ return offset; /* error from fdt_next_node() */
2459+}
2460diff --git a/common/libfdt/fdt_rw.c b/common/libfdt/fdt_rw.c
2461new file mode 100644
2462index 0000000..3621d36
2463--- /dev/null
2464+++ b/common/libfdt/fdt_rw.c
2465@@ -0,0 +1,500 @@
2466+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2467+/*
2468+ * libfdt - Flat Device Tree manipulation
2469+ * Copyright (C) 2006 David Gibson, IBM Corporation.
2470+ */
2471+#include "libfdt_env.h"
2472+
2473+#include <fdt.h>
2474+#include <libfdt.h>
2475+
2476+#include "libfdt_internal.h"
2477+
2478+static int fdt_blocks_misordered_(const void *fdt,
2479+ int mem_rsv_size, int struct_size)
2480+{
2481+ return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
2482+ || (fdt_off_dt_struct(fdt) <
2483+ (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
2484+ || (fdt_off_dt_strings(fdt) <
2485+ (fdt_off_dt_struct(fdt) + struct_size))
2486+ || (fdt_totalsize(fdt) <
2487+ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
2488+}
2489+
2490+static int fdt_rw_probe_(void *fdt)
2491+{
2492+ if (can_assume(VALID_DTB))
2493+ return 0;
2494+ FDT_RO_PROBE(fdt);
2495+
2496+ if (!can_assume(LATEST) && fdt_version(fdt) < 17)
2497+ return -FDT_ERR_BADVERSION;
2498+ if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
2499+ fdt_size_dt_struct(fdt)))
2500+ return -FDT_ERR_BADLAYOUT;
2501+ if (!can_assume(LATEST) && fdt_version(fdt) > 17)
2502+ fdt_set_version(fdt, 17);
2503+
2504+ return 0;
2505+}
2506+
2507+#define FDT_RW_PROBE(fdt) \
2508+ { \
2509+ int err_; \
2510+ if ((err_ = fdt_rw_probe_(fdt)) != 0) \
2511+ return err_; \
2512+ }
2513+
2514+static inline unsigned int fdt_data_size_(void *fdt)
2515+{
2516+ return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
2517+}
2518+
2519+static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
2520+{
2521+ char *p = splicepoint;
2522+ unsigned int dsize = fdt_data_size_(fdt);
2523+ size_t soff = p - (char *)fdt;
2524+
2525+ if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
2526+ return -FDT_ERR_BADOFFSET;
2527+ if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
2528+ return -FDT_ERR_BADOFFSET;
2529+ if (dsize - oldlen + newlen > fdt_totalsize(fdt))
2530+ return -FDT_ERR_NOSPACE;
2531+ memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
2532+ return 0;
2533+}
2534+
2535+static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
2536+ int oldn, int newn)
2537+{
2538+ int delta = (newn - oldn) * sizeof(*p);
2539+ int err;
2540+ err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
2541+ if (err)
2542+ return err;
2543+ fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
2544+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
2545+ return 0;
2546+}
2547+
2548+static int fdt_splice_struct_(void *fdt, void *p,
2549+ int oldlen, int newlen)
2550+{
2551+ int delta = newlen - oldlen;
2552+ int err;
2553+
2554+ if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
2555+ return err;
2556+
2557+ fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
2558+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
2559+ return 0;
2560+}
2561+
2562+/* Must only be used to roll back in case of error */
2563+static void fdt_del_last_string_(void *fdt, const char *s)
2564+{
2565+ int newlen = strlen(s) + 1;
2566+
2567+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
2568+}
2569+
2570+static int fdt_splice_string_(void *fdt, int newlen)
2571+{
2572+ void *p = (char *)fdt
2573+ + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
2574+ int err;
2575+
2576+ if ((err = fdt_splice_(fdt, p, 0, newlen)))
2577+ return err;
2578+
2579+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
2580+ return 0;
2581+}
2582+
2583+/**
2584+ * fdt_find_add_string_() - Find or allocate a string
2585+ *
2586+ * @fdt: pointer to the device tree to check/adjust
2587+ * @s: string to find/add
2588+ * @allocated: Set to 0 if the string was found, 1 if not found and so
2589+ * allocated. Ignored if can_assume(NO_ROLLBACK)
2590+ * @return offset of string in the string table (whether found or added)
2591+ */
2592+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
2593+{
2594+ char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
2595+ const char *p;
2596+ char *new;
2597+ int len = strlen(s) + 1;
2598+ int err;
2599+
2600+ if (!can_assume(NO_ROLLBACK))
2601+ *allocated = 0;
2602+
2603+ p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
2604+ if (p)
2605+ /* found it */
2606+ return (p - strtab);
2607+
2608+ new = strtab + fdt_size_dt_strings(fdt);
2609+ err = fdt_splice_string_(fdt, len);
2610+ if (err)
2611+ return err;
2612+
2613+ if (!can_assume(NO_ROLLBACK))
2614+ *allocated = 1;
2615+
2616+ memcpy(new, s, len);
2617+ return (new - strtab);
2618+}
2619+
2620+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
2621+{
2622+ struct fdt_reserve_entry *re;
2623+ int err;
2624+
2625+ FDT_RW_PROBE(fdt);
2626+
2627+ re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
2628+ err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
2629+ if (err)
2630+ return err;
2631+
2632+ re->address = cpu_to_fdt64(address);
2633+ re->size = cpu_to_fdt64(size);
2634+ return 0;
2635+}
2636+
2637+int fdt_del_mem_rsv(void *fdt, int n)
2638+{
2639+ struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
2640+
2641+ FDT_RW_PROBE(fdt);
2642+
2643+ if (n >= fdt_num_mem_rsv(fdt))
2644+ return -FDT_ERR_NOTFOUND;
2645+
2646+ return fdt_splice_mem_rsv_(fdt, re, 1, 0);
2647+}
2648+
2649+static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
2650+ int len, struct fdt_property **prop)
2651+{
2652+ int oldlen;
2653+ int err;
2654+
2655+ *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
2656+ if (!*prop)
2657+ return oldlen;
2658+
2659+ if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
2660+ FDT_TAGALIGN(len))))
2661+ return err;
2662+
2663+ (*prop)->len = cpu_to_fdt32(len);
2664+ return 0;
2665+}
2666+
2667+static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
2668+ int len, struct fdt_property **prop)
2669+{
2670+ int proplen;
2671+ int nextoffset;
2672+ int namestroff;
2673+ int err;
2674+ int allocated;
2675+
2676+ if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
2677+ return nextoffset;
2678+
2679+ namestroff = fdt_find_add_string_(fdt, name, &allocated);
2680+ if (namestroff < 0)
2681+ return namestroff;
2682+
2683+ *prop = fdt_offset_ptr_w_(fdt, nextoffset);
2684+ proplen = sizeof(**prop) + FDT_TAGALIGN(len);
2685+
2686+ err = fdt_splice_struct_(fdt, *prop, 0, proplen);
2687+ if (err) {
2688+ /* Delete the string if we failed to add it */
2689+ if (!can_assume(NO_ROLLBACK) && allocated)
2690+ fdt_del_last_string_(fdt, name);
2691+ return err;
2692+ }
2693+
2694+ (*prop)->tag = cpu_to_fdt32(FDT_PROP);
2695+ (*prop)->nameoff = cpu_to_fdt32(namestroff);
2696+ (*prop)->len = cpu_to_fdt32(len);
2697+ return 0;
2698+}
2699+
2700+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
2701+{
2702+ char *namep;
2703+ int oldlen, newlen;
2704+ int err;
2705+
2706+ FDT_RW_PROBE(fdt);
2707+
2708+ namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
2709+ if (!namep)
2710+ return oldlen;
2711+
2712+ newlen = strlen(name);
2713+
2714+ err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
2715+ FDT_TAGALIGN(newlen+1));
2716+ if (err)
2717+ return err;
2718+
2719+ memcpy(namep, name, newlen+1);
2720+ return 0;
2721+}
2722+
2723+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
2724+ int len, void **prop_data)
2725+{
2726+ struct fdt_property *prop;
2727+ int err;
2728+
2729+ FDT_RW_PROBE(fdt);
2730+
2731+ err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
2732+ if (err == -FDT_ERR_NOTFOUND)
2733+ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
2734+ if (err)
2735+ return err;
2736+
2737+ *prop_data = prop->data;
2738+ return 0;
2739+}
2740+
2741+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
2742+ const void *val, int len)
2743+{
2744+ void *prop_data;
2745+ int err;
2746+
2747+ err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
2748+ if (err)
2749+ return err;
2750+
2751+ if (len)
2752+ memcpy(prop_data, val, len);
2753+ return 0;
2754+}
2755+
2756+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
2757+ const void *val, int len)
2758+{
2759+ struct fdt_property *prop;
2760+ int err, oldlen, newlen;
2761+
2762+ FDT_RW_PROBE(fdt);
2763+
2764+ prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
2765+ if (prop) {
2766+ newlen = len + oldlen;
2767+ err = fdt_splice_struct_(fdt, prop->data,
2768+ FDT_TAGALIGN(oldlen),
2769+ FDT_TAGALIGN(newlen));
2770+ if (err)
2771+ return err;
2772+ prop->len = cpu_to_fdt32(newlen);
2773+ memcpy(prop->data + oldlen, val, len);
2774+ } else {
2775+ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
2776+ if (err)
2777+ return err;
2778+ memcpy(prop->data, val, len);
2779+ }
2780+ return 0;
2781+}
2782+
2783+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
2784+{
2785+ struct fdt_property *prop;
2786+ int len, proplen;
2787+
2788+ FDT_RW_PROBE(fdt);
2789+
2790+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
2791+ if (!prop)
2792+ return len;
2793+
2794+ proplen = sizeof(*prop) + FDT_TAGALIGN(len);
2795+ return fdt_splice_struct_(fdt, prop, proplen, 0);
2796+}
2797+
2798+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
2799+ const char *name, int namelen)
2800+{
2801+ struct fdt_node_header *nh;
2802+ int offset, nextoffset;
2803+ int nodelen;
2804+ int err;
2805+ uint32_t tag;
2806+ fdt32_t *endtag;
2807+
2808+ FDT_RW_PROBE(fdt);
2809+
2810+ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
2811+ if (offset >= 0)
2812+ return -FDT_ERR_EXISTS;
2813+ else if (offset != -FDT_ERR_NOTFOUND)
2814+ return offset;
2815+
2816+ /* Try to place the new node after the parent's properties */
2817+ tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
2818+ /* the fdt_subnode_offset_namelen() should ensure this never hits */
2819+ if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
2820+ return -FDT_ERR_INTERNAL;
2821+ do {
2822+ offset = nextoffset;
2823+ tag = fdt_next_tag(fdt, offset, &nextoffset);
2824+ } while ((tag == FDT_PROP) || (tag == FDT_NOP));
2825+
2826+ nh = fdt_offset_ptr_w_(fdt, offset);
2827+ nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
2828+
2829+ err = fdt_splice_struct_(fdt, nh, 0, nodelen);
2830+ if (err)
2831+ return err;
2832+
2833+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
2834+ memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
2835+ memcpy(nh->name, name, namelen);
2836+ endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
2837+ *endtag = cpu_to_fdt32(FDT_END_NODE);
2838+
2839+ return offset;
2840+}
2841+
2842+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
2843+{
2844+ return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
2845+}
2846+
2847+int fdt_del_node(void *fdt, int nodeoffset)
2848+{
2849+ int endoffset;
2850+
2851+ FDT_RW_PROBE(fdt);
2852+
2853+ endoffset = fdt_node_end_offset_(fdt, nodeoffset);
2854+ if (endoffset < 0)
2855+ return endoffset;
2856+
2857+ return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
2858+ endoffset - nodeoffset, 0);
2859+}
2860+
2861+static void fdt_packblocks_(const char *old, char *new,
2862+ int mem_rsv_size,
2863+ int struct_size,
2864+ int strings_size)
2865+{
2866+ int mem_rsv_off, struct_off, strings_off;
2867+
2868+ mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
2869+ struct_off = mem_rsv_off + mem_rsv_size;
2870+ strings_off = struct_off + struct_size;
2871+
2872+ memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
2873+ fdt_set_off_mem_rsvmap(new, mem_rsv_off);
2874+
2875+ memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
2876+ fdt_set_off_dt_struct(new, struct_off);
2877+ fdt_set_size_dt_struct(new, struct_size);
2878+
2879+ memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
2880+ fdt_set_off_dt_strings(new, strings_off);
2881+ fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
2882+}
2883+
2884+int fdt_open_into(const void *fdt, void *buf, int bufsize)
2885+{
2886+ int err;
2887+ int mem_rsv_size, struct_size;
2888+ int newsize;
2889+ const char *fdtstart = fdt;
2890+ const char *fdtend = fdtstart + fdt_totalsize(fdt);
2891+ char *tmp;
2892+
2893+ FDT_RO_PROBE(fdt);
2894+
2895+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
2896+ * sizeof(struct fdt_reserve_entry);
2897+
2898+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
2899+ struct_size = fdt_size_dt_struct(fdt);
2900+ } else if (fdt_version(fdt) == 16) {
2901+ struct_size = 0;
2902+ while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
2903+ ;
2904+ if (struct_size < 0)
2905+ return struct_size;
2906+ } else {
2907+ return -FDT_ERR_BADVERSION;
2908+ }
2909+
2910+ if (can_assume(LIBFDT_ORDER) ||
2911+ !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
2912+ /* no further work necessary */
2913+ err = fdt_move(fdt, buf, bufsize);
2914+ if (err)
2915+ return err;
2916+ fdt_set_version(buf, 17);
2917+ fdt_set_size_dt_struct(buf, struct_size);
2918+ fdt_set_totalsize(buf, bufsize);
2919+ return 0;
2920+ }
2921+
2922+ /* Need to reorder */
2923+ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
2924+ + struct_size + fdt_size_dt_strings(fdt);
2925+
2926+ if (bufsize < newsize)
2927+ return -FDT_ERR_NOSPACE;
2928+
2929+ /* First attempt to build converted tree at beginning of buffer */
2930+ tmp = buf;
2931+ /* But if that overlaps with the old tree... */
2932+ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
2933+ /* Try right after the old tree instead */
2934+ tmp = (char *)(uintptr_t)fdtend;
2935+ if ((tmp + newsize) > ((char *)buf + bufsize))
2936+ return -FDT_ERR_NOSPACE;
2937+ }
2938+
2939+ fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
2940+ fdt_size_dt_strings(fdt));
2941+ memmove(buf, tmp, newsize);
2942+
2943+ fdt_set_magic(buf, FDT_MAGIC);
2944+ fdt_set_totalsize(buf, bufsize);
2945+ fdt_set_version(buf, 17);
2946+ fdt_set_last_comp_version(buf, 16);
2947+ fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
2948+
2949+ return 0;
2950+}
2951+
2952+int fdt_pack(void *fdt)
2953+{
2954+ int mem_rsv_size;
2955+
2956+ FDT_RW_PROBE(fdt);
2957+
2958+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
2959+ * sizeof(struct fdt_reserve_entry);
2960+ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
2961+ fdt_size_dt_strings(fdt));
2962+ fdt_set_totalsize(fdt, fdt_data_size_(fdt));
2963+
2964+ return 0;
2965+}
2966diff --git a/common/libfdt/fdt_strerror.c b/common/libfdt/fdt_strerror.c
2967new file mode 100644
2968index 0000000..b435693
2969--- /dev/null
2970+++ b/common/libfdt/fdt_strerror.c
2971@@ -0,0 +1,59 @@
2972+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2973+/*
2974+ * libfdt - Flat Device Tree manipulation
2975+ * Copyright (C) 2006 David Gibson, IBM Corporation.
2976+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2977+ */
2978+#include "libfdt_env.h"
2979+
2980+#include <fdt.h>
2981+#include <libfdt.h>
2982+
2983+#include "libfdt_internal.h"
2984+
2985+struct fdt_errtabent {
2986+ const char *str;
2987+};
2988+
2989+#define FDT_ERRTABENT(val) \
2990+ [(val)] = { .str = #val, }
2991+
2992+static struct fdt_errtabent fdt_errtable[] = {
2993+ FDT_ERRTABENT(FDT_ERR_NOTFOUND),
2994+ FDT_ERRTABENT(FDT_ERR_EXISTS),
2995+ FDT_ERRTABENT(FDT_ERR_NOSPACE),
2996+
2997+ FDT_ERRTABENT(FDT_ERR_BADOFFSET),
2998+ FDT_ERRTABENT(FDT_ERR_BADPATH),
2999+ FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
3000+ FDT_ERRTABENT(FDT_ERR_BADSTATE),
3001+
3002+ FDT_ERRTABENT(FDT_ERR_TRUNCATED),
3003+ FDT_ERRTABENT(FDT_ERR_BADMAGIC),
3004+ FDT_ERRTABENT(FDT_ERR_BADVERSION),
3005+ FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
3006+ FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
3007+ FDT_ERRTABENT(FDT_ERR_INTERNAL),
3008+ FDT_ERRTABENT(FDT_ERR_BADNCELLS),
3009+ FDT_ERRTABENT(FDT_ERR_BADVALUE),
3010+ FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
3011+ FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
3012+ FDT_ERRTABENT(FDT_ERR_BADFLAGS),
3013+};
3014+#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
3015+
3016+const char *fdt_strerror(int errval)
3017+{
3018+ if (errval > 0)
3019+ return "<valid offset/length>";
3020+ else if (errval == 0)
3021+ return "<no error>";
3022+ else if (-errval < FDT_ERRTABSIZE) {
3023+ const char *s = fdt_errtable[-errval].str;
3024+
3025+ if (s)
3026+ return s;
3027+ }
3028+
3029+ return "<unknown error>";
3030+}
3031diff --git a/common/libfdt/fdt_sw.c b/common/libfdt/fdt_sw.c
3032new file mode 100644
3033index 0000000..4c569ee
3034--- /dev/null
3035+++ b/common/libfdt/fdt_sw.c
3036@@ -0,0 +1,384 @@
3037+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
3038+/*
3039+ * libfdt - Flat Device Tree manipulation
3040+ * Copyright (C) 2006 David Gibson, IBM Corporation.
3041+ */
3042+#include "libfdt_env.h"
3043+
3044+#include <fdt.h>
3045+#include <libfdt.h>
3046+
3047+#include "libfdt_internal.h"
3048+
3049+static int fdt_sw_probe_(void *fdt)
3050+{
3051+ if (!can_assume(VALID_INPUT)) {
3052+ if (fdt_magic(fdt) == FDT_MAGIC)
3053+ return -FDT_ERR_BADSTATE;
3054+ else if (fdt_magic(fdt) != FDT_SW_MAGIC)
3055+ return -FDT_ERR_BADMAGIC;
3056+ }
3057+
3058+ return 0;
3059+}
3060+
3061+#define FDT_SW_PROBE(fdt) \
3062+ { \
3063+ int err; \
3064+ if ((err = fdt_sw_probe_(fdt)) != 0) \
3065+ return err; \
3066+ }
3067+
3068+/* 'memrsv' state: Initial state after fdt_create()
3069+ *
3070+ * Allowed functions:
3071+ * fdt_add_reservemap_entry()
3072+ * fdt_finish_reservemap() [moves to 'struct' state]
3073+ */
3074+static int fdt_sw_probe_memrsv_(void *fdt)
3075+{
3076+ int err = fdt_sw_probe_(fdt);
3077+ if (err)
3078+ return err;
3079+
3080+ if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
3081+ return -FDT_ERR_BADSTATE;
3082+ return 0;
3083+}
3084+
3085+#define FDT_SW_PROBE_MEMRSV(fdt) \
3086+ { \
3087+ int err; \
3088+ if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
3089+ return err; \
3090+ }
3091+
3092+/* 'struct' state: Enter this state after fdt_finish_reservemap()
3093+ *
3094+ * Allowed functions:
3095+ * fdt_begin_node()
3096+ * fdt_end_node()
3097+ * fdt_property*()
3098+ * fdt_finish() [moves to 'complete' state]
3099+ */
3100+static int fdt_sw_probe_struct_(void *fdt)
3101+{
3102+ int err = fdt_sw_probe_(fdt);
3103+ if (err)
3104+ return err;
3105+
3106+ if (!can_assume(VALID_INPUT) &&
3107+ fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
3108+ return -FDT_ERR_BADSTATE;
3109+ return 0;
3110+}
3111+
3112+#define FDT_SW_PROBE_STRUCT(fdt) \
3113+ { \
3114+ int err; \
3115+ if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
3116+ return err; \
3117+ }
3118+
3119+static inline uint32_t sw_flags(void *fdt)
3120+{
3121+ /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
3122+ return fdt_last_comp_version(fdt);
3123+}
3124+
3125+/* 'complete' state: Enter this state after fdt_finish()
3126+ *
3127+ * Allowed functions: none
3128+ */
3129+
3130+static void *fdt_grab_space_(void *fdt, size_t len)
3131+{
3132+ unsigned int offset = fdt_size_dt_struct(fdt);
3133+ unsigned int spaceleft;
3134+
3135+ spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
3136+ - fdt_size_dt_strings(fdt);
3137+
3138+ if ((offset + len < offset) || (offset + len > spaceleft))
3139+ return NULL;
3140+
3141+ fdt_set_size_dt_struct(fdt, offset + len);
3142+ return fdt_offset_ptr_w_(fdt, offset);
3143+}
3144+
3145+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
3146+{
3147+ const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
3148+ sizeof(struct fdt_reserve_entry));
3149+ void *fdt = buf;
3150+
3151+ if (bufsize < hdrsize)
3152+ return -FDT_ERR_NOSPACE;
3153+
3154+ if (flags & ~FDT_CREATE_FLAGS_ALL)
3155+ return -FDT_ERR_BADFLAGS;
3156+
3157+ memset(buf, 0, bufsize);
3158+
3159+ /*
3160+ * magic and last_comp_version keep intermediate state during the fdt
3161+ * creation process, which is replaced with the proper FDT format by
3162+ * fdt_finish().
3163+ *
3164+ * flags should be accessed with sw_flags().
3165+ */
3166+ fdt_set_magic(fdt, FDT_SW_MAGIC);
3167+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
3168+ fdt_set_last_comp_version(fdt, flags);
3169+
3170+ fdt_set_totalsize(fdt, bufsize);
3171+
3172+ fdt_set_off_mem_rsvmap(fdt, hdrsize);
3173+ fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
3174+ fdt_set_off_dt_strings(fdt, 0);
3175+
3176+ return 0;
3177+}
3178+
3179+int fdt_create(void *buf, int bufsize)
3180+{
3181+ return fdt_create_with_flags(buf, bufsize, 0);
3182+}
3183+
3184+int fdt_resize(void *fdt, void *buf, int bufsize)
3185+{
3186+ size_t headsize, tailsize;
3187+ char *oldtail, *newtail;
3188+
3189+ FDT_SW_PROBE(fdt);
3190+
3191+ if (bufsize < 0)
3192+ return -FDT_ERR_NOSPACE;
3193+
3194+ headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
3195+ tailsize = fdt_size_dt_strings(fdt);
3196+
3197+ if (!can_assume(VALID_DTB) &&
3198+ headsize + tailsize > fdt_totalsize(fdt))
3199+ return -FDT_ERR_INTERNAL;
3200+
3201+ if ((headsize + tailsize) > (unsigned)bufsize)
3202+ return -FDT_ERR_NOSPACE;
3203+
3204+ oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
3205+ newtail = (char *)buf + bufsize - tailsize;
3206+
3207+ /* Two cases to avoid clobbering data if the old and new
3208+ * buffers partially overlap */
3209+ if (buf <= fdt) {
3210+ memmove(buf, fdt, headsize);
3211+ memmove(newtail, oldtail, tailsize);
3212+ } else {
3213+ memmove(newtail, oldtail, tailsize);
3214+ memmove(buf, fdt, headsize);
3215+ }
3216+
3217+ fdt_set_totalsize(buf, bufsize);
3218+ if (fdt_off_dt_strings(buf))
3219+ fdt_set_off_dt_strings(buf, bufsize);
3220+
3221+ return 0;
3222+}
3223+
3224+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
3225+{
3226+ struct fdt_reserve_entry *re;
3227+ int offset;
3228+
3229+ FDT_SW_PROBE_MEMRSV(fdt);
3230+
3231+ offset = fdt_off_dt_struct(fdt);
3232+ if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
3233+ return -FDT_ERR_NOSPACE;
3234+
3235+ re = (struct fdt_reserve_entry *)((char *)fdt + offset);
3236+ re->address = cpu_to_fdt64(addr);
3237+ re->size = cpu_to_fdt64(size);
3238+
3239+ fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
3240+
3241+ return 0;
3242+}
3243+
3244+int fdt_finish_reservemap(void *fdt)
3245+{
3246+ int err = fdt_add_reservemap_entry(fdt, 0, 0);
3247+
3248+ if (err)
3249+ return err;
3250+
3251+ fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
3252+ return 0;
3253+}
3254+
3255+int fdt_begin_node(void *fdt, const char *name)
3256+{
3257+ struct fdt_node_header *nh;
3258+ int namelen;
3259+
3260+ FDT_SW_PROBE_STRUCT(fdt);
3261+
3262+ namelen = strlen(name) + 1;
3263+ nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
3264+ if (! nh)
3265+ return -FDT_ERR_NOSPACE;
3266+
3267+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
3268+ memcpy(nh->name, name, namelen);
3269+ return 0;
3270+}
3271+
3272+int fdt_end_node(void *fdt)
3273+{
3274+ fdt32_t *en;
3275+
3276+ FDT_SW_PROBE_STRUCT(fdt);
3277+
3278+ en = fdt_grab_space_(fdt, FDT_TAGSIZE);
3279+ if (! en)
3280+ return -FDT_ERR_NOSPACE;
3281+
3282+ *en = cpu_to_fdt32(FDT_END_NODE);
3283+ return 0;
3284+}
3285+
3286+static int fdt_add_string_(void *fdt, const char *s)
3287+{
3288+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
3289+ unsigned int strtabsize = fdt_size_dt_strings(fdt);
3290+ unsigned int len = strlen(s) + 1;
3291+ unsigned int struct_top, offset;
3292+
3293+ offset = strtabsize + len;
3294+ struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
3295+ if (fdt_totalsize(fdt) - offset < struct_top)
3296+ return 0; /* no more room :( */
3297+
3298+ memcpy(strtab - offset, s, len);
3299+ fdt_set_size_dt_strings(fdt, strtabsize + len);
3300+ return -offset;
3301+}
3302+
3303+/* Must only be used to roll back in case of error */
3304+static void fdt_del_last_string_(void *fdt, const char *s)
3305+{
3306+ int strtabsize = fdt_size_dt_strings(fdt);
3307+ int len = strlen(s) + 1;
3308+
3309+ fdt_set_size_dt_strings(fdt, strtabsize - len);
3310+}
3311+
3312+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
3313+{
3314+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
3315+ int strtabsize = fdt_size_dt_strings(fdt);
3316+ const char *p;
3317+
3318+ *allocated = 0;
3319+
3320+ p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
3321+ if (p)
3322+ return p - strtab;
3323+
3324+ *allocated = 1;
3325+
3326+ return fdt_add_string_(fdt, s);
3327+}
3328+
3329+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
3330+{
3331+ struct fdt_property *prop;
3332+ int nameoff;
3333+ int allocated;
3334+
3335+ FDT_SW_PROBE_STRUCT(fdt);
3336+
3337+ /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
3338+ if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
3339+ allocated = 1;
3340+ nameoff = fdt_add_string_(fdt, name);
3341+ } else {
3342+ nameoff = fdt_find_add_string_(fdt, name, &allocated);
3343+ }
3344+ if (nameoff == 0)
3345+ return -FDT_ERR_NOSPACE;
3346+
3347+ prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
3348+ if (! prop) {
3349+ if (allocated)
3350+ fdt_del_last_string_(fdt, name);
3351+ return -FDT_ERR_NOSPACE;
3352+ }
3353+
3354+ prop->tag = cpu_to_fdt32(FDT_PROP);
3355+ prop->nameoff = cpu_to_fdt32(nameoff);
3356+ prop->len = cpu_to_fdt32(len);
3357+ *valp = prop->data;
3358+ return 0;
3359+}
3360+
3361+int fdt_property(void *fdt, const char *name, const void *val, int len)
3362+{
3363+ void *ptr;
3364+ int ret;
3365+
3366+ ret = fdt_property_placeholder(fdt, name, len, &ptr);
3367+ if (ret)
3368+ return ret;
3369+ memcpy(ptr, val, len);
3370+ return 0;
3371+}
3372+
3373+int fdt_finish(void *fdt)
3374+{
3375+ char *p = (char *)fdt;
3376+ fdt32_t *end;
3377+ int oldstroffset, newstroffset;
3378+ uint32_t tag;
3379+ int offset, nextoffset;
3380+
3381+ FDT_SW_PROBE_STRUCT(fdt);
3382+
3383+ /* Add terminator */
3384+ end = fdt_grab_space_(fdt, sizeof(*end));
3385+ if (! end)
3386+ return -FDT_ERR_NOSPACE;
3387+ *end = cpu_to_fdt32(FDT_END);
3388+
3389+ /* Relocate the string table */
3390+ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
3391+ newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
3392+ memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
3393+ fdt_set_off_dt_strings(fdt, newstroffset);
3394+
3395+ /* Walk the structure, correcting string offsets */
3396+ offset = 0;
3397+ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
3398+ if (tag == FDT_PROP) {
3399+ struct fdt_property *prop =
3400+ fdt_offset_ptr_w_(fdt, offset);
3401+ int nameoff;
3402+
3403+ nameoff = fdt32_to_cpu(prop->nameoff);
3404+ nameoff += fdt_size_dt_strings(fdt);
3405+ prop->nameoff = cpu_to_fdt32(nameoff);
3406+ }
3407+ offset = nextoffset;
3408+ }
3409+ if (nextoffset < 0)
3410+ return nextoffset;
3411+
3412+ /* Finally, adjust the header */
3413+ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
3414+
3415+ /* And fix up fields that were keeping intermediate state. */
3416+ fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
3417+ fdt_set_magic(fdt, FDT_MAGIC);
3418+
3419+ return 0;
3420+}
3421diff --git a/common/libfdt/fdt_wip.c b/common/libfdt/fdt_wip.c
3422new file mode 100644
3423index 0000000..c2d7566
3424--- /dev/null
3425+++ b/common/libfdt/fdt_wip.c
3426@@ -0,0 +1,94 @@
3427+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
3428+/*
3429+ * libfdt - Flat Device Tree manipulation
3430+ * Copyright (C) 2006 David Gibson, IBM Corporation.
3431+ */
3432+#include "libfdt_env.h"
3433+
3434+#include <fdt.h>
3435+#include <libfdt.h>
3436+
3437+#include "libfdt_internal.h"
3438+
3439+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
3440+ const char *name, int namelen,
3441+ uint32_t idx, const void *val,
3442+ int len)
3443+{
3444+ void *propval;
3445+ int proplen;
3446+
3447+ propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
3448+ &proplen);
3449+ if (!propval)
3450+ return proplen;
3451+
3452+ if ((unsigned)proplen < (len + idx))
3453+ return -FDT_ERR_NOSPACE;
3454+
3455+ memcpy((char *)propval + idx, val, len);
3456+ return 0;
3457+}
3458+
3459+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
3460+ const void *val, int len)
3461+{
3462+ const void *propval;
3463+ int proplen;
3464+
3465+ propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
3466+ if (!propval)
3467+ return proplen;
3468+
3469+ if (proplen != len)
3470+ return -FDT_ERR_NOSPACE;
3471+
3472+ return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
3473+ strlen(name), 0,
3474+ val, len);
3475+}
3476+
3477+static void fdt_nop_region_(void *start, int len)
3478+{
3479+ fdt32_t *p;
3480+
3481+ for (p = start; (char *)p < ((char *)start + len); p++)
3482+ *p = cpu_to_fdt32(FDT_NOP);
3483+}
3484+
3485+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
3486+{
3487+ struct fdt_property *prop;
3488+ int len;
3489+
3490+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
3491+ if (!prop)
3492+ return len;
3493+
3494+ fdt_nop_region_(prop, len + sizeof(*prop));
3495+
3496+ return 0;
3497+}
3498+
3499+int fdt_node_end_offset_(void *fdt, int offset)
3500+{
3501+ int depth = 0;
3502+
3503+ while ((offset >= 0) && (depth >= 0))
3504+ offset = fdt_next_node(fdt, offset, &depth);
3505+
3506+ return offset;
3507+}
3508+
3509+int fdt_nop_node(void *fdt, int nodeoffset)
3510+{
3511+ int endoffset;
3512+
3513+ endoffset = fdt_node_end_offset_(fdt, nodeoffset);
3514+ if (endoffset < 0)
3515+ return endoffset;
3516+
3517+ fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
3518+ endoffset - nodeoffset);
3519+ return 0;
3520+}
3521diff --git a/common/libfdt/libfdt_internal.h b/common/libfdt/libfdt_internal.h
3522new file mode 100644
3523index 0000000..16bda19
3524--- /dev/null
3525+++ b/common/libfdt/libfdt_internal.h
3526@@ -0,0 +1,192 @@
3527+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
3528+#ifndef LIBFDT_INTERNAL_H
3529+#define LIBFDT_INTERNAL_H
3530+/*
3531+ * libfdt - Flat Device Tree manipulation
3532+ * Copyright (C) 2006 David Gibson, IBM Corporation.
3533+ */
3534+#include <fdt.h>
3535+
3536+#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
3537+#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
3538+
3539+int32_t fdt_ro_probe_(const void *fdt);
3540+#define FDT_RO_PROBE(fdt) \
3541+ { \
3542+ int32_t totalsize_; \
3543+ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
3544+ return totalsize_; \
3545+ }
3546+
3547+int fdt_check_node_offset_(const void *fdt, int offset);
3548+int fdt_check_prop_offset_(const void *fdt, int offset);
3549+const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
3550+int fdt_node_end_offset_(void *fdt, int nodeoffset);
3551+
3552+static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
3553+{
3554+ return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
3555+}
3556+
3557+static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
3558+{
3559+ return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
3560+}
3561+
3562+static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
3563+{
3564+ const struct fdt_reserve_entry *rsv_table =
3565+ (const struct fdt_reserve_entry *)
3566+ ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
3567+
3568+ return rsv_table + n;
3569+}
3570+static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
3571+{
3572+ return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
3573+}
3574+
3575+/*
3576+ * Internal helpers to access tructural elements of the device tree
3577+ * blob (rather than for exaple reading integers from within property
3578+ * values). We assume that we are either given a naturally aligned
3579+ * address for the platform or if we are not, we are on a platform
3580+ * where unaligned memory reads will be handled in a graceful manner.
3581+ * If not the external helpers fdtXX_ld() from libfdt.h can be used
3582+ * instead.
3583+ */
3584+static inline uint32_t fdt32_ld_(const fdt32_t *p)
3585+{
3586+ return fdt32_to_cpu(*p);
3587+}
3588+
3589+static inline uint64_t fdt64_ld_(const fdt64_t *p)
3590+{
3591+ return fdt64_to_cpu(*p);
3592+}
3593+
3594+#define FDT_SW_MAGIC (~FDT_MAGIC)
3595+
3596+/**********************************************************************/
3597+/* Checking controls */
3598+/**********************************************************************/
3599+
3600+#ifndef FDT_ASSUME_MASK
3601+#define FDT_ASSUME_MASK 0
3602+#endif
3603+
3604+/*
3605+ * Defines assumptions which can be enabled. Each of these can be enabled
3606+ * individually. For maximum safety, don't enable any assumptions!
3607+ *
3608+ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
3609+ * You should have another method of validating the device tree, such as a
3610+ * signature or hash check before using libfdt.
3611+ *
3612+ * For situations where security is not a concern it may be safe to enable
3613+ * ASSUME_SANE.
3614+ */
3615+enum {
3616+ /*
3617+ * This does essentially no checks. Only the latest device-tree
3618+ * version is correctly handled. Inconsistencies or errors in the device
3619+ * tree may cause undefined behaviour or crashes. Invalid parameters
3620+ * passed to libfdt may do the same.
3621+ *
3622+ * If an error occurs when modifying the tree it may leave the tree in
3623+ * an intermediate (but valid) state. As an example, adding a property
3624+ * where there is insufficient space may result in the property name
3625+ * being added to the string table even though the property itself is
3626+ * not added to the struct section.
3627+ *
3628+ * Only use this if you have a fully validated device tree with
3629+ * the latest supported version and wish to minimise code size.
3630+ */
3631+ ASSUME_PERFECT = 0xff,
3632+
3633+ /*
3634+ * This assumes that the device tree is sane. i.e. header metadata
3635+ * and basic hierarchy are correct.
3636+ *
3637+ * With this assumption enabled, normal device trees produced by libfdt
3638+ * and the compiler should be handled safely. Malicious device trees and
3639+ * complete garbage may cause libfdt to behave badly or crash. Truncated
3640+ * device trees (e.g. those only partially loaded) can also cause
3641+ * problems.
3642+ *
3643+ * Note: Only checks that relate exclusively to the device tree itself
3644+ * (not the parameters passed to libfdt) are disabled by this
3645+ * assumption. This includes checking headers, tags and the like.
3646+ */
3647+ ASSUME_VALID_DTB = 1 << 0,
3648+
3649+ /*
3650+ * This builds on ASSUME_VALID_DTB and further assumes that libfdt
3651+ * functions are called with valid parameters, i.e. not trigger
3652+ * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
3653+ * extensive checking of parameters and the device tree, making various
3654+ * assumptions about correctness.
3655+ *
3656+ * It doesn't make sense to enable this assumption unless
3657+ * ASSUME_VALID_DTB is also enabled.
3658+ */
3659+ ASSUME_VALID_INPUT = 1 << 1,
3660+
3661+ /*
3662+ * This disables checks for device-tree version and removes all code
3663+ * which handles older versions.
3664+ *
3665+ * Only enable this if you know you have a device tree with the latest
3666+ * version.
3667+ */
3668+ ASSUME_LATEST = 1 << 2,
3669+
3670+ /*
3671+ * This assumes that it is OK for a failed addition to the device tree,
3672+ * due to lack of space or some other problem, to skip any rollback
3673+ * steps (such as dropping the property name from the string table).
3674+ * This is safe to enable in most circumstances, even though it may
3675+ * leave the tree in a sub-optimal state.
3676+ */
3677+ ASSUME_NO_ROLLBACK = 1 << 3,
3678+
3679+ /*
3680+ * This assumes that the device tree components appear in a 'convenient'
3681+ * order, i.e. the memory reservation block first, then the structure
3682+ * block and finally the string block.
3683+ *
3684+ * This order is not specified by the device-tree specification,
3685+ * but is expected by libfdt. The device-tree compiler always created
3686+ * device trees with this order.
3687+ *
3688+ * This assumption disables a check in fdt_open_into() and removes the
3689+ * ability to fix the problem there. This is safe if you know that the
3690+ * device tree is correctly ordered. See fdt_blocks_misordered_().
3691+ */
3692+ ASSUME_LIBFDT_ORDER = 1 << 4,
3693+
3694+ /*
3695+ * This assumes that libfdt itself does not have any internal bugs. It
3696+ * drops certain checks that should never be needed unless libfdt has an
3697+ * undiscovered bug.
3698+ *
3699+ * This can generally be considered safe to enable.
3700+ */
3701+ ASSUME_LIBFDT_FLAWLESS = 1 << 5,
3702+};
3703+
3704+/**
3705+ * can_assume_() - check if a particular assumption is enabled
3706+ *
3707+ * @mask: Mask to check (ASSUME_...)
3708+ * @return true if that assumption is enabled, else false
3709+ */
3710+static inline bool can_assume_(int mask)
3711+{
3712+ return FDT_ASSUME_MASK & mask;
3713+}
3714+
3715+/** helper macros for checking assumptions */
3716+#define can_assume(_assume) can_assume_(ASSUME_ ## _assume)
3717+
3718+#endif /* LIBFDT_INTERNAL_H */
3719diff --git a/include/fdt.h b/include/fdt.h
3720new file mode 100644
3721index 0000000..f2e6880
3722--- /dev/null
3723+++ b/include/fdt.h
3724@@ -0,0 +1,66 @@
3725+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
3726+#ifndef FDT_H
3727+#define FDT_H
3728+/*
3729+ * libfdt - Flat Device Tree manipulation
3730+ * Copyright (C) 2006 David Gibson, IBM Corporation.
3731+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
3732+ */
3733+
3734+#ifndef __ASSEMBLY__
3735+
3736+struct fdt_header {
3737+ fdt32_t magic; /* magic word FDT_MAGIC */
3738+ fdt32_t totalsize; /* total size of DT block */
3739+ fdt32_t off_dt_struct; /* offset to structure */
3740+ fdt32_t off_dt_strings; /* offset to strings */
3741+ fdt32_t off_mem_rsvmap; /* offset to memory reserve map */
3742+ fdt32_t version; /* format version */
3743+ fdt32_t last_comp_version; /* last compatible version */
3744+
3745+ /* version 2 fields below */
3746+ fdt32_t boot_cpuid_phys; /* Which physical CPU id we're
3747+ booting on */
3748+ /* version 3 fields below */
3749+ fdt32_t size_dt_strings; /* size of the strings block */
3750+
3751+ /* version 17 fields below */
3752+ fdt32_t size_dt_struct; /* size of the structure block */
3753+};
3754+
3755+struct fdt_reserve_entry {
3756+ fdt64_t address;
3757+ fdt64_t size;
3758+};
3759+
3760+struct fdt_node_header {
3761+ fdt32_t tag;
3762+ char name[0];
3763+};
3764+
3765+struct fdt_property {
3766+ fdt32_t tag;
3767+ fdt32_t len;
3768+ fdt32_t nameoff;
3769+ char data[0];
3770+};
3771+
3772+#endif /* !__ASSEMBLY */
3773+
3774+#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
3775+#define FDT_TAGSIZE sizeof(fdt32_t)
3776+
3777+#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
3778+#define FDT_END_NODE 0x2 /* End node */
3779+#define FDT_PROP 0x3 /* Property: name off,
3780+ size, content */
3781+#define FDT_NOP 0x4 /* nop */
3782+#define FDT_END 0x9
3783+
3784+#define FDT_V1_SIZE (7*sizeof(fdt32_t))
3785+#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t))
3786+#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t))
3787+#define FDT_V16_SIZE FDT_V3_SIZE
3788+#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
3789+
3790+#endif /* FDT_H */
3791diff --git a/include/libfdt.h b/include/libfdt.h
3792new file mode 100644
3793index 0000000..a7f432c
3794--- /dev/null
3795+++ b/include/libfdt.h
3796@@ -0,0 +1,2147 @@
3797+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
3798+#ifndef LIBFDT_H
3799+#define LIBFDT_H
3800+/*
3801+ * libfdt - Flat Device Tree manipulation
3802+ * Copyright (C) 2006 David Gibson, IBM Corporation.
3803+ */
3804+
3805+#include <libfdt_env.h>
3806+#include <fdt.h>
3807+
3808+#ifdef __cplusplus
3809+extern "C" {
3810+#endif
3811+
3812+#define FDT_FIRST_SUPPORTED_VERSION 0x02
3813+#define FDT_LAST_COMPATIBLE_VERSION 0x10
3814+#define FDT_LAST_SUPPORTED_VERSION 0x11
3815+
3816+/* Error codes: informative error codes */
3817+#define FDT_ERR_NOTFOUND 1
3818+ /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
3819+#define FDT_ERR_EXISTS 2
3820+ /* FDT_ERR_EXISTS: Attempted to create a node or property which
3821+ * already exists */
3822+#define FDT_ERR_NOSPACE 3
3823+ /* FDT_ERR_NOSPACE: Operation needed to expand the device
3824+ * tree, but its buffer did not have sufficient space to
3825+ * contain the expanded tree. Use fdt_open_into() to move the
3826+ * device tree to a buffer with more space. */
3827+
3828+/* Error codes: codes for bad parameters */
3829+#define FDT_ERR_BADOFFSET 4
3830+ /* FDT_ERR_BADOFFSET: Function was passed a structure block
3831+ * offset which is out-of-bounds, or which points to an
3832+ * unsuitable part of the structure for the operation. */
3833+#define FDT_ERR_BADPATH 5
3834+ /* FDT_ERR_BADPATH: Function was passed a badly formatted path
3835+ * (e.g. missing a leading / for a function which requires an
3836+ * absolute path) */
3837+#define FDT_ERR_BADPHANDLE 6
3838+ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
3839+ * This can be caused either by an invalid phandle property
3840+ * length, or the phandle value was either 0 or -1, which are
3841+ * not permitted. */
3842+#define FDT_ERR_BADSTATE 7
3843+ /* FDT_ERR_BADSTATE: Function was passed an incomplete device
3844+ * tree created by the sequential-write functions, which is
3845+ * not sufficiently complete for the requested operation. */
3846+
3847+/* Error codes: codes for bad device tree blobs */
3848+#define FDT_ERR_TRUNCATED 8
3849+ /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
3850+ * terminated (overflows, goes outside allowed bounds, or
3851+ * isn't properly terminated). */
3852+#define FDT_ERR_BADMAGIC 9
3853+ /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
3854+ * device tree at all - it is missing the flattened device
3855+ * tree magic number. */
3856+#define FDT_ERR_BADVERSION 10
3857+ /* FDT_ERR_BADVERSION: Given device tree has a version which
3858+ * can't be handled by the requested operation. For
3859+ * read-write functions, this may mean that fdt_open_into() is
3860+ * required to convert the tree to the expected version. */
3861+#define FDT_ERR_BADSTRUCTURE 11
3862+ /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
3863+ * structure block or other serious error (e.g. misnested
3864+ * nodes, or subnodes preceding properties). */
3865+#define FDT_ERR_BADLAYOUT 12
3866+ /* FDT_ERR_BADLAYOUT: For read-write functions, the given
3867+ * device tree has it's sub-blocks in an order that the
3868+ * function can't handle (memory reserve map, then structure,
3869+ * then strings). Use fdt_open_into() to reorganize the tree
3870+ * into a form suitable for the read-write operations. */
3871+
3872+/* "Can't happen" error indicating a bug in libfdt */
3873+#define FDT_ERR_INTERNAL 13
3874+ /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
3875+ * Should never be returned, if it is, it indicates a bug in
3876+ * libfdt itself. */
3877+
3878+/* Errors in device tree content */
3879+#define FDT_ERR_BADNCELLS 14
3880+ /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
3881+ * or similar property with a bad format or value */
3882+
3883+#define FDT_ERR_BADVALUE 15
3884+ /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
3885+ * value. For example: a property expected to contain a string list
3886+ * is not NUL-terminated within the length of its value. */
3887+
3888+#define FDT_ERR_BADOVERLAY 16
3889+ /* FDT_ERR_BADOVERLAY: The device tree overlay, while
3890+ * correctly structured, cannot be applied due to some
3891+ * unexpected or missing value, property or node. */
3892+
3893+#define FDT_ERR_NOPHANDLES 17
3894+ /* FDT_ERR_NOPHANDLES: The device tree doesn't have any
3895+ * phandle available anymore without causing an overflow */
3896+
3897+#define FDT_ERR_BADFLAGS 18
3898+ /* FDT_ERR_BADFLAGS: The function was passed a flags field that
3899+ * contains invalid flags or an invalid combination of flags. */
3900+
3901+#define FDT_ERR_ALIGNMENT 19
3902+ /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
3903+ * aligned. */
3904+
3905+#define FDT_ERR_MAX 19
3906+
3907+/* constants */
3908+#define FDT_MAX_PHANDLE 0xfffffffe
3909+ /* Valid values for phandles range from 1 to 2^32-2. */
3910+
3911+/**********************************************************************/
3912+/* Low-level functions (you probably don't need these) */
3913+/**********************************************************************/
3914+
3915+#ifndef SWIG /* This function is not useful in Python */
3916+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
3917+#endif
3918+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
3919+{
3920+ return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
3921+}
3922+
3923+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
3924+
3925+/*
3926+ * External helpers to access words from a device tree blob. They're built
3927+ * to work even with unaligned pointers on platforms (such as ARMv5) that don't
3928+ * like unaligned loads and stores.
3929+ */
3930+static inline uint16_t fdt16_ld(const fdt16_t *p)
3931+{
3932+ const uint8_t *bp = (const uint8_t *)p;
3933+
3934+ return ((uint16_t)bp[0] << 8) | bp[1];
3935+}
3936+
3937+static inline uint32_t fdt32_ld(const fdt32_t *p)
3938+{
3939+ const uint8_t *bp = (const uint8_t *)p;
3940+
3941+ return ((uint32_t)bp[0] << 24)
3942+ | ((uint32_t)bp[1] << 16)
3943+ | ((uint32_t)bp[2] << 8)
3944+ | bp[3];
3945+}
3946+
3947+static inline void fdt32_st(void *property, uint32_t value)
3948+{
3949+ uint8_t *bp = (uint8_t *)property;
3950+
3951+ bp[0] = value >> 24;
3952+ bp[1] = (value >> 16) & 0xff;
3953+ bp[2] = (value >> 8) & 0xff;
3954+ bp[3] = value & 0xff;
3955+}
3956+
3957+static inline uint64_t fdt64_ld(const fdt64_t *p)
3958+{
3959+ const uint8_t *bp = (const uint8_t *)p;
3960+
3961+ return ((uint64_t)bp[0] << 56)
3962+ | ((uint64_t)bp[1] << 48)
3963+ | ((uint64_t)bp[2] << 40)
3964+ | ((uint64_t)bp[3] << 32)
3965+ | ((uint64_t)bp[4] << 24)
3966+ | ((uint64_t)bp[5] << 16)
3967+ | ((uint64_t)bp[6] << 8)
3968+ | bp[7];
3969+}
3970+
3971+static inline void fdt64_st(void *property, uint64_t value)
3972+{
3973+ uint8_t *bp = (uint8_t *)property;
3974+
3975+ bp[0] = value >> 56;
3976+ bp[1] = (value >> 48) & 0xff;
3977+ bp[2] = (value >> 40) & 0xff;
3978+ bp[3] = (value >> 32) & 0xff;
3979+ bp[4] = (value >> 24) & 0xff;
3980+ bp[5] = (value >> 16) & 0xff;
3981+ bp[6] = (value >> 8) & 0xff;
3982+ bp[7] = value & 0xff;
3983+}
3984+
3985+/**********************************************************************/
3986+/* Traversal functions */
3987+/**********************************************************************/
3988+
3989+int fdt_next_node(const void *fdt, int offset, int *depth);
3990+
3991+/**
3992+ * fdt_first_subnode() - get offset of first direct subnode
3993+ * @fdt: FDT blob
3994+ * @offset: Offset of node to check
3995+ *
3996+ * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
3997+ */
3998+int fdt_first_subnode(const void *fdt, int offset);
3999+
4000+/**
4001+ * fdt_next_subnode() - get offset of next direct subnode
4002+ * @fdt: FDT blob
4003+ * @offset: Offset of previous subnode
4004+ *
4005+ * After first calling fdt_first_subnode(), call this function repeatedly to
4006+ * get direct subnodes of a parent node.
4007+ *
4008+ * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
4009+ * subnodes
4010+ */
4011+int fdt_next_subnode(const void *fdt, int offset);
4012+
4013+/**
4014+ * fdt_for_each_subnode - iterate over all subnodes of a parent
4015+ *
4016+ * @node: child node (int, lvalue)
4017+ * @fdt: FDT blob (const void *)
4018+ * @parent: parent node (int)
4019+ *
4020+ * This is actually a wrapper around a for loop and would be used like so:
4021+ *
4022+ * fdt_for_each_subnode(node, fdt, parent) {
4023+ * Use node
4024+ * ...
4025+ * }
4026+ *
4027+ * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
4028+ * Error handling
4029+ * }
4030+ *
4031+ * Note that this is implemented as a macro and @node is used as
4032+ * iterator in the loop. The parent variable be constant or even a
4033+ * literal.
4034+ */
4035+#define fdt_for_each_subnode(node, fdt, parent) \
4036+ for (node = fdt_first_subnode(fdt, parent); \
4037+ node >= 0; \
4038+ node = fdt_next_subnode(fdt, node))
4039+
4040+/**********************************************************************/
4041+/* General functions */
4042+/**********************************************************************/
4043+#define fdt_get_header(fdt, field) \
4044+ (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
4045+#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
4046+#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
4047+#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
4048+#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
4049+#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
4050+#define fdt_version(fdt) (fdt_get_header(fdt, version))
4051+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
4052+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
4053+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
4054+#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
4055+
4056+#define fdt_set_hdr_(name) \
4057+ static inline void fdt_set_##name(void *fdt, uint32_t val) \
4058+ { \
4059+ struct fdt_header *fdth = (struct fdt_header *)fdt; \
4060+ fdth->name = cpu_to_fdt32(val); \
4061+ }
4062+fdt_set_hdr_(magic);
4063+fdt_set_hdr_(totalsize);
4064+fdt_set_hdr_(off_dt_struct);
4065+fdt_set_hdr_(off_dt_strings);
4066+fdt_set_hdr_(off_mem_rsvmap);
4067+fdt_set_hdr_(version);
4068+fdt_set_hdr_(last_comp_version);
4069+fdt_set_hdr_(boot_cpuid_phys);
4070+fdt_set_hdr_(size_dt_strings);
4071+fdt_set_hdr_(size_dt_struct);
4072+#undef fdt_set_hdr_
4073+
4074+/**
4075+ * fdt_header_size - return the size of the tree's header
4076+ * @fdt: pointer to a flattened device tree
4077+ *
4078+ * Return: size of DTB header in bytes
4079+ */
4080+size_t fdt_header_size(const void *fdt);
4081+
4082+/**
4083+ * fdt_header_size_ - internal function to get header size from a version number
4084+ * @version: devicetree version number
4085+ *
4086+ * Return: size of DTB header in bytes
4087+ */
4088+size_t fdt_header_size_(uint32_t version);
4089+
4090+/**
4091+ * fdt_check_header - sanity check a device tree header
4092+ * @fdt: pointer to data which might be a flattened device tree
4093+ *
4094+ * fdt_check_header() checks that the given buffer contains what
4095+ * appears to be a flattened device tree, and that the header contains
4096+ * valid information (to the extent that can be determined from the
4097+ * header alone).
4098+ *
4099+ * returns:
4100+ * 0, if the buffer appears to contain a valid device tree
4101+ * -FDT_ERR_BADMAGIC,
4102+ * -FDT_ERR_BADVERSION,
4103+ * -FDT_ERR_BADSTATE,
4104+ * -FDT_ERR_TRUNCATED, standard meanings, as above
4105+ */
4106+int fdt_check_header(const void *fdt);
4107+
4108+/**
4109+ * fdt_move - move a device tree around in memory
4110+ * @fdt: pointer to the device tree to move
4111+ * @buf: pointer to memory where the device is to be moved
4112+ * @bufsize: size of the memory space at buf
4113+ *
4114+ * fdt_move() relocates, if possible, the device tree blob located at
4115+ * fdt to the buffer at buf of size bufsize. The buffer may overlap
4116+ * with the existing device tree blob at fdt. Therefore,
4117+ * fdt_move(fdt, fdt, fdt_totalsize(fdt))
4118+ * should always succeed.
4119+ *
4120+ * returns:
4121+ * 0, on success
4122+ * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
4123+ * -FDT_ERR_BADMAGIC,
4124+ * -FDT_ERR_BADVERSION,
4125+ * -FDT_ERR_BADSTATE, standard meanings
4126+ */
4127+int fdt_move(const void *fdt, void *buf, int bufsize);
4128+
4129+/**********************************************************************/
4130+/* Read-only functions */
4131+/**********************************************************************/
4132+
4133+int fdt_check_full(const void *fdt, size_t bufsize);
4134+
4135+/**
4136+ * fdt_get_string - retrieve a string from the strings block of a device tree
4137+ * @fdt: pointer to the device tree blob
4138+ * @stroffset: offset of the string within the strings block (native endian)
4139+ * @lenp: optional pointer to return the string's length
4140+ *
4141+ * fdt_get_string() retrieves a pointer to a single string from the
4142+ * strings block of the device tree blob at fdt, and optionally also
4143+ * returns the string's length in *lenp.
4144+ *
4145+ * returns:
4146+ * a pointer to the string, on success
4147+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
4148+ */
4149+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
4150+
4151+/**
4152+ * fdt_string - retrieve a string from the strings block of a device tree
4153+ * @fdt: pointer to the device tree blob
4154+ * @stroffset: offset of the string within the strings block (native endian)
4155+ *
4156+ * fdt_string() retrieves a pointer to a single string from the
4157+ * strings block of the device tree blob at fdt.
4158+ *
4159+ * returns:
4160+ * a pointer to the string, on success
4161+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
4162+ */
4163+const char *fdt_string(const void *fdt, int stroffset);
4164+
4165+/**
4166+ * fdt_find_max_phandle - find and return the highest phandle in a tree
4167+ * @fdt: pointer to the device tree blob
4168+ * @phandle: return location for the highest phandle value found in the tree
4169+ *
4170+ * fdt_find_max_phandle() finds the highest phandle value in the given device
4171+ * tree. The value returned in @phandle is only valid if the function returns
4172+ * success.
4173+ *
4174+ * returns:
4175+ * 0 on success or a negative error code on failure
4176+ */
4177+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
4178+
4179+/**
4180+ * fdt_get_max_phandle - retrieves the highest phandle in a tree
4181+ * @fdt: pointer to the device tree blob
4182+ *
4183+ * fdt_get_max_phandle retrieves the highest phandle in the given
4184+ * device tree. This will ignore badly formatted phandles, or phandles
4185+ * with a value of 0 or -1.
4186+ *
4187+ * This function is deprecated in favour of fdt_find_max_phandle().
4188+ *
4189+ * returns:
4190+ * the highest phandle on success
4191+ * 0, if no phandle was found in the device tree
4192+ * -1, if an error occurred
4193+ */
4194+static inline uint32_t fdt_get_max_phandle(const void *fdt)
4195+{
4196+ uint32_t phandle;
4197+ int err;
4198+
4199+ err = fdt_find_max_phandle(fdt, &phandle);
4200+ if (err < 0)
4201+ return (uint32_t)-1;
4202+
4203+ return phandle;
4204+}
4205+
4206+/**
4207+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
4208+ * @fdt: pointer to the device tree blob
4209+ * @phandle: return location for the new phandle
4210+ *
4211+ * Walks the device tree blob and looks for the highest phandle value. On
4212+ * success, the new, unused phandle value (one higher than the previously
4213+ * highest phandle value in the device tree blob) will be returned in the
4214+ * @phandle parameter.
4215+ *
4216+ * Return: 0 on success or a negative error-code on failure
4217+ */
4218+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
4219+
4220+/**
4221+ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
4222+ * @fdt: pointer to the device tree blob
4223+ *
4224+ * Returns the number of entries in the device tree blob's memory
4225+ * reservation map. This does not include the terminating 0,0 entry
4226+ * or any other (0,0) entries reserved for expansion.
4227+ *
4228+ * returns:
4229+ * the number of entries
4230+ */
4231+int fdt_num_mem_rsv(const void *fdt);
4232+
4233+/**
4234+ * fdt_get_mem_rsv - retrieve one memory reserve map entry
4235+ * @fdt: pointer to the device tree blob
4236+ * @n: index of reserve map entry
4237+ * @address: pointer to 64-bit variable to hold the start address
4238+ * @size: pointer to 64-bit variable to hold the size of the entry
4239+ *
4240+ * On success, @address and @size will contain the address and size of
4241+ * the n-th reserve map entry from the device tree blob, in
4242+ * native-endian format.
4243+ *
4244+ * returns:
4245+ * 0, on success
4246+ * -FDT_ERR_BADMAGIC,
4247+ * -FDT_ERR_BADVERSION,
4248+ * -FDT_ERR_BADSTATE, standard meanings
4249+ */
4250+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
4251+
4252+/**
4253+ * fdt_subnode_offset_namelen - find a subnode based on substring
4254+ * @fdt: pointer to the device tree blob
4255+ * @parentoffset: structure block offset of a node
4256+ * @name: name of the subnode to locate
4257+ * @namelen: number of characters of name to consider
4258+ *
4259+ * Identical to fdt_subnode_offset(), but only examine the first
4260+ * namelen characters of name for matching the subnode name. This is
4261+ * useful for finding subnodes based on a portion of a larger string,
4262+ * such as a full path.
4263+ *
4264+ * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
4265+ */
4266+#ifndef SWIG /* Not available in Python */
4267+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
4268+ const char *name, int namelen);
4269+#endif
4270+/**
4271+ * fdt_subnode_offset - find a subnode of a given node
4272+ * @fdt: pointer to the device tree blob
4273+ * @parentoffset: structure block offset of a node
4274+ * @name: name of the subnode to locate
4275+ *
4276+ * fdt_subnode_offset() finds a subnode of the node at structure block
4277+ * offset parentoffset with the given name. name may include a unit
4278+ * address, in which case fdt_subnode_offset() will find the subnode
4279+ * with that unit address, or the unit address may be omitted, in
4280+ * which case fdt_subnode_offset() will find an arbitrary subnode
4281+ * whose name excluding unit address matches the given name.
4282+ *
4283+ * returns:
4284+ * structure block offset of the requested subnode (>=0), on success
4285+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
4286+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
4287+ * tag
4288+ * -FDT_ERR_BADMAGIC,
4289+ * -FDT_ERR_BADVERSION,
4290+ * -FDT_ERR_BADSTATE,
4291+ * -FDT_ERR_BADSTRUCTURE,
4292+ * -FDT_ERR_TRUNCATED, standard meanings.
4293+ */
4294+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
4295+
4296+/**
4297+ * fdt_path_offset_namelen - find a tree node by its full path
4298+ * @fdt: pointer to the device tree blob
4299+ * @path: full path of the node to locate
4300+ * @namelen: number of characters of path to consider
4301+ *
4302+ * Identical to fdt_path_offset(), but only consider the first namelen
4303+ * characters of path as the path name.
4304+ *
4305+ * Return: offset of the node or negative libfdt error value otherwise
4306+ */
4307+#ifndef SWIG /* Not available in Python */
4308+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
4309+#endif
4310+
4311+/**
4312+ * fdt_path_offset - find a tree node by its full path
4313+ * @fdt: pointer to the device tree blob
4314+ * @path: full path of the node to locate
4315+ *
4316+ * fdt_path_offset() finds a node of a given path in the device tree.
4317+ * Each path component may omit the unit address portion, but the
4318+ * results of this are undefined if any such path component is
4319+ * ambiguous (that is if there are multiple nodes at the relevant
4320+ * level matching the given component, differentiated only by unit
4321+ * address).
4322+ *
4323+ * returns:
4324+ * structure block offset of the node with the requested path (>=0), on
4325+ * success
4326+ * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
4327+ * -FDT_ERR_NOTFOUND, if the requested node does not exist
4328+ * -FDT_ERR_BADMAGIC,
4329+ * -FDT_ERR_BADVERSION,
4330+ * -FDT_ERR_BADSTATE,
4331+ * -FDT_ERR_BADSTRUCTURE,
4332+ * -FDT_ERR_TRUNCATED, standard meanings.
4333+ */
4334+int fdt_path_offset(const void *fdt, const char *path);
4335+
4336+/**
4337+ * fdt_get_name - retrieve the name of a given node
4338+ * @fdt: pointer to the device tree blob
4339+ * @nodeoffset: structure block offset of the starting node
4340+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4341+ *
4342+ * fdt_get_name() retrieves the name (including unit address) of the
4343+ * device tree node at structure block offset nodeoffset. If lenp is
4344+ * non-NULL, the length of this name is also returned, in the integer
4345+ * pointed to by lenp.
4346+ *
4347+ * returns:
4348+ * pointer to the node's name, on success
4349+ * If lenp is non-NULL, *lenp contains the length of that name
4350+ * (>=0)
4351+ * NULL, on error
4352+ * if lenp is non-NULL *lenp contains an error code (<0):
4353+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
4354+ * tag
4355+ * -FDT_ERR_BADMAGIC,
4356+ * -FDT_ERR_BADVERSION,
4357+ * -FDT_ERR_BADSTATE, standard meanings
4358+ */
4359+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
4360+
4361+/**
4362+ * fdt_first_property_offset - find the offset of a node's first property
4363+ * @fdt: pointer to the device tree blob
4364+ * @nodeoffset: structure block offset of a node
4365+ *
4366+ * fdt_first_property_offset() finds the first property of the node at
4367+ * the given structure block offset.
4368+ *
4369+ * returns:
4370+ * structure block offset of the property (>=0), on success
4371+ * -FDT_ERR_NOTFOUND, if the requested node has no properties
4372+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
4373+ * -FDT_ERR_BADMAGIC,
4374+ * -FDT_ERR_BADVERSION,
4375+ * -FDT_ERR_BADSTATE,
4376+ * -FDT_ERR_BADSTRUCTURE,
4377+ * -FDT_ERR_TRUNCATED, standard meanings.
4378+ */
4379+int fdt_first_property_offset(const void *fdt, int nodeoffset);
4380+
4381+/**
4382+ * fdt_next_property_offset - step through a node's properties
4383+ * @fdt: pointer to the device tree blob
4384+ * @offset: structure block offset of a property
4385+ *
4386+ * fdt_next_property_offset() finds the property immediately after the
4387+ * one at the given structure block offset. This will be a property
4388+ * of the same node as the given property.
4389+ *
4390+ * returns:
4391+ * structure block offset of the next property (>=0), on success
4392+ * -FDT_ERR_NOTFOUND, if the given property is the last in its node
4393+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
4394+ * -FDT_ERR_BADMAGIC,
4395+ * -FDT_ERR_BADVERSION,
4396+ * -FDT_ERR_BADSTATE,
4397+ * -FDT_ERR_BADSTRUCTURE,
4398+ * -FDT_ERR_TRUNCATED, standard meanings.
4399+ */
4400+int fdt_next_property_offset(const void *fdt, int offset);
4401+
4402+/**
4403+ * fdt_for_each_property_offset - iterate over all properties of a node
4404+ *
4405+ * @property: property offset (int, lvalue)
4406+ * @fdt: FDT blob (const void *)
4407+ * @node: node offset (int)
4408+ *
4409+ * This is actually a wrapper around a for loop and would be used like so:
4410+ *
4411+ * fdt_for_each_property_offset(property, fdt, node) {
4412+ * Use property
4413+ * ...
4414+ * }
4415+ *
4416+ * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
4417+ * Error handling
4418+ * }
4419+ *
4420+ * Note that this is implemented as a macro and property is used as
4421+ * iterator in the loop. The node variable can be constant or even a
4422+ * literal.
4423+ */
4424+#define fdt_for_each_property_offset(property, fdt, node) \
4425+ for (property = fdt_first_property_offset(fdt, node); \
4426+ property >= 0; \
4427+ property = fdt_next_property_offset(fdt, property))
4428+
4429+/**
4430+ * fdt_get_property_by_offset - retrieve the property at a given offset
4431+ * @fdt: pointer to the device tree blob
4432+ * @offset: offset of the property to retrieve
4433+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4434+ *
4435+ * fdt_get_property_by_offset() retrieves a pointer to the
4436+ * fdt_property structure within the device tree blob at the given
4437+ * offset. If lenp is non-NULL, the length of the property value is
4438+ * also returned, in the integer pointed to by lenp.
4439+ *
4440+ * Note that this code only works on device tree versions >= 16. fdt_getprop()
4441+ * works on all versions.
4442+ *
4443+ * returns:
4444+ * pointer to the structure representing the property
4445+ * if lenp is non-NULL, *lenp contains the length of the property
4446+ * value (>=0)
4447+ * NULL, on error
4448+ * if lenp is non-NULL, *lenp contains an error code (<0):
4449+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
4450+ * -FDT_ERR_BADMAGIC,
4451+ * -FDT_ERR_BADVERSION,
4452+ * -FDT_ERR_BADSTATE,
4453+ * -FDT_ERR_BADSTRUCTURE,
4454+ * -FDT_ERR_TRUNCATED, standard meanings
4455+ */
4456+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
4457+ int offset,
4458+ int *lenp);
4459+
4460+/**
4461+ * fdt_get_property_namelen - find a property based on substring
4462+ * @fdt: pointer to the device tree blob
4463+ * @nodeoffset: offset of the node whose property to find
4464+ * @name: name of the property to find
4465+ * @namelen: number of characters of name to consider
4466+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4467+ *
4468+ * Identical to fdt_get_property(), but only examine the first namelen
4469+ * characters of name for matching the property name.
4470+ *
4471+ * Return: pointer to the structure representing the property, or NULL
4472+ * if not found
4473+ */
4474+#ifndef SWIG /* Not available in Python */
4475+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
4476+ int nodeoffset,
4477+ const char *name,
4478+ int namelen, int *lenp);
4479+#endif
4480+
4481+/**
4482+ * fdt_get_property - find a given property in a given node
4483+ * @fdt: pointer to the device tree blob
4484+ * @nodeoffset: offset of the node whose property to find
4485+ * @name: name of the property to find
4486+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4487+ *
4488+ * fdt_get_property() retrieves a pointer to the fdt_property
4489+ * structure within the device tree blob corresponding to the property
4490+ * named 'name' of the node at offset nodeoffset. If lenp is
4491+ * non-NULL, the length of the property value is also returned, in the
4492+ * integer pointed to by lenp.
4493+ *
4494+ * returns:
4495+ * pointer to the structure representing the property
4496+ * if lenp is non-NULL, *lenp contains the length of the property
4497+ * value (>=0)
4498+ * NULL, on error
4499+ * if lenp is non-NULL, *lenp contains an error code (<0):
4500+ * -FDT_ERR_NOTFOUND, node does not have named property
4501+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
4502+ * tag
4503+ * -FDT_ERR_BADMAGIC,
4504+ * -FDT_ERR_BADVERSION,
4505+ * -FDT_ERR_BADSTATE,
4506+ * -FDT_ERR_BADSTRUCTURE,
4507+ * -FDT_ERR_TRUNCATED, standard meanings
4508+ */
4509+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
4510+ const char *name, int *lenp);
4511+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
4512+ const char *name,
4513+ int *lenp)
4514+{
4515+ return (struct fdt_property *)(uintptr_t)
4516+ fdt_get_property(fdt, nodeoffset, name, lenp);
4517+}
4518+
4519+/**
4520+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
4521+ * @fdt: pointer to the device tree blob
4522+ * @offset: offset of the property to read
4523+ * @namep: pointer to a string variable (will be overwritten) or NULL
4524+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4525+ *
4526+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
4527+ * property at structure block offset 'offset' (this will be a pointer
4528+ * to within the device blob itself, not a copy of the value). If
4529+ * lenp is non-NULL, the length of the property value is also
4530+ * returned, in the integer pointed to by lenp. If namep is non-NULL,
4531+ * the property's namne will also be returned in the char * pointed to
4532+ * by namep (this will be a pointer to within the device tree's string
4533+ * block, not a new copy of the name).
4534+ *
4535+ * returns:
4536+ * pointer to the property's value
4537+ * if lenp is non-NULL, *lenp contains the length of the property
4538+ * value (>=0)
4539+ * if namep is non-NULL *namep contiains a pointer to the property
4540+ * name.
4541+ * NULL, on error
4542+ * if lenp is non-NULL, *lenp contains an error code (<0):
4543+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
4544+ * -FDT_ERR_BADMAGIC,
4545+ * -FDT_ERR_BADVERSION,
4546+ * -FDT_ERR_BADSTATE,
4547+ * -FDT_ERR_BADSTRUCTURE,
4548+ * -FDT_ERR_TRUNCATED, standard meanings
4549+ */
4550+#ifndef SWIG /* This function is not useful in Python */
4551+const void *fdt_getprop_by_offset(const void *fdt, int offset,
4552+ const char **namep, int *lenp);
4553+#endif
4554+
4555+/**
4556+ * fdt_getprop_namelen - get property value based on substring
4557+ * @fdt: pointer to the device tree blob
4558+ * @nodeoffset: offset of the node whose property to find
4559+ * @name: name of the property to find
4560+ * @namelen: number of characters of name to consider
4561+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4562+ *
4563+ * Identical to fdt_getprop(), but only examine the first namelen
4564+ * characters of name for matching the property name.
4565+ *
4566+ * Return: pointer to the property's value or NULL on error
4567+ */
4568+#ifndef SWIG /* Not available in Python */
4569+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
4570+ const char *name, int namelen, int *lenp);
4571+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
4572+ const char *name, int namelen,
4573+ int *lenp)
4574+{
4575+ return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
4576+ namelen, lenp);
4577+}
4578+#endif
4579+
4580+/**
4581+ * fdt_getprop - retrieve the value of a given property
4582+ * @fdt: pointer to the device tree blob
4583+ * @nodeoffset: offset of the node whose property to find
4584+ * @name: name of the property to find
4585+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
4586+ *
4587+ * fdt_getprop() retrieves a pointer to the value of the property
4588+ * named @name of the node at offset @nodeoffset (this will be a
4589+ * pointer to within the device blob itself, not a copy of the value).
4590+ * If @lenp is non-NULL, the length of the property value is also
4591+ * returned, in the integer pointed to by @lenp.
4592+ *
4593+ * returns:
4594+ * pointer to the property's value
4595+ * if lenp is non-NULL, *lenp contains the length of the property
4596+ * value (>=0)
4597+ * NULL, on error
4598+ * if lenp is non-NULL, *lenp contains an error code (<0):
4599+ * -FDT_ERR_NOTFOUND, node does not have named property
4600+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
4601+ * tag
4602+ * -FDT_ERR_BADMAGIC,
4603+ * -FDT_ERR_BADVERSION,
4604+ * -FDT_ERR_BADSTATE,
4605+ * -FDT_ERR_BADSTRUCTURE,
4606+ * -FDT_ERR_TRUNCATED, standard meanings
4607+ */
4608+const void *fdt_getprop(const void *fdt, int nodeoffset,
4609+ const char *name, int *lenp);
4610+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
4611+ const char *name, int *lenp)
4612+{
4613+ return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
4614+}
4615+
4616+/**
4617+ * fdt_get_phandle - retrieve the phandle of a given node
4618+ * @fdt: pointer to the device tree blob
4619+ * @nodeoffset: structure block offset of the node
4620+ *
4621+ * fdt_get_phandle() retrieves the phandle of the device tree node at
4622+ * structure block offset nodeoffset.
4623+ *
4624+ * returns:
4625+ * the phandle of the node at nodeoffset, on success (!= 0, != -1)
4626+ * 0, if the node has no phandle, or another error occurs
4627+ */
4628+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
4629+
4630+/**
4631+ * fdt_get_alias_namelen - get alias based on substring
4632+ * @fdt: pointer to the device tree blob
4633+ * @name: name of the alias th look up
4634+ * @namelen: number of characters of name to consider
4635+ *
4636+ * Identical to fdt_get_alias(), but only examine the first @namelen
4637+ * characters of @name for matching the alias name.
4638+ *
4639+ * Return: a pointer to the expansion of the alias named @name, if it exists,
4640+ * NULL otherwise
4641+ */
4642+#ifndef SWIG /* Not available in Python */
4643+const char *fdt_get_alias_namelen(const void *fdt,
4644+ const char *name, int namelen);
4645+#endif
4646+
4647+/**
4648+ * fdt_get_alias - retrieve the path referenced by a given alias
4649+ * @fdt: pointer to the device tree blob
4650+ * @name: name of the alias th look up
4651+ *
4652+ * fdt_get_alias() retrieves the value of a given alias. That is, the
4653+ * value of the property named @name in the node /aliases.
4654+ *
4655+ * returns:
4656+ * a pointer to the expansion of the alias named 'name', if it exists
4657+ * NULL, if the given alias or the /aliases node does not exist
4658+ */
4659+const char *fdt_get_alias(const void *fdt, const char *name);
4660+
4661+/**
4662+ * fdt_get_path - determine the full path of a node
4663+ * @fdt: pointer to the device tree blob
4664+ * @nodeoffset: offset of the node whose path to find
4665+ * @buf: character buffer to contain the returned path (will be overwritten)
4666+ * @buflen: size of the character buffer at buf
4667+ *
4668+ * fdt_get_path() computes the full path of the node at offset
4669+ * nodeoffset, and records that path in the buffer at buf.
4670+ *
4671+ * NOTE: This function is expensive, as it must scan the device tree
4672+ * structure from the start to nodeoffset.
4673+ *
4674+ * returns:
4675+ * 0, on success
4676+ * buf contains the absolute path of the node at
4677+ * nodeoffset, as a NUL-terminated string.
4678+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
4679+ * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
4680+ * characters and will not fit in the given buffer.
4681+ * -FDT_ERR_BADMAGIC,
4682+ * -FDT_ERR_BADVERSION,
4683+ * -FDT_ERR_BADSTATE,
4684+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4685+ */
4686+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
4687+
4688+/**
4689+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
4690+ * @fdt: pointer to the device tree blob
4691+ * @nodeoffset: offset of the node whose parent to find
4692+ * @supernodedepth: depth of the ancestor to find
4693+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
4694+ *
4695+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
4696+ * at a specific depth from the root (where the root itself has depth
4697+ * 0, its immediate subnodes depth 1 and so forth). So
4698+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
4699+ * will always return 0, the offset of the root node. If the node at
4700+ * nodeoffset has depth D, then:
4701+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
4702+ * will return nodeoffset itself.
4703+ *
4704+ * NOTE: This function is expensive, as it must scan the device tree
4705+ * structure from the start to nodeoffset.
4706+ *
4707+ * returns:
4708+ * structure block offset of the node at node offset's ancestor
4709+ * of depth supernodedepth (>=0), on success
4710+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
4711+ * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
4712+ * nodeoffset
4713+ * -FDT_ERR_BADMAGIC,
4714+ * -FDT_ERR_BADVERSION,
4715+ * -FDT_ERR_BADSTATE,
4716+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4717+ */
4718+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
4719+ int supernodedepth, int *nodedepth);
4720+
4721+/**
4722+ * fdt_node_depth - find the depth of a given node
4723+ * @fdt: pointer to the device tree blob
4724+ * @nodeoffset: offset of the node whose parent to find
4725+ *
4726+ * fdt_node_depth() finds the depth of a given node. The root node
4727+ * has depth 0, its immediate subnodes depth 1 and so forth.
4728+ *
4729+ * NOTE: This function is expensive, as it must scan the device tree
4730+ * structure from the start to nodeoffset.
4731+ *
4732+ * returns:
4733+ * depth of the node at nodeoffset (>=0), on success
4734+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
4735+ * -FDT_ERR_BADMAGIC,
4736+ * -FDT_ERR_BADVERSION,
4737+ * -FDT_ERR_BADSTATE,
4738+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4739+ */
4740+int fdt_node_depth(const void *fdt, int nodeoffset);
4741+
4742+/**
4743+ * fdt_parent_offset - find the parent of a given node
4744+ * @fdt: pointer to the device tree blob
4745+ * @nodeoffset: offset of the node whose parent to find
4746+ *
4747+ * fdt_parent_offset() locates the parent node of a given node (that
4748+ * is, it finds the offset of the node which contains the node at
4749+ * nodeoffset as a subnode).
4750+ *
4751+ * NOTE: This function is expensive, as it must scan the device tree
4752+ * structure from the start to nodeoffset, *twice*.
4753+ *
4754+ * returns:
4755+ * structure block offset of the parent of the node at nodeoffset
4756+ * (>=0), on success
4757+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
4758+ * -FDT_ERR_BADMAGIC,
4759+ * -FDT_ERR_BADVERSION,
4760+ * -FDT_ERR_BADSTATE,
4761+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4762+ */
4763+int fdt_parent_offset(const void *fdt, int nodeoffset);
4764+
4765+/**
4766+ * fdt_node_offset_by_prop_value - find nodes with a given property value
4767+ * @fdt: pointer to the device tree blob
4768+ * @startoffset: only find nodes after this offset
4769+ * @propname: property name to check
4770+ * @propval: property value to search for
4771+ * @proplen: length of the value in propval
4772+ *
4773+ * fdt_node_offset_by_prop_value() returns the offset of the first
4774+ * node after startoffset, which has a property named propname whose
4775+ * value is of length proplen and has value equal to propval; or if
4776+ * startoffset is -1, the very first such node in the tree.
4777+ *
4778+ * To iterate through all nodes matching the criterion, the following
4779+ * idiom can be used:
4780+ * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
4781+ * propval, proplen);
4782+ * while (offset != -FDT_ERR_NOTFOUND) {
4783+ * // other code here
4784+ * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
4785+ * propval, proplen);
4786+ * }
4787+ *
4788+ * Note the -1 in the first call to the function, if 0 is used here
4789+ * instead, the function will never locate the root node, even if it
4790+ * matches the criterion.
4791+ *
4792+ * returns:
4793+ * structure block offset of the located node (>= 0, >startoffset),
4794+ * on success
4795+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
4796+ * tree after startoffset
4797+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
4798+ * -FDT_ERR_BADMAGIC,
4799+ * -FDT_ERR_BADVERSION,
4800+ * -FDT_ERR_BADSTATE,
4801+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4802+ */
4803+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
4804+ const char *propname,
4805+ const void *propval, int proplen);
4806+
4807+/**
4808+ * fdt_node_offset_by_phandle - find the node with a given phandle
4809+ * @fdt: pointer to the device tree blob
4810+ * @phandle: phandle value
4811+ *
4812+ * fdt_node_offset_by_phandle() returns the offset of the node
4813+ * which has the given phandle value. If there is more than one node
4814+ * in the tree with the given phandle (an invalid tree), results are
4815+ * undefined.
4816+ *
4817+ * returns:
4818+ * structure block offset of the located node (>= 0), on success
4819+ * -FDT_ERR_NOTFOUND, no node with that phandle exists
4820+ * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
4821+ * -FDT_ERR_BADMAGIC,
4822+ * -FDT_ERR_BADVERSION,
4823+ * -FDT_ERR_BADSTATE,
4824+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4825+ */
4826+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
4827+
4828+/**
4829+ * fdt_node_check_compatible - check a node's compatible property
4830+ * @fdt: pointer to the device tree blob
4831+ * @nodeoffset: offset of a tree node
4832+ * @compatible: string to match against
4833+ *
4834+ * fdt_node_check_compatible() returns 0 if the given node contains a
4835+ * @compatible property with the given string as one of its elements,
4836+ * it returns non-zero otherwise, or on error.
4837+ *
4838+ * returns:
4839+ * 0, if the node has a 'compatible' property listing the given string
4840+ * 1, if the node has a 'compatible' property, but it does not list
4841+ * the given string
4842+ * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
4843+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
4844+ * -FDT_ERR_BADMAGIC,
4845+ * -FDT_ERR_BADVERSION,
4846+ * -FDT_ERR_BADSTATE,
4847+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4848+ */
4849+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
4850+ const char *compatible);
4851+
4852+/**
4853+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
4854+ * @fdt: pointer to the device tree blob
4855+ * @startoffset: only find nodes after this offset
4856+ * @compatible: 'compatible' string to match against
4857+ *
4858+ * fdt_node_offset_by_compatible() returns the offset of the first
4859+ * node after startoffset, which has a 'compatible' property which
4860+ * lists the given compatible string; or if startoffset is -1, the
4861+ * very first such node in the tree.
4862+ *
4863+ * To iterate through all nodes matching the criterion, the following
4864+ * idiom can be used:
4865+ * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
4866+ * while (offset != -FDT_ERR_NOTFOUND) {
4867+ * // other code here
4868+ * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
4869+ * }
4870+ *
4871+ * Note the -1 in the first call to the function, if 0 is used here
4872+ * instead, the function will never locate the root node, even if it
4873+ * matches the criterion.
4874+ *
4875+ * returns:
4876+ * structure block offset of the located node (>= 0, >startoffset),
4877+ * on success
4878+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
4879+ * tree after startoffset
4880+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
4881+ * -FDT_ERR_BADMAGIC,
4882+ * -FDT_ERR_BADVERSION,
4883+ * -FDT_ERR_BADSTATE,
4884+ * -FDT_ERR_BADSTRUCTURE, standard meanings
4885+ */
4886+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
4887+ const char *compatible);
4888+
4889+/**
4890+ * fdt_stringlist_contains - check a string list property for a string
4891+ * @strlist: Property containing a list of strings to check
4892+ * @listlen: Length of property
4893+ * @str: String to search for
4894+ *
4895+ * This is a utility function provided for convenience. The list contains
4896+ * one or more strings, each terminated by \0, as is found in a device tree
4897+ * "compatible" property.
4898+ *
4899+ * Return: 1 if the string is found in the list, 0 not found, or invalid list
4900+ */
4901+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
4902+
4903+/**
4904+ * fdt_stringlist_count - count the number of strings in a string list
4905+ * @fdt: pointer to the device tree blob
4906+ * @nodeoffset: offset of a tree node
4907+ * @property: name of the property containing the string list
4908+ *
4909+ * Return:
4910+ * the number of strings in the given property
4911+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated
4912+ * -FDT_ERR_NOTFOUND if the property does not exist
4913+ */
4914+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
4915+
4916+/**
4917+ * fdt_stringlist_search - find a string in a string list and return its index
4918+ * @fdt: pointer to the device tree blob
4919+ * @nodeoffset: offset of a tree node
4920+ * @property: name of the property containing the string list
4921+ * @string: string to look up in the string list
4922+ *
4923+ * Note that it is possible for this function to succeed on property values
4924+ * that are not NUL-terminated. That's because the function will stop after
4925+ * finding the first occurrence of @string. This can for example happen with
4926+ * small-valued cell properties, such as #address-cells, when searching for
4927+ * the empty string.
4928+ *
4929+ * return:
4930+ * the index of the string in the list of strings
4931+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated
4932+ * -FDT_ERR_NOTFOUND if the property does not exist or does not contain
4933+ * the given string
4934+ */
4935+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
4936+ const char *string);
4937+
4938+/**
4939+ * fdt_stringlist_get() - obtain the string at a given index in a string list
4940+ * @fdt: pointer to the device tree blob
4941+ * @nodeoffset: offset of a tree node
4942+ * @property: name of the property containing the string list
4943+ * @index: index of the string to return
4944+ * @lenp: return location for the string length or an error code on failure
4945+ *
4946+ * Note that this will successfully extract strings from properties with
4947+ * non-NUL-terminated values. For example on small-valued cell properties
4948+ * this function will return the empty string.
4949+ *
4950+ * If non-NULL, the length of the string (on success) or a negative error-code
4951+ * (on failure) will be stored in the integer pointer to by lenp.
4952+ *
4953+ * Return:
4954+ * A pointer to the string at the given index in the string list or NULL on
4955+ * failure. On success the length of the string will be stored in the memory
4956+ * location pointed to by the lenp parameter, if non-NULL. On failure one of
4957+ * the following negative error codes will be returned in the lenp parameter
4958+ * (if non-NULL):
4959+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated
4960+ * -FDT_ERR_NOTFOUND if the property does not exist
4961+ */
4962+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
4963+ const char *property, int index,
4964+ int *lenp);
4965+
4966+/**********************************************************************/
4967+/* Read-only functions (addressing related) */
4968+/**********************************************************************/
4969+
4970+/**
4971+ * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells
4972+ *
4973+ * This is the maximum value for #address-cells, #size-cells and
4974+ * similar properties that will be processed by libfdt. IEE1275
4975+ * requires that OF implementations handle values up to 4.
4976+ * Implementations may support larger values, but in practice higher
4977+ * values aren't used.
4978+ */
4979+#define FDT_MAX_NCELLS 4
4980+
4981+/**
4982+ * fdt_address_cells - retrieve address size for a bus represented in the tree
4983+ * @fdt: pointer to the device tree blob
4984+ * @nodeoffset: offset of the node to find the address size for
4985+ *
4986+ * When the node has a valid #address-cells property, returns its value.
4987+ *
4988+ * returns:
4989+ * 0 <= n < FDT_MAX_NCELLS, on success
4990+ * 2, if the node has no #address-cells property
4991+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
4992+ * #address-cells property
4993+ * -FDT_ERR_BADMAGIC,
4994+ * -FDT_ERR_BADVERSION,
4995+ * -FDT_ERR_BADSTATE,
4996+ * -FDT_ERR_BADSTRUCTURE,
4997+ * -FDT_ERR_TRUNCATED, standard meanings
4998+ */
4999+int fdt_address_cells(const void *fdt, int nodeoffset);
5000+
5001+/**
5002+ * fdt_size_cells - retrieve address range size for a bus represented in the
5003+ * tree
5004+ * @fdt: pointer to the device tree blob
5005+ * @nodeoffset: offset of the node to find the address range size for
5006+ *
5007+ * When the node has a valid #size-cells property, returns its value.
5008+ *
5009+ * returns:
5010+ * 0 <= n < FDT_MAX_NCELLS, on success
5011+ * 1, if the node has no #size-cells property
5012+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
5013+ * #size-cells property
5014+ * -FDT_ERR_BADMAGIC,
5015+ * -FDT_ERR_BADVERSION,
5016+ * -FDT_ERR_BADSTATE,
5017+ * -FDT_ERR_BADSTRUCTURE,
5018+ * -FDT_ERR_TRUNCATED, standard meanings
5019+ */
5020+int fdt_size_cells(const void *fdt, int nodeoffset);
5021+
5022+
5023+/**********************************************************************/
5024+/* Write-in-place functions */
5025+/**********************************************************************/
5026+
5027+/**
5028+ * fdt_setprop_inplace_namelen_partial - change a property's value,
5029+ * but not its size
5030+ * @fdt: pointer to the device tree blob
5031+ * @nodeoffset: offset of the node whose property to change
5032+ * @name: name of the property to change
5033+ * @namelen: number of characters of name to consider
5034+ * @idx: index of the property to change in the array
5035+ * @val: pointer to data to replace the property value with
5036+ * @len: length of the property value
5037+ *
5038+ * Identical to fdt_setprop_inplace(), but modifies the given property
5039+ * starting from the given index, and using only the first characters
5040+ * of the name. It is useful when you want to manipulate only one value of
5041+ * an array and you have a string that doesn't end with \0.
5042+ *
5043+ * Return: 0 on success, negative libfdt error value otherwise
5044+ */
5045+#ifndef SWIG /* Not available in Python */
5046+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
5047+ const char *name, int namelen,
5048+ uint32_t idx, const void *val,
5049+ int len);
5050+#endif
5051+
5052+/**
5053+ * fdt_setprop_inplace - change a property's value, but not its size
5054+ * @fdt: pointer to the device tree blob
5055+ * @nodeoffset: offset of the node whose property to change
5056+ * @name: name of the property to change
5057+ * @val: pointer to data to replace the property value with
5058+ * @len: length of the property value
5059+ *
5060+ * fdt_setprop_inplace() replaces the value of a given property with
5061+ * the data in val, of length len. This function cannot change the
5062+ * size of a property, and so will only work if len is equal to the
5063+ * current length of the property.
5064+ *
5065+ * This function will alter only the bytes in the blob which contain
5066+ * the given property value, and will not alter or move any other part
5067+ * of the tree.
5068+ *
5069+ * returns:
5070+ * 0, on success
5071+ * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
5072+ * -FDT_ERR_NOTFOUND, node does not have the named property
5073+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5074+ * -FDT_ERR_BADMAGIC,
5075+ * -FDT_ERR_BADVERSION,
5076+ * -FDT_ERR_BADSTATE,
5077+ * -FDT_ERR_BADSTRUCTURE,
5078+ * -FDT_ERR_TRUNCATED, standard meanings
5079+ */
5080+#ifndef SWIG /* Not available in Python */
5081+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
5082+ const void *val, int len);
5083+#endif
5084+
5085+/**
5086+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
5087+ * @fdt: pointer to the device tree blob
5088+ * @nodeoffset: offset of the node whose property to change
5089+ * @name: name of the property to change
5090+ * @val: 32-bit integer value to replace the property with
5091+ *
5092+ * fdt_setprop_inplace_u32() replaces the value of a given property
5093+ * with the 32-bit integer value in val, converting val to big-endian
5094+ * if necessary. This function cannot change the size of a property,
5095+ * and so will only work if the property already exists and has length
5096+ * 4.
5097+ *
5098+ * This function will alter only the bytes in the blob which contain
5099+ * the given property value, and will not alter or move any other part
5100+ * of the tree.
5101+ *
5102+ * returns:
5103+ * 0, on success
5104+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
5105+ * -FDT_ERR_NOTFOUND, node does not have the named property
5106+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5107+ * -FDT_ERR_BADMAGIC,
5108+ * -FDT_ERR_BADVERSION,
5109+ * -FDT_ERR_BADSTATE,
5110+ * -FDT_ERR_BADSTRUCTURE,
5111+ * -FDT_ERR_TRUNCATED, standard meanings
5112+ */
5113+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
5114+ const char *name, uint32_t val)
5115+{
5116+ fdt32_t tmp = cpu_to_fdt32(val);
5117+ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
5118+}
5119+
5120+/**
5121+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
5122+ * @fdt: pointer to the device tree blob
5123+ * @nodeoffset: offset of the node whose property to change
5124+ * @name: name of the property to change
5125+ * @val: 64-bit integer value to replace the property with
5126+ *
5127+ * fdt_setprop_inplace_u64() replaces the value of a given property
5128+ * with the 64-bit integer value in val, converting val to big-endian
5129+ * if necessary. This function cannot change the size of a property,
5130+ * and so will only work if the property already exists and has length
5131+ * 8.
5132+ *
5133+ * This function will alter only the bytes in the blob which contain
5134+ * the given property value, and will not alter or move any other part
5135+ * of the tree.
5136+ *
5137+ * returns:
5138+ * 0, on success
5139+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 8
5140+ * -FDT_ERR_NOTFOUND, node does not have the named property
5141+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5142+ * -FDT_ERR_BADMAGIC,
5143+ * -FDT_ERR_BADVERSION,
5144+ * -FDT_ERR_BADSTATE,
5145+ * -FDT_ERR_BADSTRUCTURE,
5146+ * -FDT_ERR_TRUNCATED, standard meanings
5147+ */
5148+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
5149+ const char *name, uint64_t val)
5150+{
5151+ fdt64_t tmp = cpu_to_fdt64(val);
5152+ return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
5153+}
5154+
5155+/**
5156+ * fdt_setprop_inplace_cell - change the value of a single-cell property
5157+ * @fdt: pointer to the device tree blob
5158+ * @nodeoffset: offset of the node containing the property
5159+ * @name: name of the property to change the value of
5160+ * @val: new value of the 32-bit cell
5161+ *
5162+ * This is an alternative name for fdt_setprop_inplace_u32()
5163+ * Return: 0 on success, negative libfdt error number otherwise.
5164+ */
5165+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
5166+ const char *name, uint32_t val)
5167+{
5168+ return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
5169+}
5170+
5171+/**
5172+ * fdt_nop_property - replace a property with nop tags
5173+ * @fdt: pointer to the device tree blob
5174+ * @nodeoffset: offset of the node whose property to nop
5175+ * @name: name of the property to nop
5176+ *
5177+ * fdt_nop_property() will replace a given property's representation
5178+ * in the blob with FDT_NOP tags, effectively removing it from the
5179+ * tree.
5180+ *
5181+ * This function will alter only the bytes in the blob which contain
5182+ * the property, and will not alter or move any other part of the
5183+ * tree.
5184+ *
5185+ * returns:
5186+ * 0, on success
5187+ * -FDT_ERR_NOTFOUND, node does not have the named property
5188+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5189+ * -FDT_ERR_BADMAGIC,
5190+ * -FDT_ERR_BADVERSION,
5191+ * -FDT_ERR_BADSTATE,
5192+ * -FDT_ERR_BADSTRUCTURE,
5193+ * -FDT_ERR_TRUNCATED, standard meanings
5194+ */
5195+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
5196+
5197+/**
5198+ * fdt_nop_node - replace a node (subtree) with nop tags
5199+ * @fdt: pointer to the device tree blob
5200+ * @nodeoffset: offset of the node to nop
5201+ *
5202+ * fdt_nop_node() will replace a given node's representation in the
5203+ * blob, including all its subnodes, if any, with FDT_NOP tags,
5204+ * effectively removing it from the tree.
5205+ *
5206+ * This function will alter only the bytes in the blob which contain
5207+ * the node and its properties and subnodes, and will not alter or
5208+ * move any other part of the tree.
5209+ *
5210+ * returns:
5211+ * 0, on success
5212+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5213+ * -FDT_ERR_BADMAGIC,
5214+ * -FDT_ERR_BADVERSION,
5215+ * -FDT_ERR_BADSTATE,
5216+ * -FDT_ERR_BADSTRUCTURE,
5217+ * -FDT_ERR_TRUNCATED, standard meanings
5218+ */
5219+int fdt_nop_node(void *fdt, int nodeoffset);
5220+
5221+/**********************************************************************/
5222+/* Sequential write functions */
5223+/**********************************************************************/
5224+
5225+/* fdt_create_with_flags flags */
5226+#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
5227+ /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
5228+ * names in the fdt. This can result in faster creation times, but
5229+ * a larger fdt. */
5230+
5231+#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP)
5232+
5233+/**
5234+ * fdt_create_with_flags - begin creation of a new fdt
5235+ * @buf: pointer to memory allocated where fdt will be created
5236+ * @bufsize: size of the memory space at fdt
5237+ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
5238+ *
5239+ * fdt_create_with_flags() begins the process of creating a new fdt with
5240+ * the sequential write interface.
5241+ *
5242+ * fdt creation process must end with fdt_finished() to produce a valid fdt.
5243+ *
5244+ * returns:
5245+ * 0, on success
5246+ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
5247+ * -FDT_ERR_BADFLAGS, flags is not valid
5248+ */
5249+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
5250+
5251+/**
5252+ * fdt_create - begin creation of a new fdt
5253+ * @buf: pointer to memory allocated where fdt will be created
5254+ * @bufsize: size of the memory space at fdt
5255+ *
5256+ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
5257+ *
5258+ * returns:
5259+ * 0, on success
5260+ * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
5261+ */
5262+int fdt_create(void *buf, int bufsize);
5263+
5264+int fdt_resize(void *fdt, void *buf, int bufsize);
5265+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
5266+int fdt_finish_reservemap(void *fdt);
5267+int fdt_begin_node(void *fdt, const char *name);
5268+int fdt_property(void *fdt, const char *name, const void *val, int len);
5269+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
5270+{
5271+ fdt32_t tmp = cpu_to_fdt32(val);
5272+ return fdt_property(fdt, name, &tmp, sizeof(tmp));
5273+}
5274+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
5275+{
5276+ fdt64_t tmp = cpu_to_fdt64(val);
5277+ return fdt_property(fdt, name, &tmp, sizeof(tmp));
5278+}
5279+
5280+#ifndef SWIG /* Not available in Python */
5281+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
5282+{
5283+ return fdt_property_u32(fdt, name, val);
5284+}
5285+#endif
5286+
5287+/**
5288+ * fdt_property_placeholder - add a new property and return a ptr to its value
5289+ *
5290+ * @fdt: pointer to the device tree blob
5291+ * @name: name of property to add
5292+ * @len: length of property value in bytes
5293+ * @valp: returns a pointer to where where the value should be placed
5294+ *
5295+ * returns:
5296+ * 0, on success
5297+ * -FDT_ERR_BADMAGIC,
5298+ * -FDT_ERR_NOSPACE, standard meanings
5299+ */
5300+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
5301+
5302+#define fdt_property_string(fdt, name, str) \
5303+ fdt_property(fdt, name, str, strlen(str)+1)
5304+int fdt_end_node(void *fdt);
5305+int fdt_finish(void *fdt);
5306+
5307+/**********************************************************************/
5308+/* Read-write functions */
5309+/**********************************************************************/
5310+
5311+int fdt_create_empty_tree(void *buf, int bufsize);
5312+int fdt_open_into(const void *fdt, void *buf, int bufsize);
5313+int fdt_pack(void *fdt);
5314+
5315+/**
5316+ * fdt_add_mem_rsv - add one memory reserve map entry
5317+ * @fdt: pointer to the device tree blob
5318+ * @address: 64-bit start address of the reserve map entry
5319+ * @size: 64-bit size of the reserved region
5320+ *
5321+ * Adds a reserve map entry to the given blob reserving a region at
5322+ * address address of length size.
5323+ *
5324+ * This function will insert data into the reserve map and will
5325+ * therefore change the indexes of some entries in the table.
5326+ *
5327+ * returns:
5328+ * 0, on success
5329+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5330+ * contain the new reservation entry
5331+ * -FDT_ERR_BADMAGIC,
5332+ * -FDT_ERR_BADVERSION,
5333+ * -FDT_ERR_BADSTATE,
5334+ * -FDT_ERR_BADSTRUCTURE,
5335+ * -FDT_ERR_BADLAYOUT,
5336+ * -FDT_ERR_TRUNCATED, standard meanings
5337+ */
5338+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
5339+
5340+/**
5341+ * fdt_del_mem_rsv - remove a memory reserve map entry
5342+ * @fdt: pointer to the device tree blob
5343+ * @n: entry to remove
5344+ *
5345+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
5346+ * the blob.
5347+ *
5348+ * This function will delete data from the reservation table and will
5349+ * therefore change the indexes of some entries in the table.
5350+ *
5351+ * returns:
5352+ * 0, on success
5353+ * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
5354+ * are less than n+1 reserve map entries)
5355+ * -FDT_ERR_BADMAGIC,
5356+ * -FDT_ERR_BADVERSION,
5357+ * -FDT_ERR_BADSTATE,
5358+ * -FDT_ERR_BADSTRUCTURE,
5359+ * -FDT_ERR_BADLAYOUT,
5360+ * -FDT_ERR_TRUNCATED, standard meanings
5361+ */
5362+int fdt_del_mem_rsv(void *fdt, int n);
5363+
5364+/**
5365+ * fdt_set_name - change the name of a given node
5366+ * @fdt: pointer to the device tree blob
5367+ * @nodeoffset: structure block offset of a node
5368+ * @name: name to give the node
5369+ *
5370+ * fdt_set_name() replaces the name (including unit address, if any)
5371+ * of the given node with the given string. NOTE: this function can't
5372+ * efficiently check if the new name is unique amongst the given
5373+ * node's siblings; results are undefined if this function is invoked
5374+ * with a name equal to one of the given node's siblings.
5375+ *
5376+ * This function may insert or delete data from the blob, and will
5377+ * therefore change the offsets of some existing nodes.
5378+ *
5379+ * returns:
5380+ * 0, on success
5381+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
5382+ * to contain the new name
5383+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5384+ * -FDT_ERR_BADMAGIC,
5385+ * -FDT_ERR_BADVERSION,
5386+ * -FDT_ERR_BADSTATE, standard meanings
5387+ */
5388+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
5389+
5390+/**
5391+ * fdt_setprop - create or change a property
5392+ * @fdt: pointer to the device tree blob
5393+ * @nodeoffset: offset of the node whose property to change
5394+ * @name: name of the property to change
5395+ * @val: pointer to data to set the property value to
5396+ * @len: length of the property value
5397+ *
5398+ * fdt_setprop() sets the value of the named property in the given
5399+ * node to the given value and length, creating the property if it
5400+ * does not already exist.
5401+ *
5402+ * This function may insert or delete data from the blob, and will
5403+ * therefore change the offsets of some existing nodes.
5404+ *
5405+ * returns:
5406+ * 0, on success
5407+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5408+ * contain the new property value
5409+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5410+ * -FDT_ERR_BADLAYOUT,
5411+ * -FDT_ERR_BADMAGIC,
5412+ * -FDT_ERR_BADVERSION,
5413+ * -FDT_ERR_BADSTATE,
5414+ * -FDT_ERR_BADSTRUCTURE,
5415+ * -FDT_ERR_BADLAYOUT,
5416+ * -FDT_ERR_TRUNCATED, standard meanings
5417+ */
5418+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
5419+ const void *val, int len);
5420+
5421+/**
5422+ * fdt_setprop_placeholder - allocate space for a property
5423+ * @fdt: pointer to the device tree blob
5424+ * @nodeoffset: offset of the node whose property to change
5425+ * @name: name of the property to change
5426+ * @len: length of the property value
5427+ * @prop_data: return pointer to property data
5428+ *
5429+ * fdt_setprop_placeholer() allocates the named property in the given node.
5430+ * If the property exists it is resized. In either case a pointer to the
5431+ * property data is returned.
5432+ *
5433+ * This function may insert or delete data from the blob, and will
5434+ * therefore change the offsets of some existing nodes.
5435+ *
5436+ * returns:
5437+ * 0, on success
5438+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5439+ * contain the new property value
5440+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5441+ * -FDT_ERR_BADLAYOUT,
5442+ * -FDT_ERR_BADMAGIC,
5443+ * -FDT_ERR_BADVERSION,
5444+ * -FDT_ERR_BADSTATE,
5445+ * -FDT_ERR_BADSTRUCTURE,
5446+ * -FDT_ERR_BADLAYOUT,
5447+ * -FDT_ERR_TRUNCATED, standard meanings
5448+ */
5449+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
5450+ int len, void **prop_data);
5451+
5452+/**
5453+ * fdt_setprop_u32 - set a property to a 32-bit integer
5454+ * @fdt: pointer to the device tree blob
5455+ * @nodeoffset: offset of the node whose property to change
5456+ * @name: name of the property to change
5457+ * @val: 32-bit integer value for the property (native endian)
5458+ *
5459+ * fdt_setprop_u32() sets the value of the named property in the given
5460+ * node to the given 32-bit integer value (converting to big-endian if
5461+ * necessary), or creates a new property with that value if it does
5462+ * not already exist.
5463+ *
5464+ * This function may insert or delete data from the blob, and will
5465+ * therefore change the offsets of some existing nodes.
5466+ *
5467+ * returns:
5468+ * 0, on success
5469+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5470+ * contain the new property value
5471+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5472+ * -FDT_ERR_BADLAYOUT,
5473+ * -FDT_ERR_BADMAGIC,
5474+ * -FDT_ERR_BADVERSION,
5475+ * -FDT_ERR_BADSTATE,
5476+ * -FDT_ERR_BADSTRUCTURE,
5477+ * -FDT_ERR_BADLAYOUT,
5478+ * -FDT_ERR_TRUNCATED, standard meanings
5479+ */
5480+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
5481+ uint32_t val)
5482+{
5483+ fdt32_t tmp = cpu_to_fdt32(val);
5484+ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
5485+}
5486+
5487+/**
5488+ * fdt_setprop_u64 - set a property to a 64-bit integer
5489+ * @fdt: pointer to the device tree blob
5490+ * @nodeoffset: offset of the node whose property to change
5491+ * @name: name of the property to change
5492+ * @val: 64-bit integer value for the property (native endian)
5493+ *
5494+ * fdt_setprop_u64() sets the value of the named property in the given
5495+ * node to the given 64-bit integer value (converting to big-endian if
5496+ * necessary), or creates a new property with that value if it does
5497+ * not already exist.
5498+ *
5499+ * This function may insert or delete data from the blob, and will
5500+ * therefore change the offsets of some existing nodes.
5501+ *
5502+ * returns:
5503+ * 0, on success
5504+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5505+ * contain the new property value
5506+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5507+ * -FDT_ERR_BADLAYOUT,
5508+ * -FDT_ERR_BADMAGIC,
5509+ * -FDT_ERR_BADVERSION,
5510+ * -FDT_ERR_BADSTATE,
5511+ * -FDT_ERR_BADSTRUCTURE,
5512+ * -FDT_ERR_BADLAYOUT,
5513+ * -FDT_ERR_TRUNCATED, standard meanings
5514+ */
5515+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
5516+ uint64_t val)
5517+{
5518+ fdt64_t tmp = cpu_to_fdt64(val);
5519+ return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
5520+}
5521+
5522+/**
5523+ * fdt_setprop_cell - set a property to a single cell value
5524+ * @fdt: pointer to the device tree blob
5525+ * @nodeoffset: offset of the node whose property to change
5526+ * @name: name of the property to change
5527+ * @val: 32-bit integer value for the property (native endian)
5528+ *
5529+ * This is an alternative name for fdt_setprop_u32()
5530+ *
5531+ * Return: 0 on success, negative libfdt error value otherwise.
5532+ */
5533+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
5534+ uint32_t val)
5535+{
5536+ return fdt_setprop_u32(fdt, nodeoffset, name, val);
5537+}
5538+
5539+/**
5540+ * fdt_setprop_string - set a property to a string value
5541+ * @fdt: pointer to the device tree blob
5542+ * @nodeoffset: offset of the node whose property to change
5543+ * @name: name of the property to change
5544+ * @str: string value for the property
5545+ *
5546+ * fdt_setprop_string() sets the value of the named property in the
5547+ * given node to the given string value (using the length of the
5548+ * string to determine the new length of the property), or creates a
5549+ * new property with that value if it does not already exist.
5550+ *
5551+ * This function may insert or delete data from the blob, and will
5552+ * therefore change the offsets of some existing nodes.
5553+ *
5554+ * returns:
5555+ * 0, on success
5556+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5557+ * contain the new property value
5558+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5559+ * -FDT_ERR_BADLAYOUT,
5560+ * -FDT_ERR_BADMAGIC,
5561+ * -FDT_ERR_BADVERSION,
5562+ * -FDT_ERR_BADSTATE,
5563+ * -FDT_ERR_BADSTRUCTURE,
5564+ * -FDT_ERR_BADLAYOUT,
5565+ * -FDT_ERR_TRUNCATED, standard meanings
5566+ */
5567+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
5568+ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
5569+
5570+
5571+/**
5572+ * fdt_setprop_empty - set a property to an empty value
5573+ * @fdt: pointer to the device tree blob
5574+ * @nodeoffset: offset of the node whose property to change
5575+ * @name: name of the property to change
5576+ *
5577+ * fdt_setprop_empty() sets the value of the named property in the
5578+ * given node to an empty (zero length) value, or creates a new empty
5579+ * property if it does not already exist.
5580+ *
5581+ * This function may insert or delete data from the blob, and will
5582+ * therefore change the offsets of some existing nodes.
5583+ *
5584+ * returns:
5585+ * 0, on success
5586+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5587+ * contain the new property value
5588+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5589+ * -FDT_ERR_BADLAYOUT,
5590+ * -FDT_ERR_BADMAGIC,
5591+ * -FDT_ERR_BADVERSION,
5592+ * -FDT_ERR_BADSTATE,
5593+ * -FDT_ERR_BADSTRUCTURE,
5594+ * -FDT_ERR_BADLAYOUT,
5595+ * -FDT_ERR_TRUNCATED, standard meanings
5596+ */
5597+#define fdt_setprop_empty(fdt, nodeoffset, name) \
5598+ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
5599+
5600+/**
5601+ * fdt_appendprop - append to or create a property
5602+ * @fdt: pointer to the device tree blob
5603+ * @nodeoffset: offset of the node whose property to change
5604+ * @name: name of the property to append to
5605+ * @val: pointer to data to append to the property value
5606+ * @len: length of the data to append to the property value
5607+ *
5608+ * fdt_appendprop() appends the value to the named property in the
5609+ * given node, creating the property if it does not already exist.
5610+ *
5611+ * This function may insert data into the blob, and will therefore
5612+ * change the offsets of some existing nodes.
5613+ *
5614+ * returns:
5615+ * 0, on success
5616+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5617+ * contain the new property value
5618+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5619+ * -FDT_ERR_BADLAYOUT,
5620+ * -FDT_ERR_BADMAGIC,
5621+ * -FDT_ERR_BADVERSION,
5622+ * -FDT_ERR_BADSTATE,
5623+ * -FDT_ERR_BADSTRUCTURE,
5624+ * -FDT_ERR_BADLAYOUT,
5625+ * -FDT_ERR_TRUNCATED, standard meanings
5626+ */
5627+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
5628+ const void *val, int len);
5629+
5630+/**
5631+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
5632+ * @fdt: pointer to the device tree blob
5633+ * @nodeoffset: offset of the node whose property to change
5634+ * @name: name of the property to change
5635+ * @val: 32-bit integer value to append to the property (native endian)
5636+ *
5637+ * fdt_appendprop_u32() appends the given 32-bit integer value
5638+ * (converting to big-endian if necessary) to the value of the named
5639+ * property in the given node, or creates a new property with that
5640+ * value if it does not already exist.
5641+ *
5642+ * This function may insert data into the blob, and will therefore
5643+ * change the offsets of some existing nodes.
5644+ *
5645+ * returns:
5646+ * 0, on success
5647+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5648+ * contain the new property value
5649+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5650+ * -FDT_ERR_BADLAYOUT,
5651+ * -FDT_ERR_BADMAGIC,
5652+ * -FDT_ERR_BADVERSION,
5653+ * -FDT_ERR_BADSTATE,
5654+ * -FDT_ERR_BADSTRUCTURE,
5655+ * -FDT_ERR_BADLAYOUT,
5656+ * -FDT_ERR_TRUNCATED, standard meanings
5657+ */
5658+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
5659+ const char *name, uint32_t val)
5660+{
5661+ fdt32_t tmp = cpu_to_fdt32(val);
5662+ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
5663+}
5664+
5665+/**
5666+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
5667+ * @fdt: pointer to the device tree blob
5668+ * @nodeoffset: offset of the node whose property to change
5669+ * @name: name of the property to change
5670+ * @val: 64-bit integer value to append to the property (native endian)
5671+ *
5672+ * fdt_appendprop_u64() appends the given 64-bit integer value
5673+ * (converting to big-endian if necessary) to the value of the named
5674+ * property in the given node, or creates a new property with that
5675+ * value if it does not already exist.
5676+ *
5677+ * This function may insert data into the blob, and will therefore
5678+ * change the offsets of some existing nodes.
5679+ *
5680+ * returns:
5681+ * 0, on success
5682+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5683+ * contain the new property value
5684+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5685+ * -FDT_ERR_BADLAYOUT,
5686+ * -FDT_ERR_BADMAGIC,
5687+ * -FDT_ERR_BADVERSION,
5688+ * -FDT_ERR_BADSTATE,
5689+ * -FDT_ERR_BADSTRUCTURE,
5690+ * -FDT_ERR_BADLAYOUT,
5691+ * -FDT_ERR_TRUNCATED, standard meanings
5692+ */
5693+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
5694+ const char *name, uint64_t val)
5695+{
5696+ fdt64_t tmp = cpu_to_fdt64(val);
5697+ return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
5698+}
5699+
5700+/**
5701+ * fdt_appendprop_cell - append a single cell value to a property
5702+ * @fdt: pointer to the device tree blob
5703+ * @nodeoffset: offset of the node whose property to change
5704+ * @name: name of the property to change
5705+ * @val: 32-bit integer value to append to the property (native endian)
5706+ *
5707+ * This is an alternative name for fdt_appendprop_u32()
5708+ *
5709+ * Return: 0 on success, negative libfdt error value otherwise.
5710+ */
5711+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
5712+ const char *name, uint32_t val)
5713+{
5714+ return fdt_appendprop_u32(fdt, nodeoffset, name, val);
5715+}
5716+
5717+/**
5718+ * fdt_appendprop_string - append a string to a property
5719+ * @fdt: pointer to the device tree blob
5720+ * @nodeoffset: offset of the node whose property to change
5721+ * @name: name of the property to change
5722+ * @str: string value to append to the property
5723+ *
5724+ * fdt_appendprop_string() appends the given string to the value of
5725+ * the named property in the given node, or creates a new property
5726+ * with that value if it does not already exist.
5727+ *
5728+ * This function may insert data into the blob, and will therefore
5729+ * change the offsets of some existing nodes.
5730+ *
5731+ * returns:
5732+ * 0, on success
5733+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5734+ * contain the new property value
5735+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5736+ * -FDT_ERR_BADLAYOUT,
5737+ * -FDT_ERR_BADMAGIC,
5738+ * -FDT_ERR_BADVERSION,
5739+ * -FDT_ERR_BADSTATE,
5740+ * -FDT_ERR_BADSTRUCTURE,
5741+ * -FDT_ERR_BADLAYOUT,
5742+ * -FDT_ERR_TRUNCATED, standard meanings
5743+ */
5744+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
5745+ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
5746+
5747+/**
5748+ * fdt_appendprop_addrrange - append a address range property
5749+ * @fdt: pointer to the device tree blob
5750+ * @parent: offset of the parent node
5751+ * @nodeoffset: offset of the node to add a property at
5752+ * @name: name of property
5753+ * @addr: start address of a given range
5754+ * @size: size of a given range
5755+ *
5756+ * fdt_appendprop_addrrange() appends an address range value (start
5757+ * address and size) to the value of the named property in the given
5758+ * node, or creates a new property with that value if it does not
5759+ * already exist.
5760+ * If "name" is not specified, a default "reg" is used.
5761+ * Cell sizes are determined by parent's #address-cells and #size-cells.
5762+ *
5763+ * This function may insert data into the blob, and will therefore
5764+ * change the offsets of some existing nodes.
5765+ *
5766+ * returns:
5767+ * 0, on success
5768+ * -FDT_ERR_BADLAYOUT,
5769+ * -FDT_ERR_BADMAGIC,
5770+ * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
5771+ * #address-cells property
5772+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5773+ * -FDT_ERR_BADSTATE,
5774+ * -FDT_ERR_BADSTRUCTURE,
5775+ * -FDT_ERR_BADVERSION,
5776+ * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
5777+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
5778+ * contain a new property
5779+ * -FDT_ERR_TRUNCATED, standard meanings
5780+ */
5781+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
5782+ const char *name, uint64_t addr, uint64_t size);
5783+
5784+/**
5785+ * fdt_delprop - delete a property
5786+ * @fdt: pointer to the device tree blob
5787+ * @nodeoffset: offset of the node whose property to nop
5788+ * @name: name of the property to nop
5789+ *
5790+ * fdt_del_property() will delete the given property.
5791+ *
5792+ * This function will delete data from the blob, and will therefore
5793+ * change the offsets of some existing nodes.
5794+ *
5795+ * returns:
5796+ * 0, on success
5797+ * -FDT_ERR_NOTFOUND, node does not have the named property
5798+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5799+ * -FDT_ERR_BADLAYOUT,
5800+ * -FDT_ERR_BADMAGIC,
5801+ * -FDT_ERR_BADVERSION,
5802+ * -FDT_ERR_BADSTATE,
5803+ * -FDT_ERR_BADSTRUCTURE,
5804+ * -FDT_ERR_TRUNCATED, standard meanings
5805+ */
5806+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
5807+
5808+/**
5809+ * fdt_add_subnode_namelen - creates a new node based on substring
5810+ * @fdt: pointer to the device tree blob
5811+ * @parentoffset: structure block offset of a node
5812+ * @name: name of the subnode to create
5813+ * @namelen: number of characters of name to consider
5814+ *
5815+ * Identical to fdt_add_subnode(), but use only the first @namelen
5816+ * characters of @name as the name of the new node. This is useful for
5817+ * creating subnodes based on a portion of a larger string, such as a
5818+ * full path.
5819+ *
5820+ * Return: structure block offset of the created subnode (>=0),
5821+ * negative libfdt error value otherwise
5822+ */
5823+#ifndef SWIG /* Not available in Python */
5824+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
5825+ const char *name, int namelen);
5826+#endif
5827+
5828+/**
5829+ * fdt_add_subnode - creates a new node
5830+ * @fdt: pointer to the device tree blob
5831+ * @parentoffset: structure block offset of a node
5832+ * @name: name of the subnode to locate
5833+ *
5834+ * fdt_add_subnode() creates a new node as a subnode of the node at
5835+ * structure block offset parentoffset, with the given name (which
5836+ * should include the unit address, if any).
5837+ *
5838+ * This function will insert data into the blob, and will therefore
5839+ * change the offsets of some existing nodes.
5840+ *
5841+ * returns:
5842+ * structure block offset of the created nodeequested subnode (>=0), on
5843+ * success
5844+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
5845+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
5846+ * tag
5847+ * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
5848+ * the given name
5849+ * -FDT_ERR_NOSPACE, if there is insufficient free space in the
5850+ * blob to contain the new node
5851+ * -FDT_ERR_NOSPACE
5852+ * -FDT_ERR_BADLAYOUT
5853+ * -FDT_ERR_BADMAGIC,
5854+ * -FDT_ERR_BADVERSION,
5855+ * -FDT_ERR_BADSTATE,
5856+ * -FDT_ERR_BADSTRUCTURE,
5857+ * -FDT_ERR_TRUNCATED, standard meanings.
5858+ */
5859+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
5860+
5861+/**
5862+ * fdt_del_node - delete a node (subtree)
5863+ * @fdt: pointer to the device tree blob
5864+ * @nodeoffset: offset of the node to nop
5865+ *
5866+ * fdt_del_node() will remove the given node, including all its
5867+ * subnodes if any, from the blob.
5868+ *
5869+ * This function will delete data from the blob, and will therefore
5870+ * change the offsets of some existing nodes.
5871+ *
5872+ * returns:
5873+ * 0, on success
5874+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
5875+ * -FDT_ERR_BADLAYOUT,
5876+ * -FDT_ERR_BADMAGIC,
5877+ * -FDT_ERR_BADVERSION,
5878+ * -FDT_ERR_BADSTATE,
5879+ * -FDT_ERR_BADSTRUCTURE,
5880+ * -FDT_ERR_TRUNCATED, standard meanings
5881+ */
5882+int fdt_del_node(void *fdt, int nodeoffset);
5883+
5884+/**
5885+ * fdt_overlay_apply - Applies a DT overlay on a base DT
5886+ * @fdt: pointer to the base device tree blob
5887+ * @fdto: pointer to the device tree overlay blob
5888+ *
5889+ * fdt_overlay_apply() will apply the given device tree overlay on the
5890+ * given base device tree.
5891+ *
5892+ * Expect the base device tree to be modified, even if the function
5893+ * returns an error.
5894+ *
5895+ * returns:
5896+ * 0, on success
5897+ * -FDT_ERR_NOSPACE, there's not enough space in the base device tree
5898+ * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
5899+ * properties in the base DT
5900+ * -FDT_ERR_BADPHANDLE,
5901+ * -FDT_ERR_BADOVERLAY,
5902+ * -FDT_ERR_NOPHANDLES,
5903+ * -FDT_ERR_INTERNAL,
5904+ * -FDT_ERR_BADLAYOUT,
5905+ * -FDT_ERR_BADMAGIC,
5906+ * -FDT_ERR_BADOFFSET,
5907+ * -FDT_ERR_BADPATH,
5908+ * -FDT_ERR_BADVERSION,
5909+ * -FDT_ERR_BADSTRUCTURE,
5910+ * -FDT_ERR_BADSTATE,
5911+ * -FDT_ERR_TRUNCATED, standard meanings
5912+ */
5913+int fdt_overlay_apply(void *fdt, void *fdto);
5914+
5915+/**
5916+ * fdt_overlay_target_offset - retrieves the offset of a fragment's target
5917+ * @fdt: Base device tree blob
5918+ * @fdto: Device tree overlay blob
5919+ * @fragment_offset: node offset of the fragment in the overlay
5920+ * @pathp: pointer which receives the path of the target (or NULL)
5921+ *
5922+ * fdt_overlay_target_offset() retrieves the target offset in the base
5923+ * device tree of a fragment, no matter how the actual targeting is
5924+ * done (through a phandle or a path)
5925+ *
5926+ * returns:
5927+ * the targeted node offset in the base device tree
5928+ * Negative error code on error
5929+ */
5930+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
5931+ int fragment_offset, char const **pathp);
5932+
5933+/**********************************************************************/
5934+/* Debugging / informational functions */
5935+/**********************************************************************/
5936+
5937+const char *fdt_strerror(int errval);
5938+
5939+#ifdef __cplusplus
5940+}
5941+#endif
5942+
5943+#endif /* LIBFDT_H */
5944diff --git a/include/libfdt_env.h b/include/libfdt_env.h
5945new file mode 100644
5946index 0000000..51b31d1
5947--- /dev/null
5948+++ b/include/libfdt_env.h
5949@@ -0,0 +1,95 @@
5950+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
5951+#ifndef LIBFDT_ENV_H
5952+#define LIBFDT_ENV_H
5953+/*
5954+ * libfdt - Flat Device Tree manipulation
5955+ * Copyright (C) 2006 David Gibson, IBM Corporation.
5956+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
5957+ */
5958+
5959+#include <stdbool.h>
5960+#include <stddef.h>
5961+#include <stdint.h>
5962+#include <limits.h>
5963+#include <string.h>
5964+
5965+#ifdef __CHECKER__
5966+#define FDT_FORCE __attribute__((force))
5967+#define FDT_BITWISE __attribute__((bitwise))
5968+#else
5969+#define FDT_FORCE
5970+#define FDT_BITWISE
5971+#endif
5972+
5973+typedef uint16_t FDT_BITWISE fdt16_t;
5974+typedef uint32_t FDT_BITWISE fdt32_t;
5975+typedef uint64_t FDT_BITWISE fdt64_t;
5976+
5977+#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
5978+#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
5979+#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \
5980+ (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3))
5981+#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \
5982+ (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \
5983+ (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \
5984+ (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7))
5985+
5986+static inline uint16_t fdt16_to_cpu(fdt16_t x)
5987+{
5988+ return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
5989+}
5990+static inline fdt16_t cpu_to_fdt16(uint16_t x)
5991+{
5992+ return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
5993+}
5994+
5995+static inline uint32_t fdt32_to_cpu(fdt32_t x)
5996+{
5997+ return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
5998+}
5999+static inline fdt32_t cpu_to_fdt32(uint32_t x)
6000+{
6001+ return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
6002+}
6003+
6004+static inline uint64_t fdt64_to_cpu(fdt64_t x)
6005+{
6006+ return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
6007+}
6008+static inline fdt64_t cpu_to_fdt64(uint64_t x)
6009+{
6010+ return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
6011+}
6012+#undef CPU_TO_FDT64
6013+#undef CPU_TO_FDT32
6014+#undef CPU_TO_FDT16
6015+#undef EXTRACT_BYTE
6016+
6017+#ifdef __APPLE__
6018+#include <AvailabilityMacros.h>
6019+
6020+/* strnlen() is not available on Mac OS < 10.7 */
6021+# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
6022+ MAC_OS_X_VERSION_10_7)
6023+
6024+#define strnlen fdt_strnlen
6025+
6026+/*
6027+ * fdt_strnlen: returns the length of a string or max_count - which ever is
6028+ * smallest.
6029+ * Input 1 string: the string whose size is to be determined
6030+ * Input 2 max_count: the maximum value returned by this function
6031+ * Output: length of the string or max_count (the smallest of the two)
6032+ */
6033+static inline size_t fdt_strnlen(const char *string, size_t max_count)
6034+{
6035+ const char *p = memchr(string, 0, max_count);
6036+ return p ? p - string : max_count;
6037+}
6038+
6039+#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
6040+ MAC_OS_X_VERSION_10_7) */
6041+
6042+#endif /* __APPLE__ */
6043+
6044+#endif /* LIBFDT_ENV_H */