2
0

device_tree.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Functions to help device tree manipulation using libfdt.
  3. * It also provides functions to read entries from device tree proc
  4. * interface.
  5. *
  6. * Copyright 2008 IBM Corporation.
  7. * Authors: Jerone Young <jyoung5@us.ibm.com>
  8. * Hollis Blanchard <hollisb@us.ibm.com>
  9. *
  10. * This work is licensed under the GNU GPL license version 2 or later.
  11. *
  12. */
  13. #include <stdio.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include "config.h"
  20. #include "qemu-common.h"
  21. #include "device_tree.h"
  22. #include "hw/loader.h"
  23. #include <libfdt.h>
  24. void *load_device_tree(const char *filename_path, int *sizep)
  25. {
  26. int dt_size;
  27. int dt_file_load_size;
  28. int ret;
  29. void *fdt = NULL;
  30. *sizep = 0;
  31. dt_size = get_image_size(filename_path);
  32. if (dt_size < 0) {
  33. printf("Unable to get size of device tree file '%s'\n",
  34. filename_path);
  35. goto fail;
  36. }
  37. /* Expand to 2x size to give enough room for manipulation. */
  38. dt_size += 10000;
  39. dt_size *= 2;
  40. /* First allocate space in qemu for device tree */
  41. fdt = g_malloc0(dt_size);
  42. dt_file_load_size = load_image(filename_path, fdt);
  43. if (dt_file_load_size < 0) {
  44. printf("Unable to open device tree file '%s'\n",
  45. filename_path);
  46. goto fail;
  47. }
  48. ret = fdt_open_into(fdt, fdt, dt_size);
  49. if (ret) {
  50. printf("Unable to copy device tree in memory\n");
  51. goto fail;
  52. }
  53. /* Check sanity of device tree */
  54. if (fdt_check_header(fdt)) {
  55. printf ("Device tree file loaded into memory is invalid: %s\n",
  56. filename_path);
  57. goto fail;
  58. }
  59. *sizep = dt_size;
  60. return fdt;
  61. fail:
  62. g_free(fdt);
  63. return NULL;
  64. }
  65. static int findnode_nofail(void *fdt, const char *node_path)
  66. {
  67. int offset;
  68. offset = fdt_path_offset(fdt, node_path);
  69. if (offset < 0) {
  70. fprintf(stderr, "%s Couldn't find node %s: %s\n", __func__, node_path,
  71. fdt_strerror(offset));
  72. exit(1);
  73. }
  74. return offset;
  75. }
  76. int qemu_devtree_setprop(void *fdt, const char *node_path,
  77. const char *property, void *val_array, int size)
  78. {
  79. int r;
  80. r = fdt_setprop(fdt, findnode_nofail(fdt, node_path), property, val_array, size);
  81. if (r < 0) {
  82. fprintf(stderr, "%s: Couldn't set %s/%s: %s\n", __func__, node_path,
  83. property, fdt_strerror(r));
  84. exit(1);
  85. }
  86. return r;
  87. }
  88. int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
  89. const char *property, uint32_t val)
  90. {
  91. int r;
  92. r = fdt_setprop_cell(fdt, findnode_nofail(fdt, node_path), property, val);
  93. if (r < 0) {
  94. fprintf(stderr, "%s: Couldn't set %s/%s = %#08x: %s\n", __func__,
  95. node_path, property, val, fdt_strerror(r));
  96. exit(1);
  97. }
  98. return r;
  99. }
  100. int qemu_devtree_setprop_string(void *fdt, const char *node_path,
  101. const char *property, const char *string)
  102. {
  103. int r;
  104. r = fdt_setprop_string(fdt, findnode_nofail(fdt, node_path), property, string);
  105. if (r < 0) {
  106. fprintf(stderr, "%s: Couldn't set %s/%s = %s: %s\n", __func__,
  107. node_path, property, string, fdt_strerror(r));
  108. exit(1);
  109. }
  110. return r;
  111. }
  112. int qemu_devtree_nop_node(void *fdt, const char *node_path)
  113. {
  114. int r;
  115. r = fdt_nop_node(fdt, findnode_nofail(fdt, node_path));
  116. if (r < 0) {
  117. fprintf(stderr, "%s: Couldn't nop node %s: %s\n", __func__, node_path,
  118. fdt_strerror(r));
  119. exit(1);
  120. }
  121. return r;
  122. }
  123. int qemu_devtree_add_subnode(void *fdt, const char *name)
  124. {
  125. char *dupname = g_strdup(name);
  126. char *basename = strrchr(dupname, '/');
  127. int retval;
  128. if (!basename) {
  129. g_free(dupname);
  130. return -1;
  131. }
  132. basename[0] = '\0';
  133. basename++;
  134. retval = fdt_add_subnode(fdt, findnode_nofail(fdt, dupname), basename);
  135. if (retval < 0) {
  136. fprintf(stderr, "FDT: Failed to create subnode %s: %s\n", name,
  137. fdt_strerror(retval));
  138. exit(1);
  139. }
  140. g_free(dupname);
  141. return retval;
  142. }