Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / ppc / qemu / init.c
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
39 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
40
41 struct cpudef {
42     unsigned int iu_version;
43     const char *name;
44     int icache_size, dcache_size;
45     int icache_sets, dcache_sets;
46     int icache_block_size, dcache_block_size;
47     int tlb_sets, tlb_size;
48     void (*initfn)(const struct cpudef *cpu);
49 };
50
51 static uint16_t machine_id = 0;
52
53 extern void unexpected_excep(int vector);
54
55 void
56 unexpected_excep(int vector)
57 {
58     printk("openbios panic: Unexpected exception %x\n", vector);
59     for (;;) {
60     }
61 }
62
63 extern void __divide_error(void);
64
65 void
66 __divide_error(void)
67 {
68     return;
69 }
70
71 enum {
72     ARCH_PREP = 0,
73     ARCH_MAC99,
74     ARCH_HEATHROW,
75     ARCH_MAC99_U3,
76 };
77
78 int is_apple(void)
79 {
80     return is_oldworld() || is_newworld();
81 }
82
83 int is_oldworld(void)
84 {
85     return machine_id == ARCH_HEATHROW;
86 }
87
88 int is_newworld(void)
89 {
90     return (machine_id == ARCH_MAC99) ||
91            (machine_id == ARCH_MAC99_U3);
92 }
93
94 static const pci_arch_t known_arch[] = {
95     [ARCH_PREP] = {
96         .name = "PREP",
97         .vendor_id = PCI_VENDOR_ID_MOTOROLA,
98         .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
99         .cfg_addr = 0x80000cf8,
100         .cfg_data = 0x80000cfc,
101         .cfg_base = 0x80000000,
102         .cfg_len = 0x00100000,
103         .host_pci_base = 0xc0000000,
104         .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */
105         .mem_len = 0x10000000,
106         .io_base = 0x80000000,
107         .io_len = 0x00010000,
108         .rbase = 0x00000000,
109         .rlen = 0x00400000,
110         .irqs = { 9, 11, 9, 11 }
111     },
112     [ARCH_MAC99] = {
113         .name = "MAC99",
114         .vendor_id = PCI_VENDOR_ID_APPLE,
115         .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
116         .cfg_addr = 0xf2800000,
117         .cfg_data = 0xf2c00000,
118         .cfg_base = 0xf2000000,
119         .cfg_len = 0x02000000,
120         .host_pci_base = 0x0,
121         .pci_mem_base = 0x80000000,
122         .mem_len = 0x10000000,
123         .io_base = 0xf2000000,
124         .io_len = 0x00800000,
125         .rbase = 0x00000000,
126         .rlen = 0x01000000,
127         .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
128     },
129     [ARCH_MAC99_U3] = {
130         .name = "MAC99_U3",
131         .vendor_id = PCI_VENDOR_ID_APPLE,
132         .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
133         .cfg_addr = 0xf0800000,
134         .cfg_data = 0xf0c00000,
135         .cfg_base = 0xf0000000,
136         .cfg_len = 0x02000000,
137         .host_pci_base = 0x0,
138         .pci_mem_base = 0x80000000,
139         .mem_len = 0x10000000,
140         .io_base = 0xf2000000,
141         .io_len = 0x00800000,
142         .rbase = 0x00000000,
143         .rlen = 0x01000000,
144         .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
145     },
146     [ARCH_HEATHROW] = {
147         .name = "HEATHROW",
148         .vendor_id = PCI_VENDOR_ID_MOTOROLA,
149         .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
150         .cfg_addr = 0xfec00000,
151         .cfg_data = 0xfee00000,
152         .cfg_base = 0x80000000,
153         .cfg_len = 0x7f000000,
154         .host_pci_base = 0x0,
155         .pci_mem_base = 0x80000000,
156         .mem_len = 0x10000000,
157         .io_base = 0xfe000000,
158         .io_len = 0x00800000,
159         .rbase = 0xfd000000,
160         .rlen = 0x01000000,
161         .irqs = { 21, 22, 23, 24 }
162     },
163 };
164 unsigned long isa_io_base;
165
166 extern struct _console_ops mac_console_ops, prep_console_ops;
167
168 void
169 entry(void)
170 {
171     uint32_t temp = 0;
172     char buf[5];
173
174     arch = &known_arch[ARCH_HEATHROW];
175
176     fw_cfg_init();
177
178     fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
179     buf[4] = '\0';
180     if (strncmp(buf, "QEMU", 4) == 0) {
181         temp = fw_cfg_read_i32(FW_CFG_ID);
182         if (temp == 1) {
183             machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
184             arch = &known_arch[machine_id];
185         }
186     }
187
188     isa_io_base = arch->io_base;
189
190 #ifdef CONFIG_DEBUG_CONSOLE
191     if (is_apple()) {
192         init_console(mac_console_ops);
193     } else {
194         init_console(prep_console_ops);
195     }
196 #endif
197
198     if (temp != 1) {
199         printk("Incompatible configuration device version, freezing\n");
200         for (;;) {
201         }
202     }
203
204     ofmem_init();
205     initialize_forth();
206     /* won't return */
207
208     printk("of_startup returned!\n");
209     for (;;) {
210     }
211 }
212
213 /* -- phys.lo ... phys.hi */
214 static void
215 push_physaddr(phys_addr_t value)
216 {
217     PUSH(value);
218 #ifdef CONFIG_PPC64
219     PUSH(value >> 32);
220 #endif
221 }
222
223 /* From drivers/timer.c */
224 extern unsigned long timer_freq;
225
226 static void
227 cpu_generic_init(const struct cpudef *cpu)
228 {
229     push_str("/cpus");
230     fword("find-device");
231
232     fword("new-device");
233
234     push_str(cpu->name);
235     fword("device-name");
236
237     push_str("cpu");
238     fword("device-type");
239
240     PUSH(mfpvr());
241     fword("encode-int");
242     push_str("cpu-version");
243     fword("property");
244
245     PUSH(cpu->dcache_size);
246     fword("encode-int");
247     push_str("d-cache-size");
248     fword("property");
249
250     PUSH(cpu->icache_size);
251     fword("encode-int");
252     push_str("i-cache-size");
253     fword("property");
254
255     PUSH(cpu->dcache_sets);
256     fword("encode-int");
257     push_str("d-cache-sets");
258     fword("property");
259
260     PUSH(cpu->icache_sets);
261     fword("encode-int");
262     push_str("i-cache-sets");
263     fword("property");
264
265     PUSH(cpu->dcache_block_size);
266     fword("encode-int");
267     push_str("d-cache-block-size");
268     fword("property");
269
270     PUSH(cpu->icache_block_size);
271     fword("encode-int");
272     push_str("i-cache-block-size");
273     fword("property");
274
275     PUSH(cpu->tlb_sets);
276     fword("encode-int");
277     push_str("tlb-sets");
278     fword("property");
279
280     PUSH(cpu->tlb_size);
281     fword("encode-int");
282     push_str("tlb-size");
283     fword("property");
284
285     timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ);
286     PUSH(timer_freq);
287     fword("encode-int");
288     push_str("timebase-frequency");
289     fword("property");
290
291     PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ));
292     fword("encode-int");
293     push_str("clock-frequency");
294     fword("property");
295
296     PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
297     fword("encode-int");
298     push_str("bus-frequency");
299     fword("property");
300
301     push_str("running");
302     fword("encode-string");
303     push_str("state");
304     fword("property");
305 }
306
307 static void
308 cpu_add_pir_property(void)
309 {
310     unsigned long pir;
311
312     asm("mfspr %0, 1023\n"
313         : "=r"(pir) :);
314     PUSH(pir);
315     fword("encode-int");
316     push_str("reg");
317     fword("property");
318 }
319
320 static void
321 cpu_604_init(const struct cpudef *cpu)
322 {
323     cpu_generic_init(cpu);
324     cpu_add_pir_property();
325
326     fword("finish-device");
327 }
328
329 static void
330 cpu_750_init(const struct cpudef *cpu)
331 {
332     cpu_generic_init(cpu);
333
334     PUSH(0);
335     fword("encode-int");
336     push_str("reg");
337     fword("property");
338
339     fword("finish-device");
340 }
341
342 static void
343 cpu_g4_init(const struct cpudef *cpu)
344 {
345     cpu_generic_init(cpu);
346     cpu_add_pir_property();
347
348     fword("finish-device");
349 }
350
351 #ifdef CONFIG_PPC_64BITSUPPORT
352 /* In order to get 64 bit aware handlers that rescue all our
353    GPRs from getting truncated to 32 bits, we need to patch the
354    existing handlers so they jump to our 64 bit aware ones. */
355 static void
356 ppc64_patch_handlers(void)
357 {
358     uint32_t *dsi = (uint32_t *)0x300UL;
359     uint32_t *isi = (uint32_t *)0x400UL;
360
361     // Patch the first DSI handler instruction to: ba 0x2000
362     *dsi = 0x48002002;
363
364     // Patch the first ISI handler instruction to: ba 0x2200
365     *isi = 0x48002202;
366
367     // Invalidate the cache lines
368     asm ("icbi 0, %0" : : "r"(dsi));
369     asm ("icbi 0, %0" : : "r"(isi));
370 }
371 #endif
372
373 static void
374 cpu_970_init(const struct cpudef *cpu)
375 {
376     cpu_generic_init(cpu);
377
378     PUSH(0);
379     fword("encode-int");
380     push_str("reg");
381     fword("property");
382     
383     PUSH(0);
384     PUSH(0);
385     fword("encode-bytes");
386     push_str("64-bit");
387     fword("property");
388
389     fword("finish-device");
390
391 #ifdef CONFIG_PPC_64BITSUPPORT
392     /* The 970 is a PPC64 CPU, so we need to activate
393      * 64bit aware interrupt handlers */
394
395     ppc64_patch_handlers();
396 #endif
397
398     /* The 970 also implements the HIOR which we need to set to 0 */
399
400     mtspr(S_HIOR, 0);
401 }
402
403 static const struct cpudef ppc_defs[] = {
404     {
405         .iu_version = 0x00040000,
406         .name = "PowerPC,604",
407         .icache_size = 0x4000,
408         .dcache_size = 0x4000,
409         .icache_sets = 0x80,
410         .dcache_sets = 0x80,
411         .icache_block_size = 0x20,
412         .dcache_block_size = 0x20,
413         .tlb_sets = 0x40,
414         .tlb_size = 0x80,
415         .initfn = cpu_604_init,
416     },
417     { // XXX find out real values
418         .iu_version = 0x00090000,
419         .name = "PowerPC,604e",
420         .icache_size = 0x4000,
421         .dcache_size = 0x4000,
422         .icache_sets = 0x80,
423         .dcache_sets = 0x80,
424         .icache_block_size = 0x20,
425         .dcache_block_size = 0x20,
426         .tlb_sets = 0x40,
427         .tlb_size = 0x80,
428         .initfn = cpu_604_init,
429     },
430     { // XXX find out real values
431         .iu_version = 0x000a0000,
432         .name = "PowerPC,604r",
433         .icache_size = 0x4000,
434         .dcache_size = 0x4000,
435         .icache_sets = 0x80,
436         .dcache_sets = 0x80,
437         .icache_block_size = 0x20,
438         .dcache_block_size = 0x20,
439         .tlb_sets = 0x40,
440         .tlb_size = 0x80,
441         .initfn = cpu_604_init,
442     },
443     { // XXX find out real values
444         .iu_version = 0x80040000,
445         .name = "PowerPC,MPC86xx",
446         .icache_size = 0x8000,
447         .dcache_size = 0x8000,
448         .icache_sets = 0x80,
449         .dcache_sets = 0x80,
450         .icache_block_size = 0x20,
451         .dcache_block_size = 0x20,
452         .tlb_sets = 0x40,
453         .tlb_size = 0x80,
454         .initfn = cpu_750_init,
455     },
456     {
457         .iu_version = 0x000080000,
458         .name = "PowerPC,750",
459         .icache_size = 0x8000,
460         .dcache_size = 0x8000,
461         .icache_sets = 0x80,
462         .dcache_sets = 0x80,
463         .icache_block_size = 0x20,
464         .dcache_block_size = 0x20,
465         .tlb_sets = 0x40,
466         .tlb_size = 0x80,
467         .initfn = cpu_750_init,
468     },
469     { // XXX find out real values
470         .iu_version = 0x10080000,
471         .name = "PowerPC,750",
472         .icache_size = 0x8000,
473         .dcache_size = 0x8000,
474         .icache_sets = 0x80,
475         .dcache_sets = 0x80,
476         .icache_block_size = 0x20,
477         .dcache_block_size = 0x20,
478         .tlb_sets = 0x40,
479         .tlb_size = 0x80,
480         .initfn = cpu_750_init,
481     },
482     { // XXX find out real values
483         .iu_version = 0x70000000,
484         .name = "PowerPC,750",
485         .icache_size = 0x8000,
486         .dcache_size = 0x8000,
487         .icache_sets = 0x80,
488         .dcache_sets = 0x80,
489         .icache_block_size = 0x20,
490         .dcache_block_size = 0x20,
491         .tlb_sets = 0x40,
492         .tlb_size = 0x80,
493         .initfn = cpu_750_init,
494     },
495     { // XXX find out real values
496         .iu_version = 0x70020000,
497         .name = "PowerPC,750",
498         .icache_size = 0x8000,
499         .dcache_size = 0x8000,
500         .icache_sets = 0x80,
501         .dcache_sets = 0x80,
502         .icache_block_size = 0x20,
503         .dcache_block_size = 0x20,
504         .tlb_sets = 0x40,
505         .tlb_size = 0x80,
506         .initfn = cpu_750_init,
507     },
508     { // XXX find out real values
509         .iu_version = 0x800c0000,
510         .name = "PowerPC,74xx",
511         .icache_size = 0x8000,
512         .dcache_size = 0x8000,
513         .icache_sets = 0x80,
514         .dcache_sets = 0x80,
515         .icache_block_size = 0x20,
516         .dcache_block_size = 0x20,
517         .tlb_sets = 0x40,
518         .tlb_size = 0x80,
519         .initfn = cpu_750_init,
520     },
521     {
522         .iu_version = 0x0000c0000,
523         .name = "PowerPC,G4",
524         .icache_size = 0x8000,
525         .dcache_size = 0x8000,
526         .icache_sets = 0x80,
527         .dcache_sets = 0x80,
528         .icache_block_size = 0x20,
529         .dcache_block_size = 0x20,
530         .tlb_sets = 0x40,
531         .tlb_size = 0x80,
532         .initfn = cpu_g4_init,
533     },
534     {
535         .iu_version = 0x00390000,
536         .name = "PowerPC,970",
537         .icache_size = 0x10000,
538         .dcache_size = 0x8000,
539         .icache_sets = 0x200,
540         .dcache_sets = 0x80,
541         .icache_block_size = 0x80,
542         .dcache_block_size = 0x80,
543         .tlb_sets = 0x100,
544         .tlb_size = 0x1000,
545         .initfn = cpu_970_init,
546     },
547     { // XXX find out real values
548         .iu_version = 0x003C0000,
549         .name = "PowerPC,970FX",
550         .icache_size = 0x10000,
551         .dcache_size = 0x8000,
552         .icache_sets = 0x80,
553         .dcache_sets = 0x80,
554         .icache_block_size = 0x80,
555         .dcache_block_size = 0x80,
556         .tlb_sets = 0x100,
557         .tlb_size = 0x1000,
558         .initfn = cpu_970_init,
559     },
560     {
561         .iu_version = 0x00350000,
562         .name = "PowerPC,POWER4",
563         .icache_size = 0x10000,
564         .dcache_size = 0x8000,
565         .icache_sets = 0x100,
566         .dcache_sets = 0x40,
567         .icache_block_size = 0x80,
568         .dcache_block_size = 0x80,
569         .tlb_sets = 0x100,
570         .tlb_size = 0x1000,
571         .initfn = cpu_970_init,
572     },
573 };
574
575 static const struct cpudef *
576 id_cpu(void)
577 {
578     unsigned int iu_version;
579     unsigned int i;
580
581     iu_version = mfpvr() & 0xffff0000;
582
583     for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) {
584         if (iu_version == ppc_defs[i].iu_version)
585             return &ppc_defs[i];
586     }
587     printk("Unknown cpu (pvr %x), freezing!\n", iu_version);
588     for (;;) {
589     }
590 }
591
592 static void go(void);
593
594 static void
595 go(void)
596 {
597     ucell addr;
598
599     feval("saved-program-state >sps.entry @");
600     addr = POP();
601
602     call_elf(0, 0, addr);
603 }
604
605 static void kvm_of_init(void)
606 {
607     char hypercall[4 * 4];
608     uint32_t *hc32;
609
610     /* Don't expose /hypervisor when not in KVM */
611     if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
612         return;
613
614     push_str("/");
615     fword("find-device");
616
617     fword("new-device");
618
619     push_str("hypervisor");
620     fword("device-name");
621
622     push_str("hypervisor");
623     fword("device-type");
624
625     /* compatible */
626
627     push_str("linux,kvm");
628     fword("encode-string");
629     push_str("epapr,hypervisor-0.2");
630     fword("encode-string");
631     fword("encode+");
632     push_str("compatible");
633     fword("property");
634
635     /* Tell the guest about the hypercall instructions */
636     fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
637     hc32 = (uint32_t*)hypercall;
638     PUSH(hc32[0]);
639     fword("encode-int");
640     PUSH(hc32[1]);
641     fword("encode-int");
642     fword("encode+");
643     PUSH(hc32[2]);
644     fword("encode-int");
645     fword("encode+");
646     PUSH(hc32[3]);
647     fword("encode-int");
648     fword("encode+");
649     push_str("hcall-instructions");
650     fword("property");
651
652     /* ePAPR requires us to provide a unique guest id */
653     PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
654     fword("encode-int");
655     push_str("guest-id");
656     fword("property");
657
658     /* ePAPR requires us to provide a guest name */
659     push_str("KVM guest");
660     fword("encode-string");
661     push_str("guest-name");
662     fword("property");
663
664     fword("finish-device");
665 }
666
667 /*
668  *  filll        ( addr bytes quad -- )
669  */
670
671 static void ffilll(void)
672 {
673     const u32 longval = POP();
674     u32 bytes = POP();
675     u32 *laddr = (u32 *)cell2pointer(POP());
676     u32 len;
677     
678     for (len = 0; len < bytes / sizeof(u32); len++) {
679         *laddr++ = longval;
680     }   
681 }
682
683 void
684 arch_of_init(void)
685 {
686 #ifdef CONFIG_RTAS
687     phandle_t ph;
688 #endif
689     uint64_t ram_size;
690     const struct cpudef *cpu;
691     char buf[64], qemu_uuid[16];
692     const char *stdin_path, *stdout_path, *boot_path;
693     uint32_t temp = 0;
694     char *boot_device;
695     ofmem_t *ofmem = ofmem_arch_get_private();
696
697     openbios_init();
698     modules_init();
699     setup_timers();
700 #ifdef CONFIG_DRIVER_PCI
701     ob_pci_init();
702 #endif
703
704     printk("\n");
705     printk("=============================================================\n");
706     printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
707            OPENBIOS_BUILD_DATE);
708
709     fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
710     buf[4] = '\0';
711     printk("Configuration device id %s", buf);
712
713     temp = fw_cfg_read_i32(FW_CFG_ID);
714     printk(" version %d machine id %d\n", temp, machine_id);
715
716     temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
717
718     printk("CPUs: %x\n", temp);
719
720     ram_size = ofmem->ramsize;
721
722     printk("Memory: %lldM\n", ram_size / 1024 / 1024);
723
724     fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
725
726     printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
727            qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
728            qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
729            qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
730            qemu_uuid[15]);
731
732     /* set device tree root info */
733
734     push_str("/");
735     fword("find-device");
736
737     switch(machine_id) {
738     case ARCH_HEATHROW: /* OldWorld */
739
740         /* model */
741
742         push_str("Power Macintosh");
743         fword("model");
744
745         /* compatible */
746
747         push_str("AAPL,PowerMac G3");
748         fword("encode-string");
749         push_str("MacRISC");
750         fword("encode-string");
751         fword("encode+");
752         push_str("compatible");
753         fword("property");
754
755         /* misc */
756
757         push_str("device-tree");
758         fword("encode-string");
759         push_str("AAPL,original-name");
760         fword("property");
761
762         PUSH(0);
763         fword("encode-int");
764         push_str("AAPL,cpu-id");
765         fword("property");
766
767         PUSH(66 * 1000 * 1000);
768         fword("encode-int");
769         push_str("clock-frequency");
770         fword("property");
771         break;
772
773     case ARCH_MAC99:
774     case ARCH_MAC99_U3:
775     case ARCH_PREP:
776     default:
777
778         /* model */
779
780         push_str("PowerMac3,1");
781         fword("model");
782
783         /* compatible */
784
785         push_str("PowerMac3,1");
786         fword("encode-string");
787         push_str("MacRISC");
788         fword("encode-string");
789         fword("encode+");
790         push_str("MacRISC2");
791         fword("encode-string");
792         fword("encode+");
793         push_str("Power Macintosh");
794         fword("encode-string");
795         fword("encode+");
796         push_str("compatible");
797         fword("property");
798
799         /* misc */
800
801         push_str("bootrom");
802         fword("device-type");
803
804         PUSH(100 * 1000 * 1000);
805         fword("encode-int");
806         push_str("clock-frequency");
807         fword("property");
808         break;
809     }
810
811     /* Perhaps we can store UUID here ? */
812
813     push_str("0000000000000");
814     fword("encode-string");
815     push_str("system-id");
816     fword("property");
817
818     /* memory info */
819
820     push_str("/memory");
821     fword("find-device");
822
823     /* all memory */
824
825     push_physaddr(0);
826     fword("encode-phys");
827     /* This needs adjusting if #size-cells gets increased.
828        Alternatively use multiple (address, size) tuples. */
829     PUSH(ram_size & 0xffffffff);
830     fword("encode-int");
831     fword("encode+");
832     push_str("reg");
833     fword("property");
834
835     cpu = id_cpu();
836     cpu->initfn(cpu);
837     printk("CPU type %s\n", cpu->name);
838
839     snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
840     ofmem_register(find_dev("/memory"), find_dev(buf));
841     node_methods_init(buf);
842
843 #ifdef CONFIG_RTAS
844     /* OldWorld Macs don't have an /rtas node. */
845     switch (machine_id) {
846     case ARCH_MAC99:
847     case ARCH_MAC99_U3:
848         if (!(ph = find_dev("/rtas"))) {
849             printk("Warning: No /rtas node\n");
850         } else {
851             unsigned long size = 0x1000;
852             while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
853                 size *= 2;
854             set_property(ph, "rtas-size", (char*)&size, sizeof(size));
855             set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
856         }
857         break;
858     }
859 #endif
860
861     if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
862         if (is_apple()) {
863             if (CONFIG_SERIAL_PORT) {
864                 stdin_path = "scca";
865                 stdout_path = "scca";
866             } else {
867                 stdin_path = "sccb";
868                 stdout_path = "sccb";
869             }
870         } else {
871             stdin_path = "ttya";
872             stdout_path = "ttya";
873         }
874
875         /* Some bootloaders force the output to the screen device, so
876            let's create a screen alias for the serial device too */
877
878         push_str("/aliases");
879         fword("find-device");
880
881         push_str(stdout_path);
882         fword("pathres-resolve-aliases");
883         fword("encode-string");
884         push_str("screen");
885         fword("property");
886     } else {
887         if (is_apple()) {
888             stdin_path = "adb-keyboard";
889             stdout_path = "screen";
890         } else {
891             stdin_path = "keyboard";
892             stdout_path = "screen";
893         }
894     }
895
896     kvm_of_init();
897
898     /* Setup nvram variables */
899     push_str("/options");
900     fword("find-device");
901
902     /* Setup default boot devices (not overriding user settings) */
903     fword("boot-device");
904     boot_device = pop_fstr_copy();
905     if (boot_device && strcmp(boot_device, "disk") == 0) {
906         switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) {
907             case 'c':
908                 boot_path = "hd";
909                 break;
910             default:
911             case 'd':
912                 boot_path = "cd";
913                 break;
914         }
915
916         snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path);
917         push_str(buf);
918         fword("encode-string");
919         push_str("boot-device");
920         fword("property");
921     }
922     free(boot_device);
923
924     /* Set up other properties */
925
926     push_str("/chosen");
927     fword("find-device");
928
929     push_str(stdin_path);
930     fword("pathres-resolve-aliases");
931     push_str("input-device");
932     fword("$setenv");
933
934     push_str(stdout_path);
935     fword("pathres-resolve-aliases");
936     push_str("output-device");
937     fword("$setenv");
938
939 #if 0
940     if(getbool("tty-interface?") == 1)
941 #endif
942         fword("activate-tty-interface");
943
944     device_end();
945
946     /* Implementation of filll word (required by BootX) */
947     bind_func("filll", ffilll);
948     
949     bind_func("platform-boot", boot);
950     bind_func("(go)", go);
951 }