Message ID | 1402919103-29642-5-git-send-email-ian.campbell@citrix.com |
---|---|
State | New |
Headers | show |
Hi Ian, On 06/16/2014 12:44 PM, Ian Campbell wrote: > Move the early code for walking the flattended device tree out of s/flattended/flattened/ > device_tree.c. The intention is that eventually only only the proper (i.e. I suspect you add twice "only" by mistake. > unflattened) device tree support will live in device_tree.c. > > The new home is bootfdt.c to try and better reflect the purpose of the code. > Although in theory this early code could be generic in reality it is pretty ARM > specific, so place it under xen/arch/arm until a second user wants it. > > As part of the move rename device_tree_early_init to boot_fdt_info. Drop > device_tree_dump, it is unused. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> With the small changes above: Acked-by: Julien Grall <julien.grall@linaro.org> Regards,
On Mon, 16 Jun 2014, Ian Campbell wrote: > Move the early code for walking the flattended device tree out of > device_tree.c. The intention is that eventually only only the proper (i.e. ^ ^ > unflattened) device tree support will live in device_tree.c. > > The new home is bootfdt.c to try and better reflect the purpose of the code. > Although in theory this early code could be generic in reality it is pretty ARM > specific, so place it under xen/arch/arm until a second user wants it. > > As part of the move rename device_tree_early_init to boot_fdt_info. Drop > device_tree_dump, it is unused. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > xen/arch/arm/Makefile | 1 + > xen/arch/arm/bootfdt.c | 343 +++++++++++++++++++++++++++++++++++++++ > xen/arch/arm/setup.c | 2 +- > xen/common/device_tree.c | 356 ----------------------------------------- > xen/include/asm-arm/setup.h | 2 + > xen/include/xen/device_tree.h | 3 - > 6 files changed, 347 insertions(+), 360 deletions(-) > create mode 100644 xen/arch/arm/bootfdt.c > > diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile > index 63e0460..58a6714 100644 > --- a/xen/arch/arm/Makefile > +++ b/xen/arch/arm/Makefile > @@ -21,6 +21,7 @@ obj-y += guestcopy.o > obj-y += physdev.o > obj-y += platform.o > obj-y += setup.o > +obj-y += bootfdt.o > obj-y += time.o > obj-y += smpboot.o > obj-y += smp.o > diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c > new file mode 100644 > index 0000000..11182cd > --- /dev/null > +++ b/xen/arch/arm/bootfdt.c > @@ -0,0 +1,343 @@ > +/* > + * Early Device Tree > + * > + * Copyright (C) 2012-2014 Citrix Systems, Inc. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > +#include <xen/config.h> > +#include <xen/types.h> > +#include <xen/lib.h> > +#include <xen/kernel.h> > +#include <xen/init.h> > +#include <xen/device_tree.h> > +#include <xen/libfdt/libfdt.h> > +#include <asm/setup.h> > + > +static bool_t __init device_tree_node_matches(const void *fdt, int node, > + const char *match) > +{ > + const char *name; > + size_t match_len; > + > + name = fdt_get_name(fdt, node, NULL); > + match_len = strlen(match); > + > + /* Match both "match" and "match@..." patterns but not > + "match-foo". */ > + return strncmp(name, match, match_len) == 0 > + && (name[match_len] == '@' || name[match_len] == '\0'); > +} > + > +static bool_t __init device_tree_node_compatible(const void *fdt, int node, > + const char *match) > +{ > + int len, l; > + int mlen; > + const void *prop; > + > + mlen = strlen(match); > + > + prop = fdt_getprop(fdt, node, "compatible", &len); > + if ( prop == NULL ) > + return 0; > + > + while ( len > 0 ) { > + if ( !dt_compat_cmp(prop, match) ) > + return 1; > + l = strlen(prop) + 1; > + prop += l; > + len -= l; > + } > + > + return 0; > +} > + > +static void __init device_tree_get_reg(const __be32 **cell, u32 address_cells, > + u32 size_cells, u64 *start, u64 *size) > +{ > + *start = dt_next_cell(address_cells, cell); > + *size = dt_next_cell(size_cells, cell); > +} > + > +static u32 __init device_tree_get_u32(const void *fdt, int node, > + const char *prop_name, u32 dflt) > +{ > + const struct fdt_property *prop; > + > + prop = fdt_get_property(fdt, node, prop_name, NULL); > + if ( !prop || prop->len < sizeof(u32) ) > + return dflt; > + > + return fdt32_to_cpu(*(uint32_t*)prop->data); > +} > + > +/** > + * device_tree_for_each_node - iterate over all device tree nodes > + * @fdt: flat device tree. > + * @func: function to call for each node. > + * @data: data to pass to @func. > + * > + * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. > + * > + * Returns 0 if all nodes were iterated over successfully. If @func > + * returns a value different from 0, that value is returned immediately. > + */ > +static int __init device_tree_for_each_node(const void *fdt, > + device_tree_node_func func, > + void *data) > +{ > + int node; > + int depth; > + u32 address_cells[DEVICE_TREE_MAX_DEPTH]; > + u32 size_cells[DEVICE_TREE_MAX_DEPTH]; > + int ret; > + > + for ( node = 0, depth = 0; > + node >=0 && depth >= 0; > + node = fdt_next_node(fdt, node, &depth) ) > + { > + const char *name = fdt_get_name(fdt, node, NULL); > + > + if ( depth >= DEVICE_TREE_MAX_DEPTH ) > + { > + printk("Warning: device tree node `%s' is nested too deep\n", > + name); > + continue; > + } > + > + address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells", > + depth > 0 ? address_cells[depth-1] : 0); > + size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells", > + depth > 0 ? size_cells[depth-1] : 0); > + > + > + ret = func(fdt, node, name, depth, > + address_cells[depth-1], size_cells[depth-1], data); > + if ( ret != 0 ) > + return ret; > + } > + return 0; > +} > + > +static void __init process_memory_node(const void *fdt, int node, > + const char *name, > + u32 address_cells, u32 size_cells) > +{ > + const struct fdt_property *prop; > + int i; > + int banks; > + const __be32 *cell; > + paddr_t start, size; > + u32 reg_cells = address_cells + size_cells; > + > + if ( address_cells < 1 || size_cells < 1 ) > + { > + printk("fdt: node `%s': invalid #address-cells or #size-cells", > + name); > + return; > + } > + > + prop = fdt_get_property(fdt, node, "reg", NULL); > + if ( !prop ) > + { > + printk("fdt: node `%s': missing `reg' property\n", name); > + return; > + } > + > + cell = (const __be32 *)prop->data; > + banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32)); > + > + for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ ) > + { > + device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); > + bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start; > + bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size; > + bootinfo.mem.nr_banks++; > + } > +} > + > +static void __init process_multiboot_node(const void *fdt, int node, > + const char *name, > + u32 address_cells, u32 size_cells) > +{ > + const struct fdt_property *prop; > + const __be32 *cell; > + int nr; > + struct bootmodule *mod; > + int len; > + > + if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 || > + fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 ) > + nr = MOD_KERNEL; > + else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 || > + fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 ) > + nr = MOD_INITRD; > + else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 ) > + nr = MOD_XSM; > + else > + panic("%s not a known xen multiboot type\n", name); > + > + mod = &bootinfo.modules.module[nr]; > + > + prop = fdt_get_property(fdt, node, "reg", &len); > + if ( !prop ) > + panic("node %s missing `reg' property\n", name); > + > + if ( len < dt_cells_to_size(address_cells + size_cells) ) > + panic("fdt: node `%s': `reg` property length is too short\n", > + name); > + > + cell = (const __be32 *)prop->data; > + device_tree_get_reg(&cell, address_cells, size_cells, > + &mod->start, &mod->size); > + > + prop = fdt_get_property(fdt, node, "bootargs", &len); > + if ( prop ) > + { > + if ( len > sizeof(mod->cmdline) ) > + panic("module %d command line too long\n", nr); > + > + safe_strcpy(mod->cmdline, prop->data); > + } > + else > + mod->cmdline[0] = 0; > + > + if ( nr > bootinfo.modules.nr_mods ) > + bootinfo.modules.nr_mods = nr; > +} > + > +static void __init process_chosen_node(const void *fdt, int node, > + const char *name, > + u32 address_cells, u32 size_cells) > +{ > + const struct fdt_property *prop; > + struct bootmodule *mod = &bootinfo.modules.module[MOD_INITRD]; > + paddr_t start, end; > + int len; > + > + printk("Checking for initrd in /chosen\n"); > + > + prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); > + if ( !prop ) > + /* No initrd present. */ > + return; > + if ( len != sizeof(u32) && len != sizeof(u64) ) > + { > + printk("linux,initrd-start property has invalid length %d\n", len); > + return; > + } > + start = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); > + > + prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); > + if ( !prop ) > + { > + printk("linux,initrd-end not present but -start was\n"); > + return; > + } > + if ( len != sizeof(u32) && len != sizeof(u64) ) > + { > + printk("linux,initrd-end property has invalid length %d\n", len); > + return; > + } > + end = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); > + > + if ( start >= end ) > + { > + printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", > + start, end); > + return; > + } > + > + printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); > + > + mod->start = start; > + mod->size = end - start; > + > + bootinfo.modules.nr_mods = max(MOD_INITRD, bootinfo.modules.nr_mods); > +} > + > +static int __init early_scan_node(const void *fdt, > + int node, const char *name, int depth, > + u32 address_cells, u32 size_cells, > + void *data) > +{ > + if ( device_tree_node_matches(fdt, node, "memory") ) > + process_memory_node(fdt, node, name, address_cells, size_cells); > + else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) || > + device_tree_node_compatible(fdt, node, "multiboot,module" )) > + process_multiboot_node(fdt, node, name, address_cells, size_cells); > + else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") ) > + process_chosen_node(fdt, node, name, address_cells, size_cells); > + > + return 0; > +} > + > +static void __init early_print_info(void) > +{ > + struct meminfo *mi = &bootinfo.mem; > + struct bootmodules *mods = &bootinfo.modules; > + int i, nr_rsvd; > + > + for ( i = 0; i < mi->nr_banks; i++ ) > + printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n", > + mi->bank[i].start, > + mi->bank[i].start + mi->bank[i].size - 1); > + printk("\n"); > + for ( i = 1 ; i < mods->nr_mods + 1; i++ ) > + printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %s\n", > + i, > + mods->module[i].start, > + mods->module[i].start + mods->module[i].size, > + mods->module[i].cmdline); > + nr_rsvd = fdt_num_mem_rsv(device_tree_flattened); > + for ( i = 0; i < nr_rsvd; i++ ) > + { > + paddr_t s, e; > + if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 ) > + continue; > + /* fdt_get_mem_rsv returns length */ > + e += s; > + printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n", > + i, s, e); > + } > + printk("\n"); > +} > + > +/** > + * boot_fdt_info - initialize bootinfo from a DTB > + * @fdt: flattened device tree binary > + * > + * Returns the size of the DTB. > + */ > +size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) > +{ > + struct bootmodule *mod; > + int ret; > + > + ret = fdt_check_header(fdt); > + if ( ret < 0 ) > + panic("No valid device tree\n"); > + > + mod = &bootinfo.modules.module[MOD_FDT]; > + mod->start = paddr; > + mod->size = fdt_totalsize(fdt); > + > + bootinfo.modules.nr_mods = max(MOD_FDT, bootinfo.modules.nr_mods); > + > + device_tree_for_each_node((void *)fdt, early_scan_node, NULL); > + early_print_info(); > + > + return fdt_totalsize(fdt); > +} > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > index 63f6b8e..4a84a32 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -678,7 +678,7 @@ void __init start_xen(unsigned long boot_phys_offset, > /* This is mapped by head.S */ > device_tree_flattened = (void *)BOOT_FDT_VIRT_START > + (fdt_paddr & ((1 << SECOND_SHIFT) - 1)); > - fdt_size = device_tree_early_init(device_tree_flattened, fdt_paddr); > + fdt_size = boot_fdt_info(device_tree_flattened, fdt_paddr); > > cmdline = device_tree_bootargs(device_tree_flattened); > printk("Command line: %s\n", cmdline); > diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c > index a1896d3..89de269 100644 > --- a/xen/common/device_tree.c > +++ b/xen/common/device_tree.c > @@ -22,7 +22,6 @@ > #include <xen/string.h> > #include <xen/cpumask.h> > #include <xen/ctype.h> > -#include <xen/lib.h> > #include <asm/setup.h> > > const void *device_tree_flattened; > @@ -89,52 +88,6 @@ struct dt_bus > unsigned int (*get_flags)(const __be32 *addr); > }; > > -static bool_t __init device_tree_node_matches(const void *fdt, int node, > - const char *match) > -{ > - const char *name; > - size_t match_len; > - > - name = fdt_get_name(fdt, node, NULL); > - match_len = strlen(match); > - > - /* Match both "match" and "match@..." patterns but not > - "match-foo". */ > - return strncmp(name, match, match_len) == 0 > - && (name[match_len] == '@' || name[match_len] == '\0'); > -} > - > -static bool_t __init device_tree_node_compatible(const void *fdt, int node, > - const char *match) > -{ > - int len, l; > - int mlen; > - const void *prop; > - > - mlen = strlen(match); > - > - prop = fdt_getprop(fdt, node, "compatible", &len); > - if ( prop == NULL ) > - return 0; > - > - while ( len > 0 ) { > - if ( !dt_compat_cmp(prop, match) ) > - return 1; > - l = strlen(prop) + 1; > - prop += l; > - len -= l; > - } > - > - return 0; > -} > - > -static void __init device_tree_get_reg(const __be32 **cell, u32 address_cells, > - u32 size_cells, u64 *start, u64 *size) > -{ > - *start = dt_next_cell(address_cells, cell); > - *size = dt_next_cell(size_cells, cell); > -} > - > void dt_get_range(const __be32 **cell, const struct dt_device_node *np, > u64 *address, u64 *size) > { > @@ -162,66 +115,6 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np, > dt_set_cell(cellp, dt_n_size_cells(np), size); > } > > -static u32 __init device_tree_get_u32(const void *fdt, int node, > - const char *prop_name, u32 dflt) > -{ > - const struct fdt_property *prop; > - > - prop = fdt_get_property(fdt, node, prop_name, NULL); > - if ( !prop || prop->len < sizeof(u32) ) > - return dflt; > - > - return fdt32_to_cpu(*(uint32_t*)prop->data); > -} > - > -/** > - * device_tree_for_each_node - iterate over all device tree nodes > - * @fdt: flat device tree. > - * @func: function to call for each node. > - * @data: data to pass to @func. > - * > - * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. > - * > - * Returns 0 if all nodes were iterated over successfully. If @func > - * returns a value different from 0, that value is returned immediately. > - */ > -static int __init device_tree_for_each_node(const void *fdt, > - device_tree_node_func func, > - void *data) > -{ > - int node; > - int depth; > - u32 address_cells[DEVICE_TREE_MAX_DEPTH]; > - u32 size_cells[DEVICE_TREE_MAX_DEPTH]; > - int ret; > - > - for ( node = 0, depth = 0; > - node >=0 && depth >= 0; > - node = fdt_next_node(fdt, node, &depth) ) > - { > - const char *name = fdt_get_name(fdt, node, NULL); > - > - if ( depth >= DEVICE_TREE_MAX_DEPTH ) > - { > - printk("Warning: device tree node `%s' is nested too deep\n", > - name); > - continue; > - } > - > - address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells", > - depth > 0 ? address_cells[depth-1] : 0); > - size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells", > - depth > 0 ? size_cells[depth-1] : 0); > - > - > - ret = func(fdt, node, name, depth, > - address_cells[depth-1], size_cells[depth-1], data); > - if ( ret != 0 ) > - return ret; > - } > - return 0; > -} > - > /** > * device_tree_bootargs - return the bootargs (the Xen command line) > * @fdt flat device tree. > @@ -253,255 +146,6 @@ const char *device_tree_bootargs(const void *fdt) > return prop->data; > } > > -static int dump_node(const void *fdt, int node, const char *name, int depth, > - u32 address_cells, u32 size_cells, void *data) > -{ > - char prefix[2*DEVICE_TREE_MAX_DEPTH + 1] = ""; > - int i; > - int prop; > - > - for ( i = 0; i < depth; i++ ) > - safe_strcat(prefix, " "); > - > - if ( name[0] == '\0' ) > - name = "/"; > - printk("%s%s:\n", prefix, name); > - > - for ( prop = fdt_first_property_offset(fdt, node); > - prop >= 0; > - prop = fdt_next_property_offset(fdt, prop) ) > - { > - const struct fdt_property *p; > - > - p = fdt_get_property_by_offset(fdt, prop, NULL); > - > - printk("%s %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff))); > - } > - > - return 0; > -} > - > -/** > - * device_tree_dump - print a text representation of a device tree > - * @fdt: flat device tree to print > - */ > -void __init device_tree_dump(const void *fdt) > -{ > - device_tree_for_each_node(fdt, dump_node, NULL); > -} > - > - > -static void __init process_memory_node(const void *fdt, int node, > - const char *name, > - u32 address_cells, u32 size_cells) > -{ > - const struct fdt_property *prop; > - int i; > - int banks; > - const __be32 *cell; > - paddr_t start, size; > - u32 reg_cells = address_cells + size_cells; > - > - if ( address_cells < 1 || size_cells < 1 ) > - { > - printk("fdt: node `%s': invalid #address-cells or #size-cells", > - name); > - return; > - } > - > - prop = fdt_get_property(fdt, node, "reg", NULL); > - if ( !prop ) > - { > - printk("fdt: node `%s': missing `reg' property\n", name); > - return; > - } > - > - cell = (const __be32 *)prop->data; > - banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32)); > - > - for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ ) > - { > - device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); > - bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start; > - bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size; > - bootinfo.mem.nr_banks++; > - } > -} > - > -static void __init process_multiboot_node(const void *fdt, int node, > - const char *name, > - u32 address_cells, u32 size_cells) > -{ > - const struct fdt_property *prop; > - const __be32 *cell; > - int nr; > - struct bootmodule *mod; > - int len; > - > - if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 || > - fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 ) > - nr = MOD_KERNEL; > - else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 || > - fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 ) > - nr = MOD_INITRD; > - else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 ) > - nr = MOD_XSM; > - else > - panic("%s not a known xen multiboot type\n", name); > - > - mod = &bootinfo.modules.module[nr]; > - > - prop = fdt_get_property(fdt, node, "reg", &len); > - if ( !prop ) > - panic("node %s missing `reg' property\n", name); > - > - if ( len < dt_cells_to_size(address_cells + size_cells) ) > - panic("fdt: node `%s': `reg` property length is too short\n", > - name); > - > - cell = (const __be32 *)prop->data; > - device_tree_get_reg(&cell, address_cells, size_cells, > - &mod->start, &mod->size); > - > - prop = fdt_get_property(fdt, node, "bootargs", &len); > - if ( prop ) > - { > - if ( len > sizeof(mod->cmdline) ) > - panic("module %d command line too long\n", nr); > - > - safe_strcpy(mod->cmdline, prop->data); > - } > - else > - mod->cmdline[0] = 0; > - > - if ( nr > bootinfo.modules.nr_mods ) > - bootinfo.modules.nr_mods = nr; > -} > - > -static void __init process_chosen_node(const void *fdt, int node, > - const char *name, > - u32 address_cells, u32 size_cells) > -{ > - const struct fdt_property *prop; > - struct bootmodule *mod = &bootinfo.modules.module[MOD_INITRD]; > - paddr_t start, end; > - int len; > - > - printk("Checking for initrd in /chosen\n"); > - > - prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); > - if ( !prop ) > - /* No initrd present. */ > - return; > - if ( len != sizeof(u32) && len != sizeof(u64) ) > - { > - printk("linux,initrd-start property has invalid length %d\n", len); > - return; > - } > - start = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); > - > - prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); > - if ( !prop ) > - { > - printk("linux,initrd-end not present but -start was\n"); > - return; > - } > - if ( len != sizeof(u32) && len != sizeof(u64) ) > - { > - printk("linux,initrd-end property has invalid length %d\n", len); > - return; > - } > - end = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); > - > - if ( start >= end ) > - { > - printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", > - start, end); > - return; > - } > - > - printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); > - > - mod->start = start; > - mod->size = end - start; > - > - bootinfo.modules.nr_mods = max(MOD_INITRD, bootinfo.modules.nr_mods); > -} > - > -static int __init early_scan_node(const void *fdt, > - int node, const char *name, int depth, > - u32 address_cells, u32 size_cells, > - void *data) > -{ > - if ( device_tree_node_matches(fdt, node, "memory") ) > - process_memory_node(fdt, node, name, address_cells, size_cells); > - else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) || > - device_tree_node_compatible(fdt, node, "multiboot,module" )) > - process_multiboot_node(fdt, node, name, address_cells, size_cells); > - else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") ) > - process_chosen_node(fdt, node, name, address_cells, size_cells); > - > - return 0; > -} > - > -static void __init early_print_info(void) > -{ > - struct meminfo *mi = &bootinfo.mem; > - struct bootmodules *mods = &bootinfo.modules; > - int i, nr_rsvd; > - > - for ( i = 0; i < mi->nr_banks; i++ ) > - printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n", > - mi->bank[i].start, > - mi->bank[i].start + mi->bank[i].size - 1); > - printk("\n"); > - for ( i = 1 ; i < mods->nr_mods + 1; i++ ) > - printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %s\n", > - i, > - mods->module[i].start, > - mods->module[i].start + mods->module[i].size, > - mods->module[i].cmdline); > - nr_rsvd = fdt_num_mem_rsv(device_tree_flattened); > - for ( i = 0; i < nr_rsvd; i++ ) > - { > - paddr_t s, e; > - if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 ) > - continue; > - /* fdt_get_mem_rsv returns length */ > - e += s; > - printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n", > - i, s, e); > - } > - printk("\n"); > -} > - > -/** > - * device_tree_early_init - initialize early info from a DTB > - * @fdt: flattened device tree binary > - * > - * Returns the size of the DTB. > - */ > -size_t __init device_tree_early_init(const void *fdt, paddr_t paddr) > -{ > - struct bootmodule *mod; > - int ret; > - > - ret = fdt_check_header(fdt); > - if ( ret < 0 ) > - panic("No valid device tree\n"); > - > - mod = &bootinfo.modules.module[MOD_FDT]; > - mod->start = paddr; > - mod->size = fdt_totalsize(fdt); > - > - bootinfo.modules.nr_mods = max(MOD_FDT, bootinfo.modules.nr_mods); > - > - device_tree_for_each_node((void *)fdt, early_scan_node, NULL); > - early_print_info(); > - > - return fdt_totalsize(fdt); > -} > - > static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size, > unsigned long align) > { > diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h > index ea0dc46..21dbcd4 100644 > --- a/xen/include/asm-arm/setup.h > +++ b/xen/include/asm-arm/setup.h > @@ -53,6 +53,8 @@ int construct_dom0(struct domain *d); > > void discard_initial_modules(void); > > +size_t __init boot_fdt_info(const void *fdt, paddr_t paddr); > + > #endif > /* > * Local variables: > diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h > index 74e98f5..0edec85 100644 > --- a/xen/include/xen/device_tree.h > +++ b/xen/include/xen/device_tree.h > @@ -157,10 +157,7 @@ typedef int (*device_tree_node_func)(const void *fdt, > > extern const void *device_tree_flattened; > > -size_t __init device_tree_early_init(const void *fdt, paddr_t paddr); > - > const char __init *device_tree_bootargs(const void *fdt); > -void __init device_tree_dump(const void *fdt); > > /** > * dt_unflatten_host_device_tree - Unflatten the host device tree > -- > 1.7.10.4 >
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 63e0460..58a6714 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -21,6 +21,7 @@ obj-y += guestcopy.o obj-y += physdev.o obj-y += platform.o obj-y += setup.o +obj-y += bootfdt.o obj-y += time.o obj-y += smpboot.o obj-y += smp.o diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c new file mode 100644 index 0000000..11182cd --- /dev/null +++ b/xen/arch/arm/bootfdt.c @@ -0,0 +1,343 @@ +/* + * Early Device Tree + * + * Copyright (C) 2012-2014 Citrix Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <xen/config.h> +#include <xen/types.h> +#include <xen/lib.h> +#include <xen/kernel.h> +#include <xen/init.h> +#include <xen/device_tree.h> +#include <xen/libfdt/libfdt.h> +#include <asm/setup.h> + +static bool_t __init device_tree_node_matches(const void *fdt, int node, + const char *match) +{ + const char *name; + size_t match_len; + + name = fdt_get_name(fdt, node, NULL); + match_len = strlen(match); + + /* Match both "match" and "match@..." patterns but not + "match-foo". */ + return strncmp(name, match, match_len) == 0 + && (name[match_len] == '@' || name[match_len] == '\0'); +} + +static bool_t __init device_tree_node_compatible(const void *fdt, int node, + const char *match) +{ + int len, l; + int mlen; + const void *prop; + + mlen = strlen(match); + + prop = fdt_getprop(fdt, node, "compatible", &len); + if ( prop == NULL ) + return 0; + + while ( len > 0 ) { + if ( !dt_compat_cmp(prop, match) ) + return 1; + l = strlen(prop) + 1; + prop += l; + len -= l; + } + + return 0; +} + +static void __init device_tree_get_reg(const __be32 **cell, u32 address_cells, + u32 size_cells, u64 *start, u64 *size) +{ + *start = dt_next_cell(address_cells, cell); + *size = dt_next_cell(size_cells, cell); +} + +static u32 __init device_tree_get_u32(const void *fdt, int node, + const char *prop_name, u32 dflt) +{ + const struct fdt_property *prop; + + prop = fdt_get_property(fdt, node, prop_name, NULL); + if ( !prop || prop->len < sizeof(u32) ) + return dflt; + + return fdt32_to_cpu(*(uint32_t*)prop->data); +} + +/** + * device_tree_for_each_node - iterate over all device tree nodes + * @fdt: flat device tree. + * @func: function to call for each node. + * @data: data to pass to @func. + * + * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. + * + * Returns 0 if all nodes were iterated over successfully. If @func + * returns a value different from 0, that value is returned immediately. + */ +static int __init device_tree_for_each_node(const void *fdt, + device_tree_node_func func, + void *data) +{ + int node; + int depth; + u32 address_cells[DEVICE_TREE_MAX_DEPTH]; + u32 size_cells[DEVICE_TREE_MAX_DEPTH]; + int ret; + + for ( node = 0, depth = 0; + node >=0 && depth >= 0; + node = fdt_next_node(fdt, node, &depth) ) + { + const char *name = fdt_get_name(fdt, node, NULL); + + if ( depth >= DEVICE_TREE_MAX_DEPTH ) + { + printk("Warning: device tree node `%s' is nested too deep\n", + name); + continue; + } + + address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells", + depth > 0 ? address_cells[depth-1] : 0); + size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells", + depth > 0 ? size_cells[depth-1] : 0); + + + ret = func(fdt, node, name, depth, + address_cells[depth-1], size_cells[depth-1], data); + if ( ret != 0 ) + return ret; + } + return 0; +} + +static void __init process_memory_node(const void *fdt, int node, + const char *name, + u32 address_cells, u32 size_cells) +{ + const struct fdt_property *prop; + int i; + int banks; + const __be32 *cell; + paddr_t start, size; + u32 reg_cells = address_cells + size_cells; + + if ( address_cells < 1 || size_cells < 1 ) + { + printk("fdt: node `%s': invalid #address-cells or #size-cells", + name); + return; + } + + prop = fdt_get_property(fdt, node, "reg", NULL); + if ( !prop ) + { + printk("fdt: node `%s': missing `reg' property\n", name); + return; + } + + cell = (const __be32 *)prop->data; + banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32)); + + for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ ) + { + device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); + bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start; + bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size; + bootinfo.mem.nr_banks++; + } +} + +static void __init process_multiboot_node(const void *fdt, int node, + const char *name, + u32 address_cells, u32 size_cells) +{ + const struct fdt_property *prop; + const __be32 *cell; + int nr; + struct bootmodule *mod; + int len; + + if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 || + fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 ) + nr = MOD_KERNEL; + else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 || + fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 ) + nr = MOD_INITRD; + else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 ) + nr = MOD_XSM; + else + panic("%s not a known xen multiboot type\n", name); + + mod = &bootinfo.modules.module[nr]; + + prop = fdt_get_property(fdt, node, "reg", &len); + if ( !prop ) + panic("node %s missing `reg' property\n", name); + + if ( len < dt_cells_to_size(address_cells + size_cells) ) + panic("fdt: node `%s': `reg` property length is too short\n", + name); + + cell = (const __be32 *)prop->data; + device_tree_get_reg(&cell, address_cells, size_cells, + &mod->start, &mod->size); + + prop = fdt_get_property(fdt, node, "bootargs", &len); + if ( prop ) + { + if ( len > sizeof(mod->cmdline) ) + panic("module %d command line too long\n", nr); + + safe_strcpy(mod->cmdline, prop->data); + } + else + mod->cmdline[0] = 0; + + if ( nr > bootinfo.modules.nr_mods ) + bootinfo.modules.nr_mods = nr; +} + +static void __init process_chosen_node(const void *fdt, int node, + const char *name, + u32 address_cells, u32 size_cells) +{ + const struct fdt_property *prop; + struct bootmodule *mod = &bootinfo.modules.module[MOD_INITRD]; + paddr_t start, end; + int len; + + printk("Checking for initrd in /chosen\n"); + + prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); + if ( !prop ) + /* No initrd present. */ + return; + if ( len != sizeof(u32) && len != sizeof(u64) ) + { + printk("linux,initrd-start property has invalid length %d\n", len); + return; + } + start = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); + + prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); + if ( !prop ) + { + printk("linux,initrd-end not present but -start was\n"); + return; + } + if ( len != sizeof(u32) && len != sizeof(u64) ) + { + printk("linux,initrd-end property has invalid length %d\n", len); + return; + } + end = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); + + if ( start >= end ) + { + printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", + start, end); + return; + } + + printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); + + mod->start = start; + mod->size = end - start; + + bootinfo.modules.nr_mods = max(MOD_INITRD, bootinfo.modules.nr_mods); +} + +static int __init early_scan_node(const void *fdt, + int node, const char *name, int depth, + u32 address_cells, u32 size_cells, + void *data) +{ + if ( device_tree_node_matches(fdt, node, "memory") ) + process_memory_node(fdt, node, name, address_cells, size_cells); + else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) || + device_tree_node_compatible(fdt, node, "multiboot,module" )) + process_multiboot_node(fdt, node, name, address_cells, size_cells); + else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") ) + process_chosen_node(fdt, node, name, address_cells, size_cells); + + return 0; +} + +static void __init early_print_info(void) +{ + struct meminfo *mi = &bootinfo.mem; + struct bootmodules *mods = &bootinfo.modules; + int i, nr_rsvd; + + for ( i = 0; i < mi->nr_banks; i++ ) + printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n", + mi->bank[i].start, + mi->bank[i].start + mi->bank[i].size - 1); + printk("\n"); + for ( i = 1 ; i < mods->nr_mods + 1; i++ ) + printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %s\n", + i, + mods->module[i].start, + mods->module[i].start + mods->module[i].size, + mods->module[i].cmdline); + nr_rsvd = fdt_num_mem_rsv(device_tree_flattened); + for ( i = 0; i < nr_rsvd; i++ ) + { + paddr_t s, e; + if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 ) + continue; + /* fdt_get_mem_rsv returns length */ + e += s; + printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n", + i, s, e); + } + printk("\n"); +} + +/** + * boot_fdt_info - initialize bootinfo from a DTB + * @fdt: flattened device tree binary + * + * Returns the size of the DTB. + */ +size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) +{ + struct bootmodule *mod; + int ret; + + ret = fdt_check_header(fdt); + if ( ret < 0 ) + panic("No valid device tree\n"); + + mod = &bootinfo.modules.module[MOD_FDT]; + mod->start = paddr; + mod->size = fdt_totalsize(fdt); + + bootinfo.modules.nr_mods = max(MOD_FDT, bootinfo.modules.nr_mods); + + device_tree_for_each_node((void *)fdt, early_scan_node, NULL); + early_print_info(); + + return fdt_totalsize(fdt); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 63f6b8e..4a84a32 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -678,7 +678,7 @@ void __init start_xen(unsigned long boot_phys_offset, /* This is mapped by head.S */ device_tree_flattened = (void *)BOOT_FDT_VIRT_START + (fdt_paddr & ((1 << SECOND_SHIFT) - 1)); - fdt_size = device_tree_early_init(device_tree_flattened, fdt_paddr); + fdt_size = boot_fdt_info(device_tree_flattened, fdt_paddr); cmdline = device_tree_bootargs(device_tree_flattened); printk("Command line: %s\n", cmdline); diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index a1896d3..89de269 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -22,7 +22,6 @@ #include <xen/string.h> #include <xen/cpumask.h> #include <xen/ctype.h> -#include <xen/lib.h> #include <asm/setup.h> const void *device_tree_flattened; @@ -89,52 +88,6 @@ struct dt_bus unsigned int (*get_flags)(const __be32 *addr); }; -static bool_t __init device_tree_node_matches(const void *fdt, int node, - const char *match) -{ - const char *name; - size_t match_len; - - name = fdt_get_name(fdt, node, NULL); - match_len = strlen(match); - - /* Match both "match" and "match@..." patterns but not - "match-foo". */ - return strncmp(name, match, match_len) == 0 - && (name[match_len] == '@' || name[match_len] == '\0'); -} - -static bool_t __init device_tree_node_compatible(const void *fdt, int node, - const char *match) -{ - int len, l; - int mlen; - const void *prop; - - mlen = strlen(match); - - prop = fdt_getprop(fdt, node, "compatible", &len); - if ( prop == NULL ) - return 0; - - while ( len > 0 ) { - if ( !dt_compat_cmp(prop, match) ) - return 1; - l = strlen(prop) + 1; - prop += l; - len -= l; - } - - return 0; -} - -static void __init device_tree_get_reg(const __be32 **cell, u32 address_cells, - u32 size_cells, u64 *start, u64 *size) -{ - *start = dt_next_cell(address_cells, cell); - *size = dt_next_cell(size_cells, cell); -} - void dt_get_range(const __be32 **cell, const struct dt_device_node *np, u64 *address, u64 *size) { @@ -162,66 +115,6 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np, dt_set_cell(cellp, dt_n_size_cells(np), size); } -static u32 __init device_tree_get_u32(const void *fdt, int node, - const char *prop_name, u32 dflt) -{ - const struct fdt_property *prop; - - prop = fdt_get_property(fdt, node, prop_name, NULL); - if ( !prop || prop->len < sizeof(u32) ) - return dflt; - - return fdt32_to_cpu(*(uint32_t*)prop->data); -} - -/** - * device_tree_for_each_node - iterate over all device tree nodes - * @fdt: flat device tree. - * @func: function to call for each node. - * @data: data to pass to @func. - * - * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. - * - * Returns 0 if all nodes were iterated over successfully. If @func - * returns a value different from 0, that value is returned immediately. - */ -static int __init device_tree_for_each_node(const void *fdt, - device_tree_node_func func, - void *data) -{ - int node; - int depth; - u32 address_cells[DEVICE_TREE_MAX_DEPTH]; - u32 size_cells[DEVICE_TREE_MAX_DEPTH]; - int ret; - - for ( node = 0, depth = 0; - node >=0 && depth >= 0; - node = fdt_next_node(fdt, node, &depth) ) - { - const char *name = fdt_get_name(fdt, node, NULL); - - if ( depth >= DEVICE_TREE_MAX_DEPTH ) - { - printk("Warning: device tree node `%s' is nested too deep\n", - name); - continue; - } - - address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells", - depth > 0 ? address_cells[depth-1] : 0); - size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells", - depth > 0 ? size_cells[depth-1] : 0); - - - ret = func(fdt, node, name, depth, - address_cells[depth-1], size_cells[depth-1], data); - if ( ret != 0 ) - return ret; - } - return 0; -} - /** * device_tree_bootargs - return the bootargs (the Xen command line) * @fdt flat device tree. @@ -253,255 +146,6 @@ const char *device_tree_bootargs(const void *fdt) return prop->data; } -static int dump_node(const void *fdt, int node, const char *name, int depth, - u32 address_cells, u32 size_cells, void *data) -{ - char prefix[2*DEVICE_TREE_MAX_DEPTH + 1] = ""; - int i; - int prop; - - for ( i = 0; i < depth; i++ ) - safe_strcat(prefix, " "); - - if ( name[0] == '\0' ) - name = "/"; - printk("%s%s:\n", prefix, name); - - for ( prop = fdt_first_property_offset(fdt, node); - prop >= 0; - prop = fdt_next_property_offset(fdt, prop) ) - { - const struct fdt_property *p; - - p = fdt_get_property_by_offset(fdt, prop, NULL); - - printk("%s %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff))); - } - - return 0; -} - -/** - * device_tree_dump - print a text representation of a device tree - * @fdt: flat device tree to print - */ -void __init device_tree_dump(const void *fdt) -{ - device_tree_for_each_node(fdt, dump_node, NULL); -} - - -static void __init process_memory_node(const void *fdt, int node, - const char *name, - u32 address_cells, u32 size_cells) -{ - const struct fdt_property *prop; - int i; - int banks; - const __be32 *cell; - paddr_t start, size; - u32 reg_cells = address_cells + size_cells; - - if ( address_cells < 1 || size_cells < 1 ) - { - printk("fdt: node `%s': invalid #address-cells or #size-cells", - name); - return; - } - - prop = fdt_get_property(fdt, node, "reg", NULL); - if ( !prop ) - { - printk("fdt: node `%s': missing `reg' property\n", name); - return; - } - - cell = (const __be32 *)prop->data; - banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32)); - - for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ ) - { - device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); - bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start; - bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size; - bootinfo.mem.nr_banks++; - } -} - -static void __init process_multiboot_node(const void *fdt, int node, - const char *name, - u32 address_cells, u32 size_cells) -{ - const struct fdt_property *prop; - const __be32 *cell; - int nr; - struct bootmodule *mod; - int len; - - if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 || - fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 ) - nr = MOD_KERNEL; - else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 || - fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 ) - nr = MOD_INITRD; - else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 ) - nr = MOD_XSM; - else - panic("%s not a known xen multiboot type\n", name); - - mod = &bootinfo.modules.module[nr]; - - prop = fdt_get_property(fdt, node, "reg", &len); - if ( !prop ) - panic("node %s missing `reg' property\n", name); - - if ( len < dt_cells_to_size(address_cells + size_cells) ) - panic("fdt: node `%s': `reg` property length is too short\n", - name); - - cell = (const __be32 *)prop->data; - device_tree_get_reg(&cell, address_cells, size_cells, - &mod->start, &mod->size); - - prop = fdt_get_property(fdt, node, "bootargs", &len); - if ( prop ) - { - if ( len > sizeof(mod->cmdline) ) - panic("module %d command line too long\n", nr); - - safe_strcpy(mod->cmdline, prop->data); - } - else - mod->cmdline[0] = 0; - - if ( nr > bootinfo.modules.nr_mods ) - bootinfo.modules.nr_mods = nr; -} - -static void __init process_chosen_node(const void *fdt, int node, - const char *name, - u32 address_cells, u32 size_cells) -{ - const struct fdt_property *prop; - struct bootmodule *mod = &bootinfo.modules.module[MOD_INITRD]; - paddr_t start, end; - int len; - - printk("Checking for initrd in /chosen\n"); - - prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); - if ( !prop ) - /* No initrd present. */ - return; - if ( len != sizeof(u32) && len != sizeof(u64) ) - { - printk("linux,initrd-start property has invalid length %d\n", len); - return; - } - start = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); - - prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); - if ( !prop ) - { - printk("linux,initrd-end not present but -start was\n"); - return; - } - if ( len != sizeof(u32) && len != sizeof(u64) ) - { - printk("linux,initrd-end property has invalid length %d\n", len); - return; - } - end = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); - - if ( start >= end ) - { - printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", - start, end); - return; - } - - printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); - - mod->start = start; - mod->size = end - start; - - bootinfo.modules.nr_mods = max(MOD_INITRD, bootinfo.modules.nr_mods); -} - -static int __init early_scan_node(const void *fdt, - int node, const char *name, int depth, - u32 address_cells, u32 size_cells, - void *data) -{ - if ( device_tree_node_matches(fdt, node, "memory") ) - process_memory_node(fdt, node, name, address_cells, size_cells); - else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) || - device_tree_node_compatible(fdt, node, "multiboot,module" )) - process_multiboot_node(fdt, node, name, address_cells, size_cells); - else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") ) - process_chosen_node(fdt, node, name, address_cells, size_cells); - - return 0; -} - -static void __init early_print_info(void) -{ - struct meminfo *mi = &bootinfo.mem; - struct bootmodules *mods = &bootinfo.modules; - int i, nr_rsvd; - - for ( i = 0; i < mi->nr_banks; i++ ) - printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n", - mi->bank[i].start, - mi->bank[i].start + mi->bank[i].size - 1); - printk("\n"); - for ( i = 1 ; i < mods->nr_mods + 1; i++ ) - printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %s\n", - i, - mods->module[i].start, - mods->module[i].start + mods->module[i].size, - mods->module[i].cmdline); - nr_rsvd = fdt_num_mem_rsv(device_tree_flattened); - for ( i = 0; i < nr_rsvd; i++ ) - { - paddr_t s, e; - if ( fdt_get_mem_rsv(device_tree_flattened, i, &s, &e) < 0 ) - continue; - /* fdt_get_mem_rsv returns length */ - e += s; - printk(" RESVD[%d]: %"PRIpaddr" - %"PRIpaddr"\n", - i, s, e); - } - printk("\n"); -} - -/** - * device_tree_early_init - initialize early info from a DTB - * @fdt: flattened device tree binary - * - * Returns the size of the DTB. - */ -size_t __init device_tree_early_init(const void *fdt, paddr_t paddr) -{ - struct bootmodule *mod; - int ret; - - ret = fdt_check_header(fdt); - if ( ret < 0 ) - panic("No valid device tree\n"); - - mod = &bootinfo.modules.module[MOD_FDT]; - mod->start = paddr; - mod->size = fdt_totalsize(fdt); - - bootinfo.modules.nr_mods = max(MOD_FDT, bootinfo.modules.nr_mods); - - device_tree_for_each_node((void *)fdt, early_scan_node, NULL); - early_print_info(); - - return fdt_totalsize(fdt); -} - static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size, unsigned long align) { diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h index ea0dc46..21dbcd4 100644 --- a/xen/include/asm-arm/setup.h +++ b/xen/include/asm-arm/setup.h @@ -53,6 +53,8 @@ int construct_dom0(struct domain *d); void discard_initial_modules(void); +size_t __init boot_fdt_info(const void *fdt, paddr_t paddr); + #endif /* * Local variables: diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h index 74e98f5..0edec85 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -157,10 +157,7 @@ typedef int (*device_tree_node_func)(const void *fdt, extern const void *device_tree_flattened; -size_t __init device_tree_early_init(const void *fdt, paddr_t paddr); - const char __init *device_tree_bootargs(const void *fdt); -void __init device_tree_dump(const void *fdt); /** * dt_unflatten_host_device_tree - Unflatten the host device tree
Move the early code for walking the flattended device tree out of device_tree.c. The intention is that eventually only only the proper (i.e. unflattened) device tree support will live in device_tree.c. The new home is bootfdt.c to try and better reflect the purpose of the code. Although in theory this early code could be generic in reality it is pretty ARM specific, so place it under xen/arch/arm until a second user wants it. As part of the move rename device_tree_early_init to boot_fdt_info. Drop device_tree_dump, it is unused. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/bootfdt.c | 343 +++++++++++++++++++++++++++++++++++++++ xen/arch/arm/setup.c | 2 +- xen/common/device_tree.c | 356 ----------------------------------------- xen/include/asm-arm/setup.h | 2 + xen/include/xen/device_tree.h | 3 - 6 files changed, 347 insertions(+), 360 deletions(-) create mode 100644 xen/arch/arm/bootfdt.c