These changes are the raw update to qemu-2.6.
[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     PUSH(0x20);
307     fword("encode-int");
308     push_str("reservation-granule-size");
309     fword("property");
310 }
311
312 static void
313 cpu_add_pir_property(void)
314 {
315     unsigned long pir;
316
317     asm("mfspr %0, 1023\n"
318         : "=r"(pir) :);
319     PUSH(pir);
320     fword("encode-int");
321     push_str("reg");
322     fword("property");
323 }
324
325 static void
326 cpu_604_init(const struct cpudef *cpu)
327 {
328     cpu_generic_init(cpu);
329     cpu_add_pir_property();
330
331     fword("finish-device");
332 }
333
334 static void
335 cpu_750_init(const struct cpudef *cpu)
336 {
337     cpu_generic_init(cpu);
338
339     PUSH(0);
340     fword("encode-int");
341     push_str("reg");
342     fword("property");
343
344     fword("finish-device");
345 }
346
347 static void
348 cpu_g4_init(const struct cpudef *cpu)
349 {
350     cpu_generic_init(cpu);
351     cpu_add_pir_property();
352
353     fword("finish-device");
354 }
355
356 #ifdef CONFIG_PPC_64BITSUPPORT
357 /* In order to get 64 bit aware handlers that rescue all our
358    GPRs from getting truncated to 32 bits, we need to patch the
359    existing handlers so they jump to our 64 bit aware ones. */
360 static void
361 ppc64_patch_handlers(void)
362 {
363     uint32_t *dsi = (uint32_t *)0x300UL;
364     uint32_t *isi = (uint32_t *)0x400UL;
365
366     // Patch the first DSI handler instruction to: ba 0x2000
367     *dsi = 0x48002002;
368
369     // Patch the first ISI handler instruction to: ba 0x2200
370     *isi = 0x48002202;
371
372     // Invalidate the cache lines
373     asm ("icbi 0, %0" : : "r"(dsi));
374     asm ("icbi 0, %0" : : "r"(isi));
375 }
376 #endif
377
378 static void
379 cpu_970_init(const struct cpudef *cpu)
380 {
381     cpu_generic_init(cpu);
382
383     PUSH(0);
384     fword("encode-int");
385     push_str("reg");
386     fword("property");
387     
388     PUSH(0);
389     PUSH(0);
390     fword("encode-bytes");
391     push_str("64-bit");
392     fword("property");
393
394     fword("finish-device");
395
396 #ifdef CONFIG_PPC_64BITSUPPORT
397     /* The 970 is a PPC64 CPU, so we need to activate
398      * 64bit aware interrupt handlers */
399
400     ppc64_patch_handlers();
401 #endif
402
403     /* The 970 also implements the HIOR which we need to set to 0 */
404
405     mtspr(S_HIOR, 0);
406 }
407
408 static const struct cpudef ppc_defs[] = {
409     {
410         .iu_version = 0x00040000,
411         .name = "PowerPC,604",
412         .icache_size = 0x4000,
413         .dcache_size = 0x4000,
414         .icache_sets = 0x80,
415         .dcache_sets = 0x80,
416         .icache_block_size = 0x20,
417         .dcache_block_size = 0x20,
418         .tlb_sets = 0x40,
419         .tlb_size = 0x80,
420         .initfn = cpu_604_init,
421     },
422     { // XXX find out real values
423         .iu_version = 0x00090000,
424         .name = "PowerPC,604e",
425         .icache_size = 0x4000,
426         .dcache_size = 0x4000,
427         .icache_sets = 0x80,
428         .dcache_sets = 0x80,
429         .icache_block_size = 0x20,
430         .dcache_block_size = 0x20,
431         .tlb_sets = 0x40,
432         .tlb_size = 0x80,
433         .initfn = cpu_604_init,
434     },
435     { // XXX find out real values
436         .iu_version = 0x000a0000,
437         .name = "PowerPC,604r",
438         .icache_size = 0x4000,
439         .dcache_size = 0x4000,
440         .icache_sets = 0x80,
441         .dcache_sets = 0x80,
442         .icache_block_size = 0x20,
443         .dcache_block_size = 0x20,
444         .tlb_sets = 0x40,
445         .tlb_size = 0x80,
446         .initfn = cpu_604_init,
447     },
448     { // XXX find out real values
449         .iu_version = 0x80040000,
450         .name = "PowerPC,MPC86xx",
451         .icache_size = 0x8000,
452         .dcache_size = 0x8000,
453         .icache_sets = 0x80,
454         .dcache_sets = 0x80,
455         .icache_block_size = 0x20,
456         .dcache_block_size = 0x20,
457         .tlb_sets = 0x40,
458         .tlb_size = 0x80,
459         .initfn = cpu_750_init,
460     },
461     {
462         .iu_version = 0x000080000,
463         .name = "PowerPC,750",
464         .icache_size = 0x8000,
465         .dcache_size = 0x8000,
466         .icache_sets = 0x80,
467         .dcache_sets = 0x80,
468         .icache_block_size = 0x20,
469         .dcache_block_size = 0x20,
470         .tlb_sets = 0x40,
471         .tlb_size = 0x80,
472         .initfn = cpu_750_init,
473     },
474     { // XXX find out real values
475         .iu_version = 0x10080000,
476         .name = "PowerPC,750",
477         .icache_size = 0x8000,
478         .dcache_size = 0x8000,
479         .icache_sets = 0x80,
480         .dcache_sets = 0x80,
481         .icache_block_size = 0x20,
482         .dcache_block_size = 0x20,
483         .tlb_sets = 0x40,
484         .tlb_size = 0x80,
485         .initfn = cpu_750_init,
486     },
487     { // XXX find out real values
488         .iu_version = 0x70000000,
489         .name = "PowerPC,750",
490         .icache_size = 0x8000,
491         .dcache_size = 0x8000,
492         .icache_sets = 0x80,
493         .dcache_sets = 0x80,
494         .icache_block_size = 0x20,
495         .dcache_block_size = 0x20,
496         .tlb_sets = 0x40,
497         .tlb_size = 0x80,
498         .initfn = cpu_750_init,
499     },
500     { // XXX find out real values
501         .iu_version = 0x70020000,
502         .name = "PowerPC,750",
503         .icache_size = 0x8000,
504         .dcache_size = 0x8000,
505         .icache_sets = 0x80,
506         .dcache_sets = 0x80,
507         .icache_block_size = 0x20,
508         .dcache_block_size = 0x20,
509         .tlb_sets = 0x40,
510         .tlb_size = 0x80,
511         .initfn = cpu_750_init,
512     },
513     { // XXX find out real values
514         .iu_version = 0x800c0000,
515         .name = "PowerPC,74xx",
516         .icache_size = 0x8000,
517         .dcache_size = 0x8000,
518         .icache_sets = 0x80,
519         .dcache_sets = 0x80,
520         .icache_block_size = 0x20,
521         .dcache_block_size = 0x20,
522         .tlb_sets = 0x40,
523         .tlb_size = 0x80,
524         .initfn = cpu_750_init,
525     },
526     {
527         .iu_version = 0x0000c0000,
528         .name = "PowerPC,G4",
529         .icache_size = 0x8000,
530         .dcache_size = 0x8000,
531         .icache_sets = 0x80,
532         .dcache_sets = 0x80,
533         .icache_block_size = 0x20,
534         .dcache_block_size = 0x20,
535         .tlb_sets = 0x40,
536         .tlb_size = 0x80,
537         .initfn = cpu_g4_init,
538     },
539     {
540         .iu_version = 0x00390000,
541         .name = "PowerPC,970",
542         .icache_size = 0x10000,
543         .dcache_size = 0x8000,
544         .icache_sets = 0x200,
545         .dcache_sets = 0x80,
546         .icache_block_size = 0x80,
547         .dcache_block_size = 0x80,
548         .tlb_sets = 0x100,
549         .tlb_size = 0x1000,
550         .initfn = cpu_970_init,
551     },
552     { // XXX find out real values
553         .iu_version = 0x003C0000,
554         .name = "PowerPC,970FX",
555         .icache_size = 0x10000,
556         .dcache_size = 0x8000,
557         .icache_sets = 0x80,
558         .dcache_sets = 0x80,
559         .icache_block_size = 0x80,
560         .dcache_block_size = 0x80,
561         .tlb_sets = 0x100,
562         .tlb_size = 0x1000,
563         .initfn = cpu_970_init,
564     },
565     {
566         .iu_version = 0x00350000,
567         .name = "PowerPC,POWER4",
568         .icache_size = 0x10000,
569         .dcache_size = 0x8000,
570         .icache_sets = 0x100,
571         .dcache_sets = 0x40,
572         .icache_block_size = 0x80,
573         .dcache_block_size = 0x80,
574         .tlb_sets = 0x100,
575         .tlb_size = 0x1000,
576         .initfn = cpu_970_init,
577     },
578 };
579
580 static const struct cpudef *
581 id_cpu(void)
582 {
583     unsigned int iu_version;
584     unsigned int i;
585
586     iu_version = mfpvr() & 0xffff0000;
587
588     for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) {
589         if (iu_version == ppc_defs[i].iu_version)
590             return &ppc_defs[i];
591     }
592     printk("Unknown cpu (pvr %x), freezing!\n", iu_version);
593     for (;;) {
594     }
595 }
596
597 static void go(void);
598
599 static void
600 go(void)
601 {
602     ucell addr;
603
604     /* Insert copyright property for MacOS 9 and below */
605     if (find_dev("/rom/macos")) {
606         fword("insert-copyright-property");
607     }
608     
609     feval("saved-program-state >sps.entry @");
610     addr = POP();
611
612     call_elf(0, 0, addr);
613 }
614
615 static void kvm_of_init(void)
616 {
617     char hypercall[4 * 4];
618     uint32_t *hc32;
619
620     /* Don't expose /hypervisor when not in KVM */
621     if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
622         return;
623
624     push_str("/");
625     fword("find-device");
626
627     fword("new-device");
628
629     push_str("hypervisor");
630     fword("device-name");
631
632     push_str("hypervisor");
633     fword("device-type");
634
635     /* compatible */
636
637     push_str("linux,kvm");
638     fword("encode-string");
639     push_str("epapr,hypervisor-0.2");
640     fword("encode-string");
641     fword("encode+");
642     push_str("compatible");
643     fword("property");
644
645     /* Tell the guest about the hypercall instructions */
646     fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
647     hc32 = (uint32_t*)hypercall;
648     PUSH(hc32[0]);
649     fword("encode-int");
650     PUSH(hc32[1]);
651     fword("encode-int");
652     fword("encode+");
653     PUSH(hc32[2]);
654     fword("encode-int");
655     fword("encode+");
656     PUSH(hc32[3]);
657     fword("encode-int");
658     fword("encode+");
659     push_str("hcall-instructions");
660     fword("property");
661
662     /* ePAPR requires us to provide a unique guest id */
663     PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
664     fword("encode-int");
665     push_str("guest-id");
666     fword("property");
667
668     /* ePAPR requires us to provide a guest name */
669     push_str("KVM guest");
670     fword("encode-string");
671     push_str("guest-name");
672     fword("property");
673
674     fword("finish-device");
675 }
676
677 /*
678  *  filll        ( addr bytes quad -- )
679  */
680
681 static void ffilll(void)
682 {
683     const u32 longval = POP();
684     u32 bytes = POP();
685     u32 *laddr = (u32 *)cell2pointer(POP());
686     u32 len;
687     
688     for (len = 0; len < bytes / sizeof(u32); len++) {
689         *laddr++ = longval;
690     }   
691 }
692
693 /*
694  * adler32        ( adler buf len -- checksum )
695  *
696  * Adapted from Mark Adler's original implementation (zlib license)
697  *
698  * Both OS 9 and BootX require this word for payload validation.
699  */
700
701 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
702 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
703 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
704 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
705 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
706
707 static void adler32(void)
708 {
709     uint32_t len = (uint32_t)POP();
710     char *buf = (char *)POP();
711     uint32_t adler = (uint32_t)POP();
712
713     if (buf == NULL) {
714         RET(-1);
715     }
716
717     uint32_t base = 65521;
718     uint32_t nmax = 5552;
719
720     uint32_t s1 = adler & 0xffff;
721     uint32_t s2 = (adler >> 16) & 0xffff;
722
723     uint32_t k;
724     while (len > 0) {
725         k = (len < nmax ? len : nmax);
726         len -= k;
727
728         while (k >= 16) {
729             DO16(buf);
730             buf += 16;
731             k -= 16;
732         }
733         if (k != 0) {
734             do {
735                 s1 += *buf++;
736                 s2 += s1;
737             } while (--k);
738         }
739
740         s1 %= base;
741         s2 %= base;
742     }
743
744     RET(s2 << 16 | s1);
745 }
746
747 void
748 arch_of_init(void)
749 {
750 #ifdef CONFIG_RTAS
751     phandle_t ph;
752 #endif
753     uint64_t ram_size;
754     const struct cpudef *cpu;
755     char buf[64], qemu_uuid[16];
756     const char *stdin_path, *stdout_path, *boot_path;
757     uint32_t temp = 0;
758     char *boot_device;
759     ofmem_t *ofmem = ofmem_arch_get_private();
760
761     openbios_init();
762     modules_init();
763     setup_timers();
764 #ifdef CONFIG_DRIVER_PCI
765     ob_pci_init();
766 #endif
767
768     printk("\n");
769     printk("=============================================================\n");
770     printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
771            OPENBIOS_BUILD_DATE);
772
773     fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
774     buf[4] = '\0';
775     printk("Configuration device id %s", buf);
776
777     temp = fw_cfg_read_i32(FW_CFG_ID);
778     printk(" version %d machine id %d\n", temp, machine_id);
779
780     temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
781
782     printk("CPUs: %x\n", temp);
783
784     ram_size = ofmem->ramsize;
785
786     printk("Memory: %lldM\n", ram_size / 1024 / 1024);
787
788     fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
789
790     printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
791            qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
792            qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
793            qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
794            qemu_uuid[15]);
795
796     /* set device tree root info */
797
798     push_str("/");
799     fword("find-device");
800
801     switch(machine_id) {
802     case ARCH_HEATHROW: /* OldWorld */
803
804         /* model */
805
806         push_str("Power Macintosh");
807         fword("model");
808
809         /* compatible */
810
811         push_str("AAPL,PowerMac G3");
812         fword("encode-string");
813         push_str("MacRISC");
814         fword("encode-string");
815         fword("encode+");
816         push_str("compatible");
817         fword("property");
818
819         /* misc */
820
821         push_str("device-tree");
822         fword("encode-string");
823         push_str("AAPL,original-name");
824         fword("property");
825
826         PUSH(0);
827         fword("encode-int");
828         push_str("AAPL,cpu-id");
829         fword("property");
830
831         PUSH(66 * 1000 * 1000);
832         fword("encode-int");
833         push_str("clock-frequency");
834         fword("property");
835         break;
836
837     case ARCH_MAC99:
838     case ARCH_MAC99_U3:
839     case ARCH_PREP:
840     default:
841
842         /* model */
843
844         push_str("PowerMac3,1");
845         fword("model");
846
847         /* compatible */
848
849         push_str("PowerMac3,1");
850         fword("encode-string");
851         push_str("MacRISC");
852         fword("encode-string");
853         fword("encode+");
854         push_str("MacRISC2");
855         fword("encode-string");
856         fword("encode+");
857         push_str("Power Macintosh");
858         fword("encode-string");
859         fword("encode+");
860         push_str("compatible");
861         fword("property");
862
863         /* misc */
864
865         push_str("bootrom");
866         fword("device-type");
867
868         PUSH(100 * 1000 * 1000);
869         fword("encode-int");
870         push_str("clock-frequency");
871         fword("property");
872         break;
873     }
874
875     /* Perhaps we can store UUID here ? */
876
877     push_str("0000000000000");
878     fword("encode-string");
879     push_str("system-id");
880     fword("property");
881
882     /* memory info */
883
884     push_str("/memory");
885     fword("find-device");
886
887     /* all memory */
888
889     push_physaddr(0);
890     fword("encode-phys");
891     /* This needs adjusting if #size-cells gets increased.
892        Alternatively use multiple (address, size) tuples. */
893     PUSH(ram_size & 0xffffffff);
894     fword("encode-int");
895     fword("encode+");
896     push_str("reg");
897     fword("property");
898
899     cpu = id_cpu();
900     cpu->initfn(cpu);
901     printk("CPU type %s\n", cpu->name);
902
903     snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
904     ofmem_register(find_dev("/memory"), find_dev(buf));
905     node_methods_init(buf);
906
907 #ifdef CONFIG_RTAS
908     /* OldWorld Macs don't have an /rtas node. */
909     switch (machine_id) {
910     case ARCH_MAC99:
911     case ARCH_MAC99_U3:
912         if (!(ph = find_dev("/rtas"))) {
913             printk("Warning: No /rtas node\n");
914         } else {
915             unsigned long size = 0x1000;
916             while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
917                 size *= 2;
918             set_property(ph, "rtas-size", (char*)&size, sizeof(size));
919             set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
920         }
921         break;
922     }
923 #endif
924
925     if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
926         if (is_apple()) {
927             if (CONFIG_SERIAL_PORT) {
928                 stdin_path = "scca";
929                 stdout_path = "scca";
930             } else {
931                 stdin_path = "sccb";
932                 stdout_path = "sccb";
933             }
934         } else {
935             stdin_path = "ttya";
936             stdout_path = "ttya";
937         }
938
939         /* Some bootloaders force the output to the screen device, so
940            let's create a screen alias for the serial device too */
941
942         push_str("/aliases");
943         fword("find-device");
944
945         push_str(stdout_path);
946         fword("pathres-resolve-aliases");
947         fword("encode-string");
948         push_str("screen");
949         fword("property");
950     } else {
951         if (is_apple()) {
952             stdin_path = "adb-keyboard";
953             stdout_path = "screen";
954         } else {
955             stdin_path = "keyboard";
956             stdout_path = "screen";
957         }
958     }
959
960     kvm_of_init();
961
962     /* Setup nvram variables */
963     push_str("/options");
964     fword("find-device");
965
966     /* Setup default boot devices (not overriding user settings) */
967     fword("boot-device");
968     boot_device = pop_fstr_copy();
969     if (boot_device && strcmp(boot_device, "disk") == 0) {
970         switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) {
971             case 'c':
972                 boot_path = "hd";
973                 break;
974             default:
975             case 'd':
976                 boot_path = "cd";
977                 break;
978         }
979
980         snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path);
981         push_str(buf);
982         fword("encode-string");
983         push_str("boot-device");
984         fword("property");
985     }
986     free(boot_device);
987
988     /* Set up other properties */
989
990     push_str("/chosen");
991     fword("find-device");
992
993     push_str(stdin_path);
994     fword("pathres-resolve-aliases");
995     push_str("input-device");
996     fword("$setenv");
997
998     push_str(stdout_path);
999     fword("pathres-resolve-aliases");
1000     push_str("output-device");
1001     fword("$setenv");
1002
1003 #if 0
1004     if(getbool("tty-interface?") == 1)
1005 #endif
1006         fword("activate-tty-interface");
1007
1008     device_end();
1009
1010     /* Implementation of filll word (required by BootX) */
1011     bind_func("filll", ffilll);
1012
1013     /* Implementation of adler32 word (required by OS 9, BootX) */
1014     bind_func("(adler32)", adler32);
1015     
1016     bind_func("platform-boot", boot);
1017     bind_func("(go)", go);
1018 }