1 // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2 /*
3 * libfdt - Flat Device Tree manipulation
4 * Copyright (C) 2006 David Gibson, IBM Corporation.
5 */
6 #include "libfdt_env.h"
7
8 #include <fdt.h>
9 #include <libfdt.h>
10
11 #include "libfdt_internal.h"
12
fdt_check_full(const void * fdt,size_t bufsize)13 int fdt_check_full(const void *fdt, size_t bufsize)
14 {
15 int err;
16 int num_memrsv;
17 int offset, nextoffset = 0;
18 uint32_t tag;
19 unsigned int depth = 0;
20 const void *prop;
21 const char *propname;
22 bool expect_end = false;
23
24 if (bufsize < FDT_V1_SIZE)
25 return -FDT_ERR_TRUNCATED;
26 if (bufsize < fdt_header_size(fdt))
27 return -FDT_ERR_TRUNCATED;
28 err = fdt_check_header(fdt);
29 if (err != 0)
30 return err;
31 if (bufsize < fdt_totalsize(fdt))
32 return -FDT_ERR_TRUNCATED;
33
34 num_memrsv = fdt_num_mem_rsv(fdt);
35 if (num_memrsv < 0)
36 return num_memrsv;
37
38 while (1) {
39 offset = nextoffset;
40 tag = fdt_next_tag(fdt, offset, &nextoffset);
41
42 if (nextoffset < 0)
43 return nextoffset;
44
45 /* If we see two root nodes, something is wrong */
46 if (expect_end && tag != FDT_END)
47 return -FDT_ERR_BADSTRUCTURE;
48
49 switch (tag) {
50 case FDT_NOP:
51 break;
52
53 case FDT_END:
54 if (depth != 0)
55 return -FDT_ERR_BADSTRUCTURE;
56 return 0;
57
58 case FDT_BEGIN_NODE:
59 depth++;
60 if (depth > INT_MAX)
61 return -FDT_ERR_BADSTRUCTURE;
62
63 /* The root node must have an empty name */
64 if (depth == 1) {
65 const char *name;
66 int len;
67
68 name = fdt_get_name(fdt, offset, &len);
69 if (!name || *name || len)
70 return -FDT_ERR_BADSTRUCTURE;
71 }
72 break;
73
74 case FDT_END_NODE:
75 if (depth == 0)
76 return -FDT_ERR_BADSTRUCTURE;
77 depth--;
78 if (depth == 0)
79 expect_end = true;
80 break;
81
82 case FDT_PROP:
83 prop = fdt_getprop_by_offset(fdt, offset, &propname,
84 &err);
85 if (!prop)
86 return err;
87 break;
88
89 default:
90 return -FDT_ERR_INTERNAL;
91 }
92 }
93 }
94