summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/ppc
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openbios/arch/ppc
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/openbios/arch/ppc')
-rw-r--r--qemu/roms/openbios/arch/ppc/Kconfig48
-rw-r--r--qemu/roms/openbios/arch/ppc/Makefile79
-rw-r--r--qemu/roms/openbios/arch/ppc/Makefile.asm32
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/briq.c194
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/briq.fs115
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/briq.h24
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/init.c130
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/kernel.c16
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/main.c145
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/methods.c333
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/tree.c23
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/tree.fs305
-rw-r--r--qemu/roms/openbios/arch/ppc/briq/vfd.c42
-rw-r--r--qemu/roms/openbios/arch/ppc/build.xml211
-rw-r--r--qemu/roms/openbios/arch/ppc/defconfig48
-rw-r--r--qemu/roms/openbios/arch/ppc/kernel.c99
-rw-r--r--qemu/roms/openbios/arch/ppc/kernel.h41
-rw-r--r--qemu/roms/openbios/arch/ppc/misc.S74
-rw-r--r--qemu/roms/openbios/arch/ppc/mmutypes.h76
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/console.c30
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/init.c119
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/kernel.c16
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/main.c370
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/methods.c470
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/mol.c165
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/mol.fs107
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/mol.h44
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/osi-blk.c119
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/osi-scsi.c271
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/prom.c175
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/prom.h47
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/pseudodisk.c178
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/tree.c165
-rw-r--r--qemu/roms/openbios/arch/ppc/mol/tree.fs103
-rw-r--r--qemu/roms/openbios/arch/ppc/ofmem.c308
-rw-r--r--qemu/roms/openbios/arch/ppc/osi.h170
-rw-r--r--qemu/roms/openbios/arch/ppc/osi_calls.h454
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/console.c43
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/init.c136
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/kernel.c16
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/main.c145
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/methods.c329
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/pearpc.c206
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs116
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/pearpc.h26
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/tree.c23
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/tree.fs305
-rw-r--r--qemu/roms/openbios/arch/ppc/pearpc/vfd.c42
-rw-r--r--qemu/roms/openbios/arch/ppc/ppc.fs68
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/console.c88
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/init.c951
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/kernel.c115
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/kernel.h42
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/ldscript68
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/main.c85
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/methods.c327
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/mmutypes.h97
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/ofmem.c563
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/qemu.c106
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/qemu.fs95
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/qemu.h24
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/start.S729
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/tree.fs71
-rw-r--r--qemu/roms/openbios/arch/ppc/qemu/vfd.c42
-rw-r--r--qemu/roms/openbios/arch/ppc/start.S335
-rw-r--r--qemu/roms/openbios/arch/ppc/timebase.S33
66 files changed, 10572 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/ppc/Kconfig b/qemu/roms/openbios/arch/ppc/Kconfig
new file mode 100644
index 000000000..f317c0a4d
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/Kconfig
@@ -0,0 +1,48 @@
+mainmenu "OpenBIOS Configuration"
+
+config PPC
+ bool
+ default y
+ help
+ Building for PPC hardware.
+
+config BIG_ENDIAN
+ bool
+ default y
+ help
+ PPC hardware is big endian (per default)
+
+choice
+ prompt "Platform Type"
+ default MOL
+
+config MOL
+ bool "Mac-on-Linux"
+ help
+ Build an image for Mac-on-Linux
+
+config MPC107
+ bool "MPC107 board (Crescendo)"
+ help
+ Build for Crescendo board.
+
+config BRIQ
+ bool "Total Impact briQ"
+ help
+ Build an image for the Total Impact briQ
+
+config NO_ARCH
+ bool "None"
+ help
+ Don't build any images.
+
+endchoice
+
+menu "Build hosted UNIX Binary"
+source "arch/unix/Kconfig"
+endmenu
+
+source "kernel/Kconfig"
+source "forth/Kconfig"
+source "libopenbios/Kconfig"
+source "drivers/Kconfig"
diff --git a/qemu/roms/openbios/arch/ppc/Makefile b/qemu/roms/openbios/arch/ppc/Makefile
new file mode 100644
index 000000000..e182825e5
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/Makefile
@@ -0,0 +1,79 @@
+
+include ../../config/Makefile.top
+
+SUBDIRS =
+MOL = $(CONFIG_MOL:y=mol)
+BRIQ = $(CONFIG_BRIQ:y=briq)
+XTARGETS = $(MOL) $(BRIQ) ppc mollink
+DICTIONARIES = $(MOL) $(BRIQ)
+
+INCLUDES = -I../../kernel -I../../kernel/include \
+ -I../../include/molasm -I$(ODIR)/include
+
+#############################################################################
+
+mol-OBJS = mol/init.o mol/main.o mol/mol.o mol/console.o mol/osi-blk.o \
+ mol/osi-scsi.o mol/pseudodisk.o mol/methods.o ofmem.o \
+ mol/video.o mol/prom.o mol/tree.o misc.o mol/kernel.o
+
+briq-OBJS = briq/init.o briq/main.o briq/briq.o briq/vfd.o \
+ ofmem.o briq/methods.o briq/tree.o \
+ misc.o briq/kernel.o
+
+ppc-OBJS = $(KOBJS) $(MODULE_LIBS) \
+ $(FS_LIBS) $(DRIVER_LIBS) $(LIBC_LIBS)
+
+all-$(CONFIG_MOL) += $(ODIR)/mol.image
+all-$(CONFIG_BRIQ) += $(ODIR)/briq.image
+all-$(CONFIG_MPC107) += $(ODIR)/mpc107.image
+
+
+#############################################################################
+
+mol-SRC = ppc.fs tree.fs mol.fs $(ARCHDICT_SRC)
+briq-SRC = ppc.fs briq/tree.fs briq/briq.fs $(ARCHDICT_SRC)
+
+$(ODIR)/mol/kernel.o: $(ODIR)/include/mol-dict.h
+$(ODIR)/briq/kernel.o: $(ODIR)/include/briq-dict.h
+
+$(ODIR)/include/mol-dict.h: $(ODIR)/mol.dict
+ test -d $(dir $@) || $(INSTALL) -d $(dir $@)
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@
+
+$(ODIR)/include/briq-dict.h: $(ODIR)/briq.dict
+ test -d $(dir $@) || $(INSTALL) -d $(dir $@)
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@
+
+#############################################################################
+
+$(ODIR)/mol.image: $(ODIR)/start.o $(ODIR)/libmol.a $(ODIR)/libppc.a
+ @printf "= Building %-22s : " $@
+ building=
+ $(LD) -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@
+ @nm $@ | sort > $(ODIR)/mol.syms
+ strip -g $@
+ @echo "ok"
+
+$(ODIR)/briq.image: $(ODIR)/start.o $(ODIR)/timebase.o $(ODIR)/libbriq.a $(ODIR)/libppc.a
+ @printf "= Building %-22s : " $@
+ building=
+ $(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@
+ @nm $@ | sort > $(ODIR)/briq.syms
+ #strip -g $@
+ @echo "ok"
+
+$(ODIR)/mpc107.image:
+ @echo "BUILDING mpc107.image (not yet implemented)"
+
+clean-local:
+ $(RM) $(ODIR)/*.image $(ODIR)/*.syms $(ODIR)/include/mol-dict.h
+
+include Makefile.asm
+include $(rules)/Rules.make
+include $(rules)/Rules.forth
diff --git a/qemu/roms/openbios/arch/ppc/Makefile.asm b/qemu/roms/openbios/arch/ppc/Makefile.asm
new file mode 100644
index 000000000..32d43376d
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/Makefile.asm
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+#
+# Makefile.asm - assembly support
+#
+# Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2
+
+
+#################################################
+# Rules for asm targets
+#################################################
+
+ASMFLAGS = -D__ASSEMBLY__ -I$(top_srcdir) $(ALTIVEC)
+FILTERBIN = $(top_srcdir)/scripts/asfilter
+ASFILTER = $(shell if test -x $(FILTERBIN) ; then echo $(FILTERBIN) \
+ ; else echo "tr ';' '\n'" ; fi)
+INVOKE_M4 = | $(M4) -s $(M4_NO_GNU) | $(ASFILTER)
+
+$(ODIR)/%.o: %.S
+ @printf " Compiling %-20s: " $(notdir $@)
+ assembly=
+ @install -d $(dir $@)
+ @$(RM) $@ $@.s
+ @$(CPP) $(ASMFLAGS) $(IDIRS) $< > /dev/null
+ $(CPP) $(ASMFLAGS) $(IDIRS) $(DEPFLAGS) $< $(INVOKE_M4) > $@.s
+ $(AS) $@.s $(AS_FLAGS) -o $@
+ @$(DEPEXTRA)
+ @$(RM) $@.s
+ @echo "ok"
diff --git a/qemu/roms/openbios/arch/ppc/briq/briq.c b/qemu/roms/openbios/arch/ppc/briq/briq.c
new file mode 100644
index 000000000..a8541c370
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/briq.c
@@ -0,0 +1,194 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <briq.c>
+ *
+ * Copyright (C) 2004, Greg Watson
+ *
+ * derived from mol.c
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "briq/briq.h"
+#include <stdarg.h>
+
+#define UART_BASE 0x3f8
+
+unsigned long virt_offset = 0;
+
+void
+exit( int status )
+{
+ for (;;);
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ exit(0);
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ exit(0);
+
+ /* won't come here... this keeps the gcc happy */
+ for( ;; )
+ ;
+}
+
+
+/************************************************************************/
+/* print using OSI interface */
+/************************************************************************/
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vnsprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ putchar( '>' );
+ putchar( '>' );
+ putchar( ' ' );
+ }
+ putchar( *p );
+ }
+ return i;
+}
+
+
+/************************************************************************/
+/* TTY iface */
+/************************************************************************/
+
+static int ttychar = -1;
+
+static int
+tty_avail( void )
+{
+ return 1;
+}
+
+static int
+tty_putchar( int c )
+{
+ if( tty_avail() ) {
+ while (!(inb(UART_BASE + 0x05) & 0x20))
+ ;
+ outb(c, UART_BASE);
+ while (!(inb(UART_BASE + 0x05) & 0x40))
+ ;
+ }
+ return c;
+}
+
+int
+availchar( void )
+{
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ ttychar = inb(UART_BASE);
+ return (ttychar >= 0);
+}
+
+int
+getchar( void )
+{
+ int ch;
+
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ return inb(UART_BASE);
+ ch = ttychar;
+ ttychar = -1;
+ return ch;
+}
+
+int
+putchar( int c )
+{
+ if (c == '\n')
+ tty_putchar('\r');
+ return tty_putchar(c);
+}
+
+
+/************************************************************************/
+/* briQ specific stuff */
+/************************************************************************/
+
+static char nvram[2048];
+
+void
+dump_nvram(void)
+{
+ static char hexdigit[] = "0123456789abcdef";
+ int i;
+ for (i = 0; i < 16*4; i++)
+ {
+ printk ("%c", hexdigit[nvram[i] >> 4]);
+ printk ("%c", hexdigit[nvram[i] % 16]);
+ if (!((i + 1) % 16))
+ {
+ printk ("\n");
+ }
+ else
+ {
+ printk (" ");
+ }
+ }
+}
+
+
+int
+arch_nvram_size( void )
+{
+ return sizeof(nvram);
+}
+
+void
+arch_nvram_put( char *buf )
+{
+ memcpy(nvram, buf, sizeof(nvram));
+ printk("new nvram:\n");
+ dump_nvram();
+}
+
+void
+arch_nvram_get( char *buf )
+{
+ memcpy(buf, nvram, sizeof(nvram));
+ printk("current nvram:\n");
+ dump_nvram();
+}
diff --git a/qemu/roms/openbios/arch/ppc/briq/briq.fs b/qemu/roms/openbios/arch/ppc/briq/briq.fs
new file mode 100644
index 000000000..78d77970c
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/briq.fs
@@ -0,0 +1,115 @@
+\ briq specific initialization code
+\
+\ Copyright (C) 2004 Greg Watson
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " rtc" " /pci/isa/rtc" preopen
+ " memory" " /memory" preopen
+ " mmu" " /cpu@0" preopen
+ " stdout" " /packages/terminal-emulator" preopen
+ " stdin" " keyboard" preopen
+
+; SYSTEM-initializer
+
+
+\ -------------------------------------------------------------------------
+\ device tree fixing
+\ -------------------------------------------------------------------------
+
+\ add decode-address methods
+: (make-decodable) ( phandle -- )
+
+ dup " #address-cells" rot get-package-property 0= if
+ decode-int nip nip
+ over " decode-unit" rot find-method if 2drop else
+ ( save phandle ncells )
+
+ over active-package!
+ case
+ 1 of ['] parse-hex " decode-unit" is-xt-func endof
+ 3 of
+ " bus-range" active-package get-package-property 0= if
+ decode-int nip nip
+ ['] encode-unit-pci " encode-unit" is-xt-func
+ " decode-unit" is-func-begin
+ ['] (lit) , ,
+ ['] decode-unit-pci-bus ,
+ is-func-end
+ then
+ endof
+ endcase
+ then
+ then
+ drop
+;
+
+: init-briq-tree ( -- )
+ active-package
+
+ iterate-tree-begin
+ begin ?dup while
+
+ dup (make-decodable)
+
+ iterate-tree
+ repeat
+
+ active-package!
+;
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ " /packages/terminal-emulator" " input-device" $setenv
+ " /packages/terminal-emulator" " output-device" $setenv
+ then
+;
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then
+ device-end
+;
diff --git a/qemu/roms/openbios/arch/ppc/briq/briq.h b/qemu/roms/openbios/arch/ppc/briq/briq.h
new file mode 100644
index 000000000..33a2cafa8
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/briq.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <briq.h>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_BRIQ
+#define _H_BRIQ
+
+/* vfd.c */
+extern int vfd_draw_str( const char *str );
+extern void vfd_close( void );
+
+#include "kernel.h"
+
+#endif /* _H_BRIQ */
diff --git a/qemu/roms/openbios/arch/ppc/briq/init.c b/qemu/roms/openbios/arch/ppc/briq/init.c
new file mode 100644
index 000000000..b32e97aa2
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/init.c
@@ -0,0 +1,130 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <init.c>
+ *
+ * Initialization for briq
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * based on mol/init.c:
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ * (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "briq/briq.h"
+#include "libopenbios/ofmem.h"
+#include "openbios-version.h"
+
+extern void unexpected_excep( int vector );
+extern void setup_timers( void );
+
+#if 0
+int
+get_bool_res( const char *res )
+{
+ char buf[8], *p;
+
+ p = BootHGetStrRes( res, buf, sizeof(buf) );
+ if( !p )
+ return -1;
+ if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") )
+ return 1;
+ return 0;
+}
+#endif
+
+void
+unexpected_excep( int vector )
+{
+ printk("briQ panic: Unexpected exception %x\n", vector );
+ for( ;; )
+ ;
+}
+
+unsigned long isa_io_base;
+
+void
+entry( void )
+{
+ isa_io_base = 0x80000000;
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for( ;; )
+ ;
+}
+
+static void
+setenv( char *env, char *value )
+{
+ push_str( value );
+ push_str( env );
+ fword("$setenv");
+}
+
+void
+arch_of_init( void )
+{
+#if CONFIG_RTAS
+ phandle_t ph;
+#endif
+ int autoboot;
+
+ devtree_init();
+ node_methods_init();
+ modules_init();
+ setup_timers();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+#endif
+
+#if CONFIG_RTAS
+ if( !(ph=find_dev("/rtas")) )
+ printk("Warning: No /rtas node\n");
+ else {
+ unsigned long size = 0x1000;
+ while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+ size *= 2;
+ set_property( ph, "rtas-size", (char*)&size, sizeof(size) );
+ }
+#endif
+
+#if 0
+ /* tweak boot settings */
+ autoboot = !!get_bool_res("autoboot");
+#endif
+ autoboot = 0;
+ if( !autoboot )
+ printk("Autobooting disabled - dropping into OpenFirmware\n");
+ setenv("auto-boot?", autoboot ? "true" : "false" );
+ setenv("boot-command", "briqboot");
+
+#if 0
+ if( get_bool_res("tty-interface") == 1 )
+#endif
+ fword("activate-tty-interface");
+
+ /* hack */
+ device_end();
+ bind_func("briqboot", boot );
+}
diff --git a/qemu/roms/openbios/arch/ppc/briq/kernel.c b/qemu/roms/openbios/arch/ppc/briq/kernel.c
new file mode 100644
index 000000000..e85134d43
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/kernel.c
@@ -0,0 +1,16 @@
+/*
+ * Creation Date: <2004/08/28 18:03:25 stepan>
+ * Time-stamp: <2004/08/28 18:03:25 stepan>
+ *
+ * <briq/kernel.c>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "briq-dict.h"
+#include "../kernel.c"
diff --git a/qemu/roms/openbios/arch/ppc/briq/main.c b/qemu/roms/openbios/arch/ppc/briq/main.c
new file mode 100644
index 000000000..fbb2a26de
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/main.c
@@ -0,0 +1,145 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <main.c>
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "briq/briq.h"
+#include "libopenbios/ofmem.h"
+
+static void
+transfer_control_to_elf( unsigned long entry )
+{
+ extern void call_elf( unsigned long entry );
+ printk("Starting ELF image at 0x%08lX\n", entry);
+ call_elf( 0x400000 );
+ //call_elf( entry );
+
+ fatal_error("call_elf returned unexpectedly\n");
+}
+
+static int
+load_elf_rom( unsigned long *entry, int fd )
+{
+ int i, lszz_offs, elf_offs;
+ char buf[128], *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ printk("Loading '%s'\n", get_file_path(fd));
+
+ /* the ELF-image (usually) starts at offset 0x4000 */
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ exit(1);
+ }
+ if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
+ fatal_error("elf_readhdrs failed\n");
+
+ *entry = ehdr.e_entry;
+
+ /* load segments. Compressed ROM-image assumed to be located immediately
+ * after the last segment */
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ /* p_memsz, p_flags */
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
+ fatal_error("Claim failed!\n");
+
+ addr = (char*)phdr[i].p_vaddr;
+ if( read_io(fd, addr, s) != s )
+ fatal_error("read failed\n");
+
+#if 0
+ /* patch CODE segment */
+ if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
+ patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
+ newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
+ }
+#endif
+ flush_icache_range( addr, addr+s );
+
+ /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
+ }
+ free( phdr );
+ return lszz_offs;
+}
+
+
+static void
+encode_bootpath( const char *spec, const char *args )
+{
+ phandle_t chosen_ph = find_dev("/chosen");
+ set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
+ set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
+}
+
+/************************************************************************/
+/* briq booting */
+/************************************************************************/
+
+static void
+briq_startup( void )
+{
+ const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
+ const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
+ unsigned long entry;
+ int i, fd;
+
+ for( i=0; paths[i]; i++ ) {
+ if( (fd=open_io(paths[i])) == -1 )
+ continue;
+ (void) load_elf_rom( &entry, fd );
+ close_io( fd );
+ encode_bootpath( paths[i], args[i] );
+
+ update_nvram();
+ transfer_control_to_elf( entry );
+ /* won't come here */
+ }
+ printk("*** Boot failure! No secondary bootloader specified ***\n");
+}
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ fword("update-chosen");
+ briq_startup();
+}
diff --git a/qemu/roms/openbios/arch/ppc/briq/methods.c b/qemu/roms/openbios/arch/ppc/briq/methods.c
new file mode 100644
index 000000000..649e9bafa
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/methods.c
@@ -0,0 +1,333 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "briq/briq.h"
+#include "libopenbios/ofmem.h"
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+#ifdef CONFIG_RTAS
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ int physbase = POP();
+ int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+#endif
+
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( vfd_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+ char *s = malloc( len + 1 );
+
+ strncpy_nopad( s, addr, len );
+ s[len]=0;
+
+ printk( "%s", s );
+ //vfd_draw_str( s );
+ free( s );
+
+ PUSH( len );
+}
+
+NODE_METHODS( vfd_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+ printk("=============================================================\n\n");
+}
+
+/* ( -- ms ) */
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ extern unsigned long get_timer_freq();
+ static unsigned long mticks=0, usecs=0;
+ unsigned long t;
+
+ asm volatile("mftb %0" : "=r" (t) : );
+ if( mticks )
+ usecs += get_timer_freq() / 1000000 * ( t-mticks );
+ mticks = t;
+
+ PUSH( usecs/1000 );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
+DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ int align = POP();
+ int size = POP();
+ int phys = POP();
+ int ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ int align = POP();
+ int size = POP();
+ int phys = POP();
+ int ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ int mode = POP();
+ int size = POP();
+ int virt = POP();
+ int phys = POP();
+ int ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ int align = POP();
+ int size = POP();
+ int virt = POP();
+ int ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ POP();
+ POP();
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+#ifdef CONFIG_RTAS
+ REGISTER_NODE( rtas );
+#endif
+ REGISTER_NODE( vfd_stdout );
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE( mmu );
+ REGISTER_NODE( mmu_ciface );
+ REGISTER_NODE( tty );
+}
diff --git a/qemu/roms/openbios/arch/ppc/briq/tree.c b/qemu/roms/openbios/arch/ppc/briq/tree.c
new file mode 100644
index 000000000..177183889
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/tree.c
@@ -0,0 +1,23 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <tree.c>
+ *
+ * device tree setup
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+
+void devtree_init( void )
+{
+ fword("init-briq-tree");
+}
diff --git a/qemu/roms/openbios/arch/ppc/briq/tree.fs b/qemu/roms/openbios/arch/ppc/briq/tree.fs
new file mode 100644
index 000000000..ae503266c
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/tree.fs
@@ -0,0 +1,305 @@
+\ briq specific initialization code
+\
+\ Copyright (C) 2004 Greg Watson
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+
+" chrp" device-type
+" TotalImpact,BRIQ-1" model
+h# 80000000 encode-int " isa-io-base" property
+1 encode-int " #interrupt-cells" property
+1 encode-int " #size-cells" property
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ 0 encode-int h# 1E00000 encode-int encode+
+ h# 2000000 encode-int encode+ h# 40000000 encode-int encode+
+ " available" property
+ 0 h# 40000000 reg
+ external
+ : open true ;
+ : close ;
+finish-device
+
+new-device
+ " cpu" device-name
+ " cpu" device-type
+ " " encode-string " translations" property
+ 0 encode-phys h# 8000000 encode-int encode+ " available" property
+ d# 32 encode-int " d-cache-block-size" property
+ 8 encode-int " d-cache-sets" property
+ d# 32768 encode-int " d-cache-size" property
+ d# 32 encode-int " i-cache-block-size" property
+ 8 encode-int " i-cache-sets" property
+ d# 32768 encode-int " i-cache-size" property
+ " " encode-string " cache-unified" property
+ 2 encode-int " i-tlb-sets" property
+ d# 128 encode-int " i-tlb-size" property
+ 2 encode-int " d-tlb-sets" property
+ d# 128 encode-int " d-tlb-size" property
+ " " encode-string " tlb-split" property
+ 2 encode-int " tlb-sets" property
+ d# 256 encode-int " tlb-size" property
+ " " encode-string " performance-monitor" property
+ " " encode-string " graphics" property
+ 4 encode-int " reservation-granule-size" property
+ d# 25000000 encode-int " timebase-frequency" property
+ d# 300000000 encode-int " clock-frequency" property
+ d# 66000000 encode-int " bus-frequency" property
+ h# 88201 encode-int " cpu-version" property
+ 0 encode-int " reg" property
+finish-device
+
+" /pci" find-device
+ h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ h# 80000000 encode-int encode+ 0 encode-int encode+
+ h# 01000000 encode-int encode+
+ h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+
+ h# C0000000 encode-int encode+ 0 encode-int encode+
+ h# 08000000 encode-int encode+
+ " ranges" property
+ " IBM,CPC710" model
+ h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property
+ h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 7 encode-int encode+
+ " interrupt-map-mask" property
+ 1 encode-int " #interrupt-cells" property
+ h# 80000000 encode-int " system-dma-base" property
+ d# 33333333 encode-int " clock-frequency" property
+ " " encode-string " primary-bridge" property
+ 0 encode-int " pci-bridge-number" property
+ h# FF500000 encode-int h# 100000 encode-int encode+ " reg" property
+ 0 encode-int 0 encode-int encode+ " bus-range" property
+
+new-device
+ " isa" device-name
+ " isa" device-type
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+
+ external
+ : open true ;
+ : close ;
+
+finish-device
+
+: ?devalias ( alias-str alias-len device-str device-len --
+ \ alias-str alias-len false | true )
+ active-package >r
+ " /aliases" find-device
+ \ 2dup ." Checking " type
+ 2dup find-dev if \ check if device exists
+ drop
+ 2over find-dev if \ do we already have an alias?
+ \ ." alias exists" cr
+ drop 2drop false
+ else
+ \ ." device exists" cr
+ encode-string
+ 2swap property
+ true
+ then
+ else
+ \ ." device doesn't exist" cr
+ 2drop false
+ then
+ r> active-package!
+ ;
+
+:noname
+ " hd"
+ " /pci/pci-ata/ata-1/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-1/disk@1" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@1" ?devalias not if
+ 2drop ." No disk found." cr
+ then
+ then
+ then
+ then
+
+ " cdrom"
+ " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if
+ 2drop ." No cdrom found" cr
+ then
+ then
+ then
+ then
+; SYSTEM-initializer
+
+new-device
+ " ide" device-name
+ " ide" device-type
+ " WINBOND,82C553" model
+ h# 28 encode-int " max-latency" property
+ h# 2 encode-int " min-grant" property
+ h# 1 encode-int " devsel-speed" property
+ h# 0 encode-int " subsystem-vendor-id" property
+ h# 0 encode-int " subsystem-id" property
+ h# 1018A encode-int " class-code" property
+ h# 5 encode-int " revision-id" property
+ h# 105 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " assigned-addresses" property
+ h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+new-device
+ " ethernet" device-name
+ " network" device-type
+ " AMD,79C973" model
+ h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+" /pci/isa" find-device
+ 0 0 " assigned-addresses" property
+ 0 0 " ranges" property
+ 0 encode-int " slot-names" property
+ d# 8333333 encode-int " clock-frequency" property
+ 0 encode-int " eisa-slots" property
+ 2 encode-int " #interrupt-cells" property
+ " W83C553F" encode-string " compatible" property
+ " WINBOND,82C553" model
+ 0 encode-int " max-latency" property
+ 0 encode-int " min-grant" property
+ 1 encode-int " devsel-speed" property
+ 0 encode-int " subsystem-vendor-id" property
+ 0 encode-int " subsystem-id" property
+ h# 60100 encode-int " class-code" property
+ h# 10 encode-int " revision-id" property
+ h# 565 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+ " reg" property
+
+new-device
+ " rtc" device-name
+ " rtc" device-type
+ " DS17285S" model
+ " MC146818" encode-string
+ " DS17285S" encode-string encode+
+ " pnpPNP,b00" encode-string encode+ " compatible" property
+ 8 encode-int 0 encode-int encode+ " interrupts" property
+ h# 70 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " interrupt-controller" device-name
+ " interrupt-controller" device-type
+ " 8259" model
+ " " encode-string " interrupt-controller" property
+ 2 encode-int " #interrupt-cells" property
+ 1 encode-int
+ 2 encode-int encode+
+ 3 encode-int encode+
+ 6 encode-int encode+
+ " reserved-interrupts" property
+ " 8259" encode-string
+ " chrp,iic" encode-string encode+
+ " compatible" property
+ h# 20 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " serial" device-name
+ " serial" device-type
+ " no" encode-string " ctsrts" property
+ " no" encode-string " xon" property
+ " no" encode-string " parity" property
+ d# 115200 encode-int " bps" property
+ 1 encode-int " stop-bits" property
+ 8 encode-int " data-bits" property
+ h# 70800 encode-int " divisor" property
+ h# 708000 encode-int " clock-frequency" property
+ 4 encode-int 0 encode-int encode+ " interrupts" property
+ h# 3F8 encode-int 1 encode-int encode+
+ 8 encode-int encode+ " reg" property
+finish-device
+
+" /pci" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+ h# 3800 encode-int 0 encode-int encode+
+ 0 encode-int encode+ 1 encode-int encode+
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int encode+
+ then
+ h# 0C encode-int encode+ 1 encode-int encode+
+ " interrupt-map" property
+
+" /pci/isa" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/terminal-emulator
+new-device
+ " terminal-emulator" device-name
+ external
+ : open true ;
+ : close ;
+ \ : write ( addr len -- actual )
+ \ dup -rot type
+ \ ;
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/qemu/roms/openbios/arch/ppc/briq/vfd.c b/qemu/roms/openbios/arch/ppc/briq/vfd.c
new file mode 100644
index 000000000..ffc87a079
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/briq/vfd.c
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:29:43 greg>
+ * Time-stamp: <2004/08/28 17:29:43 greg>
+ *
+ * <vfd.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "briq/briq.h"
+
+static int vfd_is_open;
+
+static int
+vfd_init( void )
+{
+ vfd_is_open = 1;
+ return 0;
+}
+
+void
+vfd_close( void )
+{
+}
+
+int
+vfd_draw_str( const char *str )
+{
+ if (!vfd_is_open)
+ vfd_init();
+
+ return 0;
+}
diff --git a/qemu/roms/openbios/arch/ppc/build.xml b/qemu/roms/openbios/arch/ppc/build.xml
new file mode 100644
index 000000000..29f6601f9
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/build.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0"?>
+<build condition="PPC">
+
+ <dictionary name="openbios-briq" init="openbios" target="forth" condition="BRIQ">
+ <object source="ppc.fs"/>
+ <object source="briq/tree.fs"/>
+ <object source="briq/briq.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <dictionary name="openbios-pearpc" init="openbios" target="forth" condition="PEARPC">
+ <object source="ppc.fs"/>
+ <object source="pearpc/tree.fs"/>
+ <object source="pearpc/pearpc.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <dictionary name="openbios-qemu" init="openbios" target="forth" condition="QEMU">
+ <object source="ppc.fs"/>
+ <object source="qemu/tree.fs"/>
+ <object source="qemu/qemu.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <dictionary name="openbios-mol" init="openbios" target="forth" condition="MOL">
+ <object source="ppc.fs"/>
+ <object source="mol/tree.fs"/>
+ <object source="mol/mol.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <!-- HACK ALERT -->
+
+ <executable name="target/include/briq-dict.h" target="target" condition="BRIQ">
+ <rule><![CDATA[
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@]]></rule>
+ <external-object source="openbios-briq.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/briq/kernel.o" target="target" condition="BRIQ">
+ <rule><![CDATA[ $(SRCDIR)/arch/ppc/briq/kernel.c $(ODIR)/target/include/static-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/briq/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+
+ <executable name="target/include/pearpc-dict.h" target="target" condition="PEARPC">
+ <rule><![CDATA[
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@]]></rule>
+ <external-object source="openbios-pearpc.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/pearpc/kernel.o" target="target" condition="PEARPC">
+ <rule><![CDATA[ $(SRCDIR)/arch/ppc/pearpc/kernel.c $(ODIR)/target/include/pearpc-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/pearpc/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <executable name="target/include/qemu-dict.h" target="target" condition="QEMU">
+ <rule><![CDATA[
+ $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule>
+ <external-object source="openbios-qemu.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/qemu/kernel.o" target="target" condition="QEMU">
+ <rule><![CDATA[ $(SRCDIR)/arch/ppc/qemu/kernel.c $(ODIR)/target/include/qemu-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/qemu/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+
+ <executable name="target/include/mol-dict.h" target="target" condition="MOL">
+ <rule><![CDATA[
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@]]></rule>
+ <external-object source="openbios-mol.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/mol/kernel.o" target="target" condition="MOL">
+ <rule><![CDATA[
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/mol/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <!-- END OF HACK ALERT -->
+
+ <library name="briq" target="target" type="static" condition="BRIQ">
+ <object source="misc.S"/>
+ <object source="ofmem.c"/>
+ <object source="briq/briq.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/briq/kernel.o"/>
+ <object source="briq/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/tree.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ </library>
+
+ <library name="pearpc" target="target" type="static" condition="PEARPC">
+ <object source="misc.S"/>
+ <object source="ofmem.c"/>
+ <object source="pearpc/pearpc.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/pearpc/kernel.o"/>
+ <object source="pearpc/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/tree.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <!-- taken from mol: generalize -->
+ <object source="pearpc/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ </library>
+
+ <library name="qemu" target="target" type="static" condition="QEMU">
+ <object source="qemu/ofmem.c"/>
+ <object source="qemu/qemu.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/qemu/kernel.o"/>
+ <object source="qemu/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ </library>
+
+ <library name="mol" target="target" type="static" condition="MOL">
+ <object source="misc.S"/>
+ <object source="ofmem.c"/>
+ <object source="mol/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/mol.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/osi-blk.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/osi-scsi.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/pseudodisk.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/prom.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/tree.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/mol/kernel.o"/>
+ </library>
+
+ <executable name="openbios-briq.elf" target="target" condition="BRIQ">
+ <rule>
+ $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-briq.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="start.S"/>
+ <object source="timebase.S"/>
+ <external-object source="libbriq.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+ <executable name="openbios-pearpc.elf" target="target" condition="PEARPC">
+ <rule>
+ $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-pearpc.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="start.S"/>
+ <object source="timebase.S"/>
+ <external-object source="libpearpc.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+ <executable name="openbios-qemu.elf" target="target" condition="QEMU">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/$(ARCH)/qemu/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-qemu.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="qemu/start.S"/>
+ <object source="timebase.S"/>
+ <external-object source="libqemu.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+ <executable name="openbios-mol.elf" target="target" condition="MOL">
+ <rule>
+ $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-mol.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="start.S"/>
+ <external-object source="libmol.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+</build>
diff --git a/qemu/roms/openbios/arch/ppc/defconfig b/qemu/roms/openbios/arch/ppc/defconfig
new file mode 100644
index 000000000..adfb181ea
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/defconfig
@@ -0,0 +1,48 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_PPC=y
+CONFIG_MOL=y
+# CONFIG_MPC107 is not set
+# CONFIG_NO_ARCH is not set
+
+#
+# Build hosted UNIX Binary
+#
+CONFIG_HOST_UNIX=y
+# CONFIG_PLUGIN_PCI is not set
+
+#
+# Kernel Debugging
+#
+CONFIG_DEBUG=y
+CONFIG_DEBUG_BOOT=y
+# CONFIG_DEBUG_DSTACK is not set
+# CONFIG_DEBUG_RSTACK is not set
+# CONFIG_DEBUG_DICTIONARY is not set
+# CONFIG_DEBUG_INTERNAL is not set
+# CONFIG_DEBUG_INTERPRETER is not set
+CONFIG_DEBUG_CONSOLE=y
+CONFIG_DEBUG_CONSOLE_SERIAL=y
+CONFIG_SERIAL_PORT=1
+CONFIG_SERIAL_SPEED=115200
+CONFIG_DEBUG_CONSOLE_VGA=y
+
+#
+# Packages
+#
+# CONFIG_PKG_DEBLOCKER is not set
+# CONFIG_PKG_DISKLABEL is not set
+# CONFIG_PKG_OBP_TFTP is not set
+# CONFIG_PKG_TERMINAL_EMULATOR is not set
+
+#
+# Module Configuration
+#
+CONFIG_DEBLOCKER=y
+CONFIG_DISK_LABEL=y
+CONFIG_PART_SUPPORT=y
+CONFIG_MAC_PARTS=y
+CONFIG_FS=y
+CONFIG_HFS=y
+CONFIG_HFSP=y
diff --git a/qemu/roms/openbios/arch/ppc/kernel.c b/qemu/roms/openbios/arch/ppc/kernel.c
new file mode 100644
index 000000000..28f2965bb
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/kernel.c
@@ -0,0 +1,99 @@
+/*
+ * Creation Date: <2003/10/25 14:07:17 samuel>
+ * Time-stamp: <2004/08/28 17:48:19 stepan>
+ *
+ * <kernel.c>
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * Based upon unix.c (from OpenBIOS):
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "dict.h"
+#include "libopenbios/bindings.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "libc/string.h"
+#include "kernel.h"
+
+#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */
+#define DICTIONARY_SIZE (512*1024) /* 512K for the dictionary */
+
+static ucell *memory;
+
+/************************************************************************/
+/* F U N C T I O N S */
+/************************************************************************/
+
+int
+forth_segv_handler( char *segv_addr )
+{
+ ucell addr = 0xdeadbeef;
+
+ if( PC >= (ucell) dict && PC <= (ucell) dict + dicthead )
+ addr = *(ucell *) PC;
+
+ printk("panic: segmentation violation at %x\n", (int)segv_addr);
+ printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n",
+ (int)dict, (int)(dict + dicthead), dicthead,
+ PC, PC - (ucell) dict);
+ printk("dstackcnt=%d rstackcnt=%d instruction=%x\n",
+ dstackcnt, rstackcnt, addr);
+
+#ifdef DEBUG_DSTACK
+ printdstack();
+#endif
+#ifdef DEBUG_RSTACK
+ printrstack();
+#endif
+ return -1;
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void
+init_memory( void )
+{
+ memory = malloc(MEMORY_SIZE);
+ if( !memory )
+ panic("panic: not enough memory on host system.\n");
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH( (ucell)memory );
+ PUSH( (ucell)memory + MEMORY_SIZE );
+}
+
+int
+initialize_forth( void )
+{
+ dict = malloc(DICTIONARY_SIZE);
+ load_dictionary( forth_dictionary, sizeof(forth_dictionary) );
+ forth_init();
+
+ PUSH_xt( bind_noname_func(arch_of_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+ if( PC ) {
+ init_memory();
+ enterforth((xt_t)PC);
+ free( memory );
+ }
+ free( dict );
+ return 0;
+}
diff --git a/qemu/roms/openbios/arch/ppc/kernel.h b/qemu/roms/openbios/arch/ppc/kernel.h
new file mode 100644
index 000000000..20cda489e
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/kernel.h
@@ -0,0 +1,41 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <kernel.h>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef __KERNEL_H__
+#define __KERNEL_H__
+
+/* misc.c */
+extern void fatal_error( const char *str );
+extern void exit( int status );
+
+/* start.S */
+extern void flush_icache_range( char *start, char *stop );
+extern char of_rtas_start[], of_rtas_end[];
+
+/* methods.c */
+extern void node_methods_init( void );
+
+/* main.c */
+extern void boot( void );
+
+/* init.c */
+extern void entry( void );
+extern void arch_of_init( void );
+extern int get_bool_res( const char *str );
+
+/* tree.c */
+extern void devtree_init( void );
+
+
+#endif /* __KERNEL_H__ */
diff --git a/qemu/roms/openbios/arch/ppc/misc.S b/qemu/roms/openbios/arch/ppc/misc.S
new file mode 100644
index 000000000..435ce0eca
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/misc.S
@@ -0,0 +1,74 @@
+/*
+ * Creation Date: <2002/10/20 15:54:50 samuel>
+ * Time-stamp: <2002/10/20 15:57:21 samuel>
+ *
+ * <misc.S>
+ *
+ * Low-level stuff
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * Based upon misc.S from the the linux kernel with the following
+ * copyrights:
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org),
+ * Cort Dougan (cort@cs.nmt.edu), Paul Mackerras
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+GLOBL(__ashrdi3):
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+GLOBL(__ashldi3):
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
+
+GLOBL(__lshrdi3):
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
diff --git a/qemu/roms/openbios/arch/ppc/mmutypes.h b/qemu/roms/openbios/arch/ppc/mmutypes.h
new file mode 100644
index 000000000..441d7f8bc
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mmutypes.h
@@ -0,0 +1,76 @@
+/*
+ * Creation Date: <2002/01/13 13:53:14 samuel>
+ * Time-stamp: <2002/01/27 19:56:11 samuel>
+ *
+ * <mmutypes.h>
+ *
+ * MMU definitions
+ *
+ * Most of these declarations originate from the Linux Kernel
+ *
+ * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_MMUTYPES
+#define _H_MMUTYPES
+
+/* Hardware Page Table Entry */
+typedef struct mPTE {
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+
+ unsigned long rpn:20; /* Real (physical) page number */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+} mPTE_t;
+
+
+typedef struct _mBATU { /* Upper part of BAT (all except 601) */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+} mBATU;
+
+typedef struct _mBATL { /* Lower part of BAT (all except 601) */
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+} mBATL;
+
+typedef struct _mBAT {
+ mBATU batu; /* Upper register */
+ mBATL batl; /* Lower register */
+} mBAT;
+
+typedef struct _mSEGREG {
+ unsigned long t:1; /* Normal or I/O type */
+ unsigned long ks:1; /* Supervisor 'key' (normally 0) */
+ unsigned long kp:1; /* User 'key' (normally 1) */
+ unsigned long n:1; /* No-execute */
+ unsigned long :4; /* Unused */
+ unsigned long vsid:24; /* Virtual Segment Identifier */
+} mSEGREG;
+
+
+#endif /* _H_MMUTYPES */
diff --git a/qemu/roms/openbios/arch/ppc/mol/console.c b/qemu/roms/openbios/arch/ppc/mol/console.c
new file mode 100644
index 000000000..966011e19
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/console.c
@@ -0,0 +1,30 @@
+/*
+ * Creation Date: <2002/10/29 18:59:05 samuel>
+ * Time-stamp: <2003/12/28 22:51:11 samuel>
+ *
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "osi_calls.h"
+#include "libopenbios/ofmem.h"
+#include "mol/mol.h"
+#include "boothelper_sh.h"
+#include "video_sh.h"
+
+#define openbios_GetFBInfo(x) OSI_GetFBInfo(x)
+
+#include "../../../packages/video.c"
+#include "../../../libopenbios/console_common.c"
diff --git a/qemu/roms/openbios/arch/ppc/mol/init.c b/qemu/roms/openbios/arch/ppc/mol/init.c
new file mode 100644
index 000000000..15333b4e1
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/init.c
@@ -0,0 +1,119 @@
+/*
+ * Creation Date: <1999/11/16 00:49:26 samuel>
+ * Time-stamp: <2004/04/12 16:26:50 samuel>
+ *
+ * <init.c>
+ *
+ * Initialization
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ # (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "mol/mol.h"
+#include "libopenbios/ofmem.h"
+#include "mol/prom.h"
+#include "openbios-version.h"
+#include "osi_calls.h"
+#include "boothelper_sh.h"
+
+extern void unexpected_excep( int vector );
+
+int
+get_bool_res( const char *res )
+{
+ char buf[8], *p;
+
+ p = BootHGetStrRes( res, buf, sizeof(buf) );
+ if( !p )
+ return -1;
+ if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") )
+ return 1;
+ return 0;
+}
+
+void
+unexpected_excep( int vector )
+{
+ printk("MOL panic: Unexpected exception %x\n", vector );
+ for( ;; )
+ ;
+}
+
+unsigned long isa_io_base;
+
+void
+entry( void )
+{
+ isa_io_base = 0x80000000;
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for( ;; )
+ ;
+}
+
+static void
+setenv( char *env, char *value )
+{
+ push_str( value );
+ push_str( env );
+ fword("$setenv");
+}
+
+void
+arch_of_init( void )
+{
+ mol_phandle_t ph;
+ int autoboot;
+
+ devtree_init();
+ node_methods_init();
+ nvram_init("/pci/mac-io/nvram");
+ openbios_init();
+ modules_init();
+ pseudodisk_init();
+ osiblk_init();
+ osiscsi_init();
+ init_video();
+
+ if( (ph=prom_find_device("/rtas")) == -1 )
+ printk("Warning: No /rtas node\n");
+ else {
+ unsigned long size = 0x1000;
+ while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+ size *= 2;
+ prom_set_prop( ph, "rtas-size", (char*)&size, sizeof(size) );
+ }
+
+ /* tweak boot settings */
+ autoboot = !!get_bool_res("autoboot");
+ if( !autoboot )
+ printk("Autobooting disabled - dropping into OpenFirmware\n");
+ setenv("auto-boot?", autoboot ? "true" : "false" );
+ setenv("boot-command", "molboot");
+
+ if( get_bool_res("tty-interface") == 1 )
+ fword("activate-tty-interface");
+
+ /* hack */
+ device_end();
+ bind_func("molboot", boot );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/kernel.c b/qemu/roms/openbios/arch/ppc/mol/kernel.c
new file mode 100644
index 000000000..1454b8a85
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/kernel.c
@@ -0,0 +1,16 @@
+/*
+ * Creation Date: <2004/08/28 18:03:25 stepan>
+ * Time-stamp: <2004/08/28 18:03:25 stepan>
+ *
+ * <mol/kernel.c>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "mol-dict.h"
+#include "../kernel.c"
diff --git a/qemu/roms/openbios/arch/ppc/mol/main.c b/qemu/roms/openbios/arch/ppc/mol/main.c
new file mode 100644
index 000000000..f6ed934d0
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/main.c
@@ -0,0 +1,370 @@
+/*
+ * Creation Date: <2002/10/02 22:24:24 samuel>
+ * Time-stamp: <2004/03/27 01:57:55 samuel>
+ *
+ * <main.c>
+ *
+ *
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "mol/mol.h"
+#include "libopenbios/ofmem.h"
+#include "osi_calls.h"
+#include "ablk_sh.h"
+#include "boothelper_sh.h"
+
+
+static void patch_newworld_rom( char *start, size_t size );
+static void newworld_timer_hack( char *start, size_t size );
+
+static void
+transfer_control_to_elf( unsigned long entry )
+{
+ extern void call_elf( unsigned long entry );
+ printk("Starting ELF boot loader\n");
+ call_elf( entry );
+
+ fatal_error("call_elf returned unexpectedly\n");
+}
+
+static int
+load_elf_rom( unsigned long *entry, int fd )
+{
+ int i, lszz_offs, elf_offs;
+ char buf[128], *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ printk("Loading '%s' from '%s'\n", get_file_path(fd),
+ get_volume_name(fd) );
+
+ /* the ELF-image (usually) starts at offset 0x4000 */
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ exit(1);
+ }
+ if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
+ fatal_error("elf_readhdrs failed\n");
+
+ *entry = ehdr.e_entry;
+
+ /* load segments. Compressed ROM-image assumed to be located immediately
+ * after the last segment */
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ /* p_memsz, p_flags */
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
+ fatal_error("Claim failed!\n");
+
+ addr = (char*)phdr[i].p_vaddr;
+ if( read_io(fd, addr, s) != s )
+ fatal_error("read failed\n");
+
+ /* patch CODE segment */
+ if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
+ patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
+ newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
+ }
+ flush_icache_range( addr, addr+s );
+
+ /* printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
+ }
+ free( phdr );
+ return lszz_offs;
+}
+
+
+/************************************************************************/
+/* newworld ROM loading */
+/************************************************************************/
+
+#define ROM_BASE 0x1100000 /* where we decide to put things */
+
+/* fix bug present in the 2.4 and the 3.0 Apple ROM */
+static void
+patch_newworld_rom( char *start, size_t size )
+{
+ int s;
+ unsigned long mark[] = { 0x7c7d1b78, /* mr r29,r3 */
+ 0x7c9c2378, /* mr r28,r4 */
+ 0x7cc33378, /* mr r3,r6 */
+ 0x7c864214, /* add r4,r6,r8 <------ BUG -- */
+ 0x80b10000, /* lwz r5,0(r17) */
+ 0x38a500e8 }; /* addi r5,r5,232 */
+
+ /* Correcting add r4,r6,r8 ----> addi r4,r6,8 */
+ for( s=0; s<size-sizeof(mark); s+=4 )
+ if( memcmp( start+s, mark, sizeof(mark)) == 0 ) {
+ printk("FIXING ROM BUG @ %X!\n", s+12);
+ ((unsigned long*)(start+s))[3] = 0x38860008; /* addi r4,r6,8 */
+ }
+}
+
+/* This hack is only needed on machines with a timebase slower than 12.5 MHz
+ * (50 MHz bus frequency). Typically only old, accelerated machines fall
+ * into this category. The cause of the problem is an overflow in Apple's
+ * calibration routine.
+ */
+static void
+newworld_timer_hack( char *start, size_t size )
+{
+ int s;
+ unsigned long mark[] = { 0x7d0000a6, 0x5507045e, 0x7ce00124, 0x4c00012c,
+ 0x38e00000, 0x3c80000f, 0x6084ffff, 0x98830c00,
+ 0x7c0006ac, 0x98830a00, 0x7c0006ac, 0x7c9603a6,
+ 0x4c00012c, 0x7cb602a6, 0x2c050000, 0x4181fff8,
+ 0x7c0004ac, 0x88830a00, 0x7c0006ac, 0x88a30800,
+ 0x7c0006ac, 0x88c30a00, 0x7c0006ac, 0x7c043040,
+ 0x40a2ffe4, 0x5085442e, 0x7ca500d0, 0x54a5043e,
+ 0x7c053840, 0x7ca72b78, 0x4082ff9c, 0x7ca32b78,
+ 0x7d000124, 0x4c00012c, 0x4e800020
+ };
+
+ /* return #via ticks corresponding to 0xfffff DEC ticks (VIA frequency == 47/60 MHz) */
+ for( s=0; s < size-sizeof(mark); s+=4 ) {
+ if( !memcmp( start+s, mark, sizeof(mark)) ) {
+ extern char timer_calib_start[], timer_calib_end[];
+ extern unsigned long nw_dec_calibration;
+ int hz = OSI_UsecsToMticks(1000);
+ nw_dec_calibration = OSI_MticksToUsecs(0xfffff*47)/60;
+ memcpy( start + s, timer_calib_start, timer_calib_end - timer_calib_start );
+
+ printk("Timer calibration fix: %d.%02d MHz [%ld]\n",
+ hz/1000, (hz/10)%100, nw_dec_calibration );
+ break;
+ }
+ }
+}
+
+static unsigned long
+load_newworld_rom( int fd )
+{
+ int lszz_offs, lszz_size;
+ unsigned long entry, data[2];
+ phandle_t ph;
+
+ lszz_offs = load_elf_rom( &entry, fd );
+ seek_io( fd, -1 );
+ lszz_size = tell(fd) - lszz_offs;
+ seek_io( fd, lszz_offs );
+
+ /* printk("Compressed ROM image: offset %08X, size %08X loaded at %08x\n",
+ lszz_offs, lszz_size, ROM_BASE ); */
+
+ if( ofmem_claim(ROM_BASE, lszz_size, 0) == -1 )
+ fatal_error("Claim failure (lszz)!\n");
+
+ read_io( fd, (char*)ROM_BASE, lszz_size );
+
+ /* Fix the /rom/macos/AAPL,toolbox-image,lzss property (phys, size) */
+#if 0
+ if( (ph=prom_create_node("/rom/macos/")) == -1 )
+ fatal_error("Failed creating /rom/macos/");
+#else
+ ph = find_dev("/rom/macos");
+#endif
+ data[0] = ROM_BASE;
+ data[1] = lszz_size;
+ set_property( ph, "AAPL,toolbox-image,lzss", (char*)data, sizeof(data) );
+
+ /* The 7.8 rom (MacOS 9.2) uses AAPL,toolbox-parcels instead of
+ * AAPL,toolbox-image,lzss. It probably doesn't hurt to have it
+ * always present (we don't have an easy way to determine ROM version...)
+ */
+ set_property( ph, "AAPL,toolbox-parcels", (char*)data, sizeof(data) );
+ return entry;
+}
+
+static int
+search_nwrom( int fd, int fast )
+{
+ char *s, buf[128];
+ int found = 0;
+
+ if( fast ) {
+ int ind;
+ found = !reopen( fd, "\\\\:tbxi" );
+ for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath", buf, sizeof(buf), ind++, 0)) ; )
+ found = !reopen( fd, s );
+ for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath_", buf, sizeof(buf), ind++, 0)) ; )
+ found = !reopen( fd, s );
+ } else {
+ printk("Searching %s for a 'Mac OS ROM' file\n", get_volume_name(fd) );
+ if( !(found=reopen_nwrom(fd)) ) {
+ printk(" \n**** HINT ***************************************************\n");
+ printk("* The booting can be speeded up by adding the line\n");
+ printk("* macos_rompath: '%s'\n", get_file_path(fd) );
+ printk("* to the /etc/mol/molrc.macos (recommended).\n");
+ printk("*************************************************************\n \n");
+ }
+ }
+ return found;
+}
+
+static void
+encode_bootpath( const char *spec, const char *args )
+{
+ phandle_t chosen_ph = find_dev("/chosen");
+ set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
+ set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
+}
+
+static char *
+newworld_load( const char *node_path, const char *spec, int do_search )
+{
+ char *p, *entry, buf[80];
+ int fd, len;
+
+ if( (fd=open_io(spec)) == -1 )
+ return NULL;
+
+ if( !search_nwrom(fd, do_search) ) {
+ close_io(fd);
+ return NULL;
+ }
+ printk("Boot Disk: %s [%s]\n", spec, get_fstype(fd) );
+
+ entry = (char*)load_newworld_rom( fd );
+
+#if 1
+ PUSH_ih( get_ih_from_fd(fd) );
+ fword("get-instance-path");
+ len = POP();
+ p = (char*)POP();
+ buf[0] = 0;
+ if( len < sizeof(buf) ) {
+ memcpy( buf, p, len );
+ buf[len] =0;
+ }
+ strcat( buf, "/x@:" );
+ printk("boot_path: %s\n", buf );
+ encode_bootpath( buf, "" );
+#endif
+ close_io( fd );
+ return entry;
+}
+
+static void
+newworld_startup( void )
+{
+ int i, j, bootunit, type, fd;
+ ablk_disk_info_t info;
+ char *entry = NULL;
+ char spec[80];
+ phandle_t ph;
+
+ char path[]="/pci/pci-bridge/mol-blk";
+ if( !(ph=find_dev(path)) )
+ fatal_error("MOLBlockDriver node not found\n");
+
+ /* user-specified newworld ROMs take precedence */
+ if( (fd=open_io("pseudo:,nwrom")) >= 0 ) {
+ entry = (char*)load_newworld_rom( fd );
+ close_io( fd );
+ }
+
+ /* determine boot volume */
+ for( bootunit=-1, type=0; bootunit==-1 && type<3 ; type++ ) {
+ for( i=0; !OSI_ABlkDiskInfo(0, i, &info) ; i++ ) {
+ if( type<=1 && !(info.flags & ABLK_BOOT_HINT) )
+ continue;
+ if( type>1 && (info.flags & ABLK_BOOT_HINT) )
+ continue;
+
+ for( j=0; !entry && j<32; j++ ) {
+ snprintf( spec, sizeof(spec), "%s/disk@%x:%d",
+ path, i, j );
+ entry = newworld_load( path, spec, (!type || type==2) );
+ }
+ if( entry ) {
+ bootunit = i;
+ break;
+ }
+ }
+ }
+
+ if( entry ) {
+ OSI_ABlkBlessDisk( 0 /*channel*/, bootunit );
+
+ update_nvram();
+ transfer_control_to_elf( (unsigned long)entry );
+ /* won't come here */
+ return;
+ }
+
+ printk("\n--- No bootable disk was found! -----------------------------\n");
+ printk("If this is an oldworld machine, try booting from the MacOS\n");
+ printk("install CD and install MacOS from within MOL.\n");
+ printk("-------------------------------------------------------------\n");
+ exit(1);
+}
+
+
+/************************************************************************/
+/* yaboot booting */
+/************************************************************************/
+
+static void
+yaboot_startup( void )
+{
+ const char *paths[] = { "pseudo:,ofclient", "pseudo:,yaboot", NULL };
+ unsigned long entry;
+ int i, fd;
+
+ for( i=0; paths[i]; i++ ) {
+ if( (fd=open_io(paths[i])) == -1 )
+ continue;
+ (void) load_elf_rom( &entry, fd );
+ close_io( fd );
+ encode_bootpath( paths[i], "" );
+
+ update_nvram();
+ transfer_control_to_elf( entry );
+ /* won't come here */
+ }
+ printk("*** Boot failure! No secondary bootloader specified ***\n");
+ exit(1);
+}
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ fword("update-chosen");
+ if( find_dev("/mol-platform") )
+ yaboot_startup();
+ else
+ newworld_startup();
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/methods.c b/qemu/roms/openbios/arch/ppc/mol/methods.c
new file mode 100644
index 000000000..bfaf51506
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/methods.c
@@ -0,0 +1,470 @@
+/*
+ * Creation Date: <2003/10/18 13:24:29 samuel>
+ * Time-stamp: <2004/03/27 02:00:30 samuel>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "mol/mol.h"
+#include "libopenbios/ofmem.h"
+#include "mol/prom.h"
+#include "osi_calls.h"
+#include "kbd_sh.h"
+
+/************************************************************************/
+/* Power Management */
+/************************************************************************/
+
+DECLARE_NODE( powermgt, INSTALL_OPEN, 0, "/pci/pci-bridge/mac-io/power-mgt" );
+
+/* ( -- ) */
+static void
+set_hybernot_flag( void )
+{
+}
+
+NODE_METHODS( powermgt ) = {
+ { "set-hybernot-flag", set_hybernot_flag },
+};
+
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ int physbase = POP();
+ int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+
+
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+
+ /* printk( "%s", s ); */
+ console_draw_fstr(addr, len);
+
+ PUSH( len );
+}
+
+NODE_METHODS( video_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "+/mol/mol-tty" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = OSI_TTYGetc();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ OSI_USleep(1);
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ OSI_TTYPutc( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+
+/************************************************************************/
+/* keyboard */
+/************************************************************************/
+
+typedef struct {
+ int cntrl;
+ int shift;
+ int meta;
+ int alt;
+ int save_key;
+ char keytable[32];
+} kbd_state_t;
+
+static const unsigned char adb_ascii_table[128] =
+ /* 0x00 */ "asdfhgzxcv`bqwer"
+ /* 0x10 */ "yt123465=97-80]o"
+ /* 0x20 */ "u[ip\nlj'k;\\,/nm."
+ /* 0x30 */ "\t <\b \e "
+ /* 0x40 */ " . * + / - "
+ /* 0x50 */ " =01234567 89 "
+ /* 0x60 */ " "
+ /* 0x70 */ " ";
+
+static const unsigned char adb_shift_table[128] =
+ /* 0x00 */ "ASDFHGZXCV~BQWER"
+ /* 0x10 */ "YT!@#$^%+(&_*)}O"
+ /* 0x20 */ "U{IP\nLJ\"K:|<?NM>"
+ /* 0x30 */ "\t <\b \e "
+ /* 0x40 */ " . * + / - "
+ /* 0x50 */ " =01234567 89 "
+ /* 0x60 */ " "
+ /* 0x70 */ " ";
+
+DECLARE_NODE( kbd, INSTALL_OPEN, sizeof(kbd_state_t),
+ "/psuedo-hid/keyboard",
+ "/mol/mol-keyboard",
+ "/mol/keyboard"
+);
+
+/* ( -- keymap ) (?) */
+/* should return a pointer to an array with 32 bytes (256 bits) */
+static void
+kbd_get_key_map( kbd_state_t *ks )
+{
+ /* printk("met_kbd_get_key_map\n"); */
+
+ /* keytable[5] = 0x40; */
+ PUSH( (int)ks->keytable );
+}
+
+/* ( buf len --- actlen ) */
+static void
+kbd_read( kbd_state_t *ks )
+{
+ int ret=0, len = POP();
+ char *p = (char*)POP();
+ int key;
+
+ if( !p || !len ) {
+ PUSH( -1 );
+ return;
+ }
+
+ if( ks->save_key ) {
+ *p = ks->save_key;
+ ks->save_key = 0;
+ RET( 1 );
+ }
+ OSI_USleep(1); /* be nice */
+
+ for( ; (key=OSI_GetAdbKey()) >= 0 ; ) {
+ int code = (key & 0x7f);
+ int down = !(key & 0x80);
+
+ if( code == 0x36 /* ctrl */ ) {
+ ks->cntrl = down;
+ continue;
+ }
+ if( code == 0x38 /* shift */ || code == 0x7b) {
+ ks->shift = down;
+ continue;
+ }
+ if( code == 0x37 /* command */ ) {
+ ks->meta = down;
+ continue;
+ }
+ if( code == 0x3a /* alt */ ) {
+ ks->alt = down;
+ continue;
+ }
+ if( !down )
+ continue;
+
+ ret = 1;
+ if( ks->shift )
+ key = adb_shift_table[ key & 0x7f ];
+ else
+ key = adb_ascii_table[ key & 0x7f ];
+
+ if( ks->meta ) {
+ ks->save_key = key;
+ key = 27;
+ } else if( ks->cntrl ) {
+ key = key - 'a' + 1;
+ }
+ *p = key;
+ if( !*p )
+ *p = 'x';
+ break;
+ }
+ PUSH( ret );
+}
+
+NODE_METHODS( kbd ) = {
+ { "read", kbd_read },
+ { "get-key-map", kbd_get_key_map },
+};
+
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+ printk("=============================================================\n\n");
+ prom_close();
+
+ OSI_KbdCntrl( kKbdCntrlSuspend );
+}
+
+/* ( -- ms ) */
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ static unsigned long mticks=0, usecs=0;
+ unsigned long t;
+
+ asm volatile("mftb %0" : "=r" (t) : );
+ if( mticks )
+ usecs += OSI_MticksToUsecs( t-mticks );
+ mticks = t;
+
+ PUSH( usecs/1000 );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpus/@0" );
+DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ ucell mode = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell phys = POP();
+ ucell ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ POP();
+ POP();
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+ REGISTER_NODE( rtas );
+ REGISTER_NODE( powermgt );
+ REGISTER_NODE( kbd );
+ REGISTER_NODE( video_stdout );
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE( mmu );
+ REGISTER_NODE( mmu_ciface );
+
+ if( OSI_CallAvailable(OSI_TTY_GETC) )
+ REGISTER_NODE( tty );
+
+ OSI_KbdCntrl( kKbdCntrlActivate );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.c b/qemu/roms/openbios/arch/ppc/mol/mol.c
new file mode 100644
index 000000000..86b3b66bf
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/mol.c
@@ -0,0 +1,165 @@
+/*
+ * Creation Date: <2003/12/19 18:46:21 samuel>
+ * Time-stamp: <2004/04/12 16:27:12 samuel>
+ *
+ * <mol.c>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "mol/mol.h"
+#include "osi_calls.h"
+#include <stdarg.h>
+
+void
+exit( int status )
+{
+ OSI_Exit();
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ OSI_Exit();
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ OSI_Exit();
+
+ /* won't come here... this keeps the gcc happy */
+ for( ;; )
+ ;
+}
+
+
+/************************************************************************/
+/* print using OSI interface */
+/************************************************************************/
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vnsprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ OSI_PutC( '>' );
+ OSI_PutC( '>' );
+ OSI_PutC( ' ' );
+ }
+ OSI_PutC( *p );
+ }
+ return i;
+}
+
+
+/************************************************************************/
+/* TTY iface */
+/************************************************************************/
+
+static int ttychar = -1;
+
+static int
+tty_avail( void )
+{
+ return OSI_CallAvailable( OSI_TTY_GETC );
+}
+
+int
+availchar( void )
+{
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ ttychar = OSI_TTYGetc();
+ if( ttychar < 0 )
+ OSI_USleep(1);
+ return (ttychar >= 0);
+}
+
+int
+getchar( void )
+{
+ int ch;
+
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ return OSI_TTYGetc();
+ ch = ttychar;
+ ttychar = -1;
+ return ch;
+}
+
+int
+putchar( int c )
+{
+ printk("%c", c );
+
+ if( tty_avail() )
+ OSI_TTYPutc( c );
+ return c;
+}
+
+
+/************************************************************************/
+/* MOL specific stuff */
+/************************************************************************/
+
+int
+arch_nvram_size( void )
+{
+ return OSI_NVRamSize();
+}
+
+void
+arch_nvram_put( char *buf )
+{
+ int i, size = arch_nvram_size();
+
+ for( i=0; i<size; i++ )
+ OSI_WriteNVRamByte( i, buf[i] );
+}
+
+void
+arch_nvram_get( char *buf )
+{
+ int i, size = arch_nvram_size();
+
+ /* support for zapping the nvram */
+ if( get_bool_res("zap_nvram") == 1 ) {
+ memset( buf, 0, size );
+ return;
+ }
+
+ for( i=0; i<size; i++ )
+ buf[i] = OSI_ReadNVRamByte( i );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.fs b/qemu/roms/openbios/arch/ppc/mol/mol.fs
new file mode 100644
index 000000000..10c99bd79
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/mol.fs
@@ -0,0 +1,107 @@
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /cpus/@0" preopen
+ " stdout" " /packages/mol-stdout" preopen
+ " stdin" " keyboard" preopen
+ " nvram" " /pci/pci-bridge/mac-io/nvram" preopen
+ " nvram" " /mol/nvram" preopen
+
+; SYSTEM-initializer
+
+
+\ -------------------------------------------------------------------------
+\ device tree fixing
+\ -------------------------------------------------------------------------
+
+\ add decode-address methods
+: (make-decodable) ( phandle -- )
+
+ dup " #address-cells" rot get-package-property 0= if
+ decode-int nip nip
+ over " decode-unit" rot find-method if 2drop else
+ ( save phandle ncells )
+
+ over active-package!
+ case
+ 1 of ['] parse-hex " decode-unit" is-xt-func endof
+ 3 of
+ " bus-range" active-package get-package-property 0= if
+ decode-int nip nip
+ ['] encode-unit-pci " encode-unit" is-xt-func
+ " decode-unit" is-func-begin
+ ['] (lit) , ,
+ ['] decode-unit-pci-bus ,
+ is-func-end
+ then
+ endof
+ endcase
+ then
+ then
+ drop
+;
+
+: tree-fixes ( -- )
+ active-package
+
+ iterate-tree-begin
+ begin ?dup while
+
+ dup (make-decodable)
+
+ iterate-tree
+ repeat
+
+ active-package!
+;
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /mol/mol-tty" find-dev if drop
+ " /mol/mol-tty" " input-device" $setenv
+ " /mol/mol-tty" " output-device" $setenv
+ then
+;
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ device-end
+;
diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.h b/qemu/roms/openbios/arch/ppc/mol/mol.h
new file mode 100644
index 000000000..cea15a350
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/mol.h
@@ -0,0 +1,44 @@
+/*
+ * Creation Date: <2003/12/20 00:20:12 samuel>
+ * Time-stamp: <2004/03/27 01:52:50 samuel>
+ *
+ * <mol.h>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_MOL
+#define _H_MOL
+
+/* video.c */
+extern void init_video( void );
+extern int video_get_res( int *w, int *h );
+extern void draw_pixel( int x, int y, int colind );
+extern void set_color( int index, unsigned long color );
+
+/* console.c */
+extern int console_draw_fstr(const char *str, int len);
+extern void console_close( void );
+
+/* pseudodisk.c */
+extern void pseudodisk_init( void );
+
+/* osi-blk.c */
+extern void osiblk_init( void );
+
+/* osi-scsi.c */
+extern void osiscsi_init( void );
+
+/* pseudofs.c */
+extern void pseudofs_init( void );
+
+#include "../kernel.h"
+
+#endif /* _H_MOL */
diff --git a/qemu/roms/openbios/arch/ppc/mol/osi-blk.c b/qemu/roms/openbios/arch/ppc/mol/osi-blk.c
new file mode 100644
index 000000000..4ed1b5ab3
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/osi-blk.c
@@ -0,0 +1,119 @@
+/*
+ * Creation Date: <2003/12/07 19:08:33 samuel>
+ * Time-stamp: <2004/01/07 19:38:36 samuel>
+ *
+ * <osi-blk.c>
+ *
+ * OSI-block interface
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "mol/mol.h"
+#include "osi_calls.h"
+
+typedef struct {
+ int unit;
+ int channel;
+} osiblk_data_t;
+
+
+DECLARE_NODE( osiblk, INSTALL_OPEN, sizeof(osiblk_data_t),
+ "/pci/pci-bridge/mol-blk/disk", "/mol/mol-blk" );
+
+
+static void
+osiblk_open( osiblk_data_t *pb )
+{
+ phandle_t ph;
+
+ fword("my-unit");
+ pb->unit = POP();
+ pb->channel = 0; /* FIXME */
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ /* printk("osi-blk: open %d\n", pb->unit ); */
+ PUSH( -1 );
+}
+
+static void
+osiblk_close( osiblk_data_t *pb )
+{
+ selfword("close-deblocker");
+}
+
+
+/* ( buf blk nblks -- actual ) */
+static void
+osiblk_read_blocks( osiblk_data_t *pb )
+{
+ int i, n = POP();
+ int blk = POP();
+ char *dest = (char*)POP();
+
+ /* printk("osiblk_read_blocks %x block=%d n=%d\n", (int)dest, blk, n ); */
+
+ for( i=0; i<n; ) {
+ char buf[4096];
+ int m = MIN( n-i, sizeof(buf)/512 );
+
+ if( OSI_ABlkSyncRead(pb->channel, pb->unit, blk+i, (int)buf, m*512) < 0 ) {
+ printk("SyncRead: error\n");
+ RET(0);
+ }
+ memcpy( dest, buf, m * 512 );
+ i += m;
+ dest += m * 512;
+ }
+ PUSH( n );
+}
+
+/* ( -- bs ) */
+static void
+osiblk_block_size( osiblk_data_t *pb )
+{
+ PUSH( 512 );
+}
+
+/* ( -- maxbytes ) */
+static void
+osiblk_max_transfer( osiblk_data_t *pb )
+{
+ PUSH( 1024*1024 );
+}
+
+static void
+osiblk_initialize( osiblk_data_t *pb )
+{
+ fword("is-deblocker");
+}
+
+
+NODE_METHODS( osiblk ) = {
+ { NULL, osiblk_initialize },
+ { "open", osiblk_open },
+ { "close", osiblk_close },
+ { "read-blocks", osiblk_read_blocks },
+ { "block-size", osiblk_block_size },
+ { "max-transfer", osiblk_max_transfer },
+};
+
+void
+osiblk_init( void )
+{
+ REGISTER_NODE( osiblk );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c b/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c
new file mode 100644
index 000000000..18f3dc577
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c
@@ -0,0 +1,271 @@
+/*
+ * Creation Date: <2003/12/11 21:23:54 samuel>
+ * Time-stamp: <2004/01/07 19:38:45 samuel>
+ *
+ * <osi-scsi.c>
+ *
+ * SCSI device node
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "mol/mol.h"
+#include "scsi_sh.h"
+#include "osi_calls.h"
+
+#define MAX_TARGETS 32
+
+typedef struct {
+ int probed;
+ int valid; /* a useable device found */
+
+ int is_cd;
+ int blocksize;
+} target_info_t;
+
+static target_info_t scsi_devs[ MAX_TARGETS ];
+
+typedef struct {
+ int target;
+ target_info_t *info;
+} instance_data_t;
+
+
+DECLARE_NODE( scsi, INSTALL_OPEN, sizeof(instance_data_t),
+ "/pci/pci-bridge/mol-scsi/sd", "/mol/mol-scsi/sd" );
+
+
+static int
+scsi_cmd_( instance_data_t *sd, const char *cmd, int cmdlen, char *dest,
+ int len, int prelen, int postlen )
+{
+ char prebuf[4096], postbuf[4096];
+ scsi_req_t r[2]; /* the [2] is a hack to get space for the sg-list */
+ char sb[32];
+
+ /* memset( dest, 0, len ); */
+
+ if( (unsigned int)prelen > sizeof(prebuf) || (unsigned int)postlen > sizeof(postbuf) ) {
+ printk("bad pre/post len %d %d\n", prelen, postlen );
+ return 1;
+ }
+
+ memset( r, 0, sizeof(r[0]) );
+ r->lun = 0;
+ r->target = sd->target;
+ r->is_write = 0;
+ memcpy( r->cdb, cmd, cmdlen );
+ r->client_addr = (int)&r;
+ r->cdb_len = cmdlen;
+ r->sense[0].base = (int)&sb;
+ r->sense[0].size = sizeof(sb);
+ r->size = prelen + len + postlen;
+ r->n_sg = 3;
+ r->sglist.n_el = 3;
+ r->sglist.vec[0].base = (int)prebuf;
+ r->sglist.vec[0].size = prelen;
+ r->sglist.vec[1].base = (int)dest;
+ r->sglist.vec[1].size = len;
+ r->sglist.vec[2].base = (int)postbuf;
+ r->sglist.vec[2].size = postlen;
+
+ if( OSI_SCSISubmit((int)&r) ) {
+ printk("OSI_SCSISubmit: error!\n");
+ return 1;
+ }
+ while( !OSI_SCSIAck() )
+ OSI_USleep( 10 );
+
+ if( r->adapter_status )
+ return -1;
+ if( r->scsi_status )
+ return ((sb[2] & 0xf) << 16) | (sb[12] << 8) | sb[13];
+ return 0;
+}
+
+static int
+scsi_cmd( instance_data_t *sd, const char *cmd, int cmdlen )
+{
+ return scsi_cmd_( sd, cmd, cmdlen, NULL, 0, 0, 0 );
+}
+
+/* ( buf blk nblks -- actual ) */
+static void
+scsi_read_blocks( instance_data_t *sd )
+{
+ int nblks = POP();
+ int blk = POP();
+ char *dest = (char*)POP();
+ unsigned char cmd[10];
+ int len = nblks * sd->info->blocksize;
+
+ memset( dest, 0, len );
+
+ /* printk("READ: blk: %d length %d\n", blk, len ); */
+ memset( cmd, 0, sizeof(cmd) );
+ cmd[0] = 0x28; /* READ_10 */
+ cmd[2] = blk >> 24;
+ cmd[3] = blk >> 16;
+ cmd[4] = blk >> 8;
+ cmd[5] = blk;
+ cmd[7] = nblks >> 8;
+ cmd[8] = nblks;
+
+ if( scsi_cmd_(sd, cmd, 10, dest, len, 0, 0) ) {
+ printk("read: scsi_cmd failed\n");
+ RET( -1 );
+ }
+ PUSH( nblks );
+}
+
+static int
+inquiry( instance_data_t *sd )
+{
+ char inquiry_cmd[6] = { 0x12, 0, 0, 0, 32, 0 };
+ char start_stop_unit_cmd[6] = { 0x1b, 0, 0, 0, 1, 0 };
+ char test_unit_ready_cmd[6] = { 0x00, 0, 0, 0, 0, 0 };
+ char prev_allow_medium_removal[6] = { 0x1e, 0, 0, 0, 1, 0 };
+ char set_cd_speed_cmd[12] = { 0xbb, 0, 0xff, 0xff, 0xff, 0xff,
+ 0, 0, 0, 0, 0, 0 };
+ target_info_t *info = &scsi_devs[sd->target];
+ char ret[32];
+ int i, sense;
+
+ if( sd->target >= MAX_TARGETS )
+ return -1;
+ sd->info = info;
+
+ if( info->probed )
+ return info->valid ? 0:-1;
+ info->probed = 1;
+
+ if( (sense=scsi_cmd_(sd, inquiry_cmd, 6, ret, 2, 0, 0)) ) {
+ if( sense < 0 )
+ return -1;
+ printk("INQUIRY failed\n");
+ return -1;
+ }
+
+ /* medium present? */
+ if( (scsi_cmd(sd, test_unit_ready_cmd, 6) >> 8) == 0x23a ) {
+ printk("no media\n");
+ return -1;
+ }
+
+ info->is_cd = 0;
+ info->blocksize = 512;
+
+ if( ret[0] == 5 /* CD/DVD */ ) {
+ info->blocksize = 2048;
+ info->is_cd = 1;
+
+ scsi_cmd( sd, prev_allow_medium_removal, 6 );
+ scsi_cmd( sd, set_cd_speed_cmd, 12 );
+ scsi_cmd( sd, start_stop_unit_cmd, 6 );
+
+ } else if( ret[0] == 0 /* DISK */ ) {
+ scsi_cmd( sd, test_unit_ready_cmd, 6 );
+ scsi_cmd( sd, start_stop_unit_cmd, 6 );
+ } else {
+ /* don't boot from this device (could be a scanner :-)) */
+ return -1;
+ }
+
+ /* wait for spin-up (or whatever) to complete */
+ for( i=0; ; i++ ) {
+ if( i > 300 ) {
+ printk("SCSI timeout (sense %x)\n", sense );
+ return -1;
+ }
+ sense = scsi_cmd( sd, test_unit_ready_cmd, 6 );
+ if( (sense & 0xf0000) == 0x20000 ) {
+ OSI_USleep( 10000 );
+ continue;
+ }
+ break;
+ }
+
+ info->valid = 1;
+ return 0;
+}
+
+/* ( -- success? ) */
+static void
+scsi_open( instance_data_t *sd )
+{
+ static int once = 0;
+ phandle_t ph;
+
+ fword("my-unit");
+ sd->target = POP();
+
+ if( !once ) {
+ once++;
+ OSI_SCSIControl( SCSI_CTRL_INIT, 0 );
+ }
+
+ /* obtiain device information */
+ if( inquiry(sd) )
+ RET(0);
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ PUSH( -1 );
+}
+
+/* ( -- ) */
+static void
+scsi_close( instance_data_t *pb )
+{
+ selfword("close-deblocker");
+}
+
+
+/* ( -- bs ) */
+static void
+scsi_block_size( instance_data_t *sd )
+{
+ PUSH( sd->info->blocksize );
+}
+
+/* ( -- maxbytes ) */
+static void
+scsi_max_transfer( instance_data_t *sd )
+{
+ PUSH( 1024*1024 );
+}
+
+static void
+scsi_initialize( instance_data_t *sd )
+{
+ fword("is-deblocker");
+}
+
+
+NODE_METHODS( scsi ) = {
+ { NULL, scsi_initialize },
+ { "open", scsi_open },
+ { "close", scsi_close },
+ { "read-blocks", scsi_read_blocks },
+ { "block-size", scsi_block_size },
+ { "max-transfer", scsi_max_transfer },
+};
+
+void
+osiscsi_init( void )
+{
+ REGISTER_NODE( scsi );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/prom.c b/qemu/roms/openbios/arch/ppc/mol/prom.c
new file mode 100644
index 000000000..0bc8bcfbc
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/prom.c
@@ -0,0 +1,175 @@
+/*
+ * Creation Date: <2002/10/03 20:55:02 samuel>
+ * Time-stamp: <2002/10/29 13:00:23 samuel>
+ *
+ * <prom.c>
+ *
+ * oftree interface
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "osi_calls.h"
+#include "mol/prom.h"
+
+/* OSI_PromClose (free linux side device tree) */
+int
+prom_close( void )
+{
+ return OSI_PromIface( kPromClose, 0 );
+}
+
+/* ret: 0 no more peers, -1 if error */
+mol_phandle_t
+prom_peer( mol_phandle_t phandle )
+{
+ return OSI_PromIface( kPromPeer, phandle );
+}
+
+/* ret: 0 no child, -1 if error */
+mol_phandle_t
+prom_child( mol_phandle_t phandle )
+{
+ return OSI_PromIface( kPromChild, phandle );
+}
+
+/* ret: 0 if root node, -1 if error */
+mol_phandle_t
+prom_parent( mol_phandle_t phandle )
+{
+ return OSI_PromIface( kPromParent, phandle );
+}
+
+/* ret: -1 error */
+int
+prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen )
+{
+ return OSI_PromIface2( kPromPackageToPath, phandle, (int)buf, buflen );
+}
+
+/* ret: -1 error */
+int
+prom_get_prop_len( mol_phandle_t phandle, const char *name )
+{
+ return OSI_PromIface1( kPromGetPropLen, phandle, (int)name );
+}
+
+/* ret: prop len or -1 if error */
+int
+prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen )
+{
+ return OSI_PromIface3( kPromGetProp, phandle, (int)name, (int)buf, buflen );
+}
+
+/* ret: prop len or -1 if error */
+int
+prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen )
+{
+ mol_phandle_t ph = prom_find_device(path);
+ return (ph != -1)? prom_get_prop( ph, name, buf, buflen) : -1;
+}
+
+/* ret: -1 error, 0 last prop, 1 otherwise */
+int
+prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf )
+{
+ return OSI_PromIface2( kPromNextProp, phandle, (int)prev, (int)buf );
+}
+
+/* ret: -1 if error */
+int
+prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen )
+{
+ return OSI_PromIface3( kPromSetProp, phandle, (int)name, (int)buf, buflen );
+}
+
+/* ret: -1 if error */
+mol_phandle_t
+prom_create_node( const char *path )
+{
+ return OSI_PromPathIface( kPromCreateNode, path );
+}
+
+/* ret: -1 if not found */
+mol_phandle_t
+prom_find_device( const char *path )
+{
+ mol_phandle_t ph;
+ char buf2[256], ch, *p;
+
+ if( !path )
+ return -1;
+
+ if( (ph=OSI_PromPathIface( kPromFindDevice, path )) != -1 )
+ return ph;
+ else if( path[0] == '/' )
+ return -1;
+
+ /* might be an alias */
+ if( !(p=strpbrk(path, "@:/")) )
+ p = (char*)path + strlen(path);
+
+ ch = *p;
+ *p = 0;
+ if( (ph=prom_get_prop(prom_find_device("/aliases"), path, buf2, sizeof(buf2))) == -1 )
+ return -1;
+ *p = ch;
+ strncat( buf2, p, sizeof(buf2) );
+
+ if( buf2[0] != '/' ) {
+ printk("Error: aliases must be absolute!\n");
+ return -1;
+ }
+ ph = OSI_PromPathIface( kPromFindDevice, buf2 );
+ return ph;
+}
+
+
+
+/************************************************************************/
+/* search the tree for nodes with matching device_type */
+/************************************************************************/
+
+static mol_phandle_t
+prom_find_device_type_( mol_phandle_t ph, const char *type, int *icount, int index )
+{
+ char buf[64];
+ int ph2;
+
+ if( ph == -1 || !ph )
+ return -1;
+ if( prom_get_prop( ph, "device_type", buf, sizeof(buf)) > 0 )
+ if( !strcmp(buf, type) )
+ if( (*icount)++ == index )
+ return ph;
+ if( (ph2=prom_find_device_type_( prom_peer(ph), type, icount, index )) != -1 )
+ return ph2;
+ if( (ph2=prom_find_device_type_( prom_child(ph), type, icount, index )) != -1 )
+ return ph2;
+ return -1;
+}
+
+mol_phandle_t
+prom_find_device_type( const char *type, int index )
+{
+ int count = 0;
+ return prom_find_device_type_( prom_peer(0), type, &count, index );
+}
+
+
+/************************************************************************/
+/* device tree tweaking */
+/************************************************************************/
+
+/* -1 if error */
+int
+prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph )
+{
+ return OSI_PromIface1( kPromChangePHandle, old_ph, (int)new_ph );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/prom.h b/qemu/roms/openbios/arch/ppc/mol/prom.h
new file mode 100644
index 000000000..54a856c27
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/prom.h
@@ -0,0 +1,47 @@
+/*
+ * Creation Date: <2002/10/03 21:07:27 samuel>
+ * Time-stamp: <2003/10/22 22:45:26 samuel>
+ *
+ * <prom.h>
+ *
+ * device tree interface
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_PROM
+#define _H_PROM
+
+/* Note 1: MOL uses -1 as the invalid phandle while OpenFirmware uses 0 as the
+ * invalid phandle (it is also the root node).
+ *
+ * Note 2: phandles might be negative. For instance, phandles originating from
+ * a real Open Firmware tree might look like 0xff123000 (a ROM address)...
+ */
+
+typedef enum { kGetRootPhandle=0 } mol_phandle_t; /* must promote to int */
+
+extern int prom_close( void );
+
+extern mol_phandle_t prom_peer( mol_phandle_t phandle );
+extern mol_phandle_t prom_child( mol_phandle_t phandle );
+extern mol_phandle_t prom_parent( mol_phandle_t phandle );
+extern int prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen );
+extern int prom_get_prop_len( mol_phandle_t phandle, const char *name );
+extern int prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen );
+extern int prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen );
+extern int prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf );
+extern int prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen );
+extern mol_phandle_t prom_create_node( const char *path );
+extern mol_phandle_t prom_find_device( const char *path );
+
+extern mol_phandle_t prom_find_device_type( const char *type, int index );
+
+extern int prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph );
+
+#endif /* _H_PROM */
diff --git a/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c b/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c
new file mode 100644
index 000000000..a98e54845
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c
@@ -0,0 +1,178 @@
+/*
+ * Creation Date: <2003/11/26 16:55:47 samuel>
+ * Time-stamp: <2004/01/07 19:41:54 samuel>
+ *
+ * <pseudodisk.c>
+ *
+ * pseudodisk (contains files exported from linux)
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "osi_calls.h"
+#include "libc/string.h"
+#include "libopenbios/ofmem.h"
+#include "mol/prom.h"
+#include "mol/mol.h"
+#include "osi_calls.h"
+#include "pseudofs_sh.h"
+
+typedef struct {
+ int seekpos;
+ int fd;
+ char *myargs;
+ char *name;
+ int size;
+} pdisk_data_t;
+
+
+DECLARE_NODE( pdisk, INSTALL_OPEN, sizeof(pdisk_data_t), "/mol/pseudo-disk/disk" );
+
+static void
+pdisk_open( pdisk_data_t *pb )
+{
+ char *ep, *name = NULL;
+ int part;
+
+ pb->myargs = my_args_copy();
+ /* printk("pdisk-open: %s\n", pb->myargs ); */
+
+ part = strtol( pb->myargs, &ep, 10 );
+ if( *ep ) {
+ if( (name=strchr(pb->myargs, ',')) ) {
+ *name = 0;
+ name++;
+ } else {
+ name = pb->myargs;
+ }
+ }
+ if( part )
+ goto err;
+
+ if( !name || !strlen(name) )
+ pb->fd = -1;
+ else {
+ if( (pb->fd=PseudoFSOpen(name)) < 0 )
+ goto err;
+ pb->size = PseudoFSGetSize( pb->fd );
+ }
+ pb->name = name;
+ RET( -1 );
+ err:
+ free( pb->myargs );
+ RET(0);
+}
+
+/* ( addr len -- actual ) */
+static void
+pdisk_read( pdisk_data_t *pb )
+{
+ int len = POP();
+ char *dest = (char*)POP();
+ int cnt;
+
+ if( pb->fd < 0 ) {
+ memset( dest, 0, len );
+ PUSH(len);
+ return;
+ }
+ /* dest is not "mol-DMA" safe (might have a nontrivial mapping) */
+ for( cnt=0; cnt<len; ) {
+ char buf[2048];
+ int n = MIN( len-cnt, sizeof(buf) );
+
+ n = PseudoFSRead( pb->fd, pb->seekpos, buf, n );
+ if( n <= 0 )
+ break;
+
+ memcpy( dest+cnt, buf, n );
+ cnt += n;
+ pb->seekpos += n;
+ }
+ PUSH( cnt );
+}
+
+/* ( addr len -- actual ) */
+static void
+pdisk_write( pdisk_data_t *pb )
+{
+ POP(); POP(); PUSH(-1);
+ printk("pdisk write\n");
+}
+
+/* ( pos.lo pos.hi -- status ) */
+static void
+pdisk_seek( pdisk_data_t *pb )
+{
+ int pos_lo;
+ POP();
+ pos_lo = POP();
+
+ if( pb->fd >= 0 ) {
+ if( pos_lo == -1 )
+ pos_lo = pb->size;
+ }
+
+ pb->seekpos = pos_lo;
+
+ PUSH(0); /* ??? */
+}
+
+/* ( -- pos.d ) */
+static void
+pdisk_tell( pdisk_data_t *pb )
+{
+ DPUSH( pb->seekpos );
+}
+
+/* ( -- cstr ) */
+static void
+pdisk_get_path( pdisk_data_t *pb )
+{
+ PUSH( (int)pb->name );
+}
+
+/* ( -- cstr ) */
+static void
+pdisk_get_fstype( pdisk_data_t *pb )
+{
+ PUSH( (int)"PSEUDO" );
+}
+
+/* ( -- cstr ) */
+static void
+pdisk_volume_name( pdisk_data_t *pb )
+{
+ PUSH( (int)"Virtual Volume" );
+}
+
+static void
+pdisk_block_size( pdisk_data_t *pb )
+{
+ PUSH(1);
+}
+
+NODE_METHODS( pdisk ) = {
+ { "open", pdisk_open },
+ { "read", pdisk_read },
+ { "write", pdisk_write },
+ { "seek", pdisk_seek },
+ { "tell", pdisk_tell },
+ { "block-size", pdisk_block_size },
+ { "get-path", pdisk_get_path },
+ { "get-fstype", pdisk_get_fstype },
+ { "volume-name", pdisk_volume_name },
+};
+
+void
+pseudodisk_init( void )
+{
+ REGISTER_NODE( pdisk );
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/tree.c b/qemu/roms/openbios/arch/ppc/mol/tree.c
new file mode 100644
index 000000000..b82c8c2c8
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/tree.c
@@ -0,0 +1,165 @@
+/*
+ * Creation Date: <2003/11/18 14:55:05 samuel>
+ * Time-stamp: <2004/03/27 02:03:55 samuel>
+ *
+ * <tree.c>
+ *
+ * device tree setup
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "mol/mol.h"
+#include "mol/prom.h"
+
+
+/************************************************************************/
+/* copy device tree */
+/************************************************************************/
+
+static void
+copy_node( mol_phandle_t molph )
+{
+ char name[40], path[80];
+ int exists;
+ phandle_t ph;
+
+ if( !molph )
+ return;
+
+ prom_package_to_path( molph, path, sizeof(path) );
+
+ /* don't copy /options node */
+ if( !strcmp("/options", path) ) {
+ copy_node( prom_peer(molph) );
+ return;
+ }
+
+ exists = 1;
+ if( !(ph=find_dev(path)) ) {
+ exists = 0;
+ fword("new-device");
+ ph = get_cur_dev();
+ }
+ activate_dev( ph );
+
+ name[0] = 0;
+ while( prom_next_prop(molph, name, name) > 0 ) {
+ int len = prom_get_prop_len( molph, name );
+ char *p;
+#if 0
+ if( len > 0x1000 ) {
+ printk("prop to large (%d)\n", len );
+ continue;
+ }
+#endif
+ /* don't copy /chosen/{stdin,stdout} (XXX: ugly hack...) */
+ if( !strcmp("/chosen", path) )
+ if( !strcmp("stdio", name) || !strcmp("stdout", name) )
+ continue;
+
+ p = malloc( len );
+ prom_get_prop( molph, name, p, len );
+ set_property( ph, name, p, len );
+ free( p );
+ }
+
+ set_int_property( ph, "MOL,phandle", molph );
+ copy_node( prom_child(molph) );
+
+ if( !exists )
+ fword("finish-device");
+ else
+ activate_device("..");
+
+ copy_node( prom_peer(molph) );
+}
+
+
+
+/************************************************************************/
+/* device tree cloning and tweaking */
+/************************************************************************/
+
+static phandle_t
+translate_molph( mol_phandle_t molph )
+{
+ static mol_phandle_t cached_molph;
+ static phandle_t cached_ph;
+ phandle_t ph=0;
+
+ if( cached_molph == molph )
+ return cached_ph;
+
+ while( (ph=dt_iterate(ph)) )
+ if( get_int_property(ph, "MOL,phandle", NULL) == molph )
+ break;
+ cached_molph = molph;
+ cached_ph = ph;
+
+ if( !ph )
+ printk("failed to translate molph\n");
+ return ph;
+}
+
+static void
+fix_phandles( void )
+{
+ static char *pnames[] = { "interrupt-parent", "interrupt-controller", NULL } ;
+ int len, *map;
+ phandle_t ph=0;
+ char **pp;
+
+ while( (ph=dt_iterate(ph)) ) {
+ for( pp=pnames; *pp; pp++ ) {
+ phandle_t *p = (phandle_t*)get_property( ph, *pp, &len );
+ if( len == 4 )
+ *p = translate_molph( *(int*)p );
+ }
+
+ /* need to fix interrupt map properties too */
+ if( (map=(int*)get_property(ph, "interrupt-map", &len)) ) {
+ int i, acells = get_int_property(ph, "#address-cells", NULL);
+ int icells = get_int_property(ph, "#interrupt-cells", NULL);
+
+ len /= sizeof(int);
+ for( i=0; i<len; i++ ) {
+ phandle_t ch_ph;
+ int ch_acells, ch_icells;
+
+ i += acells + icells;
+ if( !(ch_ph=translate_molph(map[i])) )
+ break;
+ map[i] = (int)ch_ph;
+ ch_acells = get_int_property(ch_ph, "#address-cells", NULL);
+ ch_icells = get_int_property(ch_ph, "#interrupt-cells", NULL);
+ i += ch_acells + icells;
+ }
+ if( i != len )
+ printk("interrupt map fixing failure\n");
+ }
+ }
+ /* delete MOL,phandle properties */
+ for( ph=0; (ph=dt_iterate(ph)) ; ) {
+ push_str("MOL,phandle");
+ PUSH_ph(ph);
+ fword("(delete-property)");
+ }
+ fword("device-end");
+}
+
+void
+devtree_init( void )
+{
+ activate_device("/");
+ copy_node( prom_peer(0) );
+ fix_phandles();
+ fword("tree-fixes");
+}
diff --git a/qemu/roms/openbios/arch/ppc/mol/tree.fs b/qemu/roms/openbios/arch/ppc/mol/tree.fs
new file mode 100644
index 000000000..228163ffc
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/mol/tree.fs
@@ -0,0 +1,103 @@
+
+: int-property ( val name -- )
+ rot encode-int 2swap property
+;
+
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+
+ " device-tree" device-name
+ " bootrom" device-type
+
+\ -------------------------------------------------------------
+\ /memory
+\ -------------------------------------------------------------
+
+new-device
+ " memory" device-name
+ \ 12230 encode-int " reg" property
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+\ -------------------------------------------------------------
+\ /mol/
+\ -------------------------------------------------------------
+
+new-device
+ " mol" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+
+new-device
+ " test" device-name
+
+ external
+ : open
+ ." /mol/test opened" cr
+ " argument-str" " ipose" find-package drop interpose
+ true
+ ;
+finish-device
+finish-device
+
+\ -------------------------------------------------------------
+\ /cpus/
+\ -------------------------------------------------------------
+
+new-device
+ " cpus" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+finish-device
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/mol-stdout
+new-device
+ " mol-stdout" device-name
+ external
+ : open true ;
+ : close ;
+ : write ( addr len -- actual )
+ dup -rot type
+ ;
+finish-device
+
+\ XXXXXXXXXXXXXXXXXXXXXXX TESTING
+" /" find-device
+new-device
+ " test" device-name
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/qemu/roms/openbios/arch/ppc/ofmem.c b/qemu/roms/openbios/arch/ppc/ofmem.c
new file mode 100644
index 000000000..c9b066ed6
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/ofmem.c
@@ -0,0 +1,308 @@
+/*
+ * Creation Date: <1999/11/07 19:02:11 samuel>
+ * Time-stamp: <2004/01/07 19:42:36 samuel>
+ *
+ * <ofmem.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+/* TODO: Clean up MOLisms in a decent way */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "libopenbios/ofmem.h"
+#include "kernel.h"
+#ifdef I_WANT_MOLISMS
+#include "mol/prom.h"
+#include "mol/mol.h"
+#endif
+#include "mmutypes.h"
+#include "asm/processor.h"
+#ifdef I_WANT_MOLISMS
+#include "osi_calls.h"
+#endif
+
+#define BIT(n) (1U<<(31-(n)))
+
+/* called from assembly */
+extern void dsi_exception( void );
+extern void isi_exception( void );
+extern void setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize );
+
+/****************************************************************
+ * Memory usage (before of_quiesce is called)
+ *
+ * Physical
+ *
+ * 0x00000000 Exception vectors
+ * 0x00004000 Free space
+ * 0x01e00000 Open Firmware (us)
+ * 0x01f00000 OF allocations
+ * 0x01ff0000 PTE Hash
+ * 0x02000000- Free space
+ *
+ * Allocations grow downwards from 0x01e00000
+ *
+ ****************************************************************/
+
+#define HASH_SIZE (2 << 15)
+#define SEGR_BASE 0x400 /* segment number range to use */
+
+#define FREE_BASE_1 0x00004000
+#define OF_CODE_START 0x01e00000
+/* #define OF_MALLOC_BASE 0x01f00000 */
+extern char _end[];
+#define OF_MALLOC_BASE _end
+
+#define HASH_BASE (0x02000000 - HASH_SIZE)
+#define FREE_BASE_2 0x02000000
+
+#define RAMSIZE 0x02000000 /* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */
+
+static ofmem_t s_ofmem;
+
+#define IO_BASE 0x80000000
+#define OFMEM (&s_ofmem)
+
+static inline unsigned long
+get_hash_base( void )
+{
+ return HASH_BASE;
+}
+
+static inline unsigned long
+get_hash_size( void )
+{
+ return HASH_SIZE;
+}
+
+static ucell get_heap_top( void )
+{
+ return HASH_BASE;
+}
+
+static inline size_t ALIGN_SIZE(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a-1);
+}
+
+ofmem_t* ofmem_arch_get_private(void)
+{
+ return OFMEM;
+}
+
+void* ofmem_arch_get_malloc_base(void)
+{
+ return OF_MALLOC_BASE;
+}
+
+ucell ofmem_arch_get_heap_top(void)
+{
+ return get_heap_top();
+}
+
+ucell ofmem_arch_get_virt_top(void)
+{
+ return IO_BASE;
+}
+
+void ofmem_arch_unmap_pages(ucell virt, ucell size)
+{
+ /* kill page mappings in provided range */
+}
+
+void ofmem_arch_map_pages(ucell phys, ucell virt, ucell size, ucell mode)
+{
+ /* none yet */
+}
+
+/************************************************************************/
+/* OF private allocations */
+/************************************************************************/
+
+void *
+malloc( int size )
+{
+ return ofmem_malloc(size);
+}
+
+void
+free( void *ptr )
+{
+ return ofmem_free(ptr);
+}
+
+void *
+realloc( void *ptr, size_t size )
+{
+ return ofmem_realloc(ptr, size);
+}
+
+
+/************************************************************************/
+/* misc */
+/************************************************************************/
+
+ucell ofmem_arch_default_translation_mode( ucell phys )
+{
+ /* XXX: Guard bit not set as it should! */
+ if( phys < IO_BASE || phys >= 0xffc00000 )
+ return 0x02; /*0xa*/ /* wim GxPp */
+ return 0x6a; /* WIm GxPp, I/O */
+}
+
+
+/************************************************************************/
+/* page fault handler */
+/************************************************************************/
+
+static ucell
+ea_to_phys( ucell ea, ucell *mode )
+{
+ ucell phys;
+
+ /* hardcode our translation needs */
+ if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) {
+ *mode = ofmem_arch_default_translation_mode( ea );
+ return ea;
+ }
+
+ phys = ofmem_translate(ea, mode);
+ if( phys == (ucell)-1 ) {
+#ifdef I_WANT_MOLISMS
+ if( ea != 0x80816c00 )
+ printk("ea_to_phys: no translation for %08lx, using 1-1\n", ea );
+#endif
+ phys = ea;
+ *mode = ofmem_arch_default_translation_mode( phys );
+
+#ifdef I_WANT_MOLISMS
+ forth_segv_handler( (char*)ea );
+ OSI_Debugger(1);
+#endif
+ /* print_virt_range(); */
+ /* print_phys_range(); */
+ /* print_trans(); */
+ }
+ return phys;
+}
+
+static void
+hash_page( ucell ea, ucell phys, ucell mode )
+{
+ static int next_grab_slot=0;
+ unsigned long *upte, cmp, hash1;
+ int i, vsid, found;
+ mPTE_t *pp;
+
+ vsid = (ea>>28) + SEGR_BASE;
+ cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22);
+
+ hash1 = vsid;
+ hash1 ^= (ea >> 12) & 0xffff;
+ hash1 &= (get_hash_size() - 1) >> 6;
+
+ pp = (mPTE_t*)(get_hash_base() + (hash1 << 6));
+ upte = (unsigned long*)pp;
+
+ /* replace old translation */
+ for( found=0, i=0; !found && i<8; i++ )
+ if( cmp == upte[i*2] )
+ found=1;
+
+ /* otherwise use a free slot */
+ for( i=0; !found && i<8; i++ )
+ if( !pp[i].v )
+ found=1;
+
+ /* out of slots, just evict one */
+ if( !found ) {
+ i = next_grab_slot + 1;
+ next_grab_slot = (next_grab_slot + 1) % 8;
+ }
+ i--;
+ upte[i*2] = cmp;
+ upte[i*2+1] = (phys & ~0xfff) | mode;
+
+ asm volatile( "tlbie %0" :: "r"(ea) );
+}
+
+void
+dsi_exception( void )
+{
+ unsigned long dar, dsisr;
+ ucell mode;
+ ucell phys;
+
+ asm volatile("mfdar %0" : "=r" (dar) : );
+ asm volatile("mfdsisr %0" : "=r" (dsisr) : );
+
+ //printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr );
+
+ phys = ea_to_phys(dar, &mode);
+ hash_page( dar, phys, mode );
+}
+
+void
+isi_exception( void )
+{
+ unsigned long nip, srr1;
+ ucell mode;
+ ucell phys;
+
+ asm volatile("mfsrr0 %0" : "=r" (nip) : );
+ asm volatile("mfsrr1 %0" : "=r" (srr1) : );
+
+ //printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 );
+
+ phys = ea_to_phys(nip, &mode);
+ hash_page( nip, phys, mode );
+}
+
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+void
+setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize )
+{
+ unsigned long sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16);
+ unsigned long sr_base = (0x20 << 24) | SEGR_BASE;
+ unsigned long msr;
+ int i;
+
+ asm volatile("mtsdr1 %0" :: "r" (sdr1) );
+ for( i=0; i<16; i++ ) {
+ int j = i << 28;
+ asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j) );
+ }
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr |= MSR_IR | MSR_DR;
+ asm volatile("mtmsr %0" :: "r" (msr) );
+}
+
+void
+ofmem_init( void )
+{
+ ofmem_t *ofmem = OFMEM;
+ /* In case we can't rely on memory being zero initialized */
+ memset(ofmem, 0, sizeof(ofmem));
+
+ ofmem->ramsize = RAMSIZE;
+
+ ofmem_claim_phys( 0, FREE_BASE_1, 0 );
+ ofmem_claim_virt( 0, FREE_BASE_1, 0 );
+ ofmem_claim_phys( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
+ ofmem_claim_virt( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
+}
diff --git a/qemu/roms/openbios/arch/ppc/osi.h b/qemu/roms/openbios/arch/ppc/osi.h
new file mode 100644
index 000000000..3baae1575
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/osi.h
@@ -0,0 +1,170 @@
+/*
+ * Creation Date: <1999/03/18 03:19:43 samuel>
+ * Time-stamp: <2003/12/26 16:58:19 samuel>
+ *
+ * <os_interface.h>
+ *
+ * This file includes definitions for drivers
+ * running in the "emulated" OS. (Mainly the 'sc'
+ * mechanism of communicating)
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OSI
+#define _H_OSI
+
+/* Magic register values loaded into r3 and r4 before the 'sc' assembly instruction */
+#define OSI_SC_MAGIC_R3 0x113724FA
+#define OSI_SC_MAGIC_R4 0x77810F9B
+
+
+/************************************************************************/
+/* Selectors (passed in r5) */
+/************************************************************************/
+
+#define OSI_CALL_AVAILABLE 0
+#define OSI_DEBUGGER 1 /* enter debugger */
+/* obsolete OSI_LOG_STR 3 */
+#define OSI_CMOUNT_DRV_VOL 4 /* conditionally mount driver volume */
+/* obsolete OSI_SCSI_xxx 5-6 */
+#define OSI_GET_GMT_TIME 7
+#define OSI_MOUSE_CNTRL 8
+#define OSI_GET_LOCALTIME 9 /* return time in secs from 01/01/04 */
+
+#define OSI_ENET_OPEN 10
+#define OSI_ENET_CLOSE 11
+#define OSI_ENET_GET_ADDR 12
+#define OSI_ENET_GET_STATUS 13
+#define OSI_ENET_CONTROL 14
+#define OSI_ENET_ADD_MULTI 16
+#define OSI_ENET_DEL_MULTI 17
+#define OSI_ENET_GET_PACKET 18
+#define OSI_ENET_SEND_PACKET 19
+
+#define OSI_OF_INTERFACE 20
+#define OSI_OF_TRAP 21
+#define OSI_OF_RTAS 22
+
+#define OSI_SCSI_CNTRL 23
+#define OSI_SCSI_SUBMIT 24
+#define OSI_SCSI_ACK 25
+
+#define OSI_GET_MOUSE 26 /* -- r3 status, r4-r8 mouse data */
+#define OSI_ACK_MOUSE_IRQ 27 /* -- int */
+
+#define OSI_SET_VMODE 28 /* modeID, depth -- error */
+#define OSI_GET_VMODE_INFO 29 /* mode, depth -- r3 status, r4-r9 pb */
+#define OSI_GET_MOUSE_DPI 30 /* -- mouse_dpi */
+
+#define OSI_SET_VIDEO_POWER 31
+#define OSI_GET_FB_INFO 32 /* void -- r3 status, r4-r8 video data */
+
+#define OSI_SOUND_WRITE 33
+/* #define OSI_SOUND_FORMAT 34 */
+#define OSI_SOUND_SET_VOLUME 35
+#define OSI_SOUND_CNTL 36
+/* obsolete OSI_SOUND call 37 */
+
+#define OSI_VIDEO_ACK_IRQ 38
+#define OSI_VIDEO_CNTRL 39
+
+#define OSI_SOUND_IRQ_ACK 40
+#define OSI_SOUND_START_STOP 41
+
+#define OSI_REGISTER_IRQ 42 /* reg_property[0] appl_int -- irq_cookie */
+/* obsolete OSI_IRQ 43-46 */
+
+#define OSI_LOG_PUTC 47 /* char -- */
+
+#define OSI_KBD_CNTRL 50
+#define OSI_GET_ADB_KEY 51 /* -- adb_keycode (keycode | keycode_id in r4) */
+
+#define OSI_WRITE_NVRAM_BYTE 52 /* offs, byte -- */
+#define OSI_READ_NVRAM_BYTE 53 /* offs -- byte */
+
+#define OSI_EXIT 54
+
+#define OSI_KEYCODE_TO_ADB 55 /* (keycode | keycode_id) -- adb_keycode */
+#define OSI_MAP_ADB_KEY 56 /* keycode, adbcode -- */
+#define OSI_SAVE_KEYMAPPING 57 /* -- */
+#define OSI_USLEEP 58 /* usecs -- */
+#define OSI_SET_COLOR 59 /* index value -- */
+
+#define OSI_PIC_MASK_IRQ 60 /* irq -- */
+#define OSI_PIC_UNMASK_IRQ 61 /* irq -- */
+#define OSI_PIC_ACK_IRQ 62 /* irq mask_flag -- */
+#define OSI_PIC_GET_ACTIVE_IRQ 63
+
+#define OSI_GET_COLOR 64 /* index -- value */
+
+/* 65-67 old ablk implementation */
+#define OSI_IRQTEST 65
+
+#define OSI_ENET2_OPEN 68
+#define OSI_ENET2_CLOSE 69
+#define OSI_ENET2_CNTRL 70
+#define OSI_ENET2_RING_SETUP 71
+#define OSI_ENET2_KICK 72
+#define OSI_ENET2_GET_HWADDR 73
+#define OSI_ENET2_IRQ_ACK 74
+
+#define OSI_PROM_IFACE 76
+#define kPromClose 0
+#define kPromPeer 1
+#define kPromChild 2
+#define kPromParent 3
+#define kPromPackageToPath 4
+#define kPromGetPropLen 5
+#define kPromGetProp 6
+#define kPromNextProp 7
+#define kPromSetProp 8
+#define kPromChangePHandle 9
+
+#define OSI_PROM_PATH_IFACE 77
+#define kPromCreateNode 16
+#define kPromFindDevice 17
+
+#define OSI_BOOT_HELPER 78
+#define kBootHAscii2Unicode 32
+#define kBootHUnicode2Ascii 33
+#define kBootHGetStrResInd 34 /* key, buf, len -- buf */
+#define kBootHGetRAMSize 35 /* -- ramsize */
+
+#define OSI_ABLK_RING_SETUP 79
+#define OSI_ABLK_CNTRL 80
+#define OSI_ABLK_DISK_INFO 81
+#define OSI_ABLK_KICK 82
+#define OSI_ABLK_IRQ_ACK 83
+#define OSI_ABLK_SYNC_READ 84
+#define OSI_ABLK_SYNC_WRITE 85
+#define OSI_ABLK_BLESS_DISK 86
+
+#define OSI_EMUACCEL 89 /* EMULATE_xxx, nip -- index */
+#define OSI_MAPIN_MREGS 90 /* mphys */
+#define OSI_NVRAM_SIZE 91
+
+#define OSI_MTICKS_TO_USECS 92
+#define OSI_USECS_TO_MTICKS 93
+
+/* obsolete OSI_BLK 94-95 */
+
+#define OSI_PSEUDO_FS 96
+#define kPseudoFSOpen 1
+#define kPseudoFSClose 2
+#define kPseudoFSGetSize 3
+#define kPseudoFSRead 4
+#define kPseudoFSIndex2Name 5
+
+#define OSI_TTY_PUTC 97
+#define OSI_TTY_GETC 98
+#define OSI_TTY_IRQ_ACK 99
+
+#define NUM_OSI_SELECTORS 100 /* remember to increase this... */
+
+#endif /* _H_OSI */
diff --git a/qemu/roms/openbios/arch/ppc/osi_calls.h b/qemu/roms/openbios/arch/ppc/osi_calls.h
new file mode 100644
index 000000000..1d6b3dc5e
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/osi_calls.h
@@ -0,0 +1,454 @@
+/*
+ * Creation Date: <2002/06/16 01:40:57 samuel>
+ * Time-stamp: <2003/12/26 17:02:09 samuel>
+ *
+ * <osi_calls.h>
+ *
+ * OSI call inlines
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OSI_CALLS
+#define _H_OSI_CALLS
+
+#include "osi.h"
+
+/* Old gcc versions have a limit on the number of registers used.
+ * Newer gcc versions (gcc 3.3) require that the clobber list does
+ * not overlap declared registers.
+ */
+#if __GNUC__ == 2 || ( __GNUC__ == 3 && __GNUC_MINOR__ < 3 )
+#define SHORT_REGLIST
+#endif
+
+
+/************************************************************************/
+/* OSI call instantiation macros */
+/************************************************************************/
+
+#define dreg(n) __oc_##n __asm__ (#n)
+#define ir(n) "r" (__oc_##n)
+#define rr(n) "=r" (__oc_##n)
+
+#define _oc_head( input_regs... ) \
+{ \
+ int _ret=0; \
+ { \
+ register unsigned long dreg(r3); \
+ register unsigned long dreg(r4); \
+ register unsigned long dreg(r5) \
+ ,##input_regs ;
+
+#define _oc_syscall( number, extra_ret_regs... ) \
+ __oc_r3 = OSI_SC_MAGIC_R3; \
+ __oc_r4 = OSI_SC_MAGIC_R4; \
+ __oc_r5 = number; \
+ __asm__ __volatile__ ( \
+ "sc " : rr(r3) ,## extra_ret_regs
+
+#define _oc_input( regs... ) \
+ : ir(r3), ir(r4), ir(r5) \
+ , ## regs \
+ : "memory" );
+
+/* the tail memory clobber is necessary since we violate the strict
+ * aliasing rules when we return structs through the registers.
+ */
+#define _oc_tail \
+ asm volatile ( "" : : : "memory" ); \
+ _ret = __oc_r3; \
+ } \
+ return _ret; \
+}
+
+
+/************************************************************************/
+/* Alternatives */
+/************************************************************************/
+
+#ifdef SHORT_REGLIST
+#define _oc_syscall_r10w6( number, inputregs... ) \
+ __oc_r3 = OSI_SC_MAGIC_R3; \
+ __oc_r4 = OSI_SC_MAGIC_R4; \
+ __oc_r5 = number; \
+ __asm__ __volatile__ ( \
+ "sc \n" \
+ "stw 4,0(10) \n" \
+ "stw 5,4(10) \n" \
+ "stw 6,8(10) \n" \
+ "stw 7,12(10) \n" \
+ "stw 8,16(10) \n" \
+ "stw 9,20(10) \n" \
+ : rr(r3) \
+ : ir(r3), ir(r4), ir(r5), ir(r10) \
+ ,## inputregs \
+ : "memory", \
+ "r4", "r5", "r6", "r7", "r8", "r9" );
+#endif
+
+
+/************************************************************************/
+/* Common helper functions */
+/************************************************************************/
+
+#define _osi_call0( type, name, number ) \
+type name( void ) \
+ _oc_head() \
+ _oc_syscall( number ) \
+ _oc_input() \
+ _oc_tail
+
+#define _osi_call1( type, name, number, type1, arg1 ) \
+type name( type1 arg1 ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)arg1; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6) ) \
+ _oc_tail
+
+#define _osi_call2( type, name, number, t1, a1, t2, a2 ) \
+type name( t1 a1, t2 a2 ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ _oc_tail
+
+#define _osi_call3( type, name, number, t1, a1, t2, a2, t3, a3 ) \
+type name( t1 a1, t2 a2, t3 a3 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8) ) \
+ _oc_tail
+
+#define _osi_call4( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4 ) \
+type name( t1 a1, t2 a2, t3 a3, t4 a4 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ __oc_r9 = (unsigned long)a4; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8), ir(r9) ) \
+ _oc_tail
+
+#define _osi_call5( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5 ) \
+type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ __oc_r9 = (unsigned long)a4; \
+ __oc_r10 = (unsigned long)a5; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10) ) \
+ _oc_tail
+
+#define _osi_call6( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6 ) \
+type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10), dreg(r11) )\
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ __oc_r9 = (unsigned long)a4; \
+ __oc_r10 = (unsigned long)a5; \
+ __oc_r11 = (unsigned long)a6; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10), ir(r11) ) \
+ _oc_tail
+
+
+/************************************************************************/
+/* Special */
+/************************************************************************/
+
+/* r4 returned in retarg1 pointer */
+#define _osi_call0_w1( type, name, number, type1, retarg1 ) \
+type name( type1 retarg1 ) \
+ _oc_head() \
+ _oc_syscall( number, rr(r4) ) \
+ _oc_input() \
+ *retarg1 = __oc_r4; \
+ _oc_tail
+
+#define _osi_call0_w2( type, name, number, type1, retarg1 ) \
+type name( type1 retarg1 ) \
+ _oc_head() \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input() \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg1)[1] = __oc_r5; \
+ _oc_tail
+
+/* r4-r8 returned in retarg1 pointer */
+#define _osi_call0_w5( type, name, number, type1, retarg1 ) \
+type name( type1 retarg1 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \
+ _oc_syscall( number, \
+ rr(r4), rr(r5), rr(r6), rr(r7), rr(r8) ) \
+ _oc_input() \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg1)[1] = __oc_r5; \
+ ((unsigned long*)retarg1)[2] = __oc_r6; \
+ ((unsigned long*)retarg1)[3] = __oc_r7; \
+ ((unsigned long*)retarg1)[4] = __oc_r8; \
+ _oc_tail
+
+/* r4 returned in retarg pointer */
+#define _osi_call1_w1( type, name, number, t1, a1, t2, retarg ) \
+type name( t1 a1, t2 retarg ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ _oc_tail
+
+/* r4,r5 returned in retarg1, retarg2 */
+#define _osi_call1_w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2 ) \
+type name( t1 a1, t2 retarg1, t3 retarg2 ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg2)[0] = __oc_r5; \
+ _oc_tail
+
+/* r4,r5 returned in retarg1, retarg2, retarg3 */
+#define _osi_call1_w1w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2, t4, retarg3 ) \
+type name( t1 a1, t2 retarg1, t3 retarg2, t4 retarg3 ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg2)[0] = __oc_r5; \
+ ((unsigned long*)retarg3)[0] = __oc_r6; \
+ _oc_tail
+
+/* r4,r5 returned in retarg pointer */
+#define _osi_call1_w2( type, name, number, t1, a1, t2, retarg ) \
+type name( t1 a1, t2 retarg ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ _oc_tail
+
+/* r4-r7 returned in retarg pointer */
+#define _osi_call1_w4( type, name, number, t1, a1, t2, retarg ) \
+type name( t1 a1, t2 retarg ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ ((unsigned long*)retarg)[2] = __oc_r6; \
+ ((unsigned long*)retarg)[3] = __oc_r7; \
+ _oc_tail
+
+
+/* r4-r5 returned in retarg pointer */
+#define _osi_call2_w2( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ _oc_tail
+
+/* r4-r7 returned in retarg pointer */
+#define _osi_call2_w4( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ ((unsigned long*)retarg)[2] = __oc_r6; \
+ ((unsigned long*)retarg)[3] = __oc_r7; \
+ _oc_tail
+
+#ifdef SHORT_REGLIST
+/* r4-r9 returned in retarg pointer */
+#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r10) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r10 = (unsigned long)retarg; \
+ _oc_syscall_r10w6( number, ir(r6), ir(r7) ) \
+ _oc_tail
+
+#else /* SHORT_REGLIST */
+
+/* r4-r9 returned in retarg pointer */
+#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7), rr(r8), rr(r9) ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ ((unsigned long*)retarg)[2] = __oc_r6; \
+ ((unsigned long*)retarg)[3] = __oc_r7; \
+ ((unsigned long*)retarg)[4] = __oc_r8; \
+ ((unsigned long*)retarg)[5] = __oc_r9; \
+ _oc_tail
+
+#endif /* SHORT_REGLIST */
+
+
+/************************************************************************/
+/* OSI call inlines */
+/************************************************************************/
+
+static inline _osi_call1( int, OSI_CallAvailable, OSI_CALL_AVAILABLE, int, osi_num );
+
+static inline _osi_call1( int, OSI_PutC, OSI_LOG_PUTC, int, ch );
+
+static inline _osi_call1( int, OSI_Debugger, OSI_DEBUGGER, int, num );
+static inline _osi_call0( int, OSI_Exit, OSI_EXIT );
+
+/* misc */
+static inline _osi_call0( unsigned long, OSI_GetLocalTime, OSI_GET_LOCALTIME );
+static inline _osi_call0( unsigned long, OSI_GetGMTTime, OSI_GET_GMT_TIME );
+static inline _osi_call1( int, OSI_USleep, OSI_USLEEP, int, usecs );
+
+/* NVRAM */
+static inline _osi_call0( int, OSI_NVRamSize, OSI_NVRAM_SIZE );
+static inline _osi_call1( int, OSI_ReadNVRamByte, OSI_READ_NVRAM_BYTE, int, offs );
+static inline _osi_call2( int, OSI_WriteNVRamByte, OSI_WRITE_NVRAM_BYTE, int, offs,
+ unsigned char, ch );
+
+/* keyboard stuff */
+static inline _osi_call0_w1( int, OSI_GetAdbKey2, OSI_GET_ADB_KEY, int *, raw_key );
+static inline _osi_call1( int, OSI_KbdCntrl, OSI_KBD_CNTRL, int, cmd );
+
+static inline int OSI_GetAdbKey( void )
+ { int dummy_raw_key; return OSI_GetAdbKey2( &dummy_raw_key ); }
+static inline _osi_call2( int, OSI_MapAdbKey, OSI_MAP_ADB_KEY, int, keycode, int, adbkey )
+static inline _osi_call1( int, OSI_KeycodeToAdb, OSI_KEYCODE_TO_ADB, int, keycode );
+static inline _osi_call0( int, OSI_SaveKeymapping, OSI_SAVE_KEYMAPPING );
+
+/* mouse support */
+struct osi_mouse;
+static inline _osi_call0_w5( int, OSI_GetMouse, OSI_GET_MOUSE, struct osi_mouse *, ret );
+static inline _osi_call0( int, OSI_GetMouseDPI, OSI_GET_MOUSE_DPI );
+
+/* video */
+static inline _osi_call2( int, OSI_SetVMode_, OSI_SET_VMODE, int, mode, int, depth_mode );
+struct osi_get_vmode_info;
+static inline _osi_call2_w6( int, OSI_GetVModeInfo_, OSI_GET_VMODE_INFO, int, mode, int, depth_mode,
+ struct osi_get_vmode_info *, ret );
+static inline _osi_call1( int, OSI_SetVPowerState, OSI_SET_VIDEO_POWER, int, power_state );
+static inline _osi_call2( int, OSI_SetColor, OSI_SET_COLOR, int, index, int, rgb );
+static inline _osi_call0_w1( int, OSI_VideoAckIRQ, OSI_VIDEO_ACK_IRQ, int *, events );
+
+static inline void OSI_RefreshPalette( void ) { OSI_SetColor(-1,0); }
+
+/* PIC (mac-io replacement) */
+static inline _osi_call1( int, OSI_PICMaskIRQ, OSI_PIC_MASK_IRQ, int, irq );
+static inline _osi_call1( int, OSI_PICUnmaskIRQ, OSI_PIC_UNMASK_IRQ, int, irq );
+static inline _osi_call2( int, OSI_PICAckIRQ, OSI_PIC_ACK_IRQ, int, irq, int, mask_it );
+static inline _osi_call0( int, OSI_PICGetActiveIRQ, OSI_PIC_GET_ACTIVE_IRQ );
+
+/* sound */
+static inline _osi_call1( int, OSI_SoundCntl, OSI_SOUND_CNTL, int, cmd );
+static inline _osi_call2( int, OSI_SoundCntl1, OSI_SOUND_CNTL, int, cmd, int, p1 );
+static inline _osi_call3( int, OSI_SoundCntl2, OSI_SOUND_CNTL, int, cmd, int, p1, int, p2 );
+static inline _osi_call0_w2( int, OSI_SoundIRQAck, OSI_SOUND_IRQ_ACK, unsigned long *, timestamp );
+static inline _osi_call3( int, OSI_SoundWrite, OSI_SOUND_WRITE, int, physbuf, int, len, int, restart );
+static inline _osi_call3( int, OSI_SoundSetVolume, OSI_SOUND_SET_VOLUME, int, hwvol, int, speakervol, int, mute );
+
+/* async block driver */
+struct ablk_disk_info;
+static inline _osi_call2_w4( int, OSI_ABlkDiskInfo, OSI_ABLK_DISK_INFO, int, channel, int, unit,
+ struct ablk_disk_info *, retinfo );
+static inline _osi_call1( int, OSI_ABlkKick, OSI_ABLK_KICK, int, channel );
+static inline _osi_call1_w1w1w1( int, OSI_ABlkIRQAck, OSI_ABLK_IRQ_ACK, int, channel, int *, req_count,
+ int *, active, int *, events );
+static inline _osi_call3( int, OSI_ABlkRingSetup, OSI_ABLK_RING_SETUP, int, channel, int, mphys, int, n_el );
+static inline _osi_call2( int, OSI_ABlkCntrl, OSI_ABLK_CNTRL, int, channel, int, cmd );
+static inline _osi_call3( int, OSI_ABlkCntrl1, OSI_ABLK_CNTRL, int, channel, int, cmd, int, param );
+static inline _osi_call5( int, OSI_ABlkSyncRead, OSI_ABLK_SYNC_READ, int, channel, int, unit,
+ int, blk, unsigned long, mphys, int, size );
+static inline _osi_call5( int, OSI_ABlkSyncWrite, OSI_ABLK_SYNC_WRITE, int, channel, int, unit,
+ int, blk, unsigned long, mphys, int, size );
+static inline _osi_call2( int, OSI_ABlkBlessDisk, OSI_ABLK_BLESS_DISK, int, channel, int, unit );
+
+static inline _osi_call0( int, OSI_CMountDrvVol, OSI_CMOUNT_DRV_VOL );
+
+/* enet2 */
+static inline _osi_call0( int, OSI_Enet2Open, OSI_ENET2_OPEN );
+static inline _osi_call0( int, OSI_Enet2Close, OSI_ENET2_CLOSE );
+static inline _osi_call3( int, OSI_Enet2RingSetup, OSI_ENET2_RING_SETUP, int, which_ring,
+ int, ring_mphys, int, n_el );
+static inline _osi_call2( int, OSI_Enet2Cntrl1, OSI_ENET2_CNTRL, int, cmd, int, param );
+static inline _osi_call1( int, OSI_Enet2Cntrl, OSI_ENET2_CNTRL, int, cmd );
+static inline _osi_call0( int, OSI_Enet2Kick, OSI_ENET2_KICK );
+
+static inline _osi_call0_w2( int, OSI_Enet2GetHWAddr__, OSI_ENET2_GET_HWADDR, unsigned long *, retbuf );
+static inline int OSI_Enet2GetHWAddr( unsigned char *addr ) {
+ int ret;
+ unsigned long buf[2];
+
+ ret = OSI_Enet2GetHWAddr__( buf );
+
+ ((unsigned long*)addr)[0] = buf[0];
+ ((unsigned short*)addr)[2] = (buf[1] >> 16);
+ return ret;
+}
+static inline _osi_call2( int, OSI_Enet2IRQAck, OSI_ENET2_IRQ_ACK, int, irq_enable, int, rx_head );
+
+/* PROM (device-tree) */
+static inline _osi_call2( int, OSI_PromIface, OSI_PROM_IFACE, int, what, int, ph );
+static inline _osi_call3( int, OSI_PromIface1, OSI_PROM_IFACE, int, what, int, ph, int, p1 );
+static inline _osi_call4( int, OSI_PromIface2, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2 );
+static inline _osi_call5( int, OSI_PromIface3, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2, int, p3 );
+static inline _osi_call2( int, OSI_PromPathIface, OSI_PROM_PATH_IFACE, int, what, const char *, p );
+
+/* emulation acceleration */
+static inline _osi_call1( int, OSI_MapinMregs, OSI_MAPIN_MREGS, unsigned long, mphys );
+static inline _osi_call3( int, OSI_EmuAccel, OSI_EMUACCEL, int, emuaccel_flags, int, param, int, inst_addr );
+
+/* timer frequency */
+static inline _osi_call1( int, OSI_MticksToUsecs, OSI_MTICKS_TO_USECS, unsigned long, mticks );
+static inline _osi_call1( int, OSI_UsecsToMticks, OSI_USECS_TO_MTICKS, unsigned long, usecs );
+
+/* fb info */
+struct osi_fb_info;
+static inline _osi_call0_w5( int, OSI_GetFBInfo, OSI_GET_FB_INFO, struct osi_fb_info *, retinfo );
+
+/* SCSI */
+static inline _osi_call0( int, OSI_SCSIAck, OSI_SCSI_ACK );
+static inline _osi_call1( int, OSI_SCSISubmit, OSI_SCSI_SUBMIT, int, req_mphys );
+static inline _osi_call2( int, OSI_SCSIControl, OSI_SCSI_CNTRL, int, sel, int, param );
+
+/* TTY */
+static inline _osi_call0( int, OSI_TTYGetc, OSI_TTY_GETC );
+static inline _osi_call1( int, OSI_TTYPutc, OSI_TTY_PUTC, int, ch );
+static inline _osi_call0( int, OSI_TTYIRQAck, OSI_TTY_IRQ_ACK );
+
+#endif /* _H_OSI_CALLS */
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/console.c b/qemu/roms/openbios/arch/ppc/pearpc/console.c
new file mode 100644
index 000000000..3869cbab5
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/console.c
@@ -0,0 +1,43 @@
+
+/*
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "libopenbios/ofmem.h"
+#include "pearpc/pearpc.h"
+
+
+typedef struct osi_fb_info {
+ unsigned long mphys;
+ int rb, w, h, depth;
+} osi_fb_info_t;
+
+
+int PearPC_GetFBInfo( osi_fb_info_t *fb )
+{
+
+ fb->w=1024;
+ fb->h=768;
+ fb->depth=15;
+ fb->rb=2048;
+ fb->mphys=0x84000000;
+
+ return 0;
+}
+
+#define openbios_GetFBInfo(x) PearPC_GetFBInfo(x)
+
+#include "../../../packages/video.c"
+#include "../../../libopenbios/console_common.c"
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/init.c b/qemu/roms/openbios/arch/ppc/pearpc/init.c
new file mode 100644
index 000000000..ca6da0a44
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/init.c
@@ -0,0 +1,136 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <init.c>
+ *
+ * Initialization for pearpc
+ *
+ * Copyright (C) 2004 Greg Watson
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * based on mol/init.c:
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ * (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "pearpc/pearpc.h"
+#include "libopenbios/ofmem.h"
+#include "openbios-version.h"
+
+extern void unexpected_excep( int vector );
+extern void ob_pci_init( void );
+extern void ob_adb_init( void );
+extern void setup_timers( void );
+
+#if 0
+int
+get_bool_res( const char *res )
+{
+ char buf[8], *p;
+
+ p = BootHGetStrRes( res, buf, sizeof(buf) );
+ if( !p )
+ return -1;
+ if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") )
+ return 1;
+ return 0;
+}
+#endif
+
+void
+unexpected_excep( int vector )
+{
+ printk("openbios panic: Unexpected exception %x\n", vector );
+ for( ;; )
+ ;
+}
+
+unsigned long isa_io_base;
+
+void
+entry( void )
+{
+ isa_io_base = 0x80000000;
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for( ;; )
+ ;
+}
+
+static void
+setenv( char *env, char *value )
+{
+ push_str( value );
+ push_str( env );
+ fword("$setenv");
+}
+
+void
+arch_of_init( void )
+{
+#if CONFIG_RTAS
+ phandle_t ph;
+#endif
+ int autoboot;
+
+ devtree_init();
+ nvram_init("/pci/mac-io/nvram");
+ openbios_init();
+ modules_init();
+ setup_timers();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+#endif
+ node_methods_init();
+ init_video();
+
+#if CONFIG_RTAS
+ if( !(ph=find_dev("/rtas")) )
+ printk("Warning: No /rtas node\n");
+ else {
+ unsigned long size = 0x1000;
+ while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+ size *= 2;
+ set_property( ph, "rtas-size", (char*)&size, sizeof(size) );
+ }
+#endif
+
+#if 0
+ /* tweak boot settings */
+ autoboot = !!get_bool_res("autoboot");
+#endif
+ autoboot = 0;
+ if( !autoboot )
+ printk("Autobooting disabled - dropping into OpenFirmware\n");
+ setenv("auto-boot?", autoboot ? "true" : "false" );
+ setenv("boot-command", "pearpcboot");
+
+#if 0
+ if( get_bool_res("tty-interface") == 1 )
+#endif
+ fword("activate-tty-interface");
+
+ /* hack */
+ device_end();
+ bind_func("pearpcboot", boot );
+}
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/kernel.c b/qemu/roms/openbios/arch/ppc/pearpc/kernel.c
new file mode 100644
index 000000000..6408e421e
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/kernel.c
@@ -0,0 +1,16 @@
+/*
+ * Creation Date: <2004/08/28 18:03:25 stepan>
+ * Time-stamp: <2004/08/28 18:03:25 stepan>
+ *
+ * <pearpc/kernel.c>
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "pearpc-dict.h"
+#include "../kernel.c"
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/main.c b/qemu/roms/openbios/arch/ppc/pearpc/main.c
new file mode 100644
index 000000000..085494e56
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/main.c
@@ -0,0 +1,145 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <main.c>
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "pearpc/pearpc.h"
+#include "libopenbios/ofmem.h"
+
+static void
+transfer_control_to_elf( unsigned long entry )
+{
+ extern void call_elf( unsigned long entry );
+ printk("Starting ELF image at 0x%08lX\n", entry);
+ call_elf( 0x400000 );
+ //call_elf( entry );
+
+ fatal_error("call_elf returned unexpectedly\n");
+}
+
+static int
+load_elf_rom( unsigned long *entry, int fd )
+{
+ int i, lszz_offs, elf_offs;
+ char buf[128], *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ printk("Loading '%s'\n", get_file_path(fd));
+
+ /* the ELF-image (usually) starts at offset 0x4000 */
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ exit(1);
+ }
+ if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
+ fatal_error("elf_readhdrs failed\n");
+
+ *entry = ehdr.e_entry;
+
+ /* load segments. Compressed ROM-image assumed to be located immediately
+ * after the last segment */
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ /* p_memsz, p_flags */
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
+ fatal_error("Claim failed!\n");
+
+ addr = (char*)phdr[i].p_vaddr;
+ if( read_io(fd, addr, s) != s )
+ fatal_error("read failed\n");
+
+#if 0
+ /* patch CODE segment */
+ if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
+ patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
+ newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
+ }
+#endif
+ flush_icache_range( addr, addr+s );
+
+ /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
+ }
+ free( phdr );
+ return lszz_offs;
+}
+
+
+static void
+encode_bootpath( const char *spec, const char *args )
+{
+ phandle_t chosen_ph = find_dev("/chosen");
+ set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
+ set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
+}
+
+/************************************************************************/
+/* pearpc booting */
+/************************************************************************/
+
+static void
+pearpc_startup( void )
+{
+ const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
+ const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
+ unsigned long entry;
+ int i, fd;
+
+ for( i=0; paths[i]; i++ ) {
+ if( (fd=open_io(paths[i])) == -1 )
+ continue;
+ (void) load_elf_rom( &entry, fd );
+ close_io( fd );
+ encode_bootpath( paths[i], args[i] );
+
+ update_nvram();
+ transfer_control_to_elf( entry );
+ /* won't come here */
+ }
+ printk("*** Boot failure! No secondary bootloader specified ***\n");
+}
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ fword("update-chosen");
+ pearpc_startup();
+}
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/methods.c b/qemu/roms/openbios/arch/ppc/pearpc/methods.c
new file mode 100644
index 000000000..f505b6cea
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/methods.c
@@ -0,0 +1,329 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "pearpc/pearpc.h"
+#include "libopenbios/ofmem.h"
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+#ifdef CONFIG_RTAS
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ int physbase = POP();
+ int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+#endif
+
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+
+ printk( "%s", s );
+ //vfd_draw_str( s );
+ console_draw_fstr(addr, len);
+
+ PUSH( len );
+}
+
+NODE_METHODS( video_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+ printk("=============================================================\n\n");
+}
+
+/* ( -- ms ) */
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ extern unsigned long get_timer_freq();
+ static unsigned long mticks=0, usecs=0;
+ unsigned long t;
+
+ asm volatile("mftb %0" : "=r" (t) : );
+ if( mticks )
+ usecs += get_timer_freq() / 1000000 * ( t-mticks );
+ mticks = t;
+
+ PUSH( usecs/1000 );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
+DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == (ucell)-1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ ucell mode = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell phys = POP();
+ ucell ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ POP();
+ POP();
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+#ifdef CONFIG_RTAS
+ REGISTER_NODE( rtas );
+#endif
+ REGISTER_NODE( video_stdout );
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE( mmu );
+ REGISTER_NODE( mmu_ciface );
+ REGISTER_NODE( tty );
+}
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/pearpc.c b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.c
new file mode 100644
index 000000000..234052ce4
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.c
@@ -0,0 +1,206 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <pearpc.c>
+ *
+ * Copyright (C) 2004, Greg Watson
+ *
+ * derived from mol.c
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "pearpc/pearpc.h"
+#include <stdarg.h>
+
+#define UART_BASE 0x3f8
+
+// FIXME
+unsigned long virt_offset = 0;
+
+
+void
+exit( int status )
+{
+ for (;;);
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ exit(0);
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ exit(0);
+
+ /* won't come here... this keeps the gcc happy */
+ for( ;; )
+ ;
+}
+
+
+/************************************************************************/
+/* print using OSI interface */
+/************************************************************************/
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ putchar( '>' );
+ putchar( '>' );
+ putchar( ' ' );
+ }
+ putchar( *p );
+ }
+ return i;
+}
+
+
+/************************************************************************/
+/* TTY iface */
+/************************************************************************/
+
+static int ttychar = -1;
+
+static int
+tty_avail( void )
+{
+ return 1;
+}
+
+static int
+tty_putchar( int c )
+{
+ if( tty_avail() ) {
+ while (!(inb(UART_BASE + 0x05) & 0x20))
+ ;
+ outb(c, UART_BASE);
+ while (!(inb(UART_BASE + 0x05) & 0x40))
+ ;
+ }
+ return c;
+}
+
+int
+availchar( void )
+{
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ ttychar = inb(UART_BASE);
+ return (ttychar >= 0);
+}
+
+int
+getchar( void )
+{
+ int ch;
+
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ return inb(UART_BASE);
+ ch = ttychar;
+ ttychar = -1;
+ return ch;
+}
+
+int
+putchar( int c )
+{
+ if (c == '\n')
+ tty_putchar('\r');
+ return tty_putchar(c);
+}
+
+
+/************************************************************************/
+/* briQ specific stuff */
+/************************************************************************/
+
+#define IO_NVRAM_PA_START 0x80860000
+#define IO_NVRAM_PA_END 0x80880000
+
+static char *nvram=(char *)IO_NVRAM_PA_START;
+
+void
+dump_nvram(void)
+{
+ static char hexdigit[] = "0123456789abcdef";
+ int i;
+ for (i = 0; i < 16*4; i++)
+ {
+ printk ("%c", hexdigit[nvram[i<<4] >> 4]);
+ printk ("%c", hexdigit[nvram[i<<4] % 16]);
+ if (!((i + 1) % 16))
+ {
+ printk ("\n");
+ }
+ else
+ {
+ printk (" ");
+ }
+ }
+}
+
+
+int
+arch_nvram_size( void )
+{
+ return (IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4;
+}
+
+void
+arch_nvram_put( char *buf )
+{
+ int i;
+ for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++)
+ nvram[i<<4]=buf[i];
+ // memcpy(nvram, buf, IO_NVRAM_PA_END-IO_NVRAM_PA_START);
+ printk("new nvram:\n");
+ dump_nvram();
+}
+
+void
+arch_nvram_get( char *buf )
+{
+ int i;
+ for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++)
+ buf[i]=nvram[i<<4];
+
+ //memcpy(buf, nvram, IO_NVRAM_PA_END-IO_NVRAM_PA_START);
+ printk("current nvram:\n");
+ dump_nvram();
+}
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs
new file mode 100644
index 000000000..0d018b1c3
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs
@@ -0,0 +1,116 @@
+\ pearpc specific initialization code
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " rtc" " /pci/isa/rtc" preopen
+ " memory" " /memory" preopen
+ " mmu" " /cpu@0" preopen
+ \ " stdout" " /packages/terminal-emulator" preopen
+ " stdout" " /pci/pci6666,6666" preopen
+ " stdin" " /pci/via-cuda/adb" preopen
+
+; SYSTEM-initializer
+
+
+\ -------------------------------------------------------------------------
+\ device tree fixing
+\ -------------------------------------------------------------------------
+
+\ add decode-address methods
+: (make-decodable) ( phandle -- )
+
+ dup " #address-cells" rot get-package-property 0= if
+ decode-int nip nip
+ over " decode-unit" rot find-method if 2drop else
+ ( save phandle ncells )
+
+ over active-package!
+ case
+ 1 of ['] parse-hex " decode-unit" is-xt-func endof
+ 3 of
+ " bus-range" active-package get-package-property 0= if
+ decode-int nip nip
+ ['] encode-unit-pci " encode-unit" is-xt-func
+ " decode-unit" is-func-begin
+ ['] (lit) , ,
+ ['] decode-unit-pci-bus ,
+ is-func-end
+ then
+ endof
+ endcase
+ then
+ then
+ drop
+;
+
+: init-pearpc-tree ( -- )
+ active-package
+
+ iterate-tree-begin
+ begin ?dup while
+
+ dup (make-decodable)
+
+ iterate-tree
+ repeat
+
+ active-package!
+;
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ " /pci/via-cuda/adb" " input-device" $setenv
+ " /pci/pci6666,6666" " output-device" $setenv
+ then
+;
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then
+ device-end
+;
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/pearpc.h b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.h
new file mode 100644
index 000000000..44497d79e
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.h
@@ -0,0 +1,26 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <pearpc.h>
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_PEARPC
+#define _H_PEARPC
+
+/* vfd.c */
+extern int vfd_draw_str( const char *str );
+extern void vfd_close( void );
+
+extern int console_draw_fstr(const char *str, int len);
+
+#include "kernel.h"
+
+#endif /* _H_PEARPC */
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/tree.c b/qemu/roms/openbios/arch/ppc/pearpc/tree.c
new file mode 100644
index 000000000..abd1bf024
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/tree.c
@@ -0,0 +1,23 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <tree.c>
+ *
+ * device tree setup
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+
+void devtree_init( void )
+{
+ fword("init-pearpc-tree");
+}
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/tree.fs b/qemu/roms/openbios/arch/ppc/pearpc/tree.fs
new file mode 100644
index 000000000..d19b485f8
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/tree.fs
@@ -0,0 +1,305 @@
+\ PearPC specific initialization code
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+
+" chrp" device-type
+" OpenSource,PEARPC" model
+h# 80000000 encode-int " isa-io-base" property
+1 encode-int " #interrupt-cells" property
+1 encode-int " #size-cells" property
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ 0 encode-int h# 1E00000 encode-int encode+
+ h# 2000000 encode-int encode+ h# 40000000 encode-int encode+
+ " available" property
+ 0 h# 40000000 reg
+ external
+ : open true ;
+ : close ;
+finish-device
+
+new-device
+ " cpu" device-name
+ " cpu" device-type
+ " " encode-string " translations" property
+ 0 encode-phys h# 8000000 encode-int encode+ " available" property
+ d# 32 encode-int " d-cache-block-size" property
+ 8 encode-int " d-cache-sets" property
+ d# 32768 encode-int " d-cache-size" property
+ d# 32 encode-int " i-cache-block-size" property
+ 8 encode-int " i-cache-sets" property
+ d# 32768 encode-int " i-cache-size" property
+ " " encode-string " cache-unified" property
+ 2 encode-int " i-tlb-sets" property
+ d# 128 encode-int " i-tlb-size" property
+ 2 encode-int " d-tlb-sets" property
+ d# 128 encode-int " d-tlb-size" property
+ " " encode-string " tlb-split" property
+ 2 encode-int " tlb-sets" property
+ d# 256 encode-int " tlb-size" property
+ " " encode-string " performance-monitor" property
+ " " encode-string " graphics" property
+ 4 encode-int " reservation-granule-size" property
+ d# 25000000 encode-int " timebase-frequency" property
+ d# 300000000 encode-int " clock-frequency" property
+ d# 66000000 encode-int " bus-frequency" property
+ h# 88201 encode-int " cpu-version" property
+ 0 encode-int " reg" property
+finish-device
+
+" /pci" find-device
+ h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ h# 80000000 encode-int encode+ 0 encode-int encode+
+ h# 01000000 encode-int encode+
+ h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+
+ h# C0000000 encode-int encode+ 0 encode-int encode+
+ h# 08000000 encode-int encode+
+ " ranges" property
+ " IBM,CPC710" model
+ h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property
+ h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 7 encode-int encode+
+ " interrupt-map-mask" property
+ 1 encode-int " #interrupt-cells" property
+ h# 80000000 encode-int " system-dma-base" property
+ d# 33333333 encode-int " clock-frequency" property
+ " " encode-string " primary-bridge" property
+ 0 encode-int " pci-bridge-number" property
+ h# FEC00000 encode-int h# 100000 encode-int encode+ " reg" property
+ 0 encode-int 0 encode-int encode+ " bus-range" property
+
+new-device
+ " isa" device-name
+ " isa" device-type
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+
+ external
+ : open true ;
+ : close ;
+
+finish-device
+
+: ?devalias ( alias-str alias-len device-str device-len --
+ \ alias-str alias-len false | true )
+ active-package >r
+ " /aliases" find-device
+ \ 2dup ." Checking " type
+ 2dup find-dev if \ check if device exists
+ drop
+ 2over find-dev if \ do we already have an alias?
+ \ ." alias exists" cr
+ drop 2drop false
+ else
+ \ ." device exists" cr
+ encode-string
+ 2swap property
+ true
+ then
+ else
+ \ ." device doesn't exist" cr
+ 2drop false
+ then
+ r> active-package!
+ ;
+
+:noname
+ " hd"
+ " /pci/pci-ata/ata-1/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-1/disk@1" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@1" ?devalias not if
+ 2drop ." No disk found." cr
+ then
+ then
+ then
+ then
+
+ " cdrom"
+ " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if
+ 2drop ." No cdrom found" cr
+ then
+ then
+ then
+ then
+; SYSTEM-initializer
+
+new-device
+ " ide" device-name
+ " ide" device-type
+ " WINBOND,82C553" model
+ h# 28 encode-int " max-latency" property
+ h# 2 encode-int " min-grant" property
+ h# 1 encode-int " devsel-speed" property
+ h# 0 encode-int " subsystem-vendor-id" property
+ h# 0 encode-int " subsystem-id" property
+ h# 1018A encode-int " class-code" property
+ h# 5 encode-int " revision-id" property
+ h# 105 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " assigned-addresses" property
+ h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+new-device
+ " ethernet" device-name
+ " network" device-type
+ " AMD,79C973" model
+ h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+" /pci/isa" find-device
+ 0 0 " assigned-addresses" property
+ 0 0 " ranges" property
+ 0 encode-int " slot-names" property
+ d# 8333333 encode-int " clock-frequency" property
+ 0 encode-int " eisa-slots" property
+ 2 encode-int " #interrupt-cells" property
+ " W83C553F" encode-string " compatible" property
+ " WINBOND,82C553" model
+ 0 encode-int " max-latency" property
+ 0 encode-int " min-grant" property
+ 1 encode-int " devsel-speed" property
+ 0 encode-int " subsystem-vendor-id" property
+ 0 encode-int " subsystem-id" property
+ h# 60100 encode-int " class-code" property
+ h# 10 encode-int " revision-id" property
+ h# 565 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+ " reg" property
+
+new-device
+ " rtc" device-name
+ " rtc" device-type
+ " DS17285S" model
+ " MC146818" encode-string
+ " DS17285S" encode-string encode+
+ " pnpPNP,b00" encode-string encode+ " compatible" property
+ 8 encode-int 0 encode-int encode+ " interrupts" property
+ h# 70 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " interrupt-controller" device-name
+ " interrupt-controller" device-type
+ " 8259" model
+ " " encode-string " interrupt-controller" property
+ 2 encode-int " #interrupt-cells" property
+ 1 encode-int
+ 2 encode-int encode+
+ 3 encode-int encode+
+ 6 encode-int encode+
+ " reserved-interrupts" property
+ " 8259" encode-string
+ " chrp,iic" encode-string encode+
+ " compatible" property
+ h# 20 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " serial" device-name
+ " serial" device-type
+ " no" encode-string " ctsrts" property
+ " no" encode-string " xon" property
+ " no" encode-string " parity" property
+ d# 115200 encode-int " bps" property
+ 1 encode-int " stop-bits" property
+ 8 encode-int " data-bits" property
+ h# 70800 encode-int " divisor" property
+ h# 708000 encode-int " clock-frequency" property
+ 4 encode-int 0 encode-int encode+ " interrupts" property
+ h# 3F8 encode-int 1 encode-int encode+
+ 8 encode-int encode+ " reg" property
+finish-device
+
+" /pci" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+ h# 3800 encode-int 0 encode-int encode+
+ 0 encode-int encode+ 1 encode-int encode+
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int encode+
+ then
+ h# 0C encode-int encode+ 1 encode-int encode+
+ " interrupt-map" property
+
+" /pci/isa" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/terminal-emulator
+new-device
+ " terminal-emulator" device-name
+ external
+ : open true ;
+ : close ;
+ \ : write ( addr len -- actual )
+ \ dup -rot type
+ \ ;
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/qemu/roms/openbios/arch/ppc/pearpc/vfd.c b/qemu/roms/openbios/arch/ppc/pearpc/vfd.c
new file mode 100644
index 000000000..06485f2dc
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/pearpc/vfd.c
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:29:43 greg>
+ * Time-stamp: <2004/08/28 17:29:43 greg>
+ *
+ * <vfd.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "pearpc/pearpc.h"
+
+static int vfd_is_open;
+
+static int
+vfd_init( void )
+{
+ vfd_is_open = 1;
+ return 0;
+}
+
+void
+vfd_close( void )
+{
+}
+
+int
+vfd_draw_str( const char *str )
+{
+ if (!vfd_is_open)
+ vfd_init();
+
+ return 0;
+}
diff --git a/qemu/roms/openbios/arch/ppc/ppc.fs b/qemu/roms/openbios/arch/ppc/ppc.fs
new file mode 100644
index 000000000..0414f22c4
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/ppc.fs
@@ -0,0 +1,68 @@
+include config.fs
+
+\ -------------------------------------------------------------------------
+\ registers
+\ -------------------------------------------------------------------------
+
+0 value %cr
+0 value %ctr
+0 value %lr
+0 value %msr
+0 value %srr0
+0 value %srr1
+0 value %pc \ should be an alias for %srr0
+
+0 value %r0
+0 value %r1
+0 value %r2
+0 value %r3
+0 value %r4
+0 value %r5
+0 value %r6
+0 value %r7
+0 value %r8
+0 value %r9
+0 value %r10
+0 value %r11
+0 value %r12
+0 value %r13
+0 value %r14
+0 value %r15
+0 value %r16
+0 value %r17
+0 value %r18
+0 value %r19
+0 value %r20
+0 value %r21
+0 value %r22
+0 value %r23
+0 value %r24
+0 value %r25
+0 value %r26
+0 value %r27
+0 value %r28
+0 value %r29
+0 value %r30
+0 value %r31
+
+0 value %xer
+0 value %sprg0
+0 value %sprg1
+0 value %sprg2
+0 value %sprg3
+
+\ -------------------------------------------------------------------------
+\ Load VGA FCode driver blob
+\ -------------------------------------------------------------------------
+
+[IFDEF] CONFIG_DRIVER_VGA
+ -1 value vga-driver-fcode
+ " QEMU,VGA.bin" $encode-file to vga-driver-fcode
+[THEN]
+
+\ -------------------------------------------------------------------------
+\ other
+\ -------------------------------------------------------------------------
+
+\ Set by BootX when booting Mac OS X
+defer spin
diff --git a/qemu/roms/openbios/arch/ppc/qemu/console.c b/qemu/roms/openbios/arch/ppc/qemu/console.c
new file mode 100644
index 000000000..53a321525
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/console.c
@@ -0,0 +1,88 @@
+/*
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/drivers.h"
+
+#ifdef CONFIG_DEBUG_CONSOLE
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+static int mac_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ escc_uart_putchar(c & 0xff);
+#endif
+ return c;
+}
+
+static int mac_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (escc_uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+ return 0;
+}
+
+static int mac_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (escc_uart_charav(CONFIG_SERIAL_PORT))
+ return (escc_uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+ return 0;
+}
+
+struct _console_ops mac_console_ops = {
+ .putchar = mac_putchar,
+ .availchar = mac_availchar,
+ .getchar = mac_getchar
+};
+
+static int prep_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ uart_putchar(c & 0xff);
+#endif
+ return c;
+}
+
+static int prep_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+ return 0;
+}
+
+static int prep_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return (uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+ return 0;
+}
+
+struct _console_ops prep_console_ops = {
+ .putchar = prep_putchar,
+ .availchar = prep_availchar,
+ .getchar = prep_getchar
+};
+
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/qemu/roms/openbios/arch/ppc/qemu/init.c b/qemu/roms/openbios/arch/ppc/qemu/init.c
new file mode 100644
index 000000000..4fe8b7220
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/init.c
@@ -0,0 +1,951 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <init.c>
+ *
+ * Initialization for qemu
+ *
+ * Copyright (C) 2004 Greg Watson
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * based on mol/init.c:
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ * (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/pci.h"
+#include "arch/common/nvram.h"
+#include "drivers/drivers.h"
+#include "qemu/qemu.h"
+#include "libopenbios/ofmem.h"
+#include "openbios-version.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+#include "arch/ppc/processor.h"
+
+#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+struct cpudef {
+ unsigned int iu_version;
+ const char *name;
+ int icache_size, dcache_size;
+ int icache_sets, dcache_sets;
+ int icache_block_size, dcache_block_size;
+ int tlb_sets, tlb_size;
+ void (*initfn)(const struct cpudef *cpu);
+};
+
+static uint16_t machine_id = 0;
+
+extern void unexpected_excep(int vector);
+
+void
+unexpected_excep(int vector)
+{
+ printk("openbios panic: Unexpected exception %x\n", vector);
+ for (;;) {
+ }
+}
+
+extern void __divide_error(void);
+
+void
+__divide_error(void)
+{
+ return;
+}
+
+enum {
+ ARCH_PREP = 0,
+ ARCH_MAC99,
+ ARCH_HEATHROW,
+ ARCH_MAC99_U3,
+};
+
+int is_apple(void)
+{
+ return is_oldworld() || is_newworld();
+}
+
+int is_oldworld(void)
+{
+ return machine_id == ARCH_HEATHROW;
+}
+
+int is_newworld(void)
+{
+ return (machine_id == ARCH_MAC99) ||
+ (machine_id == ARCH_MAC99_U3);
+}
+
+static const pci_arch_t known_arch[] = {
+ [ARCH_PREP] = {
+ .name = "PREP",
+ .vendor_id = PCI_VENDOR_ID_MOTOROLA,
+ .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
+ .cfg_addr = 0x80000cf8,
+ .cfg_data = 0x80000cfc,
+ .cfg_base = 0x80000000,
+ .cfg_len = 0x00100000,
+ .host_pci_base = 0xc0000000,
+ .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */
+ .mem_len = 0x10000000,
+ .io_base = 0x80000000,
+ .io_len = 0x00010000,
+ .rbase = 0x00000000,
+ .rlen = 0x00400000,
+ .irqs = { 9, 11, 9, 11 }
+ },
+ [ARCH_MAC99] = {
+ .name = "MAC99",
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
+ .cfg_addr = 0xf2800000,
+ .cfg_data = 0xf2c00000,
+ .cfg_base = 0xf2000000,
+ .cfg_len = 0x02000000,
+ .host_pci_base = 0x0,
+ .pci_mem_base = 0x80000000,
+ .mem_len = 0x10000000,
+ .io_base = 0xf2000000,
+ .io_len = 0x00800000,
+ .rbase = 0x00000000,
+ .rlen = 0x01000000,
+ .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
+ },
+ [ARCH_MAC99_U3] = {
+ .name = "MAC99_U3",
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
+ .cfg_addr = 0xf0800000,
+ .cfg_data = 0xf0c00000,
+ .cfg_base = 0xf0000000,
+ .cfg_len = 0x02000000,
+ .host_pci_base = 0x0,
+ .pci_mem_base = 0x80000000,
+ .mem_len = 0x10000000,
+ .io_base = 0xf2000000,
+ .io_len = 0x00800000,
+ .rbase = 0x00000000,
+ .rlen = 0x01000000,
+ .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
+ },
+ [ARCH_HEATHROW] = {
+ .name = "HEATHROW",
+ .vendor_id = PCI_VENDOR_ID_MOTOROLA,
+ .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
+ .cfg_addr = 0xfec00000,
+ .cfg_data = 0xfee00000,
+ .cfg_base = 0x80000000,
+ .cfg_len = 0x7f000000,
+ .host_pci_base = 0x0,
+ .pci_mem_base = 0x80000000,
+ .mem_len = 0x10000000,
+ .io_base = 0xfe000000,
+ .io_len = 0x00800000,
+ .rbase = 0xfd000000,
+ .rlen = 0x01000000,
+ .irqs = { 21, 22, 23, 24 }
+ },
+};
+unsigned long isa_io_base;
+
+extern struct _console_ops mac_console_ops, prep_console_ops;
+
+void
+entry(void)
+{
+ uint32_t temp = 0;
+ char buf[5];
+
+ arch = &known_arch[ARCH_HEATHROW];
+
+ fw_cfg_init();
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+ if (strncmp(buf, "QEMU", 4) == 0) {
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ if (temp == 1) {
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+ arch = &known_arch[machine_id];
+ }
+ }
+
+ isa_io_base = arch->io_base;
+
+#ifdef CONFIG_DEBUG_CONSOLE
+ if (is_apple()) {
+ init_console(mac_console_ops);
+ } else {
+ init_console(prep_console_ops);
+ }
+#endif
+
+ if (temp != 1) {
+ printk("Incompatible configuration device version, freezing\n");
+ for (;;) {
+ }
+ }
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for (;;) {
+ }
+}
+
+/* -- phys.lo ... phys.hi */
+static void
+push_physaddr(phys_addr_t value)
+{
+ PUSH(value);
+#ifdef CONFIG_PPC64
+ PUSH(value >> 32);
+#endif
+}
+
+/* From drivers/timer.c */
+extern unsigned long timer_freq;
+
+static void
+cpu_generic_init(const struct cpudef *cpu)
+{
+ push_str("/cpus");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str(cpu->name);
+ fword("device-name");
+
+ push_str("cpu");
+ fword("device-type");
+
+ PUSH(mfpvr());
+ fword("encode-int");
+ push_str("cpu-version");
+ fword("property");
+
+ PUSH(cpu->dcache_size);
+ fword("encode-int");
+ push_str("d-cache-size");
+ fword("property");
+
+ PUSH(cpu->icache_size);
+ fword("encode-int");
+ push_str("i-cache-size");
+ fword("property");
+
+ PUSH(cpu->dcache_sets);
+ fword("encode-int");
+ push_str("d-cache-sets");
+ fword("property");
+
+ PUSH(cpu->icache_sets);
+ fword("encode-int");
+ push_str("i-cache-sets");
+ fword("property");
+
+ PUSH(cpu->dcache_block_size);
+ fword("encode-int");
+ push_str("d-cache-block-size");
+ fword("property");
+
+ PUSH(cpu->icache_block_size);
+ fword("encode-int");
+ push_str("i-cache-block-size");
+ fword("property");
+
+ PUSH(cpu->tlb_sets);
+ fword("encode-int");
+ push_str("tlb-sets");
+ fword("property");
+
+ PUSH(cpu->tlb_size);
+ fword("encode-int");
+ push_str("tlb-size");
+ fword("property");
+
+ timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ);
+ PUSH(timer_freq);
+ fword("encode-int");
+ push_str("timebase-frequency");
+ fword("property");
+
+ PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ));
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+
+ PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
+ fword("encode-int");
+ push_str("bus-frequency");
+ fword("property");
+
+ push_str("running");
+ fword("encode-string");
+ push_str("state");
+ fword("property");
+}
+
+static void
+cpu_add_pir_property(void)
+{
+ unsigned long pir;
+
+ asm("mfspr %0, 1023\n"
+ : "=r"(pir) :);
+ PUSH(pir);
+ fword("encode-int");
+ push_str("reg");
+ fword("property");
+}
+
+static void
+cpu_604_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+ cpu_add_pir_property();
+
+ fword("finish-device");
+}
+
+static void
+cpu_750_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("reg");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static void
+cpu_g4_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+ cpu_add_pir_property();
+
+ fword("finish-device");
+}
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+/* In order to get 64 bit aware handlers that rescue all our
+ GPRs from getting truncated to 32 bits, we need to patch the
+ existing handlers so they jump to our 64 bit aware ones. */
+static void
+ppc64_patch_handlers(void)
+{
+ uint32_t *dsi = (uint32_t *)0x300UL;
+ uint32_t *isi = (uint32_t *)0x400UL;
+
+ // Patch the first DSI handler instruction to: ba 0x2000
+ *dsi = 0x48002002;
+
+ // Patch the first ISI handler instruction to: ba 0x2200
+ *isi = 0x48002202;
+
+ // Invalidate the cache lines
+ asm ("icbi 0, %0" : : "r"(dsi));
+ asm ("icbi 0, %0" : : "r"(isi));
+}
+#endif
+
+static void
+cpu_970_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("reg");
+ fword("property");
+
+ PUSH(0);
+ PUSH(0);
+ fword("encode-bytes");
+ push_str("64-bit");
+ fword("property");
+
+ fword("finish-device");
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+ /* The 970 is a PPC64 CPU, so we need to activate
+ * 64bit aware interrupt handlers */
+
+ ppc64_patch_handlers();
+#endif
+
+ /* The 970 also implements the HIOR which we need to set to 0 */
+
+ mtspr(S_HIOR, 0);
+}
+
+static const struct cpudef ppc_defs[] = {
+ {
+ .iu_version = 0x00040000,
+ .name = "PowerPC,604",
+ .icache_size = 0x4000,
+ .dcache_size = 0x4000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_604_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x00090000,
+ .name = "PowerPC,604e",
+ .icache_size = 0x4000,
+ .dcache_size = 0x4000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_604_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x000a0000,
+ .name = "PowerPC,604r",
+ .icache_size = 0x4000,
+ .dcache_size = 0x4000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_604_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x80040000,
+ .name = "PowerPC,MPC86xx",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ {
+ .iu_version = 0x000080000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x10080000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x70000000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x70020000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x800c0000,
+ .name = "PowerPC,74xx",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ {
+ .iu_version = 0x0000c0000,
+ .name = "PowerPC,G4",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_g4_init,
+ },
+ {
+ .iu_version = 0x00390000,
+ .name = "PowerPC,970",
+ .icache_size = 0x10000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x200,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x80,
+ .dcache_block_size = 0x80,
+ .tlb_sets = 0x100,
+ .tlb_size = 0x1000,
+ .initfn = cpu_970_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x003C0000,
+ .name = "PowerPC,970FX",
+ .icache_size = 0x10000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x80,
+ .dcache_block_size = 0x80,
+ .tlb_sets = 0x100,
+ .tlb_size = 0x1000,
+ .initfn = cpu_970_init,
+ },
+ {
+ .iu_version = 0x00350000,
+ .name = "PowerPC,POWER4",
+ .icache_size = 0x10000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x100,
+ .dcache_sets = 0x40,
+ .icache_block_size = 0x80,
+ .dcache_block_size = 0x80,
+ .tlb_sets = 0x100,
+ .tlb_size = 0x1000,
+ .initfn = cpu_970_init,
+ },
+};
+
+static const struct cpudef *
+id_cpu(void)
+{
+ unsigned int iu_version;
+ unsigned int i;
+
+ iu_version = mfpvr() & 0xffff0000;
+
+ for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) {
+ if (iu_version == ppc_defs[i].iu_version)
+ return &ppc_defs[i];
+ }
+ printk("Unknown cpu (pvr %x), freezing!\n", iu_version);
+ for (;;) {
+ }
+}
+
+static void go(void);
+
+static void
+go(void)
+{
+ ucell addr;
+
+ feval("saved-program-state >sps.entry @");
+ addr = POP();
+
+ call_elf(0, 0, addr);
+}
+
+static void kvm_of_init(void)
+{
+ char hypercall[4 * 4];
+ uint32_t *hc32;
+
+ /* Don't expose /hypervisor when not in KVM */
+ if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
+ return;
+
+ push_str("/");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str("hypervisor");
+ fword("device-name");
+
+ push_str("hypervisor");
+ fword("device-type");
+
+ /* compatible */
+
+ push_str("linux,kvm");
+ fword("encode-string");
+ push_str("epapr,hypervisor-0.2");
+ fword("encode-string");
+ fword("encode+");
+ push_str("compatible");
+ fword("property");
+
+ /* Tell the guest about the hypercall instructions */
+ fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
+ hc32 = (uint32_t*)hypercall;
+ PUSH(hc32[0]);
+ fword("encode-int");
+ PUSH(hc32[1]);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(hc32[2]);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(hc32[3]);
+ fword("encode-int");
+ fword("encode+");
+ push_str("hcall-instructions");
+ fword("property");
+
+ /* ePAPR requires us to provide a unique guest id */
+ PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
+ fword("encode-int");
+ push_str("guest-id");
+ fword("property");
+
+ /* ePAPR requires us to provide a guest name */
+ push_str("KVM guest");
+ fword("encode-string");
+ push_str("guest-name");
+ fword("property");
+
+ fword("finish-device");
+}
+
+/*
+ * filll ( addr bytes quad -- )
+ */
+
+static void ffilll(void)
+{
+ const u32 longval = POP();
+ u32 bytes = POP();
+ u32 *laddr = (u32 *)cell2pointer(POP());
+ u32 len;
+
+ for (len = 0; len < bytes / sizeof(u32); len++) {
+ *laddr++ = longval;
+ }
+}
+
+void
+arch_of_init(void)
+{
+#ifdef CONFIG_RTAS
+ phandle_t ph;
+#endif
+ uint64_t ram_size;
+ const struct cpudef *cpu;
+ char buf[64], qemu_uuid[16];
+ const char *stdin_path, *stdout_path, *boot_path;
+ uint32_t temp = 0;
+ char *boot_device;
+ ofmem_t *ofmem = ofmem_arch_get_private();
+
+ openbios_init();
+ modules_init();
+ setup_timers();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+#endif
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+ printk("Configuration device id %s", buf);
+
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ printk(" version %d machine id %d\n", temp, machine_id);
+
+ temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
+
+ printk("CPUs: %x\n", temp);
+
+ ram_size = ofmem->ramsize;
+
+ printk("Memory: %lldM\n", ram_size / 1024 / 1024);
+
+ fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
+
+ printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
+ qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
+ qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+ qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
+ qemu_uuid[15]);
+
+ /* set device tree root info */
+
+ push_str("/");
+ fword("find-device");
+
+ switch(machine_id) {
+ case ARCH_HEATHROW: /* OldWorld */
+
+ /* model */
+
+ push_str("Power Macintosh");
+ fword("model");
+
+ /* compatible */
+
+ push_str("AAPL,PowerMac G3");
+ fword("encode-string");
+ push_str("MacRISC");
+ fword("encode-string");
+ fword("encode+");
+ push_str("compatible");
+ fword("property");
+
+ /* misc */
+
+ push_str("device-tree");
+ fword("encode-string");
+ push_str("AAPL,original-name");
+ fword("property");
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("AAPL,cpu-id");
+ fword("property");
+
+ PUSH(66 * 1000 * 1000);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+ break;
+
+ case ARCH_MAC99:
+ case ARCH_MAC99_U3:
+ case ARCH_PREP:
+ default:
+
+ /* model */
+
+ push_str("PowerMac3,1");
+ fword("model");
+
+ /* compatible */
+
+ push_str("PowerMac3,1");
+ fword("encode-string");
+ push_str("MacRISC");
+ fword("encode-string");
+ fword("encode+");
+ push_str("MacRISC2");
+ fword("encode-string");
+ fword("encode+");
+ push_str("Power Macintosh");
+ fword("encode-string");
+ fword("encode+");
+ push_str("compatible");
+ fword("property");
+
+ /* misc */
+
+ push_str("bootrom");
+ fword("device-type");
+
+ PUSH(100 * 1000 * 1000);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+ break;
+ }
+
+ /* Perhaps we can store UUID here ? */
+
+ push_str("0000000000000");
+ fword("encode-string");
+ push_str("system-id");
+ fword("property");
+
+ /* memory info */
+
+ push_str("/memory");
+ fword("find-device");
+
+ /* all memory */
+
+ push_physaddr(0);
+ fword("encode-phys");
+ /* This needs adjusting if #size-cells gets increased.
+ Alternatively use multiple (address, size) tuples. */
+ PUSH(ram_size & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ cpu = id_cpu();
+ cpu->initfn(cpu);
+ printk("CPU type %s\n", cpu->name);
+
+ snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
+ ofmem_register(find_dev("/memory"), find_dev(buf));
+ node_methods_init(buf);
+
+#ifdef CONFIG_RTAS
+ /* OldWorld Macs don't have an /rtas node. */
+ switch (machine_id) {
+ case ARCH_MAC99:
+ case ARCH_MAC99_U3:
+ if (!(ph = find_dev("/rtas"))) {
+ printk("Warning: No /rtas node\n");
+ } else {
+ unsigned long size = 0x1000;
+ while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
+ size *= 2;
+ set_property(ph, "rtas-size", (char*)&size, sizeof(size));
+ set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
+ }
+ break;
+ }
+#endif
+
+ if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
+ if (is_apple()) {
+ if (CONFIG_SERIAL_PORT) {
+ stdin_path = "scca";
+ stdout_path = "scca";
+ } else {
+ stdin_path = "sccb";
+ stdout_path = "sccb";
+ }
+ } else {
+ stdin_path = "ttya";
+ stdout_path = "ttya";
+ }
+
+ /* Some bootloaders force the output to the screen device, so
+ let's create a screen alias for the serial device too */
+
+ push_str("/aliases");
+ fword("find-device");
+
+ push_str(stdout_path);
+ fword("pathres-resolve-aliases");
+ fword("encode-string");
+ push_str("screen");
+ fword("property");
+ } else {
+ if (is_apple()) {
+ stdin_path = "adb-keyboard";
+ stdout_path = "screen";
+ } else {
+ stdin_path = "keyboard";
+ stdout_path = "screen";
+ }
+ }
+
+ kvm_of_init();
+
+ /* Setup nvram variables */
+ push_str("/options");
+ fword("find-device");
+
+ /* Setup default boot devices (not overriding user settings) */
+ fword("boot-device");
+ boot_device = pop_fstr_copy();
+ if (boot_device && strcmp(boot_device, "disk") == 0) {
+ switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) {
+ case 'c':
+ boot_path = "hd";
+ break;
+ default:
+ case 'd':
+ boot_path = "cd";
+ break;
+ }
+
+ snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path);
+ push_str(buf);
+ fword("encode-string");
+ push_str("boot-device");
+ fword("property");
+ }
+ free(boot_device);
+
+ /* Set up other properties */
+
+ push_str("/chosen");
+ fword("find-device");
+
+ push_str(stdin_path);
+ fword("pathres-resolve-aliases");
+ push_str("input-device");
+ fword("$setenv");
+
+ push_str(stdout_path);
+ fword("pathres-resolve-aliases");
+ push_str("output-device");
+ fword("$setenv");
+
+#if 0
+ if(getbool("tty-interface?") == 1)
+#endif
+ fword("activate-tty-interface");
+
+ device_end();
+
+ /* Implementation of filll word (required by BootX) */
+ bind_func("filll", ffilll);
+
+ bind_func("platform-boot", boot);
+ bind_func("(go)", go);
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/kernel.c b/qemu/roms/openbios/arch/ppc/qemu/kernel.c
new file mode 100644
index 000000000..b26fba5f7
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/kernel.c
@@ -0,0 +1,115 @@
+/*
+ * Creation Date: <2003/10/25 14:07:17 samuel>
+ * Time-stamp: <2004/08/28 17:48:19 stepan>
+ *
+ * <kernel.c>
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * Based upon unix.c (from OpenBIOS):
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "dict.h"
+#include "libopenbios/bindings.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "libc/string.h"
+#include "kernel.h"
+
+#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */
+/* 512K for the dictionary */
+#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell))
+#ifdef __powerpc64__
+#define DICTIONARY_BASE 0xfff08000 /* this must match the value in ldscript! */
+#define DICTIONARY_SECTION __attribute__((section(".data.dict")))
+#else
+#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary))
+#define DICTIONARY_SECTION
+#endif
+
+static ucell forth_dictionary[DICTIONARY_SIZE] DICTIONARY_SECTION = {
+#include "qemu-dict.h"
+};
+
+static ucell *memory;
+
+/************************************************************************/
+/* F U N C T I O N S */
+/************************************************************************/
+
+int
+forth_segv_handler( char *segv_addr )
+{
+ ucell addr = 0xdeadbeef;
+
+ if( PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead )
+ addr = *(ucell *)cell2pointer(PC);
+
+ printk("panic: segmentation violation at 0x%p\n", segv_addr);
+ printk("dict=0x%p here=0x%p(dict+0x%x) pc=0x%x(dict+0x%x)\n",
+ dict, (char*)dict + dicthead, dicthead,
+ PC, PC - pointer2cell(dict));
+ printk("dstackcnt=%d rstackcnt=%d instruction=%x\n",
+ dstackcnt, rstackcnt, addr);
+
+#ifdef DEBUG_DSTACK
+ printdstack();
+#endif
+#ifdef DEBUG_RSTACK
+ printrstack();
+#endif
+ return -1;
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void
+init_memory( void )
+{
+ memory = malloc(MEMORY_SIZE);
+ if( !memory )
+ panic("panic: not enough memory on host system.\n");
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH( pointer2cell(memory) );
+ PUSH( pointer2cell(memory) + MEMORY_SIZE );
+}
+
+int
+initialize_forth( void )
+{
+ dict = (unsigned char *)forth_dictionary;
+ dicthead = (ucell)FORTH_DICTIONARY_END;
+ last = (ucell *)((unsigned char *)forth_dictionary +
+ FORTH_DICTIONARY_LAST);
+ dictlimit = sizeof(forth_dictionary);
+
+ forth_init();
+
+ PUSH_xt( bind_noname_func(arch_of_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+ if( PC ) {
+ init_memory();
+ enterforth((xt_t)PC);
+ free( memory );
+ }
+ free( dict );
+ return 0;
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/kernel.h b/qemu/roms/openbios/arch/ppc/qemu/kernel.h
new file mode 100644
index 000000000..fe9be83d9
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/kernel.h
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <kernel.h>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef __KERNEL_H__
+#define __KERNEL_H__
+
+/* misc.c */
+extern void fatal_error( const char *str );
+extern void exit( int status ) __attribute__ ((noreturn));
+
+/* start.S */
+extern void flush_icache_range( char *start, char *stop );
+extern char of_rtas_start[], of_rtas_end[];
+extern void call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry );
+
+/* methods.c */
+extern void node_methods_init( const char *cpuname );
+
+/* main.c */
+extern void boot( void );
+
+/* init.c */
+extern void entry( void );
+extern void arch_of_init( void );
+extern int get_bool_res( const char *str );
+
+/* tree.c */
+extern void devtree_init( void );
+
+
+#endif /* __KERNEL_H__ */
diff --git a/qemu/roms/openbios/arch/ppc/qemu/ldscript b/qemu/roms/openbios/arch/ppc/qemu/ldscript
new file mode 100644
index 000000000..8027b39db
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/ldscript
@@ -0,0 +1,68 @@
+OUTPUT_FORMAT(elf32-powerpc)
+OUTPUT_ARCH(powerpc:common)
+
+/* Initial load address
+ */
+BASE_ADDR = 0xfff00000;
+
+/* As NVRAM is at 0xfff04000, the .text needs to be after that
+ */
+TEXT_ADDR = 0xfff08000;
+
+/* Hard reset vector address
+ */
+HRESET_ADDR = 0xfffffffc;
+
+CSTACK_SIZE = 32768; /* client stack size */
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ _start = BASE_ADDR + 0x0100;
+ .text.vectors ALIGN(4096): {
+ *(.text.vectors)
+ }
+
+ . = TEXT_ADDR;
+ /* Normal sections */
+ .text ALIGN(4096): {
+ *(.text)
+ *(.text.*)
+ }
+
+ .rodata ALIGN(4096): {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ *(.note.ELFBoot)
+ }
+ .data ALIGN(4096): {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ _edata = .;
+ }
+
+ .bss ALIGN(4096): {
+ _bss = .;
+ *(.sbss)
+ *(.sbss.*)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ . = HRESET_ADDR;
+
+ .romentry : { *(.romentry) }
+
+ . = ALIGN(4096);
+ _end = .;
+
+ /* We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+
+ /DISCARD/ : { *(.comment*) *(.note.*) }
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/main.c b/qemu/roms/openbios/arch/ppc/qemu/main.c
new file mode 100644
index 000000000..44b16666b
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/main.c
@@ -0,0 +1,85 @@
+/*
+ * Creation Date: <2002/10/02 22:24:24 samuel>
+ * Time-stamp: <2004/03/27 01:57:55 samuel>
+ *
+ * <main.c>
+ *
+ *
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elf_load.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "kernel.h"
+#include "drivers/drivers.h"
+#include "libopenbios/ofmem.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+//#define DEBUG_QEMU
+
+#ifdef DEBUG_QEMU
+#define SUBSYS_DPRINTF(subsys, fmt, args...) \
+ do { printk("%s - %s: " fmt, subsys, __func__ , ##args); } while (0)
+#else
+#define SUBSYS_DPRINTF(subsys, fmt, args...) \
+ do { } while (0)
+#endif
+#define CHRP_DPRINTF(fmt, args...) SUBSYS_DPRINTF("CHRP", fmt, ##args)
+#define ELF_DPRINTF(fmt, args...) SUBSYS_DPRINTF("ELF", fmt, ##args)
+#define NEWWORLD_DPRINTF(fmt, args...) SUBSYS_DPRINTF("NEWWORLD", fmt, ##args)
+
+static void check_preloaded_kernel(void)
+{
+ unsigned long kernel_image, kernel_size;
+ unsigned long initrd_image, initrd_size;
+ const char * kernel_cmdline;
+
+ kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
+ if (kernel_size) {
+ kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
+ kernel_cmdline = (const char *)(uintptr_t) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
+ initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR);
+ initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE);
+ printk("[ppc] Kernel already loaded (0x%8.8lx + 0x%8.8lx) "
+ "(initrd 0x%8.8lx + 0x%8.8lx)\n",
+ kernel_image, kernel_size, initrd_image, initrd_size);
+ if (kernel_cmdline) {
+ phandle_t ph;
+ printk("[ppc] Kernel command line: %s\n", kernel_cmdline);
+ ph = find_dev("/chosen");
+ set_property(ph, "bootargs", strdup(kernel_cmdline), strlen(kernel_cmdline) + 1);
+ }
+ call_elf(initrd_image, initrd_size, kernel_image);
+ }
+}
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
+
+ fword("update-chosen");
+ if (boot_device == 'm') {
+ check_preloaded_kernel();
+ }
+
+ if (is_apple()) {
+ update_nvram();
+ }
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/methods.c b/qemu/roms/openbios/arch/ppc/qemu/methods.c
new file mode 100644
index 000000000..fd993daa9
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/methods.c
@@ -0,0 +1,327 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "drivers/drivers.h"
+#include "libc/string.h"
+#include "qemu/qemu.h"
+#include "libopenbios/ofmem.h"
+#include "arch/ppc/processor.h"
+#include "drivers/usb.h"
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+#ifdef CONFIG_RTAS
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ ucell physbase = POP();
+ ucell s=0x1000, size = (ucell)of_rtas_end - (ucell)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+#endif
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)cell2pointer(POP());
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)cell2pointer(POP());
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "+/openprom/client-services" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+ usb_exit();
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+}
+
+/* ( -- ms ) */
+#define TIMER_FREQUENCY 16600000ULL
+
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ unsigned long tbu, tbl, temp;
+ unsigned long long ticks, msecs;
+
+ asm volatile(
+ "1:\n"
+ "mftbu %2\n"
+ "mftb %0\n"
+ "mftbu %1\n"
+ "cmpw %2,%1\n"
+ "bne 1b\n"
+ : "=r"(tbl), "=r"(tbu), "=r"(temp)
+ :
+ : "cc");
+
+ ticks = (((unsigned long long)tbu) << 32) | (unsigned long long)tbl;
+ msecs = (1000 * ticks) / TIMER_FREQUENCY;
+ PUSH( msecs );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_UNNAMED_NODE( mmu, INSTALL_OPEN, 0 );
+DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ ucell mode = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell phys = POP();
+ ucell ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ ucell size = POP();
+ ucell virt = POP();
+ ofmem_release(virt, size);
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( const char *cpuname )
+{
+ phandle_t chosen, ph;
+#ifdef CONFIG_RTAS
+ if (is_newworld()) {
+ REGISTER_NODE( rtas );
+ }
+#endif
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE_METHODS( mmu, cpuname );
+ REGISTER_NODE( mmu_ciface );
+ REGISTER_NODE( tty );
+
+ chosen = find_dev("/chosen");
+ if (chosen) {
+ push_str(cpuname);
+ fword("open-dev");
+ ph = POP();
+ set_int_property(chosen, "mmu", ph);
+ }
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/mmutypes.h b/qemu/roms/openbios/arch/ppc/qemu/mmutypes.h
new file mode 100644
index 000000000..512c23d0e
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/mmutypes.h
@@ -0,0 +1,97 @@
+/*
+ * Creation Date: <2002/01/13 13:53:14 samuel>
+ * Time-stamp: <2002/01/27 19:56:11 samuel>
+ *
+ * <mmutypes.h>
+ *
+ * MMU definitions
+ *
+ * Most of these declarations originate from the Linux Kernel
+ *
+ * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_MMUTYPES
+#define _H_MMUTYPES
+
+/* Hardware Page Table Entry */
+typedef struct mPTE {
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+
+ unsigned long rpn:20; /* Real (physical) page number */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+} mPTE_t;
+
+typedef struct mPTE_64 {
+ uint32_t avpn_low; /* Abbreviated Virtual Page Number (unused) */
+ uint32_t avpn:25; /* Abbreviated Virtual Page Number */
+ uint32_t sw:4; /* Software Use */
+ uint32_t :1; /* Reserved */
+ uint32_t h:1; /* Hash algorithm indicator */
+ uint32_t v:1; /* Entry is valid */
+
+ uint32_t rpn_low; /* Real (physical) page number (unused) */
+ uint32_t rpn:20; /* Real (physical) page number */
+ uint32_t :2; /* Reserved */
+ uint32_t ac:1; /* Address Compare*/
+ uint32_t r:1; /* Referenced */
+ uint32_t c:1; /* Changed */
+ uint32_t w:1; /* Write-thru cache mode */
+ uint32_t i:1; /* Cache inhibited */
+ uint32_t m:1; /* Memory coherence */
+ uint32_t g:1; /* Guarded */
+ uint32_t n:1; /* No-Execute */
+ uint32_t pp:2; /* Page protection */
+} mPTE_64_t;
+
+typedef struct _mBATU { /* Upper part of BAT (all except 601) */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+} mBATU;
+
+typedef struct _mBATL { /* Lower part of BAT (all except 601) */
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+} mBATL;
+
+typedef struct _mBAT {
+ mBATU batu; /* Upper register */
+ mBATL batl; /* Lower register */
+} mBAT;
+
+typedef struct _mSEGREG {
+ unsigned long t:1; /* Normal or I/O type */
+ unsigned long ks:1; /* Supervisor 'key' (normally 0) */
+ unsigned long kp:1; /* User 'key' (normally 1) */
+ unsigned long n:1; /* No-execute */
+ unsigned long :4; /* Unused */
+ unsigned long vsid:24; /* Virtual Segment Identifier */
+} mSEGREG;
+
+
+#endif /* _H_MMUTYPES */
diff --git a/qemu/roms/openbios/arch/ppc/qemu/ofmem.c b/qemu/roms/openbios/arch/ppc/qemu/ofmem.c
new file mode 100644
index 000000000..6f346a3d4
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/ofmem.c
@@ -0,0 +1,563 @@
+/*
+ * Creation Date: <1999/11/07 19:02:11 samuel>
+ * Time-stamp: <2004/01/07 19:42:36 samuel>
+ *
+ * <ofmem.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "libopenbios/ofmem.h"
+#include "kernel.h"
+#include "mmutypes.h"
+#include "asm/processor.h"
+
+#define BIT(n) (1U << (31 - (n)))
+
+#define SLB_VSID_SHIFT 12
+
+/* called from assembly */
+extern void dsi_exception(void);
+extern void isi_exception(void);
+extern void setup_mmu(unsigned long code_base);
+
+/*
+ * From Apple's BootX source comments:
+ *
+ * 96 MB map (currently unused - 4363357 tracks re-adoption)
+ * 00000000 - 00003FFF : Exception Vectors
+ * 00004000 - 03FFFFFF : Kernel Image, Boot Struct and Drivers (~64 MB)
+ * 04000000 - 04FFFFFF : File Load Area (16 MB) [80 MB]
+ * 05000000 - 053FFFFF : FS Cache (4 MB) [84 MB]
+ * 05400000 - 055FFFFF : Malloc Zone (2 MB) [86 MB]
+ * 05600000 - 057FFFFF : BootX Image (2 MB) [88 MB]
+ * 05800000 - 05FFFFFF : Unused/OF (8 MB) [96 MB]
+ *
+ */
+
+#define FREE_BASE 0x00004000UL
+#define OF_CODE_START 0xfff00000UL
+#define OF_CODE_SIZE 0x00100000
+#define IO_BASE 0x80000000UL
+
+#ifdef __powerpc64__
+#define HASH_BITS 18
+#else
+#define HASH_BITS 15
+#endif
+#define HASH_SIZE (2 << HASH_BITS)
+#define OFMEM_SIZE (1 * 1024 * 1024 + 512 * 1024)
+
+#define SEGR_USER BIT(2)
+#define SEGR_BASE 0x0400
+
+static inline unsigned long
+get_hash_base(void)
+{
+ return (mfsdr1() & SDR1_HTABORG_MASK);
+}
+
+static inline unsigned long
+get_rom_base(void)
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ return ofmem->ramsize - OF_CODE_SIZE;
+}
+
+static unsigned long
+get_ram_top(void)
+{
+ return get_hash_base() - (32 + 64 + 64) * 1024 - OFMEM_SIZE;
+}
+
+static unsigned long
+get_ram_bottom(void)
+{
+ return FREE_BASE;
+}
+
+static unsigned long get_heap_top(void)
+{
+ return get_hash_base() - (32 + 64 + 64) * 1024;
+}
+
+static inline size_t ALIGN_SIZE(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a - 1);
+}
+
+ofmem_t* ofmem_arch_get_private(void)
+{
+ return (ofmem_t*)cell2pointer(get_heap_top() - OFMEM_SIZE);
+}
+
+void* ofmem_arch_get_malloc_base(void)
+{
+ return (char*)ofmem_arch_get_private() + ALIGN_SIZE(sizeof(ofmem_t), 4);
+}
+
+ucell ofmem_arch_get_heap_top(void)
+{
+ return get_heap_top();
+}
+
+ucell ofmem_arch_get_virt_top(void)
+{
+ return IO_BASE;
+}
+
+void ofmem_arch_unmap_pages(ucell virt, ucell size)
+{
+ /* kill page mappings in provided range */
+}
+
+void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
+{
+ /* none yet */
+}
+
+ucell ofmem_arch_get_iomem_base(void)
+{
+ /* Currently unused */
+ return 0;
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+ /* Currently unused */
+ return 0;
+}
+
+retain_t *ofmem_arch_get_retained(void)
+{
+ /* not implemented */
+ return NULL;
+}
+
+int ofmem_arch_get_physaddr_cellsize(void)
+{
+#ifdef CONFIG_PPC64
+ return 2;
+#else
+ return 1;
+#endif
+}
+
+int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
+{
+ int n = 0;
+#ifdef CONFIG_PPC64
+ p[n++] = value >> 32;
+#endif
+ p[n++] = value;
+ return n;
+}
+
+/* Return size of a single MMU package translation property entry in cells */
+int ofmem_arch_get_translation_entry_size(void)
+{
+ return 3 + ofmem_arch_get_physaddr_cellsize();
+}
+
+/* Generate translation property entry for PPC.
+ * According to the platform bindings for PPC
+ * (http://www.openfirmware.org/1275/bindings/ppc/release/ppc-2_1.html#REF34579)
+ * a translation property entry has the following layout:
+ *
+ * virtual address
+ * length
+ * physical address
+ * mode
+ */
+void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
+{
+ int i = 0;
+
+ transentry[i++] = t->virt;
+ transentry[i++] = t->size;
+ i += ofmem_arch_encode_physaddr(&transentry[i], t->phys);
+ transentry[i++] = t->mode;
+}
+
+/* Return the size of a memory available entry given the phandle in cells */
+int ofmem_arch_get_available_entry_size(phandle_t ph)
+{
+ if (ph == s_phandle_memory) {
+ return 1 + ofmem_arch_get_physaddr_cellsize();
+ } else {
+ return 1 + 1;
+ }
+}
+
+/* Generate memory available property entry for PPC */
+void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
+{
+ int i = 0;
+
+ if (ph == s_phandle_memory) {
+ i += ofmem_arch_encode_physaddr(availentry, start);
+ } else {
+ availentry[i++] = start;
+ }
+
+ availentry[i] = size;
+}
+
+/************************************************************************/
+/* OF private allocations */
+/************************************************************************/
+
+/* Private functions for mapping between physical/virtual addresses */
+phys_addr_t
+va2pa(unsigned long va)
+{
+ if (va >= OF_CODE_START && va < OF_CODE_START + OF_CODE_SIZE) {
+ return (phys_addr_t)get_rom_base() - OF_CODE_START + va;
+ } else {
+ return (phys_addr_t)va;
+ }
+}
+
+unsigned long
+pa2va(phys_addr_t pa)
+{
+ if ((pa - get_rom_base() + OF_CODE_START >= OF_CODE_START) &&
+ (pa - get_rom_base() + OF_CODE_START < OF_CODE_START + OF_CODE_SIZE))
+ return (unsigned long)pa - get_rom_base() + OF_CODE_START;
+ else
+ return (unsigned long)pa;
+}
+
+void *
+malloc(int size)
+{
+ return ofmem_malloc(size);
+}
+
+void
+free(void *ptr)
+{
+ ofmem_free(ptr);
+}
+
+void *
+realloc(void *ptr, size_t size)
+{
+ return ofmem_realloc(ptr, size);
+}
+
+
+/************************************************************************/
+/* misc */
+/************************************************************************/
+
+ucell ofmem_arch_default_translation_mode(phys_addr_t phys)
+{
+ /* XXX: Guard bit not set as it should! */
+ if (phys < IO_BASE)
+ return 0x02; /*0xa*/ /* wim GxPp */
+ return 0x6a; /* WIm GxPp, I/O */
+}
+
+ucell ofmem_arch_io_translation_mode(phys_addr_t phys)
+{
+ return 0x6a; /* WIm GxPp, I/O */
+}
+
+/************************************************************************/
+/* page fault handler */
+/************************************************************************/
+
+static phys_addr_t
+ea_to_phys(unsigned long ea, ucell *mode)
+{
+ phys_addr_t phys;
+
+ if (ea >= OF_CODE_START && ea <= 0xffffffffUL) {
+ /* ROM into RAM */
+ ea -= OF_CODE_START;
+ phys = get_rom_base() + ea;
+ *mode = 0x02;
+ return phys;
+ }
+
+ phys = ofmem_translate(ea, mode);
+ if (phys == -1) {
+ phys = ea;
+ *mode = ofmem_arch_default_translation_mode(phys);
+
+ /* print_virt_range(); */
+ /* print_phys_range(); */
+ /* print_trans(); */
+ }
+ return phys;
+}
+
+/* Converts a global variable (from .data or .bss) into a pointer that
+ can be accessed from real mode */
+static void *
+global_ptr_real(void *p)
+{
+ return (void*)((uintptr_t)p - OF_CODE_START + get_rom_base());
+}
+
+/* Return the next slot to evict, in the range of [0..7] */
+static int
+next_evicted_slot(void)
+{
+ static int next_grab_slot;
+ int *next_grab_slot_va;
+ int r;
+
+ next_grab_slot_va = global_ptr_real(&next_grab_slot);
+ r = *next_grab_slot_va;
+ *next_grab_slot_va = (r + 1) % 8;
+
+ return r;
+}
+
+static void
+hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode)
+{
+ uint64_t vsid_mask, page_mask, pgidx, hash;
+ uint64_t htab_mask, mask, avpn;
+ unsigned long pgaddr;
+ int i, found;
+ unsigned int vsid, vsid_sh, sdr, sdr_sh, sdr_mask;
+ mPTE_64_t *pp;
+
+ vsid = (ea >> 28) + SEGR_BASE;
+ vsid_sh = 7;
+ vsid_mask = 0x00003FFFFFFFFF80ULL;
+ sdr = mfsdr1();
+ sdr_sh = 18;
+ sdr_mask = 0x3FF80;
+ page_mask = 0x0FFFFFFF; // XXX correct?
+ pgidx = (ea & page_mask) >> PAGE_SHIFT;
+ avpn = (vsid << 12) | ((pgidx >> 4) & 0x0F80);;
+
+ hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+ htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
+ mask = (htab_mask << sdr_sh) | sdr_mask;
+ pgaddr = sdr | (hash & mask);
+ pp = (mPTE_64_t *)pgaddr;
+
+ /* replace old translation */
+ for (found = 0, i = 0; !found && i < 8; i++)
+ if (pp[i].avpn == avpn)
+ found = 1;
+
+ /* otherwise use a free slot */
+ for (i = 0; !found && i < 8; i++)
+ if (!pp[i].v)
+ found = 1;
+
+ /* out of slots, just evict one */
+ if (!found)
+ i = next_evicted_slot() + 1;
+ i--;
+ {
+ mPTE_64_t p = {
+ // .avpn_low = avpn,
+ .avpn = avpn >> 7,
+ .h = 0,
+ .v = 1,
+
+ .rpn = (phys & ~0xfffUL) >> 12,
+ .r = mode & (1 << 8) ? 1 : 0,
+ .c = mode & (1 << 7) ? 1 : 0,
+ .w = mode & (1 << 6) ? 1 : 0,
+ .i = mode & (1 << 5) ? 1 : 0,
+ .m = mode & (1 << 4) ? 1 : 0,
+ .g = mode & (1 << 3) ? 1 : 0,
+ .n = mode & (1 << 2) ? 1 : 0,
+ .pp = mode & 3,
+ };
+ pp[i] = p;
+ }
+
+ asm volatile("tlbie %0" :: "r"(ea));
+}
+
+static void
+hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode)
+{
+#ifndef __powerpc64__
+ unsigned long *upte, cmp, hash1;
+ int i, vsid, found;
+ mPTE_t *pp;
+
+ vsid = (ea >> 28) + SEGR_BASE;
+ cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22);
+
+ hash1 = vsid;
+ hash1 ^= (ea >> 12) & 0xffff;
+ hash1 &= (((mfsdr1() & 0x1ff) << 16) | 0xffff) >> 6;
+
+ pp = (mPTE_t*)(get_hash_base() + (hash1 << 6));
+ upte = (unsigned long*)pp;
+
+ /* replace old translation */
+ for (found = 0, i = 0; !found && i < 8; i++)
+ if (cmp == upte[i*2])
+ found = 1;
+
+ /* otherwise use a free slot */
+ for (i = 0; !found && i < 8; i++)
+ if (!pp[i].v)
+ found = 1;
+
+ /* out of slots, just evict one */
+ if (!found)
+ i = next_evicted_slot() + 1;
+ i--;
+ upte[i * 2] = cmp;
+ upte[i * 2 + 1] = (phys & ~0xfff) | mode;
+
+ asm volatile("tlbie %0" :: "r"(ea));
+#endif
+}
+
+static int is_ppc64(void)
+{
+#ifdef __powerpc64__
+ return 1;
+#elif defined(CONFIG_PPC_64BITSUPPORT)
+ unsigned int pvr = mfpvr();
+ return ((pvr >= 0x330000) && (pvr < 0x70330000));
+#else
+ return 0;
+#endif
+}
+
+/* XXX Remove these ugly constructs when legacy 64-bit support is dropped. */
+static void hash_page(unsigned long ea, phys_addr_t phys, ucell mode)
+{
+ if (is_ppc64())
+ hash_page_64(ea, phys, mode);
+ else
+ hash_page_32(ea, phys, mode);
+}
+
+void
+dsi_exception(void)
+{
+ unsigned long dar, dsisr;
+ ucell mode;
+ phys_addr_t phys;
+
+ asm volatile("mfdar %0" : "=r" (dar) : );
+ asm volatile("mfdsisr %0" : "=r" (dsisr) : );
+
+ phys = ea_to_phys(dar, &mode);
+ hash_page(dar, phys, mode);
+}
+
+void
+isi_exception(void)
+{
+ unsigned long nip, srr1;
+ ucell mode;
+ phys_addr_t phys;
+
+ asm volatile("mfsrr0 %0" : "=r" (nip) : );
+ asm volatile("mfsrr1 %0" : "=r" (srr1) : );
+
+ phys = ea_to_phys(nip, &mode);
+ hash_page(nip, phys, mode);
+}
+
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+void
+setup_mmu(unsigned long ramsize)
+{
+ ofmem_t *ofmem;
+#ifndef __powerpc64__
+ unsigned long sr_base;
+#endif
+ unsigned long hash_base;
+ unsigned long hash_mask = ~0x000fffffUL; /* alignment for ppc64 */
+ int i;
+
+ /* SDR1: Storage Description Register 1 */
+
+ hash_base = (ramsize - OF_CODE_SIZE - HASH_SIZE) & hash_mask;
+ memset((void *)hash_base, 0, HASH_SIZE);
+ if (is_ppc64())
+ mtsdr1(hash_base | MAX(HASH_BITS - 18, 0));
+ else
+ mtsdr1(hash_base | ((HASH_SIZE - 1) >> 16));
+
+#ifdef __powerpc64__
+
+ /* Segment Lookaside Buffer */
+
+ slbia(); /* Invalidate all SLBs except SLB 0 */
+ for (i = 0; i < 16; i++) {
+ unsigned long rs = (0x400 + i) << SLB_VSID_SHIFT;
+ unsigned long rb = ((unsigned long)i << 28) | (1 << 27) | i;
+ slbmte(rs, rb);
+ }
+
+#else
+
+ /* Segment Register */
+
+ sr_base = SEGR_USER | SEGR_BASE ;
+ for (i = 0; i < 16; i++) {
+ int j = i << 28;
+ asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j));
+ }
+
+#endif
+
+ ofmem = ofmem_arch_get_private();
+ memset(ofmem, 0, sizeof(ofmem_t));
+ ofmem->ramsize = ramsize;
+
+ memcpy((void *)get_rom_base(), (void *)OF_CODE_START, OF_CODE_SIZE);
+
+ /* Enable MMU */
+
+ mtmsr(mfmsr() | MSR_IR | MSR_DR);
+}
+
+void
+ofmem_init(void)
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+
+ /* Map the memory (don't map page 0 to allow catching of NULL dereferences) */
+ ofmem_claim_phys(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
+ ofmem_claim_virt(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
+ ofmem_map(PAGE_SIZE, PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
+
+ /* Mark the first page as non-free */
+ ofmem_claim_phys(0, PAGE_SIZE, 0);
+ ofmem_claim_virt(0, PAGE_SIZE, 0);
+
+ /* Map everything at the top of physical RAM 1:1, minus the OpenBIOS ROM in RAM copy */
+ ofmem_claim_phys(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0);
+ ofmem_claim_virt(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0);
+ ofmem_map(get_ram_top(), get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0);
+
+ /* Map the OpenBIOS ROM in RAM copy */
+ ofmem_claim_phys(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_SIZE, 0);
+ ofmem_claim_virt(OF_CODE_START, OF_CODE_SIZE, 0);
+ ofmem_map(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_START, OF_CODE_SIZE, 0);
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.c b/qemu/roms/openbios/arch/ppc/qemu/qemu.c
new file mode 100644
index 000000000..381affb77
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.c
@@ -0,0 +1,106 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <qemu.c>
+ *
+ * Copyright (C) 2004, Greg Watson
+ *
+ * derived from mol.c
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libopenbios/bindings.h"
+#include "drivers/drivers.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "libc/byteorder.h"
+#include "qemu/qemu.h"
+#include <stdarg.h>
+
+//#define DUMP_NVRAM
+
+unsigned long virt_offset = 0;
+
+void
+exit( int status __attribute__ ((unused)))
+{
+ for (;;);
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ exit(0);
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ exit(0);
+}
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ putchar( '>' );
+ putchar( '>' );
+ putchar( ' ' );
+ }
+ putchar( *p );
+ }
+ return i;
+}
+
+int arch_nvram_size(void)
+{
+ if (is_apple()) {
+ return macio_get_nvram_size();
+ } else {
+ // not implemented
+ }
+ return 0;
+}
+
+void arch_nvram_put(char *buf)
+{
+ if (is_apple()) {
+ macio_nvram_put(buf);
+ } else {
+ // not implemented
+ }
+}
+
+void arch_nvram_get(char *buf)
+{
+ if (is_apple()) {
+ macio_nvram_get(buf);
+ } else {
+ // not implemented
+ }
+}
diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.fs b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs
new file mode 100644
index 000000000..458af1bc7
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs
@@ -0,0 +1,95 @@
+\ qemu specific initialization code
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " rtc" " rtc" preopen
+ " memory" " /memory" preopen
+; SYSTEM-initializer
+
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ then
+;
+
+variable keyboard-phandle 0 keyboard-phandle !
+
+: (find-keyboard-device) ( phandle -- )
+ recursive
+ keyboard-phandle @ 0= if \ Return first match
+ >dn.child @
+ begin ?dup while
+ dup dup " device_type" rot get-package-property 0= if
+ drop dup cstrlen
+ " keyboard" strcmp 0= if
+ dup to keyboard-phandle
+ then
+ then
+ (find-keyboard-device)
+ >dn.peer @
+ repeat
+ else
+ drop
+ then
+;
+
+\ create the keyboard devalias
+:noname
+ device-tree @ (find-keyboard-device)
+ keyboard-phandle @ if
+ active-package
+ " /aliases" find-device
+ keyboard-phandle @ get-package-path
+ encode-string " keyboard" property
+ active-package!
+ then
+; SYSTEM-initializer
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ device-end
+;
+
+:noname
+ set-defaults
+; PREPOST-initializer
diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.h b/qemu/roms/openbios/arch/ppc/qemu/qemu.h
new file mode 100644
index 000000000..6edf4d451
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <qemu.h>
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_QEMU
+#define _H_QEMU
+
+/* vfd.c */
+extern int vfd_draw_str( const char *str );
+extern void vfd_close( void );
+
+#include "kernel.h"
+
+#endif /* _H_QEMU */
diff --git a/qemu/roms/openbios/arch/ppc/qemu/start.S b/qemu/roms/openbios/arch/ppc/qemu/start.S
new file mode 100644
index 000000000..ae2fd53dc
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/start.S
@@ -0,0 +1,729 @@
+/*
+ * Creation Date: <2001/06/16 21:30:18 samuel>
+ * Time-stamp: <2003/04/04 16:32:06 samuel>
+ *
+ * <init.S>
+ *
+ * Asm glue for ELF images
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "autoconf.h"
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+/************************************************************************/
+/* Macros */
+/************************************************************************/
+
+#define ILLEGAL_VECTOR( v ) .org __vectors + v ; vector__##v: bl trap_error ;
+#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+
+/* We're trying to use the same code for the ppc32 and ppc64 handlers here.
+ * On ppc32 we only save/restore the registers, C considers volatile.
+ *
+ * On ppc64 on the other hand, we have to save/restore all registers, because
+ * all OF code is 32 bits, which only saves/restores the low 32 bits of the
+ * registers it clobbers.
+ */
+
+#define EXCEPTION_PREAMBLE_TEMPLATE \
+ mtsprg1 r1 ; /* scratch */ \
+ mfcr r1 ; \
+ mtsprg2 r1 ; /* scratch */ \
+ lis r1, 0x8000 ; /* r1=0x80000000 */ \
+ add. r1,r1,r1 ; /* r1=r1+r1 (high 32bit !0) */ \
+ beq 1f; \
+ \
+ mfmsr r1 ; /* unset MSR_SF */ \
+ clrldi r1,r1,1 ; \
+ mtmsrd r1 ; \
+1: \
+ mfsprg0 r1 ; /* exception stack in sprg0 */ \
+.ifc ULONG_SIZE, 8 ; \
+ addi r1,r1,-(40 * ULONG_SIZE) ; /* push exception frame */ \
+.else ; \
+ addi r1,r1,-(20 * ULONG_SIZE) ; /* push exception frame */ \
+.endif ; \
+ \
+ stl r0,(0 * ULONG_SIZE)(r1) ; /* save r0 */ \
+ mfsprg1 r0 ; \
+ stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \
+ stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \
+ stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \
+ stl r4,(4 * ULONG_SIZE)(r1) ; \
+ stl r5,(5 * ULONG_SIZE)(r1) ; \
+ stl r6,(6 * ULONG_SIZE)(r1) ; \
+ stl r7,(7 * ULONG_SIZE)(r1) ; \
+ stl r8,(8 * ULONG_SIZE)(r1) ; \
+ stl r9,(9 * ULONG_SIZE)(r1) ; \
+ stl r10,(10 * ULONG_SIZE)(r1) ; \
+ stl r11,(11 * ULONG_SIZE)(r1) ; \
+ stl r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+ stl r13,(17 * ULONG_SIZE)(r1) ; \
+ stl r14,(18 * ULONG_SIZE)(r1) ; \
+ stl r15,(19 * ULONG_SIZE)(r1) ; \
+ stl r16,(20 * ULONG_SIZE)(r1) ; \
+ stl r17,(21 * ULONG_SIZE)(r1) ; \
+ stl r18,(22 * ULONG_SIZE)(r1) ; \
+ stl r19,(23 * ULONG_SIZE)(r1) ; \
+ stl r20,(24 * ULONG_SIZE)(r1) ; \
+ stl r21,(25 * ULONG_SIZE)(r1) ; \
+ stl r22,(26 * ULONG_SIZE)(r1) ; \
+ stl r23,(27 * ULONG_SIZE)(r1) ; \
+ stl r24,(28 * ULONG_SIZE)(r1) ; \
+ stl r25,(29 * ULONG_SIZE)(r1) ; \
+ stl r26,(30 * ULONG_SIZE)(r1) ; \
+ stl r27,(31 * ULONG_SIZE)(r1) ; \
+ stl r28,(32 * ULONG_SIZE)(r1) ; \
+ stl r29,(33 * ULONG_SIZE)(r1) ; \
+ stl r30,(34 * ULONG_SIZE)(r1) ; \
+ stl r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+ \
+ mflr r0 ; \
+ stl r0,(13 * ULONG_SIZE)(r1) ; \
+ mfsprg2 r0 ; \
+ stl r0,(14 * ULONG_SIZE)(r1) ; \
+ mfctr r0 ; \
+ stl r0,(15 * ULONG_SIZE)(r1) ; \
+ mfxer r0 ; \
+ stl r0,(16 * ULONG_SIZE)(r1) ; \
+ \
+ /* 76(r1) unused */ \
+ addi r1,r1,-16 ; /* C ABI uses 0(r1) and 4(r1)... */
+
+#define EXCEPTION_EPILOGUE_TEMPLATE \
+ addi r1,r1,16 ; /* pop ABI frame */ \
+\
+ ll r0,(13 * ULONG_SIZE)(r1) ; \
+ mtlr r0 ; \
+ ll r0,(14 * ULONG_SIZE)(r1) ; \
+ mtcr r0 ; \
+ ll r0,(15 * ULONG_SIZE)(r1) ; \
+ mtctr r0 ; \
+ ll r0,(16 * ULONG_SIZE)(r1) ; \
+ mtxer r0 ; \
+\
+ ll r0,(0 * ULONG_SIZE)(r1) ; \
+ ll r2,(2 * ULONG_SIZE)(r1) ; \
+ ll r3,(3 * ULONG_SIZE)(r1) ; \
+ ll r4,(4 * ULONG_SIZE)(r1) ; \
+ ll r5,(5 * ULONG_SIZE)(r1) ; \
+ ll r6,(6 * ULONG_SIZE)(r1) ; \
+ ll r7,(7 * ULONG_SIZE)(r1) ; \
+ ll r8,(8 * ULONG_SIZE)(r1) ; \
+ ll r9,(9 * ULONG_SIZE)(r1) ; \
+ ll r10,(10 * ULONG_SIZE)(r1) ; \
+ ll r11,(11 * ULONG_SIZE)(r1) ; \
+ ll r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+ ll r13,(17 * ULONG_SIZE)(r1) ; \
+ ll r14,(18 * ULONG_SIZE)(r1) ; \
+ ll r15,(19 * ULONG_SIZE)(r1) ; \
+ ll r16,(20 * ULONG_SIZE)(r1) ; \
+ ll r17,(21 * ULONG_SIZE)(r1) ; \
+ ll r18,(22 * ULONG_SIZE)(r1) ; \
+ ll r19,(23 * ULONG_SIZE)(r1) ; \
+ ll r20,(24 * ULONG_SIZE)(r1) ; \
+ ll r21,(25 * ULONG_SIZE)(r1) ; \
+ ll r22,(26 * ULONG_SIZE)(r1) ; \
+ ll r23,(27 * ULONG_SIZE)(r1) ; \
+ ll r24,(28 * ULONG_SIZE)(r1) ; \
+ ll r25,(29 * ULONG_SIZE)(r1) ; \
+ ll r26,(30 * ULONG_SIZE)(r1) ; \
+ ll r27,(31 * ULONG_SIZE)(r1) ; \
+ ll r28,(32 * ULONG_SIZE)(r1) ; \
+ ll r29,(33 * ULONG_SIZE)(r1) ; \
+ ll r30,(34 * ULONG_SIZE)(r1) ; \
+ ll r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+ ll r1,(1 * ULONG_SIZE)(r1) ; /* restore stack at last */ \
+ rfi
+
+// PPC32
+
+#define ULONG_SIZE 4
+#define stl stw
+#define ll lwz
+
+.macro EXCEPTION_PREAMBLE
+ EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE
+ EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+// PPC64
+
+#define ULONG_SIZE 8
+#define stl std
+#define ll ld
+
+.macro EXCEPTION_PREAMBLE_64
+ EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE_64
+ EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+#define ULONG_SIZE 4
+#define STACKFRAME_MINSIZE 16
+
+#else /* !CONFIG_PPC_64BITSUPPORT */
+
+#ifdef __powerpc64__
+
+#define ULONG_SIZE 8
+#define STACKFRAME_MINSIZE 48
+#define stl std
+#define ll ld
+
+#else
+
+#define ULONG_SIZE 4
+#define STACKFRAME_MINSIZE 16
+#define stl stw
+#define ll lwz
+
+#endif
+
+.macro EXCEPTION_PREAMBLE
+ mtsprg1 r1 /* scratch */
+ mfsprg0 r1 /* exception stack in sprg0 */
+ addi r1, r1, -(20 * ULONG_SIZE) /* push exception frame */
+
+ stl r0, ( 0 * ULONG_SIZE)(r1) /* save r0 */
+ mfsprg1 r0
+ stl r0, ( 1 * ULONG_SIZE)(r1) /* save r1 */
+ stl r2, ( 2 * ULONG_SIZE)(r1) /* save r2 */
+ stl r3, ( 3 * ULONG_SIZE)(r1) /* save r3 */
+ stl r4, ( 4 * ULONG_SIZE)(r1)
+ stl r5, ( 5 * ULONG_SIZE)(r1)
+ stl r6, ( 6 * ULONG_SIZE)(r1)
+ stl r7, ( 7 * ULONG_SIZE)(r1)
+ stl r8, ( 8 * ULONG_SIZE)(r1)
+ stl r9, ( 9 * ULONG_SIZE)(r1)
+ stl r10, (10 * ULONG_SIZE)(r1)
+ stl r11, (11 * ULONG_SIZE)(r1)
+ stl r12, (12 * ULONG_SIZE)(r1)
+
+ mflr r0
+ stl r0, (13 * ULONG_SIZE)(r1)
+ mfcr r0
+ stl r0, (14 * ULONG_SIZE)(r1)
+ mfctr r0
+ stl r0, (15 * ULONG_SIZE)(r1)
+ mfxer r0
+ stl r0, (16 * ULONG_SIZE)(r1)
+
+ addi r1, r1, -STACKFRAME_MINSIZE /* C ABI saves LR and SP */
+.endm
+
+.macro EXCEPTION_EPILOGUE
+ addi r1, r1, STACKFRAME_MINSIZE /* pop ABI frame */
+
+ ll r0, (13 * ULONG_SIZE)(r1)
+ mtlr r0
+ ll r0, (14 * ULONG_SIZE)(r1)
+ mtcr r0
+ ll r0, (15 * ULONG_SIZE)(r1)
+ mtctr r0
+ ll r0, (16 * ULONG_SIZE)(r1)
+ mtxer r0
+
+ ll r0, ( 0 * ULONG_SIZE)(r1)
+ ll r2, ( 2 * ULONG_SIZE)(r1)
+ ll r3, ( 3 * ULONG_SIZE)(r1)
+ ll r4, ( 4 * ULONG_SIZE)(r1)
+ ll r5, ( 5 * ULONG_SIZE)(r1)
+ ll r6, ( 6 * ULONG_SIZE)(r1)
+ ll r7, ( 7 * ULONG_SIZE)(r1)
+ ll r8, ( 8 * ULONG_SIZE)(r1)
+ ll r9, ( 9 * ULONG_SIZE)(r1)
+ ll r10, (10 * ULONG_SIZE)(r1)
+ ll r11, (11 * ULONG_SIZE)(r1)
+ ll r12, (12 * ULONG_SIZE)(r1)
+
+ ll r1, ( 1 * ULONG_SIZE)(r1) /* restore stack at last */
+ RFI
+.endm
+
+#endif /* !CONFIG_PPC_64BITSUPPORT */
+
+/************************************************************************/
+/* vectors */
+/************************************************************************/
+
+ .section .text.vectors, "ax"
+GLOBL(__vectors):
+ nop // NULL-jmp trap
+1: nop //
+ b 1b
+
+VECTOR( 0x100, "SRE" ):
+ b _entry
+
+trap_error:
+ lis r1, 0x8000 /* r1=0x80000000 */
+ add. r1,r1,r1 /* r1=r1+r1 (high 32bit !0) */
+ beq 1f
+
+ mfmsr r1 /* unset MSR_SF */
+ clrldi r1,r1,1
+ mtmsrd r1
+1:
+ mflr r3
+ LOAD_REG_FUNC(r4, unexpected_excep)
+ mtctr r4
+ bctr
+
+ILLEGAL_VECTOR( 0x200 )
+
+VECTOR( 0x300, "DSI" ):
+ b real_dsi
+
+ILLEGAL_VECTOR( 0x380 )
+
+VECTOR( 0x400, "ISI" ):
+ b real_isi
+
+ILLEGAL_VECTOR( 0x480 )
+
+ ILLEGAL_VECTOR( 0x500 )
+ ILLEGAL_VECTOR( 0x600 )
+ ILLEGAL_VECTOR( 0x700 )
+
+VECTOR( 0x800, "FPU" ):
+ mtsprg1 r3
+ mfsrr1 r3
+ ori r3,r3,0x2000
+ mtsrr1 r3
+ mfsprg1 r3
+ RFI
+
+ILLEGAL_VECTOR( 0x900 )
+ILLEGAL_VECTOR( 0xa00 )
+ILLEGAL_VECTOR( 0xb00 )
+ILLEGAL_VECTOR( 0xc00 )
+ILLEGAL_VECTOR( 0xd00 )
+ILLEGAL_VECTOR( 0xe00 )
+ILLEGAL_VECTOR( 0xf00 )
+ILLEGAL_VECTOR( 0xf20 )
+ILLEGAL_VECTOR( 0x1000 )
+ILLEGAL_VECTOR( 0x1100 )
+ILLEGAL_VECTOR( 0x1200 )
+ILLEGAL_VECTOR( 0x1300 )
+ILLEGAL_VECTOR( 0x1400 )
+ILLEGAL_VECTOR( 0x1500 )
+ILLEGAL_VECTOR( 0x1600 )
+ILLEGAL_VECTOR( 0x1700 )
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+
+VECTOR( 0x2000, "DSI_64" ):
+ EXCEPTION_PREAMBLE_64
+ LOAD_REG_IMMEDIATE(r3, dsi_exception)
+ mtctr r3
+ bctrl
+ EXCEPTION_EPILOGUE_64
+
+VECTOR( 0x2200, "ISI_64" ):
+ EXCEPTION_PREAMBLE_64
+ LOAD_REG_IMMEDIATE(r3, isi_exception)
+ mtctr r3
+ bctrl
+ EXCEPTION_EPILOGUE_64
+
+#endif
+
+real_dsi:
+ EXCEPTION_PREAMBLE
+ LOAD_REG_FUNC(r3, dsi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+real_isi:
+ EXCEPTION_PREAMBLE
+ LOAD_REG_FUNC(r3, isi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+exception_return:
+ EXCEPTION_EPILOGUE
+
+GLOBL(__vectors_end):
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+GLOBL(_entry):
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+ li r0,0
+
+ lis r3, 0x8000 /* r1=0x80000000 */
+ add. r3,r3,r3 /* r1=r1+r1 (high 32bit !0) */
+ beq no_64bit /* only true when !MSR_SF */
+
+ /* clear MSR, disable MMU, SF */
+ mtmsrd r0
+ b real_entry
+
+no_64bit:
+ /* clear MSR, disable MMU */
+ mtmsr r0
+
+real_entry:
+#endif
+
+ /* copy exception vectors */
+
+ LOAD_REG_IMMEDIATE(r3, __vectors)
+ li r4,0
+ li r5,__vectors_end - __vectors + 16
+ rlwinm r5,r5,0,0,28
+1: lwz r6,0(r3)
+ lwz r7,4(r3)
+ lwz r8,8(r3)
+ lwz r9,12(r3)
+ stw r6,0(r4)
+ stw r7,4(r4)
+ stw r8,8(r4)
+ stw r9,12(r4)
+ dcbst 0,r4
+ sync
+ icbi 0,r4
+ sync
+ addi r5,r5,-16
+ addi r3,r3,16
+ addi r4,r4,16
+ cmpwi r5,0
+ bgt 1b
+ isync
+
+ bl compute_ramsize
+
+ /* Memory map:
+ *
+ * Top +-------------------------+
+ * | |
+ * | ROM into RAM (1 MB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | MMU Hash Table (64 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Exception Stack (32 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Stack (64 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Client Stack (64 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Malloc Zone (2 MiB) |
+ * | |
+ * +-------------------------+
+ * : :
+ * Bottom
+ */
+
+ addis r1, r3, -16 /* ramsize - 1MB */
+
+ /* setup hash table */
+
+ addis r1, r1, -1 /* - 64 kB */
+ clrrwi r1, r1, 5*4 /* & ~0xfffff */
+
+ /* setup exception stack */
+
+ mtsprg0 r1
+
+ /* setup stack */
+
+ addi r1, r1, -32768 /* - 32 kB */
+
+ /* save memory size in stack */
+
+#ifdef __powerpc64__
+ /* set up TOC pointer */
+
+ LOAD_REG_IMMEDIATE(r2, setup_mmu)
+ ld r2, 8(r2)
+#endif
+
+ bl BRANCH_LABEL(setup_mmu)
+ bl BRANCH_LABEL(entry)
+1: nop
+ b 1b
+
+
+ /* According to IEEE 1275, PPC bindings:
+ *
+ * MSR = FP, ME + (DR|IR)
+ * r1 = stack (32 K + 32 bytes link area above)
+ * r5 = client interface handler
+ * r6 = address of client program arguments (unused)
+ * r7 = length of client program arguments (unused)
+ *
+ * Yaboot and Linux use r3 and r4 for initrd address and size
+ */
+ .data
+saved_stack:
+ DATA_LONG(0)
+ .previous
+ /* void call_elf( arg1, arg2, entry ) */
+_GLOBAL(call_elf):
+ mflr r0
+ PPC_STLU r1, -STACKFRAME_MINSIZE(r1)
+ PPC_STL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
+ mtlr r5
+ LOAD_REG_IMMEDIATE(r8, saved_stack) // save our stack pointer
+ PPC_STL r1,0(r8)
+ mfsdr1 r1
+ addi r1, r1, -32768 /* - 32 KiB exception stack */
+ addis r1, r1, -1 /* - 64 KiB stack */
+ LOAD_REG_IMMEDIATE(r5, of_client_callback) // r5 = callback
+ li r6,0 // r6 = address of client program arguments (unused)
+ li r7,0 // r7 = length of client program arguments (unused)
+ li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
+ MTMSRD(r0)
+ blrl
+
+#ifdef CONFIG_PPC64
+ /* Restore SF bit */
+ LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR)
+ MTMSRD(r0)
+#endif
+ LOAD_REG_IMMEDIATE(r8, saved_stack) // restore stack pointer
+ mr r1,r8
+ PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
+ mtlr r0
+ addi r1, r1, STACKFRAME_MINSIZE
+ // XXX: should restore r12-r31 etc..
+ // we should not really come here though
+ blr
+
+#ifdef __powerpc64__
+#define STKOFF STACKFRAME_MINSIZE
+#define SAVE_SPACE 320
+#else
+#define STKOFF 8
+#define SAVE_SPACE 144
+#endif
+GLOBL(of_client_callback):
+
+#ifdef CONFIG_PPC64
+ PPC_STLU r1, -(STACKFRAME_MINSIZE + 16)(r1)
+#else
+ PPC_STLU r1, -STACKFRAME_MINSIZE(r1) /* fits within alignment */
+#endif
+
+ /* save r4 */
+
+ PPC_STL r4, STKOFF(r1)
+
+ /* save lr */
+
+ mflr r4
+ PPC_STL r4, PPC_LR_STKOFF(r1)
+
+ /* restore OF stack */
+
+ LOAD_REG_IMMEDIATE(r4, saved_stack)
+ PPC_LL r4, 0(r4)
+
+ PPC_STLU r4,-SAVE_SPACE(r4)
+ PPC_STL r1,(STKOFF)(r4) // save caller stack
+ mr r1,r4
+
+ PPC_STL r2, (STKOFF + 1 * ULONG_SIZE)(r1)
+ PPC_STL r0, (STKOFF + 2 * ULONG_SIZE)(r1)
+
+ /* save ctr, cr and xer */
+
+ mfctr r2
+ PPC_STL r2, (STKOFF + 3 * ULONG_SIZE)(r1)
+ mfcr r2
+ PPC_STL r2, (STKOFF + 4 * ULONG_SIZE)(r1)
+ mfxer r2
+ PPC_STL r2, (STKOFF + 5 * ULONG_SIZE)(r1)
+
+ /* save r5 - r31 */
+
+ PPC_STL r5, (STKOFF + 6 * ULONG_SIZE)(r1)
+ PPC_STL r6, (STKOFF + 7 * ULONG_SIZE)(r1)
+ PPC_STL r7, (STKOFF + 8 * ULONG_SIZE)(r1)
+ PPC_STL r8, (STKOFF + 9 * ULONG_SIZE)(r1)
+ PPC_STL r9, (STKOFF + 10 * ULONG_SIZE)(r1)
+ PPC_STL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
+ PPC_STL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
+ PPC_STL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
+ PPC_STL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
+ PPC_STL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
+ PPC_STL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
+ PPC_STL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
+ PPC_STL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
+ PPC_STL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
+ PPC_STL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
+ PPC_STL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
+ PPC_STL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
+ PPC_STL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
+ PPC_STL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
+ PPC_STL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
+ PPC_STL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
+ PPC_STL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
+ PPC_STL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
+ PPC_STL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
+ PPC_STL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
+ PPC_STL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
+ PPC_STL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
+
+#ifdef CONFIG_PPC64
+ LOAD_REG_IMMEDIATE(r2, of_client_interface)
+ ld r2, 8(r2)
+#endif
+ bl BRANCH_LABEL(of_client_interface)
+
+ /* restore r5 - r31 */
+
+ PPC_LL r5, (STKOFF + 6 * ULONG_SIZE)(r1)
+ PPC_LL r6, (STKOFF + 7 * ULONG_SIZE)(r1)
+ PPC_LL r7, (STKOFF + 8 * ULONG_SIZE)(r1)
+ PPC_LL r8, (STKOFF + 9 * ULONG_SIZE)(r1)
+ PPC_LL r9, (STKOFF + 10 * ULONG_SIZE)(r1)
+ PPC_LL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
+ PPC_LL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
+ PPC_LL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
+ PPC_LL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
+ PPC_LL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
+ PPC_LL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
+ PPC_LL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
+ PPC_LL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
+ PPC_LL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
+ PPC_LL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
+ PPC_LL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
+ PPC_LL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
+ PPC_LL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
+ PPC_LL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
+ PPC_LL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
+ PPC_LL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
+ PPC_LL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
+ PPC_LL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
+ PPC_LL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
+ PPC_LL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
+ PPC_LL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
+ PPC_LL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
+
+ /* restore ctr, cr and xer */
+
+ PPC_LL r2, (STKOFF + 3 * ULONG_SIZE)(r1)
+ mtctr r2
+ PPC_LL r2, (STKOFF + 4 * ULONG_SIZE)(r1)
+ mtcr r2
+ PPC_LL r2, (STKOFF + 5 * ULONG_SIZE)(r1)
+ mtxer r2
+
+ /* restore r0 and r2 */
+
+ PPC_LL r2, (STKOFF + 1 * ULONG_SIZE)(r1)
+ PPC_LL r0, (STKOFF + 2 * ULONG_SIZE)(r1)
+
+ /* restore caller stack */
+
+ PPC_LL r1, (STKOFF)(r1)
+
+ PPC_LL r4, PPC_LR_STKOFF(r1)
+ mtlr r4
+ PPC_LL r4, STKOFF(r1)
+ PPC_LL r1, 0(r1)
+
+ blr
+
+ /* rtas glue (must be reloctable) */
+GLOBL(of_rtas_start):
+ /* r3 = argument buffer, r4 = of_rtas_start */
+ /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
+ blr
+GLOBL(of_rtas_end):
+
+
+#define CACHE_LINE_SIZE 32
+#define LG_CACHE_LINE_SIZE 5
+
+/* flush_icache_range( unsigned long start, unsigned long stop) */
+_GLOBAL(flush_icache_range):
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
+
+ /* Get RAM size from QEMU configuration device */
+
+#define CFG_ADDR 0xf0000510
+#define FW_CFG_RAM_SIZE 0x03
+
+compute_ramsize:
+ LOAD_REG_IMMEDIATE(r9, CFG_ADDR)
+ li r0,FW_CFG_RAM_SIZE
+ sth r0,0(r9)
+ LOAD_REG_IMMEDIATE(r9, CFG_ADDR + 2)
+ lbz r1,0(r9)
+ lbz r0,0(r9)
+ slwi r0,r0,8
+ or r1,r1,r0
+ lbz r0,0(r9)
+ slwi r0,r0,16
+ or r1,r1,r0
+ lbz r0,0(r9)
+ slwi r0,r0,24
+ or r3,r1,r0
+ blr
+
+ /* Hard reset vector */
+ .section .romentry,"ax"
+ bl _entry
diff --git a/qemu/roms/openbios/arch/ppc/qemu/tree.fs b/qemu/roms/openbios/arch/ppc/qemu/tree.fs
new file mode 100644
index 000000000..1ed838397
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/tree.fs
@@ -0,0 +1,71 @@
+\ QEMU specific initialization code
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+include config.fs
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+\ Apple calls the root node device-tree
+" device-tree" device-name
+[IFDEF] CONFIG_PPC64 2 [ELSE] 1 [THEN] encode-int " #address-cells" property
+1 encode-int " #size-cells" property
+h# 05f5e100 encode-int " clock-frequency" property
+
+new-device
+ " cpus" device-name
+ 1 encode-int " #address-cells" property
+ 0 encode-int " #size-cells" property
+ external
+
+ : encode-unit ( unit -- str len )
+ pocket tohexstr
+ ;
+
+ : decode-unit ( str len -- unit )
+ parse-hex
+ ;
+
+finish-device
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ external
+ : open true ;
+ : close ;
+finish-device
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/terminal-emulator
+new-device
+ " terminal-emulator" device-name
+ external
+ : open true ;
+ : close ;
+ \ : write ( addr len -- actual )
+ \ dup -rot type
+ \ ;
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/qemu/roms/openbios/arch/ppc/qemu/vfd.c b/qemu/roms/openbios/arch/ppc/qemu/vfd.c
new file mode 100644
index 000000000..308d0e338
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/qemu/vfd.c
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:29:43 greg>
+ * Time-stamp: <2004/08/28 17:29:43 greg>
+ *
+ * <vfd.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "qemu/qemu.h"
+
+static int vfd_is_open;
+
+static int
+vfd_init( void )
+{
+ vfd_is_open = 1;
+ return 0;
+}
+
+void
+vfd_close( void )
+{
+}
+
+int
+vfd_draw_str( const char *str )
+{
+ if (!vfd_is_open)
+ vfd_init();
+
+ return 0;
+}
diff --git a/qemu/roms/openbios/arch/ppc/start.S b/qemu/roms/openbios/arch/ppc/start.S
new file mode 100644
index 000000000..40ee08963
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/start.S
@@ -0,0 +1,335 @@
+/*
+ * Creation Date: <2001/06/16 21:30:18 samuel>
+ * Time-stamp: <2003/04/04 16:32:06 samuel>
+ *
+ * <init.S>
+ *
+ * Asm glue for ELF images run inside MOL
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+#include "osi.h"
+
+/************************************************************************/
+/* Macros */
+/************************************************************************/
+
+#define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ;
+#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
+
+#define EXCEPTION_PREAMBLE \
+ mtsprg1 r1 ; /* scratch */ \
+ mfsprg0 r1 ; /* exception stack in sprg0 */ \
+ addi r1,r1,-80 ; /* push exception frame */ \
+ \
+ stw r0,0(r1) ; /* save r0 */ \
+ mfsprg1 r0 ; \
+ stw r0,4(r1) ; /* save r1 */ \
+ stw r2,8(r1) ; /* save r2 */ \
+ stw r3,12(r1) ; /* save r3 */ \
+ stw r4,16(r1) ; \
+ stw r5,20(r1) ; \
+ stw r6,24(r1) ; \
+ stw r7,28(r1) ; \
+ stw r8,32(r1) ; \
+ stw r9,36(r1) ; \
+ stw r10,40(r1) ; \
+ stw r11,44(r1) ; \
+ stw r12,48(r1) ; \
+ \
+ mflr r0 ; \
+ stw r0,52(r1) ; \
+ mfcr r0 ; \
+ stw r0,56(r1) ; \
+ mfctr r0 ; \
+ stw r0,60(r1) ; \
+ mfxer r0 ; \
+ stw r0,64(r1) ; \
+ \
+ /* 76(r1) unused */ \
+ addi r1,r1,-16 ; /* call conventions uses 0(r1) and 4(r1)... */
+
+
+/************************************************************************/
+/* stack space */
+/************************************************************************/
+
+ .section .bss
+ .balign 32
+ .space 32*1024 // 32 K client stack
+client_stack:
+ .space 128
+
+ .space 64*1024 // 64 K stack
+stack: .space 64
+
+ .space 32*1024 // 32 K exception stack
+estack: .space 128
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+ .text
+GLOBL(_start):
+ li r0,0
+ mtmsr r0
+
+ lis r1,HA(estack)
+ addi r1,r1,LO(estack)
+ mtsprg0 r1 // setup exception stack
+ lis r1,HA(stack)
+ addi r1,r1,LO(stack)
+
+ // copy exception vectors
+ lis r3,HA(__vectors)
+ addi r3,r3,LO(__vectors)
+ li r4,0
+ li r5,__vectors_end - __vectors + 16
+ rlwinm r5,r5,0,0,28
+1: lwz r6,0(r3)
+ lwz r7,4(r3)
+ lwz r8,8(r3)
+ lwz r9,12(r3)
+ stw r6,0(r4)
+ stw r7,4(r4)
+ stw r8,8(r4)
+ stw r9,12(r4)
+ dcbst 0,r4
+ sync
+ icbi 0,r4
+ sync
+ addi r5,r5,-16
+ addi r3,r3,16
+ addi r4,r4,16
+ cmpwi r5,0
+ bgt 1b
+ isync
+
+ bl setup_mmu
+ bl entry
+1: nop
+ b 1b
+
+
+ /* According to IEEE 1275, PPC bindings:
+ *
+ * MSR = FP, ME + (DR|IR)
+ * r1 = stack (32 K + 32 bytes link area above)
+ * r5 = clint interface handler
+ * r6 = address of client program arguments (unused)
+ * r7 = length of client program arguments (unsed)
+ */
+saved_stack:
+ .long 0
+ /* void call_elf( entry ) */
+GLOBL(call_elf):
+ mflr r0
+ stwu r1,-16(r1)
+ stw r0,20(r1)
+ mtlr r3
+ lis r8,HA(saved_stack)
+ addi r8,r8,LO(saved_stack) // save our stack pointer
+ stw r1,0(r8)
+ lis r1,HA(client_stack)
+ addi r1,r1,LO(client_stack)
+ lis r5,HA(of_client_callback)
+ addi r5,r5,LO(of_client_callback) // r5 = callback
+ li r6,0 // r6 = address of client program arguments (unused)
+ li r7,0 // r7 = length of client program arguments (unused)
+ li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
+ mtmsr r0
+ blrl
+
+ lis r8,HA(saved_stack)
+ addi r8,r8,LO(saved_stack) // restore stack pointer
+ mr r1,r8
+ lwz r0,20(r1)
+ mtlr r0
+ addi r1,r1,16
+ // XXX: should restore r12-r31 etc..
+ // we should not really come here though
+ blr
+
+GLOBL(of_client_callback):
+ lis r4,HA(saved_stack)
+ addi r4,r4,LO(saved_stack)
+ lwz r4,0(r4)
+ stwu r4,-32(r4)
+ mflr r5
+ stw r5,32+4(r4)
+ stw r1,8(r4) // save caller stack
+ mr r1,r4
+ stw r2,12(r1)
+ stw r0,16(r1)
+ mfctr r2
+ stw r2,20(r1)
+ mfcr r2
+ stw r2,24(r1)
+ mfxer r2
+ stw r2,28(r1)
+ // do we need to save more registers?
+ bl of_client_interface
+ lwz r4,32+4(r1)
+ mtlr r4
+ lwz r2,20(r1)
+ mtctr r2
+ lwz r2,24(r1)
+ mtcr r2
+ lwz r2,28(r1)
+ mtxer r2
+ lwz r2,12(r1)
+ lwz r0,16(r1)
+ lwz r1,8(r1) // restore caller stack
+ blr
+
+ /* rtas glue (must be reloctable) */
+GLOBL(of_rtas_start):
+ /* r3 = argument buffer, r4 = of_rtas_start */
+ /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
+ mr r6,r3
+ lis r3,HA(OSI_SC_MAGIC_R3)
+ addi r3,r3,LO(OSI_SC_MAGIC_R3)
+ lis r4,HA(OSI_SC_MAGIC_R4)
+ addi r4,r4,LO(OSI_SC_MAGIC_R4)
+ li r5,OSI_OF_RTAS
+ sc
+ blr
+GLOBL(of_rtas_end):
+
+
+ /* used in a hack to the newworld calibration */
+GLOBL(nw_dec_calibration):
+ .long 0
+GLOBL(timer_calib_start):
+ lis r3,HA(nw_dec_calibration)
+ addi r3,r3,LO(nw_dec_calibration)
+ lwz r3,0(r3)
+ blr
+GLOBL(timer_calib_end):
+
+
+/************************************************************************/
+/* vectors */
+/************************************************************************/
+
+GLOBL(__vectors):
+ nop // NULL-jmp trap
+1: nop //
+ b 1b
+
+exception_return:
+ addi r1,r1,16 // pop ABI frame
+
+ lwz r0,52(r1)
+ mtlr r0
+ lwz r0,56(r1)
+ mtcr r0
+ lwz r0,60(r1)
+ mtctr r0
+ lwz r0,64(r1)
+ mtxer r0
+
+ lwz r0,0(r1) // restore r0
+ lwz r2,8(r1) // restore r2
+ lwz r3,12(r1) // restore r3
+ lwz r4,16(r1)
+ lwz r5,20(r1)
+ lwz r6,24(r1)
+ lwz r7,28(r1)
+ lwz r8,32(r1)
+ lwz r9,36(r1)
+ lwz r10,40(r1)
+ lwz r11,44(r1)
+ lwz r12,48(r1)
+ lwz r1,4(r1) // restore r1
+ rfi
+
+trap_error:
+ mflr r3
+ b unexpected_excep
+
+ILLEGAL_VECTOR( 0x100 )
+ILLEGAL_VECTOR( 0x200 )
+
+VECTOR( 0x300, "DSI" ):
+ EXCEPTION_PREAMBLE
+ lis r3,HA(dsi_exception)
+ addi r3,r3,LO(dsi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+VECTOR( 0x400, "ISI" ):
+ EXCEPTION_PREAMBLE
+ lis r3,HA(isi_exception)
+ addi r3,r3,LO(isi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+ ILLEGAL_VECTOR( 0x500 )
+ ILLEGAL_VECTOR( 0x600 )
+ ILLEGAL_VECTOR( 0x700 )
+
+VECTOR( 0x800, "FPU" ):
+ mtsprg1 r3
+ mfsrr1 r3
+ ori r3,r3,0x2000
+ mtsrr1 r3
+ mfsprg1 r3
+ rfi
+
+ILLEGAL_VECTOR( 0x900 )
+ILLEGAL_VECTOR( 0xa00 )
+ILLEGAL_VECTOR( 0xb00 )
+ILLEGAL_VECTOR( 0xc00 )
+ILLEGAL_VECTOR( 0xd00 )
+ILLEGAL_VECTOR( 0xe00 )
+ILLEGAL_VECTOR( 0xf00 )
+ILLEGAL_VECTOR( 0xf20 )
+ILLEGAL_VECTOR( 0x1000 )
+ILLEGAL_VECTOR( 0x1100 )
+ILLEGAL_VECTOR( 0x1200 )
+ILLEGAL_VECTOR( 0x1300 )
+ILLEGAL_VECTOR( 0x1400 )
+ILLEGAL_VECTOR( 0x1500 )
+ILLEGAL_VECTOR( 0x1600 )
+ILLEGAL_VECTOR( 0x1700 )
+
+GLOBL(__vectors_end):
+
+
+#define CACHE_LINE_SIZE 32
+#define LG_CACHE_LINE_SIZE 5
+
+/* flush_icache_range( unsigned long start, unsigned long stop) */
+GLOBL(flush_icache_range):
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
diff --git a/qemu/roms/openbios/arch/ppc/timebase.S b/qemu/roms/openbios/arch/ppc/timebase.S
new file mode 100644
index 000000000..19faed49d
--- /dev/null
+++ b/qemu/roms/openbios/arch/ppc/timebase.S
@@ -0,0 +1,33 @@
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+/*
+ * unsigned long long _get_ticks(void);
+ */
+_GLOBAL(_get_ticks):
+1: mftbu r3
+ mftb r4
+ mftbu r5
+ cmpw 0,r3,r5
+ bne 1b
+ blr
+
+/*
+ * Delay for a number of ticks
+ */
+_GLOBAL(_wait_ticks):
+ mflr r8 /* save link register */
+ mr r7, r3 /* save tick count */
+ bl BRANCH_LABEL(_get_ticks) /* Get start time */
+
+ /* Calculate end time */
+ addc r7, r4, r7 /* Compute end time lower */
+ addze r6, r3 /* and end time upper */
+
+1: bl BRANCH_LABEL(_get_ticks) /* Get current time */
+ subfc r4, r4, r7 /* Subtract current time from end time */
+ subfe. r3, r3, r6
+ bge 1b /* Loop until time expired */
+
+ mtlr r8 /* restore link register */
+ blr