Commit d2c63fc185f3d126ef177105166a491ab3556f5c
1 parent
57c26279
Update OHW interface to version 3.
Use common ABI description file with OpenBIOS. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3648 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
324 additions
and
254 deletions
hw/firmware_abi.h
0 → 100755
| 1 | +#ifndef FIRMWARE_ABI_H | ||
| 2 | +#define FIRMWARE_ABI_H | ||
| 3 | + | ||
| 4 | +#ifndef __ASSEMBLY__ | ||
| 5 | +/* Open Hack'Ware NVRAM configuration structure */ | ||
| 6 | + | ||
| 7 | +/* Version 3 */ | ||
| 8 | +typedef struct ohwcfg_v3_t ohwcfg_v3_t; | ||
| 9 | +struct ohwcfg_v3_t { | ||
| 10 | + /* 0x00: structure identifier */ | ||
| 11 | + uint8_t struct_ident[0x10]; | ||
| 12 | + /* 0x10: structure version and NVRAM description */ | ||
| 13 | + uint32_t struct_version; | ||
| 14 | + uint16_t nvram_size; | ||
| 15 | + uint16_t pad0; | ||
| 16 | + uint16_t nvram_arch_ptr; | ||
| 17 | + uint16_t nvram_arch_size; | ||
| 18 | + uint16_t nvram_arch_crc; | ||
| 19 | + uint8_t pad1[0x02]; | ||
| 20 | + /* 0x20: host architecture */ | ||
| 21 | + uint8_t arch[0x10]; | ||
| 22 | + /* 0x30: RAM/ROM description */ | ||
| 23 | + uint64_t RAM0_base; | ||
| 24 | + uint64_t RAM0_size; | ||
| 25 | + uint64_t RAM1_base; | ||
| 26 | + uint64_t RAM1_size; | ||
| 27 | + uint64_t RAM2_base; | ||
| 28 | + uint64_t RAM2_size; | ||
| 29 | + uint64_t RAM3_base; | ||
| 30 | + uint64_t RAM3_size; | ||
| 31 | + uint64_t ROM_base; | ||
| 32 | + uint64_t ROM_size; | ||
| 33 | + /* 0x80: Kernel description */ | ||
| 34 | + uint64_t kernel_image; | ||
| 35 | + uint64_t kernel_size; | ||
| 36 | + /* 0x90: Kernel command line */ | ||
| 37 | + uint64_t cmdline; | ||
| 38 | + uint64_t cmdline_size; | ||
| 39 | + /* 0xA0: Kernel boot image */ | ||
| 40 | + uint64_t initrd_image; | ||
| 41 | + uint64_t initrd_size; | ||
| 42 | + /* 0xB0: NVRAM image */ | ||
| 43 | + uint64_t NVRAM_image; | ||
| 44 | + uint8_t pad2[8]; | ||
| 45 | + /* 0xC0: graphic configuration */ | ||
| 46 | + uint16_t width; | ||
| 47 | + uint16_t height; | ||
| 48 | + uint16_t depth; | ||
| 49 | + uint16_t graphic_flags; | ||
| 50 | + /* 0xC8: CPUs description */ | ||
| 51 | + uint8_t nb_cpus; | ||
| 52 | + uint8_t boot_cpu; | ||
| 53 | + uint8_t nboot_devices; | ||
| 54 | + uint8_t pad3[5]; | ||
| 55 | + /* 0xD0: boot devices */ | ||
| 56 | + uint8_t boot_devices[0x10]; | ||
| 57 | + /* 0xE0 */ | ||
| 58 | + uint8_t pad4[0x1C]; /* 28 */ | ||
| 59 | + /* 0xFC: checksum */ | ||
| 60 | + uint16_t crc; | ||
| 61 | + uint8_t pad5[0x02]; | ||
| 62 | +} __attribute__ (( packed )); | ||
| 63 | + | ||
| 64 | +#define OHW_GF_NOGRAPHICS 0x0001 | ||
| 65 | + | ||
| 66 | +static inline uint16_t | ||
| 67 | +OHW_crc_update (uint16_t prev, uint16_t value) | ||
| 68 | +{ | ||
| 69 | + uint16_t tmp; | ||
| 70 | + uint16_t pd, pd1, pd2; | ||
| 71 | + | ||
| 72 | + tmp = prev >> 8; | ||
| 73 | + pd = prev ^ value; | ||
| 74 | + pd1 = pd & 0x000F; | ||
| 75 | + pd2 = ((pd >> 4) & 0x000F) ^ pd1; | ||
| 76 | + tmp ^= (pd1 << 3) | (pd1 << 8); | ||
| 77 | + tmp ^= pd2 | (pd2 << 7) | (pd2 << 12); | ||
| 78 | + | ||
| 79 | + return tmp; | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +static inline uint16_t | ||
| 83 | +OHW_compute_crc (ohwcfg_v3_t *header, uint32_t start, uint32_t count) | ||
| 84 | +{ | ||
| 85 | + uint32_t i; | ||
| 86 | + uint16_t crc = 0xFFFF; | ||
| 87 | + uint8_t *ptr = (uint8_t *)header; | ||
| 88 | + int odd; | ||
| 89 | + | ||
| 90 | + odd = count & 1; | ||
| 91 | + count &= ~1; | ||
| 92 | + for (i = 0; i != count; i++) { | ||
| 93 | + crc = OHW_crc_update(crc, (ptr[start + i] << 8) | ptr[start + i + 1]); | ||
| 94 | + } | ||
| 95 | + if (odd) { | ||
| 96 | + crc = OHW_crc_update(crc, ptr[start + i] << 8); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + return crc; | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +/* Sparc32 runtime NVRAM structure for SMP CPU boot */ | ||
| 103 | +struct sparc_arch_cfg { | ||
| 104 | + uint32_t smp_ctx; | ||
| 105 | + uint32_t smp_ctxtbl; | ||
| 106 | + uint32_t smp_entry; | ||
| 107 | + uint8_t valid; | ||
| 108 | + uint8_t unused[51]; | ||
| 109 | +}; | ||
| 110 | + | ||
| 111 | +/* OpenBIOS NVRAM partition */ | ||
| 112 | +struct OpenBIOS_nvpart_v1 { | ||
| 113 | + uint8_t signature; | ||
| 114 | + uint8_t checksum; | ||
| 115 | + uint16_t len; // BE, length divided by 16 | ||
| 116 | + char name[12]; | ||
| 117 | +}; | ||
| 118 | + | ||
| 119 | +#define OPENBIOS_PART_SYSTEM 0x70 | ||
| 120 | +#define OPENBIOS_PART_FREE 0x7f | ||
| 121 | + | ||
| 122 | +static inline void | ||
| 123 | +OpenBIOS_finish_partition(struct OpenBIOS_nvpart_v1 *header, uint32_t size) | ||
| 124 | +{ | ||
| 125 | + unsigned int i, sum; | ||
| 126 | + uint8_t *tmpptr; | ||
| 127 | + | ||
| 128 | + // Length divided by 16 | ||
| 129 | + header->len = cpu_to_be16(size >> 4); | ||
| 130 | + | ||
| 131 | + // Checksum | ||
| 132 | + tmpptr = (uint8_t *)header; | ||
| 133 | + sum = *tmpptr; | ||
| 134 | + for (i = 0; i < 14; i++) { | ||
| 135 | + sum += tmpptr[2 + i]; | ||
| 136 | + sum = (sum + ((sum & 0xff00) >> 8)) & 0xff; | ||
| 137 | + } | ||
| 138 | + header->checksum = sum & 0xff; | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +static inline uint32_t | ||
| 142 | +OpenBIOS_set_var(uint8_t *nvram, uint32_t addr, const unsigned char *str) | ||
| 143 | +{ | ||
| 144 | + uint32_t len; | ||
| 145 | + | ||
| 146 | + len = strlen(str) + 1; | ||
| 147 | + memcpy(&nvram[addr], str, len); | ||
| 148 | + | ||
| 149 | + return addr + len; | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +/* Sun IDPROM structure at the end of NVRAM */ | ||
| 153 | +struct Sun_nvram { | ||
| 154 | + uint8_t type; | ||
| 155 | + uint8_t machine_id; | ||
| 156 | + uint8_t macaddr[6]; | ||
| 157 | + uint8_t unused[7]; | ||
| 158 | + uint8_t checksum; | ||
| 159 | +}; | ||
| 160 | + | ||
| 161 | +static inline void | ||
| 162 | +Sun_init_header(struct Sun_nvram *header, const uint8_t *macaddr, int machine_id) | ||
| 163 | +{ | ||
| 164 | + uint8_t tmp, *tmpptr; | ||
| 165 | + unsigned int i; | ||
| 166 | + | ||
| 167 | + header->type = 1; | ||
| 168 | + header->machine_id = machine_id & 0xff; | ||
| 169 | + memcpy(&header->macaddr, macaddr, 6); | ||
| 170 | + /* Calculate checksum */ | ||
| 171 | + tmp = 0; | ||
| 172 | + tmpptr = (uint8_t *)header; | ||
| 173 | + for (i = 0; i < 15; i++) | ||
| 174 | + tmp ^= tmpptr[i]; | ||
| 175 | + | ||
| 176 | + header->checksum = tmp; | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +#else /* __ASSEMBLY__ */ | ||
| 180 | + | ||
| 181 | +/* Structure offsets for asm use */ | ||
| 182 | + | ||
| 183 | +/* Open Hack'Ware NVRAM configuration structure */ | ||
| 184 | +#define OHW_ARCH_PTR 0x18 | ||
| 185 | +#define OHW_RAM_SIZE 0x38 | ||
| 186 | +#define OHW_BOOT_CPU 0xC9 | ||
| 187 | + | ||
| 188 | +/* Sparc32 runtime NVRAM structure for SMP CPU boot */ | ||
| 189 | +#define SPARC_SMP_CTX 0x0 | ||
| 190 | +#define SPARC_SMP_CTXTBL 0x4 | ||
| 191 | +#define SPARC_SMP_ENTRY 0x8 | ||
| 192 | +#define SPARC_SMP_VALID 0xc | ||
| 193 | + | ||
| 194 | +/* Sun IDPROM structure at the end of NVRAM */ | ||
| 195 | +#define SPARC_MACHINE_ID 0x1fd9 | ||
| 196 | + | ||
| 197 | +#endif /* __ASSEMBLY__ */ | ||
| 198 | +#endif /* FIRMWARE_ABI_H */ |
hw/sun4m.c
| @@ -22,6 +22,9 @@ | @@ -22,6 +22,9 @@ | ||
| 22 | * THE SOFTWARE. | 22 | * THE SOFTWARE. |
| 23 | */ | 23 | */ |
| 24 | #include "vl.h" | 24 | #include "vl.h" |
| 25 | +#include "m48t59.h" | ||
| 26 | +#include "firmware_abi.h" | ||
| 27 | + | ||
| 25 | //#define DEBUG_IRQ | 28 | //#define DEBUG_IRQ |
| 26 | 29 | ||
| 27 | /* | 30 | /* |
| @@ -102,131 +105,87 @@ void DMA_register_channel (int nchan, | @@ -102,131 +105,87 @@ void DMA_register_channel (int nchan, | ||
| 102 | { | 105 | { |
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | -static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value) | ||
| 106 | -{ | ||
| 107 | - m48t59_write(nvram, addr++, (value >> 8) & 0xff); | ||
| 108 | - m48t59_write(nvram, addr++, value & 0xff); | ||
| 109 | -} | ||
| 110 | - | ||
| 111 | -static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value) | ||
| 112 | -{ | ||
| 113 | - m48t59_write(nvram, addr++, value >> 24); | ||
| 114 | - m48t59_write(nvram, addr++, (value >> 16) & 0xff); | ||
| 115 | - m48t59_write(nvram, addr++, (value >> 8) & 0xff); | ||
| 116 | - m48t59_write(nvram, addr++, value & 0xff); | ||
| 117 | -} | ||
| 118 | - | ||
| 119 | -static void nvram_set_string (m48t59_t *nvram, uint32_t addr, | ||
| 120 | - const unsigned char *str, uint32_t max) | ||
| 121 | -{ | ||
| 122 | - unsigned int i; | ||
| 123 | - | ||
| 124 | - for (i = 0; i < max && str[i] != '\0'; i++) { | ||
| 125 | - m48t59_write(nvram, addr + i, str[i]); | ||
| 126 | - } | ||
| 127 | - m48t59_write(nvram, addr + max - 1, '\0'); | ||
| 128 | -} | ||
| 129 | - | ||
| 130 | -static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr, | ||
| 131 | - const unsigned char *str) | ||
| 132 | -{ | ||
| 133 | - uint32_t len; | ||
| 134 | - | ||
| 135 | - len = strlen(str) + 1; | ||
| 136 | - nvram_set_string(nvram, addr, str, len); | ||
| 137 | - | ||
| 138 | - return addr + len; | ||
| 139 | -} | ||
| 140 | - | ||
| 141 | -static void nvram_finish_partition (m48t59_t *nvram, uint32_t start, | ||
| 142 | - uint32_t end) | ||
| 143 | -{ | ||
| 144 | - unsigned int i, sum; | ||
| 145 | - | ||
| 146 | - // Length divided by 16 | ||
| 147 | - m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff); | ||
| 148 | - m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff); | ||
| 149 | - // Checksum | ||
| 150 | - sum = m48t59_read(nvram, start); | ||
| 151 | - for (i = 0; i < 14; i++) { | ||
| 152 | - sum += m48t59_read(nvram, start + 2 + i); | ||
| 153 | - sum = (sum + ((sum & 0xff00) >> 8)) & 0xff; | ||
| 154 | - } | ||
| 155 | - m48t59_write(nvram, start + 1, sum & 0xff); | ||
| 156 | -} | ||
| 157 | - | ||
| 158 | extern int nographic; | 108 | extern int nographic; |
| 159 | 109 | ||
| 160 | static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline, | 110 | static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline, |
| 161 | - const char *boot_device, uint32_t RAM_size, | 111 | + const char *boot_devices, uint32_t RAM_size, |
| 162 | uint32_t kernel_size, | 112 | uint32_t kernel_size, |
| 163 | int width, int height, int depth, | 113 | int width, int height, int depth, |
| 164 | int machine_id) | 114 | int machine_id) |
| 165 | { | 115 | { |
| 166 | - unsigned char tmp = 0; | ||
| 167 | - unsigned int i, j; | 116 | + unsigned int i; |
| 168 | uint32_t start, end; | 117 | uint32_t start, end; |
| 118 | + uint8_t image[0x1ff0]; | ||
| 119 | + ohwcfg_v3_t *header = (ohwcfg_v3_t *)ℑ | ||
| 120 | + struct sparc_arch_cfg *sparc_header; | ||
| 121 | + struct OpenBIOS_nvpart_v1 *part_header; | ||
| 122 | + | ||
| 123 | + memset(image, '\0', sizeof(image)); | ||
| 169 | 124 | ||
| 170 | // Try to match PPC NVRAM | 125 | // Try to match PPC NVRAM |
| 171 | - nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16); | ||
| 172 | - nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */ | ||
| 173 | - // NVRAM_size, arch not applicable | ||
| 174 | - m48t59_write(nvram, 0x2D, smp_cpus & 0xff); | ||
| 175 | - m48t59_write(nvram, 0x2E, 0); | ||
| 176 | - m48t59_write(nvram, 0x2F, nographic & 0xff); | ||
| 177 | - nvram_set_lword(nvram, 0x30, RAM_size); | ||
| 178 | - m48t59_write(nvram, 0x34, boot_device[0] & 0xff); | ||
| 179 | - nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR); | ||
| 180 | - nvram_set_lword(nvram, 0x3C, kernel_size); | 126 | + strcpy(header->struct_ident, "QEMU_BIOS"); |
| 127 | + header->struct_version = cpu_to_be32(3); /* structure v3 */ | ||
| 128 | + | ||
| 129 | + header->nvram_size = cpu_to_be16(0x2000); | ||
| 130 | + header->nvram_arch_ptr = cpu_to_be16(sizeof(ohwcfg_v3_t)); | ||
| 131 | + header->nvram_arch_size = cpu_to_be16(sizeof(struct sparc_arch_cfg)); | ||
| 132 | + strcpy(header->arch, "sun4m"); | ||
| 133 | + header->nb_cpus = smp_cpus & 0xff; | ||
| 134 | + header->RAM0_base = 0; | ||
| 135 | + header->RAM0_size = cpu_to_be64((uint64_t)RAM_size); | ||
| 136 | + strcpy(header->boot_devices, boot_devices); | ||
| 137 | + header->nboot_devices = strlen(boot_devices) & 0xff; | ||
| 138 | + header->kernel_image = cpu_to_be64((uint64_t)KERNEL_LOAD_ADDR); | ||
| 139 | + header->kernel_size = cpu_to_be64((uint64_t)kernel_size); | ||
| 181 | if (cmdline) { | 140 | if (cmdline) { |
| 182 | strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); | 141 | strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); |
| 183 | - nvram_set_lword(nvram, 0x40, CMDLINE_ADDR); | ||
| 184 | - nvram_set_lword(nvram, 0x44, strlen(cmdline)); | 142 | + header->cmdline = cpu_to_be64((uint64_t)CMDLINE_ADDR); |
| 143 | + header->cmdline_size = cpu_to_be64((uint64_t)strlen(cmdline)); | ||
| 185 | } | 144 | } |
| 186 | - // initrd_image, initrd_size passed differently | ||
| 187 | - nvram_set_word(nvram, 0x54, width); | ||
| 188 | - nvram_set_word(nvram, 0x56, height); | ||
| 189 | - nvram_set_word(nvram, 0x58, depth); | 145 | + // XXX add initrd_image, initrd_size |
| 146 | + header->width = cpu_to_be16(width); | ||
| 147 | + header->height = cpu_to_be16(height); | ||
| 148 | + header->depth = cpu_to_be16(depth); | ||
| 149 | + if (nographic) | ||
| 150 | + header->graphic_flags = cpu_to_be16(OHW_GF_NOGRAPHICS); | ||
| 151 | + | ||
| 152 | + header->crc = cpu_to_be16(OHW_compute_crc(header, 0x00, 0xF8)); | ||
| 153 | + | ||
| 154 | + // Architecture specific header | ||
| 155 | + start = sizeof(ohwcfg_v3_t); | ||
| 156 | + sparc_header = (struct sparc_arch_cfg *)&image[start]; | ||
| 157 | + sparc_header->valid = 0; | ||
| 158 | + start += sizeof(struct sparc_arch_cfg); | ||
| 190 | 159 | ||
| 191 | // OpenBIOS nvram variables | 160 | // OpenBIOS nvram variables |
| 192 | // Variable partition | 161 | // Variable partition |
| 193 | - start = 252; | ||
| 194 | - m48t59_write(nvram, start, 0x70); | ||
| 195 | - nvram_set_string(nvram, start + 4, "system", 12); | 162 | + part_header = (struct OpenBIOS_nvpart_v1 *)&image[start]; |
| 163 | + part_header->signature = OPENBIOS_PART_SYSTEM; | ||
| 164 | + strcpy(part_header->name, "system"); | ||
| 196 | 165 | ||
| 197 | - end = start + 16; | 166 | + end = start + sizeof(struct OpenBIOS_nvpart_v1); |
| 198 | for (i = 0; i < nb_prom_envs; i++) | 167 | for (i = 0; i < nb_prom_envs; i++) |
| 199 | - end = nvram_set_var(nvram, end, prom_envs[i]); | 168 | + end = OpenBIOS_set_var(image, end, prom_envs[i]); |
| 169 | + | ||
| 170 | + // End marker | ||
| 171 | + image[end++] = '\0'; | ||
| 200 | 172 | ||
| 201 | - m48t59_write(nvram, end++ , 0); | ||
| 202 | end = start + ((end - start + 15) & ~15); | 173 | end = start + ((end - start + 15) & ~15); |
| 203 | - nvram_finish_partition(nvram, start, end); | 174 | + OpenBIOS_finish_partition(part_header, end - start); |
| 204 | 175 | ||
| 205 | // free partition | 176 | // free partition |
| 206 | start = end; | 177 | start = end; |
| 207 | - m48t59_write(nvram, start, 0x7f); | ||
| 208 | - nvram_set_string(nvram, start + 4, "free", 12); | 178 | + part_header = (struct OpenBIOS_nvpart_v1 *)&image[start]; |
| 179 | + part_header->signature = OPENBIOS_PART_FREE; | ||
| 180 | + strcpy(part_header->name, "free"); | ||
| 209 | 181 | ||
| 210 | end = 0x1fd0; | 182 | end = 0x1fd0; |
| 211 | - nvram_finish_partition(nvram, start, end); | ||
| 212 | - | ||
| 213 | - // Sun4m specific use | ||
| 214 | - start = i = 0x1fd8; | ||
| 215 | - m48t59_write(nvram, i++, 0x01); | ||
| 216 | - m48t59_write(nvram, i++, machine_id); | ||
| 217 | - j = 0; | ||
| 218 | - m48t59_write(nvram, i++, macaddr[j++]); | ||
| 219 | - m48t59_write(nvram, i++, macaddr[j++]); | ||
| 220 | - m48t59_write(nvram, i++, macaddr[j++]); | ||
| 221 | - m48t59_write(nvram, i++, macaddr[j++]); | ||
| 222 | - m48t59_write(nvram, i++, macaddr[j++]); | ||
| 223 | - m48t59_write(nvram, i, macaddr[j]); | ||
| 224 | - | ||
| 225 | - /* Calculate checksum */ | ||
| 226 | - for (i = start; i < start + 15; i++) { | ||
| 227 | - tmp ^= m48t59_read(nvram, i); | ||
| 228 | - } | ||
| 229 | - m48t59_write(nvram, start + 15, tmp); | 183 | + OpenBIOS_finish_partition(part_header, end - start); |
| 184 | + | ||
| 185 | + Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, machine_id); | ||
| 186 | + | ||
| 187 | + for (i = 0; i < sizeof(image); i++) | ||
| 188 | + m48t59_write(nvram, i, image[i]); | ||
| 230 | } | 189 | } |
| 231 | 190 | ||
| 232 | static void *slavio_intctl; | 191 | static void *slavio_intctl; |
hw/sun4u.c
| @@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
| 23 | */ | 23 | */ |
| 24 | #include "vl.h" | 24 | #include "vl.h" |
| 25 | #include "m48t59.h" | 25 | #include "m48t59.h" |
| 26 | +#include "firmware_abi.h" | ||
| 26 | 27 | ||
| 27 | #define KERNEL_LOAD_ADDR 0x00404000 | 28 | #define KERNEL_LOAD_ADDR 0x00404000 |
| 28 | #define CMDLINE_ADDR 0x003ff000 | 29 | #define CMDLINE_ADDR 0x003ff000 |
| @@ -66,179 +67,91 @@ void DMA_register_channel (int nchan, | @@ -66,179 +67,91 @@ void DMA_register_channel (int nchan, | ||
| 66 | { | 67 | { |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | -/* NVRAM helpers */ | ||
| 70 | -static void nvram_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value) | ||
| 71 | -{ | ||
| 72 | - m48t59_write(nvram, addr, value); | ||
| 73 | -} | ||
| 74 | - | ||
| 75 | -static uint8_t nvram_get_byte (m48t59_t *nvram, uint32_t addr) | ||
| 76 | -{ | ||
| 77 | - return m48t59_read(nvram, addr); | ||
| 78 | -} | ||
| 79 | - | ||
| 80 | -static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value) | ||
| 81 | -{ | ||
| 82 | - m48t59_write(nvram, addr++, (value >> 8) & 0xff); | ||
| 83 | - m48t59_write(nvram, addr++, value & 0xff); | ||
| 84 | -} | ||
| 85 | - | ||
| 86 | -static uint16_t nvram_get_word (m48t59_t *nvram, uint32_t addr) | ||
| 87 | -{ | ||
| 88 | - uint16_t tmp; | ||
| 89 | - | ||
| 90 | - tmp = m48t59_read(nvram, addr) << 8; | ||
| 91 | - tmp |= m48t59_read(nvram, addr + 1); | ||
| 92 | - | ||
| 93 | - return tmp; | ||
| 94 | -} | ||
| 95 | - | ||
| 96 | -static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value) | ||
| 97 | -{ | ||
| 98 | - m48t59_write(nvram, addr++, value >> 24); | ||
| 99 | - m48t59_write(nvram, addr++, (value >> 16) & 0xff); | ||
| 100 | - m48t59_write(nvram, addr++, (value >> 8) & 0xff); | ||
| 101 | - m48t59_write(nvram, addr++, value & 0xff); | ||
| 102 | -} | ||
| 103 | - | ||
| 104 | -static void nvram_set_string (m48t59_t *nvram, uint32_t addr, | ||
| 105 | - const unsigned char *str, uint32_t max) | ||
| 106 | -{ | ||
| 107 | - unsigned int i; | ||
| 108 | - | ||
| 109 | - for (i = 0; i < max && str[i] != '\0'; i++) { | ||
| 110 | - m48t59_write(nvram, addr + i, str[i]); | ||
| 111 | - } | ||
| 112 | - m48t59_write(nvram, addr + max - 1, '\0'); | ||
| 113 | -} | ||
| 114 | - | ||
| 115 | -static uint16_t nvram_crc_update (uint16_t prev, uint16_t value) | ||
| 116 | -{ | ||
| 117 | - uint16_t tmp; | ||
| 118 | - uint16_t pd, pd1, pd2; | ||
| 119 | - | ||
| 120 | - tmp = prev >> 8; | ||
| 121 | - pd = prev ^ value; | ||
| 122 | - pd1 = pd & 0x000F; | ||
| 123 | - pd2 = ((pd >> 4) & 0x000F) ^ pd1; | ||
| 124 | - tmp ^= (pd1 << 3) | (pd1 << 8); | ||
| 125 | - tmp ^= pd2 | (pd2 << 7) | (pd2 << 12); | ||
| 126 | - | ||
| 127 | - return tmp; | ||
| 128 | -} | ||
| 129 | - | ||
| 130 | -static uint16_t nvram_compute_crc (m48t59_t *nvram, uint32_t start, | ||
| 131 | - uint32_t count) | ||
| 132 | -{ | ||
| 133 | - uint32_t i; | ||
| 134 | - uint16_t crc = 0xFFFF; | ||
| 135 | - int odd; | ||
| 136 | - | ||
| 137 | - odd = count & 1; | ||
| 138 | - count &= ~1; | ||
| 139 | - for (i = 0; i != count; i++) { | ||
| 140 | - crc = nvram_crc_update(crc, nvram_get_word(nvram, start + i)); | ||
| 141 | - } | ||
| 142 | - if (odd) { | ||
| 143 | - crc = nvram_crc_update(crc, nvram_get_byte(nvram, start + i) << 8); | ||
| 144 | - } | ||
| 145 | - | ||
| 146 | - return crc; | ||
| 147 | -} | ||
| 148 | - | ||
| 149 | -static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr, | ||
| 150 | - const unsigned char *str) | ||
| 151 | -{ | ||
| 152 | - uint32_t len; | ||
| 153 | - | ||
| 154 | - len = strlen(str) + 1; | ||
| 155 | - nvram_set_string(nvram, addr, str, len); | ||
| 156 | - | ||
| 157 | - return addr + len; | ||
| 158 | -} | ||
| 159 | - | ||
| 160 | -static void nvram_finish_partition (m48t59_t *nvram, uint32_t start, | ||
| 161 | - uint32_t end) | ||
| 162 | -{ | ||
| 163 | - unsigned int i, sum; | ||
| 164 | - | ||
| 165 | - // Length divided by 16 | ||
| 166 | - m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff); | ||
| 167 | - m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff); | ||
| 168 | - // Checksum | ||
| 169 | - sum = m48t59_read(nvram, start); | ||
| 170 | - for (i = 0; i < 14; i++) { | ||
| 171 | - sum += m48t59_read(nvram, start + 2 + i); | ||
| 172 | - sum = (sum + ((sum & 0xff00) >> 8)) & 0xff; | ||
| 173 | - } | ||
| 174 | - m48t59_write(nvram, start + 1, sum & 0xff); | ||
| 175 | -} | ||
| 176 | - | ||
| 177 | extern int nographic; | 70 | extern int nographic; |
| 178 | 71 | ||
| 179 | -int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, | ||
| 180 | - const unsigned char *arch, | ||
| 181 | - uint32_t RAM_size, int boot_device, | ||
| 182 | - uint32_t kernel_image, uint32_t kernel_size, | ||
| 183 | - const char *cmdline, | ||
| 184 | - uint32_t initrd_image, uint32_t initrd_size, | ||
| 185 | - uint32_t NVRAM_image, | ||
| 186 | - int width, int height, int depth) | 72 | +static int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, |
| 73 | + const unsigned char *arch, | ||
| 74 | + uint32_t RAM_size, const char *boot_devices, | ||
| 75 | + uint32_t kernel_image, uint32_t kernel_size, | ||
| 76 | + const char *cmdline, | ||
| 77 | + uint32_t initrd_image, uint32_t initrd_size, | ||
| 78 | + uint32_t NVRAM_image, | ||
| 79 | + int width, int height, int depth) | ||
| 187 | { | 80 | { |
| 188 | - uint16_t crc; | ||
| 189 | unsigned int i; | 81 | unsigned int i; |
| 190 | uint32_t start, end; | 82 | uint32_t start, end; |
| 191 | - | ||
| 192 | - /* Set parameters for Open Hack'Ware BIOS */ | ||
| 193 | - nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16); | ||
| 194 | - nvram_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */ | ||
| 195 | - nvram_set_word(nvram, 0x14, NVRAM_size); | ||
| 196 | - nvram_set_string(nvram, 0x20, arch, 16); | ||
| 197 | - nvram_set_byte(nvram, 0x2f, nographic & 0xff); | ||
| 198 | - nvram_set_lword(nvram, 0x30, RAM_size); | ||
| 199 | - nvram_set_byte(nvram, 0x34, boot_device); | ||
| 200 | - nvram_set_lword(nvram, 0x38, kernel_image); | ||
| 201 | - nvram_set_lword(nvram, 0x3C, kernel_size); | 83 | + uint8_t image[0x1ff0]; |
| 84 | + ohwcfg_v3_t *header = (ohwcfg_v3_t *)ℑ | ||
| 85 | + struct sparc_arch_cfg *sparc_header; | ||
| 86 | + struct OpenBIOS_nvpart_v1 *part_header; | ||
| 87 | + | ||
| 88 | + memset(image, '\0', sizeof(image)); | ||
| 89 | + | ||
| 90 | + // Try to match PPC NVRAM | ||
| 91 | + strcpy(header->struct_ident, "QEMU_BIOS"); | ||
| 92 | + header->struct_version = cpu_to_be32(3); /* structure v3 */ | ||
| 93 | + | ||
| 94 | + header->nvram_size = cpu_to_be16(NVRAM_size); | ||
| 95 | + header->nvram_arch_ptr = cpu_to_be16(sizeof(ohwcfg_v3_t)); | ||
| 96 | + header->nvram_arch_size = cpu_to_be16(sizeof(struct sparc_arch_cfg)); | ||
| 97 | + strcpy(header->arch, arch); | ||
| 98 | + header->nb_cpus = smp_cpus & 0xff; | ||
| 99 | + header->RAM0_base = 0; | ||
| 100 | + header->RAM0_size = cpu_to_be64((uint64_t)RAM_size); | ||
| 101 | + strcpy(header->boot_devices, boot_devices); | ||
| 102 | + header->nboot_devices = strlen(boot_devices) & 0xff; | ||
| 103 | + header->kernel_image = cpu_to_be64((uint64_t)kernel_image); | ||
| 104 | + header->kernel_size = cpu_to_be64((uint64_t)kernel_size); | ||
| 202 | if (cmdline) { | 105 | if (cmdline) { |
| 203 | - /* XXX: put the cmdline in NVRAM too ? */ | ||
| 204 | strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); | 106 | strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); |
| 205 | - nvram_set_lword(nvram, 0x40, CMDLINE_ADDR); | ||
| 206 | - nvram_set_lword(nvram, 0x44, strlen(cmdline)); | ||
| 207 | - } else { | ||
| 208 | - nvram_set_lword(nvram, 0x40, 0); | ||
| 209 | - nvram_set_lword(nvram, 0x44, 0); | 107 | + header->cmdline = cpu_to_be64((uint64_t)CMDLINE_ADDR); |
| 108 | + header->cmdline_size = cpu_to_be64((uint64_t)strlen(cmdline)); | ||
| 210 | } | 109 | } |
| 211 | - nvram_set_lword(nvram, 0x48, initrd_image); | ||
| 212 | - nvram_set_lword(nvram, 0x4C, initrd_size); | ||
| 213 | - nvram_set_lword(nvram, 0x50, NVRAM_image); | 110 | + header->initrd_image = cpu_to_be64((uint64_t)initrd_image); |
| 111 | + header->initrd_size = cpu_to_be64((uint64_t)initrd_size); | ||
| 112 | + header->NVRAM_image = cpu_to_be64((uint64_t)NVRAM_image); | ||
| 113 | + | ||
| 114 | + header->width = cpu_to_be16(width); | ||
| 115 | + header->height = cpu_to_be16(height); | ||
| 116 | + header->depth = cpu_to_be16(depth); | ||
| 117 | + if (nographic) | ||
| 118 | + header->graphic_flags = cpu_to_be16(OHW_GF_NOGRAPHICS); | ||
| 214 | 119 | ||
| 215 | - nvram_set_word(nvram, 0x54, width); | ||
| 216 | - nvram_set_word(nvram, 0x56, height); | ||
| 217 | - nvram_set_word(nvram, 0x58, depth); | ||
| 218 | - crc = nvram_compute_crc(nvram, 0x00, 0xF8); | ||
| 219 | - nvram_set_word(nvram, 0xFC, crc); | 120 | + header->crc = cpu_to_be16(OHW_compute_crc(header, 0x00, 0xF8)); |
| 121 | + | ||
| 122 | + // Architecture specific header | ||
| 123 | + start = sizeof(ohwcfg_v3_t); | ||
| 124 | + sparc_header = (struct sparc_arch_cfg *)&image[start]; | ||
| 125 | + sparc_header->valid = 0; | ||
| 126 | + start += sizeof(struct sparc_arch_cfg); | ||
| 220 | 127 | ||
| 221 | // OpenBIOS nvram variables | 128 | // OpenBIOS nvram variables |
| 222 | // Variable partition | 129 | // Variable partition |
| 223 | - start = 256; | ||
| 224 | - m48t59_write(nvram, start, 0x70); | ||
| 225 | - nvram_set_string(nvram, start + 4, "system", 12); | 130 | + part_header = (struct OpenBIOS_nvpart_v1 *)&image[start]; |
| 131 | + part_header->signature = OPENBIOS_PART_SYSTEM; | ||
| 132 | + strcpy(part_header->name, "system"); | ||
| 226 | 133 | ||
| 227 | - end = start + 16; | 134 | + end = start + sizeof(struct OpenBIOS_nvpart_v1); |
| 228 | for (i = 0; i < nb_prom_envs; i++) | 135 | for (i = 0; i < nb_prom_envs; i++) |
| 229 | - end = nvram_set_var(nvram, end, prom_envs[i]); | 136 | + end = OpenBIOS_set_var(image, end, prom_envs[i]); |
| 137 | + | ||
| 138 | + // End marker | ||
| 139 | + image[end++] = '\0'; | ||
| 230 | 140 | ||
| 231 | - m48t59_write(nvram, end++ , 0); | ||
| 232 | end = start + ((end - start + 15) & ~15); | 141 | end = start + ((end - start + 15) & ~15); |
| 233 | - nvram_finish_partition(nvram, start, end); | 142 | + OpenBIOS_finish_partition(part_header, end - start); |
| 234 | 143 | ||
| 235 | // free partition | 144 | // free partition |
| 236 | start = end; | 145 | start = end; |
| 237 | - m48t59_write(nvram, start, 0x7f); | ||
| 238 | - nvram_set_string(nvram, start + 4, "free", 12); | 146 | + part_header = (struct OpenBIOS_nvpart_v1 *)&image[start]; |
| 147 | + part_header->signature = OPENBIOS_PART_FREE; | ||
| 148 | + strcpy(part_header->name, "free"); | ||
| 239 | 149 | ||
| 240 | end = 0x1fd0; | 150 | end = 0x1fd0; |
| 241 | - nvram_finish_partition(nvram, start, end); | 151 | + OpenBIOS_finish_partition(part_header, end - start); |
| 152 | + | ||
| 153 | + for (i = 0; i < sizeof(image); i++) | ||
| 154 | + m48t59_write(nvram, i, image[i]); | ||
| 242 | 155 | ||
| 243 | return 0; | 156 | return 0; |
| 244 | } | 157 | } |
| @@ -306,7 +219,7 @@ static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; | @@ -306,7 +219,7 @@ static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; | ||
| 306 | static fdctrl_t *floppy_controller; | 219 | static fdctrl_t *floppy_controller; |
| 307 | 220 | ||
| 308 | /* Sun4u hardware initialisation */ | 221 | /* Sun4u hardware initialisation */ |
| 309 | -static void sun4u_init(int ram_size, int vga_ram_size, const char *boot_device, | 222 | +static void sun4u_init(int ram_size, int vga_ram_size, const char *boot_devices, |
| 310 | DisplayState *ds, const char **fd_filename, int snapshot, | 223 | DisplayState *ds, const char **fd_filename, int snapshot, |
| 311 | const char *kernel_filename, const char *kernel_cmdline, | 224 | const char *kernel_filename, const char *kernel_cmdline, |
| 312 | const char *initrd_filename, const char *cpu_model) | 225 | const char *initrd_filename, const char *cpu_model) |
| @@ -428,7 +341,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, const char *boot_device, | @@ -428,7 +341,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, const char *boot_device, | ||
| 428 | i8042_init(NULL/*1*/, NULL/*12*/, 0x60); | 341 | i8042_init(NULL/*1*/, NULL/*12*/, 0x60); |
| 429 | floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd_table); | 342 | floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd_table); |
| 430 | nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59); | 343 | nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59); |
| 431 | - sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device[0], | 344 | + sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_devices, |
| 432 | KERNEL_LOAD_ADDR, kernel_size, | 345 | KERNEL_LOAD_ADDR, kernel_size, |
| 433 | kernel_cmdline, | 346 | kernel_cmdline, |
| 434 | INITRD_LOAD_ADDR, initrd_size, | 347 | INITRD_LOAD_ADDR, initrd_size, |