hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/scripts/dtc/libfdt/fdt_rw.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
....@@ -67,29 +22,31 @@
6722 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
6823 }
6924
70
-static int fdt_rw_check_header_(void *fdt)
25
+static int fdt_rw_probe_(void *fdt)
7126 {
72
- FDT_CHECK_HEADER(fdt);
27
+ if (can_assume(VALID_DTB))
28
+ return 0;
29
+ FDT_RO_PROBE(fdt);
7330
74
- if (fdt_version(fdt) < 17)
31
+ if (!can_assume(LATEST) && fdt_version(fdt) < 17)
7532 return -FDT_ERR_BADVERSION;
7633 if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
7734 fdt_size_dt_struct(fdt)))
7835 return -FDT_ERR_BADLAYOUT;
79
- if (fdt_version(fdt) > 17)
36
+ if (!can_assume(LATEST) && fdt_version(fdt) > 17)
8037 fdt_set_version(fdt, 17);
8138
8239 return 0;
8340 }
8441
85
-#define FDT_RW_CHECK_HEADER(fdt) \
42
+#define FDT_RW_PROBE(fdt) \
8643 { \
8744 int err_; \
88
- if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
45
+ if ((err_ = fdt_rw_probe_(fdt)) != 0) \
8946 return err_; \
9047 }
9148
92
-static inline int fdt_data_size_(void *fdt)
49
+static inline unsigned int fdt_data_size_(void *fdt)
9350 {
9451 return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
9552 }
....@@ -97,15 +54,16 @@
9754 static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
9855 {
9956 char *p = splicepoint;
100
- char *end = (char *)fdt + fdt_data_size_(fdt);
57
+ unsigned int dsize = fdt_data_size_(fdt);
58
+ size_t soff = p - (char *)fdt;
10159
102
- if (((p + oldlen) < p) || ((p + oldlen) > end))
60
+ if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
10361 return -FDT_ERR_BADOFFSET;
104
- if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
62
+ if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
10563 return -FDT_ERR_BADOFFSET;
106
- if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
64
+ if (dsize - oldlen + newlen > fdt_totalsize(fdt))
10765 return -FDT_ERR_NOSPACE;
108
- memmove(p + newlen, p + oldlen, end - p - oldlen);
66
+ memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
10967 return 0;
11068 }
11169
....@@ -136,6 +94,14 @@
13694 return 0;
13795 }
13896
97
+/* Must only be used to roll back in case of error */
98
+static void fdt_del_last_string_(void *fdt, const char *s)
99
+{
100
+ int newlen = strlen(s) + 1;
101
+
102
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
103
+}
104
+
139105 static int fdt_splice_string_(void *fdt, int newlen)
140106 {
141107 void *p = (char *)fdt
....@@ -149,13 +115,25 @@
149115 return 0;
150116 }
151117
152
-static int fdt_find_add_string_(void *fdt, const char *s)
118
+/**
119
+ * fdt_find_add_string_() - Find or allocate a string
120
+ *
121
+ * @fdt: pointer to the device tree to check/adjust
122
+ * @s: string to find/add
123
+ * @allocated: Set to 0 if the string was found, 1 if not found and so
124
+ * allocated. Ignored if can_assume(NO_ROLLBACK)
125
+ * @return offset of string in the string table (whether found or added)
126
+ */
127
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
153128 {
154129 char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
155130 const char *p;
156131 char *new;
157132 int len = strlen(s) + 1;
158133 int err;
134
+
135
+ if (!can_assume(NO_ROLLBACK))
136
+ *allocated = 0;
159137
160138 p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
161139 if (p)
....@@ -167,6 +145,9 @@
167145 if (err)
168146 return err;
169147
148
+ if (!can_assume(NO_ROLLBACK))
149
+ *allocated = 1;
150
+
170151 memcpy(new, s, len);
171152 return (new - strtab);
172153 }
....@@ -176,7 +157,7 @@
176157 struct fdt_reserve_entry *re;
177158 int err;
178159
179
- FDT_RW_CHECK_HEADER(fdt);
160
+ FDT_RW_PROBE(fdt);
180161
181162 re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
182163 err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
....@@ -192,7 +173,7 @@
192173 {
193174 struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
194175
195
- FDT_RW_CHECK_HEADER(fdt);
176
+ FDT_RW_PROBE(fdt);
196177
197178 if (n >= fdt_num_mem_rsv(fdt))
198179 return -FDT_ERR_NOTFOUND;
....@@ -225,11 +206,12 @@
225206 int nextoffset;
226207 int namestroff;
227208 int err;
209
+ int allocated;
228210
229211 if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
230212 return nextoffset;
231213
232
- namestroff = fdt_find_add_string_(fdt, name);
214
+ namestroff = fdt_find_add_string_(fdt, name, &allocated);
233215 if (namestroff < 0)
234216 return namestroff;
235217
....@@ -237,8 +219,12 @@
237219 proplen = sizeof(**prop) + FDT_TAGALIGN(len);
238220
239221 err = fdt_splice_struct_(fdt, *prop, 0, proplen);
240
- if (err)
222
+ if (err) {
223
+ /* Delete the string if we failed to add it */
224
+ if (!can_assume(NO_ROLLBACK) && allocated)
225
+ fdt_del_last_string_(fdt, name);
241226 return err;
227
+ }
242228
243229 (*prop)->tag = cpu_to_fdt32(FDT_PROP);
244230 (*prop)->nameoff = cpu_to_fdt32(namestroff);
....@@ -252,7 +238,7 @@
252238 int oldlen, newlen;
253239 int err;
254240
255
- FDT_RW_CHECK_HEADER(fdt);
241
+ FDT_RW_PROBE(fdt);
256242
257243 namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
258244 if (!namep)
....@@ -275,7 +261,7 @@
275261 struct fdt_property *prop;
276262 int err;
277263
278
- FDT_RW_CHECK_HEADER(fdt);
264
+ FDT_RW_PROBE(fdt);
279265
280266 err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
281267 if (err == -FDT_ERR_NOTFOUND)
....@@ -308,7 +294,7 @@
308294 struct fdt_property *prop;
309295 int err, oldlen, newlen;
310296
311
- FDT_RW_CHECK_HEADER(fdt);
297
+ FDT_RW_PROBE(fdt);
312298
313299 prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
314300 if (prop) {
....@@ -334,7 +320,7 @@
334320 struct fdt_property *prop;
335321 int len, proplen;
336322
337
- FDT_RW_CHECK_HEADER(fdt);
323
+ FDT_RW_PROBE(fdt);
338324
339325 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
340326 if (!prop)
....@@ -354,7 +340,7 @@
354340 uint32_t tag;
355341 fdt32_t *endtag;
356342
357
- FDT_RW_CHECK_HEADER(fdt);
343
+ FDT_RW_PROBE(fdt);
358344
359345 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
360346 if (offset >= 0)
....@@ -394,7 +380,7 @@
394380 {
395381 int endoffset;
396382
397
- FDT_RW_CHECK_HEADER(fdt);
383
+ FDT_RW_PROBE(fdt);
398384
399385 endoffset = fdt_node_end_offset_(fdt, nodeoffset);
400386 if (endoffset < 0)
....@@ -435,12 +421,12 @@
435421 const char *fdtend = fdtstart + fdt_totalsize(fdt);
436422 char *tmp;
437423
438
- FDT_CHECK_HEADER(fdt);
424
+ FDT_RO_PROBE(fdt);
439425
440426 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
441427 * sizeof(struct fdt_reserve_entry);
442428
443
- if (fdt_version(fdt) >= 17) {
429
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
444430 struct_size = fdt_size_dt_struct(fdt);
445431 } else {
446432 struct_size = 0;
....@@ -450,7 +436,8 @@
450436 return struct_size;
451437 }
452438
453
- if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
439
+ if (can_assume(LIBFDT_ORDER) ||
440
+ !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
454441 /* no further work necessary */
455442 err = fdt_move(fdt, buf, bufsize);
456443 if (err)
....@@ -494,7 +481,7 @@
494481 {
495482 int mem_rsv_size;
496483
497
- FDT_RW_CHECK_HEADER(fdt);
484
+ FDT_RW_PROBE(fdt);
498485
499486 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
500487 * sizeof(struct fdt_reserve_entry);