libfdt-wrapper.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * This file does the necessary interface mapping between the bootwrapper
  4. * device tree operations and the interface provided by shared source
  5. * files flatdevicetree.[ch].
  6. *
  7. * Copyright 2007 David Gibson, IBM Corporation.
  8. */
  9. #include <stddef.h>
  10. #include <stdio.h>
  11. #include <page.h>
  12. #include <libfdt.h>
  13. #include "ops.h"
  14. #define DEBUG 0
  15. #define BAD_ERROR(err) (((err) < 0) \
  16. && ((err) != -FDT_ERR_NOTFOUND) \
  17. && ((err) != -FDT_ERR_EXISTS))
  18. #define check_err(err) \
  19. ({ \
  20. if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
  21. printf("%s():%d %s\n\r", __func__, __LINE__, \
  22. fdt_strerror(err)); \
  23. if (BAD_ERROR(err)) \
  24. exit(); \
  25. (err < 0) ? -1 : 0; \
  26. })
  27. #define offset_devp(off) \
  28. ({ \
  29. unsigned long _offset = (off); \
  30. check_err(_offset) ? NULL : (void *)(_offset+1); \
  31. })
  32. #define devp_offset_find(devp) (((unsigned long)(devp))-1)
  33. #define devp_offset(devp) (devp ? ((unsigned long)(devp))-1 : 0)
  34. static void *fdt;
  35. static void *buf; /* = NULL */
  36. #define EXPAND_GRANULARITY 1024
  37. static void expand_buf(int minexpand)
  38. {
  39. int size = fdt_totalsize(fdt);
  40. int rc;
  41. size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
  42. buf = platform_ops.realloc(buf, size);
  43. if (!buf)
  44. fatal("Couldn't find %d bytes to expand device tree\n\r", size);
  45. rc = fdt_open_into(fdt, buf, size);
  46. if (rc != 0)
  47. fatal("Couldn't expand fdt into new buffer: %s\n\r",
  48. fdt_strerror(rc));
  49. fdt = buf;
  50. }
  51. static void *fdt_wrapper_finddevice(const char *path)
  52. {
  53. return offset_devp(fdt_path_offset(fdt, path));
  54. }
  55. static int fdt_wrapper_getprop(const void *devp, const char *name,
  56. void *buf, const int buflen)
  57. {
  58. const void *p;
  59. int len;
  60. p = fdt_getprop(fdt, devp_offset(devp), name, &len);
  61. if (!p)
  62. return check_err(len);
  63. memcpy(buf, p, min(len, buflen));
  64. return len;
  65. }
  66. static int fdt_wrapper_setprop(const void *devp, const char *name,
  67. const void *buf, const int len)
  68. {
  69. int rc;
  70. rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
  71. if (rc == -FDT_ERR_NOSPACE) {
  72. expand_buf(len + 16);
  73. rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
  74. }
  75. return check_err(rc);
  76. }
  77. static int fdt_wrapper_del_node(const void *devp)
  78. {
  79. return fdt_del_node(fdt, devp_offset(devp));
  80. }
  81. static void *fdt_wrapper_get_parent(const void *devp)
  82. {
  83. return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
  84. }
  85. static void *fdt_wrapper_create_node(const void *devp, const char *name)
  86. {
  87. int offset;
  88. offset = fdt_add_subnode(fdt, devp_offset(devp), name);
  89. if (offset == -FDT_ERR_NOSPACE) {
  90. expand_buf(strlen(name) + 16);
  91. offset = fdt_add_subnode(fdt, devp_offset(devp), name);
  92. }
  93. return offset_devp(offset);
  94. }
  95. static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
  96. const char *name,
  97. const char *val,
  98. int len)
  99. {
  100. int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),
  101. name, val, len);
  102. return offset_devp(offset);
  103. }
  104. static void *fdt_wrapper_find_node_by_compatible(const void *prev,
  105. const char *val)
  106. {
  107. int offset = fdt_node_offset_by_compatible(fdt, devp_offset_find(prev),
  108. val);
  109. return offset_devp(offset);
  110. }
  111. static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
  112. {
  113. int rc;
  114. rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
  115. if (check_err(rc))
  116. return NULL;
  117. return buf;
  118. }
  119. static unsigned long fdt_wrapper_finalize(void)
  120. {
  121. int rc;
  122. rc = fdt_pack(fdt);
  123. if (rc != 0)
  124. fatal("Couldn't pack flat tree: %s\n\r",
  125. fdt_strerror(rc));
  126. return (unsigned long)fdt;
  127. }
  128. void fdt_init(void *blob)
  129. {
  130. int err;
  131. int bufsize;
  132. dt_ops.finddevice = fdt_wrapper_finddevice;
  133. dt_ops.getprop = fdt_wrapper_getprop;
  134. dt_ops.setprop = fdt_wrapper_setprop;
  135. dt_ops.get_parent = fdt_wrapper_get_parent;
  136. dt_ops.create_node = fdt_wrapper_create_node;
  137. dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
  138. dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;
  139. dt_ops.del_node = fdt_wrapper_del_node;
  140. dt_ops.get_path = fdt_wrapper_get_path;
  141. dt_ops.finalize = fdt_wrapper_finalize;
  142. /* Make sure the dt blob is the right version and so forth */
  143. fdt = blob;
  144. bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY;
  145. buf = malloc(bufsize);
  146. if(!buf)
  147. fatal("malloc failed. can't relocate the device tree\n\r");
  148. err = fdt_open_into(fdt, buf, bufsize);
  149. if (err != 0)
  150. fatal("fdt_init(): %s\n\r", fdt_strerror(err));
  151. fdt = buf;
  152. }