summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data.c50
-rw-r--r--dtc-parser.y4
-rw-r--r--dtc.h5
-rw-r--r--flattree.c13
4 files changed, 60 insertions, 12 deletions
diff --git a/data.c b/data.c
index 3d68792..3e96d11 100644
--- a/data.c
+++ b/data.c
@@ -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; }
;
diff --git a/dtc.h b/dtc.h
index 8cfe1a1..0a1f960 100644
--- a/dtc.h
+++ b/dtc.h
@@ -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);
diff --git a/flattree.c b/flattree.c
index 31609d6..c7817c6 100644
--- a/flattree.c
+++ b/flattree.c
@@ -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",