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