ppc: Turn 32-bit ppc64 into a config option, to be deprecated
[openbios/afaerber.git] / arch / ppc / qemu / init.c
blob834e65d321317bb73a4f434d6752b327a0056efa
1 /*
2 * Creation Date: <2004/08/28 18:38:22 greg>
3 * Time-stamp: <2004/08/28 18:38:22 greg>
5 * <init.c>
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
23 #include "config.h"
24 #include "libopenbios/openbios.h"
25 #include "libopenbios/bindings.h"
26 #include "drivers/pci.h"
27 #include "arch/common/nvram.h"
28 #include "drivers/drivers.h"
29 #include "qemu/qemu.h"
30 #include "libopenbios/ofmem.h"
31 #include "openbios-version.h"
32 #include "libc/byteorder.h"
33 #include "libc/vsprintf.h"
34 #define NO_QEMU_PROTOS
35 #include "arch/common/fw_cfg.h"
36 #include "arch/ppc/processor.h"
38 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
40 struct cpudef {
41 unsigned long iu_version;
42 const char *name;
43 int icache_size, dcache_size;
44 int icache_sets, dcache_sets;
45 int icache_block_size, dcache_block_size;
46 int clock_frequency;
47 void (*initfn)(const struct cpudef *cpu);
50 static uint16_t machine_id = 0;
52 extern void unexpected_excep( int vector );
54 void
55 unexpected_excep( int vector )
57 printk("openbios panic: Unexpected exception %x\n", vector );
58 for( ;; )
62 enum {
63 ARCH_PREP = 0,
64 ARCH_MAC99,
65 ARCH_HEATHROW,
66 ARCH_MAC99_U3,
69 int is_apple(void)
71 return 1;
74 int is_oldworld(void)
76 return machine_id == ARCH_HEATHROW;
79 int is_newworld(void)
81 return (machine_id == ARCH_MAC99) ||
82 (machine_id == ARCH_MAC99_U3);
85 static const pci_arch_t known_arch[] = {
86 [ARCH_PREP] = {
87 .name = "PREP",
88 .vendor_id = PCI_VENDOR_ID_MOTOROLA,
89 .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
90 .cfg_addr = 0x80800000,
91 .cfg_data = 0x800c0000,
92 .cfg_base = 0x80000000,
93 .cfg_len = 0x00100000,
94 .host_mem_base = 0xf0000000,
95 .pci_mem_base = 0xf0000000,
96 .mem_len = 0x10000000,
97 .io_base = 0x80000000,
98 .io_len = 0x00010000,
99 .rbase = 0x00000000,
100 .rlen = 0x00400000,
101 .irqs = { 9, 11, 9, 11 }
103 [ARCH_MAC99] = {
104 .name = "MAC99",
105 .vendor_id = PCI_VENDOR_ID_APPLE,
106 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
107 .cfg_addr = 0xf2800000,
108 .cfg_data = 0xf2c00000,
109 .cfg_base = 0xf2000000,
110 .cfg_len = 0x02000000,
111 .host_mem_base = 0x80000000,
112 .pci_mem_base = 0x80000000,
113 .mem_len = 0x10000000,
114 .io_base = 0xf2000000,
115 .io_len = 0x00800000,
116 .rbase = 0x00000000,
117 .rlen = 0x01000000,
118 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
120 [ARCH_MAC99_U3] = {
121 .name = "MAC99_U3",
122 .vendor_id = PCI_VENDOR_ID_APPLE,
123 .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
124 .cfg_addr = 0xf0800000,
125 .cfg_data = 0xf0c00000,
126 .cfg_base = 0xf0000000,
127 .cfg_len = 0x02000000,
128 .host_mem_base = 0x80000000,
129 .pci_mem_base = 0x80000000,
130 .mem_len = 0x10000000,
131 .io_base = 0xf2000000,
132 .io_len = 0x00800000,
133 .rbase = 0x00000000,
134 .rlen = 0x01000000,
135 .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
137 [ARCH_HEATHROW] = {
138 .name = "HEATHROW",
139 .vendor_id = PCI_VENDOR_ID_MOTOROLA,
140 .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
141 .cfg_addr = 0xfec00000,
142 .cfg_data = 0xfee00000,
143 .cfg_base = 0x80000000,
144 .cfg_len = 0x7f000000,
145 .host_mem_base = 0x80000000,
146 .pci_mem_base = 0x80000000,
147 .mem_len = 0x01000000,
148 .io_base = 0xfe000000,
149 .io_len = 0x00800000,
150 .rbase = 0xfd000000,
151 .rlen = 0x01000000,
152 .irqs = { 21, 22, 23, 24 }
155 uint32_t isa_io_base;
157 void
158 entry( void )
160 uint32_t temp = 0;
161 char buf[5];
163 arch = &known_arch[ARCH_HEATHROW];
165 fw_cfg_init();
167 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
168 buf[4] = '\0';
169 if (strncmp(buf, "QEMU", 4) == 0) {
170 temp = fw_cfg_read_i32(FW_CFG_ID);
171 if (temp == 1) {
172 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
173 arch = &known_arch[machine_id];
177 isa_io_base = arch->io_base;
179 if (temp != 1) {
180 printk("Incompatible configuration device version, freezing\n");
181 for(;;);
184 ofmem_init();
185 initialize_forth();
186 /* won't return */
188 printk("of_startup returned!\n");
189 for( ;; )
193 static void
194 cpu_generic_init(const struct cpudef *cpu)
196 unsigned long iu_version;
198 push_str("/cpus");
199 fword("find-device");
201 fword("new-device");
203 push_str(cpu->name);
204 fword("device-name");
206 push_str("cpu");
207 fword("device-type");
209 asm("mfpvr %0\n"
210 : "=r"(iu_version) :);
211 PUSH(iu_version);
212 fword("encode-int");
213 push_str("cpu-version");
214 fword("property");
216 PUSH(cpu->dcache_size);
217 fword("encode-int");
218 push_str("dcache-size");
219 fword("property");
221 PUSH(cpu->icache_size);
222 fword("encode-int");
223 push_str("icache-size");
224 fword("property");
226 PUSH(cpu->dcache_sets);
227 fword("encode-int");
228 push_str("dcache-sets");
229 fword("property");
231 PUSH(cpu->icache_sets);
232 fword("encode-int");
233 push_str("icache-sets");
234 fword("property");
236 PUSH(cpu->dcache_block_size);
237 fword("encode-int");
238 push_str("dcache-block-size");
239 fword("property");
241 PUSH(cpu->icache_block_size);
242 fword("encode-int");
243 push_str("icache-block-size");
244 fword("property");
246 PUSH(fw_cfg_read_i32(FW_CFG_PPC_TBFREQ));
247 fword("encode-int");
248 push_str("timebase-frequency");
249 fword("property");
251 PUSH(fw_cfg_read_i32(FW_CFG_PPC_CPUFREQ));
252 fword("encode-int");
253 push_str("clock-frequency");
254 fword("property");
256 push_str("running");
257 fword("encode-string");
258 push_str("state");
259 fword("property");
262 static void
263 cpu_add_pir_property(void)
265 unsigned long pir;
267 asm("mfspr %0, 1023\n"
268 : "=r"(pir) :);
269 PUSH(pir);
270 fword("encode-int");
271 push_str("reg");
272 fword("property");
275 static void
276 cpu_604_init(const struct cpudef *cpu)
278 cpu_generic_init(cpu);
279 cpu_add_pir_property();
281 fword("finish-device");
284 static void
285 cpu_750_init(const struct cpudef *cpu)
287 cpu_generic_init(cpu);
289 PUSH(0);
290 fword("encode-int");
291 push_str("reg");
292 fword("property");
294 fword("finish-device");
297 static void
298 cpu_g4_init(const struct cpudef *cpu)
300 cpu_generic_init(cpu);
301 cpu_add_pir_property();
303 fword("finish-device");
306 #ifdef CONFIG_PPC_64BITSUPPORT
307 /* In order to get 64 bit aware handlers that rescue all our
308 GPRs from getting truncated to 32 bits, we need to patch the
309 existing handlers so they jump to our 64 bit aware ones. */
310 static void
311 ppc64_patch_handlers(void)
313 uint32_t *dsi = (uint32_t *)0x300UL;
314 uint32_t *isi = (uint32_t *)0x400UL;
316 // Patch the first DSI handler instruction to: ba 0x2000
317 *dsi = 0x48002002;
319 // Patch the first ISI handler instruction to: ba 0x2200
320 *isi = 0x48002202;
322 // Invalidate the cache lines
323 asm ( "icbi 0, %0" : : "r"(dsi) );
324 asm ( "icbi 0, %0" : : "r"(isi) );
326 #endif
328 static void
329 cpu_970_init(const struct cpudef *cpu)
331 cpu_generic_init(cpu);
333 PUSH(0);
334 fword("encode-int");
335 push_str("reg");
336 fword("property");
338 PUSH(0);
339 PUSH(0);
340 fword("encode-bytes");
341 push_str("64-bit");
342 fword("property");
344 fword("finish-device");
346 #ifdef CONFIG_PPC_64BITSUPPORT
347 /* The 970 is a PPC64 CPU, so we need to activate
348 * 64bit aware interrupt handlers */
350 ppc64_patch_handlers();
351 #endif
353 /* The 970 also implements the HIOR which we need to set to 0 */
355 mtspr(S_HIOR, 0);
358 static const struct cpudef ppc_defs[] = {
360 .iu_version = 0x00040000,
361 .name = "PowerPC,604",
362 .icache_size = 0x4000,
363 .dcache_size = 0x4000,
364 .icache_sets = 0x80,
365 .dcache_sets = 0x80,
366 .icache_block_size = 0x20,
367 .dcache_block_size = 0x20,
368 .clock_frequency = 0x07de2900,
369 .initfn = cpu_604_init,
371 { // XXX find out real values
372 .iu_version = 0x00090000,
373 .name = "PowerPC,604e",
374 .icache_size = 0x4000,
375 .dcache_size = 0x4000,
376 .icache_sets = 0x80,
377 .dcache_sets = 0x80,
378 .icache_block_size = 0x20,
379 .dcache_block_size = 0x20,
380 .clock_frequency = 0x07de2900,
381 .initfn = cpu_604_init,
383 { // XXX find out real values
384 .iu_version = 0x000a0000,
385 .name = "PowerPC,604r",
386 .icache_size = 0x4000,
387 .dcache_size = 0x4000,
388 .icache_sets = 0x80,
389 .dcache_sets = 0x80,
390 .icache_block_size = 0x20,
391 .dcache_block_size = 0x20,
392 .clock_frequency = 0x07de2900,
393 .initfn = cpu_604_init,
395 { // XXX find out real values
396 .iu_version = 0x80040000,
397 .name = "PowerPC,MPC86xx",
398 .icache_size = 0x8000,
399 .dcache_size = 0x8000,
400 .icache_sets = 0x80,
401 .dcache_sets = 0x80,
402 .icache_block_size = 0x20,
403 .dcache_block_size = 0x20,
404 .clock_frequency = 0x14dc9380,
405 .initfn = cpu_750_init,
408 .iu_version = 0x000080000,
409 .name = "PowerPC,750",
410 .icache_size = 0x8000,
411 .dcache_size = 0x8000,
412 .icache_sets = 0x80,
413 .dcache_sets = 0x80,
414 .icache_block_size = 0x20,
415 .dcache_block_size = 0x20,
416 .clock_frequency = 0x14dc9380,
417 .initfn = cpu_750_init,
419 { // XXX find out real values
420 .iu_version = 0x10080000,
421 .name = "PowerPC,750",
422 .icache_size = 0x8000,
423 .dcache_size = 0x8000,
424 .icache_sets = 0x80,
425 .dcache_sets = 0x80,
426 .icache_block_size = 0x20,
427 .dcache_block_size = 0x20,
428 .clock_frequency = 0x14dc9380,
429 .initfn = cpu_750_init,
431 { // XXX find out real values
432 .iu_version = 0x70000000,
433 .name = "PowerPC,750",
434 .icache_size = 0x8000,
435 .dcache_size = 0x8000,
436 .icache_sets = 0x80,
437 .dcache_sets = 0x80,
438 .icache_block_size = 0x20,
439 .dcache_block_size = 0x20,
440 .clock_frequency = 0x14dc9380,
441 .initfn = cpu_750_init,
443 { // XXX find out real values
444 .iu_version = 0x70020000,
445 .name = "PowerPC,750",
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 .clock_frequency = 0x14dc9380,
453 .initfn = cpu_750_init,
455 { // XXX find out real values
456 .iu_version = 0x800c0000,
457 .name = "PowerPC,74xx",
458 .icache_size = 0x8000,
459 .dcache_size = 0x8000,
460 .icache_sets = 0x80,
461 .dcache_sets = 0x80,
462 .icache_block_size = 0x20,
463 .dcache_block_size = 0x20,
464 .clock_frequency = 0x14dc9380,
465 .initfn = cpu_750_init,
468 .iu_version = 0x0000c0000,
469 .name = "PowerPC,G4",
470 .icache_size = 0x8000,
471 .dcache_size = 0x8000,
472 .icache_sets = 0x80,
473 .dcache_sets = 0x80,
474 .icache_block_size = 0x20,
475 .dcache_block_size = 0x20,
476 .clock_frequency = 0x1dcd6500,
477 .initfn = cpu_g4_init,
480 .iu_version = 0x00390000,
481 .name = "PowerPC,970",
482 .icache_size = 0x10000,
483 .dcache_size = 0x8000,
484 .icache_sets = 0x200,
485 .dcache_sets = 0x80,
486 .icache_block_size = 0x80,
487 .dcache_block_size = 0x80,
488 .clock_frequency = 0x5f5e1000,
489 .initfn = cpu_970_init,
491 { // XXX find out real values
492 .iu_version = 0x003C0000,
493 .name = "PowerPC,970FX",
494 .icache_size = 0x10000,
495 .dcache_size = 0x8000,
496 .icache_sets = 0x80,
497 .dcache_sets = 0x80,
498 .icache_block_size = 0x80,
499 .dcache_block_size = 0x80,
500 .clock_frequency = 0x1dcd6500,
501 .initfn = cpu_970_init,
505 static const struct cpudef *
506 id_cpu(void)
508 unsigned long iu_version;
509 unsigned int i;
511 asm("mfpvr %0\n"
512 : "=r"(iu_version) :);
513 iu_version &= 0xffff0000;
515 for (i = 0; i < sizeof(ppc_defs)/sizeof(struct cpudef); i++) {
516 if (iu_version == ppc_defs[i].iu_version)
517 return &ppc_defs[i];
519 printk("Unknown cpu (pvr %lx), freezing!\n", iu_version);
520 for (;;);
523 static void go( void );
525 static void
526 go( void )
528 ucell addr;
530 feval("saved-program-state >sps.entry @");
531 addr = POP();
533 call_elf( 0, 0, addr);
536 static void kvm_of_init(void)
538 char hypercall[4 * 4];
539 uint32_t *hc32;
541 /* Don't expose /hypervisor when not in KVM */
542 if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
543 return;
545 push_str("/");
546 fword("find-device");
548 fword("new-device");
550 push_str("hypervisor");
551 fword("device-name");
553 push_str("hypervisor");
554 fword("device-type");
556 /* compatible */
558 push_str("linux,kvm");
559 fword("encode-string");
560 push_str("epapr,hypervisor-0.2");
561 fword("encode-string");
562 fword("encode+");
563 push_str("compatible");
564 fword("property");
566 /* Tell the guest about the hypercall instructions */
567 fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
568 hc32 = (uint32_t*)hypercall;
569 PUSH(hc32[0]);
570 fword("encode-int");
571 PUSH(hc32[1]);
572 fword("encode-int");
573 fword("encode+");
574 PUSH(hc32[2]);
575 fword("encode-int");
576 fword("encode+");
577 PUSH(hc32[3]);
578 fword("encode-int");
579 fword("encode+");
580 push_str("hcall-instructions");
581 fword("property");
583 /* ePAPR requires us to provide a unique guest id */
584 PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
585 fword("encode-int");
586 push_str("guest-id");
587 fword("property");
589 /* ePAPR requires us to provide a guest name */
590 push_str("KVM guest");
591 fword("encode-string");
592 push_str("guest-name");
593 fword("property");
595 fword("finish-device");
598 void
599 arch_of_init( void )
601 #ifdef CONFIG_RTAS
602 phandle_t ph;
603 #endif
604 uint64_t ram_size;
605 const struct cpudef *cpu;
606 char buf[64], qemu_uuid[16];
607 const char *stdin_path, *stdout_path, *boot_path;
608 uint32_t temp = 0;
610 ofmem_t *ofmem = ofmem_arch_get_private();
612 openbios_init();
613 modules_init();
614 setup_timers();
615 #ifdef CONFIG_DRIVER_PCI
616 ob_pci_init();
617 #endif
619 printk("\n");
620 printk("=============================================================\n");
621 printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
622 OPENBIOS_BUILD_DATE);
624 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
625 buf[4] = '\0';
626 printk("Configuration device id %s", buf);
628 temp = fw_cfg_read_i32(FW_CFG_ID);
629 printk(" version %d machine id %d\n", temp, machine_id);
631 temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
633 printk("CPUs: %x\n", temp);
635 ram_size = ofmem->ramsize;
637 printk("Memory: %lldM\n", ram_size / 1024 / 1024);
639 fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
641 printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
642 qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
643 qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
644 qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
645 qemu_uuid[15]);
647 /* set device tree root info */
649 push_str("/");
650 fword("find-device");
652 switch(machine_id) {
653 case ARCH_HEATHROW: /* OldWorld */
655 /* model */
657 push_str("Power Macintosh");
658 fword("model");
660 /* compatible */
662 push_str("AAPL,PowerMac G3");
663 fword("encode-string");
664 push_str("MacRISC");
665 fword("encode-string");
666 fword("encode+");
667 push_str("compatible");
668 fword("property");
670 /* misc */
672 push_str("device-tree");
673 fword("encode-string");
674 push_str("AAPL,original-name");
675 fword("property");
677 PUSH(0);
678 fword("encode-int");
679 push_str("AAPL,cpu-id");
680 fword("property");
682 PUSH(66 * 1000 * 1000);
683 fword("encode-int");
684 push_str("clock-frequency");
685 fword("property");
686 break;
688 case ARCH_MAC99:
689 case ARCH_MAC99_U3:
690 case ARCH_PREP:
691 default:
693 /* model */
695 push_str("PowerMac2,1");
696 fword("model");
698 /* compatible */
700 push_str("PowerMac2,1");
701 fword("encode-string");
702 push_str("MacRISC");
703 fword("encode-string");
704 fword("encode+");
705 push_str("Power Macintosh");
706 fword("encode-string");
707 fword("encode+");
708 push_str("compatible");
709 fword("property");
711 /* misc */
713 push_str("bootrom");
714 fword("device-type");
716 PUSH(100 * 1000 * 1000);
717 fword("encode-int");
718 push_str("clock-frequency");
719 fword("property");
720 break;
723 /* Perhaps we can store UUID here ? */
725 push_str("0000000000000");
726 fword("encode-string");
727 push_str("system-id");
728 fword("property");
730 /* memory info */
732 push_str("/memory");
733 fword("find-device");
735 /* all memory */
737 /* TODO Adjust this when #address-cells gets increased for ppc64. */
738 PUSH(0);
739 fword("encode-phys");
740 /* This needs adjusting if #size-cells gets increased.
741 Alternatively use multiple (address, size) tuples. */
742 PUSH(ram_size & 0xffffffff);
743 fword("encode-int");
744 fword("encode+");
745 push_str("reg");
746 fword("property");
748 cpu = id_cpu();
749 cpu->initfn(cpu);
750 printk("CPU type %s\n", cpu->name);
752 snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
753 ofmem_register(find_dev("/memory"), find_dev(buf));
754 node_methods_init(buf);
756 #ifdef CONFIG_RTAS
757 /* OldWorld Macs don't have an /rtas node. */
758 switch (machine_id) {
759 case ARCH_MAC99:
760 case ARCH_MAC99_U3:
761 if (!(ph = find_dev("/rtas"))) {
762 printk("Warning: No /rtas node\n");
763 } else {
764 unsigned long size = 0x1000;
765 while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
766 size *= 2;
767 set_property(ph, "rtas-size", (char*)&size, sizeof(size));
768 set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
770 break;
772 #endif
774 if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
775 if (CONFIG_SERIAL_PORT) {
776 stdin_path = "scca";
777 stdout_path = "scca";
778 } else {
779 stdin_path = "sccb";
780 stdout_path = "sccb";
783 /* Some bootloaders force the output to the screen device, so
784 let's create a screen alias for the serial device too */
785 push_str("/aliases");
786 fword("find-device");
788 push_str(stdout_path);
789 fword("pathres-resolve-aliases");
790 fword("encode-string");
791 push_str("screen");
792 fword("property");
793 } else {
794 stdin_path = "adb-keyboard";
795 stdout_path = "screen";
798 kvm_of_init();
800 /* Setup nvram variables */
801 push_str("/options");
802 fword("find-device");
804 uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
805 switch (boot_device) {
806 case 'c':
807 boot_path = "hd";
808 break;
809 default:
810 case 'd':
811 boot_path = "cd";
812 break;
815 /* Setup default boot devices */
816 snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt", boot_path, boot_path);
817 push_str(buf);
818 fword("encode-string");
819 push_str("boot-device");
820 fword("property");
822 /* Set up other properties */
823 push_str("/chosen");
824 fword("find-device");
826 push_str(stdin_path);
827 fword("open-dev");
828 fword("encode-int");
829 push_str("stdin");
830 fword("property");
832 push_str(stdout_path);
833 fword("open-dev");
834 fword("encode-int");
835 push_str("stdout");
836 fword("property");
838 push_str(stdin_path);
839 fword("pathres-resolve-aliases");
840 push_str("input-device");
841 fword("$setenv");
843 push_str(stdout_path);
844 fword("pathres-resolve-aliases");
845 push_str("output-device");
846 fword("$setenv");
848 push_str(stdin_path);
849 fword("input");
851 push_str(stdout_path);
852 fword("output");
854 #if 0
855 if( getbool("tty-interface?") == 1 )
856 #endif
857 fword("activate-tty-interface");
859 device_end();
861 bind_func("platform-boot", boot );
862 bind_func("(go)", go);