yamltree.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * (C) Copyright Linaro, Ltd. 2018
  4. * (C) Copyright Arm Holdings. 2017
  5. * (C) Copyright David Gibson <[email protected]>, IBM Corporation. 2005.
  6. */
  7. #include <stdlib.h>
  8. #include <yaml.h>
  9. #include "dtc.h"
  10. #include "srcpos.h"
  11. char *yaml_error_name[] = {
  12. [YAML_NO_ERROR] = "no error",
  13. [YAML_MEMORY_ERROR] = "memory error",
  14. [YAML_READER_ERROR] = "reader error",
  15. [YAML_SCANNER_ERROR] = "scanner error",
  16. [YAML_PARSER_ERROR] = "parser error",
  17. [YAML_COMPOSER_ERROR] = "composer error",
  18. [YAML_WRITER_ERROR] = "writer error",
  19. [YAML_EMITTER_ERROR] = "emitter error",
  20. };
  21. #define yaml_emitter_emit_or_die(emitter, event) ( \
  22. { \
  23. if (!yaml_emitter_emit(emitter, event)) \
  24. die("yaml '%s': %s in %s, line %i\n", \
  25. yaml_error_name[(emitter)->error], \
  26. (emitter)->problem, __func__, __LINE__); \
  27. })
  28. static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers,
  29. char *data, unsigned int seq_offset, unsigned int len, int width)
  30. {
  31. yaml_event_t event;
  32. void *tag;
  33. unsigned int off;
  34. switch(width) {
  35. case 1: tag = "!u8"; break;
  36. case 2: tag = "!u16"; break;
  37. case 4: tag = "!u32"; break;
  38. case 8: tag = "!u64"; break;
  39. default:
  40. die("Invalid width %i", width);
  41. }
  42. assert(len % width == 0);
  43. yaml_sequence_start_event_initialize(&event, NULL,
  44. (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
  45. yaml_emitter_emit_or_die(emitter, &event);
  46. for (off = 0; off < len; off += width) {
  47. char buf[32];
  48. struct marker *m;
  49. bool is_phandle = false;
  50. switch(width) {
  51. case 1:
  52. sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
  53. break;
  54. case 2:
  55. sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off));
  56. break;
  57. case 4:
  58. sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off));
  59. m = markers;
  60. is_phandle = false;
  61. for_each_marker_of_type(m, REF_PHANDLE) {
  62. if (m->offset == (seq_offset + off)) {
  63. is_phandle = true;
  64. break;
  65. }
  66. }
  67. break;
  68. case 8:
  69. sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off));
  70. break;
  71. }
  72. if (is_phandle)
  73. yaml_scalar_event_initialize(&event, NULL,
  74. (yaml_char_t*)"!phandle", (yaml_char_t *)buf,
  75. strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
  76. else
  77. yaml_scalar_event_initialize(&event, NULL,
  78. (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
  79. strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
  80. yaml_emitter_emit_or_die(emitter, &event);
  81. }
  82. yaml_sequence_end_event_initialize(&event);
  83. yaml_emitter_emit_or_die(emitter, &event);
  84. }
  85. static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
  86. {
  87. yaml_event_t event;
  88. int i;
  89. assert(str[len-1] == '\0');
  90. /* Make sure the entire string is in the lower 7-bit ascii range */
  91. for (i = 0; i < len; i++)
  92. assert(isascii(str[i]));
  93. yaml_scalar_event_initialize(&event, NULL,
  94. (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
  95. len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
  96. yaml_emitter_emit_or_die(emitter, &event);
  97. }
  98. static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
  99. {
  100. yaml_event_t event;
  101. unsigned int len = prop->val.len;
  102. struct marker *m = prop->val.markers;
  103. struct marker *markers = prop->val.markers;
  104. /* Emit the property name */
  105. yaml_scalar_event_initialize(&event, NULL,
  106. (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
  107. strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
  108. yaml_emitter_emit_or_die(emitter, &event);
  109. /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
  110. if (len == 0) {
  111. yaml_scalar_event_initialize(&event, NULL,
  112. (yaml_char_t *)YAML_BOOL_TAG,
  113. (yaml_char_t*)"true",
  114. strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
  115. yaml_emitter_emit_or_die(emitter, &event);
  116. return;
  117. }
  118. if (!m)
  119. die("No markers present in property '%s' value\n", prop->name);
  120. yaml_sequence_start_event_initialize(&event, NULL,
  121. (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
  122. yaml_emitter_emit_or_die(emitter, &event);
  123. for_each_marker(m) {
  124. int chunk_len;
  125. char *data = &prop->val.val[m->offset];
  126. if (m->type < TYPE_UINT8)
  127. continue;
  128. chunk_len = type_marker_length(m) ? : len;
  129. assert(chunk_len > 0);
  130. len -= chunk_len;
  131. switch(m->type) {
  132. case TYPE_UINT16:
  133. yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2);
  134. break;
  135. case TYPE_UINT32:
  136. yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4);
  137. break;
  138. case TYPE_UINT64:
  139. yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8);
  140. break;
  141. case TYPE_STRING:
  142. yaml_propval_string(emitter, data, chunk_len);
  143. break;
  144. default:
  145. yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1);
  146. break;
  147. }
  148. }
  149. yaml_sequence_end_event_initialize(&event);
  150. yaml_emitter_emit_or_die(emitter, &event);
  151. }
  152. static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
  153. {
  154. struct property *prop;
  155. struct node *child;
  156. yaml_event_t event;
  157. if (tree->deleted)
  158. return;
  159. yaml_mapping_start_event_initialize(&event, NULL,
  160. (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
  161. yaml_emitter_emit_or_die(emitter, &event);
  162. for_each_property(tree, prop)
  163. yaml_propval(emitter, prop);
  164. /* Loop over all the children, emitting them into the map */
  165. for_each_child(tree, child) {
  166. yaml_scalar_event_initialize(&event, NULL,
  167. (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
  168. strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
  169. yaml_emitter_emit_or_die(emitter, &event);
  170. yaml_tree(child, emitter);
  171. }
  172. yaml_mapping_end_event_initialize(&event);
  173. yaml_emitter_emit_or_die(emitter, &event);
  174. }
  175. void dt_to_yaml(FILE *f, struct dt_info *dti)
  176. {
  177. yaml_emitter_t emitter;
  178. yaml_event_t event;
  179. yaml_emitter_initialize(&emitter);
  180. yaml_emitter_set_output_file(&emitter, f);
  181. yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
  182. yaml_emitter_emit_or_die(&emitter, &event);
  183. yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
  184. yaml_emitter_emit_or_die(&emitter, &event);
  185. yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
  186. yaml_emitter_emit_or_die(&emitter, &event);
  187. yaml_tree(dti->dt, &emitter);
  188. yaml_sequence_end_event_initialize(&event);
  189. yaml_emitter_emit_or_die(&emitter, &event);
  190. yaml_document_end_event_initialize(&event, 0);
  191. yaml_emitter_emit_or_die(&emitter, &event);
  192. yaml_stream_end_event_initialize(&event);
  193. yaml_emitter_emit_or_die(&emitter, &event);
  194. yaml_emitter_delete(&emitter);
  195. }