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