1 /*
2 * Creation Date: <2004/08/28 18:38:22 greg>
3 * Time-stamp: <2004/08/28 18:38:22 greg>
4 *
5 * <init.c>
6 *
7 * Initialization for qemu
8 *
9 * Copyright (C) 2004 Greg Watson
10 * Copyright (C) 2005 Stefan Reinauer
11 *
12 * based on mol/init.c:
13 *
14 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
15 * (samuel@ibrium.se, dary@lindesign.se)
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation
20 *
21 */
22
23 #include "config.h"
24 #include "libopenbios/openbios.h"
25 #include "libopenbios/bindings.h"
26 #include "libopenbios/console.h"
27 #include "drivers/pci.h"
28 #include "arch/common/nvram.h"
29 #include "drivers/drivers.h"
30 #include "qemu/qemu.h"
31 #include "libopenbios/ofmem.h"
32 #include "openbios-version.h"
33 #include "libc/byteorder.h"
34 #include "libc/vsprintf.h"
35 #define NO_QEMU_PROTOS
36 #include "arch/common/fw_cfg.h"
37 #include "arch/ppc/processor.h"
38 #include "context.h"
39
40 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
41
42 struct cpudef {
43 unsigned int iu_version;
44 const char *name;
45 int icache_size, dcache_size;
46 int icache_sets, dcache_sets;
47 int icache_block_size, dcache_block_size;
48 int tlb_sets, tlb_size;
49 void (*initfn)(const struct cpudef *cpu);
50 };
51
52 static uint16_t machine_id = 0;
53
54 extern void unexpected_excep(int vector);
55
56 void
unexpected_excep(int vector)57 unexpected_excep(int vector)
58 {
59 printk("openbios panic: Unexpected exception %x\n", vector);
60 for (;;) {
61 }
62 }
63
64 extern void __divide_error(void);
65
66 void
__divide_error(void)67 __divide_error(void)
68 {
69 return;
70 }
71
72 enum {
73 ARCH_PREP = 0,
74 ARCH_MAC99,
75 ARCH_HEATHROW,
76 ARCH_MAC99_U3,
77 };
78
is_apple(void)79 int is_apple(void)
80 {
81 return is_oldworld() || is_newworld();
82 }
83
is_oldworld(void)84 int is_oldworld(void)
85 {
86 return machine_id == ARCH_HEATHROW;
87 }
88
is_newworld(void)89 int is_newworld(void)
90 {
91 return (machine_id == ARCH_MAC99) ||
92 (machine_id == ARCH_MAC99_U3);
93 }
94
95 #define CORE99_VIA_CONFIG_CUDA 0x0
96 #define CORE99_VIA_CONFIG_PMU 0x1
97 #define CORE99_VIA_CONFIG_PMU_ADB 0x2
98
has_pmu(void)99 int has_pmu(void)
100 {
101 uint32_t via_config = fw_cfg_read_i32(FW_CFG_PPC_VIACONFIG);
102
103 return (via_config != CORE99_VIA_CONFIG_CUDA);
104 }
105
has_adb(void)106 int has_adb(void)
107 {
108 uint32_t via_config = fw_cfg_read_i32(FW_CFG_PPC_VIACONFIG);
109
110 return (via_config == CORE99_VIA_CONFIG_CUDA ||
111 via_config == CORE99_VIA_CONFIG_PMU_ADB);
112 }
113
114 static const pci_arch_t known_arch[] = {
115 [ARCH_PREP] = {
116 .name = "PREP",
117 .vendor_id = PCI_VENDOR_ID_MOTOROLA,
118 .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
119 .cfg_addr = 0x80000cf8,
120 .cfg_data = 0x80000cfc,
121 .cfg_base = 0x80000000,
122 .cfg_len = 0x00100000,
123 .host_pci_base = 0xc0000000,
124 .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */
125 .mem_len = 0x10000000,
126 .io_base = 0x80000000,
127 .io_len = 0x00010000,
128 .host_ranges = {
129 { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0x80000000, .len = 0x00010000 },
130 { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = 0xc0100000, .len = 0x10000000 },
131 { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 }
132 },
133 .irqs = { 15, 15, 15, 15 }
134 },
135 [ARCH_MAC99] = {
136 .name = "MAC99",
137 .vendor_id = PCI_VENDOR_ID_APPLE,
138 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
139 .cfg_addr = 0xf2800000,
140 .cfg_data = 0xf2c00000,
141 .cfg_base = 0xf2000000,
142 .cfg_len = 0x02000000,
143 .host_pci_base = 0x0,
144 .pci_mem_base = 0x80000000,
145 .mem_len = 0x10000000,
146 .io_base = 0xf2000000,
147 .io_len = 0x00800000,
148 .host_ranges = {
149 { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xf2000000, .len = 0x00800000 },
150 { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 },
151 { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 }
152 },
153 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
154 },
155 [ARCH_MAC99_U3] = {
156 .name = "MAC99_U3",
157 .vendor_id = PCI_VENDOR_ID_APPLE,
158 .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
159 .cfg_addr = 0xf0800000,
160 .cfg_data = 0xf0c00000,
161 .cfg_base = 0xf0000000,
162 .cfg_len = 0x02000000,
163 .host_pci_base = 0x0,
164 .pci_mem_base = 0x80000000,
165 .mem_len = 0x10000000,
166 .io_base = 0xf2000000,
167 .io_len = 0x00800000,
168 .host_ranges = {
169 { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xf2000000, .len = 0x00800000 },
170 { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 },
171 { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 }
172 },
173 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
174 },
175 [ARCH_HEATHROW] = {
176 .name = "HEATHROW",
177 .vendor_id = PCI_VENDOR_ID_MOTOROLA,
178 .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
179 .cfg_addr = 0xfec00000,
180 .cfg_data = 0xfee00000,
181 .cfg_base = 0x80000000,
182 .cfg_len = 0x7f000000,
183 .host_pci_base = 0x0,
184 .pci_mem_base = 0x80000000,
185 .mem_len = 0x10000000,
186 .io_base = 0xfe000000,
187 .io_len = 0x00800000,
188 .host_ranges = {
189 { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xfe000000, .len = 0x00800000 },
190 { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = 0xfd000000, .len = 0x01000000 },
191 { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 },
192 { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 }
193 },
194 .irqs = { 21, 22, 23, 24 }
195 },
196 };
197 unsigned long isa_io_base;
198
199 extern struct _console_ops mac_console_ops, prep_console_ops;
200
201 void
entry(void)202 entry(void)
203 {
204 uint32_t temp = 0;
205 char buf[5];
206
207 arch = &known_arch[ARCH_HEATHROW];
208
209 fw_cfg_init();
210
211 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
212 buf[4] = '\0';
213 if (strncmp(buf, "QEMU", 4) == 0) {
214 temp = fw_cfg_read_i32(FW_CFG_ID);
215 if (temp == 1) {
216 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
217 arch = &known_arch[machine_id];
218 }
219 }
220
221 isa_io_base = arch->io_base;
222
223 #ifdef CONFIG_DEBUG_CONSOLE
224 if (is_apple()) {
225 init_console(mac_console_ops);
226 } else {
227 init_console(prep_console_ops);
228 }
229 #endif
230
231 if (temp != 1) {
232 printk("Incompatible configuration device version, freezing\n");
233 for (;;) {
234 }
235 }
236
237 ofmem_init();
238 initialize_forth();
239 /* won't return */
240
241 printk("of_startup returned!\n");
242 for (;;) {
243 }
244 }
245
246 /* -- phys.lo ... phys.hi */
247 static void
push_physaddr(phys_addr_t value)248 push_physaddr(phys_addr_t value)
249 {
250 PUSH(value);
251 #ifdef CONFIG_PPC64
252 PUSH(value >> 32);
253 #endif
254 }
255
256 /* From drivers/timer.c */
257 extern unsigned long timer_freq;
258
259 static void
cpu_generic_init(const struct cpudef * cpu)260 cpu_generic_init(const struct cpudef *cpu)
261 {
262 push_str("/cpus");
263 fword("find-device");
264
265 fword("new-device");
266
267 push_str(cpu->name);
268 fword("device-name");
269
270 push_str("cpu");
271 fword("device-type");
272
273 PUSH(mfpvr());
274 fword("encode-int");
275 push_str("cpu-version");
276 fword("property");
277
278 PUSH(cpu->dcache_size);
279 fword("encode-int");
280 push_str("d-cache-size");
281 fword("property");
282
283 PUSH(cpu->icache_size);
284 fword("encode-int");
285 push_str("i-cache-size");
286 fword("property");
287
288 PUSH(cpu->dcache_sets);
289 fword("encode-int");
290 push_str("d-cache-sets");
291 fword("property");
292
293 PUSH(cpu->icache_sets);
294 fword("encode-int");
295 push_str("i-cache-sets");
296 fword("property");
297
298 PUSH(cpu->dcache_block_size);
299 fword("encode-int");
300 push_str("d-cache-block-size");
301 fword("property");
302
303 PUSH(cpu->icache_block_size);
304 fword("encode-int");
305 push_str("i-cache-block-size");
306 fword("property");
307
308 PUSH(cpu->tlb_sets);
309 fword("encode-int");
310 push_str("tlb-sets");
311 fword("property");
312
313 PUSH(cpu->tlb_size);
314 fword("encode-int");
315 push_str("tlb-size");
316 fword("property");
317
318 timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ);
319 PUSH(timer_freq);
320 fword("encode-int");
321 push_str("timebase-frequency");
322 fword("property");
323
324 PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ));
325 fword("encode-int");
326 push_str("clock-frequency");
327 fword("property");
328
329 PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
330 fword("encode-int");
331 push_str("bus-frequency");
332 fword("property");
333
334 push_str("running");
335 fword("encode-string");
336 push_str("state");
337 fword("property");
338
339 PUSH(0x20);
340 fword("encode-int");
341 push_str("reservation-granule-size");
342 fword("property");
343 }
344
345 static void
cpu_add_pir_property(void)346 cpu_add_pir_property(void)
347 {
348 unsigned long pir;
349
350 asm("mfspr %0, 1023\n"
351 : "=r"(pir) :);
352 PUSH(pir);
353 fword("encode-int");
354 push_str("reg");
355 fword("property");
356 }
357
358 static void
cpu_604_init(const struct cpudef * cpu)359 cpu_604_init(const struct cpudef *cpu)
360 {
361 cpu_generic_init(cpu);
362 cpu_add_pir_property();
363
364 fword("finish-device");
365 }
366
367 static void
cpu_750_init(const struct cpudef * cpu)368 cpu_750_init(const struct cpudef *cpu)
369 {
370 cpu_generic_init(cpu);
371
372 PUSH(0);
373 fword("encode-int");
374 push_str("reg");
375 fword("property");
376
377 fword("finish-device");
378 }
379
380 static void
cpu_g4_init(const struct cpudef * cpu)381 cpu_g4_init(const struct cpudef *cpu)
382 {
383 cpu_generic_init(cpu);
384 cpu_add_pir_property();
385
386 fword("finish-device");
387 }
388
389 #ifdef CONFIG_PPC_64BITSUPPORT
390 /* In order to get 64 bit aware handlers that rescue all our
391 GPRs from getting truncated to 32 bits, we need to patch the
392 existing handlers so they jump to our 64 bit aware ones. */
393 static void
ppc64_patch_handlers(void)394 ppc64_patch_handlers(void)
395 {
396 uint32_t *dsi = (uint32_t *)0x300UL;
397 uint32_t *isi = (uint32_t *)0x400UL;
398
399 // Patch the first DSI handler instruction to: ba 0x2000
400 *dsi = 0x48002002;
401
402 // Patch the first ISI handler instruction to: ba 0x2200
403 *isi = 0x48002202;
404
405 // Invalidate the cache lines
406 asm ("icbi 0, %0" : : "r"(dsi));
407 asm ("icbi 0, %0" : : "r"(isi));
408 }
409 #endif
410
411 static void
cpu_970_init(const struct cpudef * cpu)412 cpu_970_init(const struct cpudef *cpu)
413 {
414 cpu_generic_init(cpu);
415
416 PUSH(0);
417 fword("encode-int");
418 push_str("reg");
419 fword("property");
420
421 PUSH(0);
422 PUSH(0);
423 fword("encode-bytes");
424 push_str("64-bit");
425 fword("property");
426
427 fword("finish-device");
428
429 #ifdef CONFIG_PPC_64BITSUPPORT
430 /* The 970 is a PPC64 CPU, so we need to activate
431 * 64bit aware interrupt handlers */
432
433 ppc64_patch_handlers();
434 #endif
435
436 /* The 970 also implements the HIOR which we need to set to 0 */
437
438 mtspr(S_HIOR, 0);
439 }
440
441 static const struct cpudef ppc_defs[] = {
442 {
443 .iu_version = 0x00040000,
444 .name = "PowerPC,604",
445 .icache_size = 0x4000,
446 .dcache_size = 0x4000,
447 .icache_sets = 0x80,
448 .dcache_sets = 0x80,
449 .icache_block_size = 0x20,
450 .dcache_block_size = 0x20,
451 .tlb_sets = 0x40,
452 .tlb_size = 0x80,
453 .initfn = cpu_604_init,
454 },
455 { // XXX find out real values
456 .iu_version = 0x00090000,
457 .name = "PowerPC,604e",
458 .icache_size = 0x4000,
459 .dcache_size = 0x4000,
460 .icache_sets = 0x80,
461 .dcache_sets = 0x80,
462 .icache_block_size = 0x20,
463 .dcache_block_size = 0x20,
464 .tlb_sets = 0x40,
465 .tlb_size = 0x80,
466 .initfn = cpu_604_init,
467 },
468 { // XXX find out real values
469 .iu_version = 0x000a0000,
470 .name = "PowerPC,604r",
471 .icache_size = 0x4000,
472 .dcache_size = 0x4000,
473 .icache_sets = 0x80,
474 .dcache_sets = 0x80,
475 .icache_block_size = 0x20,
476 .dcache_block_size = 0x20,
477 .tlb_sets = 0x40,
478 .tlb_size = 0x80,
479 .initfn = cpu_604_init,
480 },
481 { // XXX find out real values
482 .iu_version = 0x80040000,
483 .name = "PowerPC,MPC86xx",
484 .icache_size = 0x8000,
485 .dcache_size = 0x8000,
486 .icache_sets = 0x80,
487 .dcache_sets = 0x80,
488 .icache_block_size = 0x20,
489 .dcache_block_size = 0x20,
490 .tlb_sets = 0x40,
491 .tlb_size = 0x80,
492 .initfn = cpu_750_init,
493 },
494 {
495 .iu_version = 0x000080000,
496 .name = "PowerPC,750",
497 .icache_size = 0x8000,
498 .dcache_size = 0x8000,
499 .icache_sets = 0x80,
500 .dcache_sets = 0x80,
501 .icache_block_size = 0x20,
502 .dcache_block_size = 0x20,
503 .tlb_sets = 0x40,
504 .tlb_size = 0x80,
505 .initfn = cpu_750_init,
506 },
507 { // XXX find out real values
508 .iu_version = 0x10080000,
509 .name = "PowerPC,750",
510 .icache_size = 0x8000,
511 .dcache_size = 0x8000,
512 .icache_sets = 0x80,
513 .dcache_sets = 0x80,
514 .icache_block_size = 0x20,
515 .dcache_block_size = 0x20,
516 .tlb_sets = 0x40,
517 .tlb_size = 0x80,
518 .initfn = cpu_750_init,
519 },
520 { // XXX find out real values
521 .iu_version = 0x70000000,
522 .name = "PowerPC,750",
523 .icache_size = 0x8000,
524 .dcache_size = 0x8000,
525 .icache_sets = 0x80,
526 .dcache_sets = 0x80,
527 .icache_block_size = 0x20,
528 .dcache_block_size = 0x20,
529 .tlb_sets = 0x40,
530 .tlb_size = 0x80,
531 .initfn = cpu_750_init,
532 },
533 { // XXX find out real values
534 .iu_version = 0x70020000,
535 .name = "PowerPC,750",
536 .icache_size = 0x8000,
537 .dcache_size = 0x8000,
538 .icache_sets = 0x80,
539 .dcache_sets = 0x80,
540 .icache_block_size = 0x20,
541 .dcache_block_size = 0x20,
542 .tlb_sets = 0x40,
543 .tlb_size = 0x80,
544 .initfn = cpu_750_init,
545 },
546 { // XXX find out real values
547 .iu_version = 0x800c0000,
548 .name = "PowerPC,74xx",
549 .icache_size = 0x8000,
550 .dcache_size = 0x8000,
551 .icache_sets = 0x80,
552 .dcache_sets = 0x80,
553 .icache_block_size = 0x20,
554 .dcache_block_size = 0x20,
555 .tlb_sets = 0x40,
556 .tlb_size = 0x80,
557 .initfn = cpu_750_init,
558 },
559 {
560 .iu_version = 0x0000c0000,
561 .name = "PowerPC,G4",
562 .icache_size = 0x8000,
563 .dcache_size = 0x8000,
564 .icache_sets = 0x80,
565 .dcache_sets = 0x80,
566 .icache_block_size = 0x20,
567 .dcache_block_size = 0x20,
568 .tlb_sets = 0x40,
569 .tlb_size = 0x80,
570 .initfn = cpu_g4_init,
571 },
572 {
573 .iu_version = 0x00390000,
574 .name = "PowerPC,970",
575 .icache_size = 0x10000,
576 .dcache_size = 0x8000,
577 .icache_sets = 0x200,
578 .dcache_sets = 0x80,
579 .icache_block_size = 0x80,
580 .dcache_block_size = 0x80,
581 .tlb_sets = 0x100,
582 .tlb_size = 0x1000,
583 .initfn = cpu_970_init,
584 },
585 { // XXX find out real values
586 .iu_version = 0x003C0000,
587 .name = "PowerPC,970FX",
588 .icache_size = 0x10000,
589 .dcache_size = 0x8000,
590 .icache_sets = 0x80,
591 .dcache_sets = 0x80,
592 .icache_block_size = 0x80,
593 .dcache_block_size = 0x80,
594 .tlb_sets = 0x100,
595 .tlb_size = 0x1000,
596 .initfn = cpu_970_init,
597 },
598 {
599 .iu_version = 0x00350000,
600 .name = "PowerPC,POWER4",
601 .icache_size = 0x10000,
602 .dcache_size = 0x8000,
603 .icache_sets = 0x100,
604 .dcache_sets = 0x40,
605 .icache_block_size = 0x80,
606 .dcache_block_size = 0x80,
607 .tlb_sets = 0x100,
608 .tlb_size = 0x1000,
609 .initfn = cpu_970_init,
610 },
611 };
612
613 static const struct cpudef *
id_cpu(void)614 id_cpu(void)
615 {
616 unsigned int iu_version;
617 unsigned int i;
618
619 iu_version = mfpvr() & 0xffff0000;
620
621 for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) {
622 if (iu_version == ppc_defs[i].iu_version)
623 return &ppc_defs[i];
624 }
625 printk("Unknown cpu (pvr %x), freezing!\n", iu_version);
626 for (;;) {
627 }
628 }
629
630 static void arch_go(void);
631
632 static void
arch_go(void)633 arch_go(void)
634 {
635 phandle_t ph;
636 xt_t xt;
637
638 /* Insert copyright property for MacOS 9 and below */
639 if (find_dev("/rom/macos")) {
640 fword("insert-copyright-property");
641 }
642
643 /* PReP machines expect a standard VGA console, so disable
644 VBE extensions just before we transfer control */
645 if (!is_apple()) {
646 ph = dt_iterate_type(find_dev("/"), "display");
647 if (ph != 0) {
648 xt = find_package_method("vbe-deinit", ph);
649 if (xt != 0) {
650 PUSH(xt);
651 fword("execute");
652 }
653 }
654 }
655 }
656
kvm_of_init(void)657 static void kvm_of_init(void)
658 {
659 char hypercall[4 * 4];
660 uint32_t *hc32;
661
662 /* Don't expose /hypervisor when not in KVM */
663 if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
664 return;
665
666 push_str("/");
667 fword("find-device");
668
669 fword("new-device");
670
671 push_str("hypervisor");
672 fword("device-name");
673
674 push_str("hypervisor");
675 fword("device-type");
676
677 /* compatible */
678
679 push_str("linux,kvm");
680 fword("encode-string");
681 push_str("epapr,hypervisor-0.2");
682 fword("encode-string");
683 fword("encode+");
684 push_str("compatible");
685 fword("property");
686
687 /* Tell the guest about the hypercall instructions */
688 fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
689 hc32 = (uint32_t*)hypercall;
690 PUSH(hc32[0]);
691 fword("encode-int");
692 PUSH(hc32[1]);
693 fword("encode-int");
694 fword("encode+");
695 PUSH(hc32[2]);
696 fword("encode-int");
697 fword("encode+");
698 PUSH(hc32[3]);
699 fword("encode-int");
700 fword("encode+");
701 push_str("hcall-instructions");
702 fword("property");
703
704 /* ePAPR requires us to provide a unique guest id */
705 PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
706 fword("encode-int");
707 push_str("guest-id");
708 fword("property");
709
710 /* ePAPR requires us to provide a guest name */
711 push_str("KVM guest");
712 fword("encode-string");
713 push_str("guest-name");
714 fword("property");
715
716 fword("finish-device");
717 }
718
719 /*
720 * filll ( addr bytes quad -- )
721 */
722
ffilll(void)723 static void ffilll(void)
724 {
725 const u32 longval = POP();
726 u32 bytes = POP();
727 u32 *laddr = (u32 *)cell2pointer(POP());
728 u32 len;
729
730 for (len = 0; len < bytes / sizeof(u32); len++) {
731 *laddr++ = longval;
732 }
733 }
734
735 /*
736 * adler32 ( adler buf len -- checksum )
737 *
738 * Adapted from Mark Adler's original implementation (zlib license)
739 *
740 * Both OS 9 and BootX require this word for payload validation.
741 */
742
743 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
744 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
745 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
746 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
747 #define DO16(buf) DO8(buf,0); DO8(buf,8);
748
adler32(void)749 static void adler32(void)
750 {
751 uint32_t len = (uint32_t)POP();
752 char *buf = (char *)POP();
753 uint32_t adler = (uint32_t)POP();
754
755 if (buf == NULL) {
756 RET(-1);
757 }
758
759 uint32_t base = 65521;
760 uint32_t nmax = 5552;
761
762 uint32_t s1 = adler & 0xffff;
763 uint32_t s2 = (adler >> 16) & 0xffff;
764
765 uint32_t k;
766 while (len > 0) {
767 k = (len < nmax ? len : nmax);
768 len -= k;
769
770 while (k >= 16) {
771 DO16(buf);
772 buf += 16;
773 k -= 16;
774 }
775 if (k != 0) {
776 do {
777 s1 += *buf++;
778 s2 += s1;
779 } while (--k);
780 }
781
782 s1 %= base;
783 s2 %= base;
784 }
785
786 RET(s2 << 16 | s1);
787 }
788
789 /* ( size -- virt ) */
790 static void
dma_alloc(void)791 dma_alloc(void)
792 {
793 ucell size = POP();
794 ucell addr;
795 int ret;
796
797 ret = ofmem_posix_memalign((void *)&addr, size, PAGE_SIZE);
798
799 if (ret) {
800 PUSH(0);
801 } else {
802 PUSH(addr);
803 }
804 }
805
806 /* ( virt size cacheable? -- devaddr ) */
807 static void
dma_map_in(void)808 dma_map_in(void)
809 {
810 POP();
811 POP();
812 ucell va = POP();
813
814 if (is_apple()) {
815 PUSH(va);
816 } else {
817 /* PReP */
818 PUSH(va + 0x80000000);
819 }
820 }
821
822 /* ( virt devaddr size -- ) */
823 static void
dma_sync(void)824 dma_sync(void)
825 {
826 ucell size = POP();
827 POP();
828 ucell virt = POP();
829
830 flush_dcache_range(cell2pointer(virt), cell2pointer(virt + size));
831 flush_icache_range(cell2pointer(virt), cell2pointer(virt + size));
832 }
833
834 void
arch_of_init(void)835 arch_of_init(void)
836 {
837 #ifdef CONFIG_RTAS
838 phandle_t ph;
839 #endif
840 uint64_t ram_size;
841 const struct cpudef *cpu;
842 char buf[256], qemu_uuid[16];
843 const char *stdin_path, *stdout_path, *boot_path;
844 uint32_t temp = 0;
845 char *boot_device, *bootorder_file;
846 uint32_t bootorder_sz, sz;
847 ofmem_t *ofmem = ofmem_arch_get_private();
848 ucell load_base;
849
850 openbios_init();
851 modules_init();
852 setup_timers();
853
854 bind_func("ppc-dma-alloc", dma_alloc);
855 feval("['] ppc-dma-alloc to (dma-alloc)");
856 bind_func("ppc-dma-map-in", dma_map_in);
857 feval("['] ppc-dma-map-in to (dma-map-in)");
858 bind_func("ppc-dma-sync", dma_sync);
859 feval("['] ppc-dma-sync to (dma-sync)");
860
861 #ifdef CONFIG_DRIVER_PCI
862 push_str("/");
863 fword("find-device");
864 feval("\" /\" open-dev to my-self");
865
866 switch (machine_id) {
867 case ARCH_MAC99:
868 case ARCH_MAC99_U3:
869 /* The NewWorld NVRAM is not located in the MacIO device */
870 macio_nvram_init("/", 0);
871 ob_pci_init();
872 ob_unin_init();
873 break;
874 default:
875 ob_pci_init();
876 }
877
878 feval("0 to my-self");
879 #endif
880
881 printk("\n");
882 printk("=============================================================\n");
883 printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
884 OPENBIOS_BUILD_DATE);
885
886 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
887 buf[4] = '\0';
888 printk("Configuration device id %s", buf);
889
890 temp = fw_cfg_read_i32(FW_CFG_ID);
891 printk(" version %d machine id %d\n", temp, machine_id);
892
893 temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
894
895 printk("CPUs: %x\n", temp);
896
897 ram_size = ofmem->ramsize;
898
899 printk("Memory: %lldM\n", ram_size / 1024 / 1024);
900
901 fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
902
903 printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
904 qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
905 qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
906 qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
907 qemu_uuid[15]);
908
909 /* set device tree root info */
910
911 push_str("/");
912 fword("find-device");
913
914 switch(machine_id) {
915 case ARCH_HEATHROW: /* OldWorld */
916
917 /* model */
918
919 push_str("Power Macintosh");
920 fword("model");
921
922 /* compatible */
923
924 push_str("AAPL,PowerMac G3");
925 fword("encode-string");
926 push_str("MacRISC");
927 fword("encode-string");
928 fword("encode+");
929 push_str("compatible");
930 fword("property");
931
932 /* misc */
933
934 push_str("device-tree");
935 fword("encode-string");
936 push_str("AAPL,original-name");
937 fword("property");
938
939 PUSH(0);
940 fword("encode-int");
941 push_str("AAPL,cpu-id");
942 fword("property");
943
944 PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
945 fword("encode-int");
946 push_str("clock-frequency");
947 fword("property");
948 break;
949
950 case ARCH_MAC99:
951 case ARCH_MAC99_U3:
952 case ARCH_PREP:
953 default:
954
955 /* model */
956
957 push_str("PowerMac3,1");
958 fword("model");
959
960 /* compatible */
961
962 push_str("PowerMac3,1");
963 fword("encode-string");
964 push_str("MacRISC");
965 fword("encode-string");
966 fword("encode+");
967 push_str("MacRISC2");
968 fword("encode-string");
969 fword("encode+");
970 push_str("Power Macintosh");
971 fword("encode-string");
972 fword("encode+");
973 push_str("compatible");
974 fword("property");
975
976 /* misc */
977
978 push_str("bootrom");
979 fword("device-type");
980
981 PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
982 fword("encode-int");
983 push_str("clock-frequency");
984 fword("property");
985 break;
986 }
987
988 /* Perhaps we can store UUID here ? */
989
990 push_str("0000000000000");
991 fword("encode-string");
992 push_str("system-id");
993 fword("property");
994
995 /* memory info */
996
997 push_str("/memory");
998 fword("find-device");
999
1000 /* all memory */
1001
1002 push_physaddr(0);
1003 fword("encode-phys");
1004 /* This needs adjusting if #size-cells gets increased.
1005 Alternatively use multiple (address, size) tuples. */
1006 PUSH(ram_size & 0xffffffff);
1007 fword("encode-int");
1008 fword("encode+");
1009 push_str("reg");
1010 fword("property");
1011
1012 cpu = id_cpu();
1013 cpu->initfn(cpu);
1014 printk("CPU type %s\n", cpu->name);
1015
1016 snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
1017 ofmem_register(find_dev("/memory"), find_dev(buf));
1018 node_methods_init(buf);
1019
1020 #ifdef CONFIG_RTAS
1021 /* OldWorld Macs don't have an /rtas node. */
1022 switch (machine_id) {
1023 case ARCH_MAC99:
1024 case ARCH_MAC99_U3:
1025 if (!(ph = find_dev("/rtas"))) {
1026 printk("Warning: No /rtas node\n");
1027 } else {
1028 unsigned long size = 0x1000;
1029 while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
1030 size *= 2;
1031 set_property(ph, "rtas-size", (char*)&size, sizeof(size));
1032 set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
1033 }
1034 break;
1035 }
1036 #endif
1037
1038 if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
1039 if (is_apple()) {
1040 if (CONFIG_SERIAL_PORT) {
1041 stdin_path = "sccb";
1042 stdout_path = "sccb";
1043 } else {
1044 stdin_path = "scca";
1045 stdout_path = "scca";
1046 }
1047 } else {
1048 stdin_path = "ttya";
1049 stdout_path = "ttya";
1050 }
1051
1052 /* Some bootloaders force the output to the screen device, so
1053 let's create a screen alias for the serial device too */
1054
1055 push_str("/aliases");
1056 fword("find-device");
1057
1058 push_str(stdout_path);
1059 fword("pathres-resolve-aliases");
1060 fword("encode-string");
1061 push_str("screen");
1062 fword("property");
1063 } else {
1064 stdin_path = "keyboard";
1065 stdout_path = "screen";
1066 }
1067
1068 kvm_of_init();
1069
1070 /* Setup nvram variables */
1071 push_str("/options");
1072 fword("find-device");
1073
1074 /* Boot order */
1075 bootorder_file = fw_cfg_read_file("bootorder", &bootorder_sz);
1076
1077 if (bootorder_file == NULL) {
1078 /* No bootorder present, use fw_cfg device if no custom
1079 boot-device specified */
1080 fword("boot-device");
1081 boot_device = pop_fstr_copy();
1082
1083 if (boot_device && strcmp(boot_device, "disk") == 0) {
1084 switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) {
1085 case 'c':
1086 boot_path = "hd";
1087 break;
1088 default:
1089 case 'd':
1090 boot_path = "cd";
1091 break;
1092 }
1093
1094 snprintf(buf, sizeof(buf),
1095 "%s:,\\\\:tbxi "
1096 "%s:,\\ppc\\bootinfo.txt "
1097 "%s:,%%BOOT",
1098 boot_path, boot_path, boot_path);
1099
1100 push_str(buf);
1101 fword("encode-string");
1102 push_str("boot-device");
1103 fword("property");
1104 }
1105
1106 free(boot_device);
1107 } else {
1108 sz = bootorder_sz * (3 * 2);
1109 boot_device = malloc(sz);
1110 memset(boot_device, 0, sz);
1111
1112 while ((boot_path = strsep(&bootorder_file, "\n")) != NULL) {
1113 snprintf(buf, sizeof(buf),
1114 "%s:,\\\\:tbxi "
1115 "%s:,\\ppc\\bootinfo.txt "
1116 "%s:,%%BOOT ",
1117 boot_path, boot_path, boot_path);
1118
1119 strncat(boot_device, buf, sz);
1120 }
1121
1122 push_str(boot_device);
1123 fword("encode-string");
1124 push_str("boot-device");
1125 fword("property");
1126
1127 free(boot_device);
1128 }
1129
1130 /* Set up other properties */
1131
1132 push_str("/chosen");
1133 fword("find-device");
1134
1135 push_str(stdin_path);
1136 fword("pathres-resolve-aliases");
1137 push_str("input-device");
1138 fword("$setenv");
1139
1140 push_str(stdout_path);
1141 fword("pathres-resolve-aliases");
1142 push_str("output-device");
1143 fword("$setenv");
1144
1145 #if 0
1146 if(getbool("tty-interface?") == 1)
1147 #endif
1148 fword("activate-tty-interface");
1149
1150 device_end();
1151
1152 /* Implementation of filll word (required by BootX) */
1153 bind_func("filll", ffilll);
1154
1155 /* Implementation of adler32 word (required by OS 9, BootX) */
1156 bind_func("(adler32)", adler32);
1157
1158 bind_func("platform-boot", boot);
1159 bind_func("(arch-go)", arch_go);
1160
1161 /* Allocate 8MB memory at load-base */
1162 fword("load-base");
1163 load_base = POP();
1164 ofmem_claim_phys(load_base, 0x800000, 0);
1165 ofmem_claim_virt(load_base, 0x800000, 0);
1166 ofmem_map(load_base, load_base, 0x800000, 0);
1167 }
1168