WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

RE: [Xen-devel] RFC/Patch: Support for other bootloaders

Here's a revised patch.

I've eliminated support for trying to combine two modules into one
loadable image.  As per previous  discussions, I think in these
circumstances if a ramdisk is required it is adequate for it to be
built-in to the dom0 image (e.g. embedded initramfs).

Also included the agreed-upon cmdline hack, and SMP booting has been
verified and fixed.

(Not "signed-off" because I don't think it is ready just yet.)

-- 
Michal Ostrowski <mostrows@xxxxxxxxxxxxxx>


# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/24 09:19:31-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx 
#   Support for non-grub boot-loaders.
# 
# BitKeeper/etc/logging_ok
#   2005/03/24 09:19:31-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +1 -0
#   Logging to logging@xxxxxxxxxxxxxxx accepted
# 
# xen/arch/x86/mkzen
#   2005/03/24 09:19:28-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +76 -0
# 
# xen/include/xen/multiboot.h
#   2005/03/24 09:19:28-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +4 -0
#   Define reasonable max number of modules.
# 
# xen/arch/x86/mkzen
#   2005/03/24 09:19:28-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +0 -0
#   BitKeeper file /home/mostrows/xen/xen.base/xen/arch/x86/mkzen
# 
# xen/include/xen/lib.h
#   2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +2 -1
#   Return pointer to unparse portion of command line.
#   Stop parsing command line at "--".
# 
# xen/common/kernel.c
#   2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +9 -2
#   Return pointer to unparse portion of command line.
#   Stop parsing command line at "--".
# 
# xen/arch/x86/setup.c
#   2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +166 -52
#   Handle Linux-style boot-params structure if multi-boot headers not
present.
# 
# xen/arch/x86/boot/x86_32.S
#   2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +13 -7
#   Detect Linux-style boot-params in %ebx if no multi-boot magic number
present.
# 
# xen/arch/x86/Makefile
#   2005/03/24 09:19:27-05:00 mostrows@xxxxxxxxxxxxxxxxxxxxx +42 -0
#   Add rules to build a zenImg (which incorporates Linux bzImage
binaries). 
#    Depends on LINUX_BUILD being defined to point to a linux build
tree.
# 
diff -Nru a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     2005-03-24 09:20:15 -05:00
+++ b/xen/arch/x86/Makefile     2005-03-24 09:20:15 -05:00
@@ -15,7 +15,11 @@
 OBJS := $(patsubst cdb%.o,,$(OBJS))
 endif
 
+ifdef LINUX_BUILD
+default: $(TARGET) zenImg
+else
 default: $(TARGET)
+endif
 
 $(TARGET): $(TARGET)-syms boot/mkelf32
        ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000
@@ -32,6 +36,44 @@
 
 boot/mkelf32: boot/mkelf32.c
        $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
+
+
+ifdef LINUX_BUILD
+
+#
+# Check Makefile in Linux build dir.  If it contains KERNELSRC, then
use
+# that as source dir, otherwise build==source dir
+LINUX_SRC:= $(shell if grep -q KERNELSRC $(LINUX_BUILD)/Makefile ; then
\
+                       sed -e '/^KERNELSRC/!d' $(LINUX_BUILD)/Makefile | \
+                       bash -c '( read A B C ; echo -n $$C)' ; \
+                   else \
+                       echo -n $(LINUX_BUILD); \
+                   fi )
+
+$(TARGET).bin: $(TARGET)
+       $(OBJCOPY) -O binary -R .note -R .comment -S  $^ $@
+
+$(TARGET).bin.gz: $(TARGET).bin
+       gzip -f -9 < $< > $@
+
+piggy.o: $(TARGET).bin.gz
+       $(LD) -m elf_i386  -r --format binary --oformat elf32-i386 \
+       -T $(LINUX_SRC)/arch/i386/boot/compressed/vmlinux.scr $< -o $@
+
+zen:   $(LINUX_BUILD)/arch/i386/boot/compressed/head.o \
+       $(LINUX_BUILD)/arch/i386/boot/compressed/misc.o \
+       piggy.o
+       $(LD) -m elf_i386  -Ttext 0x100000 -e startup_32 $^ -o $@
+
+zenImg: zen
+       $(OBJCOPY) -O binary -R .note -R .comment -S  $^ $@.tmp
+       $(LINUX_BUILD)/arch/i386/boot/tools/build \
+               -b $(LINUX_BUILD)/arch/i386/boot/bootsect \
+               $(LINUX_BUILD)/arch/i386/boot/setup $@.tmp > $@
+
+
+endif
+
 
 clean:
        rm -f *.o *.s *~ core boot/*.o boot/*~ boot/core boot/mkelf32
diff -Nru a/xen/arch/x86/boot/x86_32.S b/xen/arch/x86/boot/x86_32.S
--- a/xen/arch/x86/boot/x86_32.S        2005-03-24 09:20:15 -05:00
+++ b/xen/arch/x86/boot/x86_32.S        2005-03-24 09:20:15 -05:00
@@ -55,7 +55,7 @@
         mov     %ecx,%gs
         ljmp    $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET
 1:      lss     stack_start-__PAGE_OFFSET,%esp
-
+       
         /* Reset EFLAGS (subsumes CLI and CLD). */
        pushl   $0
        popf
@@ -82,15 +82,21 @@
         and     $0x7f,%cl   # CR4.PGE (global enable)
         mov     %ecx,%cr4
                 
-        cmp     $(SECONDARY_CPU_FLAG),%ebx
-        je      start_paging
-                
         /* Check for Multiboot bootloader */
         cmp     $0x2BADB002,%eax
-        jne     not_multiboot
+        je     1f
 
-        /* Save the Multiboot info structure for later use. */
-       add     $__PAGE_OFFSET,%ebx
+       /* No multi-boot?  Hope that we've got a Linux boot-params */
+       /* stashed in esi. Save in %ebx until stack is ready. */
+       /* But do this only if this isn't a secondary cpu. */
+        cmp     $(SECONDARY_CPU_FLAG),%ebx
+       je      1f
+       movl    %esi, %ebx
+1:
+        cmp     $(SECONDARY_CPU_FLAG),%ebx
+        je      start_paging
+                
+       /* Stack is now ready, so store boot parameter pointer */
         push    %ebx
 
         /* Initialize BSS (no nasty surprises!) */
diff -Nru a/xen/arch/x86/mkzen b/xen/arch/x86/mkzen
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/xen/arch/x86/mkzen        2005-03-24 09:20:15 -05:00
@@ -0,0 +1,76 @@
+#!/bin/bash
+#
+# Copyright (C) 2005 Michal Ostrowski <mostrows@xxxxxxxxxxxxxx>, 
+#                                        IBM Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
+#
+
+
+# Reaches into a Linux build tree and uses objects and scripts from
+# linux to wrap a Xen ELF image in the Linuz bzImage machinery,
+# allowing the resulting "zen" image to be booted using any
+# boot-loader thant can load a Linux bzImage.
+
+#
+# Usage: mkzen <LINUX_BUILD> <XEN IMAGE> <ZEN>
+
+set -e
+LINUX_BUILD=$1
+XEN=$2
+ZEN=$3
+
+: ${CROSS_COMPILE:=}
+: ${OBJCOPY:=${CROSS_COMPILE}objcopy}
+: ${LD:=${CROSS_COMPILE}ld}
+
+function cleanup(){
+    rm -f ${XEN}.bin.$$ ${XEN}.bin.gz.$$ ${XEN}.piggy.o.$$
+    rm -f ${ZEN}.1.$$ ${ZEN}.2.$$
+}
+
+trap cleanup ERR
+
+#
+# Check Makefile in Linux build dir.  If it contains KERNELSRC, then
use
+# that as source dir, otherwise build==source dir
+#
+LINUX_SRC=`sed -e '/^KERNELSRC/!d;s/^.*:=[ ]*//'  <
${LINUX_BUILD}/Makefile`
+if [ -z "${LINUX_SRC}" ]; then
+    LINUX_SRC=${LINUX_BUILD};
+fi
+
+${OBJCOPY} -O binary -R .note -R .comment -S ${XEN} ${XEN}.bin.$$
+
+gzip -f -9 < ${XEN}.bin.$$ > ${XEN}.bin.gz.$$
+
+${LD} -m elf_i386  -r --format binary --oformat elf32-i386 \
+    -T ${LINUX_SRC}/arch/i386/boot/compressed/vmlinux.scr \
+    ${XEN}.bin.gz -o ${XEN}.piggy.o.$$
+
+
+${LD} -m elf_i386  -Ttext 0x100000 -e startup_32 \
+    ${LINUX_BUILD}/arch/i386/boot/compressed/head.o \
+    ${LINUX_BUILD}/arch/i386/boot/compressed/misc.o ${XEN}.piggy.o.$$ \
+    -o ${ZEN}.1.$$
+
+${OBJCOPY} -O binary -R .note -R .comment -S  ${ZEN}.1.$$ ${ZEN}.2.$$
+
+${LINUX_BUILD}/arch/i386/boot/tools/build \
+    -b ${LINUX_BUILD}/arch/i386/boot/bootsect \
+    ${LINUX_BUILD}/arch/i386/boot/setup ${ZEN}.2.$$ > ${ZEN}
+
+
+cleanup
\ No newline at end of file
diff -Nru a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      2005-03-24 09:20:15 -05:00
+++ b/xen/arch/x86/setup.c      2005-03-24 09:20:15 -05:00
@@ -86,6 +86,22 @@
 int phys_proc_id[NR_CPUS];
 int logical_proc_id[NR_CPUS];
 
+
+/* Details about what is found where in the Linux boot parameters area.
*/
+/* Put into a seperate header if it grows much more. */
+#define PARAM_SIZE              2048
+#define COMMAND_LINE_SIZE       256
+#define NEW_CL_POINTER          0x228
+#define E820NR                  0x1e8
+#define E820MAP                 0x2d0
+#define INITRD_START            0x218
+#define INITRD_SIZE             0x21c
+
+static unsigned char boot_params[PARAM_SIZE];
+static module_t boot_modules[MAX_MBI_MODULES];
+
+
+
 /* Standard macro to see if a specific flag is changeable. */
 static inline int flag_is_changeable_p(unsigned long flag)
 {
@@ -453,36 +469,19 @@
 #endif
 }
 
-void __init __start_xen(multiboot_info_t *mbi)
+static int __init boot_param_e820_setup(unsigned char *boot_params, 
+                                        struct e820entry *e820raw)
 {
-    char *cmdline;
-    module_t *mod = (module_t *)__va(mbi->mods_addr);
-    void *heap_start;
-    unsigned long firsthole_start, nr_pages;
-    unsigned long initial_images_start, initial_images_end;
-    struct e820entry e820_raw[E820MAX];
-    int i, e820_raw_nr = 0, bytes = 0;
-
-    /* Parse the command-line options. */
-    if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
-        cmdline_parse(__va(mbi->cmdline));
-
-    /* Must do this early -- e.g., spinlocks rely on get_current(). */
-    set_current(&idle0_exec_domain);
-
-    /* We initialise the serial devices very early so we can get
debugging. */
-    serial_init_stage1();
-
-    init_console();
-
-    /* Check that we have at least one Multiboot module. */
-    if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
-    {
-        printk("FATAL ERROR: Require at least one Multiboot
module.\n");
-        for ( ; ; ) ;
-    }
+    int e820_raw_nr = *(int*)&boot_params[E820NR];
+    memcpy(e820raw, boot_params + E820MAP, e820_raw_nr *
sizeof(*e820raw));
+    return e820_raw_nr;
+}
 
-    xenheap_phys_end = opt_xenheap_megabytes << 20;
+static int __init mbi_e820_setup(multiboot_info_t *mbi, 
+                                 struct e820entry *e820_raw)
+{
+    int bytes = 0;
+    int e820_raw_nr = 0;
 
     if ( mbi->flags & MBI_MEMMAP )
     {
@@ -509,14 +508,134 @@
         e820_raw[1].type = E820_RAM;
         e820_raw_nr = 2;
     }
+    return e820_raw_nr;
+}
+
+int __init mbi_boot_modules(multiboot_info_t *mbi)
+{
+    /* Check that we have at least one Multiboot module. */
+    if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
+    {
+        printk("FATAL ERROR: Require at least one Multiboot
module.\n");
+        for ( ; ; ) ;
+    }
+
+    memcpy(&boot_modules, __va(mbi->mods_addr), 
+           sizeof(module_t) * mbi->mods_count);
+    return mbi->mods_count;
+}
+
+int __init boot_param_modules(unsigned char *params)
+{
+    u32 rd = *(u32*)&boot_params[INITRD_START];
+    int size = *(int*)&boot_params[INITRD_SIZE];
+
+    boot_modules[0].mod_start = rd;
+    boot_modules[0].mod_end = rd + size;
+    boot_modules[0].string = 0;
+    boot_modules[0].reserved = 0;
+
+    return 1;
+}
+
+void __init __start_xen(void *params)
+{
+    void *heap_start;
+    unsigned long firsthole_start, nr_pages;
+    unsigned long initial_images_start, initial_images_end;
+    struct e820entry e820_raw[E820MAX];
+    int i, e820_raw_nr = 0;
+    int num_mods = 0;
+    multiboot_info_t *mbi = NULL;
+    char *leftover;
+    unsigned char cmdline[COMMAND_LINE_SIZE + 1];
+    unsigned char dom0_cmdline[COMMAND_LINE_SIZE + 1];
+    
+    /* Forces correct empty-string and null-termination behavior */
+    memset(cmdline, 0, sizeof(cmdline));
+    memset(dom0_cmdline, 0, sizeof(dom0_cmdline));
+    
+    if (MULTIBOOT_BOOTLOADER_MAGIC == *(u32*)__va(params) ) 
+    {
+        mbi = (struct multiboot_info_t*)__va(mbi);
+        if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) 
+        {
+            memcpy(cmdline, __va(mbi->cmdline), COMMAND_LINE_SIZE);
+        }
+    } 
+    else 
+    {
+        /* Hope it is a Linux boot parameters area. */
+        unsigned char* orig_cmd_line;
+        memcpy(boot_params, __va(((char*)params)), PARAM_SIZE);
+        
+        orig_cmd_line = __va(*(unsigned
char**)&boot_params[NEW_CL_POINTER]);
+
+        memcpy(cmdline, orig_cmd_line, COMMAND_LINE_SIZE);
+    }
+
+    /* Parse the command-line options. */
+    leftover = cmdline_parse(cmdline);
+    
+    /* Must do this early -- e.g., spinlocks rely on get_current(). */
+    set_current(&idle0_exec_domain);
+
+    /* We initialise the serial devices very early so we can get
debugging. */
+    serial_init_stage1();
+
+    init_console();
+    
+    xenheap_phys_end = opt_xenheap_megabytes << 20;
+
+    if ( mbi != NULL ) 
+    {
+        e820_raw_nr = mbi_e820_setup(mbi, e820_raw);
+    }
     else
     {
+        e820_raw_nr = boot_param_e820_setup(boot_params, e820_raw);
+    }
+
+    if (e820_raw_nr == 0) 
+    {
         printk("FATAL ERROR: Bootloader provided no memory
information.\n");
         for ( ; ; ) ;
     }
 
     max_page = init_e820(e820_raw, e820_raw_nr);
 
+    if (mbi != NULL)
+    {
+        num_mods = mbi_boot_modules(mbi);        
+    }
+    else
+    {
+        num_mods = boot_param_modules(boot_params);
+    }
+
+    /* Save dom0 cmd line to a known place. */
+    if ( boot_modules[0].string )
+    {
+#if defined(__i386__)
+        char *cmdline = (char *)boot_modules[0].string;
+#elif defined(__x86_64__)
+        char *cmdline = (char *)__va(boot_modules[0].string);
+#endif        
+        /* Skip past the image name. */
+        int  i = 0;
+        while ( cmdline[i] && cmdline[i] == ' ' ) ++i;
+        while ( cmdline[i] && cmdline[i] != ' ') ++i;
+        while ( cmdline[i] && cmdline[i] == ' ' ) ++i;
+  
+        memcpy(dom0_cmdline, cmdline, COMMAND_LINE_SIZE - i);
+    } 
+    else if ( leftover )
+    {
+        /* NULL termination is guaranteed on the cmdline buffer, */
+        /* and leftover is a pointer into that. */
+        strcpy(dom0_cmdline, leftover);
+    }
+
     /* Find the first high-memory RAM hole. */
     for ( i = 0; i < e820.nr_map; i++ )
         if ( (e820.map[i].type == E820_RAM) &&
@@ -527,7 +646,7 @@
     /* Relocate the Multiboot modules. */
     initial_images_start = xenheap_phys_end;
     initial_images_end   = initial_images_start + 
-        (mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
+        (boot_modules[num_mods - 1].mod_end -
boot_modules[0].mod_start);
     if ( initial_images_end > firsthole_start )
     {
         printk("Not enough memory to stash the DOM0 kernel image.\n");
@@ -535,14 +654,14 @@
     }
 #if defined(__i386__)
     memmove((void *)initial_images_start,  /* use low mapping */
-            (void *)mod[0].mod_start,      /* use low mapping */
-            mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
+            (void *)boot_modules[0].mod_start,      /* use low mapping
*/
+            boot_modules[num_mods - 1].mod_end -
boot_modules[0].mod_start);
 #elif defined(__x86_64__)
     memmove(__va(initial_images_start),
-            __va(mod[0].mod_start),
-            mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
+            __va(boot_modules[0].mod_start),
+            boot_modules[num_mods-1].mod_end -
boot_modules[0].mod_start);
 #endif
-
+    
     /* Initialise boot-time allocator with all RAM situated after
modules. */
     heap_start = memguard_init(&_end);
     heap_start = __va(init_boot_allocator(__pa(heap_start)));
@@ -586,28 +705,23 @@
 
     set_bit(DF_PRIVILEGED, &dom0->d_flags);
 
-    /* Grab the DOM0 command line. Skip past the image name. */
-    cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
-    if ( cmdline != NULL )
-    {
-        while ( *cmdline == ' ' ) cmdline++;
-        if ( (cmdline = strchr(cmdline, ' ')) != NULL )
-            while ( *cmdline == ' ' ) cmdline++;
-    }
-
     /*
      * We're going to setup domain0 using the module(s) that we stashed
safely
      * above our heap. The second module, if present, is an initrd
ramdisk.
      */
-    if ( construct_dom0(dom0,
-                        initial_images_start, 
-                        mod[0].mod_end-mod[0].mod_start,
-                        (mbi->mods_count == 1) ? 0 :
-                        initial_images_start + 
-                        (mod[1].mod_start-mod[0].mod_start),
-                        (mbi->mods_count == 1) ? 0 :
-                        mod[mbi->mods_count-1].mod_end -
mod[1].mod_start,
-                        cmdline) != 0)
+    u32 img_size = boot_modules[0].mod_end - boot_modules[0].mod_start;
+    u32 rd_start = 0;
+    u32 rd_size = 0;
+    if ( num_mods > 1 ) 
+    {
+        rd_start = initial_images_start
+                   + boot_modules[1].mod_start -
boot_modules[0].mod_start;
+
+        rd_size = boot_modules[num_mods-1].mod_end -
boot_modules[1].mod_start;
+    }
+
+    if ( construct_dom0(dom0, initial_images_start, img_size,
+                        rd_start, rd_size, dom0_cmdline) != 0)
         panic("Could not set up DOM0 guest OS\n");
 
     /* Scrub RAM that is still free and so may go to an unprivileged
domain. */
diff -Nru a/xen/common/kernel.c b/xen/common/kernel.c
--- a/xen/common/kernel.c       2005-03-24 09:20:15 -05:00
+++ b/xen/common/kernel.c       2005-03-24 09:20:15 -05:00
@@ -14,13 +14,14 @@
 #include <xen/compile.h>
 #include <xen/sched.h>
 
-void cmdline_parse(char *cmdline)
+/* Returns pointer to unparsed portion of command line. */
+char* cmdline_parse(char *cmdline)
 {
     char *opt_end, *opt;
     struct kernel_param *param;
     
     if ( cmdline == NULL )
-        return;
+        return NULL;
 
     while ( *cmdline == ' ' )
         cmdline++;
@@ -31,6 +32,11 @@
             cmdline++;
         if ( *cmdline == '\0' )
             break;
+        
+        /* Pass all options after -- to dom0 */
+        if ( *cmdline == '-' && ( cmdline[1] == '-' || cmdline[1] ==
'\0' ) )
+            return cmdline + 2;
+            
         opt_end = strchr(cmdline, ' ');
         if ( opt_end != NULL )
             *opt_end++ = '\0';
@@ -62,6 +68,7 @@
         }
         cmdline = opt_end;
     }
+    return NULL;
 }
 
 /*
diff -Nru a/xen/include/xen/lib.h b/xen/include/xen/lib.h
--- a/xen/include/xen/lib.h     2005-03-24 09:20:15 -05:00
+++ b/xen/include/xen/lib.h     2005-03-24 09:20:15 -05:00
@@ -29,7 +29,8 @@
 
 struct domain;
 
-void cmdline_parse(char *cmdline);
+/* Returns pointer to unparsed portion of command line. */
+char* cmdline_parse(char *cmdline);
 
 #ifndef NDEBUG
 extern int debugtrace_send_to_console;
diff -Nru a/xen/include/xen/multiboot.h b/xen/include/xen/multiboot.h
--- a/xen/include/xen/multiboot.h       2005-03-24 09:20:15 -05:00
+++ b/xen/include/xen/multiboot.h       2005-03-24 09:20:15 -05:00
@@ -28,6 +28,10 @@
 #define MBI_MEMMAP     (1<<6)
 #define MBI_LOADERNAME (1<<9)
 
+/* Make up some reasonable maximum that we support. */
+#define MAX_MBI_MODULES 4
+
+
 /* The symbol table for a.out.  */
 typedef struct {
     u32 tabsize;

Attachment: signature.asc
Description: This is a digitally signed message part