1 /* tag: openbios forth environment, executable code
2  *
3  * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
4  *
5  * See the file "COPYING" for further information about
6  * the copyright and warranty status of this work.
7  */
8 
9 #include "config.h"
10 #include "libopenbios/openbios.h"
11 #include "libopenbios/bindings.h"
12 #include "libopenbios/console.h"
13 #include "drivers/drivers.h"
14 #include "asm/types.h"
15 #include "dict.h"
16 #include "kernel/kernel.h"
17 #include "kernel/stack.h"
18 #include "arch/common/nvram.h"
19 #include "packages/nvram.h"
20 #include "../../drivers/timer.h" // XXX
21 #include "libopenbios/sys_info.h"
22 #include "openbios.h"
23 #include "boot.h"
24 #include "romvec.h"
25 #include "openprom.h"
26 #include "psr.h"
27 #include "libopenbios/video.h"
28 #define NO_QEMU_PROTOS
29 #include "arch/common/fw_cfg.h"
30 #include "arch/sparc32/ofmem_sparc32.h"
31 
32 #define MEMORY_SIZE     (128*1024)       /* 128K ram for hosted system */
33 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
34 #define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
35 
36 int qemu_machine_type;
37 
38 struct hwdef {
39     uint64_t iommu_base, slavio_base;
40     uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
41     unsigned long fd_offset, counter_offset, intr_offset;
42     unsigned long aux1_offset, aux2_offset;
43     uint64_t dma_base, esp_base, le_base;
44     uint64_t tcx_base;
45     uint32_t simm_size;
46     int intr_ncpu;
47     int mid_offset;
48     int machine_id_low, machine_id_high;
49 };
50 
51 static const struct hwdef hwdefs[] = {
52     /* SS-5 */
53     {
54         .iommu_base   = 0x10000000,
55         .tcx_base     = 0x50000000,
56         .slavio_base  = 0x71000000,
57         .ms_kb_base   = 0x71000000,
58         .serial_base  = 0x71100000,
59         .nvram_base   = 0x71200000,
60         .fd_offset    = 0x00400000,
61         .counter_offset = 0x00d00000,
62         .intr_offset  = 0x00e00000,
63         .intr_ncpu    = 1,
64         .aux1_offset  = 0x00900000,
65         .aux2_offset  = 0x00910000,
66         .dma_base     = 0x78400000,
67         .esp_base     = 0x78800000,
68         .le_base      = 0x78c00000,
69         .simm_size    = 0x2000000,
70         .mid_offset   = 0,
71         .machine_id_low = 32,
72         .machine_id_high = 63,
73     },
74     /* SS-10, SS-20 */
75     {
76         .iommu_base   = 0xfe0000000ULL,
77         .tcx_base     = 0xe20000000ULL,
78         .slavio_base  = 0xff1000000ULL,
79         .ms_kb_base   = 0xff1000000ULL,
80         .serial_base  = 0xff1100000ULL,
81         .nvram_base   = 0xff1200000ULL,
82         .fd_offset    = 0x00700000, // 0xff1700000ULL,
83         .counter_offset = 0x00300000, // 0xff1300000ULL,
84         .intr_offset  = 0x00400000, // 0xff1400000ULL,
85         .intr_ncpu    = 4,
86         .aux1_offset  = 0x00800000, // 0xff1800000ULL,
87         .aux2_offset  = 0x00a01000, // 0xff1a01000ULL,
88         .dma_base     = 0xef0400000ULL,
89         .esp_base     = 0xef0800000ULL,
90         .le_base      = 0xef0c00000ULL,
91         .simm_size    = 0x4000000,
92         .mid_offset   = 8,
93         .machine_id_low = 64,
94         .machine_id_high = 65,
95     },
96     /* SS-600MP */
97     {
98         .iommu_base   = 0xfe0000000ULL,
99         .tcx_base     = 0xe20000000ULL,
100         .slavio_base  = 0xff1000000ULL,
101         .ms_kb_base   = 0xff1000000ULL,
102         .serial_base  = 0xff1100000ULL,
103         .nvram_base   = 0xff1200000ULL,
104         .fd_offset    = -1,
105         .counter_offset = 0x00300000, // 0xff1300000ULL,
106         .intr_offset  = 0x00400000, // 0xff1400000ULL,
107         .intr_ncpu    = 4,
108         .aux1_offset  = 0x00800000, // 0xff1800000ULL,
109         .aux2_offset  = 0x00a01000, // 0xff1a01000ULL, XXX should not exist
110         .dma_base     = 0xef0081000ULL,
111         .esp_base     = 0xef0080000ULL,
112         .le_base      = 0xef0060000ULL,
113         .simm_size    = 0x4000000,
114         .mid_offset   = 8,
115         .machine_id_low = 66,
116         .machine_id_high = 66,
117     },
118 };
119 
120 static const struct hwdef *hwdef;
121 
setup_timers(void)122 void setup_timers(void)
123 {
124 }
125 
udelay(unsigned int usecs)126 void udelay(unsigned int usecs)
127 {
128 }
129 
mdelay(unsigned int msecs)130 void mdelay(unsigned int msecs)
131 {
132 }
133 
mb86904_init(void)134 static void mb86904_init(void)
135 {
136     PUSH(32);
137     fword("encode-int");
138     push_str("cache-line-size");
139     fword("property");
140 
141     PUSH(512);
142     fword("encode-int");
143     push_str("cache-nlines");
144     fword("property");
145 
146     PUSH(0x23);
147     fword("encode-int");
148     push_str("mask_rev");
149     fword("property");
150 }
151 
tms390z55_init(void)152 static void tms390z55_init(void)
153 {
154     push_str("");
155     fword("encode-string");
156     push_str("ecache-parity?");
157     fword("property");
158 
159     push_str("");
160     fword("encode-string");
161     push_str("bfill?");
162     fword("property");
163 
164     push_str("");
165     fword("encode-string");
166     push_str("bcopy?");
167     fword("property");
168 
169     push_str("");
170     fword("encode-string");
171     push_str("cache-physical?");
172     fword("property");
173 
174     PUSH(0xf);
175     fword("encode-int");
176     PUSH(0xf8fffffc);
177     fword("encode-int");
178     fword("encode+");
179     PUSH(4);
180     fword("encode-int");
181     fword("encode+");
182 
183     PUSH(0xf);
184     fword("encode-int");
185     fword("encode+");
186     PUSH(0xf8c00000);
187     fword("encode-int");
188     fword("encode+");
189     PUSH(0x1000);
190     fword("encode-int");
191     fword("encode+");
192 
193     PUSH(0xf);
194     fword("encode-int");
195     fword("encode+");
196     PUSH(0xf8000000);
197     fword("encode-int");
198     fword("encode+");
199     PUSH(0x1000);
200     fword("encode-int");
201     fword("encode+");
202 
203     PUSH(0xf);
204     fword("encode-int");
205     fword("encode+");
206     PUSH(0xf8800000);
207     fword("encode-int");
208     fword("encode+");
209     PUSH(0x1000);
210     fword("encode-int");
211     fword("encode+");
212     push_str("reg");
213     fword("property");
214 }
215 
rt625_init(void)216 static void rt625_init(void)
217 {
218     PUSH(32);
219     fword("encode-int");
220     push_str("cache-line-size");
221     fword("property");
222 
223     PUSH(512);
224     fword("encode-int");
225     push_str("cache-nlines");
226     fword("property");
227 
228 }
229 
bad_cpu_init(void)230 static void bad_cpu_init(void)
231 {
232     printk("This CPU is not supported yet, freezing.\n");
233     for(;;);
234 }
235 
236 struct cpudef {
237     unsigned long iu_version;
238     const char *name;
239     int psr_impl, psr_vers, impl, vers;
240     int dcache_line_size, dcache_lines, dcache_assoc;
241     int icache_line_size, icache_lines, icache_assoc;
242     int ecache_line_size, ecache_lines, ecache_assoc;
243     int mmu_nctx;
244     void (*initfn)(void);
245 };
246 
247 static const struct cpudef sparc_defs[] = {
248     {
249         .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
250         .name = "FMI,MB86900",
251         .initfn = bad_cpu_init,
252     },
253     {
254         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
255         .name = "FMI,MB86904",
256         .psr_impl = 0,
257         .psr_vers = 4,
258         .impl = 0,
259         .vers = 4,
260         .dcache_line_size = 0x10,
261         .dcache_lines = 0x200,
262         .dcache_assoc = 1,
263         .icache_line_size = 0x20,
264         .icache_lines = 0x200,
265         .icache_assoc = 1,
266         .ecache_line_size = 0x20,
267         .ecache_lines = 0x4000,
268         .ecache_assoc = 1,
269         .mmu_nctx = 0x100,
270         .initfn = mb86904_init,
271     },
272     {
273         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
274         .name = "FMI,MB86907",
275         .psr_impl = 0,
276         .psr_vers = 5,
277         .impl = 0,
278         .vers = 5,
279         .dcache_line_size = 0x20,
280         .dcache_lines = 0x200,
281         .dcache_assoc = 1,
282         .icache_line_size = 0x20,
283         .icache_lines = 0x200,
284         .icache_assoc = 1,
285         .ecache_line_size = 0x20,
286         .ecache_lines = 0x4000,
287         .ecache_assoc = 1,
288         .mmu_nctx = 0x100,
289         .initfn = mb86904_init,
290     },
291     {
292         .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
293         .name = "LSI,L64811",
294         .initfn = bad_cpu_init,
295     },
296     {
297         .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
298         .name = "CY,CY7C601",
299         .psr_impl = 1,
300         .psr_vers = 1,
301         .impl = 1,
302         .vers = 1,
303         .mmu_nctx = 0x10,
304         .initfn = bad_cpu_init,
305     },
306     {
307         .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
308         .name = "CY,CY7C611",
309         .initfn = bad_cpu_init,
310     },
311     {
312         .iu_version = 0x40000000,
313         .name = "TI,TMS390Z55",
314         .psr_impl = 4,
315         .psr_vers = 0,
316         .impl = 0,
317         .vers = 4,
318         .dcache_line_size = 0x20,
319         .dcache_lines = 0x80,
320         .dcache_assoc = 4,
321         .icache_line_size = 0x40,
322         .icache_lines = 0x40,
323         .icache_assoc = 5,
324         .ecache_line_size = 0x20,
325         .ecache_lines = 0x8000,
326         .ecache_assoc = 1,
327         .mmu_nctx = 0x10000,
328         .initfn = tms390z55_init,
329     },
330     {
331         .iu_version = 0x41000000,
332         .name = "TI,TMS390S10",
333         .psr_impl = 4,
334         .psr_vers = 1,
335         .impl = 4,
336         .vers = 1,
337         .dcache_line_size = 0x10,
338         .dcache_lines = 0x80,
339         .dcache_assoc = 4,
340         .icache_line_size = 0x20,
341         .icache_lines = 0x80,
342         .icache_assoc = 5,
343         .ecache_line_size = 0x20,
344         .ecache_lines = 0x8000,
345         .ecache_assoc = 1,
346         .mmu_nctx = 0x10000,
347         .initfn = tms390z55_init,
348     },
349     {
350         .iu_version = 0x42000000,
351         .name = "TI,TMS390S10",
352         .psr_impl = 4,
353         .psr_vers = 2,
354         .impl = 4,
355         .vers = 2,
356         .dcache_line_size = 0x10,
357         .dcache_lines = 0x80,
358         .dcache_assoc = 4,
359         .icache_line_size = 0x20,
360         .icache_lines = 0x80,
361         .icache_assoc = 5,
362         .ecache_line_size = 0x20,
363         .ecache_lines = 0x8000,
364         .ecache_assoc = 1,
365         .mmu_nctx = 0x10000,
366         .initfn = tms390z55_init,
367     },
368     {
369         .iu_version = 0x43000000,
370         .name = "TI,TMS390S10",
371         .psr_impl = 4,
372         .psr_vers = 3,
373         .impl = 4,
374         .vers = 3,
375         .dcache_line_size = 0x10,
376         .dcache_lines = 0x80,
377         .dcache_assoc = 4,
378         .icache_line_size = 0x20,
379         .icache_lines = 0x80,
380         .icache_assoc = 5,
381         .ecache_line_size = 0x20,
382         .ecache_lines = 0x8000,
383         .ecache_assoc = 1,
384         .mmu_nctx = 0x10000,
385         .initfn = tms390z55_init,
386     },
387     {
388         .iu_version = 0x44000000,
389         .name = "TI,TMS390S10",
390         .psr_impl = 4,
391         .psr_vers = 4,
392         .impl = 4,
393         .vers = 4,
394         .dcache_line_size = 0x10,
395         .dcache_lines = 0x80,
396         .dcache_assoc = 4,
397         .icache_line_size = 0x20,
398         .icache_lines = 0x80,
399         .icache_assoc = 5,
400         .ecache_line_size = 0x20,
401         .ecache_lines = 0x8000,
402         .ecache_assoc = 1,
403         .mmu_nctx = 0x10000,
404         .initfn = tms390z55_init,
405     },
406     {
407         .iu_version = 0x1e000000,
408         .name = "Ross,RT625",
409         .psr_impl = 1,
410         .psr_vers = 14,
411         .impl = 1,
412         .vers = 7,
413         .dcache_line_size = 0x20,
414         .dcache_lines = 0x80,
415         .dcache_assoc = 4,
416         .icache_line_size = 0x40,
417         .icache_lines = 0x40,
418         .icache_assoc = 5,
419         .ecache_line_size = 0x20,
420         .ecache_lines = 0x8000,
421         .ecache_assoc = 1,
422         .mmu_nctx = 0x10000,
423         .initfn = rt625_init,
424     },
425     {
426         .iu_version = 0x1f000000,
427         .name = "Ross,RT620",
428         .psr_impl = 1,
429         .psr_vers = 15,
430         .impl = 1,
431         .vers = 7,
432         .dcache_line_size = 0x20,
433         .dcache_lines = 0x80,
434         .dcache_assoc = 4,
435         .icache_line_size = 0x40,
436         .icache_lines = 0x40,
437         .icache_assoc = 5,
438         .ecache_line_size = 0x20,
439         .ecache_lines = 0x8000,
440         .ecache_assoc = 1,
441         .mmu_nctx = 0x10000,
442         .initfn = rt625_init,
443     },
444     {
445         .iu_version = 0x20000000,
446         .name = "BIT,B5010",
447         .initfn = bad_cpu_init,
448     },
449     {
450         .iu_version = 0x50000000,
451         .name = "MC,MN10501",
452         .initfn = bad_cpu_init,
453     },
454     {
455         .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
456         .name = "Weitek,W8601",
457         .initfn = bad_cpu_init,
458     },
459     {
460         .iu_version = 0xf2000000,
461         .name = "GR,LEON2",
462         .initfn = bad_cpu_init,
463     },
464     {
465         .iu_version = 0xf3000000,
466         .name = "GR,LEON3",
467         .initfn = bad_cpu_init,
468     },
469 };
470 
471 static const struct cpudef *
id_cpu(void)472 id_cpu(void)
473 {
474     unsigned long iu_version;
475     unsigned int i;
476 
477     asm("rd %%psr, %0\n"
478         : "=r"(iu_version) :);
479     iu_version &= 0xff000000;
480 
481     for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
482         if (iu_version == sparc_defs[i].iu_version)
483             return &sparc_defs[i];
484     }
485     printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
486     for (;;);
487 }
488 
setup_cpu(int mid_offset)489 static void setup_cpu(int mid_offset)
490 {
491     uint32_t temp;
492     unsigned int i;
493     const struct cpudef *cpu;
494 
495     // Add cpus
496     temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
497 
498     printk("CPUs: %x", temp);
499     cpu = id_cpu();
500     printk(" x %s\n", cpu->name);
501     for (i = 0; i < temp; i++) {
502         push_str("/");
503         fword("find-device");
504 
505         fword("new-device");
506 
507         push_str(cpu->name);
508         fword("device-name");
509 
510         push_str("cpu");
511         fword("device-type");
512 
513         PUSH(cpu->psr_impl);
514         fword("encode-int");
515         push_str("psr-implementation");
516         fword("property");
517 
518         PUSH(cpu->psr_vers);
519         fword("encode-int");
520         push_str("psr-version");
521         fword("property");
522 
523         PUSH(cpu->impl);
524         fword("encode-int");
525         push_str("implementation");
526         fword("property");
527 
528         PUSH(cpu->vers);
529         fword("encode-int");
530         push_str("version");
531         fword("property");
532 
533         PUSH(4096);
534         fword("encode-int");
535         push_str("page-size");
536         fword("property");
537 
538         PUSH(cpu->dcache_line_size);
539         fword("encode-int");
540         push_str("dcache-line-size");
541         fword("property");
542 
543         PUSH(cpu->dcache_lines);
544         fword("encode-int");
545         push_str("dcache-nlines");
546         fword("property");
547 
548         PUSH(cpu->dcache_assoc);
549         fword("encode-int");
550         push_str("dcache-associativity");
551         fword("property");
552 
553         PUSH(cpu->icache_line_size);
554         fword("encode-int");
555         push_str("icache-line-size");
556         fword("property");
557 
558         PUSH(cpu->icache_lines);
559         fword("encode-int");
560         push_str("icache-nlines");
561         fword("property");
562 
563         PUSH(cpu->icache_assoc);
564         fword("encode-int");
565         push_str("icache-associativity");
566         fword("property");
567 
568         PUSH(cpu->ecache_line_size);
569         fword("encode-int");
570         push_str("ecache-line-size");
571         fword("property");
572 
573         PUSH(cpu->ecache_lines);
574         fword("encode-int");
575         push_str("ecache-nlines");
576         fword("property");
577 
578         PUSH(cpu->ecache_assoc);
579         fword("encode-int");
580         push_str("ecache-associativity");
581         fword("property");
582 
583         PUSH(2);
584         fword("encode-int");
585         push_str("ncaches");
586         fword("property");
587 
588         PUSH(cpu->mmu_nctx);
589         fword("encode-int");
590         push_str("mmu-nctx");
591         fword("property");
592 
593         PUSH(8);
594         fword("encode-int");
595         push_str("sparc-version");
596         fword("property");
597 
598         push_str("");
599         fword("encode-string");
600         push_str("cache-coherence?");
601         fword("property");
602 
603         PUSH(i + mid_offset);
604         fword("encode-int");
605         push_str("mid");
606         fword("property");
607 
608         cpu->initfn();
609 
610         fword("finish-device");
611     }
612 }
613 
dummy_mach_init(uint64_t base)614 static void dummy_mach_init(uint64_t base)
615 {
616 }
617 
618 struct machdef {
619     uint16_t machine_id;
620     const char *banner_name;
621     const char *model;
622     const char *name;
623     void (*initfn)(uint64_t base);
624 };
625 
626 static const struct machdef sun4m_defs[] = {
627     {
628         .machine_id = 32,
629         .banner_name = "SPARCstation 5",
630         .model = "SUNW,501-3059",
631         .name = "SUNW,SPARCstation-5",
632         .initfn = ss5_init,
633     },
634     {
635         .machine_id = 33,
636         .banner_name = "SPARCstation Voyager",
637         .model = "SUNW,501-2581",
638         .name = "SUNW,SPARCstation-Voyager",
639         .initfn = dummy_mach_init,
640     },
641     {
642         .machine_id = 34,
643         .banner_name = "SPARCstation LX",
644         .model = "SUNW,501-2031",
645         .name = "SUNW,SPARCstation-LX",
646         .initfn = dummy_mach_init,
647     },
648     {
649         .machine_id = 35,
650         .banner_name = "SPARCstation 4",
651         .model = "SUNW,501-2572",
652         .name = "SUNW,SPARCstation-4",
653         .initfn = ss5_init,
654     },
655     {
656         .machine_id = 36,
657         .banner_name = "SPARCstation Classic",
658         .model = "SUNW,501-2326",
659         .name = "SUNW,SPARCstation-Classic",
660         .initfn = dummy_mach_init,
661     },
662     {
663         .machine_id = 37,
664         .banner_name = "Tadpole S3 GX",
665         .model = "S3",
666         .name = "Tadpole_S3GX",
667         .initfn = ss5_init,
668     },
669     {
670         .machine_id = 64,
671         .banner_name = "SPARCstation 10 (1 X 390Z55)",
672         .model = "SUNW,S10,501-2365",
673         .name = "SUNW,SPARCstation-10",
674         .initfn = ob_eccmemctl_init,
675     },
676     {
677         .machine_id = 65,
678         .banner_name = "SPARCstation 20 (1 X 390Z55)",
679         .model = "SUNW,S20,501-2324",
680         .name = "SUNW,SPARCstation-20",
681         .initfn = ob_eccmemctl_init,
682     },
683     {
684         .machine_id = 66,
685         .banner_name = "SPARCsystem 600(1 X 390Z55)",
686         .model = NULL,
687         .name = "SUNW,SPARCsystem-600",
688         .initfn = ob_eccmemctl_init,
689     },
690 };
691 
692 static const struct machdef *
id_machine(uint16_t machine_id)693 id_machine(uint16_t machine_id)
694 {
695     unsigned int i;
696 
697     for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
698         if (machine_id == sun4m_defs[i].machine_id)
699             return &sun4m_defs[i];
700     }
701     printk("Unknown machine (ID %d), freezing!\n", machine_id);
702     for (;;);
703 }
704 
setup_machine(uint64_t base)705 static void setup_machine(uint64_t base)
706 {
707     uint16_t machine_id;
708     const struct machdef *mach;
709 
710     machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
711     mach = id_machine(machine_id);
712 
713     push_str("/");
714     fword("find-device");
715     push_str(mach->banner_name);
716     fword("encode-string");
717     push_str("banner-name");
718     fword("property");
719 
720     if (mach->model) {
721         push_str(mach->model);
722         fword("encode-string");
723         push_str("model");
724         fword("property");
725     }
726     push_str(mach->name);
727     fword("encode-string");
728     push_str("name");
729     fword("property");
730 
731     mach->initfn(base);
732 }
733 
734 /* Add /uuid */
setup_uuid(void)735 static void setup_uuid(void)
736 {
737     static uint8_t qemu_uuid[16];
738 
739     fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
740 
741     printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
742            qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
743            qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
744            qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
745            qemu_uuid[15]);
746 
747     push_str("/");
748     fword("find-device");
749 
750     PUSH((long)&qemu_uuid);
751     PUSH(16);
752     fword("encode-bytes");
753     push_str("uuid");
754     fword("property");
755 }
756 
setup_stdio(void)757 static void setup_stdio(void)
758 {
759     char nographic;
760     const char *stdin, *stdout;
761     phandle_t display_ph;
762 
763     fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
764 
765     /* Check to see if any framebuffer present */
766     display_ph = dt_iterate_type(0, "display");
767     if (display_ph == 0) {
768         nographic = 1;
769     }
770 
771     if (nographic) {
772         obp_stdin = PROMDEV_TTYA;
773         obp_stdout = PROMDEV_TTYA;
774         stdin = "ttya";
775         stdout = "ttya";
776     } else {
777         obp_stdin = PROMDEV_KBD;
778         obp_stdout = PROMDEV_SCREEN;
779         stdin = "keyboard";
780         stdout = "screen";
781     }
782 
783     push_str(stdin);
784     push_str("input-device");
785     fword("$setenv");
786 
787     push_str(stdout);
788     push_str("output-device");
789     fword("$setenv");
790 
791     obp_stdin_path = stdin;
792     obp_stdout_path = stdout;
793 }
794 
init_memory(void)795 static void init_memory(void)
796 {
797     phys_addr_t phys;
798     ucell virt;
799 
800     /* Claim the memory from OFMEM */
801     phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE);
802     if (!phys)
803         printk("panic: not enough physical memory on host system.\n");
804 
805     virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0);
806     if (!virt)
807         printk("panic: not enough virtual memory on host system.\n");
808 
809     /* Generate the mapping (and lock translation into the TLBs) */
810     ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys));
811 
812     /* we push start and end of memory to the stack
813      * so that it can be used by the forth word QUIT
814      * to initialize the memory allocator
815      */
816 
817     PUSH(virt);
818     PUSH(virt + MEMORY_SIZE);
819 }
820 
821 /* ( size -- virt ) */
822 static void
dma_alloc(void)823 dma_alloc(void)
824 {
825     ucell size = POP();
826     unsigned long *va;
827 
828     va = dvma_alloc(size);
829 
830     PUSH(pointer2cell(va));
831 }
832 
833 /* ( virt devaddr size -- ) */
834 static void
dma_sync(void)835 dma_sync(void)
836 {
837     ucell size = POP();
838     POP();
839     ucell virt = POP();
840 
841     dvma_sync(cell2pointer(virt), size);
842 }
843 
844 /* ( virt size cacheable? -- devaddr ) */
845 static void
dma_map_in(void)846 dma_map_in(void)
847 {
848     unsigned int iova;
849 
850     POP();
851     POP();
852     ucell virt = POP();
853 
854     iova = dvma_map_in(cell2pointer(virt));
855     PUSH((ucell)iova);
856 }
857 
858 static void
arch_init(void)859 arch_init( void )
860 {
861 	char *cmdline;
862         const char *kernel_cmdline;
863         uint32_t temp;
864         uint16_t machine_id;
865         char buf[256];
866         unsigned long mem_size;
867 
868         fw_cfg_init();
869 
870         fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
871         buf[4] = '\0';
872 
873         printk("Configuration device id %s", buf);
874 
875         temp = fw_cfg_read_i32(FW_CFG_ID);
876         machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
877 
878         printk(" version %d machine id %d\n", temp, machine_id);
879 
880         if (temp != 1) {
881             printk("Incompatible configuration device version, freezing\n");
882             for(;;);
883         }
884 
885         graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH);
886 
887 	openbios_init();
888 	modules_init();
889         ob_init_mmu(hwdef->simm_size);
890         ob_init_iommu(hwdef->iommu_base);
891 
892         bind_func("(sparc32-dma-alloc)", dma_alloc);
893         feval("['] (sparc32-dma-alloc) to (dma-alloc)");
894         bind_func("(sparc32-dma-sync)", dma_sync);
895         feval("['] (sparc32-dma-sync) to (dma-sync)");
896         bind_func("(sparc32-dma-map-in)", dma_map_in);
897         feval("['] (sparc32-dma-map-in) to (dma-map-in)");
898 
899 #ifdef CONFIG_DRIVER_OBIO
900         mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
901 	ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
902                      hwdef->counter_offset, hwdef->intr_offset, hwdef->intr_ncpu,
903                      hwdef->aux1_offset, hwdef->aux2_offset,
904                      mem_size);
905 
906         setup_machine(hwdef->slavio_base);
907 
908         nvconf_init();
909 #endif
910 #ifdef CONFIG_DRIVER_SBUS
911 #ifdef CONFIG_DEBUG_CONSOLE_VIDEO
912 	setup_video();
913 #endif
914 	ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
915 #endif
916 	device_end();
917 
918         setup_cpu(hwdef->mid_offset);
919 
920         setup_stdio();
921 	/* Initialiase openprom romvec */
922         romvec = init_openprom();
923 
924 	kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
925 	if (kernel_size) {
926 		kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
927 
928 		/* Map krnel memory a similar way to SILO */
929 		ofmem_map(PAGE_ALIGN(kernel_image), IMAGE_VIRT_ADDR, PAGE_ALIGN(kernel_size), -1);
930 	}
931 
932     kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
933     if (kernel_cmdline) {
934         cmdline = strdup(kernel_cmdline);
935     } else {
936         cmdline = strdup("");
937     }
938     obp_arg.argv[1] = cmdline;
939     qemu_cmdline = (uint32_t)cmdline;
940 
941     initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE);
942     if (initrd_size) {
943         initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR);
944 
945         /* Map krnel memory a similar way to SILO */
946         ofmem_map(PAGE_ALIGN(initrd_image), INITRD_VIRT_ADDR, PAGE_ALIGN(initrd_size), -1);
947     }
948 
949     if (kernel_size)
950         printk("kernel phys 0x%x virt 0x%x size 0x%x\n", kernel_image, 0x4000, kernel_size);
951     if (initrd_size)
952         printk("initrd phys 0x%x virt 0x%x size 0x%x\n", initrd_image, INITRD_VIRT_ADDR, initrd_size);
953 
954     /* Setup nvram variables */
955     push_str("/options");
956     fword("find-device");
957     push_str(cmdline);
958     fword("encode-string");
959     push_str("boot-file");
960     fword("property");
961 
962 	boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
963 
964 	switch (boot_device) {
965 	case 'a':
966 		push_str("floppy");
967 		break;
968 	case 'c':
969 		push_str("disk:a disk");
970 		break;
971 	default:
972 	case 'd':
973 		push_str("cdrom:d cdrom");
974 		break;
975 	case 'n':
976 		push_str("net");
977 		break;
978 	}
979 
980 	fword("encode-string");
981 	push_str("boot-device");
982 	fword("property");
983 
984 	device_end();
985 
986 	bind_func("platform-boot", boot );
987 	bind_func("(arch-go)", setup_romvec );
988 
989 	/* Set up other properties */
990         push_str("/chosen");
991         fword("find-device");
992 
993         setup_uuid();
994 
995 	/* Enable interrupts */
996 	temp = get_psr();
997 	temp = (temp & ~PSR_PIL) | (13 << 8); /* Enable CPU timer interrupt (level 14) */
998 	put_psr(temp);
999 }
1000 
1001 extern struct _console_ops arch_console_ops;
1002 
openbios(void)1003 int openbios(void)
1004 {
1005         unsigned int i;
1006 
1007         for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
1008             if (hwdefs[i].machine_id_low <= qemu_machine_type &&
1009                 hwdefs[i].machine_id_high >= qemu_machine_type) {
1010                 hwdef = &hwdefs[i];
1011                 break;
1012             }
1013         }
1014         if (!hwdef)
1015             for(;;); // Internal inconsistency, hang
1016 
1017 #ifdef CONFIG_DEBUG_CONSOLE
1018         init_console(arch_console_ops);
1019 #endif
1020         /* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */
1021         ofmem_init();
1022 
1023 #ifdef CONFIG_DRIVER_SBUS
1024         init_mmu_swift();
1025 #endif
1026 #ifdef CONFIG_DEBUG_CONSOLE
1027 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
1028 	escc_uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL),
1029                   CONFIG_SERIAL_SPEED);
1030 #endif
1031 #ifdef CONFIG_DEBUG_CONSOLE_VIDEO
1032 	kbd_init(hwdef->ms_kb_base);
1033 #endif
1034 #endif
1035 
1036         collect_sys_info(&sys_info);
1037 
1038         dict = (unsigned char *)sys_info.dict_start;
1039         dicthead = (cell)sys_info.dict_end;
1040         last = sys_info.dict_last;
1041         dictlimit = sys_info.dict_limit;
1042 
1043 	forth_init();
1044 
1045 #ifdef CONFIG_DEBUG_BOOT
1046 	printk("forth started.\n");
1047 	printk("initializing memory...");
1048 #endif
1049 
1050 	init_memory();
1051 
1052 #ifdef CONFIG_DEBUG_BOOT
1053 	printk("done\n");
1054 #endif
1055 
1056 	PUSH_xt( bind_noname_func(arch_init) );
1057 	fword("PREPOST-initializer");
1058 
1059 	PC = (ucell)findword("initialize-of");
1060 
1061 	if (!PC) {
1062 		printk("panic: no dictionary entry point.\n");
1063 		return -1;
1064 	}
1065 #ifdef CONFIG_DEBUG_DICTIONARY
1066 	printk("done (%d bytes).\n", dicthead);
1067 	printk("Jumping to dictionary...\n");
1068 #endif
1069 
1070 	enterforth((xt_t)PC);
1071 
1072         free(dict);
1073 	return 0;
1074 }
1075