]> xenbits.xensource.com Git - people/liuw/stubdom.git/commitdiff
domain builder: multiboot-like module support
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 11 Dec 2009 08:44:33 +0000 (08:44 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 11 Dec 2009 08:44:33 +0000 (08:44 +0000)
This defines how multiple modules can be passed to a domain by packing
them together into a "multiboot module" in a way very similar to the
multiboot standard.  An SIF_ flag is added to announce such package.
This also adds a packing implementation to PV-GRUB.

Signed-Off-By: Samuel Thibault <samuel.thibault@ens-lyon.org>
grub.patches/99minios
grub/config.h
grub/kexec.c
grub/mini-os.c

index 6c481b17746989720d6ce001c4f4bf8c12eff6bc..6296ae2c5fb09f419bf5517b7a7fc2b6c20da173 100644 (file)
@@ -151,6 +151,14 @@ Index: grub/stage2/builtins.c
  
  /* print */
  static int
+@@ -2910,6 +2910,7 @@
+   switch (kernel_type)
+     {
+     case KERNEL_TYPE_MULTIBOOT:
++    case KERNEL_TYPE_PV:
+       if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN)
+       {
+         errnum = ERR_WONT_FIT;
 @@ -3776,6 +3802,7 @@
  };
  
index dcb2e7a15c35629ac3201ab934598f1c8a37b792..1649d514592fe5c51a27be6064079a7b679fe359 100644 (file)
@@ -5,7 +5,7 @@
 #define debug _debug
 #define grub_halt(a) do_exit()
 #define printf grub_printf
-void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline);
+void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags);
 struct fbfront_dev *fb_open(void *fb, int width, int height, int depth);
 void fb_close(void);
 void pv_boot (void);
index 5400fe88cdcf880706d7e0bf97374c61bf069278..5b86c502dc62f4ad4542b87d00c488077a8da56f 100644 (file)
@@ -103,7 +103,7 @@ int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to)
     return 0;
 }
 
-void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline)
+void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags)
 {
     struct xc_dom_image *dom;
     int rc;
@@ -129,7 +129,7 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char
     dom->ramdisk_blob = module;
     dom->ramdisk_size = module_size;
 
-    dom->flags = 0;
+    dom->flags = flags;
     dom->console_evtchn = start_info.console.domU.evtchn;
     dom->xenstore_evtchn = start_info.store_evtchn;
 
index 80330ab92303d75824bfbf69549ae82c01086ed9..4f1804170bebf273de803be75ec4999409a6b64c 100644 (file)
@@ -173,6 +173,8 @@ load_file(char *name, void **ptr, long *size)
 void *kernel_image, *module_image;
 long  kernel_size, module_size;
 char *kernel_arg, *module_arg;
+void *multiboot_next_module;
+struct xen_multiboot_mod_list *multiboot_next_module_header;
 
 kernel_t
 load_image (char *kernel, char *arg, kernel_t suggested_type,
@@ -196,6 +198,8 @@ load_initrd (char *initrd)
     if (module_image)
         free(module_image);
     module_image = NULL;
+    multiboot_next_module = NULL;
+    multiboot_next_module_header = NULL;
     load_file (initrd, &module_image, &module_size);
     return ! errnum;
 }
@@ -203,20 +207,76 @@ load_initrd (char *initrd)
 int
 load_module (char *module, char *arg)
 {
-    if (module_image)
+    void *new_module, *new_module_image;
+    long new_module_size, rounded_new_module_size;
+
+    if (load_file (module, &new_module, &new_module_size))
+        return 0;
+    if (strlen(arg) >= PAGE_SIZE) {
+        /* Too big module command line */
+        errnum = ERR_WONT_FIT;
+        return 0;
+    }
+    rounded_new_module_size = (new_module_size + PAGE_SIZE - 1) & PAGE_MASK;
+
+    if (module_image && !multiboot_next_module_header) {
+        /* Initrd already loaded, drop it */
         free(module_image);
-    module_image = NULL;
-    load_file (module, &module_image, &module_size);
-    if (module_arg)
-        free(module_arg);
-    module_arg = strdup(arg);
-    return ! errnum;
+        if (module_arg)
+            free(module_arg);
+        module_image = NULL;
+    }
+    if (!module_image)
+        /* Reserve one page for the header */
+        multiboot_next_module = (void*) PAGE_SIZE;
+
+    /* Allocate more room for the new module plus its arg */
+    new_module_image = realloc(module_image,
+            (multiboot_next_module - module_image) + rounded_new_module_size + PAGE_SIZE);
+
+    /* Update pointers */
+    multiboot_next_module += new_module_image - module_image;
+    multiboot_next_module_header = (void*) multiboot_next_module_header + (new_module_image - module_image);
+    module_image = new_module_image;
+
+    if ((void*) (multiboot_next_module_header+1) - module_image > PAGE_SIZE) {
+        /* Too many modules */
+        ERR_WONT_FIT;
+        return 0;
+    }
+
+    /* Copy module */
+    memcpy(multiboot_next_module, new_module, new_module_size);
+    multiboot_next_module_header->mod_start = multiboot_next_module - module_image;
+    multiboot_next_module_header->mod_end = multiboot_next_module_header->mod_start + new_module_size - 1;
+    multiboot_next_module += rounded_new_module_size;
+
+    /* Copy cmdline */
+    strcpy(multiboot_next_module, arg);
+    multiboot_next_module_header->cmdline = multiboot_next_module - module_image;
+    multiboot_next_module += PAGE_SIZE;
+
+    /* Pad */
+    multiboot_next_module_header->pad = 0;
+
+    multiboot_next_module_header++;
+
+    return 1;
 }
 
 void
 pv_boot (void)
 {
-    kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg);
+    unsigned long flags = 0;
+    if (multiboot_next_module_header) {
+        /* Termination entry */
+        multiboot_next_module_header->mod_start = 0;
+        /* Total size */
+        module_size = multiboot_next_module - module_image;
+        /* It's a multiboot module */
+        flags |= SIF_MULTIBOOT_MOD;
+    }
+    kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg, flags);
 }
 
 /*