yamltree.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * (C) Copyright Linaro, Ltd. 2018
  3. * (C) Copyright Arm Holdings. 2017
  4. * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  19. * USA
  20. */
  21. #include <stdlib.h>
  22. #include <yaml.h>
  23. #include "dtc.h"
  24. #include "srcpos.h"
  25. char *yaml_error_name[] = {
  26. [YAML_NO_ERROR] = "no error",
  27. [YAML_MEMORY_ERROR] = "memory error",
  28. [YAML_READER_ERROR] = "reader error",
  29. [YAML_SCANNER_ERROR] = "scanner error",
  30. [YAML_PARSER_ERROR] = "parser error",
  31. [YAML_COMPOSER_ERROR] = "composer error",
  32. [YAML_WRITER_ERROR] = "writer error",
  33. [YAML_EMITTER_ERROR] = "emitter error",
  34. };
  35. #define yaml_emitter_emit_or_die(emitter, event) ( \
  36. { \
  37. if (!yaml_emitter_emit(emitter, event)) \
  38. die("yaml '%s': %s in %s, line %i\n", \
  39. yaml_error_name[(emitter)->error], \
  40. (emitter)->problem, __func__, __LINE__); \
  41. })
  42. static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
  43. {
  44. yaml_event_t event;
  45. void *tag;
  46. int off, start_offset = markers->offset;
  47. switch(width) {
  48. case 1: tag = "!u8"; break;
  49. case 2: tag = "!u16"; break;
  50. case 4: tag = "!u32"; break;
  51. case 8: tag = "!u64"; break;
  52. default:
  53. die("Invalid width %i", width);
  54. }
  55. assert(len % width == 0);
  56. yaml_sequence_start_event_initialize(&event, NULL,
  57. (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
  58. yaml_emitter_emit_or_die(emitter, &event);
  59. for (off = 0; off < len; off += width) {
  60. char buf[32];
  61. struct marker *m;
  62. bool is_phandle = false;
  63. switch(width) {
  64. case 1:
  65. sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
  66. break;
  67. case 2:
  68. sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off)));
  69. break;
  70. case 4:
  71. sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off)));
  72. m = markers;
  73. is_phandle = false;
  74. for_each_marker_of_type(m, REF_PHANDLE) {
  75. if (m->offset == (start_offset + off)) {
  76. is_phandle = true;
  77. break;
  78. }
  79. }
  80. break;
  81. case 8:
  82. sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off)));
  83. break;
  84. }
  85. if (is_phandle)
  86. yaml_scalar_event_initialize(&event, NULL,
  87. (yaml_char_t*)"!phandle", (yaml_char_t *)buf,
  88. strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
  89. else
  90. yaml_scalar_event_initialize(&event, NULL,
  91. (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
  92. strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
  93. yaml_emitter_emit_or_die(emitter, &event);
  94. }
  95. yaml_sequence_end_event_initialize(&event);
  96. yaml_emitter_emit_or_die(emitter, &event);
  97. }
  98. static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
  99. {
  100. yaml_event_t event;
  101. int i;
  102. assert(str[len-1] == '\0');
  103. /* Make sure the entire string is in the lower 7-bit ascii range */
  104. for (i = 0; i < len; i++)
  105. assert(isascii(str[i]));
  106. yaml_scalar_event_initialize(&event, NULL,
  107. (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
  108. len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
  109. yaml_emitter_emit_or_die(emitter, &event);
  110. }
  111. static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
  112. {
  113. yaml_event_t event;
  114. int len = prop->val.len;
  115. struct marker *m = prop->val.markers;
  116. /* Emit the property name */
  117. yaml_scalar_event_initialize(&event, NULL,
  118. (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
  119. strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
  120. yaml_emitter_emit_or_die(emitter, &event);
  121. /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
  122. if (len == 0) {
  123. yaml_scalar_event_initialize(&event, NULL,
  124. (yaml_char_t *)YAML_BOOL_TAG,
  125. (yaml_char_t*)"true",
  126. strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
  127. yaml_emitter_emit_or_die(emitter, &event);
  128. return;
  129. }
  130. if (!m)
  131. die("No markers present in property '%s' value\n", prop->name);
  132. yaml_sequence_start_event_initialize(&event, NULL,
  133. (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
  134. yaml_emitter_emit_or_die(emitter, &event);
  135. for_each_marker(m) {
  136. int chunk_len;
  137. char *data = &prop->val.val[m->offset];
  138. if (m->type < TYPE_UINT8)
  139. continue;
  140. chunk_len = type_marker_length(m) ? : len;
  141. assert(chunk_len > 0);
  142. len -= chunk_len;
  143. switch(m->type) {
  144. case TYPE_UINT16:
  145. yaml_propval_int(emitter, m, data, chunk_len, 2);
  146. break;
  147. case TYPE_UINT32:
  148. yaml_propval_int(emitter, m, data, chunk_len, 4);
  149. break;
  150. case TYPE_UINT64:
  151. yaml_propval_int(emitter, m, data, chunk_len, 8);
  152. break;
  153. case TYPE_STRING:
  154. yaml_propval_string(emitter, data, chunk_len);
  155. break;
  156. default:
  157. yaml_propval_int(emitter, m, data, chunk_len, 1);
  158. break;
  159. }
  160. }
  161. yaml_sequence_end_event_initialize(&event);
  162. yaml_emitter_emit_or_die(emitter, &event);
  163. }
  164. static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
  165. {
  166. struct property *prop;
  167. struct node *child;
  168. yaml_event_t event;
  169. if (tree->deleted)
  170. return;
  171. yaml_mapping_start_event_initialize(&event, NULL,
  172. (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
  173. yaml_emitter_emit_or_die(emitter, &event);
  174. for_each_property(tree, prop)
  175. yaml_propval(emitter, prop);
  176. /* Loop over all the children, emitting them into the map */
  177. for_each_child(tree, child) {
  178. yaml_scalar_event_initialize(&event, NULL,
  179. (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
  180. strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
  181. yaml_emitter_emit_or_die(emitter, &event);
  182. yaml_tree(child, emitter);
  183. }
  184. yaml_mapping_end_event_initialize(&event);
  185. yaml_emitter_emit_or_die(emitter, &event);
  186. }
  187. void dt_to_yaml(FILE *f, struct dt_info *dti)
  188. {
  189. yaml_emitter_t emitter;
  190. yaml_event_t event;
  191. yaml_emitter_initialize(&emitter);
  192. yaml_emitter_set_output_file(&emitter, f);
  193. yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
  194. yaml_emitter_emit_or_die(&emitter, &event);
  195. yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
  196. yaml_emitter_emit_or_die(&emitter, &event);
  197. yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
  198. yaml_emitter_emit_or_die(&emitter, &event);
  199. yaml_tree(dti->dt, &emitter);
  200. yaml_sequence_end_event_initialize(&event);
  201. yaml_emitter_emit_or_die(&emitter, &event);
  202. yaml_document_end_event_initialize(&event, 0);
  203. yaml_emitter_emit_or_die(&emitter, &event);
  204. yaml_stream_end_event_initialize(&event);
  205. yaml_emitter_emit_or_die(&emitter, &event);
  206. yaml_emitter_delete(&emitter);
  207. }