| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) | |
| /* | |
| * libfdt - Flat Device Tree manipulation | |
| * Copyright (C) 2006 David Gibson, IBM Corporation. | |
| */ | |
| #include "libfdt_env.h" | |
| #include <fdt.h> | |
| #include <libfdt.h> | |
| #include "libfdt_internal.h" | |
| int fdt_check_full(const void *fdt, size_t bufsize) | |
| { | |
| int err; | |
| int num_memrsv; | |
| int offset, nextoffset = 0; | |
| uint32_t tag; | |
| unsigned int depth = 0; | |
| const void *prop; | |
| const char *propname; | |
| bool expect_end = false; | |
| if (bufsize < FDT_V1_SIZE) | |
| return -FDT_ERR_TRUNCATED; | |
| if (bufsize < fdt_header_size(fdt)) | |
| return -FDT_ERR_TRUNCATED; | |
| err = fdt_check_header(fdt); | |
| if (err != 0) | |
| return err; | |
| if (bufsize < fdt_totalsize(fdt)) | |
| return -FDT_ERR_TRUNCATED; | |
| num_memrsv = fdt_num_mem_rsv(fdt); | |
| if (num_memrsv < 0) | |
| return num_memrsv; | |
| while (1) { | |
| offset = nextoffset; | |
| tag = fdt_next_tag(fdt, offset, &nextoffset); | |
| if (nextoffset < 0) | |
| return nextoffset; | |
| /* If we see two root nodes, something is wrong */ | |
| if (expect_end && tag != FDT_END) | |
| return -FDT_ERR_BADSTRUCTURE; | |
| switch (tag) { | |
| case FDT_NOP: | |
| break; | |
| case FDT_END: | |
| if (depth != 0) | |
| return -FDT_ERR_BADSTRUCTURE; | |
| return 0; | |
| case FDT_BEGIN_NODE: | |
| depth++; | |
| if (depth > INT_MAX) | |
| return -FDT_ERR_BADSTRUCTURE; | |
| /* The root node must have an empty name */ | |
| if (depth == 1) { | |
| const char *name; | |
| int len; | |
| name = fdt_get_name(fdt, offset, &len); | |
| if (*name || len) | |
| return -FDT_ERR_BADSTRUCTURE; | |
| } | |
| break; | |
| case FDT_END_NODE: | |
| if (depth == 0) | |
| return -FDT_ERR_BADSTRUCTURE; | |
| depth--; | |
| if (depth == 0) | |
| expect_end = true; | |
| break; | |
| case FDT_PROP: | |
| prop = fdt_getprop_by_offset(fdt, offset, &propname, | |
| &err); | |
| if (!prop) | |
| return err; | |
| break; | |
| default: | |
| return -FDT_ERR_INTERNAL; | |
| } | |
| } | |
| } |