Revision d2c63fc1 hw/sun4u.c
b/hw/sun4u.c | ||
---|---|---|
23 | 23 |
*/ |
24 | 24 |
#include "vl.h" |
25 | 25 |
#include "m48t59.h" |
26 |
#include "firmware_abi.h" |
|
26 | 27 |
|
27 | 28 |
#define KERNEL_LOAD_ADDR 0x00404000 |
28 | 29 |
#define CMDLINE_ADDR 0x003ff000 |
... | ... | |
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 | 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 | 81 |
unsigned int i; |
190 | 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 | 105 |
if (cmdline) { |
203 |
/* XXX: put the cmdline in NVRAM too ? */ |
|
204 | 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 | 128 |
// OpenBIOS nvram variables |
222 | 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 | 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 | 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 | 144 |
// free partition |
236 | 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 | 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 | 156 |
return 0; |
244 | 157 |
} |
... | ... | |
306 | 219 |
static fdctrl_t *floppy_controller; |
307 | 220 |
|
308 | 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 | 223 |
DisplayState *ds, const char **fd_filename, int snapshot, |
311 | 224 |
const char *kernel_filename, const char *kernel_cmdline, |
312 | 225 |
const char *initrd_filename, const char *cpu_model) |
... | ... | |
428 | 341 |
i8042_init(NULL/*1*/, NULL/*12*/, 0x60); |
429 | 342 |
floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd_table); |
430 | 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 | 345 |
KERNEL_LOAD_ADDR, kernel_size, |
433 | 346 |
kernel_cmdline, |
434 | 347 |
INITRD_LOAD_ADDR, initrd_size, |
Also available in: Unified diff