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, |