aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bbl/bbl.c6
-rw-r--r--machine/fdt.c156
-rw-r--r--machine/fdt.h6
3 files changed, 166 insertions, 2 deletions
diff --git a/bbl/bbl.c b/bbl/bbl.c
index 300182c..44802c1 100644
--- a/bbl/bbl.c
+++ b/bbl/bbl.c
@@ -21,6 +21,12 @@ static void filter_dtb(uintptr_t source)
uintptr_t dest = dtb_output();
uint32_t size = fdt_size(source);
memcpy((void*)dest, (void*)source, size);
+
+ // Remove information from the chained FDT
+ // filter_harts(dest, 0x2);
+ filter_plic(dest);
+ filter_compat(dest, "riscv,clint0");
+ filter_compat(dest, "riscv,debug-013");
}
void boot_other_hart(uintptr_t dtb)
diff --git a/machine/fdt.c b/machine/fdt.c
index bd8da74..908b2ea 100644
--- a/machine/fdt.c
+++ b/machine/fdt.c
@@ -106,6 +106,19 @@ const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *v
return value;
}
+int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str)
+{
+ const char *list = (const char *)prop->value;
+ const char *end = list + prop->len;
+ int index = 0;
+ while (end - list > 0) {
+ if (!strcmp(list, str)) return index;
+ ++index;
+ list += strlen(list) + 1;
+ }
+ return -1;
+}
+
//////////////////////////////////////////// MEMORY SCAN /////////////////////////////////////////
struct mem_scan {
@@ -280,7 +293,7 @@ static void clint_open(const struct fdt_scan_node *node, void *extra)
static void clint_prop(const struct fdt_scan_prop *prop, void *extra)
{
struct clint_scan *scan = (struct clint_scan *)extra;
- if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,clint0")) {
+ if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, "riscv,clint0") >= 0) {
scan->compat = 1;
} else if (!strcmp(prop->name, "reg")) {
fdt_get_address(prop->node->parent, prop->value, &scan->reg);
@@ -358,7 +371,7 @@ static void plic_open(const struct fdt_scan_node *node, void *extra)
static void plic_prop(const struct fdt_scan_prop *prop, void *extra)
{
struct plic_scan *scan = (struct plic_scan *)extra;
- if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "riscv,plic0")) {
+ if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, "riscv,plic0") >= 0) {
scan->compat = 1;
} else if (!strcmp(prop->name, "reg")) {
fdt_get_address(prop->node->parent, prop->value, &scan->reg);
@@ -435,3 +448,142 @@ void query_plic(uintptr_t fdt)
scan.done = 0;
fdt_scan(fdt, &cb);
}
+
+static void plic_redact(const struct fdt_scan_node *node, void *extra)
+{
+ struct plic_scan *scan = (struct plic_scan *)extra;
+ uint32_t *value = scan->int_value;
+ uint32_t *end = value + scan->int_len/4;
+
+ if (!scan->compat) return;
+ scan->done = 1;
+
+ while (end - value > 0) {
+ if (bswap(value[1]) == IRQ_M_EXT) value[1] = bswap(-1);
+ value += 2;
+ }
+}
+
+void filter_plic(uintptr_t fdt)
+{
+ struct fdt_cb cb;
+ struct plic_scan scan;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.open = plic_open;
+ cb.prop = plic_prop;
+ cb.done = plic_redact;
+ cb.extra = &scan;
+
+ scan.done = 0;
+ fdt_scan(fdt, &cb);
+}
+
+//////////////////////////////////////////// COMPAT SCAN ////////////////////////////////////////
+
+struct compat_scan
+{
+ const char *compat;
+ int depth;
+ int kill;
+};
+
+static void compat_open(const struct fdt_scan_node *node, void *extra)
+{
+ struct compat_scan *scan = (struct compat_scan *)extra;
+ ++scan->depth;
+}
+
+static void compat_prop(const struct fdt_scan_prop *prop, void *extra)
+{
+ struct compat_scan *scan = (struct compat_scan *)extra;
+ if (!strcmp(prop->name, "compatible") && fdt_string_list_index(prop, scan->compat) >= 0)
+ if (scan->depth < scan->kill)
+ scan->kill = scan->depth;
+}
+
+static int compat_close(const struct fdt_scan_node *node, void *extra)
+{
+ struct compat_scan *scan = (struct compat_scan *)extra;
+ if (scan->kill == scan->depth--) {
+ scan->kill = 999;
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+void filter_compat(uintptr_t fdt, const char *compat)
+{
+ struct fdt_cb cb;
+ struct compat_scan scan;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.open = compat_open;
+ cb.prop = compat_prop;
+ cb.close = compat_close;
+ cb.extra = &scan;
+
+ scan.compat = compat;
+ scan.depth = 0;
+ scan.kill = 999;
+ fdt_scan(fdt, &cb);
+}
+
+//////////////////////////////////////////// HART FILTER ////////////////////////////////////////
+
+struct hart_filter {
+ int compat;
+ int hart;
+ char *status;
+ unsigned long mask;
+};
+
+static void hart_filter_open(const struct fdt_scan_node *node, void *extra)
+{
+ struct hart_filter *filter = (struct hart_filter *)extra;
+ filter->status = 0;
+ filter->compat = 0;
+ filter->hart = -1;
+}
+
+static void hart_filter_prop(const struct fdt_scan_prop *prop, void *extra)
+{
+ struct hart_filter *filter = (struct hart_filter *)extra;
+ if (!strcmp(prop->name, "device_type") && !strcmp((const char*)prop->value, "cpu")) {
+ filter->compat = 1;
+ } else if (!strcmp(prop->name, "reg")) {
+ uintptr_t reg;
+ fdt_get_address(prop->node->parent, prop->value, &reg);
+ filter->hart = reg;
+ } else if (!strcmp(prop->name, "status")) {
+ filter->status = (char*)prop->value;
+ }
+}
+
+static void hart_filter_done(const struct fdt_scan_node *node, void *extra)
+{
+ struct hart_filter *filter = (struct hart_filter *)extra;
+
+ if (!filter->compat) return;
+ assert (filter->status);
+ assert (filter->hart >= 0);
+
+ if (((filter->mask >> filter->hart) & 1))
+ strcpy(filter->status, "masked");
+}
+
+void filter_harts(uintptr_t fdt, unsigned long hart_mask)
+{
+ struct fdt_cb cb;
+ struct hart_filter filter;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.open = hart_filter_open;
+ cb.prop = hart_filter_prop;
+ cb.done = hart_filter_done;
+ cb.extra = &filter;
+
+ filter.mask = hart_mask;
+ fdt_scan(fdt, &cb);
+}
diff --git a/machine/fdt.h b/machine/fdt.h
index 235bb2e..0581e95 100644
--- a/machine/fdt.h
+++ b/machine/fdt.h
@@ -52,6 +52,7 @@ uint32_t fdt_size(uintptr_t fdt);
// Extract fields
const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value);
const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *base, uintptr_t *value);
+int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str); // -1 if not found
// Setup memory+clint+plic
void query_mem(uintptr_t fdt);
@@ -59,6 +60,11 @@ void query_harts(uintptr_t fdt);
void query_plic(uintptr_t fdt);
void query_clint(uintptr_t fdt);
+// Remove information from FDT
+void filter_harts(uintptr_t fdt, unsigned long hart_mask);
+void filter_plic(uintptr_t fdt);
+void filter_compat(uintptr_t fdt, const char *compat);
+
// The hartids of available harts
extern uint64_t hart_mask;