@@ -165,23 +165,22 @@ static void __init process_multiboot_node(const void *fdt, int node,
{
const struct fdt_property *prop;
const __be32 *cell;
- int nr;
- struct bootmodule *mod;
+ bootmodulekind kind;
+ paddr_t start, size;
+ const char *cmdline;
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;
+ kind = BOOTMOD_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;
+ kind = BOOTMOD_RAMDISK;
else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 )
- nr = MOD_XSM;
+ kind = BOOTMOD_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);
@@ -191,22 +190,19 @@ static void __init process_multiboot_node(const void *fdt, int node,
name);
cell = (const __be32 *)prop->data;
- device_tree_get_reg(&cell, address_cells, size_cells,
- &mod->start, &mod->size);
+ device_tree_get_reg(&cell, address_cells, size_cells, &start, &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);
+ if ( len > BOOTMOD_MAX_CMDLINE )
+ panic("module %s command line too long\n", name);
+ cmdline = prop->data;
}
else
- mod->cmdline[0] = 0;
+ cmdline = NULL;
- if ( nr > bootinfo.modules.nr_mods )
- bootinfo.modules.nr_mods = nr;
+ add_boot_module(kind, start, size, cmdline);
}
static void __init process_chosen_node(const void *fdt, int node,
@@ -214,7 +210,6 @@ static void __init process_chosen_node(const void *fdt, int node,
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;
@@ -253,10 +248,7 @@ static void __init process_chosen_node(const void *fdt, int node,
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);
+ add_boot_module(BOOTMOD_RAMDISK, start, end-start, NULL);
}
static int __init early_scan_node(const void *fdt,
@@ -286,7 +278,7 @@ static void __init early_print_info(void)
mi->bank[i].start,
mi->bank[i].start + mi->bank[i].size - 1);
printk("\n");
- for ( i = 1 ; i < mods->nr_mods + 1; i++ )
+ for ( i = 1 ; i < mods->nr_mods; i++ )
printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %s\n",
i,
mods->module[i].start,
@@ -314,18 +306,13 @@ static void __init early_print_info(void)
*/
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);
+ add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), NULL);
device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
early_print_info();
@@ -345,10 +332,8 @@ const char *boot_fdt_cmdline(const void *fdt)
prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL);
if ( prop == NULL )
{
- struct bootmodule *dom0_mod = NULL;
-
- if ( bootinfo.modules.nr_mods >= MOD_KERNEL )
- dom0_mod = &bootinfo.modules.module[MOD_KERNEL];
+ struct bootmodule *dom0_mod =
+ boot_module_find_by_kind(BOOTMOD_KERNEL);
if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) ||
( dom0_mod && dom0_mod->cmdline[0] ) )
@@ -161,9 +161,10 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
int res = 0;
int had_dom0_bootargs = 0;
- if ( bootinfo.modules.nr_mods >= MOD_KERNEL &&
- bootinfo.modules.module[MOD_KERNEL].cmdline[0] )
- bootargs = &bootinfo.modules.module[MOD_KERNEL].cmdline[0];
+ struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+
+ if ( mod && mod->cmdline[0] )
+ bootargs = &mod->cmdline[0];
dt_for_each_property_node (node, prop)
{
@@ -210,6 +211,8 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
if ( dt_node_path_is_equal(node, "/chosen") )
{
+ struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+
if ( bootargs )
{
res = fdt_property(kinfo->fdt, "bootargs", bootargs,
@@ -222,7 +225,7 @@ static int write_properties(struct domain *d, struct kernel_info *kinfo,
* If the bootloader provides an initrd, we must create a placeholder
* for the initrd properties. The values will be replaced later.
*/
- if ( bootinfo.modules.module[MOD_INITRD].size )
+ if ( mod && mod->size )
{
u64 a = 0;
res = fdt_property(kinfo->fdt, "linux,initrd-start", &a, sizeof(a));
@@ -976,18 +979,21 @@ static void dtb_load(struct kernel_info *kinfo)
static void initrd_load(struct kernel_info *kinfo)
{
+ struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_RAMDISK);
paddr_t load_addr = kinfo->initrd_paddr;
- paddr_t paddr = bootinfo.modules.module[MOD_INITRD].start;
- paddr_t len = bootinfo.modules.module[MOD_INITRD].size;
+ paddr_t paddr, len;
unsigned long offs;
int node;
int res;
__be32 val[2];
__be32 *cellp;
- if ( !len )
+ if ( !mod || !mod->size )
return;
+ paddr = mod->start;
+ len = mod->size;
+
printk("Loading dom0 initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
paddr, load_addr, load_addr + len);
@@ -68,8 +68,8 @@ static void place_modules(struct kernel_info *info,
paddr_t kernbase, paddr_t kernend)
{
/* Align DTB and initrd size to 2Mb. Linux only requires 4 byte alignment */
- const paddr_t initrd_len =
- ROUNDUP(bootinfo.modules.module[MOD_INITRD].size, MB(2));
+ const struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+ const paddr_t initrd_len = ROUNDUP(mod ? mod->size : 0, MB(2));
const paddr_t dtb_len = ROUNDUP(fdt_totalsize(info->fdt), MB(2));
const paddr_t modsize = initrd_len + dtb_len;
@@ -372,20 +372,21 @@ err:
int kernel_probe(struct kernel_info *info)
{
+ struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
int rc;
paddr_t start, size;
- start = bootinfo.modules.module[MOD_KERNEL].start;
- size = bootinfo.modules.module[MOD_KERNEL].size;
-
- if ( !size )
+ if ( !mod || !mod->size )
{
printk(XENLOG_ERR "Missing kernel boot module?\n");
return -ENOENT;
}
- printk("Loading kernel from boot module %d\n", MOD_KERNEL);
+ start = mod->start;
+ size = mod->size;
+
+ printk("Loading kernel from boot module @ %"PRIpaddr"\n", start);
#ifdef CONFIG_ARM_64
rc = kernel_zimage64_probe(info, start, size);
@@ -183,17 +183,56 @@ static void dt_unreserved_regions(paddr_t s, paddr_t e,
cb(s, e);
}
+void add_boot_module(bootmodulekind kind, paddr_t start, paddr_t size,
+ const char *cmdline)
+{
+ struct bootmodules *mods = &bootinfo.modules;
+ struct bootmodule *mod;
+
+ if ( mods->nr_mods == MAX_MODULES )
+ {
+ printk("Ignoring boot module at %"PRIpaddr"-%"PRIpaddr" (too many)\n",
+ start, start + size);
+ return;
+ }
+
+ mod = &mods->module[mods->nr_mods++];
+ mod->kind = kind;
+ mod->start = start;
+ mod->size = size;
+ if ( cmdline )
+ safe_strcpy(mod->cmdline, cmdline);
+ else
+ mod->cmdline[0] = 0;
+
+}
+
+struct bootmodule * __init boot_module_find_by_kind(bootmodulekind kind)
+{
+ struct bootmodules *mods = &bootinfo.modules;
+ struct bootmodule *mod;
+ int i;
+ for (i = 0 ; i < mods->nr_mods ; i++ )
+ {
+ mod = &mods->module[i];
+ if ( mod->kind == kind )
+ return mod;
+ }
+ return NULL;
+}
+
void __init discard_initial_modules(void)
{
struct bootmodules *mi = &bootinfo.modules;
int i;
- for ( i = MOD_DISCARD_FIRST; i <= mi->nr_mods; i++ )
+ for ( i = 0; i <= mi->nr_mods; i++ )
{
paddr_t s = mi->module[i].start;
paddr_t e = s + PAGE_ALIGN(mi->module[i].size);
- dt_unreserved_regions(s, e, init_domheap_pages, 0);
+ if ( mi->module[i].kind > BOOTMOD_LAST_PRESERVE )
+ dt_unreserved_regions(s, e, init_domheap_pages, 0);
}
mi->nr_mods = 0;
@@ -360,9 +399,7 @@ static paddr_t __init get_xen_paddr(void)
printk("Placing Xen at 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
paddr, paddr + min_size);
- bootinfo.modules.module[MOD_XEN].start = paddr;
- bootinfo.modules.module[MOD_XEN].size = min_size;
-
+ add_boot_module(BOOTMOD_XEN, paddr, min_size, NULL);
return paddr;
}
@@ -5,14 +5,19 @@
#define NR_MEM_BANKS 8
-#define MOD_XEN 0
-#define MOD_FDT 1
-#define MOD_KERNEL 2
-#define MOD_INITRD 3
-#define MOD_XSM 4
-#define NR_MODULES 5
+#define MAX_MODULES 5 /* Current maximum useful modules */
+
+typedef enum {
+ BOOTMOD_XEN,
+ BOOTMOD_FDT,
+ /* Everything up to here is not freed after start of day */
+ BOOTMOD_LAST_PRESERVE = BOOTMOD_FDT,
+ BOOTMOD_KERNEL,
+ BOOTMOD_RAMDISK,
+ BOOTMOD_XSM,
+ BOOTMOD_UNKNOWN
+} bootmodulekind;
-#define MOD_DISCARD_FIRST MOD_FDT
struct membank {
paddr_t start;
@@ -24,16 +29,18 @@ struct meminfo {
struct membank bank[NR_MEM_BANKS];
};
+#define BOOTMOD_MAX_CMDLINE 1024
struct bootmodule {
+ bootmodulekind kind;
paddr_t start;
paddr_t size;
- char cmdline[1024];
+ char cmdline[BOOTMOD_MAX_CMDLINE];
};
struct bootmodules {
int nr_mods;
/* Module 0 is Xen itself, followed by the provided modules-proper */
- struct bootmodule module[NR_MODULES];
+ struct bootmodule module[MAX_MODULES];
};
struct bootinfo {
@@ -56,6 +63,10 @@ void discard_initial_modules(void);
size_t __init boot_fdt_info(const void *fdt, paddr_t paddr);
const char __init *boot_fdt_cmdline(const void *fdt);
+void add_boot_module(bootmodulekind kind, paddr_t start, paddr_t size,
+ const char *cmdline);
+struct bootmodule *boot_module_find_by_kind(bootmodulekind kind);
+
#endif
/*
* Local variables:
This is more natural and better matches how multiboot is actually supposed to work. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/bootfdt.c | 49 +++++++++++++++---------------------------- xen/arch/arm/domain_build.c | 20 +++++++++++------- xen/arch/arm/kernel.c | 15 ++++++------- xen/arch/arm/setup.c | 47 ++++++++++++++++++++++++++++++++++++----- xen/include/asm-arm/setup.h | 29 +++++++++++++++++-------- 5 files changed, 100 insertions(+), 60 deletions(-)