| 1 |
|
| 2 | #ifndef DTC_H
|
| 3 | #define DTC_H
|
| 4 |
|
| 5 | |
| 6 | * (C) Copyright David Gibson <[email protected]>, IBM Corporation. 2005.
|
| 7 |
|
| 8 |
|
| 9 | #include <stdio.h>
|
| 10 | #include <string.h>
|
| 11 | #include <stdlib.h>
|
| 12 | #include <stdint.h>
|
| 13 | #include <stdbool.h>
|
| 14 | #include <stdarg.h>
|
| 15 | #include <assert.h>
|
| 16 | #include <ctype.h>
|
| 17 | #include <errno.h>
|
| 18 | #include <unistd.h>
|
| 19 | #include <inttypes.h>
|
| 20 |
|
| 21 | #include <libfdt_env.h>
|
| 22 | #include <fdt.h>
|
| 23 |
|
| 24 | #include "util.h"
|
| 25 |
|
| 26 | #ifdef DEBUG
|
| 27 | #define debug(...) printf(__VA_ARGS__)
|
| 28 | #else
|
| 29 | #define debug(...)
|
| 30 | #endif
|
| 31 |
|
| 32 | #define DEFAULT_FDT_VERSION 17
|
| 33 |
|
| 34 | |
| 35 | * Command line options
|
| 36 |
|
| 37 | extern int quiet;
|
| 38 | extern unsigned int reservenum;
|
| 39 | extern int minsize;
|
| 40 | extern int padsize;
|
| 41 | extern int alignsize;
|
| 42 | extern int phandle_format;
|
| 43 | extern int generate_symbols;
|
| 44 | extern int generate_fixups;
|
| 45 | extern int auto_label_aliases;
|
| 46 | extern int annotate;
|
| 47 |
|
| 48 | #define PHANDLE_LEGACY 0x1
|
| 49 | #define PHANDLE_EPAPR 0x2
|
| 50 | #define PHANDLE_BOTH 0x3
|
| 51 |
|
| 52 | typedef uint32_t cell_t;
|
| 53 |
|
| 54 | static inline bool phandle_is_valid(cell_t phandle)
|
| 55 | {
|
| 56 | return phandle != 0 && phandle != ~0U;
|
| 57 | }
|
| 58 |
|
| 59 | static inline uint16_t dtb_ld16(const void *p)
|
| 60 | {
|
| 61 | const uint8_t *bp = (const uint8_t *)p;
|
| 62 |
|
| 63 | return ((uint16_t)bp[0] << 8)
|
| 64 | | bp[1];
|
| 65 | }
|
| 66 |
|
| 67 | static inline uint32_t dtb_ld32(const void *p)
|
| 68 | {
|
| 69 | const uint8_t *bp = (const uint8_t *)p;
|
| 70 |
|
| 71 | return ((uint32_t)bp[0] << 24)
|
| 72 | | ((uint32_t)bp[1] << 16)
|
| 73 | | ((uint32_t)bp[2] << 8)
|
| 74 | | bp[3];
|
| 75 | }
|
| 76 |
|
| 77 | static inline uint64_t dtb_ld64(const void *p)
|
| 78 | {
|
| 79 | const uint8_t *bp = (const uint8_t *)p;
|
| 80 |
|
| 81 | return ((uint64_t)bp[0] << 56)
|
| 82 | | ((uint64_t)bp[1] << 48)
|
| 83 | | ((uint64_t)bp[2] << 40)
|
| 84 | | ((uint64_t)bp[3] << 32)
|
| 85 | | ((uint64_t)bp[4] << 24)
|
| 86 | | ((uint64_t)bp[5] << 16)
|
| 87 | | ((uint64_t)bp[6] << 8)
|
| 88 | | bp[7];
|
| 89 | }
|
| 90 |
|
| 91 | #define streq(a, b) (strcmp((a), (b)) == 0)
|
| 92 | #define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
|
| 93 | #define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
|
| 94 | static inline bool strends(const char *str, const char *suffix)
|
| 95 | {
|
| 96 | unsigned int len, suffix_len;
|
| 97 |
|
| 98 | len = strlen(str);
|
| 99 | suffix_len = strlen(suffix);
|
| 100 | if (len < suffix_len)
|
| 101 | return false;
|
| 102 | return streq(str + len - suffix_len, suffix);
|
| 103 | }
|
| 104 |
|
| 105 | #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
| 106 |
|
| 107 |
|
| 108 | enum markertype {
|
| 109 | TYPE_NONE,
|
| 110 | REF_PHANDLE,
|
| 111 | REF_PATH,
|
| 112 | LABEL,
|
| 113 | TYPE_UINT8,
|
| 114 | TYPE_UINT16,
|
| 115 | TYPE_UINT32,
|
| 116 | TYPE_UINT64,
|
| 117 | TYPE_STRING,
|
| 118 | };
|
| 119 |
|
| 120 | static inline bool is_type_marker(enum markertype type)
|
| 121 | {
|
| 122 | return type >= TYPE_UINT8;
|
| 123 | }
|
| 124 |
|
| 125 | extern const char *markername(enum markertype markertype);
|
| 126 |
|
| 127 | struct marker {
|
| 128 | enum markertype type;
|
| 129 | unsigned int offset;
|
| 130 | char *ref;
|
| 131 | struct marker *next;
|
| 132 | };
|
| 133 |
|
| 134 | struct data {
|
| 135 | unsigned int len;
|
| 136 | char *val;
|
| 137 | struct marker *markers;
|
| 138 | };
|
| 139 |
|
| 140 |
|
| 141 | #define empty_data ((struct data){ 0 })
|
| 142 |
|
| 143 | #define for_each_marker(m) \
|
| 144 | for (; (m); (m) = (m)->next)
|
| 145 | #define for_each_marker_of_type(m, t) \
|
| 146 | for_each_marker(m) \
|
| 147 | if ((m)->type == (t))
|
| 148 |
|
| 149 | static inline struct marker *next_type_marker(struct marker *m)
|
| 150 | {
|
| 151 | for_each_marker(m)
|
| 152 | if (is_type_marker(m->type))
|
| 153 | break;
|
| 154 | return m;
|
| 155 | }
|
| 156 |
|
| 157 | static inline size_t type_marker_length(struct marker *m)
|
| 158 | {
|
| 159 | struct marker *next = next_type_marker(m->next);
|
| 160 |
|
| 161 | if (next)
|
| 162 | return next->offset - m->offset;
|
| 163 | return 0;
|
| 164 | }
|
| 165 |
|
| 166 | void data_free(struct data d);
|
| 167 |
|
| 168 | struct data data_grow_for(struct data d, unsigned int xlen);
|
| 169 |
|
| 170 | struct data data_copy_mem(const char *mem, int len);
|
| 171 | struct data data_copy_escape_string(const char *s, int len);
|
| 172 | struct data data_copy_file(FILE *f, size_t len);
|
| 173 |
|
| 174 | struct data data_append_data(struct data d, const void *p, int len);
|
| 175 | struct data data_insert_at_marker(struct data d, struct marker *m,
|
| 176 | const void *p, int len);
|
| 177 | struct data data_merge(struct data d1, struct data d2);
|
| 178 | struct data data_append_cell(struct data d, cell_t word);
|
| 179 | struct data data_append_integer(struct data d, uint64_t word, int bits);
|
| 180 | struct data data_append_re(struct data d, uint64_t address, uint64_t size);
|
| 181 | struct data data_append_addr(struct data d, uint64_t addr);
|
| 182 | struct data data_append_byte(struct data d, uint8_t byte);
|
| 183 | struct data data_append_zeroes(struct data d, int len);
|
| 184 | struct data data_append_align(struct data d, int align);
|
| 185 | struct data data_insert_data(struct data d, struct marker *m, struct data old);
|
| 186 |
|
| 187 | struct marker *alloc_marker(unsigned int offset, enum markertype type,
|
| 188 | char *ref);
|
| 189 | struct data data_add_marker(struct data d, enum markertype type, char *ref);
|
| 190 |
|
| 191 | bool data_is_one_string(struct data d);
|
| 192 |
|
| 193 |
|
| 194 |
|
| 195 | #define MAX_PROPNAME_LEN 31
|
| 196 | #define MAX_NODENAME_LEN 31
|
| 197 |
|
| 198 |
|
| 199 | struct label {
|
| 200 | bool deleted;
|
| 201 | char *label;
|
| 202 | struct label *next;
|
| 203 | };
|
| 204 |
|
| 205 | struct bus_type {
|
| 206 | const char *name;
|
| 207 | };
|
| 208 |
|
| 209 | struct property {
|
| 210 | bool deleted;
|
| 211 | char *name;
|
| 212 | struct data val;
|
| 213 |
|
| 214 | struct property *next;
|
| 215 |
|
| 216 | struct label *labels;
|
| 217 | struct srcpos *srcpos;
|
| 218 | };
|
| 219 |
|
| 220 | struct node {
|
| 221 | bool deleted;
|
| 222 | char *name;
|
| 223 | struct property *proplist;
|
| 224 | struct node *children;
|
| 225 |
|
| 226 | struct node *parent;
|
| 227 | struct node *next_sibling;
|
| 228 |
|
| 229 | char *fullpath;
|
| 230 | size_t basenamelen;
|
| 231 |
|
| 232 | cell_t phandle;
|
| 233 | int addr_cells, size_cells;
|
| 234 |
|
| 235 | struct label *labels;
|
| 236 | const struct bus_type *bus;
|
| 237 | struct srcpos *srcpos;
|
| 238 |
|
| 239 | bool omit_if_unused, is_referenced;
|
| 240 | };
|
| 241 |
|
| 242 | #define for_each_label_withdel(l0, l) \
|
| 243 | for ((l) = (l0); (l); (l) = (l)->next)
|
| 244 |
|
| 245 | #define for_each_label(l0, l) \
|
| 246 | for_each_label_withdel(l0, l) \
|
| 247 | if (!(l)->deleted)
|
| 248 |
|
| 249 | #define for_each_property_withdel(n, p) \
|
| 250 | for ((p) = (n)->proplist; (p); (p) = (p)->next)
|
| 251 |
|
| 252 | #define for_each_property(n, p) \
|
| 253 | for_each_property_withdel(n, p) \
|
| 254 | if (!(p)->deleted)
|
| 255 |
|
| 256 | #define for_each_child_withdel(n, c) \
|
| 257 | for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
|
| 258 |
|
| 259 | #define for_each_child(n, c) \
|
| 260 | for_each_child_withdel(n, c) \
|
| 261 | if (!(c)->deleted)
|
| 262 |
|
| 263 | void add_label(struct label **labels, char *label);
|
| 264 | void delete_labels(struct label **labels);
|
| 265 |
|
| 266 | struct property *build_property(const char *name, struct data val,
|
| 267 | struct srcpos *srcpos);
|
| 268 | struct property *build_property_delete(const char *name);
|
| 269 | struct property *chain_property(struct property *first, struct property *list);
|
| 270 | struct property *reverse_properties(struct property *first);
|
| 271 |
|
| 272 | struct node *build_node(struct property *proplist, struct node *children,
|
| 273 | struct srcpos *srcpos);
|
| 274 | struct node *build_node_delete(struct srcpos *srcpos);
|
| 275 | struct node *name_node(struct node *node, const char *name);
|
| 276 | struct node *omit_node_if_unused(struct node *node);
|
| 277 | struct node *reference_node(struct node *node);
|
| 278 | struct node *chain_node(struct node *first, struct node *list);
|
| 279 | struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
| 280 | struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
|
| 281 |
|
| 282 | void add_property(struct node *node, struct property *prop);
|
| 283 | void delete_property_by_name(struct node *node, char *name);
|
| 284 | void delete_property(struct property *prop);
|
| 285 | void add_child(struct node *parent, struct node *child);
|
| 286 | void delete_node_by_name(struct node *parent, char *name);
|
| 287 | void delete_node(struct node *node);
|
| 288 | void append_to_property(struct node *node,
|
| 289 | char *name, const void *data, int len,
|
| 290 | enum markertype type);
|
| 291 |
|
| 292 | const char *get_unitname(struct node *node);
|
| 293 | struct property *get_property(struct node *node, const char *propname);
|
| 294 | cell_t propval_cell(struct property *prop);
|
| 295 | cell_t propval_cell_n(struct property *prop, unsigned int n);
|
| 296 | struct property *get_property_by_label(struct node *tree, const char *label,
|
| 297 | struct node **node);
|
| 298 | struct marker *get_marker_label(struct node *tree, const char *label,
|
| 299 | struct node **node, struct property **prop);
|
| 300 | struct node *get_subnode(struct node *node, const char *nodename);
|
| 301 | struct node *get_node_by_path(struct node *tree, const char *path);
|
| 302 | struct node *get_node_by_label(struct node *tree, const char *label);
|
| 303 | struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
|
| 304 | struct node *get_node_by_ref(struct node *tree, const char *ref);
|
| 305 | cell_t get_node_phandle(struct node *root, struct node *node);
|
| 306 |
|
| 307 | uint32_t guess_boot_cpuid(struct node *tree);
|
| 308 |
|
| 309 |
|
| 310 |
|
| 311 | struct reserve_info {
|
| 312 | uint64_t address, size;
|
| 313 |
|
| 314 | struct reserve_info *next;
|
| 315 |
|
| 316 | struct label *labels;
|
| 317 | };
|
| 318 |
|
| 319 | struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len);
|
| 320 | struct reserve_info *chain_reserve_entry(struct reserve_info *first,
|
| 321 | struct reserve_info *list);
|
| 322 | struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
| 323 | struct reserve_info *new);
|
| 324 |
|
| 325 |
|
| 326 | struct dt_info {
|
| 327 | unsigned int dtsflags;
|
| 328 | struct reserve_info *reservelist;
|
| 329 | uint32_t boot_cpuid_phys;
|
| 330 | struct node *dt;
|
| 331 | const char *outname;
|
| 332 | };
|
| 333 |
|
| 334 |
|
| 335 | #define DTSF_V1 0x0001
|
| 336 | #define DTSF_PLUGIN 0x0002
|
| 337 |
|
| 338 | struct dt_info *build_dt_info(unsigned int dtsflags,
|
| 339 | struct reserve_info *reservelist,
|
| 340 | struct node *tree, uint32_t boot_cpuid_phys);
|
| 341 | void sort_tree(struct dt_info *dti);
|
| 342 | void generate_labels_from_tree(struct dt_info *dti, const char *name);
|
| 343 | void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
|
| 344 | void generate_fixups_tree(struct dt_info *dti, const char *name);
|
| 345 | void fixup_phandles(struct dt_info *dti, const char *name);
|
| 346 | void generate_local_fixups_tree(struct dt_info *dti, const char *name);
|
| 347 | void local_fixup_phandles(struct dt_info *dti, const char *name);
|
| 348 |
|
| 349 |
|
| 350 |
|
| 351 | void parse_checks_option(bool warn, bool error, const char *arg);
|
| 352 | void process_checks(bool force, struct dt_info *dti);
|
| 353 |
|
| 354 |
|
| 355 |
|
| 356 | void dt_to_blob(FILE *f, struct dt_info *dti, int version);
|
| 357 | void dt_to_asm(FILE *f, struct dt_info *dti, int version);
|
| 358 |
|
| 359 | struct dt_info *dt_from_blob(const char *fname);
|
| 360 |
|
| 361 |
|
| 362 |
|
| 363 | void property_add_marker(struct property *prop,
|
| 364 | enum markertype type, unsigned int offset, char *ref);
|
| 365 | void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset);
|
| 366 | void dt_to_source(FILE *f, struct dt_info *dti);
|
| 367 | struct dt_info *dt_from_source(const char *f);
|
| 368 |
|
| 369 |
|
| 370 |
|
| 371 | void dt_to_yaml(FILE *f, struct dt_info *dti);
|
| 372 |
|
| 373 |
|
| 374 |
|
| 375 | struct dt_info *dt_from_fs(const char *dirname);
|
| 376 |
|
| 377 | #endif
|