2 * Creation Date: <2004/08/28 18:38:22 greg>
3 * Time-stamp: <2004/08/28 18:38:22 greg>
7 * Initialization for qemu
9 * Copyright (C) 2004 Greg Watson
10 * Copyright (C) 2005 Stefan Reinauer
12 * based on mol/init.c:
14 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
15 * (samuel@ibrium.se, dary@lindesign.se)
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
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"
39 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
42 unsigned int iu_version;
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);
51 static uint16_t machine_id = 0;
53 extern void unexpected_excep(int vector);
56 unexpected_excep(int vector)
58 printk("openbios panic: Unexpected exception %x\n", vector);
63 extern void __divide_error(void);
80 return is_oldworld() || is_newworld();
85 return machine_id == ARCH_HEATHROW;
90 return (machine_id == ARCH_MAC99) ||
91 (machine_id == ARCH_MAC99_U3);
94 static const pci_arch_t known_arch[] = {
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,
110 .irqs = { 9, 11, 9, 11 }
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,
127 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
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,
144 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
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,
161 .irqs = { 21, 22, 23, 24 }
164 unsigned long isa_io_base;
166 extern struct _console_ops mac_console_ops, prep_console_ops;
174 arch = &known_arch[ARCH_HEATHROW];
178 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
180 if (strncmp(buf, "QEMU", 4) == 0) {
181 temp = fw_cfg_read_i32(FW_CFG_ID);
183 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
184 arch = &known_arch[machine_id];
188 isa_io_base = arch->io_base;
190 #ifdef CONFIG_DEBUG_CONSOLE
192 init_console(mac_console_ops);
194 init_console(prep_console_ops);
199 printk("Incompatible configuration device version, freezing\n");
208 printk("of_startup returned!\n");
213 /* -- phys.lo ... phys.hi */
215 push_physaddr(phys_addr_t value)
223 /* From drivers/timer.c */
224 extern unsigned long timer_freq;
227 cpu_generic_init(const struct cpudef *cpu)
230 fword("find-device");
235 fword("device-name");
238 fword("device-type");
242 push_str("cpu-version");
245 PUSH(cpu->dcache_size);
247 push_str("d-cache-size");
250 PUSH(cpu->icache_size);
252 push_str("i-cache-size");
255 PUSH(cpu->dcache_sets);
257 push_str("d-cache-sets");
260 PUSH(cpu->icache_sets);
262 push_str("i-cache-sets");
265 PUSH(cpu->dcache_block_size);
267 push_str("d-cache-block-size");
270 PUSH(cpu->icache_block_size);
272 push_str("i-cache-block-size");
277 push_str("tlb-sets");
282 push_str("tlb-size");
285 timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ);
288 push_str("timebase-frequency");
291 PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ));
293 push_str("clock-frequency");
296 PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
298 push_str("bus-frequency");
302 fword("encode-string");
308 push_str("reservation-granule-size");
313 cpu_add_pir_property(void)
317 asm("mfspr %0, 1023\n"
326 cpu_604_init(const struct cpudef *cpu)
328 cpu_generic_init(cpu);
329 cpu_add_pir_property();
331 fword("finish-device");
335 cpu_750_init(const struct cpudef *cpu)
337 cpu_generic_init(cpu);
344 fword("finish-device");
348 cpu_g4_init(const struct cpudef *cpu)
350 cpu_generic_init(cpu);
351 cpu_add_pir_property();
353 fword("finish-device");
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. */
361 ppc64_patch_handlers(void)
363 uint32_t *dsi = (uint32_t *)0x300UL;
364 uint32_t *isi = (uint32_t *)0x400UL;
366 // Patch the first DSI handler instruction to: ba 0x2000
369 // Patch the first ISI handler instruction to: ba 0x2200
372 // Invalidate the cache lines
373 asm ("icbi 0, %0" : : "r"(dsi));
374 asm ("icbi 0, %0" : : "r"(isi));
379 cpu_970_init(const struct cpudef *cpu)
381 cpu_generic_init(cpu);
390 fword("encode-bytes");
394 fword("finish-device");
396 #ifdef CONFIG_PPC_64BITSUPPORT
397 /* The 970 is a PPC64 CPU, so we need to activate
398 * 64bit aware interrupt handlers */
400 ppc64_patch_handlers();
403 /* The 970 also implements the HIOR which we need to set to 0 */
408 static const struct cpudef ppc_defs[] = {
410 .iu_version = 0x00040000,
411 .name = "PowerPC,604",
412 .icache_size = 0x4000,
413 .dcache_size = 0x4000,
416 .icache_block_size = 0x20,
417 .dcache_block_size = 0x20,
420 .initfn = cpu_604_init,
422 { // XXX find out real values
423 .iu_version = 0x00090000,
424 .name = "PowerPC,604e",
425 .icache_size = 0x4000,
426 .dcache_size = 0x4000,
429 .icache_block_size = 0x20,
430 .dcache_block_size = 0x20,
433 .initfn = cpu_604_init,
435 { // XXX find out real values
436 .iu_version = 0x000a0000,
437 .name = "PowerPC,604r",
438 .icache_size = 0x4000,
439 .dcache_size = 0x4000,
442 .icache_block_size = 0x20,
443 .dcache_block_size = 0x20,
446 .initfn = cpu_604_init,
448 { // XXX find out real values
449 .iu_version = 0x80040000,
450 .name = "PowerPC,MPC86xx",
451 .icache_size = 0x8000,
452 .dcache_size = 0x8000,
455 .icache_block_size = 0x20,
456 .dcache_block_size = 0x20,
459 .initfn = cpu_750_init,
462 .iu_version = 0x000080000,
463 .name = "PowerPC,750",
464 .icache_size = 0x8000,
465 .dcache_size = 0x8000,
468 .icache_block_size = 0x20,
469 .dcache_block_size = 0x20,
472 .initfn = cpu_750_init,
474 { // XXX find out real values
475 .iu_version = 0x10080000,
476 .name = "PowerPC,750",
477 .icache_size = 0x8000,
478 .dcache_size = 0x8000,
481 .icache_block_size = 0x20,
482 .dcache_block_size = 0x20,
485 .initfn = cpu_750_init,
487 { // XXX find out real values
488 .iu_version = 0x70000000,
489 .name = "PowerPC,750",
490 .icache_size = 0x8000,
491 .dcache_size = 0x8000,
494 .icache_block_size = 0x20,
495 .dcache_block_size = 0x20,
498 .initfn = cpu_750_init,
500 { // XXX find out real values
501 .iu_version = 0x70020000,
502 .name = "PowerPC,750",
503 .icache_size = 0x8000,
504 .dcache_size = 0x8000,
507 .icache_block_size = 0x20,
508 .dcache_block_size = 0x20,
511 .initfn = cpu_750_init,
513 { // XXX find out real values
514 .iu_version = 0x800c0000,
515 .name = "PowerPC,74xx",
516 .icache_size = 0x8000,
517 .dcache_size = 0x8000,
520 .icache_block_size = 0x20,
521 .dcache_block_size = 0x20,
524 .initfn = cpu_750_init,
527 .iu_version = 0x0000c0000,
528 .name = "PowerPC,G4",
529 .icache_size = 0x8000,
530 .dcache_size = 0x8000,
533 .icache_block_size = 0x20,
534 .dcache_block_size = 0x20,
537 .initfn = cpu_g4_init,
540 .iu_version = 0x00390000,
541 .name = "PowerPC,970",
542 .icache_size = 0x10000,
543 .dcache_size = 0x8000,
544 .icache_sets = 0x200,
546 .icache_block_size = 0x80,
547 .dcache_block_size = 0x80,
550 .initfn = cpu_970_init,
552 { // XXX find out real values
553 .iu_version = 0x003C0000,
554 .name = "PowerPC,970FX",
555 .icache_size = 0x10000,
556 .dcache_size = 0x8000,
559 .icache_block_size = 0x80,
560 .dcache_block_size = 0x80,
563 .initfn = cpu_970_init,
566 .iu_version = 0x00350000,
567 .name = "PowerPC,POWER4",
568 .icache_size = 0x10000,
569 .dcache_size = 0x8000,
570 .icache_sets = 0x100,
572 .icache_block_size = 0x80,
573 .dcache_block_size = 0x80,
576 .initfn = cpu_970_init,
580 static const struct cpudef *
583 unsigned int iu_version;
586 iu_version = mfpvr() & 0xffff0000;
588 for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) {
589 if (iu_version == ppc_defs[i].iu_version)
592 printk("Unknown cpu (pvr %x), freezing!\n", iu_version);
597 static void go(void);
604 /* Insert copyright property for MacOS 9 and below */
605 if (find_dev("/rom/macos")) {
606 fword("insert-copyright-property");
609 feval("saved-program-state >sps.entry @");
612 call_elf(0, 0, addr);
615 static void kvm_of_init(void)
617 char hypercall[4 * 4];
620 /* Don't expose /hypervisor when not in KVM */
621 if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
625 fword("find-device");
629 push_str("hypervisor");
630 fword("device-name");
632 push_str("hypervisor");
633 fword("device-type");
637 push_str("linux,kvm");
638 fword("encode-string");
639 push_str("epapr,hypervisor-0.2");
640 fword("encode-string");
642 push_str("compatible");
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;
659 push_str("hcall-instructions");
662 /* ePAPR requires us to provide a unique guest id */
663 PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
665 push_str("guest-id");
668 /* ePAPR requires us to provide a guest name */
669 push_str("KVM guest");
670 fword("encode-string");
671 push_str("guest-name");
674 fword("finish-device");
678 * filll ( addr bytes quad -- )
681 static void ffilll(void)
683 const u32 longval = POP();
685 u32 *laddr = (u32 *)cell2pointer(POP());
688 for (len = 0; len < bytes / sizeof(u32); len++) {
694 * adler32 ( adler buf len -- checksum )
696 * Adapted from Mark Adler's original implementation (zlib license)
698 * Both OS 9 and BootX require this word for payload validation.
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);
707 static void adler32(void)
709 uint32_t len = (uint32_t)POP();
710 char *buf = (char *)POP();
711 uint32_t adler = (uint32_t)POP();
717 uint32_t base = 65521;
718 uint32_t nmax = 5552;
720 uint32_t s1 = adler & 0xffff;
721 uint32_t s2 = (adler >> 16) & 0xffff;
725 k = (len < nmax ? len : nmax);
754 const struct cpudef *cpu;
755 char buf[64], qemu_uuid[16];
756 const char *stdin_path, *stdout_path, *boot_path;
759 ofmem_t *ofmem = ofmem_arch_get_private();
764 #ifdef CONFIG_DRIVER_PCI
769 printk("=============================================================\n");
770 printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
771 OPENBIOS_BUILD_DATE);
773 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
775 printk("Configuration device id %s", buf);
777 temp = fw_cfg_read_i32(FW_CFG_ID);
778 printk(" version %d machine id %d\n", temp, machine_id);
780 temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
782 printk("CPUs: %x\n", temp);
784 ram_size = ofmem->ramsize;
786 printk("Memory: %lldM\n", ram_size / 1024 / 1024);
788 fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
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],
796 /* set device tree root info */
799 fword("find-device");
802 case ARCH_HEATHROW: /* OldWorld */
806 push_str("Power Macintosh");
811 push_str("AAPL,PowerMac G3");
812 fword("encode-string");
814 fword("encode-string");
816 push_str("compatible");
821 push_str("device-tree");
822 fword("encode-string");
823 push_str("AAPL,original-name");
828 push_str("AAPL,cpu-id");
831 PUSH(66 * 1000 * 1000);
833 push_str("clock-frequency");
844 push_str("PowerMac3,1");
849 push_str("PowerMac3,1");
850 fword("encode-string");
852 fword("encode-string");
854 push_str("MacRISC2");
855 fword("encode-string");
857 push_str("Power Macintosh");
858 fword("encode-string");
860 push_str("compatible");
866 fword("device-type");
868 PUSH(100 * 1000 * 1000);
870 push_str("clock-frequency");
875 /* Perhaps we can store UUID here ? */
877 push_str("0000000000000");
878 fword("encode-string");
879 push_str("system-id");
885 fword("find-device");
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);
901 printk("CPU type %s\n", cpu->name);
903 snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
904 ofmem_register(find_dev("/memory"), find_dev(buf));
905 node_methods_init(buf);
908 /* OldWorld Macs don't have an /rtas node. */
909 switch (machine_id) {
912 if (!(ph = find_dev("/rtas"))) {
913 printk("Warning: No /rtas node\n");
915 unsigned long size = 0x1000;
916 while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
918 set_property(ph, "rtas-size", (char*)&size, sizeof(size));
919 set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
925 if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
927 if (CONFIG_SERIAL_PORT) {
929 stdout_path = "scca";
932 stdout_path = "sccb";
936 stdout_path = "ttya";
939 /* Some bootloaders force the output to the screen device, so
940 let's create a screen alias for the serial device too */
942 push_str("/aliases");
943 fword("find-device");
945 push_str(stdout_path);
946 fword("pathres-resolve-aliases");
947 fword("encode-string");
952 stdin_path = "adb-keyboard";
953 stdout_path = "screen";
955 stdin_path = "keyboard";
956 stdout_path = "screen";
962 /* Setup nvram variables */
963 push_str("/options");
964 fword("find-device");
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)) {
980 snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path);
982 fword("encode-string");
983 push_str("boot-device");
988 /* Set up other properties */
991 fword("find-device");
993 push_str(stdin_path);
994 fword("pathres-resolve-aliases");
995 push_str("input-device");
998 push_str(stdout_path);
999 fword("pathres-resolve-aliases");
1000 push_str("output-device");
1004 if(getbool("tty-interface?") == 1)
1006 fword("activate-tty-interface");
1010 /* Implementation of filll word (required by BootX) */
1011 bind_func("filll", ffilll);
1013 /* Implementation of adler32 word (required by OS 9, BootX) */
1014 bind_func("(adler32)", adler32);
1016 bind_func("platform-boot", boot);
1017 bind_func("(go)", go);