fdt_check.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. #include <fdt.h>
  8. #include <libfdt.h>
  9. #include "libfdt_internal.h"
  10. int fdt_check_full(const void *fdt, size_t bufsize)
  11. {
  12. int err;
  13. int num_memrsv;
  14. int offset, nextoffset = 0;
  15. uint32_t tag;
  16. unsigned int depth = 0;
  17. const void *prop;
  18. const char *propname;
  19. bool expect_end = false;
  20. if (bufsize < FDT_V1_SIZE)
  21. return -FDT_ERR_TRUNCATED;
  22. if (bufsize < fdt_header_size(fdt))
  23. return -FDT_ERR_TRUNCATED;
  24. err = fdt_check_header(fdt);
  25. if (err != 0)
  26. return err;
  27. if (bufsize < fdt_totalsize(fdt))
  28. return -FDT_ERR_TRUNCATED;
  29. num_memrsv = fdt_num_mem_rsv(fdt);
  30. if (num_memrsv < 0)
  31. return num_memrsv;
  32. while (1) {
  33. offset = nextoffset;
  34. tag = fdt_next_tag(fdt, offset, &nextoffset);
  35. if (nextoffset < 0)
  36. return nextoffset;
  37. /* If we see two root nodes, something is wrong */
  38. if (expect_end && tag != FDT_END)
  39. return -FDT_ERR_BADSTRUCTURE;
  40. switch (tag) {
  41. case FDT_NOP:
  42. break;
  43. case FDT_END:
  44. if (depth != 0)
  45. return -FDT_ERR_BADSTRUCTURE;
  46. return 0;
  47. case FDT_BEGIN_NODE:
  48. depth++;
  49. if (depth > INT_MAX)
  50. return -FDT_ERR_BADSTRUCTURE;
  51. /* The root node must have an empty name */
  52. if (depth == 1) {
  53. const char *name;
  54. int len;
  55. name = fdt_get_name(fdt, offset, &len);
  56. if (*name || len)
  57. return -FDT_ERR_BADSTRUCTURE;
  58. }
  59. break;
  60. case FDT_END_NODE:
  61. if (depth == 0)
  62. return -FDT_ERR_BADSTRUCTURE;
  63. depth--;
  64. if (depth == 0)
  65. expect_end = true;
  66. break;
  67. case FDT_PROP:
  68. prop = fdt_getprop_by_offset(fdt, offset, &propname,
  69. &err);
  70. if (!prop)
  71. return err;
  72. break;
  73. default:
  74. return -FDT_ERR_INTERNAL;
  75. }
  76. }
  77. }