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