summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/sun4m.c61
-rw-r--r--hw/sun4u.c52
-rw-r--r--qemu-doc.texi9
-rw-r--r--vl.c21
-rw-r--r--vl.h6
5 files changed, 144 insertions, 5 deletions
diff --git a/hw/sun4m.c b/hw/sun4m.c
index c24e52aadd..ae9222af1e 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -117,6 +117,34 @@ static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
     m48t59_write(nvram, addr + max - 1, '\0');
 }
 
+static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
+                                const unsigned char *str)
+{
+    uint32_t len;
+
+    len = strlen(str) + 1;
+    nvram_set_string(nvram, addr, str, len);
+
+    return addr + len;
+}
+
+static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
+                                    uint32_t end)
+{
+    unsigned int i, sum;
+
+    // Length divided by 16
+    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
+    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
+    // Checksum
+    sum = m48t59_read(nvram, start);
+    for (i = 0; i < 14; i++) {
+        sum += m48t59_read(nvram, start + 2 + i);
+        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
+    }
+    m48t59_write(nvram, start + 1, sum & 0xff);
+}
+
 static m48t59_t *nvram;
 
 extern int nographic;
@@ -128,7 +156,8 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
                        int machine_id)
 {
     unsigned char tmp = 0;
-    int i, j;
+    unsigned int i, j;
+    uint32_t start, end;
 
     // Try to match PPC NVRAM
     nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
@@ -151,8 +180,30 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
     nvram_set_word(nvram,   0x56, height);
     nvram_set_word(nvram,   0x58, depth);
 
+    // OpenBIOS nvram variables
+    // Variable partition
+    start = 252;
+    m48t59_write(nvram, start, 0x70);
+    nvram_set_string(nvram, start + 4, "system", 12);
+
+    end = start + 16;
+    for (i = 0; i < nb_prom_envs; i++)
+        end = nvram_set_var(nvram, end, prom_envs[i]);
+
+    m48t59_write(nvram, end++ , 0);
+    end = start + ((end - start + 15) & ~15);
+    nvram_finish_partition(nvram, start, end);
+
+    // free partition
+    start = end;
+    m48t59_write(nvram, start, 0x7f);
+    nvram_set_string(nvram, start + 4, "free", 12);
+
+    end = 0x1fd0;
+    nvram_finish_partition(nvram, start, end);
+
     // Sun4m specific use
-    i = 0x1fd8;
+    start = i = 0x1fd8;
     m48t59_write(nvram, i++, 0x01);
     m48t59_write(nvram, i++, machine_id);
     j = 0;
@@ -164,10 +215,10 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
     m48t59_write(nvram, i, macaddr[j]);
 
     /* Calculate checksum */
-    for (i = 0x1fd8; i < 0x1fe7; i++) {
-	tmp ^= m48t59_read(nvram, i);
+    for (i = start; i < start + 15; i++) {
+        tmp ^= m48t59_read(nvram, i);
     }
-    m48t59_write(nvram, 0x1fe7, tmp);
+    m48t59_write(nvram, start + 15, tmp);
 }
 
 static void *slavio_intctl;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index b10722f6e6..952beff3cd 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -170,6 +170,34 @@ uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
     return crc;
 }
 
+static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
+                                const unsigned char *str)
+{
+    uint32_t len;
+
+    len = strlen(str) + 1;
+    NVRAM_set_string(nvram, addr, str, len);
+
+    return addr + len;
+}
+
+static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
+                                    uint32_t end)
+{
+    unsigned int i, sum;
+
+    // Length divided by 16
+    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
+    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
+    // Checksum
+    sum = m48t59_read(nvram, start);
+    for (i = 0; i < 14; i++) {
+        sum += m48t59_read(nvram, start + 2 + i);
+        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
+    }
+    m48t59_write(nvram, start + 1, sum & 0xff);
+}
+
 extern int nographic;
 
 int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
@@ -182,6 +210,8 @@ int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                           int width, int height, int depth)
 {
     uint16_t crc;
+    unsigned int i;
+    uint32_t start, end;
 
     /* Set parameters for Open Hack'Ware BIOS */
     NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
@@ -212,6 +242,28 @@ int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
     crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
     NVRAM_set_word(nvram,  0xFC, crc);
 
+    // OpenBIOS nvram variables
+    // Variable partition
+    start = 252;
+    m48t59_write(nvram, start, 0x70);
+    NVRAM_set_string(nvram, start + 4, "system", 12);
+
+    end = start + 16;
+    for (i = 0; i < nb_prom_envs; i++)
+        end = nvram_set_var(nvram, end, prom_envs[i]);
+
+    m48t59_write(nvram, end++ , 0);
+    end = start + ((end - start + 15) & ~15);
+    nvram_finish_partition(nvram, start, end);
+
+    // free partition
+    start = end;
+    m48t59_write(nvram, start, 0x7f);
+    NVRAM_set_string(nvram, start + 4, "free", 12);
+
+    end = 0x1fd0;
+    nvram_finish_partition(nvram, start, end);
+
     return 0;
 }
 
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 830a2b6f44..43d34defe9 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -1661,6 +1661,15 @@ The following options are specific to the Sparc emulation:
 
 Set the initial TCX graphic mode. The default is 1024x768.
 
+@item -prom-env string
+
+Set OpenBIOS variables in NVRAM, for example:
+
+@example
+qemu-system-sparc -prom-env 'auto-boot?=false' \
+ -prom-env 'boot-device=sd(0,2,0):d' -prom-env 'boot-args=linux single'
+@end example
+
 @end table
 
 @c man end 
diff --git a/vl.c b/vl.c
index bf8df5dc9b..f4be194680 100644
--- a/vl.c
+++ b/vl.c
@@ -197,6 +197,10 @@ int nb_option_roms;
 int semihosting_enabled = 0;
 int autostart = 1;
 const char *qemu_name;
+#ifdef TARGET_SPARC
+unsigned int nb_prom_envs = 0;
+const char *prom_envs[MAX_PROM_ENVS];
+#endif
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -6530,6 +6534,9 @@ void help(void)
 	   "-daemonize      daemonize QEMU after initializing\n"
 #endif
 	   "-option-rom rom load a file, rom, into the option ROM space\n"
+#ifdef TARGET_SPARC
+           "-prom-env variable=value  set OpenBIOS nvram variables\n"
+#endif
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -6624,6 +6631,7 @@ enum {
     QEMU_OPTION_option_rom,
     QEMU_OPTION_semihosting,
     QEMU_OPTION_name,
+    QEMU_OPTION_prom_env,
 };
 
 typedef struct QEMUOption {
@@ -6721,6 +6729,9 @@ const QEMUOption qemu_options[] = {
     { "semihosting", 0, QEMU_OPTION_semihosting },
 #endif
     { "name", HAS_ARG, QEMU_OPTION_name },
+#if defined(TARGET_SPARC)
+    { "prom-env", HAS_ARG, QEMU_OPTION_prom_env },
+#endif
     { NULL },
 };
 
@@ -7478,6 +7489,16 @@ int main(int argc, char **argv)
             case QEMU_OPTION_name:
                 qemu_name = optarg;
                 break;
+#ifdef TARGET_SPARC
+            case QEMU_OPTION_prom_env:
+                if (nb_prom_envs >= MAX_PROM_ENVS) {
+                    fprintf(stderr, "Too many prom variables\n");
+                    exit(1);
+                }
+                prom_envs[nb_prom_envs] = optarg;
+                nb_prom_envs++;
+                break;
+#endif
             }
         }
     }
diff --git a/vl.h b/vl.h
index 26e72bd7c6..f44eeab5fd 100644
--- a/vl.h
+++ b/vl.h
@@ -169,6 +169,12 @@ extern const char *bootp_filename;
 extern const char *option_rom[MAX_OPTION_ROMS];
 extern int nb_option_roms;
 
+#ifdef TARGET_SPARC
+#define MAX_PROM_ENVS 128
+extern const char *prom_envs[MAX_PROM_ENVS];
+extern unsigned int nb_prom_envs;
+#endif
+
 /* XXX: make it dynamic */
 #define MAX_BIOS_SIZE (4 * 1024 * 1024)
 #if defined (TARGET_PPC) || defined (TARGET_SPARC64)