diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index d50658bfea..fb1ec87ddd 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -222,11 +222,12 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo, */ if ( early_info.modules.module[MOD_INITRD].size ) { - res = fdt_property_cell(kinfo->fdt, "linux,initrd-start", 0); + u64 a = 0; + res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a)); if ( res ) return res; - res = fdt_property_cell(kinfo->fdt, "linux,initrd-end", 0); + res = fdt_property(kinfo->fdt, "linux,initrd-end", &a, sizeof(a)); if ( res ) return res; } @@ -926,6 +927,8 @@ static void initrd_load(struct kernel_info *kinfo) unsigned long offs; int node; int res; + __be32 val[2]; + __be32 *cellp; if ( !len ) return; @@ -938,13 +941,17 @@ static void initrd_load(struct kernel_info *kinfo) if ( node < 0 ) panic("Cannot find the /chosen node"); - res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-start", - load_addr); + cellp = (__be32 *)val; + dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr); + res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-start", + val, sizeof(val)); if ( res ) panic("Cannot fix up \"linux,initrd-start\" property"); - res = fdt_setprop_inplace_cell(kinfo->fdt, node, "linux,initrd-end", - load_addr + len); + cellp = (__be32 *)val; + dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr + len); + res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-end", + val, sizeof(val)); if ( res ) panic("Cannot fix up \"linux,initrd-end\" property"); diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index 943b18185d..84e709d95e 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -390,18 +390,45 @@ 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 dt_mb_module *mod = &early_info.modules.module[MOD_INITRD]; - u32 start, end; + paddr_t start, end; + int len; dt_printk("Checking for initrd in /chosen\n"); - start = device_tree_get_u32(fdt, node, "linux,initrd-start", 0); - end = device_tree_get_u32(fdt, node, "linux,initrd-end", 0); - - if ( !start || !end || (start >= end) ) + prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); + if ( !prop ) + /* No initrd present. */ return; + if ( len != sizeof(u32) && len != sizeof(u64) ) + { + dt_printk("linux,initrd-start property has invalid length %d\n", len); + return; + } + start = dt_read_number((void *)&prop->data, dt_size_to_cells(len)); - dt_printk("Initrd 0x%x-0x%x\n", start, end); + prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); + if ( !prop ) + { + dt_printk("linux,initrd-end not present but -start was\n"); + return; + } + if ( len != sizeof(u32) && len != sizeof(u64) ) + { + dt_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 ) + { + dt_printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", + start, end); + return; + } + + dt_printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); mod->start = start; mod->size = end - start; diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h index da78c9f0d4..9a8c3de719 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -256,12 +256,18 @@ static inline u64 dt_read_number(const __be32 *cell, int size) return r; } -/* Helper to convert a number of cells in bytes */ +/* Helper to convert a number of cells to bytes */ static inline int dt_cells_to_size(int size) { return (size * sizeof (u32)); } +/* Helper to convert a number of bytes to cells, rounds down */ +static inline int dt_size_to_cells(int bytes) +{ + return (bytes / sizeof(u32)); +} + static inline u64 dt_next_cell(int s, const __be32 **cellp) { const __be32 *p = *cellp;