fdt_wrappers.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. /* Helper functions to offer easier navigation of Device Tree Blob */
  7. #include <assert.h>
  8. #include <string.h>
  9. #include <libfdt.h>
  10. #include <common/debug.h>
  11. #include <common/fdt_wrappers.h>
  12. /*
  13. * Read cells from a given property of the given node. At most 2 cells of the
  14. * property are read, and pointer is updated. Returns 0 on success, and -1 upon
  15. * error
  16. */
  17. int fdtw_read_cells(const void *dtb, int node, const char *prop,
  18. unsigned int cells, void *value)
  19. {
  20. const uint32_t *value_ptr;
  21. uint32_t hi = 0, lo;
  22. int value_len;
  23. assert(dtb != NULL);
  24. assert(prop != NULL);
  25. assert(value != NULL);
  26. assert(node >= 0);
  27. /* We expect either 1 or 2 cell property */
  28. assert(cells <= 2U);
  29. /* Access property and obtain its length (in bytes) */
  30. value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
  31. &value_len);
  32. if (value_ptr == NULL) {
  33. WARN("Couldn't find property %s in dtb\n", prop);
  34. return -1;
  35. }
  36. /* Verify that property length accords with cell length */
  37. if (NCELLS((unsigned int)value_len) != cells) {
  38. WARN("Property length mismatch\n");
  39. return -1;
  40. }
  41. if (cells == 2U) {
  42. hi = fdt32_to_cpu(*value_ptr);
  43. value_ptr++;
  44. }
  45. lo = fdt32_to_cpu(*value_ptr);
  46. if (cells == 2U)
  47. *((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
  48. else
  49. *((uint32_t *) value) = lo;
  50. return 0;
  51. }
  52. /*
  53. * Read cells from a given property of the given node. Any number of 32-bit
  54. * cells of the property can be read. The fdt pointer is updated. Returns 0 on
  55. * success, and -1 on error.
  56. */
  57. int fdtw_read_array(const void *dtb, int node, const char *prop,
  58. unsigned int cells, void *value)
  59. {
  60. const uint32_t *value_ptr;
  61. int value_len;
  62. assert(dtb != NULL);
  63. assert(prop != NULL);
  64. assert(value != NULL);
  65. assert(node >= 0);
  66. /* Access property and obtain its length (in bytes) */
  67. value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
  68. &value_len);
  69. if (value_ptr == NULL) {
  70. WARN("Couldn't find property %s in dtb\n", prop);
  71. return -1;
  72. }
  73. /* Verify that property length accords with cell length */
  74. if (NCELLS((unsigned int)value_len) != cells) {
  75. WARN("Property length mismatch\n");
  76. return -1;
  77. }
  78. uint32_t *dst = value;
  79. for (unsigned int i = 0U; i < cells; i++) {
  80. dst[i] = fdt32_to_cpu(value_ptr[i]);
  81. }
  82. return 0;
  83. }
  84. /*
  85. * Read string from a given property of the given node. Up to 'size - 1'
  86. * characters are read, and a NUL terminator is added. Returns 0 on success,
  87. * and -1 upon error.
  88. */
  89. int fdtw_read_string(const void *dtb, int node, const char *prop,
  90. char *str, size_t size)
  91. {
  92. const char *ptr;
  93. size_t len;
  94. assert(dtb != NULL);
  95. assert(node >= 0);
  96. assert(prop != NULL);
  97. assert(str != NULL);
  98. assert(size > 0U);
  99. ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL);
  100. if (ptr == NULL) {
  101. WARN("Couldn't find property %s in dtb\n", prop);
  102. return -1;
  103. }
  104. len = strlcpy(str, ptr, size);
  105. if (len >= size) {
  106. WARN("String of property %s in dtb has been truncated\n", prop);
  107. return -1;
  108. }
  109. return 0;
  110. }
  111. /*
  112. * Write cells in place to a given property of the given node. At most 2 cells
  113. * of the property are written. Returns 0 on success, and -1 upon error.
  114. */
  115. int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
  116. unsigned int cells, void *value)
  117. {
  118. int err, len;
  119. assert(dtb != NULL);
  120. assert(prop != NULL);
  121. assert(value != NULL);
  122. assert(node >= 0);
  123. /* We expect either 1 or 2 cell property */
  124. assert(cells <= 2U);
  125. if (cells == 2U)
  126. *(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value);
  127. else
  128. *(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value);
  129. len = (int)cells * 4;
  130. /* Set property value in place */
  131. err = fdt_setprop_inplace(dtb, node, prop, value, len);
  132. if (err != 0) {
  133. WARN("Modify property %s failed with error %d\n", prop, err);
  134. return -1;
  135. }
  136. return 0;
  137. }