[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] boot-wrapper: simple multi module loading support



Apparently kvmarm@ is the place for boot-wrapper discussions so
apologies for the otherwise Xen related mail ;)

The following implements support for a very basic protocol for loading
multiple "modules" and providing them to the kernel. The ARM port of Xen
uses this to support passing both a dom0 kernel and initrd to the
hypervisor "kernel".

The Xen side of this can be found in the series at:
        http://lists.xen.org/archives/html/xen-devel/2012-09/msg00065.html

With that you can boot Xen on arm using the semi-hosting feature of the
model (paths are host paths):
        $MODEL linux-system-semi.axf -C cluster.cpu0.semihosting-cmd_line=\
                        '--kernel xen-arm.bin \
                         --module zImage earlyprintk=xenboot console=ttyAMA1 
root=/dev/mmcblk0 ro \
                         --dtb vexpress-v2p-aem-v7a-xen.dtb -- dom0_mem=256M'

Until we know what bootloaders are going to become common in the ARM
servers world it hard to know who we should be working with to define a
proper protocol going forward and which bootloaders to supply patches
for etc. If anyone has any pointers that would be very useful.

One thing I've been considering is a port of the multiboot protocol[0]
used on x86 to ARM.

It seems like there is at least the kernel of an idea to port Grub2 to
ARM[1] which makes a port of multiboot as well seem like a reasonable
thing since grub is the reference implementation of the multiboot spec.

Ian.

[0] http://www.gnu.org/software/grub/manual/multiboot/multiboot.html
[1] https://wiki.linaro.org/OfficeofCTO/Grub2

8<--------------------------------------------

>From bb3c6184beb57ba2649970b8e8568b29c0720294 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ian.campbell@xxxxxxxxxx>
Date: Thu, 23 Aug 2012 14:56:26 +0000
Subject: [PATCH] Implement simple multi-module support.

This implementation supports up to 2 modules, each with its own
command line.
---
 semi_loader.c |  129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 semi_loader.h |   16 +++++++-
 semihosting.h |    7 +++
 3 files changed, 146 insertions(+), 6 deletions(-)

diff --git a/semi_loader.c b/semi_loader.c
index 6677527..348a394 100644
--- a/semi_loader.c
+++ b/semi_loader.c
@@ -46,6 +46,7 @@ static void _print_info(char const **strings)
 
 #define CMDLINE_KERNEL "--kernel"
 #define CMDLINE_INITRD "--initrd"
+#define CMDLINE_MODULE "--module"
 #define CMDLINE_NOINITRD "--no-initrd"
 #define CMDLINE_DTB "--dtb"
 #define CMDLINE_FDT "--fdt"    /* deprecated */
@@ -99,7 +100,7 @@ static int _fdt_make_node(void *fdt, int parentoffset, const 
char *name)
 
 static void update_fdt(void **dest, struct loader_info *info)
 {
-       int e;
+       int e, m;
        int _chosen;
        void *fdt;
        uint32_t const *p;
@@ -184,6 +185,31 @@ no_add_memory:
        if(e < 0)
                goto libfdt_error;
 
+       /* XXX this should be a loop & some string munging in lieu of printf */
+       if(info->nr_modules > 0) {
+               if ((e = fdt_setprop_cell(fdt, _chosen, "module1-start",
+                                         info->module[0].start)) < 0)
+                       goto libfdt_error;
+               if ((e = fdt_setprop_cell(fdt, _chosen, "module1-end",
+                                         info->module[0].end)) < 0)
+                       goto libfdt_error;
+               if ((e = fdt_setprop_string(fdt, _chosen, "module1-args",
+                                         info->module[0].args)) < 0)
+                       goto libfdt_error;
+       }
+       if(info->nr_modules > 1) {
+               if ((e = fdt_setprop_cell(fdt, _chosen, "module2-start",
+                                         info->module[1].start)) < 0)
+                       goto libfdt_error;
+               if ((e = fdt_setprop_cell(fdt, _chosen, "module2-end",
+                                         info->module[1].end)) < 0)
+                       goto libfdt_error;
+               if ((e = fdt_setprop_string(fdt, _chosen, "module2-args",
+                                         info->module[1].args)) < 0)
+                       goto libfdt_error;
+       }
+
+
        if(info->initrd_start) {
                uint32_t initrd_end = info->initrd_start + info->initrd_size;
 
@@ -196,6 +222,12 @@ no_add_memory:
                        goto libfdt_error;
        }
 
+       if (info->nr_modules > 0) {
+               if ((e = fdt_setprop_cell(fdt, _chosen, "nr-modules",
+                                         info->nr_modules)) < 0)
+                       goto libfdt_error;
+       }
+
        /* success */
 
        /* clean up */
@@ -234,6 +266,18 @@ static void find_space(char **s)
        *s = t;
 }
 
+static void find_delim(char **s, char const *delim)
+{
+       int l = strlen(delim);
+       char *t = *s;
+       while (*t) {
+               if (!strncmp(t, delim, l))
+                       break;
+               t++;
+       }
+       *s = t;
+}
+
 static int match_word(char **s, char const *string)
 {
        unsigned l;
@@ -260,7 +304,7 @@ static char *match_option(char **s, char const 
*option_string)
                return (void *)0;
 
        if(!**s)
-               usage_fatal("Option requires as argument: ",
+               usage_fatal("Option requires an argument: ",
                        option_string, "\n");
 
        /* otherwise, *s now points to the argument */
@@ -275,6 +319,42 @@ static char *match_option(char **s, char const 
*option_string)
        return arg;
 }
 
+/* Match up to the next -- */
+static int match_module_arg(char **s,
+                           char const *option_string,
+                           int no_more_room,
+                           char **mod, char **args)
+{
+       char *arg;
+       if(!match_word(s, option_string))
+               return 0;
+
+       if(!**s)
+               usage_fatal("Option requires an argument: ",
+                       option_string, "\n");
+
+       if ( no_more_room )
+               usage_fatal("Too many modules\n");
+
+       /* *s points to the module */
+       *mod = *s;
+
+       find_space(s);
+       if(**s) {
+               *(*s)++ = '\0'; /* null-terminate if necessary */
+               skip_space(s);  /* skip any remaining space */
+       }
+
+       /* Now find the (optional) module arguments */
+       arg = *s;
+       find_delim(s, "--");
+       if (**s)
+               *((*s)-1) = '\0'; /* null-terminate if necessary */
+       if (arg != *s)
+               *args = arg;
+       return 1;
+}
+
 static void load_file_essential(void **dest, char const *filename,
                                unsigned *size, char const *failmsg)
 {
@@ -331,17 +411,23 @@ static char *fdt_arg = (void *)0;
 static char *dtb_arg = (void *)0;
 static char *cmdline_arg = (void *)0;
 static char *noinitrd_arg = (void *)0;
+static struct module_arg_t {
+       char *mod;
+       char *args;
+} module_args[MODULES_MAX];
+int nr_modules = 0;
 
 static const struct {
        char const *option_string;
        char **argp;
-       enum { OPT_ARG, OPT_BOOL, OPT_REST } action;
+       enum { OPT_ARG, OPT_BOOL, OPT_MODULE, OPT_REST } action;
 } options[] = {
        { CMDLINE_KERNEL,       &kernel_arg,    OPT_ARG         },
        { CMDLINE_INITRD,       &initrd_arg,    OPT_ARG         },
        { CMDLINE_NOINITRD,     &noinitrd_arg,  OPT_BOOL        },
        { CMDLINE_FDT,          &fdt_arg,       OPT_ARG         },
        { CMDLINE_DTB,          &dtb_arg,       OPT_ARG         },
+       { CMDLINE_MODULE,       NULL,           OPT_MODULE      },
        { CMDLINE_REST,         &cmdline_arg,   OPT_REST        },
 };
 
@@ -391,8 +477,19 @@ void load_kernel(struct loader_info *info)
                                                options[i].option_string))
                                        continue;
 
-                       *options[i].argp = cmdline;
-                       goto args_done;
+                               *options[i].argp = cmdline;
+                               goto args_done;
+
+                       case OPT_MODULE:
+                               if (!match_module_arg(&cmdline,
+                                       options[i].option_string,
+                                       nr_modules >= MODULES_MAX,
+                                       &module_args[nr_modules].mod,
+                                       &module_args[nr_modules].args))
+                                       continue;
+
+                               nr_modules++;
+                               goto next_arg;
 
                        case OPT_ARG:
                                arg = match_option(&cmdline,
@@ -420,6 +517,11 @@ args_done:
        if(initrd_arg && noinitrd_arg)
                usage_fatal("Option --initrd conflicts with --no-initrd.\n");
 
+       if (initrd_arg && nr_modules)
+               usage_fatal("Option --initrd and --modules conflict\n");
+       if (noinitrd_arg && nr_modules)
+               usage_fatal("Option --no-initrd and --modules conflict\n");
+
        if(fdt_arg) {
                warn("--fdt is deprecated.  Please use --dtb instead.\n");
 
@@ -462,6 +564,23 @@ args_done:
        } else
                usage_fatal("Expected " CMDLINE_KERNEL "\n");
 
+       phys = PHYS_OFFSET + MODULES_OFFSET;
+       for (i = 0 ; i < nr_modules; i++)
+       {
+               unsigned size;
+
+               phys = ALIGN(phys, MODULES_ALIGN);
+
+               info->module[i].start = (unsigned)phys;
+
+               load_file_essential(&phys, module_args[i].mod, &size,
+                                   "Failed to load module image");
+               info("Loaded module: ", module_args[i].mod, "\n");
+               info->module[i].end = (unsigned)phys;
+               info->module[i].args = module_args[i].args;
+       }
+       info->nr_modules = nr_modules;
+
        /* move the kernel to the correct place, if necessary */
 
        correct_kernel_location(info);
diff --git a/semi_loader.h b/semi_loader.h
index 6d9d565..a3a486a 100644
--- a/semi_loader.h
+++ b/semi_loader.h
@@ -57,7 +57,11 @@ static const char uImage_magic[] = {
 #define PHYS_OFFSET 0x80000000
 #define PHYS_SIZE 0x80000000 /* can limit on kernel cmdline if necessary */
 #define ATAGS_OFFSET 0x100
-#define TEXT_OFFSET 0x200000
+#define TEXT_OFFSET   0x200000
+#define MODULES_OFFSET   0xA00000
+
+#define MODULES_ALIGN 0x1000 /* Modules are 4K aligned */
+
 #define INITRD_OFFSET 0xD00000 /* qemu uses the same random offset */
 
 #define FDT_SIZE_MAX 0x10000   /* maximum size allowed for device tree blob */
@@ -71,6 +75,13 @@ static const char uImage_magic[] = {
 #define ALIGN_INT(n, size) (((n) + ((size) - 1)) & ~((size) - 1))
 #define ALIGN(p, size) ((void *)ALIGN_INT((unsigned)(p), size))
 
+#define MODULES_MAX 2
+struct module_t {
+       unsigned start;
+       unsigned end;
+       char *args;
+};
+
 struct loader_info {
        unsigned kernel_size;   /* nonzero indicates preloaded kernel size */
        unsigned initrd_start;  /* start of preloaded initrd, if any */
@@ -78,6 +89,9 @@ struct loader_info {
        unsigned cmdline_start; /* start of cmdline buffer */
        unsigned cmdline_size;
 
+       struct module_t module[MODULES_MAX];
+       int nr_modules;
+
        /* The remaining fields are set by the loader: */
 
        /* There could be a built-in FDT, but currently that it not supported */
diff --git a/semihosting.h b/semihosting.h
index 40817c2..baad318 100644
--- a/semihosting.h
+++ b/semihosting.h
@@ -45,6 +45,13 @@ void semi_exit(void);
 /* semi_load_file: *dest is advanced to point to the end of the loaded data */
 int semi_load_file(void **dest, unsigned *size, char const *filename);
 
+/* Trigger a break point in the fast model... */
+#define MODEL_BKPT() asm volatile(\
+       "mov r0, #0x18;\n /* angel_SWIreason_ReportException */\n"\
+       "mov r1, #0x20000;/* 0x20020= ADP_Stopped_BreakPoint */\n"\
+       "orr r1, r1, #0x20;\n"\
+       "swi 0x123456;\n" ::: "r0", "r1")
+
 #endif /* ! __ASSEMBLER__ */
 
 #endif /* ! SEMIHOSTING_H */
-- 
1.7.9.1




_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.