diff options
author | Wesley W. Terpstra <wesley@sifive.com> | 2017-04-05 16:22:47 -0700 |
---|---|---|
committer | Wesley W. Terpstra <wesley@sifive.com> | 2017-04-05 16:22:47 -0700 |
commit | 91636ac4639a7993c485288d34f1c8e22b1980b4 (patch) | |
tree | d50d564fbdabf9987c531267e15a7a32a07fbb8d /machine | |
parent | cd558016be4fdc99055814bd1adcfc2962b425c0 (diff) | |
download | riscv-pk-91636ac4639a7993c485288d34f1c8e22b1980b4.zip riscv-pk-91636ac4639a7993c485288d34f1c8e22b1980b4.tar.gz riscv-pk-91636ac4639a7993c485288d34f1c8e22b1980b4.tar.bz2 |
fdt: redact clint, plic, and debug hardware
Diffstat (limited to 'machine')
-rw-r--r-- | machine/fdt.c | 156 | ||||
-rw-r--r-- | machine/fdt.h | 6 |
2 files changed, 160 insertions, 2 deletions
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, ®); + 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; |