All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: RFC/Patch: Support for other bootloaders
@ 2005-03-22  9:29 Ian Pratt
  2005-03-22 14:18 ` Michal Ostrowski
  0 siblings, 1 reply; 27+ messages in thread
From: Ian Pratt @ 2005-03-22  9:29 UTC (permalink / raw)
  To: Keir Fraser, Michal Ostrowski; +Cc: xen-devel, Tim Deegan, ian.pratt

 

> The assembly code only needed writing once. If we need a wrapper 
> program at all, I'd rather push skanky argument parsing into 
> that than 
> add another format to Xen. The info you can get from BIOS calls is 
> increasingly redundant -- apart from e820 it's all passed in MP and 
> ACPI tables these days.

We need to get one of these approaches checked into the main tree, lest
someon writes a third.

The wrapper program is pretty unavoidable as the 'legacy' loaders only
support two modules and we potentially need three. Having both the xen
and kernel command line's configurable via a '--' hack seems sane. 

Michael, Tim: Please can you try and agree on a way forward.

Thanks,
Ian


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_ide95&alloc_id\x14396&op=click

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: RFC/Patch: Support for other bootloaders
@ 2005-03-23 17:30 Ian Pratt
  2005-03-24 14:27 ` Michal Ostrowski
  0 siblings, 1 reply; 27+ messages in thread
From: Ian Pratt @ 2005-03-23 17:30 UTC (permalink / raw)
  To: Michal Ostrowski, Tim Deegan; +Cc: Keir Fraser, xen-devel, ian.pratt


> > It should be.  xen-vmlinux is an ELF, so if we can be 
> *sure* that the
> > largest file offset in an ELF header is the same as the size of the
> > file, then it would be possible to just do
> > 
> >  $ cat vmlinux-xen0 initrd-xen0 >pseudo-initrd
> > 
> >  boot: xen pseudo-initrd.
> > 
> > and then have Xen root around in the ELF headers to see 
> where the break
> > is.
> > 
> 
> Sure, you could do that.  You could also define, in Linux, two symbols
> "initrd_start", "initrd_end".
> 
> Then, use objcopy to insert a ramdisk in between the two.  It's not
> "cat", but you can just create a wrapper shell script around the
> objcopy.
> 
> Linux then checks to see if the two symbols point to the same spot; if
> they don't it's got a ramdisk embedded in it.

You mentioned that ppc Linux already has a build target for making an
initrd and wrapping it with a kernel. Do other architectures have this?
How does it work? What are the prospects of getting such funcitonality
added to native i386? Can we ease make the procedure for producing a
wrapped file easy when your building on a different machine from the
target (i.e. where mkinitrd needs different args)?
 
> > Suporting gzipped vmlinux should be possible too; Xen needs 
> to unzip the
> > kernel and then knows that the next byte after the gzipped 
> input will be
> > ramdisk.  (As long as the bootloader doesn't helfully unzip the
> > 'ramdisk' for us.)

As I recall, we currently rely on having GRUB uncompressing the kernel
and initrd. It's a bit grim to do this in Xen, but doable.

> Sure,  but I thought the direction we're going in is to use 
> your wrapper
> around the Xen binary.  If that's the case then I don't see 
> much further use for my code.  

I don't think we have all the inputs to have a firm direction yet. 


Ian


-------------------------------------------------------
This SF.net email is sponsored by Microsoft Mobile & Embedded DevCon 2005
Attend MEDC 2005 May 9-12 in Vegas. Learn more about the latest Windows
Embedded(r) & Windows Mobile(tm) platforms, applications & content.  Register
by 3/29 & save $300 http://ads.osdn.com/?ad_idh83&alloc_id\x15149&op=click

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: RFC/Patch: Support for other bootloaders
@ 2005-03-23 15:52 Ian Pratt
  2005-03-23 16:10 ` Michal Ostrowski
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Ian Pratt @ 2005-03-23 15:52 UTC (permalink / raw)
  To: Michal Ostrowski, Tim Deegan; +Cc: Keir Fraser, xen-devel, ian.pratt

 > It just seems to me that extreme measures are being taken so that one
> can say that Xen changes are not required.  If this is going to be a
> blessed utility for booting Xen it is in effect a part of Xen, whether
> or not it is in the Xen bk repository, whether or not it is in the Xen
> code proper.  My opinion is that it's better to support it in a
> first-class way that to try to sweep it under the rug and pretend it
> doesn't exist.  
> 
> Regardless, mbootpack works just as well so go with it.

My current feeling is that since a wrapper program has to be required to
package the three items into two, we might as well put the complexity in
the wrapper rather than in Xen.   

If the wrapping wasn't required, your approach would clearly be better
[*]. As it stands, I don't think there's much in it, and mbootpack does
have the advantage that a bunch of people have used it successfully. 

Let's get mbootpack documented and checked into the main repository.

Ian

[*] would it possible to do something whereby the vmlinuz and initrd
image were simply cat'ed together? This might swing the balance the
other way from a userbility POV, not sure.



-------------------------------------------------------
This SF.net email is sponsored by: 2005 Windows Mobile Application Contest
Submit applications for Windows Mobile(tm)-based Pocket PCs or Smartphones
for the chance to win $25,000 and application distribution. Enter today at
http://ads.osdn.com/?ad_idh82&alloc_id\x15148&op=click

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: RFC/Patch: Support for other bootloaders
@ 2005-03-21 21:57 Ian Pratt
  2005-03-21 23:01 ` Tim Deegan
  0 siblings, 1 reply; 27+ messages in thread
From: Ian Pratt @ 2005-03-21 21:57 UTC (permalink / raw)
  To: Michal Ostrowski, Tim Deegan; +Cc: xen-devel, ian.pratt

 
> > Did you try using mbootpack for this?  (I haven't tested 
> its output with
> > PXELinux, so I don't know if it would work.)
> 
> No.  This is the first I've heard of it.
> 
> Given the two implementations, let's compare and discuss...
> 
> My objective was to try to use the Linux bits as-is and to have Xen
> recognize that it is not loaded via GRUB (are there any other
> non-GRUB-related multi-boot implementations?).  

kexec supports multiboot (admittedly thanks to a patch from us). 

> As you can see, the
> changes required for Xen to recognize the parameters as passed out of
> Linux's setup.S are not very complicated.  Figuring out where 
> everything
> is is the tough part.
>
> I'm not attached at all to necessarily reach into a Linux 
> build tree to
> extract a built setup and bootsect.  I just think this is the easiest
> way to do it.   x86 BIOS code is just icky and so I'd like to 
> be able to
> avoid having to maintain or even change it.   I think it's easier to
> have Xen get data out of boot_params.

As I recall, mbootpack uses Linux's x86 BIOS code too, so this shouldn't
be an issue. 
 
> So, what I think it boils down to is whether Xen should accept
> parameters passed into it in Linux-style boot_params array, or only
> accept parameters in GRUB format.

I can't see any obvious advantage over the mbootpack approach, and that
has the advantage of being simpler and doesn't require making Xen
understand another boot parameter format.

Is there a downside I haven't spotted?

Ian


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_ide95&alloc_id\x14396&op=click

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RFC/Patch: Support for other bootloaders
@ 2005-03-21 15:46 Michal Ostrowski
  2005-03-21 16:26 ` Tim Deegan
  2005-03-23 20:40 ` Christian Limpach
  0 siblings, 2 replies; 27+ messages in thread
From: Michal Ostrowski @ 2005-03-21 15:46 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1300 bytes --]


I need to net-boot xen on an HS20 blade.  HS20's have a Broadcom NIC,
which is not supported by grub.  The attached patch allows me to build a
Xen image which I can boot using PXELinux  (and the entire SysLinux
family of boot-loaders).

PXELinux should work with any PXE-enabled NIC and thus does not face the
same driver-support issues as grub.

This functionality is enabled by using the Linux code that is wrapped
around a vmlinux to form a zImage.  I've come up with two ways of doing
this; as part of the xen build, or a seperate shell-script ("mkzen").

Both methods reach into a specified Linux-kernel build tree to grab the
bits for the wrapper.  The result, from the boot-loader's point of view
looks identical to a zImage.

However, running in this environment, Xen must now accept arguments in
the format used between a zImage and a vmlinux and distinguish between
this format and the multi-boot format.

Also, since grub is not being used, loading of multiple modules is not
supported.  Thus I've created a tool to package multiple images, with
parameter lists into a "meta-ramdisk".  My patch also includes code for
Xen to extract multiple images from such a meta-ramdisk.

Comments/suggestions appreciated.

-- 
Michal Ostrowski <mostrows@watson.ibm.com>

[-- Attachment #1.2: bootloader.patch --]
[-- Type: text/x-patch, Size: 26857 bytes --]

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/20 16:10:07-05:00 mostrows@heater.watson.ibm.com 
#   Support being booted by arbitrary boot-loaders with bzImage code from Linux.
#   Wrap xen with Linux's bzImage code, either through support in Makefiles or via 
#   the mkzen script.  Both methods require that one specify the location
#   of a linux i386 build tree, from which we extract the necessary bits.
#   
#   Booting with the bzImage code requires that xen recognize parameters in the format 
#   that vmlinux expects. Have __setup_xen be able to recognize both kinds of parameter
#   formats.
#   
#   Using non-grub boot-loaders means that we'll only see one module loaded in addition
#   to the "kernel" image.
#   
#   Add a "mkmetard" tool to create "meta-ramdisks" which can include multiple modules with
#   parameters, all packaged into one ramdisk image.
#   
#   Support decomposition of meta-ramdisks in xen.
# 
# xen/arch/x86/mkzen
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +76 -0
# 
# xen/tools/Makefile
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +3 -1
#   Built the mkmetard tool.
# 
# xen/include/xen/multiboot.h
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +4 -0
#   Reasonable max number of MBI modules.
# 
# xen/arch/x86/setup.c
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +190 -44
#   Support being booted by arbitrary boot-loaders with bzImage code from Linux.
#   Thus, parameters may be passed via pointer in %esi.  Add appropriate checks to
#   detect parameters of this form vs. multi-boot.
#   
#   Add code to extract parameter and system data (e820 memory maps) from either multi-boot
#   or Linux parameter formats.
#   
#   If using Linux parameter format, it is possible that the single ramdisk is a "meta-ramdisk",
#   with a multi-boot-like record that describes multiple module images and parameter
#   strings.
# 
# xen/arch/x86/mkzen
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +0 -0
#   BitKeeper file /home/mostrows/xen/xeno-unstable.bk/xen/arch/x86/mkzen
# 
# xen/arch/x86/boot/x86_32.S
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +9 -7
#   Support being booted by arbitrary boot-loaders with bzImage code from Linux.
#   Thus, parameters may be passed via pointer in %esi.  Add appropriate checks to
#   detect parameters of this form vs. multi-boot.
# 
# xen/arch/x86/Makefile
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +42 -0
#   Add target to build zenImg -- xen wrapped with Linux's bzImage machinery.
# 
# xen/Makefile
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +3 -1
#   Build mkmetard.
# 
# xen/tools/mkmetard/mkmetard.c
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +225 -0
# 
# xen/tools/mkmetard/Makefile
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +10 -0
# 
# xen/tools/mkmetard/mkmetard.c
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +0 -0
#   BitKeeper file /home/mostrows/xen/xeno-unstable.bk/xen/tools/mkmetard/mkmetard.c
# 
# xen/tools/mkmetard/Makefile
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +0 -0
#   BitKeeper file /home/mostrows/xen/xeno-unstable.bk/xen/tools/mkmetard/Makefile
# 
diff -Nru a/xen/Makefile b/xen/Makefile
--- a/xen/Makefile	2005-03-20 16:15:16 -05:00
+++ b/xen/Makefile	2005-03-20 16:15:16 -05:00
@@ -27,7 +27,7 @@
 dist: install
 
 build: $(TARGET).gz
-	
+
 install: $(TARGET).gz
 	[ -d $(DESTDIR)/boot ] || $(INSTALL_DIR) $(DESTDIR)/boot
 	$(INSTALL_DATA) $(TARGET).gz $(DESTDIR)/boot
@@ -52,9 +52,11 @@
 	[ -e include/asm ] || ln -sf asm-$(TARGET_ARCH) include/asm
 	$(MAKE) -C arch/$(TARGET_ARCH) asm-offsets.s
 	$(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h
+	$(MAKE) -C tools/mkmetard
 	$(MAKE) -C common
 	$(MAKE) -C drivers
 	$(MAKE) -C arch/$(TARGET_ARCH)
+
 
 # drivers/char/console.o may contain static banner/compile info. Blow it away.
 delete-unfresh-files:
diff -Nru a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile	2005-03-20 16:15:16 -05:00
+++ b/xen/arch/x86/Makefile	2005-03-20 16:15:16 -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-20 16:15:16 -05:00
+++ b/xen/arch/x86/boot/x86_32.S	2005-03-20 16:15:16 -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,17 @@
         and     $0x7f,%cl   # CR4.PGE (global enable)
         mov     %ecx,%cr4
                 
+        /* Check for Multiboot bootloader */
+        cmp     $0x2BADB002,%eax
+        je     1f
+	/* No multi-boot?  Hope that we've got a Linux boot-params */
+	/* stashed in esi. Save in %ebx until stack is ready. */
+	movl	%esi, %ebx
+1:
         cmp     $(SECONDARY_CPU_FLAG),%ebx
         je      start_paging
                 
-        /* Check for Multiboot bootloader */
-        cmp     $0x2BADB002,%eax
-        jne     not_multiboot
-
-        /* Save the Multiboot info structure for later use. */
-	add     $__PAGE_OFFSET,%ebx
+	/* 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-20 16:15:16 -05:00
@@ -0,0 +1,76 @@
+#!/bin/bash
+#
+# Copyright (C) 2005 Michal Ostrowski <mostrows@watson.ibm.com>, 
+#					  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-20 16:15:16 -05:00
+++ b/xen/arch/x86/setup.c	2005-03-20 16:15:16 -05:00
@@ -86,6 +86,24 @@
 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 unsigned char cmd_line_buf[COMMAND_LINE_SIZE];
+static unsigned char dom0_cmd_line_buf[COMMAND_LINE_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 +471,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 +510,154 @@
         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;
+
+    u32 *magic = (u32*)boot_modules[0].mod_start;
+    u32 num_modules = magic[1];
+    u32 base = boot_modules[0].mod_start;
+    
+    printf("Multi-module: %x %d %x\n", *magic, num_modules, base);
+    printf("Module: %x %x %x\n",
+           boot_modules[0].mod_start, boot_modules[0].mod_end,
+           boot_modules[0].string);
+    
+
+    if ( *magic != MULTIBOOT_BOOTLOADER_MAGIC )
+    {
+        return 1;
+    }
+    
+    memcpy(&boot_modules[0], (void*)(base + sizeof(u32) * 2), 
+                                     num_modules * sizeof(module_t));
+    printf("Module: %x %x %x\n",
+           boot_modules[0].mod_start, boot_modules[0].mod_end,
+           boot_modules[0].string);
+    
+    int i = 0;
+    for ( ; i < num_modules; ++i) 
+    {
+        boot_modules[i].mod_start += base;
+        boot_modules[i].mod_end += base;
+        boot_modules[i].string += base;
+    }
+    printf("Module: %x %x %x\n",
+           boot_modules[0].mod_start, boot_modules[0].mod_end,
+           boot_modules[0].string);
+    return num_modules;
+}
+
+void __init __start_xen(void *params)
+{
+    char *cmdline = NULL;
+    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;
+    
+    if (MULTIBOOT_BOOTLOADER_MAGIC == *(u32*)params ) 
+    {
+        mbi = (struct multiboot_info_t*)__va(mbi);
+        if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) 
+        {
+            cmdline = __va(mbi->cmdline);
+        }
+    } 
+    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(cmd_line_buf, orig_cmd_line, COMMAND_LINE_SIZE);
+        cmdline = cmd_line_buf;
+    }
+
+    /* Parse the command-line options. */
+    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__)
+        memcpy(dom0_cmd_line_buf, (void*)boot_modules[0].string, 
+               COMMAND_LINE_SIZE);
+#elif defined(__x86_64__)
+        memcpy(dom0_cmd_line_buf, __va(boot_modules[0].string), 
+               COMMAND_LINE_SIZE);
+#endif
+    } 
+    else
+    {
+        dom0_cmd_line_buf[0] = 0;
+    }
+    
     /* Find the first high-memory RAM hole. */
     for ( i = 0; i < e820.nr_map; i++ )
         if ( (e820.map[i].type == E820_RAM) &&
@@ -527,7 +668,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 +676,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)));
@@ -587,7 +728,8 @@
     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);
+    cmdline = (dom0_cmd_line_buf[0] ? dom0_cmd_line_buf : NULL);
+
     if ( cmdline != NULL )
     {
         while ( *cmdline == ' ' ) cmdline++;
@@ -599,15 +741,19 @@
      * 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, 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/include/xen/multiboot.h b/xen/include/xen/multiboot.h
--- a/xen/include/xen/multiboot.h	2005-03-20 16:15:16 -05:00
+++ b/xen/include/xen/multiboot.h	2005-03-20 16:15:16 -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;
diff -Nru a/xen/tools/Makefile b/xen/tools/Makefile
--- a/xen/tools/Makefile	2005-03-20 16:15:16 -05:00
+++ b/xen/tools/Makefile	2005-03-20 16:15:16 -05:00
@@ -1,6 +1,8 @@
 
 default:
 	$(MAKE) -C figlet
+	$(MAKE) -C mkmetard
 
 clean:
-	$(MAKE) -C figlet clean
\ No newline at end of file
+	$(MAKE) -C figlet clean
+	$(MAKE) -C mkmetard clean
\ No newline at end of file
diff -Nru a/xen/tools/mkmetard/Makefile b/xen/tools/mkmetard/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/xen/tools/mkmetard/Makefile	2005-03-20 16:15:16 -05:00
@@ -0,0 +1,10 @@
+
+include ../../../Config.mk
+
+CFLAGS += -DBUILD_ARCH=$(XEN_COMPILE_ARCH) -DTARGET_ARCH=$(XEN_TARGET_ARCH)
+CFLAGS += -I$(BASEDIR)/include
+mkmetard: mkmetard.c
+	$(HOSTCC) $(CFLAGS) -o $@ $<
+
+clean:
+	rm -f *.o mkmetard
diff -Nru a/xen/tools/mkmetard/mkmetard.c b/xen/tools/mkmetard/mkmetard.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/xen/tools/mkmetard/mkmetard.c	2005-03-20 16:15:16 -05:00
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2005 Michal Ostrowski <mostrows@watson.ibm.com>, 
+ *					  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
+ *
+ */
+
+/* Combines several images and cmdlines into one meta-ramdisk image.
+ * For use with non-grub boot-loader that don't do "multi-boot" as
+ * grub does.
+ *
+ * Usage: mkmetard <output_file> <module1_file> <mod1_arg1> ... \
+ *								 --- <module2_file> <mod2_arg1> ...
+ * 
+ * Allows up to 4 module images.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <endian.h>
+#include <byteswap.h>
+
+
+
+/* We need to know whether build platform endianness matches that of target */
+#define LITTLE_ENDIAN_ppc		0
+#define LITTLE_ENDIAN_x86_32	1
+#define LITTLE_ENDIAN_x86_64	1
+#define LITTLE_ENDIAN_ia64		1
+
+#define __CAT(a,b)		a##b
+#define IS_LITTLE_ENDIAN(arch) __CAT(LITTLE_ENDIAN_,arch)
+
+#if IS_LITTLE_ENDIAN(BUILD_ARCH) == IS_LITTLE_ENDIAN(TARGET_ARCH)
+#define ENDIAN_MATCH	1
+#else
+#define ENDIAN_MATCH	0
+#endif
+
+
+#if ENDIAN_MATCH == 0
+#define byteswap(x)								\
+	({											\
+		typeof(x) tmp = x;						\
+		switch(sizeof(tmp))						\
+		{										\
+		case 1:									\
+			break;								\
+		case 2:									\
+			tmp = bswap_16(tmp);				\
+			break;								\
+		case 4:									\
+			tmp = bswap_32(tmp);				\
+			break;								\
+		case 8:									\
+			tmp = bswap_64(tmp);				\
+			break;								\
+		default:								\
+			printf("no valid byteswap for " #x);	\
+			tmp = 0;								\
+			break;									\
+		}											\
+		tmp;										\
+	})
+#else /* ENDIAN_MATCH == 0 */		
+#define byteswap(x) (x)
+#endif /* ENDIAN_MATCH == 0 */		
+
+
+
+/* We cannot use types.h, since we may be cross-compiling and thus
+ * don't want to pick up an asm header that doesn't match the
+ * architecture we're building for */
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+/* See if we are 32 or 64-bit */
+#if 2147483647L == __LONG_MAX__
+typedef signed long long s64;
+typedef unsigned long long u64;
+#define BITS_PER_LONG 32
+#else
+typedef signed long s64;
+typedef unsigned long u64;
+#define BITS_PER_LONG 64
+#endif
+
+#include <xen/multiboot.h>
+
+int curr_offset = 0;
+int rd_fd;
+
+static inline void 
+write_to_file(void* buf, int len)
+{
+	int ret = write(rd_fd, buf, len);
+	if (ret == len) 
+	{
+		curr_offset += ret;
+	}
+	else
+	{
+		perror("Incomplete write to ramdisk file.");
+		exit(-1);
+	}
+}
+
+
+module_t mods[MAX_MBI_MODULES];
+
+int main(int argc, char** argv)
+{
+	char* rdname = argv[1];
+	argv += 2;
+	argc -= 2;
+	
+	int mod = 0;
+	int x = 0;
+	
+	int parts[MAX_MBI_MODULES + 1] = { -1, };
+
+	parts[mod] = 0;
+
+	/* Identify cmdlines for each module */
+	while ( x < argc && mod < MAX_MBI_MODULES)
+	{
+		if ( strcmp(argv[x],"---") == 0 )
+		{
+			++x;
+			if (x < argc && mod < MAX_MBI_MODULES)
+			{
+				++mod;
+				parts[mod] = x;
+			}
+			
+		}
+		else 
+		{
+			++x;
+		}
+	}
+	++mod;
+
+	rd_fd = open(rdname, O_RDWR | O_CREAT | O_TRUNC, 0644);
+	if ( rd_fd < 0 ) perror("Can't open meta-ramdisk image file\n");
+	
+	/* Use the multi-boot magic number, can't see why not to. */
+	u32 magic = byteswap(MULTIBOOT_BOOTLOADER_MAGIC);
+	write_to_file(&magic, sizeof(magic));
+
+	magic = byteswap(mod);
+	write_to_file(&magic, sizeof(magic));
+
+	/* We'll come back and re-write this later, but we just need
+	 * filler for now */
+	write_to_file(&mods, sizeof(module_t) * mod);
+
+	for ( x = 0; x < mod; ++x ) 
+	{
+		int fd = open(argv[parts[x]], O_RDONLY);
+		if ( fd < 0 ) 
+		{
+			perror("Can't open image file");
+			exit(-1);
+		}
+		
+		char string[1024];
+		char buf[1024];
+		int size = 0;
+		int ret;
+		
+		/* Copy cmdline component */
+		string[0] = 0;
+		
+		int y = parts[x];
+		while(y < argc  && strcmp(argv[y], "---")!=0 )
+		{
+			strcpy(string + size, argv[y]);
+			size += strlen(argv[y]);
+			string[size++] = ' ';
+			++y;
+		}
+		string[size++] = 0;
+		
+		mods[x].string = byteswap(curr_offset);
+		write_to_file(string, size);
+		
+		/* Now copy module image */
+		mods[x].mod_start = byteswap(curr_offset);
+		while ( (ret = read(fd, buf, 1024)) > 0)
+		{
+			write_to_file(buf, ret);
+		}
+		mods[x].mod_end = byteswap(curr_offset);
+	}
+
+	/* Re-write the modules structs at the start of the file */
+	lseek(rd_fd, sizeof(magic) * 2, SEEK_SET);
+	write(rd_fd, &mods, sizeof(module_t) * mod);
+	
+	return 0;
+	
+}

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RFC/Patch: Support for other bootloaders
@ 2005-03-21 12:15 Michal Ostrowski
  0 siblings, 0 replies; 27+ messages in thread
From: Michal Ostrowski @ 2005-03-21 12:15 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1300 bytes --]


I need to net-boot xen on an HS20 blade.  HS20's have a Broadcom NIC,
which is not supported by grub.  The attached patch allows me to build a
Xen image which I can boot using PXELinux  (and the entire SysLinux
family of boot-loaders).

PXELinux should work with any PXE-enabled NIC and thus does not face the
same driver-support issues as grub.

This functionality is enabled by using the Linux code that is wrapped
around a vmlinux to form a zImage.  I've come up with two ways of doing
this; as part of the xen build, or a seperate shell-script ("mkzen").

Both methods reach into a specified Linux-kernel build tree to grab the
bits for the wrapper.  The result, from the boot-loader's point of view
looks identical to a zImage.

However, running in this environment, Xen must now accept arguments in
the format used between a zImage and a vmlinux and distinguish between
this format and the multi-boot format.

Also, since grub is not being used, loading of multiple modules is not
supported.  Thus I've created a tool to package multiple images, with
parameter lists into a "meta-ramdisk".  My patch also includes code for
Xen to extract multiple images from such a meta-ramdisk.

Comments/suggestions appreciated.

-- 
Michal Ostrowski <mostrows@watson.ibm.com>

[-- Attachment #1.2: bootloader.patch --]
[-- Type: text/x-patch, Size: 26857 bytes --]

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/03/20 16:10:07-05:00 mostrows@heater.watson.ibm.com 
#   Support being booted by arbitrary boot-loaders with bzImage code from Linux.
#   Wrap xen with Linux's bzImage code, either through support in Makefiles or via 
#   the mkzen script.  Both methods require that one specify the location
#   of a linux i386 build tree, from which we extract the necessary bits.
#   
#   Booting with the bzImage code requires that xen recognize parameters in the format 
#   that vmlinux expects. Have __setup_xen be able to recognize both kinds of parameter
#   formats.
#   
#   Using non-grub boot-loaders means that we'll only see one module loaded in addition
#   to the "kernel" image.
#   
#   Add a "mkmetard" tool to create "meta-ramdisks" which can include multiple modules with
#   parameters, all packaged into one ramdisk image.
#   
#   Support decomposition of meta-ramdisks in xen.
# 
# xen/arch/x86/mkzen
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +76 -0
# 
# xen/tools/Makefile
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +3 -1
#   Built the mkmetard tool.
# 
# xen/include/xen/multiboot.h
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +4 -0
#   Reasonable max number of MBI modules.
# 
# xen/arch/x86/setup.c
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +190 -44
#   Support being booted by arbitrary boot-loaders with bzImage code from Linux.
#   Thus, parameters may be passed via pointer in %esi.  Add appropriate checks to
#   detect parameters of this form vs. multi-boot.
#   
#   Add code to extract parameter and system data (e820 memory maps) from either multi-boot
#   or Linux parameter formats.
#   
#   If using Linux parameter format, it is possible that the single ramdisk is a "meta-ramdisk",
#   with a multi-boot-like record that describes multiple module images and parameter
#   strings.
# 
# xen/arch/x86/mkzen
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +0 -0
#   BitKeeper file /home/mostrows/xen/xeno-unstable.bk/xen/arch/x86/mkzen
# 
# xen/arch/x86/boot/x86_32.S
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +9 -7
#   Support being booted by arbitrary boot-loaders with bzImage code from Linux.
#   Thus, parameters may be passed via pointer in %esi.  Add appropriate checks to
#   detect parameters of this form vs. multi-boot.
# 
# xen/arch/x86/Makefile
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +42 -0
#   Add target to build zenImg -- xen wrapped with Linux's bzImage machinery.
# 
# xen/Makefile
#   2005/03/20 16:10:06-05:00 mostrows@heater.watson.ibm.com +3 -1
#   Build mkmetard.
# 
# xen/tools/mkmetard/mkmetard.c
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +225 -0
# 
# xen/tools/mkmetard/Makefile
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +10 -0
# 
# xen/tools/mkmetard/mkmetard.c
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +0 -0
#   BitKeeper file /home/mostrows/xen/xeno-unstable.bk/xen/tools/mkmetard/mkmetard.c
# 
# xen/tools/mkmetard/Makefile
#   2005/03/20 15:01:15-05:00 mostrows@heater.watson.ibm.com +0 -0
#   BitKeeper file /home/mostrows/xen/xeno-unstable.bk/xen/tools/mkmetard/Makefile
# 
diff -Nru a/xen/Makefile b/xen/Makefile
--- a/xen/Makefile	2005-03-20 16:15:16 -05:00
+++ b/xen/Makefile	2005-03-20 16:15:16 -05:00
@@ -27,7 +27,7 @@
 dist: install
 
 build: $(TARGET).gz
-	
+
 install: $(TARGET).gz
 	[ -d $(DESTDIR)/boot ] || $(INSTALL_DIR) $(DESTDIR)/boot
 	$(INSTALL_DATA) $(TARGET).gz $(DESTDIR)/boot
@@ -52,9 +52,11 @@
 	[ -e include/asm ] || ln -sf asm-$(TARGET_ARCH) include/asm
 	$(MAKE) -C arch/$(TARGET_ARCH) asm-offsets.s
 	$(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h
+	$(MAKE) -C tools/mkmetard
 	$(MAKE) -C common
 	$(MAKE) -C drivers
 	$(MAKE) -C arch/$(TARGET_ARCH)
+
 
 # drivers/char/console.o may contain static banner/compile info. Blow it away.
 delete-unfresh-files:
diff -Nru a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile	2005-03-20 16:15:16 -05:00
+++ b/xen/arch/x86/Makefile	2005-03-20 16:15:16 -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-20 16:15:16 -05:00
+++ b/xen/arch/x86/boot/x86_32.S	2005-03-20 16:15:16 -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,17 @@
         and     $0x7f,%cl   # CR4.PGE (global enable)
         mov     %ecx,%cr4
                 
+        /* Check for Multiboot bootloader */
+        cmp     $0x2BADB002,%eax
+        je     1f
+	/* No multi-boot?  Hope that we've got a Linux boot-params */
+	/* stashed in esi. Save in %ebx until stack is ready. */
+	movl	%esi, %ebx
+1:
         cmp     $(SECONDARY_CPU_FLAG),%ebx
         je      start_paging
                 
-        /* Check for Multiboot bootloader */
-        cmp     $0x2BADB002,%eax
-        jne     not_multiboot
-
-        /* Save the Multiboot info structure for later use. */
-	add     $__PAGE_OFFSET,%ebx
+	/* 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-20 16:15:16 -05:00
@@ -0,0 +1,76 @@
+#!/bin/bash
+#
+# Copyright (C) 2005 Michal Ostrowski <mostrows@watson.ibm.com>, 
+#					  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-20 16:15:16 -05:00
+++ b/xen/arch/x86/setup.c	2005-03-20 16:15:16 -05:00
@@ -86,6 +86,24 @@
 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 unsigned char cmd_line_buf[COMMAND_LINE_SIZE];
+static unsigned char dom0_cmd_line_buf[COMMAND_LINE_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 +471,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 +510,154 @@
         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;
+
+    u32 *magic = (u32*)boot_modules[0].mod_start;
+    u32 num_modules = magic[1];
+    u32 base = boot_modules[0].mod_start;
+    
+    printf("Multi-module: %x %d %x\n", *magic, num_modules, base);
+    printf("Module: %x %x %x\n",
+           boot_modules[0].mod_start, boot_modules[0].mod_end,
+           boot_modules[0].string);
+    
+
+    if ( *magic != MULTIBOOT_BOOTLOADER_MAGIC )
+    {
+        return 1;
+    }
+    
+    memcpy(&boot_modules[0], (void*)(base + sizeof(u32) * 2), 
+                                     num_modules * sizeof(module_t));
+    printf("Module: %x %x %x\n",
+           boot_modules[0].mod_start, boot_modules[0].mod_end,
+           boot_modules[0].string);
+    
+    int i = 0;
+    for ( ; i < num_modules; ++i) 
+    {
+        boot_modules[i].mod_start += base;
+        boot_modules[i].mod_end += base;
+        boot_modules[i].string += base;
+    }
+    printf("Module: %x %x %x\n",
+           boot_modules[0].mod_start, boot_modules[0].mod_end,
+           boot_modules[0].string);
+    return num_modules;
+}
+
+void __init __start_xen(void *params)
+{
+    char *cmdline = NULL;
+    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;
+    
+    if (MULTIBOOT_BOOTLOADER_MAGIC == *(u32*)params ) 
+    {
+        mbi = (struct multiboot_info_t*)__va(mbi);
+        if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) 
+        {
+            cmdline = __va(mbi->cmdline);
+        }
+    } 
+    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(cmd_line_buf, orig_cmd_line, COMMAND_LINE_SIZE);
+        cmdline = cmd_line_buf;
+    }
+
+    /* Parse the command-line options. */
+    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__)
+        memcpy(dom0_cmd_line_buf, (void*)boot_modules[0].string, 
+               COMMAND_LINE_SIZE);
+#elif defined(__x86_64__)
+        memcpy(dom0_cmd_line_buf, __va(boot_modules[0].string), 
+               COMMAND_LINE_SIZE);
+#endif
+    } 
+    else
+    {
+        dom0_cmd_line_buf[0] = 0;
+    }
+    
     /* Find the first high-memory RAM hole. */
     for ( i = 0; i < e820.nr_map; i++ )
         if ( (e820.map[i].type == E820_RAM) &&
@@ -527,7 +668,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 +676,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)));
@@ -587,7 +728,8 @@
     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);
+    cmdline = (dom0_cmd_line_buf[0] ? dom0_cmd_line_buf : NULL);
+
     if ( cmdline != NULL )
     {
         while ( *cmdline == ' ' ) cmdline++;
@@ -599,15 +741,19 @@
      * 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, 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/include/xen/multiboot.h b/xen/include/xen/multiboot.h
--- a/xen/include/xen/multiboot.h	2005-03-20 16:15:16 -05:00
+++ b/xen/include/xen/multiboot.h	2005-03-20 16:15:16 -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;
diff -Nru a/xen/tools/Makefile b/xen/tools/Makefile
--- a/xen/tools/Makefile	2005-03-20 16:15:16 -05:00
+++ b/xen/tools/Makefile	2005-03-20 16:15:16 -05:00
@@ -1,6 +1,8 @@
 
 default:
 	$(MAKE) -C figlet
+	$(MAKE) -C mkmetard
 
 clean:
-	$(MAKE) -C figlet clean
\ No newline at end of file
+	$(MAKE) -C figlet clean
+	$(MAKE) -C mkmetard clean
\ No newline at end of file
diff -Nru a/xen/tools/mkmetard/Makefile b/xen/tools/mkmetard/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/xen/tools/mkmetard/Makefile	2005-03-20 16:15:16 -05:00
@@ -0,0 +1,10 @@
+
+include ../../../Config.mk
+
+CFLAGS += -DBUILD_ARCH=$(XEN_COMPILE_ARCH) -DTARGET_ARCH=$(XEN_TARGET_ARCH)
+CFLAGS += -I$(BASEDIR)/include
+mkmetard: mkmetard.c
+	$(HOSTCC) $(CFLAGS) -o $@ $<
+
+clean:
+	rm -f *.o mkmetard
diff -Nru a/xen/tools/mkmetard/mkmetard.c b/xen/tools/mkmetard/mkmetard.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/xen/tools/mkmetard/mkmetard.c	2005-03-20 16:15:16 -05:00
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2005 Michal Ostrowski <mostrows@watson.ibm.com>, 
+ *					  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
+ *
+ */
+
+/* Combines several images and cmdlines into one meta-ramdisk image.
+ * For use with non-grub boot-loader that don't do "multi-boot" as
+ * grub does.
+ *
+ * Usage: mkmetard <output_file> <module1_file> <mod1_arg1> ... \
+ *								 --- <module2_file> <mod2_arg1> ...
+ * 
+ * Allows up to 4 module images.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <endian.h>
+#include <byteswap.h>
+
+
+
+/* We need to know whether build platform endianness matches that of target */
+#define LITTLE_ENDIAN_ppc		0
+#define LITTLE_ENDIAN_x86_32	1
+#define LITTLE_ENDIAN_x86_64	1
+#define LITTLE_ENDIAN_ia64		1
+
+#define __CAT(a,b)		a##b
+#define IS_LITTLE_ENDIAN(arch) __CAT(LITTLE_ENDIAN_,arch)
+
+#if IS_LITTLE_ENDIAN(BUILD_ARCH) == IS_LITTLE_ENDIAN(TARGET_ARCH)
+#define ENDIAN_MATCH	1
+#else
+#define ENDIAN_MATCH	0
+#endif
+
+
+#if ENDIAN_MATCH == 0
+#define byteswap(x)								\
+	({											\
+		typeof(x) tmp = x;						\
+		switch(sizeof(tmp))						\
+		{										\
+		case 1:									\
+			break;								\
+		case 2:									\
+			tmp = bswap_16(tmp);				\
+			break;								\
+		case 4:									\
+			tmp = bswap_32(tmp);				\
+			break;								\
+		case 8:									\
+			tmp = bswap_64(tmp);				\
+			break;								\
+		default:								\
+			printf("no valid byteswap for " #x);	\
+			tmp = 0;								\
+			break;									\
+		}											\
+		tmp;										\
+	})
+#else /* ENDIAN_MATCH == 0 */		
+#define byteswap(x) (x)
+#endif /* ENDIAN_MATCH == 0 */		
+
+
+
+/* We cannot use types.h, since we may be cross-compiling and thus
+ * don't want to pick up an asm header that doesn't match the
+ * architecture we're building for */
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+/* See if we are 32 or 64-bit */
+#if 2147483647L == __LONG_MAX__
+typedef signed long long s64;
+typedef unsigned long long u64;
+#define BITS_PER_LONG 32
+#else
+typedef signed long s64;
+typedef unsigned long u64;
+#define BITS_PER_LONG 64
+#endif
+
+#include <xen/multiboot.h>
+
+int curr_offset = 0;
+int rd_fd;
+
+static inline void 
+write_to_file(void* buf, int len)
+{
+	int ret = write(rd_fd, buf, len);
+	if (ret == len) 
+	{
+		curr_offset += ret;
+	}
+	else
+	{
+		perror("Incomplete write to ramdisk file.");
+		exit(-1);
+	}
+}
+
+
+module_t mods[MAX_MBI_MODULES];
+
+int main(int argc, char** argv)
+{
+	char* rdname = argv[1];
+	argv += 2;
+	argc -= 2;
+	
+	int mod = 0;
+	int x = 0;
+	
+	int parts[MAX_MBI_MODULES + 1] = { -1, };
+
+	parts[mod] = 0;
+
+	/* Identify cmdlines for each module */
+	while ( x < argc && mod < MAX_MBI_MODULES)
+	{
+		if ( strcmp(argv[x],"---") == 0 )
+		{
+			++x;
+			if (x < argc && mod < MAX_MBI_MODULES)
+			{
+				++mod;
+				parts[mod] = x;
+			}
+			
+		}
+		else 
+		{
+			++x;
+		}
+	}
+	++mod;
+
+	rd_fd = open(rdname, O_RDWR | O_CREAT | O_TRUNC, 0644);
+	if ( rd_fd < 0 ) perror("Can't open meta-ramdisk image file\n");
+	
+	/* Use the multi-boot magic number, can't see why not to. */
+	u32 magic = byteswap(MULTIBOOT_BOOTLOADER_MAGIC);
+	write_to_file(&magic, sizeof(magic));
+
+	magic = byteswap(mod);
+	write_to_file(&magic, sizeof(magic));
+
+	/* We'll come back and re-write this later, but we just need
+	 * filler for now */
+	write_to_file(&mods, sizeof(module_t) * mod);
+
+	for ( x = 0; x < mod; ++x ) 
+	{
+		int fd = open(argv[parts[x]], O_RDONLY);
+		if ( fd < 0 ) 
+		{
+			perror("Can't open image file");
+			exit(-1);
+		}
+		
+		char string[1024];
+		char buf[1024];
+		int size = 0;
+		int ret;
+		
+		/* Copy cmdline component */
+		string[0] = 0;
+		
+		int y = parts[x];
+		while(y < argc  && strcmp(argv[y], "---")!=0 )
+		{
+			strcpy(string + size, argv[y]);
+			size += strlen(argv[y]);
+			string[size++] = ' ';
+			++y;
+		}
+		string[size++] = 0;
+		
+		mods[x].string = byteswap(curr_offset);
+		write_to_file(string, size);
+		
+		/* Now copy module image */
+		mods[x].mod_start = byteswap(curr_offset);
+		while ( (ret = read(fd, buf, 1024)) > 0)
+		{
+			write_to_file(buf, ret);
+		}
+		mods[x].mod_end = byteswap(curr_offset);
+	}
+
+	/* Re-write the modules structs at the start of the file */
+	lseek(rd_fd, sizeof(magic) * 2, SEEK_SET);
+	write(rd_fd, &mods, sizeof(module_t) * mod);
+	
+	return 0;
+	
+}

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2005-03-24 14:27 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-22  9:29 RFC/Patch: Support for other bootloaders Ian Pratt
2005-03-22 14:18 ` Michal Ostrowski
2005-03-22 14:42   ` Tim Deegan
2005-03-22 15:05     ` Michal Ostrowski
2005-03-23 11:20     ` Tim Deegan
2005-03-23 13:00       ` Michal Ostrowski
2005-03-23 16:09       ` Anthony Liguori
  -- strict thread matches above, loose matches on Subject: below --
2005-03-23 17:30 Ian Pratt
2005-03-24 14:27 ` Michal Ostrowski
2005-03-23 15:52 Ian Pratt
2005-03-23 16:10 ` Michal Ostrowski
2005-03-23 16:23 ` Tim Deegan
2005-03-23 16:44   ` Michal Ostrowski
2005-03-23 16:57   ` Anthony Liguori
2005-03-23 16:56 ` Jeremy Katz
2005-03-23 23:39   ` Michal Ostrowski
2005-03-21 21:57 Ian Pratt
2005-03-21 23:01 ` Tim Deegan
2005-03-21 23:35   ` Michal Ostrowski
2005-03-22  9:17     ` Keir Fraser
2005-03-22  0:08   ` Michal Ostrowski
2005-03-21 15:46 Michal Ostrowski
2005-03-21 16:26 ` Tim Deegan
2005-03-21 21:04   ` Michal Ostrowski
2005-03-23 20:40 ` Christian Limpach
2005-03-23 23:15   ` Michal Ostrowski
2005-03-21 12:15 Michal Ostrowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.