hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/scripts/dtc/libfdt/fdt_ro.c
....@@ -1,52 +1,7 @@
1
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
12 /*
23 * libfdt - Flat Device Tree manipulation
34 * Copyright (C) 2006 David Gibson, IBM Corporation.
4
- *
5
- * libfdt is dual licensed: you can use it either under the terms of
6
- * the GPL, or the BSD license, at your option.
7
- *
8
- * a) This library is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License as
10
- * published by the Free Software Foundation; either version 2 of the
11
- * License, or (at your option) any later version.
12
- *
13
- * This library is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public
19
- * License along with this library; if not, write to the Free
20
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21
- * MA 02110-1301 USA
22
- *
23
- * Alternatively,
24
- *
25
- * b) Redistribution and use in source and binary forms, with or
26
- * without modification, are permitted provided that the following
27
- * conditions are met:
28
- *
29
- * 1. Redistributions of source code must retain the above
30
- * copyright notice, this list of conditions and the following
31
- * disclaimer.
32
- * 2. Redistributions in binary form must reproduce the above
33
- * copyright notice, this list of conditions and the following
34
- * disclaimer in the documentation and/or other materials
35
- * provided with the distribution.
36
- *
37
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
505 */
516 #include "libfdt_env.h"
527
....@@ -76,60 +31,171 @@
7631 return 0;
7732 }
7833
34
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
35
+{
36
+ int32_t totalsize;
37
+ uint32_t absoffset;
38
+ size_t len;
39
+ int err;
40
+ const char *s, *n;
41
+
42
+ if (can_assume(VALID_INPUT)) {
43
+ s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
44
+
45
+ if (lenp)
46
+ *lenp = strlen(s);
47
+ return s;
48
+ }
49
+ totalsize = fdt_ro_probe_(fdt);
50
+ err = totalsize;
51
+ if (totalsize < 0)
52
+ goto fail;
53
+
54
+ err = -FDT_ERR_BADOFFSET;
55
+ absoffset = stroffset + fdt_off_dt_strings(fdt);
56
+ if (absoffset >= (unsigned)totalsize)
57
+ goto fail;
58
+ len = totalsize - absoffset;
59
+
60
+ if (fdt_magic(fdt) == FDT_MAGIC) {
61
+ if (stroffset < 0)
62
+ goto fail;
63
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
64
+ if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
65
+ goto fail;
66
+ if ((fdt_size_dt_strings(fdt) - stroffset) < len)
67
+ len = fdt_size_dt_strings(fdt) - stroffset;
68
+ }
69
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
70
+ unsigned int sw_stroffset = -stroffset;
71
+
72
+ if ((stroffset >= 0) ||
73
+ (sw_stroffset > fdt_size_dt_strings(fdt)))
74
+ goto fail;
75
+ if (sw_stroffset < len)
76
+ len = sw_stroffset;
77
+ } else {
78
+ err = -FDT_ERR_INTERNAL;
79
+ goto fail;
80
+ }
81
+
82
+ s = (const char *)fdt + absoffset;
83
+ n = memchr(s, '\0', len);
84
+ if (!n) {
85
+ /* missing terminating NULL */
86
+ err = -FDT_ERR_TRUNCATED;
87
+ goto fail;
88
+ }
89
+
90
+ if (lenp)
91
+ *lenp = n - s;
92
+ return s;
93
+
94
+fail:
95
+ if (lenp)
96
+ *lenp = err;
97
+ return NULL;
98
+}
99
+
79100 const char *fdt_string(const void *fdt, int stroffset)
80101 {
81
- return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
102
+ return fdt_get_string(fdt, stroffset, NULL);
82103 }
83104
84105 static int fdt_string_eq_(const void *fdt, int stroffset,
85106 const char *s, int len)
86107 {
87
- const char *p = fdt_string(fdt, stroffset);
108
+ int slen;
109
+ const char *p = fdt_get_string(fdt, stroffset, &slen);
88110
89
- return (strlen(p) == len) && (memcmp(p, s, len) == 0);
111
+ return p && (slen == len) && (memcmp(p, s, len) == 0);
90112 }
91113
92
-uint32_t fdt_get_max_phandle(const void *fdt)
114
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
93115 {
94
- uint32_t max_phandle = 0;
95
- int offset;
116
+ uint32_t max = 0;
117
+ int offset = -1;
96118
97
- for (offset = fdt_next_node(fdt, -1, NULL);;
98
- offset = fdt_next_node(fdt, offset, NULL)) {
99
- uint32_t phandle;
119
+ while (true) {
120
+ uint32_t value;
100121
101
- if (offset == -FDT_ERR_NOTFOUND)
102
- return max_phandle;
122
+ offset = fdt_next_node(fdt, offset, NULL);
123
+ if (offset < 0) {
124
+ if (offset == -FDT_ERR_NOTFOUND)
125
+ break;
103126
104
- if (offset < 0)
105
- return (uint32_t)-1;
127
+ return offset;
128
+ }
106129
107
- phandle = fdt_get_phandle(fdt, offset);
108
- if (phandle == (uint32_t)-1)
109
- continue;
130
+ value = fdt_get_phandle(fdt, offset);
110131
111
- if (phandle > max_phandle)
112
- max_phandle = phandle;
132
+ if (value > max)
133
+ max = value;
113134 }
135
+
136
+ if (phandle)
137
+ *phandle = max;
114138
115139 return 0;
116140 }
117141
142
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
143
+{
144
+ uint32_t max;
145
+ int err;
146
+
147
+ err = fdt_find_max_phandle(fdt, &max);
148
+ if (err < 0)
149
+ return err;
150
+
151
+ if (max == FDT_MAX_PHANDLE)
152
+ return -FDT_ERR_NOPHANDLES;
153
+
154
+ if (phandle)
155
+ *phandle = max + 1;
156
+
157
+ return 0;
158
+}
159
+
160
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
161
+{
162
+ unsigned int offset = n * sizeof(struct fdt_reserve_entry);
163
+ unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
164
+
165
+ if (!can_assume(VALID_INPUT)) {
166
+ if (absoffset < fdt_off_mem_rsvmap(fdt))
167
+ return NULL;
168
+ if (absoffset > fdt_totalsize(fdt) -
169
+ sizeof(struct fdt_reserve_entry))
170
+ return NULL;
171
+ }
172
+ return fdt_mem_rsv_(fdt, n);
173
+}
174
+
118175 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
119176 {
120
- FDT_CHECK_HEADER(fdt);
121
- *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
122
- *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
177
+ const struct fdt_reserve_entry *re;
178
+
179
+ FDT_RO_PROBE(fdt);
180
+ re = fdt_mem_rsv(fdt, n);
181
+ if (!can_assume(VALID_INPUT) && !re)
182
+ return -FDT_ERR_BADOFFSET;
183
+
184
+ *address = fdt64_ld(&re->address);
185
+ *size = fdt64_ld(&re->size);
123186 return 0;
124187 }
125188
126189 int fdt_num_mem_rsv(const void *fdt)
127190 {
128
- int i = 0;
191
+ int i;
192
+ const struct fdt_reserve_entry *re;
129193
130
- while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
131
- i++;
132
- return i;
194
+ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
195
+ if (fdt64_ld(&re->size) == 0)
196
+ return i;
197
+ }
198
+ return -FDT_ERR_TRUNCATED;
133199 }
134200
135201 static int nextprop_(const void *fdt, int offset)
....@@ -161,7 +227,7 @@
161227 {
162228 int depth;
163229
164
- FDT_CHECK_HEADER(fdt);
230
+ FDT_RO_PROBE(fdt);
165231
166232 for (depth = 0;
167233 (offset >= 0) && (depth >= 0);
....@@ -187,7 +253,7 @@
187253 const char *p = path;
188254 int offset = 0;
189255
190
- FDT_CHECK_HEADER(fdt);
256
+ FDT_RO_PROBE(fdt);
191257
192258 /* see if we have an alias */
193259 if (*path != '/') {
....@@ -237,13 +303,13 @@
237303 const char *nameptr;
238304 int err;
239305
240
- if (((err = fdt_check_header(fdt)) != 0)
306
+ if (((err = fdt_ro_probe_(fdt)) < 0)
241307 || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
242308 goto fail;
243309
244310 nameptr = nh->name;
245311
246
- if (fdt_version(fdt) < 0x10) {
312
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
247313 /*
248314 * For old FDT versions, match the naming conventions of V16:
249315 * give only the leaf name (after all /). The actual tree
....@@ -294,7 +360,8 @@
294360 int err;
295361 const struct fdt_property *prop;
296362
297
- if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
363
+ if (!can_assume(VALID_INPUT) &&
364
+ (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
298365 if (lenp)
299366 *lenp = err;
300367 return NULL;
....@@ -303,7 +370,7 @@
303370 prop = fdt_offset_ptr_(fdt, offset);
304371
305372 if (lenp)
306
- *lenp = fdt32_to_cpu(prop->len);
373
+ *lenp = fdt32_ld(&prop->len);
307374
308375 return prop;
309376 }
....@@ -315,7 +382,7 @@
315382 /* Prior to version 16, properties may need realignment
316383 * and this API does not work. fdt_getprop_*() will, however. */
317384
318
- if (fdt_version(fdt) < 0x10) {
385
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
319386 if (lenp)
320387 *lenp = -FDT_ERR_BADVERSION;
321388 return NULL;
....@@ -336,11 +403,12 @@
336403 (offset = fdt_next_property_offset(fdt, offset))) {
337404 const struct fdt_property *prop;
338405
339
- if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
406
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
407
+ if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
340408 offset = -FDT_ERR_INTERNAL;
341409 break;
342410 }
343
- if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
411
+ if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
344412 name, namelen)) {
345413 if (poffset)
346414 *poffset = offset;
....@@ -361,7 +429,7 @@
361429 {
362430 /* Prior to version 16, properties may need realignment
363431 * and this API does not work. fdt_getprop_*() will, however. */
364
- if (fdt_version(fdt) < 0x10) {
432
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
365433 if (lenp)
366434 *lenp = -FDT_ERR_BADVERSION;
367435 return NULL;
....@@ -392,8 +460,8 @@
392460 return NULL;
393461
394462 /* Handle realignment */
395
- if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
396
- fdt32_to_cpu(prop->len) >= 8)
463
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
464
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
397465 return prop->data + 4;
398466 return prop->data;
399467 }
....@@ -406,12 +474,27 @@
406474 prop = fdt_get_property_by_offset_(fdt, offset, lenp);
407475 if (!prop)
408476 return NULL;
409
- if (namep)
410
- *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
477
+ if (namep) {
478
+ const char *name;
479
+ int namelen;
480
+
481
+ if (!can_assume(VALID_INPUT)) {
482
+ name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
483
+ &namelen);
484
+ if (!name) {
485
+ if (lenp)
486
+ *lenp = namelen;
487
+ return NULL;
488
+ }
489
+ *namep = name;
490
+ } else {
491
+ *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
492
+ }
493
+ }
411494
412495 /* Handle realignment */
413
- if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
414
- fdt32_to_cpu(prop->len) >= 8)
496
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
497
+ (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
415498 return prop->data + 4;
416499 return prop->data;
417500 }
....@@ -436,7 +519,7 @@
436519 return 0;
437520 }
438521
439
- return fdt32_to_cpu(*php);
522
+ return fdt32_ld(php);
440523 }
441524
442525 const char *fdt_get_alias_namelen(const void *fdt,
....@@ -462,7 +545,7 @@
462545 int offset, depth, namelen;
463546 const char *name;
464547
465
- FDT_CHECK_HEADER(fdt);
548
+ FDT_RO_PROBE(fdt);
466549
467550 if (buflen < 2)
468551 return -FDT_ERR_NOSPACE;
....@@ -514,7 +597,7 @@
514597 int offset, depth;
515598 int supernodeoffset = -FDT_ERR_INTERNAL;
516599
517
- FDT_CHECK_HEADER(fdt);
600
+ FDT_RO_PROBE(fdt);
518601
519602 if (supernodedepth < 0)
520603 return -FDT_ERR_NOTFOUND;
....@@ -536,10 +619,12 @@
536619 }
537620 }
538621
539
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
540
- return -FDT_ERR_BADOFFSET;
541
- else if (offset == -FDT_ERR_BADOFFSET)
542
- return -FDT_ERR_BADSTRUCTURE;
622
+ if (!can_assume(VALID_INPUT)) {
623
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
624
+ return -FDT_ERR_BADOFFSET;
625
+ else if (offset == -FDT_ERR_BADOFFSET)
626
+ return -FDT_ERR_BADSTRUCTURE;
627
+ }
543628
544629 return offset; /* error from fdt_next_node() */
545630 }
....@@ -551,7 +636,8 @@
551636
552637 err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
553638 if (err)
554
- return (err < 0) ? err : -FDT_ERR_INTERNAL;
639
+ return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
640
+ -FDT_ERR_INTERNAL;
555641 return nodedepth;
556642 }
557643
....@@ -573,7 +659,7 @@
573659 const void *val;
574660 int len;
575661
576
- FDT_CHECK_HEADER(fdt);
662
+ FDT_RO_PROBE(fdt);
577663
578664 /* FIXME: The algorithm here is pretty horrible: we scan each
579665 * property of a node in fdt_getprop(), then if that didn't
....@@ -596,10 +682,10 @@
596682 {
597683 int offset;
598684
599
- if ((phandle == 0) || (phandle == -1))
685
+ if ((phandle == 0) || (phandle == ~0U))
600686 return -FDT_ERR_BADPHANDLE;
601687
602
- FDT_CHECK_HEADER(fdt);
688
+ FDT_RO_PROBE(fdt);
603689
604690 /* FIXME: The algorithm here is pretty horrible: we
605691 * potentially scan each property of a node in
....@@ -752,7 +838,7 @@
752838 {
753839 int offset, err;
754840
755
- FDT_CHECK_HEADER(fdt);
841
+ FDT_RO_PROBE(fdt);
756842
757843 /* FIXME: The algorithm here is pretty horrible: we scan each
758844 * property of a node in fdt_node_check_compatible(), then if