diff options
-rw-r--r-- | data.c | 50 | ||||
-rw-r--r-- | dtc-parser.y | 4 | ||||
-rw-r--r-- | dtc.h | 5 | ||||
-rw-r--r-- | flattree.c | 13 |
4 files changed, 60 insertions, 12 deletions
@@ -29,12 +29,17 @@ void fixup_free(struct fixup *f) void data_free(struct data d) { - struct fixup *f; + struct fixup *f, *nf; f = d.refs; while (f) { - struct fixup *nf; + nf = f->next; + fixup_free(f); + f = nf; + } + f = d.labels; + while (f) { nf = f->next; fixup_free(f); f = nf; @@ -198,27 +203,36 @@ struct data data_append_data(struct data d, void *p, int len) return d; } -struct data data_merge(struct data d1, struct data d2) +void fixup_merge(struct fixup **fd, struct fixup **fd2, int d1_len) { - struct data d; struct fixup **ff; struct fixup *f, *f2; - d = data_append_data(d1, d2.val, d2.len); - /* Extract d2's fixups */ - f2 = d2.refs; - d2.refs = NULL; + f2 = *fd2; + *fd2 = NULL; /* Tack them onto d's list of fixups */ - ff = &d.refs; + ff = fd; while (*ff) ff = &((*ff)->next); *ff = f2; /* And correct them for their new position */ for (f = f2; f; f = f->next) - f->offset += d1.len; + f->offset += d1_len; + + +} + +struct data data_merge(struct data d1, struct data d2) +{ + struct data d; + + d = data_append_data(d1, d2.val, d2.len); + + fixup_merge(&d.refs, &d2.refs, d1.len); + fixup_merge(&d.labels, &d2.labels, d1.len); data_free(d2); @@ -285,6 +299,22 @@ struct data data_add_fixup(struct data d, char *ref) return nd; } +struct data data_add_label(struct data d, char *label) +{ + struct fixup *f; + struct data nd; + + f = xmalloc(sizeof(*f)); + f->offset = d.len; + f->ref = label; + f->next = d.labels; + + nd = d; + nd.labels = f; + + return nd; +} + int data_is_one_string(struct data d) { int i; diff --git a/dtc-parser.y b/dtc-parser.y index d88cbf1..19bc58e 100644 --- a/dtc-parser.y +++ b/dtc-parser.y @@ -131,9 +131,11 @@ propdata: propdataprefix DT_STRING { $$ = data_merge($1, $2); } $$ = data_merge(data_append_align($1, sizeof(cell_t)), $3); } | propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); } + | propdata DT_LABEL { $$ = data_add_label($1, $2); } ; propdataprefix: propdata ',' { $$ = $1; } + | propdataprefix DT_LABEL { $$ = data_add_label($1, $2); } | /* empty */ { $$ = empty_data; } ; @@ -150,10 +152,12 @@ celllist: celllist opt_cell_base DT_CELL { | celllist DT_REF { $$ = data_append_cell(data_add_fixup($1, $2), -1); } + | celllist DT_LABEL { $$ = data_add_label($1, $2); } | /* empty */ { $$ = empty_data; } ; bytestring: bytestring DT_BYTE { $$ = data_append_byte($1, $2); } + | bytestring DT_LABEL { $$ = data_add_label($1, $2); } | /* empty */ { $$ = empty_data; } ; @@ -111,10 +111,10 @@ struct data { char *val; int asize; struct fixup *refs; + struct fixup *labels; }; -#define empty_data \ - ((struct data){.len = 0, .val = NULL, .asize = 0, .refs = NULL}) +#define empty_data ((struct data){ /* all .members = 0 or NULL */ }) void fixup_free(struct fixup *f); void data_free(struct data d); @@ -135,6 +135,7 @@ struct data data_append_zeroes(struct data d, int len); struct data data_append_align(struct data d, int align); struct data data_add_fixup(struct data d, char *ref); +struct data data_add_label(struct data d, char *label); int data_is_one_string(struct data d); @@ -121,6 +121,12 @@ static void emit_label(FILE *f, char *prefix, char *label) fprintf(f, "_%s_%s:\n", prefix, label); } +static void emit_offset_label(FILE *f, char *label, int offset) +{ + fprintf(f, "\t.globl\t%s\n", label); + fprintf(f, "%s\t= . + %d\n", label, offset); +} + static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; @@ -157,6 +163,13 @@ static void asm_emit_data(void *e, struct data d) { FILE *f = e; int off = 0; + struct fixup *l; + + l = d.labels; + while (l) { + emit_offset_label(f, l->ref, l->offset); + l = l->next; + } while ((d.len - off) >= sizeof(u32)) { fprintf(f, "\t.long\t0x%x\n", |