Xen on x86 uses GRUB's "multiboot" capabilities to load an arbitrary
number of images, including Xen, dom0 kernel, dom0 initrd, and ACM
policy. On PowerPC, we've had to build Xen, the dom0 kernel and the dom0
initrd all into the same file to get them loaded. Since we currently
boot directly from Open Firmware, early PPC Xen code then fakes up a
multiboot info structure which later PPC Xen code extracts data from.

GRUB2, which supports PowerPC, is defining a new multiboot format
because the original was far too x86-specific. That loader is not yet
committed but is fairly complete, so to test it out I'm adapting PPC Xen
to it.

This is the first step: I've replaced our early multiboot code to fake
up a multiboot2 structure instead. I haven't yet tried to boot this from
GRUB2, but we will likely want to continue supporting directly booting
from firmware so this code needs to work.

Of interest is that I've changed the memory map to simplify some of the
early memory allocation code (which unlike x86 tried to handle unordered
discontiguous allocations). With this patch, our memory map now looks
like this:
        
        exception handlers (0x0 to 0x4000)
        RTAS
        Open Firmware device tree
        boot allocator bitmap (common Xen code)
        Xen heap
                ...
        _start (0x400000; 64MB)
                [Xen text/data]
        _end
        modules
                [dom0, dom0 initrd, etc]
        Xen heap
                ...
                [fixed size]
        domain heap
                ...
                [consumes all remaining memory]
        
Comments and testing are welcome, or I'll probably check this in in a
day or so.

Signed-off-by: Hollis Blanchard <[EMAIL PROTECTED]>

diff -r dbc74db14a4b xen/arch/powerpc/boot_of.c
--- a/xen/arch/powerpc/boot_of.c        Tue Dec 12 14:35:07 2006 -0600
+++ b/xen/arch/powerpc/boot_of.c        Wed Jan 03 10:50:07 2007 -0600
@@ -22,7 +22,7 @@
 #include <xen/config.h>
 #include <xen/init.h>
 #include <xen/lib.h>
-#include <xen/multiboot.h>
+#include <xen/multiboot2.h>
 #include <xen/version.h>
 #include <xen/spinlock.h>
 #include <xen/serial.h>
@@ -30,6 +30,7 @@
 #include <xen/sched.h>
 #include <asm/page.h>
 #include <asm/io.h>
+#include <asm/boot.h>
 #include "exceptions.h"
 #include "of-devtree.h"
 #include "oftree.h"
@@ -77,6 +78,28 @@ static int bof_chosen;
 static int bof_chosen;
 
 static struct of_service s;
+
+static unsigned char xentags[512];
+static int xentags_pos;
+
+static int of_printf(const char *fmt, ...)
+    __attribute__ ((format (printf, 1, 2)));
+
+static void *alloc_tag(int key, int len)
+{
+    struct mb2_tag_header *tag;
+
+    if (xentags_pos + len > sizeof(xentags))
+        of_panic("Couldn't allocate multiboot tag.");
+
+    tag = (struct mb2_tag_header *)(xentags + xentags_pos);
+    tag->key = key;
+    tag->len = len;
+
+    xentags_pos += len;
+
+    return tag;
+}
 
 static int __init of_call(
     const char *service, u32 nargs, u32 nrets, s32 rets[], ...)
@@ -160,8 +183,6 @@ static int __init of_write(int ih, const
     return sum;
 }
 
-static int of_printf(const char *fmt, ...)
-    __attribute__ ((format (printf, 1, 2)));
 static int __init of_printf(const char *fmt, ...)
 {
     static char buf[1024];
@@ -609,8 +630,11 @@ static ulong boot_of_mem_init(void)
     return 0;
 }
 
-static void boot_of_bootargs(multiboot_info_t *mbi)
-{
+static char *boot_of_bootargs(char **dom0_cmdline)
+{
+    static const char *sepr[] = {" -- ", " || "};
+    char *p;
+    int sepr_index;
     int rc;
 
     if (builtin_cmdline[0] == '\0') {
@@ -620,10 +644,22 @@ static void boot_of_bootargs(multiboot_i
             of_panic("bootargs[] not big enough for /chosen/bootargs\n");
     }
 
-    mbi->flags |= MBI_CMDLINE;
-    mbi->cmdline = (ulong)builtin_cmdline;
-
     of_printf("bootargs = %s\n", builtin_cmdline);
+
+    /* look for delimiter: "--" or "||" */
+    for (sepr_index = 0; sepr_index < ARRAY_SIZE(sepr); sepr_index++){
+        p = strstr((char *)builtin_cmdline, sepr[sepr_index]);
+        if (p != NULL) {
+            /* Xen proper should never know about the dom0 args.  */
+            *(char *)p = '\0';
+            p += strlen(sepr[sepr_index]);
+            *dom0_cmdline = p;
+            of_printf("%s: dom0 cmdline: %s\n", __func__, *dom0_cmdline);
+            break;
+        }
+    }
+
+    return builtin_cmdline;
 }
 
 static int save_props(void *m, ofdn_t n, int pkg)
@@ -894,8 +930,8 @@ static void __init boot_of_fix_maple(voi
         }
     }
 }
-    
-static int __init boot_of_serial(void *oft)
+
+void __init boot_of_serial(void *oft)
 {
     int n;
     int p;
@@ -975,11 +1011,9 @@ static int __init boot_of_serial(void *o
                   __func__, ns16550.irq);
         ns16550.irq = 0;
     }
-
-    return 1;
-}
-
-static int __init boot_of_rtas(module_t *mod, multiboot_info_t *mbi)
+}
+
+static int __init boot_of_rtas(void)
 {
     int rtas_node;
     int rtas_instance;
@@ -1026,12 +1060,10 @@ static int __init boot_of_rtas(module_t 
     rtas_end = mem + size;
     rtas_msr = of_msr;
 
-    mod->mod_start = rtas_base;
-    mod->mod_end = rtas_end;
     return 1;
 }
 
-static void * __init boot_of_devtree(module_t *mod, multiboot_info_t *mbi)
+void __init *boot_of_devtree(void)
 {
     void *oft;
     ulong oft_sz = 48 * PAGE_SIZE;
@@ -1057,105 +1089,32 @@ static void * __init boot_of_devtree(mod
 
     ofd_walk(oft, __func__, OFD_ROOT, /* add_hype_props */ NULL, 2);
 
-    mod->mod_start = (ulong)oft;
-    mod->mod_end = mod->mod_start + oft_sz;
-    of_printf("%s: devtree mod @ 0x%016x - 0x%016x\n", __func__,
-              mod->mod_start, mod->mod_end);
+    oftree = (ulong)oft;
+    oftree_end = (ulong)oft + oft_sz;
+    oftree_len = oft_sz;
 
     return oft;
 }
 
-static void * __init boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
-{
-    static module_t mods[4];
-    ulong mod0_start;
-    ulong mod0_size;
-    static const char * sepr[] = {" -- ", " || "};
-    int sepr_index;
+/* Create a module tag for dom0. */
+static void __init boot_of_module(char *dom0_cmdline)
+{
+    struct mb2_tag_module *tag;
     extern char dom0_start[] __attribute__ ((weak));
     extern char dom0_size[] __attribute__ ((weak));
-    const char *p = NULL;
-    int mod;
-    void *oft;
-
-    if ((r3 > 0) && (r4 > 0)) {
-        /* was it handed to us in registers ? */
-        mod0_start = r3;
-        mod0_size = r4;
-            of_printf("%s: Dom0 was loaded and found using r3/r4:"
-                      "0x%lx[size 0x%lx]\n",
-                      __func__, mod0_start, mod0_size);
-    } else {
-        /* see if it is in the boot params */
-        p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
-        if ( p != NULL) {
-            p += 11;
-            mod0_start = simple_strtoul(p, NULL, 0);
-
-            p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
-            p += 10;
-            mod0_size = simple_strtoul(p, NULL, 0);
-            of_printf("%s: Dom0 was loaded and found using cmdline:"
-                      "0x%lx[size 0x%lx]\n",
-                      __func__, mod0_start, mod0_size);
-        } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
-            /* was it linked in ? */
-        
-            mod0_start = (ulong)dom0_start;
-            mod0_size = (ulong)dom0_size;
-            of_printf("%s: Dom0 is linked in: 0x%lx[size 0x%lx]\n",
-                      __func__, mod0_start, mod0_size);
-        } else {
-            mod0_start = (ulong)_end;
-            mod0_size = 0;
-            of_printf("%s: FYI Dom0 is unknown, will be caught later\n",
-                      __func__);
-        }
-    }
-
-    if (mod0_size > 0) {
-        const char *c = (const char *)mod0_start;
-
-        of_printf("mod0: %o %c %c %c\n", c[0], c[1], c[2], c[3]);
-    }
-
-    mod = 0;
-    mods[mod].mod_start = mod0_start;
-    mods[mod].mod_end = mod0_start + mod0_size;
-
-    of_printf("%s: dom0 mod @ 0x%016x[0x%x]\n", __func__,
-              mods[mod].mod_start, mods[mod].mod_end);
-
-    /* look for delimiter: "--" or "||" */
-    for (sepr_index = 0; sepr_index < ARRAY_SIZE(sepr); sepr_index++){
-        p = strstr((char *)(ulong)mbi->cmdline, sepr[sepr_index]);
-        if (p != NULL)
-            break;
-    }
-
-    if (p != NULL) {
-        /* Xen proper should never know about the dom0 args.  */
-        *(char *)p = '\0';
-        p += strlen(sepr[sepr_index]);
-        mods[mod].string = (u32)(ulong)p;
-        of_printf("%s: dom0 mod string: %s\n", __func__, p);
-    }
-
-    ++mod;
-    if (boot_of_rtas(&mods[mod], mbi))
-        ++mod;
-
-    oft = boot_of_devtree(&mods[mod], mbi);
-    if (oft == NULL)
-        of_panic("%s: boot_of_devtree failed\n", __func__);
-
-    ++mod;
-
-    mbi->flags |= MBI_MODULES;
-    mbi->mods_count = mod;
-    mbi->mods_addr = (u32)mods;
-
-    return oft;
+    const char *c = (const char *)dom0_start;
+
+    if (dom0_size == 0)
+        return;
+
+    of_printf("%s: dom0 @ %p[%p]\n", __func__, dom0_start, dom0_size);
+    of_printf("dom0: %o %c %c %c\n", c[0], c[1], c[2], c[3]);
+
+    tag = alloc_tag(MB2_TAG_MODULE, sizeof(*tag) + strlen(dom0_cmdline));
+    tag->addr = (ulong)dom0_start;
+    tag->size = (ulong)dom0_size;
+    strcpy(tag->type, "dom0");
+    strcpy(tag->cmdline, dom0_cmdline);
 }
 
 static int __init boot_of_cpus(void)
@@ -1278,15 +1237,19 @@ static int __init boot_of_cpus(void)
     return 1;
 }
 
-multiboot_info_t __init *boot_of_init(
-        ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
-{
-    static multiboot_info_t mbi;
-    void *oft;
+void __init boot_of_init(ulong vec, ulong orig_msr)
+{
     int r;
 
     of_vec = vec;
     of_msr = orig_msr;
+
+    if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
+        of_panic("Hmm.. OF[0x%lx] seems to have stepped on our image "
+                "that ranges: %p .. %p.\n",
+                vec, _start, _end);
+    }
+    of_printf("%s: _start %p _end %p\n", __func__, _start, _end);
 
     bof_chosen = of_finddevice("/chosen");
     of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out));
@@ -1297,32 +1260,56 @@ multiboot_info_t __init *boot_of_init(
               xen_compile_by(), xen_compile_domain(),
               xen_compiler(), xen_compile_date());
 
-    of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
-            "boot msr: 0x%lx\n",
-            __func__,
-            r3, r4, vec, r6, r7, orig_msr);
-
-    if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
-        of_panic("Hmm.. OF[0x%lx] seems to have stepped on our image "
-                "that ranges: %p .. %p.\n",
-                vec, _start, _end);
-    }
-    of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6);
-
     boot_of_fix_maple();
     r = boot_of_mem_init();
     if (r == 0)
         of_panic("failure to initialize memory allocator");
-    boot_of_bootargs(&mbi);
-    oft = boot_of_module(r3, r4, &mbi);
+
+    boot_of_rtas();
     boot_of_cpus();
-    boot_of_serial(oft);
-
+}
+
+/* Create a structure as if we were loaded by a multiboot bootloader. */
+struct mb2_tag_header __init *boot_of_multiboot(void)
+{
+    struct mb2_tag_start *start;
+    struct mb2_tag_name *name;
+    struct mb2_tag_module *xenmod;
+    struct mb2_tag_end *end;
+    char *xen_cmdline;
+    char *dom0_cmdline = NULL;
+    static char *namestr = "xen";
+
+    /* create "start" tag. start->size is filled in later. */
+    start = alloc_tag(MB2_TAG_START, sizeof(*start));
+
+    /* create "name" tag. */
+    name = alloc_tag(MB2_TAG_NAME, sizeof(*name) + strlen(namestr));
+    strcpy(name->name, namestr);
+
+    /* figure out the command line and create the Xen module tag. */
+    xen_cmdline = boot_of_bootargs(&dom0_cmdline);
+    xenmod = alloc_tag(MB2_TAG_MODULE, sizeof(*xenmod) + strlen(xen_cmdline));
+    xenmod->addr = (ulong)_start;
+    xenmod->size = _end - _start;
+    strcpy(xenmod->type, "xen");
+    strcpy(xenmod->cmdline, xen_cmdline);
+
+    /* create more module tags. */
+    boot_of_module(dom0_cmdline);
+
+    /* create "end" tag and terminate "start" tag. */
+    end = alloc_tag(MB2_TAG_END, sizeof(*end));
+    start->size = xentags_pos;
+
+    return (struct mb2_tag_header *)xentags;
+}
+
+void __init boot_of_finish(void)
+{
     /* end of OF */
     of_printf("Quiescing Open Firmware ...\n");
     of_call("quiesce", 0, 0, NULL);
-
-    return &mbi;
 }
 
 /*
diff -r dbc74db14a4b xen/arch/powerpc/exceptions.h
--- a/xen/arch/powerpc/exceptions.h     Tue Dec 12 14:35:07 2006 -0600
+++ b/xen/arch/powerpc/exceptions.h     Tue Jan 02 15:49:20 2007 -0600
@@ -33,9 +33,6 @@ extern void ack_APIC_irq(void);
 extern void ack_APIC_irq(void);
 extern int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 
*pval);
 extern int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 
val);
-extern void __start_xen_ppc(
-    ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr);
-extern  multiboot_info_t *boot_of_init(ulong r3, ulong r4, ulong vec, ulong 
r6, ulong r7, ulong orig_msr);
 
 extern void do_timer(struct cpu_user_regs *regs);
 extern void do_dec(struct cpu_user_regs *regs);
diff -r dbc74db14a4b xen/arch/powerpc/memory.c
--- a/xen/arch/powerpc/memory.c Tue Dec 12 14:35:07 2006 -0600
+++ b/xen/arch/powerpc/memory.c Tue Jan 02 15:58:29 2007 -0600
@@ -21,6 +21,8 @@
 #include <xen/sched.h>
 #include <xen/mm.h>
 #include <xen/numa.h>
+#include <xen/multiboot2.h>
+#include <asm/boot.h>
 #include "of-devtree.h"
 #include "oftree.h"
 #include "rtas.h"
@@ -141,43 +143,9 @@ static void ofd_walk_mem(void *m, walk_m
     }
 }
 
-static void setup_xenheap(module_t *mod, int mcount)
-{
-    int i;
-    ulong freemem;
-
-    freemem = ALIGN_UP((ulong)_end, PAGE_SIZE);
-
-    for (i = 0; i < mcount; i++) {
-        u32 s;
-
-        if (mod[i].mod_end == mod[i].mod_start)
-            continue;
-
-        s = ALIGN_DOWN(mod[i].mod_start, PAGE_SIZE);
-
-        if (mod[i].mod_start > (ulong)_start &&
-            mod[i].mod_start < (ulong)_end) {
-            /* mod was linked in */
-            continue;
-        }
-
-        if (s < freemem) 
-            panic("module addresses must assend\n");
-
-        free_xenheap(freemem, s);
-        freemem = ALIGN_UP(mod[i].mod_end, PAGE_SIZE);
-        
-    }
-
-    /* the rest of the xenheap, starting at the end of modules */
-    free_xenheap(freemem, xenheap_phys_end);
-}
-
-void memory_init(module_t *mod, int mcount)
+void memory_init(ulong mod_end)
 {
     ulong eomem;
-    ulong heap_start;
     ulong xh_pages;
 
     /* lets find out how much memory there is and set max_page */
@@ -185,19 +153,8 @@ void memory_init(module_t *mod, int mcou
     printk("Physical RAM map:\n");
     ofd_walk_mem((void *)oftree, set_max_page);
     eomem = max_page << PAGE_SHIFT;
-
-    if (eomem == 0){
+    if (eomem == 0) {
         panic("ofd_walk_mem() failed\n");
-    }
-
-    /* find the portion of memory we need to keep safe */
-    save_start = oftree;
-    save_end = oftree_end;
-    if (rtas_base) {
-        if (save_start > rtas_base)
-            save_start = rtas_base;
-        if (save_end < rtas_end)
-            save_end = rtas_end;
     }
 
     /* minimum heap has to reach to the end of all Xen required memory */
@@ -214,16 +171,10 @@ void memory_init(module_t *mod, int mcou
 
     printk("End of RAM: %luMiB (%luKiB)\n", eomem >> 20, eomem >> 10);
 
-    /* Architecturally the first 4 pages are exception hendlers, we
-     * will also be copying down some code there */
-    heap_start = 4 << PAGE_SHIFT;
-    if (oftree < (ulong)_start)
-        heap_start = ALIGN_UP(oftree_end, PAGE_SIZE);
-
-    heap_start = init_boot_allocator(heap_start);
-    if (heap_start > (ulong)_start) {
+    freemem_start = init_boot_allocator(freemem_start);
+    if (freemem_start > (ulong)_start) {
         panic("space below _start (%p) is not enough memory "
-              "for heap (0x%lx)\n", _start, heap_start);
+              "for heap (0x%lx)\n", _start, freemem_start);
     }
 
     /* allow everything else to be allocated */
@@ -242,12 +193,14 @@ void memory_init(module_t *mod, int mcou
 
     numa_initmem_init(0, max_page);
 
+    /* domain heap gets all the still-unclaimed memory */
     end_boot_allocator();
 
-    /* Add memory between the beginning of the heap and the beginning
-     * of our text */
-    free_xenheap(heap_start, (ulong)_start);
-    setup_xenheap(mod, mcount);
+    /* xen heap: memory below _start */
+    free_xenheap(freemem_start, (ulong)_start);
+    /* xen heap: memory after modules */
+    free_xenheap(mod_end, xenheap_phys_end);
+
     printk("Xen Heap: %luMiB (%luKiB)\n",
            xenheap_size >> 20, xenheap_size >> 10);
 
diff -r dbc74db14a4b xen/arch/powerpc/oftree.h
--- a/xen/arch/powerpc/oftree.h Tue Dec 12 14:35:07 2006 -0600
+++ b/xen/arch/powerpc/oftree.h Tue Jan 02 15:51:54 2007 -0600
@@ -34,6 +34,4 @@ extern int firmware_image_start[0];
 extern int firmware_image_start[0];
 extern int firmware_image_size[0];
 
-extern void memory_init(module_t *mod, int mcount);
-
 #endif  /* #ifndef _OFTREE_H */
diff -r dbc74db14a4b xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c  Tue Dec 12 14:35:07 2006 -0600
+++ b/xen/arch/powerpc/setup.c  Wed Jan 03 11:04:10 2007 -0600
@@ -24,8 +24,8 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/cpumask.h>
+#include <xen/multiboot2.h>
 #include <xen/sched.h>
-#include <xen/multiboot.h>
 #include <xen/serial.h>
 #include <xen/softirq.h>
 #include <xen/console.h>
@@ -46,6 +46,7 @@
 #include <asm/delay.h>
 #include <asm/percpu.h>
 #include <asm/io.h>
+#include <asm/boot.h>
 #include "exceptions.h"
 #include "of-devtree.h"
 #include "oftree.h"
@@ -76,6 +77,7 @@ ulong oftree;
 ulong oftree;
 ulong oftree_len;
 ulong oftree_end;
+ulong freemem_start;
 
 uint cpu_hard_id[NR_CPUS] __initdata;
 cpumask_t cpu_present_map;
@@ -287,21 +289,31 @@ void secondary_cpu_init(int cpuid, unsig
     panic("should never get here\n");
 }
 
-static void __init __start_xen(multiboot_info_t *mbi)
-{
-    char *cmdline;
-    module_t *mod = (module_t *)((ulong)mbi->mods_addr);
-    ulong dom0_start, dom0_len;
-    ulong initrd_start, initrd_len;
+static void __init __start_xen(struct mb2_tag_header *tags)
+{
+    struct mb2_tag_header *tag;
+    ulong mod_end = (ulong)_end;
+    char *dom0_cmdline;
+    ulong dom0_start = 0;
+    ulong dom0_len = 0;
+    ulong initrd_start = 0;
+    ulong initrd_len = 0;
 
     memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
     synchronize_caches(0, exception_vectors_end - exception_vectors);
 
     ticks_per_usec = timebase_freq / 1000000ULL;
 
-    /* Parse the command-line options. */
-    if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
-        cmdline_parse(__va((ulong)mbi->cmdline));
+    /* parse the command-line options. */
+    for_each_tag(tag, tags) {
+        if (tag->key == MB2_TAG_MODULE) {
+            struct mb2_tag_module *module = (struct mb2_tag_module *)tag;
+            if (!strcmp(module->type, "xen")) {
+                cmdline_parse(module->cmdline);
+                break;
+            }
+        }
+    }
 
     /* we need to be able to identify this CPU early on */
     init_boot_cpu();
@@ -314,32 +326,28 @@ static void __init __start_xen(multiboot
     serial_init_preirq();
 
     init_console();
-    /* let synchronize until we really get going */
-    console_start_sync();
-
-    /* Check that we have at least one Multiboot module. */
-    if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
-        panic("FATAL ERROR: Require at least one Multiboot module.\n");
-    }
-
-    /* OF dev tree is the last module */
-    oftree = mod[mbi->mods_count-1].mod_start;
-    oftree_end = mod[mbi->mods_count-1].mod_end;
-    oftree_len = oftree_end - oftree;
-
-    /* remove it from consideration */
-    mod[mbi->mods_count-1].mod_start = 0;
-    mod[mbi->mods_count-1].mod_end = 0;
-    --mbi->mods_count;
-
-    if (rtas_entry) {
-        rtas_init((void *)oftree);
-        /* remove rtas module from consideration */
-        mod[mbi->mods_count-1].mod_start = 0;
-        mod[mbi->mods_count-1].mod_end = 0;
-        --mbi->mods_count;
-    }
-    memory_init(mod, mbi->mods_count);
+    console_start_sync(); /* stay synchronous for early debugging. */
+
+    rtas_init((void *)oftree);
+
+    /* copy modules to a contiguous space immediately after Xen */
+    for_each_tag(tag, tags) {
+        if (tag->key == MB2_TAG_MODULE) {
+            struct mb2_tag_module *module = (struct mb2_tag_module *)tag;
+            memmove((void *)mod_end, (void *)(ulong)module->addr, 
module->size);
+            if (!strcmp(module->type, "dom0")) {
+                dom0_start = mod_end;
+                dom0_len = module->size;
+                dom0_cmdline = module->cmdline;
+            } else if (!strcmp(module->type, "initrd")) {
+                initrd_start = mod_end;
+                initrd_len = module->size;
+            }
+            mod_end += module->size;
+        }
+    }
+
+    memory_init(mod_end);
 
 #ifdef OF_DEBUG
     key_ofdump(0);
@@ -392,25 +400,17 @@ static void __init __start_xen(multiboot
     /* Post-create hook sets security label. */
     acm_post_domain0_create(dom0->domain_id);
 
-    cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
-
     /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
     local_irq_enable();
     /* Scrub RAM that is still free and so may go to an unprivileged domain. */
     scrub_heap_pages();
 
-    dom0_start = mod[0].mod_start;
-    dom0_len = mod[0].mod_end - mod[0].mod_start;
-    if (mbi->mods_count > 1) {
-        initrd_start = mod[1].mod_start;
-        initrd_len = mod[1].mod_end - mod[1].mod_start;
-    } else {
-        initrd_start = 0;
-        initrd_len = 0;
-    }
+    if ((dom0_start == 0) || (dom0_len == 0))
+        panic("No domain 0 found.\n");
+
     if (construct_dom0(dom0, dom0_start, dom0_len,
                        initrd_start, initrd_len,
-                       cmdline) != 0) {
+                       dom0_cmdline) != 0) {
         panic("Could not set up DOM0 guest OS\n");
     }
 
@@ -439,22 +439,37 @@ void __init __start_xen_ppc(
 void __init __start_xen_ppc(
     ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr)
 {
-    multiboot_info_t *mbi = NULL;
+    struct mb2_tag_header *tags = NULL;
+    void *oft;
+
+    /* Open Firmware required. */
+    if (!r5)
+        return;
 
     /* clear bss */
     memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);
 
-    if (r5 > 0) {
-        /* we were booted by OpenFirmware */
-        mbi = boot_of_init(r3, r4, r5, r6, r7, orig_msr);
-
+    boot_of_init(r5, orig_msr);
+    /* copy device tree from firmware */
+    oft = boot_of_devtree();
+    freemem_start = oftree_end;
+
+    /* detect the Xen console from the device tree */
+    boot_of_serial(oft);
+
+    if (r3 == MB2_BOOTLOADER_MAGIC) {
+        tags = (struct mb2_tag_header *)r4;
+        if (tags->key != MB2_TAG_START)
+            return;
     } else {
-        /* booted by someone else that hopefully has a trap handler */
-        __builtin_trap();
-    }
-
-    __start_xen(mbi);
-
+        /* We were booted directly from Open Firmware. Fake up some multiboot
+         * tags. */
+        tags = boot_of_multiboot();
+    }
+
+    boot_of_finish();
+
+    __start_xen(tags);
 }
 
 extern void arch_get_xen_caps(xen_capabilities_info_t info);
diff -r dbc74db14a4b xen/include/asm-powerpc/boot.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-powerpc/boot.h    Tue Jan 02 15:55:49 2007 -0600
@@ -0,0 +1,38 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2005
+ *
+ * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
+ */
+
+#ifndef _ASM_BOOT_H
+#define _ASM_BOOT_H
+
+struct mb2_tag_header;
+
+extern ulong freemem_start;
+
+extern void boot_of_init(ulong, ulong);
+extern void *boot_of_devtree(void);
+extern void boot_of_serial(void *);
+extern struct mb2_tag_header *boot_of_multiboot(void);
+extern void boot_of_finish(void);
+
+extern void __start_xen_ppc(ulong, ulong, ulong, ulong, ulong, ulong);
+
+extern void memory_init(ulong);
+
+#endif
diff -r dbc74db14a4b xen/include/xen/multiboot2.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/multiboot2.h      Tue Jan 02 15:41:42 2007 -0600
@@ -0,0 +1,102 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
+ *          
+ */
+
+#ifndef _MULTIBOOT2_H_
+#define _MULTIBOOT2_H_
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MB2_HEADER_SEARCH           8192
+
+/* The magic field should contain this.  */
+#define MB2_HEADER_MAGIC            0xe85250d6
+
+/* Passed from the bootloader to the kernel.  */
+#define MB2_BOOTLOADER_MAGIC        0x36d76289
+
+#include <stdint.h>
+
+#define for_each_tag(_tag, _tags) \
+    for ((_tag) = (_tags); \
+            (_tag)->key != MB2_TAG_END; \
+            (_tag) = (void *)(_tag) + (_tag)->len)
+
+typedef uint32_t mb2_word;
+
+struct mb2_header
+{
+  uint32_t magic;
+};
+
+struct mb2_tag_header
+{
+  uint32_t key;
+  uint32_t len;
+};
+
+#define MB2_TAG_RESERVED1 0
+#define MB2_TAG_RESERVED2 (~0)
+
+#define MB2_TAG_START     1
+struct mb2_tag_start
+{
+  struct mb2_tag_header header;
+  mb2_word size; /* Total size of all mb2 tags. */
+};
+
+#define MB2_TAG_NAME      2
+struct mb2_tag_name
+{
+  struct mb2_tag_header header;
+  char name[1];
+};
+
+#define MB2_TAG_MODULE    3
+struct mb2_tag_module
+{
+  struct mb2_tag_header header;
+  mb2_word addr;
+  mb2_word size;
+  unsigned char type[36];
+  unsigned char cmdline[1];
+};
+
+#define MB2_TAG_MEMORY    4
+struct mb2_tag_memory
+{
+  struct mb2_tag_header header;
+  mb2_word addr;
+  mb2_word size;
+  mb2_word type;
+};
+
+#define MB2_TAG_UNUSED    5
+struct mb2_tag_unused
+{
+  struct mb2_tag_header header;
+};
+
+#define MB2_TAG_END       0xffff
+struct mb2_tag_end
+{
+  struct mb2_tag_header header;
+};
+
+#endif


-- 
Hollis Blanchard
IBM Linux Technology Center


_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to