diff options
-rw-r--r-- | hw/sun4m.c | 61 | ||||
-rw-r--r-- | hw/sun4u.c | 52 | ||||
-rw-r--r-- | qemu-doc.texi | 9 | ||||
-rw-r--r-- | vl.c | 21 | ||||
-rw-r--r-- | vl.h | 6 |
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 @@ -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 } } } @@ -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) |