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
13int 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 || 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