fdt_wip.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * libfdt - Flat Device Tree manipulation
  3. * Copyright (C) 2006 David Gibson, IBM Corporation.
  4. * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
  5. */
  6. #include <libfdt_env.h>
  7. #ifndef USE_HOSTCC
  8. #include <fdt.h>
  9. #include <libfdt.h>
  10. #else
  11. #include "fdt_host.h"
  12. #endif
  13. #include "libfdt_internal.h"
  14. int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
  15. const char *name, int namelen,
  16. uint32_t idx, const void *val,
  17. int len)
  18. {
  19. void *propval;
  20. int proplen;
  21. propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
  22. &proplen);
  23. if (!propval)
  24. return proplen;
  25. if (proplen < (len + idx))
  26. return -FDT_ERR_NOSPACE;
  27. memcpy((char *)propval + idx, val, len);
  28. return 0;
  29. }
  30. int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  31. const void *val, int len)
  32. {
  33. const void *propval;
  34. int proplen;
  35. propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
  36. if (!propval)
  37. return proplen;
  38. if (proplen != len)
  39. return -FDT_ERR_NOSPACE;
  40. return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
  41. strlen(name), 0,
  42. val, len);
  43. }
  44. static void _fdt_nop_region(void *start, int len)
  45. {
  46. fdt32_t *p;
  47. for (p = start; (char *)p < ((char *)start + len); p++)
  48. *p = cpu_to_fdt32(FDT_NOP);
  49. }
  50. int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
  51. {
  52. struct fdt_property *prop;
  53. int len;
  54. prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
  55. if (!prop)
  56. return len;
  57. _fdt_nop_region(prop, len + sizeof(*prop));
  58. return 0;
  59. }
  60. int _fdt_node_end_offset(void *fdt, int offset)
  61. {
  62. int depth = 0;
  63. while ((offset >= 0) && (depth >= 0))
  64. offset = fdt_next_node(fdt, offset, &depth);
  65. return offset;
  66. }
  67. int fdt_nop_node(void *fdt, int nodeoffset)
  68. {
  69. int endoffset;
  70. endoffset = _fdt_node_end_offset(fdt, nodeoffset);
  71. if (endoffset < 0)
  72. return endoffset;
  73. _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
  74. endoffset - nodeoffset);
  75. return 0;
  76. }
  77. #define FDT_MAX_DEPTH 32
  78. static int str_in_list(const char *str, char * const list[], int count)
  79. {
  80. int i;
  81. for (i = 0; i < count; i++)
  82. if (!strcmp(list[i], str))
  83. return 1;
  84. return 0;
  85. }
  86. int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
  87. char * const exc_prop[], int exc_prop_count,
  88. struct fdt_region region[], int max_regions,
  89. char *path, int path_len, int add_string_tab)
  90. {
  91. int stack[FDT_MAX_DEPTH];
  92. char *end;
  93. int nextoffset = 0;
  94. uint32_t tag;
  95. int count = 0;
  96. int start = -1;
  97. int depth = -1;
  98. int want = 0;
  99. int base = fdt_off_dt_struct(fdt);
  100. end = path;
  101. *end = '\0';
  102. do {
  103. const struct fdt_property *prop;
  104. const char *name;
  105. const char *str;
  106. int include = 0;
  107. int stop_at = 0;
  108. int offset;
  109. int len;
  110. offset = nextoffset;
  111. tag = fdt_next_tag(fdt, offset, &nextoffset);
  112. stop_at = nextoffset;
  113. switch (tag) {
  114. case FDT_PROP:
  115. include = want >= 2;
  116. stop_at = offset;
  117. prop = fdt_get_property_by_offset(fdt, offset, NULL);
  118. str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
  119. if (str_in_list(str, exc_prop, exc_prop_count))
  120. include = 0;
  121. break;
  122. case FDT_NOP:
  123. include = want >= 2;
  124. stop_at = offset;
  125. break;
  126. case FDT_BEGIN_NODE:
  127. depth++;
  128. if (depth == FDT_MAX_DEPTH)
  129. return -FDT_ERR_BADSTRUCTURE;
  130. name = fdt_get_name(fdt, offset, &len);
  131. if (end - path + 2 + len >= path_len)
  132. return -FDT_ERR_NOSPACE;
  133. if (end != path + 1)
  134. *end++ = '/';
  135. strcpy(end, name);
  136. end += len;
  137. stack[depth] = want;
  138. if (want == 1)
  139. stop_at = offset;
  140. if (str_in_list(path, inc, inc_count))
  141. want = 2;
  142. else if (want)
  143. want--;
  144. else
  145. stop_at = offset;
  146. include = want;
  147. break;
  148. case FDT_END_NODE:
  149. include = want;
  150. want = stack[depth--];
  151. while (end > path && *--end != '/')
  152. ;
  153. *end = '\0';
  154. break;
  155. case FDT_END:
  156. include = 1;
  157. break;
  158. }
  159. if (include && start == -1) {
  160. /* Should we merge with previous? */
  161. if (count && count <= max_regions &&
  162. offset == region[count - 1].offset +
  163. region[count - 1].size - base)
  164. start = region[--count].offset - base;
  165. else
  166. start = offset;
  167. }
  168. if (!include && start != -1) {
  169. if (count < max_regions) {
  170. region[count].offset = base + start;
  171. region[count].size = stop_at - start;
  172. }
  173. count++;
  174. start = -1;
  175. }
  176. } while (tag != FDT_END);
  177. if (nextoffset != fdt_size_dt_struct(fdt))
  178. return -FDT_ERR_BADLAYOUT;
  179. /* Add a region for the END tag and the string table */
  180. if (count < max_regions) {
  181. region[count].offset = base + start;
  182. region[count].size = nextoffset - start;
  183. if (add_string_tab)
  184. region[count].size += fdt_size_dt_strings(fdt);
  185. }
  186. count++;
  187. return count;
  188. }