Index: openbios-quilt/include/openbios/fw_cfg.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openbios-quilt/include/openbios/fw_cfg.h	2008-09-11 17:50:56.000000000 +0000
@@ -0,0 +1,33 @@
+#ifndef FW_CFG_H
+#define FW_CFG_H
+
+#define FW_CFG_SIGNATURE        0x00
+#define FW_CFG_ID               0x01
+#define FW_CFG_UUID             0x02
+#define FW_CFG_RAM_SIZE         0x03
+#define FW_CFG_NOGRAPHIC        0x04
+#define FW_CFG_NB_CPUS          0x05
+#define FW_CFG_MACHINE_ID       0x06
+#define FW_CFG_MAX_ENTRY        0x10
+
+#define FW_CFG_WRITE_CHANNEL    0x4000
+#define FW_CFG_ARCH_LOCAL       0x8000
+#define FW_CFG_ENTRY_MASK       ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)
+
+#define FW_CFG_INVALID          0xffff
+
+#ifndef NO_QEMU_PROTOS
+typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
+
+int fw_cfg_add_bytes(void *opaque, uint16_t key, uint8_t *data, uint16_t len);
+int fw_cfg_add_i16(void *opaque, uint16_t key, uint16_t value);
+int fw_cfg_add_i32(void *opaque, uint16_t key, uint32_t value);
+int fw_cfg_add_i64(void *opaque, uint16_t key, uint64_t value);
+int fw_cfg_add_callback(void *opaque, uint16_t key, FWCfgCallback callback,
+                        void *callback_opaque, uint8_t *data, size_t len);
+void *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
+		target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
+
+#endif /* NO_QEMU_PROTOS */
+
+#endif
Index: openbios-quilt/arch/sparc64/entry.S
===================================================================
--- openbios-quilt.orig/arch/sparc64/entry.S	2008-09-02 15:33:04.000000000 +0000
+++ openbios-quilt/arch/sparc64/entry.S	2008-09-11 17:53:37.000000000 +0000
@@ -11,10 +11,11 @@
 #include "asi.h"
 #include "pstate.h"
 #include "lsu.h"
-#define __ASSEMBLY__
-#include "openbios/firmware_abi.h"
+#define NO_QEMU_PROTOS
+#include "openbios/fw_cfg.h"
 
 #define PROM_ADDR 0x1fff0000000
+#define CFG_ADDR  0x1fe02000510
 
         .globl	entry, _entry
 
@@ -52,58 +53,64 @@
         ! Disable I/D MMUs and caches
         stxa    %g0, [%g0] ASI_LSU_CONTROL
 
-        ! Get memory size from NVRAM
-        setx    0x1fe02000074, %g2, %g5
-        mov     OHW_RAM_SIZE, %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-        add     %g5, 1, %g1
-        stba    %g0, [%g1] ASI_PHYS_BYPASS_EC_E
-        add     %g1, 2, %g1
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g4
-
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        ! Check signature "QEMU"
+        setx    CFG_ADDR, %g2, %g5
+        mov     FW_CFG_SIGNATURE, %g2
+        stha    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
+        inc     %g5
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+        cmp     %g2, 'Q'
+        bne     bad_conf
+         nop
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+        cmp     %g2, 'E'
+        bne     bad_conf
+         nop
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+        cmp     %g2, 'M'
+        bne     bad_conf
+         nop
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+        cmp     %g2, 'U'
+        bne     bad_conf
+         nop
+
+        ! Get memory size from configuration device
+        ! NB: little endian format
+        mov     FW_CFG_RAM_SIZE, %g2
+        dec     %g5
+        stha    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
+        inc     %g5
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g4
+
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 8, %g3
         or      %g3, %g4, %g4
 
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 16, %g3
         or      %g3, %g4, %g4
 
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 24, %g3
         or      %g3, %g4, %g4
 
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 32, %g3
         or      %g3, %g4, %g4
 
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 40, %g3
         or      %g3, %g4, %g4
 
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 48, %g3
         or      %g3, %g4, %g4
 
-        sll     %g4, 8, %g4
-        inc     %g2
-        stba    %g2, [%g5] ASI_PHYS_BYPASS_EC_E
-	lduba	[%g1] ASI_PHYS_BYPASS_EC_E, %g3
+        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+        sllx    %g3, 56, %g3
         or      %g3, %g4, %g1
-	! %g1 contains end of memory
-
+        ! %g1 contains end of memory
 
         setx    _end, %g7, %g3
         set     0xffff, %g2
@@ -301,8 +308,7 @@
 
         /* We get here when the main context switches back to
          * the boot context.
-         * Return to previous bootloader.
          */
-        ret
+bad_conf:
+        b       bad_conf
          nop
-
Index: openbios-quilt/arch/sparc64/openbios.c
===================================================================
--- openbios-quilt.orig/arch/sparc64/openbios.c	2008-09-02 15:51:58.000000000 +0000
+++ openbios-quilt/arch/sparc64/openbios.c	2008-09-11 17:57:28.000000000 +0000
@@ -24,6 +24,11 @@
 #include "asi.h"
 #include "spitfire.h"
 #include "libc/vsprintf.h"
+#define NO_QEMU_PROTOS
+#include "openbios/fw_cfg.h"
+
+#define BIOS_CFG_CMD  0x510
+#define BIOS_CFG_DATA 0x511
 
 #define REGISTER_NAMED_NODE( name, path )   do {                        \
         bind_new_node( name##_flags_, name##_size_,                     \
@@ -67,6 +72,8 @@
 #define PAGE_MASK_64K  (64 * 1024 - 1)
 #define PAGE_MASK_8K   (8 * 1024 - 1)
 
+#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
 static void
 mmu_open(void)
 {
@@ -474,6 +481,8 @@
     for (;;);
 }
 
+static uint8_t qemu_uuid[16];
+
 void arch_nvram_get(char *data)
 {
     unsigned short i;
@@ -481,6 +490,9 @@
     uint32_t size;
     const struct cpudef *cpu;
     const char *bootpath;
+    char buf[256];
+    uint32_t temp;
+    uint64_t ram_size;
 
     for (i = 0; i < sizeof(ohwcfg_v3_t); i++) {
         outb(i & 0xff, 0x74);
@@ -488,14 +500,20 @@
         *nvptr++ = inb(0x77);
     }
 
-    printk("Nvram id %s, version %d\n", nv_info.struct_ident,
-           nv_info.struct_version);
-    if (strcmp(nv_info.struct_ident, "QEMU_BIOS") ||
-        nv_info.struct_version != 3 ||
-        OHW_compute_crc(&nv_info, 0x00, 0xF8) != nv_info.crc) {
-        printk("Unknown nvram, freezing!\n");
-        for (;;);
-    }
+    outw(__cpu_to_le16(FW_CFG_SIGNATURE), BIOS_CFG_CMD);
+    for (i = 0; i < 4; i++)
+        buf[i] = inb(BIOS_CFG_DATA);
+
+    buf[4] = '\0';
+
+    printk("Configuration device id %s", buf);
+
+    outw(__cpu_to_le16(FW_CFG_ID), BIOS_CFG_CMD);
+    for (i = 0; i < 4; i++)
+        buf[i] = inb(BIOS_CFG_DATA);
+
+    temp = __le32_to_cpu(*(uint32_t *)buf);
+    printk(" version %d\n", temp);
 
     kernel_image = nv_info.kernel_image;
     kernel_size = nv_info.kernel_size;
@@ -518,16 +536,40 @@
         data[i] = inb(0x77);
     }
 
-    printk("CPUs: %x", nv_info.nb_cpus);
+    outw(__cpu_to_le16(FW_CFG_NB_CPUS), BIOS_CFG_CMD);
+    for (i = 0; i < 4; i++)
+        buf[i] = inb(BIOS_CFG_DATA);
+
+    temp = __le32_to_cpu(*(uint32_t *)buf);
+
+    printk("CPUs: %x", temp);
+
     cpu = id_cpu();
     //cpu->initfn();
     cpu_generic_init(cpu);
     printk(" x %s\n", cpu->name);
 
-    // Add /idprom
+    // Add /uuid
+    outw(__cpu_to_le16(FW_CFG_UUID), BIOS_CFG_CMD);
+    for (i = 0; i < 16; i++)
+        qemu_uuid[i] = inb(BIOS_CFG_DATA);
+
+    printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
+           qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
+           qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+           qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
+           qemu_uuid[15]);
+
     push_str("/");
     fword("find-device");
 
+    PUSH((long)&qemu_uuid);
+    PUSH(16);
+    fword("encode-bytes");
+    push_str("uuid");
+    fword("property");
+
+    // Add /idprom
     for (i = 0; i < 32; i++) {
         outb((i + 0x1fd8) & 0xff, 0x74);
         outb((i + 0x1fd8) >> 8, 0x75);
@@ -548,16 +590,22 @@
     push_str("/memory");
     fword("find-device");
 
+    outw(__cpu_to_le16(FW_CFG_RAM_SIZE), BIOS_CFG_CMD);
+    for (i = 0; i < 8; i++)
+        buf[i] = inb(BIOS_CFG_DATA);
+
+    ram_size = __le64_to_cpu(*(uint64_t *)buf);
+
     // All memory: 0 to RAM_size
     PUSH(0);
     fword("encode-int");
     PUSH(0);
     fword("encode-int");
     fword("encode+");
-    PUSH((int)(nv_info.RAM0_size >> 32));
+    PUSH((int)(ram_size >> 32));
     fword("encode-int");
     fword("encode+");
-    PUSH((int)(nv_info.RAM0_size & 0xffffffff));
+    PUSH((int)(ram_size & 0xffffffff));
     fword("encode-int");
     fword("encode+");
     push_str("reg");
Index: openbios-quilt/arch/sparc32/entry.S
===================================================================
--- openbios-quilt.orig/arch/sparc32/entry.S	2008-09-02 15:33:04.000000000 +0000
+++ openbios-quilt/arch/sparc32/entry.S	2008-09-11 19:15:46.000000000 +0000
@@ -12,6 +12,11 @@
 #include "asm/crs.h"
 #define __ASSEMBLY__
 #include "openbios/firmware_abi.h"
+#define NO_QEMU_PROTOS
+#include "openbios/fw_cfg.h"
+
+#define CFG_ADDR 0x00000510
+#define CFG_ASI  0x2d
 
 #define PHYS_JJ_EEPROM	0x71200000  /* [2000] MK48T08 */
 #define PHYS_JJ_INTR0	0x71E00000  /* CPU0 interrupt control registers */
@@ -44,41 +49,84 @@
          * Main context is statically defined in C.
          */
 
-        ! Check if this is QEMU for SS-5
-        set PHYS_JJ_EEPROM, %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
+        ! Check signature "QEMU"
+        set     CFG_ADDR, %g5
+        mov     FW_CFG_SIGNATURE, %g2
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g2
         cmp     %g2, 'Q'
-        bne     ss10
-         inc    %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
+        bne     bad_conf
+         nop
+        lduba   [%g5] CFG_ASI, %g2
         cmp     %g2, 'E'
-        bne     ss10
-         inc    %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
+        bne     bad_conf
+         nop
+        lduba   [%g5] CFG_ASI, %g2
         cmp     %g2, 'M'
-        bne     ss10
-         inc    %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
+        bne     bad_conf
+         nop
+        lduba   [%g5] CFG_ASI, %g2
         cmp     %g2, 'U'
-        bne     ss10
+        bne     bad_conf
+         nop
+
+        ! Get memory size from configuration device
+        ! NB: little endian format
+        mov     FW_CFG_RAM_SIZE, %g2
+        sub     %g5, 2, %g5
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 8, %g3
+        or      %g3, %g4, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 16, %g3
+        or      %g3, %g4, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 24, %g3
+        or      %g3, %g4, %g1
+        ! %g1 contains end of memory
+
+        ! Get machine ID from configuration device
+        mov     FW_CFG_MACHINE_ID, %g2
+        sub     %g5, 2, %g5
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 8, %g3
+        or      %g3, %g4, %g4
+        mov     %g4, %y
+
+        cmp     %g4, 96
+        bgeu    ss1000
+         cmp    %g4, 64
+        bgeu    ss10
+         cmp    %g4, 32
+        blu     ss2
+         nop
 
         ! Ok, this is SS-5
-        mov     0x80, %y
         ! Find architecture specific part
-        set     PHYS_JJ_EEPROM + OHW_ARCH_PTR, %g1
-        lduha   [%g1] ASI_M_BYPASS, %g2
-        set     PHYS_JJ_EEPROM, %g1
-        add     %g1, %g2, %g3
+        set     PHYS_JJ_EEPROM + OHW_ARCH_PTR, %g5
+        lduha   [%g5] ASI_M_BYPASS, %g2
+        set     PHYS_JJ_EEPROM, %g5
+        add     %g5, %g2, %g3
         ! Check if this not the first SMP CPU, if so, bypass PROM entirely
-        add     %g3, SPARC_SMP_VALID, %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
-        stba    %g0, [%g1] ASI_M_BYPASS
-        set	PHYS_JJ_EEPROM + OHW_RAM_SIZE, %g1
-        ldda	[%g1] ASI_M_BYPASS, %g0
+        add     %g3, SPARC_SMP_VALID, %g5
+        lduba   [%g5] ASI_M_BYPASS, %g2
+        stba    %g0, [%g5] ASI_M_BYPASS
         tst     %g2
         bz      first_cpu
          nop
 
+        ! SMP init, jump to user specified address
         set     PHYS_JJ_INTR0 + 0x04, %g1
         sll     %g2, 12, %g2
         add     %g1, %g2, %g2
@@ -104,41 +152,21 @@
          sta    %g1, [%g0] ASI_M_MMUREGS        ! enable mmu
 
 ss10:
-        set PHYS_SS10_EEPROM, %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'Q'
-        bne     ss2
-         inc    %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'E'
-        bne     ss2
-         inc    %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'M'
-        bne     ss2
-         inc    %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'U'
-        bne     ss2
-
         ! Ok, this is SS-10 or SS-600MP
-        set     PHYS_SS10_EEPROM + SPARC_MACHINE_ID, %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        mov     %g2, %y
         ! Find architecture specific part
-        set     PHYS_SS10_EEPROM + OHW_ARCH_PTR, %g1
-        lduha   [%g1] ASI_M_CTL, %g2
-        set     PHYS_SS10_EEPROM, %g1
-        add     %g1, %g2, %g3
+        set     PHYS_SS10_EEPROM + OHW_ARCH_PTR, %g5
+        lduha   [%g5] ASI_M_CTL, %g2
+        set     PHYS_SS10_EEPROM, %g5
+        add     %g5, %g2, %g3
         ! Check if this not the first SMP CPU, if so, bypass PROM entirely
-        add     %g3, SPARC_SMP_VALID, %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        stba    %g0, [%g1] ASI_M_CTL
-        set     PHYS_SS10_EEPROM + OHW_RAM_SIZE, %g1
-        ldda	[%g1] ASI_M_CTL, %g0
+        add     %g3, SPARC_SMP_VALID, %g5
+        lduba   [%g5] ASI_M_CTL, %g2
+        stba    %g0, [%g5] ASI_M_CTL
         tst     %g2
         bz      first_cpu
          nop
+
+        ! SMP init, jump to user specified address
         set     PHYS_SS10_INTR0 + 0x04, %g1
         sll     %g2, 12, %g2
         add     %g1, %g2, %g2
@@ -164,46 +192,12 @@
          sta    %g1, [%g0] ASI_M_MMUREGS        ! enable mmu
 
 ss2:
-        set PHYS_SS2_EEPROM, %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
-        cmp     %g2, 'Q'
-        bne     ss1000
-         inc    %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
-        cmp     %g2, 'E'
-        bne     ss1000
-         inc    %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
-        cmp     %g2, 'M'
-        bne     ss1000
-         inc    %g1
-        lduba   [%g1] ASI_M_BYPASS, %g2
-        cmp     %g2, 'U'
-        bne     ss1000
-
         ! Ok, this is SS-2
         set     ss2_error, %o2
         b       ss2_ss1000_halt
          nop
 
 ss1000:
-        set     PHYS_SS1000_EEPROM, %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'Q'
-        bne     bad_nvram
-         inc    %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'E'
-        bne     bad_nvram
-         inc    %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'M'
-        bne     bad_nvram
-         inc    %g1
-        lduba   [%g1] ASI_M_CTL, %g2
-        cmp     %g2, 'U'
-        bne     bad_nvram
-
         ! Ok, this is SS-1000 or SS-2000
         set     ss1000_error, %o2
         b       ss2_ss1000_halt
@@ -408,7 +402,7 @@
         stba    %o3, [%o1] ASI_M_CTL
         b       1b
          inc    %o2
-bad_nvram:
+bad_conf:
 2:      b       2b
          nop
 
Index: openbios-quilt/arch/sparc32/openbios.c
===================================================================
--- openbios-quilt.orig/arch/sparc32/openbios.c	2008-09-02 15:33:04.000000000 +0000
+++ openbios-quilt/arch/sparc32/openbios.c	2008-09-11 17:49:59.000000000 +0000
@@ -27,7 +27,7 @@
     unsigned long aux1_offset, aux2_offset;
     uint64_t dma_base, esp_base, le_base;
     uint64_t tcx_base;
-    int machine_id;
+    int machine_id_low, machine_id_high;
 };
 
 static const struct hwdef hwdefs[] = {
@@ -47,7 +47,8 @@
         .dma_base     = 0x78400000,
         .esp_base     = 0x78800000,
         .le_base      = 0x78c00000,
-        .machine_id = 0x80,
+        .machine_id_low = 32,
+        .machine_id_high = 63,
     },
     /* SS-10 */
     {
@@ -65,7 +66,8 @@
         .dma_base     = 0xef0400000ULL,
         .esp_base     = 0xef0800000ULL,
         .le_base      = 0xef0c00000ULL,
-        .machine_id = 0x72,
+        .machine_id_low = 64,
+        .machine_id_high = 65,
     },
     /* SS-600MP */
     {
@@ -83,7 +85,8 @@
         .dma_base     = 0xef0081000ULL,
         .esp_base     = 0xef0080000ULL,
         .le_base      = 0xef0060000ULL,
-        .machine_id = 0x71,
+        .machine_id_low = 66,
+        .machine_id_high = 66,
     },
 };
 
@@ -121,7 +124,7 @@
 #ifdef CONFIG_DEBUG_CONSOLE_VIDEO
 	init_video();
 #endif
-	ob_sbus_init(hwdef->iommu_base + 0x1000ULL, hwdef->machine_id);
+	ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
 #endif
 	device_end();
 
@@ -133,7 +136,8 @@
         unsigned int i;
 
         for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
-            if (hwdefs[i].machine_id == qemu_machine_type) {
+            if (hwdefs[i].machine_id_low <= qemu_machine_type &&
+                hwdefs[i].machine_id_high >= qemu_machine_type) {
                 hwdef = &hwdefs[i];
                 break;
             }
Index: openbios-quilt/drivers/obio.c
===================================================================
--- openbios-quilt.orig/drivers/obio.c	2008-09-02 15:33:04.000000000 +0000
+++ openbios-quilt/drivers/obio.c	2008-09-11 18:05:51.000000000 +0000
@@ -21,6 +21,8 @@
 #include "obio.h"
 #define cpu_to_be16(x) __cpu_to_be16(x)
 #include "openbios/firmware_abi.h"
+#define NO_QEMU_PROTOS
+#include "openbios/fw_cfg.h"
 
 #define REGISTER_NAMED_NODE( name, path )   do { \
 	     bind_new_node( name##_flags_, name##_size_, \
@@ -294,7 +296,7 @@
     }
 }
 
-static uint32_t
+static void
 ob_eccmemctl_init(void)
 {
     uint32_t version, *regs;
@@ -333,8 +335,6 @@
     fword("property");
 
     fword("finish-device");
-
-    return version;
 }
 
 static unsigned char *nvram;
@@ -716,6 +716,67 @@
     for (;;);
 }
 
+static void dummy_mach_init(void)
+{
+}
+
+struct machdef {
+    uint16_t machine_id;
+    const char *banner_name;
+    const char *model;
+    const char *name;
+    int mid_offset;
+    void (*initfn)(void);
+};
+
+static const struct machdef sun4m_defs[] = {
+    {
+        .machine_id = 32,
+        .banner_name = "SPARCstation 5",
+        .model = "SUNW,501-3059",
+        .name = "SUNW,SPARCstation-5",
+        .mid_offset = 0,
+        .initfn = dummy_mach_init,
+    },
+    {
+        .machine_id = 64,
+        .banner_name = "SPARCstation 10 (1 X 390Z55)",
+        .model = "SUNW,S10,501-2365",
+        .name = "SUNW,SPARCstation-10",
+        .mid_offset = 8,
+        .initfn = ob_eccmemctl_init,
+    },
+    {
+        .machine_id = 65,
+        .banner_name = "SPARCstation 20 (1 X 390Z55)",
+        .model = "SUNW,S20,501-2324",
+        .name = "SUNW,SPARCstation-20",
+        .mid_offset = 8,
+        .initfn = ob_eccmemctl_init,
+    },
+    {
+        .machine_id = 66,
+        .banner_name = "SPARCsystem 600(1 X 390Z55)",
+        .model = NULL,
+        .name = "SUNW,SPARCsystem-600",
+        .mid_offset = 8,
+        .initfn = ob_eccmemctl_init,
+    },
+};
+
+static const struct machdef *
+id_machine(uint16_t machine_id)
+{
+    unsigned int i;
+
+    for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
+        if (machine_id == sun4m_defs[i].machine_id)
+            return &sun4m_defs[i];
+    }
+    printk("Unknown machine (ID %d), freezing!\n", machine_id);
+    for (;;);
+}
+
 static void
 ob_nvram_init(uint64_t base, uint64_t offset)
 {
@@ -732,9 +793,14 @@
     unsigned int i;
     char nographic;
     uint32_t size;
-    unsigned int machine_id;
+    uint16_t machine_id;
     const struct cpudef *cpu;
+    const struct machdef *mach;
     ohwcfg_v3_t *header;
+    volatile uint8_t *fw_cfg_data;
+    volatile uint16_t *fw_cfg_cmd;
+    char buf[256];
+    uint32_t temp;
 
     ob_new_obio_device("eeprom", NULL);
 
@@ -745,17 +811,30 @@
     push_str("address");
     fword("property");
 
-    memcpy(&nv_info, nvram, sizeof(nv_info));
-    machine_id = (unsigned int)nvram[0x1fd9] & 0xff;
-    printk("Nvram id %s, version %d, machine id 0x%2.2x\n",
-           nv_info.struct_ident, nv_info.struct_version, machine_id);
-    if (strcmp(nv_info.struct_ident, "QEMU_BIOS") ||
-        nv_info.struct_version != 3 ||
-        OHW_compute_crc(&nv_info, 0x00, 0xF8) != nv_info.crc) {
-        printk("Unknown nvram, freezing!\n");
-        for (;;);
-    }
+    fw_cfg_cmd = map_io(CFG_ADDR, CFG_SIZE);
+    fw_cfg_data = (uint8_t *)fw_cfg_cmd + 2;
+
+    *fw_cfg_cmd = FW_CFG_SIGNATURE;
+    for (i = 0; i < 4; i++)
+        buf[i] = *fw_cfg_data;
+    buf[4] = '\0';
+    printk("Configuration device id %s", buf);
+
+    *fw_cfg_cmd = FW_CFG_ID;
+    for (i = 0; i < 4; i++)
+        buf[i] = *fw_cfg_data;
+
+    temp = __le32_to_cpu(*(uint32_t *)buf);
+    printk(" version %d", temp);
+
+    *fw_cfg_cmd = FW_CFG_MACHINE_ID;
+    for (i = 0; i < 2; i++)
+        buf[i] = *fw_cfg_data;
 
+    machine_id = __le16_to_cpu(*(uint16_t *)buf);
+    printk(" machine id %d\n", machine_id);
+
+    memcpy(&nv_info, nvram, sizeof(nv_info));
     kernel_image = nv_info.kernel_image;
     kernel_size = nv_info.kernel_size;
     size = nv_info.cmdline_size;
@@ -772,8 +851,10 @@
     header->crc = OHW_compute_crc(header, 0x00, 0xF8);
 
     boot_device = nv_info.boot_devices[0];
-    nographic = nv_info.graphic_flags & OHW_GF_NOGRAPHICS;
-    graphic_depth = nv_info.depth;
+    *fw_cfg_cmd = FW_CFG_NOGRAPHIC;
+    nographic = *fw_cfg_data;
+    *fw_cfg_cmd = FW_CFG_SUN4M_DEPTH;
+    graphic_depth = *fw_cfg_data;
 
     push_str("mk48t08");
     fword("model");
@@ -790,74 +871,37 @@
     push_str("idprom");
     fword("property");
 
-    switch (machine_id) {
-    case 0x71:
-        push_str("SPARCsystem 600(1 X 390Z55)");
-        fword("encode-string");
-        push_str("banner-name");
-        fword("property");
-        push_str("SUNW,SPARCsystem-600");
-        fword("encode-string");
-        push_str("name");
-        fword("property");
-        ob_eccmemctl_init();
-        break;
-    case 0x72:
-        switch (ob_eccmemctl_init()) {
-        default:
-        case 0x10000000:
-            push_str("SPARCstation 10 (1 X 390Z55)");
-            fword("encode-string");
-            push_str("banner-name");
-            fword("property");
-            push_str("SUNW,S10,501-2365");
-            fword("encode-string");
-            push_str("model");
-            fword("property");
-            push_str("SUNW,SPARCstation-10");
-            fword("encode-string");
-            push_str("name");
-            fword("property");
-            break;
-        case 0x20000000:
-            push_str("SPARCstation 20 (1 X 390Z55)");
-            fword("encode-string");
-            push_str("banner-name");
-            fword("property");
-            push_str("SUNW,S20,501-2324");
-            fword("encode-string");
-            push_str("model");
-            fword("property");
-            push_str("SUNW,SPARCstation-20");
-            fword("encode-string");
-            push_str("name");
-            fword("property");
-            break;
-        }
-        break;
-    case 0x80:
-        push_str("SPARCstation 5");
-        fword("encode-string");
-        push_str("banner-name");
-        fword("property");
-        push_str("SUNW,501-3059");
+    mach = id_machine(machine_id);
+
+    mach->initfn();
+
+    push_str(mach->banner_name);
+    fword("encode-string");
+    push_str("banner-name");
+    fword("property");
+
+    if (mach->model) {
+        push_str(mach->model);
         fword("encode-string");
         push_str("model");
         fword("property");
-        push_str("SUNW,SPARCstation-5");
-        fword("encode-string");
-        push_str("name");
-        fword("property");
-        break;
-    default:
-        printk("Unknown machine, freezing!\n");
-        for (;;);
     }
+    push_str(mach->name);
+    fword("encode-string");
+    push_str("name");
+    fword("property");
+
     // Add cpus
-    printk("CPUs: %x", nv_info.nb_cpus);
+    *fw_cfg_cmd = FW_CFG_NB_CPUS;
+    for (i = 0; i < 4; i++)
+        buf[i] = *fw_cfg_data;
+
+    temp = __le32_to_cpu(*(uint32_t *)buf);
+
+    printk("CPUs: %x", temp);
     cpu = id_cpu();
     printk(" x %s\n", cpu->name);
-    for (i = 0; i < (unsigned int)nv_info.nb_cpus; i++) {
+    for (i = 0; i < temp; i++) {
         push_str("/");
         fword("find-device");
 
@@ -959,15 +1003,7 @@
         push_str("cache-coherence?");
         fword("property");
 
-        switch (machine_id) {
-        case 0x71:
-        case 0x72:
-            PUSH(i + 8);
-            break;
-        case 0x80:
-            PUSH(i);
-            break;
-        }
+        PUSH(i + mach->mid_offset);
         fword("encode-int");
         push_str("mid");
         fword("property");
Index: openbios-quilt/drivers/obio.h
===================================================================
--- openbios-quilt.orig/drivers/obio.h	2008-09-02 15:33:04.000000000 +0000
+++ openbios-quilt/drivers/obio.h	2008-09-11 18:06:33.000000000 +0000
@@ -38,6 +38,10 @@
 #define SUN4M_NCPUS      16
 #define PAGE_SIZE        4096
 
+#define CFG_ADDR         0xd00000510ULL
+#define CFG_SIZE         3
+#define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
+
 /* linux/include/asm-sparc/timer.h */
 
 /* A sun4m has two blocks of registers which are probably of the same
Index: openbios-quilt/drivers/sbus.c
===================================================================
--- openbios-quilt.orig/drivers/sbus.c	2008-09-02 15:33:04.000000000 +0000
+++ openbios-quilt/drivers/sbus.c	2008-09-11 17:49:59.000000000 +0000
@@ -571,11 +571,11 @@
     ob_sbus_node_init(base);
 
     switch (machine_id) {
-    case 0x71:
+    case 66:
         return ob_sbus_init_ss600mp();
-    case 0x72:
+    case 64 ... 65:
         return ob_sbus_init_ss10();
-    case 0x80:
+    case 32 ... 63:
         return ob_sbus_init_ss5();
     default:
         return -1;
