qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] PMAC NVRAM cleanup
@ 2008-05-01 11:41 Laurent Vivier
  2008-05-01 14:49 ` Blue Swirl
  2008-08-24 19:20 ` Andreas Färber
  0 siblings, 2 replies; 4+ messages in thread
From: Laurent Vivier @ 2008-05-01 11:41 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 372 bytes --]

Hi,

I'm trying to boot openbios on PPC target (for the moment I'm only  
able to load yaboot).

This patch is a cleanup of PMAC nvram.

It stores nvram in a file and create valid partitions.

This doesn't break OpenHackware.

Regards,
Laurent
----------------------- Laurent Vivier ----------------------
"The best way to predict the future is to invent it."
- Alan Kay


[-- Attachment #2: 0001-PowerMac-NVRAM-cleanup.patch --]
[-- Type: application/octet-stream, Size: 8135 bytes --]

From 545b62d971c549155a03b6540536069ad9f9bcca Mon Sep 17 00:00:00 2001
From: Laurent Vivier <Laurent@lvivier.info>
Date: Thu, 1 May 2008 12:25:18 +0200
Subject: [PATCH] PowerMac NVRAM cleanup

---
 hw/mac_nvram.c    |  151 ++++++++++++++++++++++++++++++++++++++++++++--------
 hw/ppc_mac.h      |    4 +-
 hw/ppc_oldworld.c |    4 +-
 3 files changed, 131 insertions(+), 28 deletions(-)

diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index 7304ac2..366cd62 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -25,11 +25,25 @@
 #include "hw.h"
 #include "ppc_mac.h"
 
+#define DEF_SYSTEM_SIZE 0xc10
+
+#define NV_SIG_SYSTEM   0x70
+#define NV_SIG_FREE     0x7f
+
+#define NV_NAME_LEN     12
+
+#define NV_SIGNATURE    0
+#define NV_CHECKSUM     1
+#define NV_LEN          2
+#define NV_NAME         4
+#define NV_DATA         16
+
 struct MacIONVRAMState {
     target_phys_addr_t mem_base;
-    target_phys_addr_t size;
+    uint32_t size;
+    QEMUFile *file;
     int mem_index;
-    uint8_t data[0x2000];
+    uint8_t data[NVRAM_SIZE];
 };
 
 /* Direct access to NVRAM */
@@ -39,7 +53,7 @@ uint32_t macio_nvram_read (void *opaque, uint32_t addr)
     uint32_t ret;
 
     //    printf("%s: %p addr %04x\n", __func__, s, addr);
-    if (addr < 0x2000)
+    if (addr < NVRAM_SIZE)
         ret = s->data[addr];
     else
         ret = -1;
@@ -52,7 +66,7 @@ void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val)
     MacIONVRAMState *s = opaque;
 
     //    printf("%s: %p addr %04x val %02x\n", __func__, s, addr, val);
-    if (addr < 0x2000)
+    if (addr < NVRAM_SIZE)
         s->data[addr] = val;
 }
 
@@ -63,9 +77,14 @@ static void macio_nvram_writeb (void *opaque,
     MacIONVRAMState *s = opaque;
 
     addr -= s->mem_base;
-    addr = (addr >> 4) & 0x1fff;
+    addr = (addr >> 4) & (NVRAM_SIZE-1);
     s->data[addr] = value;
     //    printf("macio_nvram_writeb %04x = %02x\n", addr, value);
+    if (s->file) {
+        qemu_fseek(s->file, addr, SEEK_SET);
+        qemu_put_byte(s->file, value);
+        qemu_fflush(s->file);
+    }
 }
 
 static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
@@ -74,7 +93,7 @@ static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
     uint32_t value;
 
     addr -= s->mem_base;
-    addr = (addr >> 4) & 0x1fff;
+    addr = (addr >> 4) & (NVRAM_SIZE-1);
     value = s->data[addr];
     //    printf("macio_nvram_readb %04x = %02x\n", addr, value);
 
@@ -93,17 +112,32 @@ static CPUReadMemoryFunc *nvram_read[] = {
     &macio_nvram_readb,
 };
 
-MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size)
+MacIONVRAMState *macio_nvram_init (int *mem_index, const char *filename)
 {
     MacIONVRAMState *s;
+    QEMUFile *file;
 
     s = qemu_mallocz(sizeof(MacIONVRAMState));
     if (!s)
         return NULL;
-    s->size = size;
+    s->size = NVRAM_SIZE << 4;
     s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
     *mem_index = s->mem_index;
 
+    /* Read current file */
+    file = qemu_fopen(filename, "rb");
+    if (file) {
+        /* Read nvram contents */
+        qemu_get_buffer(file, s->data, s->size >> 4);
+        qemu_fclose(file);
+    }
+    s->file = qemu_fopen(filename, "wb");
+    if (s->file) {
+        /* Write back contents, as 'wb' mode cleaned the file */
+        qemu_put_buffer(s->file, s->data, s->size >> 4);
+        qemu_fflush(s->file);
+    }
+
     return s;
 }
 
@@ -116,26 +150,95 @@ void macio_nvram_map (void *opaque, target_phys_addr_t mem_base)
     cpu_register_physical_memory(mem_base, s->size, s->mem_index);
 }
 
-static uint8_t nvram_chksum (const uint8_t *buf, int n)
+static uint8_t nvram_chksum (const uint8_t *buf)
 {
     int sum, i;
-    sum = 0;
-    for(i = 0; i < n; i++)
+    sum = buf[0];
+    for(i = 2; i < 16; i++) {
         sum += buf[i];
-    return (sum & 0xff) + (sum >> 8);
+    if (sum > 255)
+        sum = (sum - 256 + 1) & 0xff;
+    }
+    return sum;
+}
+
+static inline uint16_t nvram_readw(uint8_t *addr)
+{
+    return ((*addr) << 8) + *(addr + 1);
+}
+
+static inline void nvram_writew(uint8_t *addr, uint16_t val)
+{
+    *addr = val >> 8;
+    *(addr + 1) = val;
+}
+
+static void nvram_set_header(MacIONVRAMState *nvr,
+                             uint32_t addr,
+                             uint8_t signature,
+                             uint16_t size,
+                             char* name)
+{
+    uint8_t *buf = nvr->data;
+
+    memset(buf + addr, 0, NV_DATA);
+    buf[addr + NV_SIGNATURE] = signature;
+    strncpy(buf + addr + NV_NAME, name, NV_NAME_LEN);
+    nvram_writew(buf + addr + NV_LEN, size >> 4);
+    buf[addr + NV_CHECKSUM] = nvram_chksum(buf + addr);
+}
+
+static void create_free_part(MacIONVRAMState *nvr, uint32_t addr, int size )
+{
+    nvram_set_header(nvr, addr, NV_SIG_FREE, size, "777777777777");
+}
+
+static int
+next_nvpart(MacIONVRAMState *nvr, uint32_t *addr, uint32_t end)
+{
+    uint8_t *buf = nvr->data;
+        int len;
+
+        len = nvram_readw(buf + *addr + NV_LEN);
+        if (len == 0)
+                return 1;
+
+        *addr = (*addr) + len;
+        if( *addr < end )
+                return 1;
+        if( *addr == end )
+                return 0;
+        return -1;
+}
+
+static int create_nv_part(MacIONVRAMState *nvr, uint32_t base, int max_size,
+                          int signature, char *name, int size )
+{
+    uint8_t *buf = nvr->data;
+    uint32_t addr = base;
+    uint32_t end = base + max_size;
+    int len;
+
+     do {
+        if (buf[addr + NV_SIGNATURE] != NV_SIG_FREE)
+            continue;
+
+        len = nvram_readw(buf + addr + NV_LEN) << 4;
+        if (len < size)
+            size = len;
+
+        nvram_set_header(nvr, addr, signature, size, name);
+        if (len > size)
+            create_free_part(nvr, addr + size, len - size);
+        return size;
+    } while (next_nvpart(nvr, &addr, end) > 0 );
+    return -1;
 }
 
-/* set a free Mac OS NVRAM partition */
-void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
+/* set a system Mac OS NVRAM partition */
+void pmac_format_nvram_partition (MacIONVRAMState *nvr)
 {
-    uint8_t *buf;
-    char partition_name[12] = "wwwwwwwwwwww";
-
-    buf = nvr->data;
-    buf[0] = 0x7f; /* free partition magic */
-    buf[1] = 0; /* checksum */
-    buf[2] = len >> 8;
-    buf[3] = len;
-    memcpy(buf + 4, partition_name, 12);
-    buf[1] = nvram_chksum(buf, 16);
+    create_free_part(nvr, 0, sizeof(nvr->data));
+    create_nv_part(nvr, 0, sizeof(nvr->data),
+                   NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE);
 }
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index 3a26cde..5dd727d 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -62,9 +62,9 @@ PCIBus *pci_pmac_init(qemu_irq *pic);
 /* Mac NVRAM */
 typedef struct MacIONVRAMState MacIONVRAMState;
 
-MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size);
+MacIONVRAMState *macio_nvram_init (int *mem_index, const char *filename);
 void macio_nvram_map (void *opaque, target_phys_addr_t mem_base);
-void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
+void pmac_format_nvram_partition (MacIONVRAMState *nvr);
 uint32_t macio_nvram_read (void *opaque, uint32_t addr);
 void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
 
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 6b4f202..41f1128 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -334,8 +334,8 @@ static void ppc_heathrow_init (int ram_size, int vga_ram_size,
     adb_kbd_init(&adb_bus);
     adb_mouse_init(&adb_bus);
 
-    nvr = macio_nvram_init(&nvram_mem_index, 0x2000);
-    pmac_format_nvram_partition(nvr, 0x2000);
+    nvr = macio_nvram_init(&nvram_mem_index, "g3bw_nvram");
+    pmac_format_nvram_partition(nvr);
 
     dbdma_init(&dbdma_mem_index);
 
-- 
1.5.5


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





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

end of thread, other threads:[~2008-08-24 19:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-01 11:41 [Qemu-devel] [PATCH] PMAC NVRAM cleanup Laurent Vivier
2008-05-01 14:49 ` Blue Swirl
2008-05-01 15:56   ` Laurent Vivier
2008-08-24 19:20 ` Andreas Färber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).