diff options
Diffstat (limited to 'qemu/roms/openbios/arch/ppc')
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 |