[OpenBIOS] [PATCH] qemu better support

Laurent Vivier laurent at lvivier.info
Sat Dec 20 21:17:18 CET 2008


This patches copies all needed ppc files to qemu and modifies them.

The generated OpenBIOS image must be loaded at adresse 0xfff00000 by   
Qemu.

It is able to load Yaboot from disk and Yaboot is able to load Linux,  
but Linux hangs somewhere... of course it needs more work (but this  
cleans up my patch queue).

Thank you to Blue Swirl and Aurélien Jarno for their help.

Signed-off-by: Laurent Vivier <Laurent at lvivier.info>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: qemu-specif
Type: application/octet-stream
Size: 49861 bytes
Desc: not available
URL: <http://lists.openbios.org/pipermail/openbios/attachments/20081220/a9c2c8fa/attachment-0001.dmg>
-------------- next part --------------


---
  arch/ppc/build.xml                   |    7
  arch/ppc/qemu/init.c                 |   75 ++-
  arch/ppc/qemu/kernel.c               |   95 ++++
  arch/ppc/qemu/kernel.h               |   41 ++
  arch/ppc/qemu/ldscript               |   55 ++
  arch/ppc/qemu/main.c                 |   58 +-
  arch/ppc/qemu/methods.c              |   38 -
  arch/ppc/qemu/mmutypes.h             |   76 +++
  arch/ppc/qemu/ofmem.c                |  708 +++++++++++++++++++++++++ 
++++++++++
  arch/ppc/qemu/qemu.fs                |    1
  arch/ppc/qemu/start.S                |  393 +++++++++++++++++++
  arch/ppc/qemu/tree.fs                |    5
  config/examples/cross-ppc_config.xml |   18
  drivers/timer.c                      |    2
  include/ofmem.h                      |    2
  15 files changed, 1470 insertions(+), 104 deletions(-)

Index: openbios-devel/arch/ppc/qemu/main.c
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/main.c	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/main.c	2008-12-20 20:52:21.000000000  
+0100
@@ -1,12 +1,11 @@
  /*
- *   Creation Date: <2004/08/28 18:38:22 greg>
- *   Time-stamp: <2004/08/28 18:38:22 greg>
+ *   Creation Date: <2002/10/02 22:24:24 samuel>
+ *   Time-stamp: <2004/03/27 01:57:55 samuel>
   *
   *	<main.c>
   *
- *   Copyright (C) 2004 Greg Watson
   *
- *   Based on MOL specific code which is
+ *
   *   Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel at ibrium.se)
   *
   *   This program is free software; you can redistribute it and/or
@@ -22,16 +21,23 @@
  #include "openbios/nvram.h"
  #include "libc/diskio.h"
  #include "libc/vsprintf.h"
-#include "qemu/qemu.h"
  #include "ofmem.h"

+//#define DEBUG_ELF
+
+#ifdef DEBUG_ELF
+#define ELF_DPRINTF(fmt, args...) \
+do { printk("ELF - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define ELF_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
  static void
-transfer_control_to_elf( ulong elf_entry )
+transfer_control_to_elf( ulong entry )
  {
  	extern void call_elf( ulong entry );
-	printk("Starting ELF image at 0x%08lX\n", elf_entry);
-	call_elf( 0x400000 );
-	//call_elf( entry );
+	ELF_DPRINTF("Starting ELF boot loader\n");
+	call_elf( entry );

  	fatal_error("call_elf returned unexpectedly\n");
  }
@@ -45,11 +51,12 @@
  	Elf_phdr *phdr;
  	size_t s;

-	printk("Loading '%s'\n", get_file_path(fd));
+	ELF_DPRINTF("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 );
+		ELF_DPRINTF("----> %s is not an ELF image\n", buf );
  		exit(1);
  	}
  	if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
@@ -65,12 +72,12 @@
  		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",
+		ELF_DPRINTF("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 ); */
+		   phdr[i].p_vaddr );

  		if( phdr[i].p_vaddr != phdr[i].p_paddr )
-			printk("WARNING: ELF segment virtual addr != physical addr\n");
+			ELF_DPRINTF("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;
@@ -81,24 +88,15 @@
  		if( read_io(fd, addr, s) != s )
  			fatal_error("read failed\n");

-#if 0
-		/* patch CODE segment */
-                if( *elf_entry >= phdr[i].p_vaddr &&
-                    *elf_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",
-		   (ulong)phdr[i].p_vaddr, (ulong)phdr[i].p_memsz );*/
+		ELF_DPRINTF("ELF ROM-section loaded at %08lX (size %08lX)\n",
+			    (ulong)phdr[i].p_vaddr, (ulong)phdr[i].p_memsz );
  	}
  	free( phdr );
  	return lszz_offs;
  }

-
  static void
  encode_bootpath( const char *spec, const char *args )
  {
@@ -112,10 +110,10 @@
  / 
************************************************************************/

  static void
-qemu_startup( void )
+yaboot_startup( void )
  {
-	const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
-	const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
+	const char *paths[] = { "hd:2,\\ofclient", "hd:2,\\yaboot", NULL };
+	const char *args[] = { "", "conf=hd:2,\\yaboot.conf", NULL };
          ulong elf_entry;
  	int i, fd;

@@ -127,6 +125,8 @@
  		encode_bootpath( paths[i], args[i] );

  		update_nvram();
+		ELF_DPRINTF("Transfering control to %s %s\n",
+			    paths[i], args[i]);
                  transfer_control_to_elf( elf_entry );
  		/* won't come here */
  	}
@@ -142,5 +142,5 @@
  boot( void )
  {
  	fword("update-chosen");
-	qemu_startup();
+	yaboot_startup();
  }
Index: openbios-devel/arch/ppc/qemu/tree.fs
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/tree.fs	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/tree.fs	2008-12-20 20:52:21.000000000  
+0100
@@ -15,17 +15,12 @@

  " chrp" device-type
  " OpenSource,QEMU" 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 ;
Index: openbios-devel/arch/ppc/qemu/init.c
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/init.c	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/init.c	2008-12-20 20:52:21.000000000  
+0100
@@ -32,6 +32,11 @@
  extern void ob_pci_init( void );
  extern void setup_timers( void );

+extern ulong get_ram_size( void );
+extern ulong get_ram_top( void );
+extern ulong get_ram_bottom( void );
+
+
  void
  unexpected_excep( int vector )
  {
@@ -67,11 +72,9 @@
  {
  	arch = &known_arch[ARCH_HEATHROW];
  	isa_io_base = arch->io_base;
-#ifdef CONFIG_DEBUG_CONSOLE
-#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+
  	serial_init();
-#endif
-#endif
+
  	printk("\n");
  	 
printk("============================================================= 
\n");
  	printk("OpenBIOS %s [%s]\n", OPENBIOS_RELEASE, OPENBIOS_BUILD_DATE );
@@ -100,8 +103,59 @@
  	phandle_t ph;
  #endif
  	int autoboot;
+	uint64_t ram_size;

  	devtree_init();
+
+	/* ISA BASE */
+
+	push_str("/");
+	fword("find-device");
+
+	PUSH(isa_io_base);
+	fword("encode-int");
+	push_str("isa-io-base");
+	fword("property");
+
+	/* memory info */
+
+	push_str("/memory");
+	fword("find-device");
+
+	/* all memory */
+
+	ram_size = get_ram_size();
+
+	PUSH(ram_size >> 32);
+	fword("encode-int");
+	PUSH(ram_size & 0xffffffff);
+	fword("encode-int");
+	fword("encode+");
+	PUSH(0);
+	fword("encode-int");
+	fword("encode+");
+	PUSH(0);
+	fword("encode-int");
+	fword("encode+");
+	push_str("reg");
+	fword("property");
+
+	/* available memory */
+
+	PUSH(0);
+	fword("encode-int");
+	PUSH((unsigned long)get_ram_bottom());
+	fword("encode-int");
+	fword("encode+");
+	PUSH((unsigned long)get_ram_top());
+	fword("encode-int");
+	fword("encode+");
+	PUSH(ram_size);
+	fword("encode-int");
+	fword("encode+");
+	push_str("available");
+	fword("property");
+
  	modules_init();
  	setup_timers();
  #ifdef CONFIG_DRIVER_PCI
@@ -119,22 +173,13 @@
  		set_property( ph, "rtas-size", (char*)&size, sizeof(size) );
  	}
  #endif
-#if 0
-	/* tweak boot settings */
-	autoboot = !!getbool("autoboot?");
-#endif
-	autoboot = 0;
-	if( !autoboot )
-		printk("Autobooting disabled - dropping into OpenFirmware\n");
-	setenv("auto-boot?", autoboot ? "true" : "false" );
-	setenv("boot-command", "qemuboot");

  #if 0
  	if( getbool("tty-interface?") == 1 )
  #endif
  		fword("activate-tty-interface");

-	/* hack */
  	device_end();
-	bind_func("qemuboot", boot );
+
+	bind_func("platform-boot", boot );
  }
Index: openbios-devel/arch/ppc/qemu/methods.c
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/methods.c	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/methods.c	2008-12-20  
20:52:21.000000000 +0100
@@ -24,6 +24,7 @@
  #include "libc/string.h"
  #include "qemu/qemu.h"
  #include "ofmem.h"
+#include "ppc/processor.h"

  / 
************************************************************************/
  /*	RTAS (run-time abstraction services)				*/
@@ -60,37 +61,6 @@


  / 
************************************************************************/
-/*	stdout								*/
-/ 
************************************************************************/
-
-DECLARE_NODE( video_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 );
-	console_draw_str( s );
-
-	free( s );
-
-	PUSH( len );
-}
-
-NODE_METHODS( video_stdout ) = {
-	{ "write",	stdout_write	},
-};
-
-
-/ 
************************************************************************/
  /*	tty								*/
  / 
************************************************************************/

@@ -136,7 +106,7 @@
  /*	client interface 'quiesce'					*/
  / 
************************************************************************/

-DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+DECLARE_NODE( ciface, 0, 0, "+/openprom/client-services" );

  /* ( -- ) */
  static void
@@ -149,7 +119,6 @@
  	msr &= ~(MSR_IR | MSR_DR);
  	asm volatile("mtmsr %0" :: "r" (msr) );
  #endif
-	printk("============================================================= 
\n\n");
  }

  /* ( -- ms ) */
@@ -181,7 +150,7 @@

  DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
  DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu at 0" );
-DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" );


  /* ( phys size align --- base ) */
@@ -327,7 +296,6 @@
  #ifdef USE_RTAS
  	REGISTER_NODE( rtas );
  #endif
-	REGISTER_NODE( video_stdout );
  	REGISTER_NODE( ciface );
  	REGISTER_NODE( memory );
  	REGISTER_NODE( mmu );
Index: openbios-devel/config/examples/cross-ppc_config.xml
===================================================================
--- openbios-devel.orig/config/examples/cross-ppc_config.xml	 
2008-12-20 20:51:41.000000000 +0100
+++ openbios-devel/config/examples/cross-ppc_config.xml	2008-12-20  
20:52:21.000000000 +0100
@@ -4,9 +4,9 @@
    <!-- generic -->
    <!--<option name="CONFIG_AMD64" type="boolean" value="true"/> -->
    <option name="CONFIG_PPC" type="boolean" value="true"/>
-  <!--<option name="CONFIG_MOL" type="boolean" value="true"/>-->
-  <!--<option name="CONFIG_BRIQ" type="boolean" value="true"/>-->
-  <!--<option name="CONFIG_PEARPC" type="boolean" value="true"/>-->
+  <option name="CONFIG_MOL" type="boolean" value="false"/>
+  <option name="CONFIG_BRIQ" type="boolean" value="false"/>
+  <option name="CONFIG_PEARPC" type="boolean" value="false"/>
    <option name="CONFIG_QEMU" type="boolean" value="true"/>
    <option name="CONFIG_BIG_ENDIAN" type="boolean" value="true"/>

@@ -17,7 +17,7 @@

    <!-- Kernel Debugging -->
    <option name="CONFIG_DEBUG" type="boolean" value="true"/>
-  <option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/>
+  <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/>
    <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
    <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
    <option name="CONFIG_DEBUG_DICTIONARY" type="boolean"  
value="false"/>
@@ -42,14 +42,14 @@
    <option name="CONFIG_DEBUG_MAC_PARTS" type="boolean" value="false"/>
    <option name="CONFIG_PC_PARTS" type="boolean" value="true"/>
    <option name="CONFIG_FS" type="boolean" value="true"/>
-  <option name="CONFIG_HFS" type="boolean" value="false"/>
-  <option name="CONFIG_HFSP" type="boolean" value="true"/>
+  <option name="CONFIG_HFS" type="boolean" value="true"/>
+  <option name="CONFIG_HFSP" type="boolean" value="false"/>
    <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
-  <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="false"/>
+  <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
    <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
-  <option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/>
+  <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/>
@@ -57,7 +57,7 @@
    <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
    <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
-  <option name="CONFIG_DEBUG_FS" type="boolean" value="true"/>
+  <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>

    <!-- Miscellaneous -->
    <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
Index: openbios-devel/drivers/timer.c
===================================================================
--- openbios-devel.orig/drivers/timer.c	2008-12-20 20:51:41.000000000  
+0100
+++ openbios-devel/drivers/timer.c	2008-12-20 20:52:21.000000000 +0100
@@ -81,7 +81,7 @@

  unsigned long get_timer_freq(void)
  {
-	return 100000000 / 4;
+	return 10000000 / 4;
  }

  void udelay(unsigned int usecs)
Index: openbios-devel/arch/ppc/qemu/qemu.fs
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/qemu.fs	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/qemu.fs	2008-12-20 20:52:21.000000000  
+0100
@@ -111,6 +111,5 @@
    " /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
  ;
Index: openbios-devel/arch/ppc/qemu/ofmem.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openbios-devel/arch/ppc/qemu/ofmem.c	2008-12-20 20:52:21.000000000  
+0100
@@ -0,0 +1,708 @@
+/*
+ *   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 at 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 "openbios/config.h"
+#include "openbios/bindings.h"
+#include "libc/string.h"
+#include "ofmem.h"
+#include "kernel.h"
+#include "mmutypes.h"
+#include "asm/processor.h"
+
+#define BIT(n)		(1U<<(31-(n)))
+
+#define FREE_BASE		0x00004000
+#define IO_BASE			0x80000000
+#define OFMEM			((ofmem_t*)FREE_BASE)
+#define OF_MALLOC_BASE		((char*)OFMEM + ((sizeof(ofmem_t) + 3) & ~3))
+
+#define HASH_SIZE		(2 << 15)
+
+#define	SEGR_USER		BIT(2)
+#define SEGR_BASE		0x0400
+
+typedef struct alloc_desc {
+	struct alloc_desc 	*next;
+	int			size;			/* size (including) this struct */
+} alloc_desc_t;
+
+typedef struct mem_range {
+	struct mem_range	*next;
+	ulong			start;
+	ulong			size;
+} range_t;
+
+typedef struct trans {
+	struct trans		*next;
+	ulong			virt;			/* chain is sorted by virt */
+	ulong			size;
+	ulong			phys;
+	int			mode;
+} translation_t;
+
+typedef struct {
+	ulong			ramsize;
+	char 			*next_malloc;
+	alloc_desc_t		*mfree;		/* list of free malloc blocks */
+
+	range_t			*phys_range;
+	range_t			*virt_range;
+
+	translation_t		*trans;	/* this is really a translation_t */
+} ofmem_t;
+
+static inline ulong
+get_hash_base( void )
+{
+	ulong sdr1;
+
+	asm volatile("mfsdr1 %0" :: "r" (sdr1) );
+
+	return (sdr1 & 0xffff0000);
+}
+
+static inline ulong
+get_hash_size( void )
+{
+	ulong sdr1;
+
+	asm volatile("mfsdr1 %0" :: "r" (sdr1) );
+
+	return ((sdr1 << 16) | 0x0000ffff) + 1;
+}
+
+ulong
+get_ram_size( void )
+{
+	ofmem_t *ofmem = OFMEM;
+	return ofmem->ramsize;
+}
+
+static inline ulong
+get_rom_base( void )
+{
+	return get_ram_size() - 0x00100000;
+}
+
+ulong
+get_ram_top( void )
+{
+	return get_rom_base() - HASH_SIZE - (32 + 32 + 64) * 1024;
+}
+
+ulong
+get_ram_bottom( void )
+{
+	return OF_MALLOC_BASE;
+}
+
+/ 
************************************************************************/
+/*	OF private allocations						*/
+/ 
************************************************************************/
+
+void *
+malloc( int size )
+{
+	ofmem_t *ofmem = OFMEM;
+	alloc_desc_t *d, **pp;
+	char *ret;
+	ulong top;
+
+	if( !size )
+		return NULL;
+
+	if( !ofmem->next_malloc )
+		ofmem->next_malloc = (char*)OF_MALLOC_BASE;
+
+	if( size & 3 )
+		size += 4 - (size & 3);
+	size += sizeof(alloc_desc_t);
+
+	/* look in the freelist */
+	for( pp=&ofmem->mfree; *pp && (**pp).size < size; pp = &(**pp).next )
+		;
+
+	/* waste at most 4K by taking an entry from the freelist */
+	if( *pp && (**pp).size < size + 0x1000 ) {
+		ret = (char*)*pp + sizeof(alloc_desc_t);
+		memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) );
+		*pp = (**pp).next;
+		return ret;
+	}
+
+	top = get_hash_base() - (32 + 64) * 1024;
+	if( (ulong)ofmem->next_malloc + size > top ) {
+		printk("out of malloc memory (%x)!\n", size );
+		return NULL;
+	}
+
+	d = (alloc_desc_t*) ofmem->next_malloc;
+	ofmem->next_malloc += size;
+
+	d->next = NULL;
+	d->size = size;
+
+	ret = (char*)d + sizeof(alloc_desc_t);
+	memset( ret, 0, size - sizeof(alloc_desc_t) );
+
+	return ret;
+}
+
+void
+free( void *ptr )
+{
+	ofmem_t *ofmem = OFMEM;
+	alloc_desc_t **pp, *d;
+
+	/* it is legal to free NULL pointers (size zero allocations) */
+	if( !ptr )
+		return;
+
+	d = (alloc_desc_t*)(ptr - sizeof(alloc_desc_t));
+	d->next = ofmem->mfree;
+
+	/* insert in the (sorted) freelist */
+	for( pp=&ofmem->mfree; *pp && (**pp).size < d->size ; pp =  
&(**pp).next )
+		;
+	d->next = *pp;
+	*pp = d;
+}
+
+void *
+realloc( void *ptr, size_t size )
+{
+	alloc_desc_t *d = (alloc_desc_t*)(ptr - sizeof(alloc_desc_t));
+	char *p;
+
+	if( !ptr )
+		return malloc( size );
+	if( !size ) {
+		free( ptr );
+		return NULL;
+	}
+	p = malloc( size );
+	memcpy( p, ptr, MIN(d->size - sizeof(alloc_desc_t),size) );
+	free( ptr );
+	return p;
+}
+
+
+/ 
************************************************************************/
+/*	misc								*/
+/ 
************************************************************************/
+
+extern char _start[], _end[];
+static inline int
+def_memmode( ulong phys )
+{
+	/* XXX: Guard bit not set as it should! */
+	if( phys < IO_BASE )
+		return 0x02;	/*0xa*/	/* wim GxPp */
+	return 0x6a;		/* WIm GxPp, I/O */
+}
+
+
+/ 
************************************************************************/
+/*	client interface						*/
+/ 
************************************************************************/
+
+static int
+is_free( ulong ea, ulong size, range_t *r )
+{
+	if( size == 0 )
+		return 1;
+	for( ; r ; r=r->next ) {
+		if( r->start + r->size - 1 >= ea && r->start <= ea )
+			return 0;
+		if( r->start >= ea && r->start <= ea + size - 1 )
+			return 0;
+	}
+	return 1;
+}
+
+static void
+add_entry_( ulong ea, ulong size, range_t **r )
+{
+	range_t *nr;
+
+	for( ; *r && (**r).start < ea; r=&(**r).next )
+		;
+	nr = (range_t*)malloc( sizeof(range_t) );
+	nr->next = *r;
+	nr->start = ea;
+	nr->size = size;
+	*r = nr;
+}
+
+static int
+add_entry( ulong ea, ulong size, range_t **r )
+{
+	if( !is_free( ea, size, *r ) ) {
+		printk("add_entry: range not free!\n");
+		return -1;
+	}
+	add_entry_( ea, size, r );
+	return 0;
+}
+
+static void
+join_ranges( range_t **rr )
+{
+	range_t *n, *r = *rr;
+	while( r ) {
+		if( !(n=r->next) )
+			break;
+
+		if( r->start + r->size - 1 >= n->start -1 ) {
+			int s = n->size + (n->start - r->start - r->size);
+			if( s > 0 )
+				r->size += s;
+			r->next = n->next;
+			free( n );
+			continue;
+		}
+		r=r->next;
+	}
+}
+
+static void
+fill_range( ulong ea, int size, range_t **rr )
+{
+	add_entry_( ea, size, rr );
+	join_ranges( rr );
+}
+
+static ulong
+find_area( ulong align, ulong size, range_t *r, ulong min, ulong max,  
int reverse )
+{
+	ulong base = min;
+	range_t *r2;
+
+	if( (align & (align-1)) ) {
+		printk("bad alignment %ld\n", align);
+		align = 0x1000;
+	}
+	if( !align )
+		align = 0x1000;
+
+	base = reverse ? max - size : min;
+	r2 = reverse ? NULL : r;
+
+	for( ;; ) {
+		if( !reverse ) {
+			base = (base + align - 1) & ~(align-1);
+			if( base < min )
+				base = min;
+			if( base + size - 1 >= max -1 )
+				break;
+		} else {
+			if( base > max - size )
+				base = max - size;
+			base -= base & (align-1);
+		}
+		if( is_free( base, size, r ) )
+			return base;
+
+		if( !reverse ) {
+			if( !r2 )
+				break;
+			base = r2->start + r2->size;
+			r2 = r2->next;
+		} else {
+			range_t *rp;
+			for( rp=r; rp && rp->next != r2 ; rp=rp->next )
+				;
+			r2 = rp;
+			if( !r2 )
+				break;
+			base = r2->start - size;
+		}
+	}
+	return (ulong)-1;
+}
+
+static ulong
+ofmem_claim_phys_( ulong phys, ulong size, ulong align, int min, int  
max, int reverse )
+{
+	ofmem_t *ofmem = OFMEM;
+	if( !align ) {
+		if( !is_free( phys, size, ofmem->phys_range ) ) {
+			printk("Non-free physical memory claimed!\n");
+			return -1;
+		}
+		add_entry( phys, size, &ofmem->phys_range );
+		return phys;
+	}
+	phys = find_area( align, size, ofmem->phys_range, min, max, reverse );
+	if( phys == (ulong)-1 ) {
+		printk("ofmem->claim_phys - out of space\n");
+		return -1;
+	}
+	add_entry( phys, size, &ofmem->phys_range );
+	return phys;
+}
+
+/* if align != 0, phys is ignored. Returns -1 on error */
+ulong
+ofmem_claim_phys( ulong phys, ulong size, ulong align )
+{
+	/* printk("+ ofmem_claim phys %08lx %lx %ld\n", phys, size, align );  
*/
+	return ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 0 );
+}
+
+static ulong
+ofmem_claim_virt_( ulong virt, ulong size, ulong align, int min, int  
max, int reverse )
+{
+	ofmem_t *ofmem = OFMEM;
+	if( !align ) {
+		if( !is_free( virt, size, ofmem->virt_range ) ) {
+			printk("Non-free physical memory claimed!\n");
+			return -1;
+		}
+		add_entry( virt, size, &ofmem->virt_range );
+		return virt;
+	}
+
+	virt = find_area( align, size, ofmem->virt_range, min, max, reverse );
+	if( virt == (ulong)-1 ) {
+		printk("ofmem_claim_virt - out of space\n");
+		return -1;
+	}
+	add_entry( virt, size, &ofmem->virt_range );
+	return virt;
+}
+
+ulong
+ofmem_claim_virt( ulong virt, ulong size, ulong align )
+{
+	/* printk("+ ofmem_claim virt %08lx %lx %ld\n", virt, size, align );  
*/
+	return ofmem_claim_virt_( virt, size, align, get_ram_size() ,  
IO_BASE, 0 );
+}
+
+
+/* allocate both physical and virtual space and add a translation */
+ulong
+ofmem_claim( ulong addr, ulong size, ulong align )
+{
+	ofmem_t *ofmem = OFMEM;
+	ulong virt, phys;
+	ulong offs = addr & 0xfff;
+
+	/* printk("+ ofmem_claim %08lx %lx %ld\n", addr, size, align ); */
+	virt = phys = 0;
+	if( !align ) {
+		if( is_free(addr, size, ofmem->virt_range) &&
+		    is_free(addr, size, ofmem->phys_range) ) {
+			ofmem_claim_phys_( addr, size, 0, 0, 0, 0 );
+			ofmem_claim_virt_( addr, size, 0, 0, 0, 0 );
+			virt = phys = addr;
+		} else {
+			/* printk("**** ofmem_claim failure ***!\n"); */
+			return -1;
+		}
+	} else {
+		if( align < 0x1000 )
+			align = 0x1000;
+		phys = ofmem_claim_phys_( addr, size, align, 0, get_ram_size(), 1 / 
* reverse */ );
+		virt = ofmem_claim_virt_( addr, size, align, 0, get_ram_size(), 1 / 
* reverse */ );
+		if( phys == (ulong)-1 || virt == (ulong)-1 ) {
+			printk("ofmem_claim failed\n");
+			return -1;
+		}
+		/* printk("...phys = %08lX, virt = %08lX, size = %08lX\n", phys,  
virt, size ); */
+	}
+
+	/* align */
+	if( phys & 0xfff ) {
+		size += (phys & 0xfff);
+		virt -= (phys & 0xfff);
+		phys &= ~0xfff;
+	}
+	if( size & 0xfff )
+		size = (size + 0xfff) & ~0xfff;
+
+	/* printk("...free memory found... phys: %08lX, virt: %08lX, size %lX 
\n", phys, virt, size ); */
+	ofmem_map( phys, virt, size, def_memmode(phys) );
+	return virt + offs;
+}
+
+
+/ 
************************************************************************/
+/*	keep track of ea -> phys translations				*/
+/ 
************************************************************************/
+
+static void
+split_trans( ulong virt )
+{
+	ofmem_t *ofmem = OFMEM;
+	translation_t *t, *t2;
+
+	for( t=ofmem->trans; t; t=t->next ) {
+		if( virt > t->virt && virt < t->virt + t->size-1 ) {
+			t2 = (translation_t*)malloc( sizeof(translation_t) );
+			t2->virt = virt;
+			t2->size = t->size - (virt - t->virt);
+			t->size = virt - t->virt;
+			t2->phys = t->phys + t->size;
+			t2->mode = t->mode;
+			t2->next = t->next;
+			t->next = t2;
+		}
+	}
+}
+
+static int
+map_page_range( ulong virt, ulong phys, ulong size, int mode )
+{
+	ofmem_t *ofmem = OFMEM;
+	translation_t *t, **tt;
+
+	split_trans( virt );
+	split_trans( virt + size );
+
+	/* detect remappings */
+	for( t=ofmem->trans; t; ) {
+		if( virt == t->virt || (virt < t->virt && virt + size > t->virt )) {
+			if( t->phys + virt - t->virt != phys ) {
+				printk("mapping altered (ea %08lx)\n", t->virt );
+			} else if( t->mode != mode ){
+				printk("mapping mode altered\n");
+			}
+			for( tt=&ofmem->trans; *tt != t ; tt=&(**tt).next )
+				;
+			*tt = t->next;
+			free((char*)t);
+			t=ofmem->trans;
+			continue;
+		}
+		t=t->next;
+	}
+	/* add mapping */
+	for( tt=&ofmem->trans; *tt && (**tt).virt < virt ; tt=&(**tt).next )
+		;
+	t = (translation_t*)malloc( sizeof(translation_t) );
+	t->virt = virt;
+	t->phys = phys;
+	t->size = size;
+	t->mode = mode;
+	t->next = *tt;
+	*tt = t;
+
+	return 0;
+}
+
+int
+ofmem_map( ulong phys, ulong virt, ulong size, int mode )
+{
+	ofmem_t *ofmem = OFMEM;
+	/* printk("+ofmem_map: %08lX --> %08lX (size %08lX, mode 0x%02X)\n",
+	   virt, phys, size, mode ); */
+
+	if( (phys & 0xfff) || (virt & 0xfff) || (size & 0xfff) ) {
+		printk("ofmem_map: Bad parameters (%08lX %08lX %08lX)\n", phys,  
virt, size );
+		phys &= ~0xfff;
+		virt &= ~0xfff;
+		size = (size + 0xfff) & ~0xfff;
+	}
+#if 1
+	/* claim any unclaimed virtual memory in the range */
+	fill_range( virt, size, &ofmem->virt_range );
+	/* hmm... we better claim the physical range too */
+	fill_range( phys, size, &ofmem->phys_range );
+#endif
+	//printk("map_page_range %08lx -> %08lx %08lx\n", virt, phys, size );
+	map_page_range( virt, phys, size, (mode==-1)? def_memmode(phys) :  
mode );
+	return 0;
+}
+
+/* virtual -> physical. */
+ulong
+ofmem_translate( ulong virt, int *mode )
+{
+	ofmem_t *ofmem = OFMEM;
+	translation_t *t;
+
+	for( t=ofmem->trans; t && t->virt <= virt ; t=t->next ) {
+		ulong offs;
+		if( t->virt + t->size - 1 < virt )
+			continue;
+		offs = virt - t->virt;
+		*mode = t->mode;
+		return t->phys + offs;
+	}
+
+	//printk("ofmem_translate: no translation defined (%08lx)\n", virt);
+	//print_trans();
+	return -1UL;
+}
+
+/* release memory allocated by ofmem_claim */
+void
+ofmem_release( ulong virt, ulong size )
+{
+	/* printk("ofmem_release unimplemented (%08lx, %08lx)\n", virt,  
size ); */
+}
+
+
+/ 
************************************************************************/
+/*	page fault handler						*/
+/ 
************************************************************************/
+
+static ulong
+ea_to_phys( ulong ea, int *mode )
+{
+	ulong phys;
+
+	if (ea >= 0xfff00000UL) {
+		/* ROM into RAM */
+		ea -= 0xfff00000UL;
+		phys = get_rom_base() + ea;
+		*mode = 0x02;
+		return phys;
+	}
+
+	phys = ofmem_translate(ea, mode);
+	if( phys == -1UL ) {
+		phys = ea;
+		*mode = def_memmode( phys );
+
+		/* print_virt_range(); */
+		/* print_phys_range(); */
+		/* print_trans(); */
+	}
+	return phys;
+}
+
+static void
+hash_page( ulong ea, ulong phys, int mode )
+{
+	static int next_grab_slot=0;
+	ulong *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 = (ulong*)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 )
+{
+	ulong dar, dsisr;
+	int mode;
+	ulong 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 )
+{
+	ulong nip, srr1;
+	int mode;
+	ulong 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( ulong ramsize )
+{
+	ofmem_t *ofmem = OFMEM;
+	ulong sdr1, sr_base, msr;
+	ulong hash_base, page;
+	ulong data_size, bss_size;
+	int i;
+
+	memset(ofmem, 0, sizeof(ofmem_t));
+	ofmem->ramsize = ramsize;
+
+	/* SDR1: Storage Description Register 1 */
+
+	hash_base = (ramsize - 0x00100000 - HASH_SIZE) & 0xffff0000;
+	memset(hash_base, 0, HASH_SIZE);
+	sdr1 = hash_base | ((HASH_SIZE-1) >> 16);
+	asm volatile("mtsdr1 %0" :: "r" (sdr1) );
+
+	/* 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) );
+	}
+
+	memcpy(get_rom_base(), 0xfff00000, 0x00100000);
+
+	/* Enable MMU */
+
+	asm volatile("mfmsr %0" : "=r" (msr) : );
+	msr |= MSR_IR | MSR_DR;
+	asm volatile("mtmsr %0" :: "r" (msr) );
+}
+
+void
+ofmem_init( void )
+{
+	ulong top;
+
+	ofmem_claim_phys( 0, get_ram_bottom(), 0 );
+	ofmem_claim_virt( 0, get_ram_bottom(), 0 );
+	ofmem_claim_phys( get_ram_top(), get_ram_size() - get_ram_top(), 0);
+	ofmem_claim_virt( get_ram_top(), get_ram_size() - get_ram_top(), 0);
+}
Index: openbios-devel/arch/ppc/qemu/start.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openbios-devel/arch/ppc/qemu/start.S	2008-12-20 20:52:21.000000000  
+0100
@@ -0,0 +1,393 @@
+/*
+ *   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 at 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"
+
+/ 
************************************************************************/
+/*	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)... */
+
+
+/ 
************************************************************************/
+/*	entry								*/
+/ 
************************************************************************/
+
+
+	.text
+	.space 0x0100
+GLOBL(_start):
+	/* clear MSR, disable MMU */
+
+	li	r0,0
+	mtmsr	r0
+
+	/* 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 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)    |
+	 *     |                         |
+	 *     +-------------------------+
+	 *     :                         :
+	 * Bottom
+	 */
+
+	addis	r1, r3, -16		/* ramsize - 1MB */
+
+	/* setup exception stack */
+
+	addis	r1, r1, -1		/* - 64 kB */
+	mtsprg0	r1
+
+	/* setup stack */
+
+	addi	r1, r1, -32768		/* - 32 kB */
+
+	/* save memory size in stack */
+
+	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)
+	mfsdr1	r1
+	addis	r1, r1, -96
+	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?) */
+	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
+
+	.globl	__divide_error
+__divide_error:
+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
+	ba	exception_return
+
+VECTOR( 0x400, "ISI" ):
+	EXCEPTION_PREAMBLE
+	lis	r3,HA(isi_exception)
+	addi	r3,r3,LO(isi_exception)
+	mtctr	r3
+	bctrl
+	ba	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( ulong start, ulong 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
+
+	/* compute RAM size
+	 *
+	 * Exception vectors are beween 0x00000000 and 0x00004000
+	 * RAM size is limited to 2 MB (0x80000000)
+	 * MMIO and IO are after 0x80000000.
+	 * ROM is at 0xfff00000
+	 * so we can scan from 0x4000 to 0x80000000
+	 *
+	 */
+
+compute_ramsize:
+	li	r3, 0x4000	/* start address */
+
+	/* how many pages between 0x4000 and 0x80000000 */
+
+	lis	r4, 0x0007
+	ori	r4, r4, 0xfffc
+	mtctr	r4
+
+	/* pattern to write in memory */
+
+	lis	r4, 0x55aa
+	ori	r4, r4, 0x55aa
+
+memloop:
+	/* store and re-read pattern */
+
+	stw	r4, 0(r3)
+	sync
+	lwz	r0, 0(r3)
+	cmpw	cr7, r0, r4
+	bne	cr7, exit_memloop
+	addi	r3, r3, 4096	/* add page size */
+	bdnz	memloop
+exit_memloop:
+	blr
+
+	.section .romentry,"ax"
+	bl	_start
Index: openbios-devel/arch/ppc/qemu/kernel.c
===================================================================
--- openbios-devel.orig/arch/ppc/qemu/kernel.c	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/qemu/kernel.c	2008-12-20  
20:52:21.000000000 +0100
@@ -1,10 +1,15 @@
  /*
- *   Creation Date: <2004/08/28 18:03:25 stepan>
- *   Time-stamp: <2004/08/28 18:03:25 stepan>
+ *   Creation Date: <2003/10/25 14:07:17 samuel>
+ *   Time-stamp: <2004/08/28 17:48:19 stepan>
   *
- *	<qemu/kernel.c>
+ *	<kernel.c>
   *
- *   Copyright (C) 2005 Stefan Reinauer
+ *   Copyright (C) 2003, 2004 Samuel Rydh (samuel at 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
@@ -13,4 +18,84 @@
   */

  #include "qemu-dict.h"
-#include "../kernel.c"
+#include "openbios/config.h"
+#include "dict.h"
+#include "openbios/bindings.h"
+#include "openbios/stack.h"
+#include "openbios/kernel.h"
+#include "libc/string.h"
+#include "kernel.h"
+
+#define MEMORY_SIZE	(256*1024)	/* 256K ram for hosted system */
+#define DICTIONARY_SIZE	(512*1024)	/* 128K for the dictionary   */
+
+extern unsigned char 	*dict;
+extern cell 		dicthead;
+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) );
+
+	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;
+}
Index: openbios-devel/arch/ppc/qemu/kernel.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openbios-devel/arch/ppc/qemu/kernel.h	2008-12-20  
20:52:21.000000000 +0100
@@ -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__ */
Index: openbios-devel/arch/ppc/qemu/mmutypes.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openbios-devel/arch/ppc/qemu/mmutypes.h	2008-12-20  
20:52:21.000000000 +0100
@@ -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 at 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 */
Index: openbios-devel/arch/ppc/build.xml
===================================================================
--- openbios-devel.orig/arch/ppc/build.xml	2008-12-20  
20:51:41.000000000 +0100
+++ openbios-devel/arch/ppc/build.xml	2008-12-20 20:52:21.000000000  
+0100
@@ -136,7 +136,7 @@
     <rule><![CDATA[
  	$(CC) $$EXTRACFLAGS $(AS_FLAGS) $(CFLAGS) $(INCLUDES) -c -o $@  
$^]]></rule>
    </object>
-  <object source="ofmem.c"/>
+  <object source="qemu/ofmem.c"/>
    <object source="qemu/qemu.c" flags="-Iarch/ppc"/>
    <object source="qemu/init.c" flags="-Iarch/ppc"/>
    <external-object source="target/arch/ppc/qemu/kernel.o"/>
@@ -216,12 +216,12 @@

   <executable name="openbios-qemu.elf" target="target"  
condition="QEMU">
    <rule>
-	$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc- 
file-name) -o $@
+	$(LD) --warn-common -N -T arch/ppc/qemu/ldscript $^ -o $@
  	$(NM) $@ | sort > $(ODIR)/openbios-qemu.syms
  	cp $@ $@.nostrip
  	$(STRIP) $@
    </rule>
-  <object source="start.S">
+  <object source="qemu/start.S">
     <rule><![CDATA[
  	$(CC) $$EXTRACFLAGS $(AS_FLAGS) $(CFLAGS) $(INCLUDES) -c -o $@  
$^]]></rule>
    </object>
@@ -235,6 +235,7 @@
    <external-object source="libdrivers.a"/>
    <external-object source="liblibc.a"/>
    <external-object source="libfs.a"/>
+  <external-object source="libgcc.a"/>
   </executable>


Index: openbios-devel/arch/ppc/qemu/ldscript
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ openbios-devel/arch/ppc/qemu/ldscript	2008-12-20  
20:52:21.000000000 +0100
@@ -0,0 +1,55 @@
+OUTPUT_FORMAT(elf32-powerpc)
+OUTPUT_ARCH(powerpc)
+
+/* Initial load address
+ */
+BASE_ADDR = 0xfff00000;
+
+CSTACK_SIZE = 32768;	/* client stack size */
+
+SECTIONS
+{
+    . = BASE_ADDR;
+
+    _start = BASE_ADDR + 0x0100;
+
+    /* Normal sections */
+    .text ALIGN(4096): {
+        *(.text.vectors)
+        *(.text)
+        *(.text.*)
+    }
+
+    .rodata ALIGN(4096): {
+        _rodata = .;
+	*(.rodata)
+	*(.rodata.*)
+        *(.note.ELFBoot)
+    }
+    .data ALIGN(4096): {
+        _data = .;
+        *(.data)
+        *(.data.*)
+	_edata = .;
+    }
+
+    .bss ALIGN(4096): {
+        _bss = .;
+	*(.bss)
+	*(.bss.*)
+	*(COMMON)
+	_ebss = .;
+    }
+
+    . = 0xfffffffc;
+
+    .romentry : { *(.romentry) }
+
+    . = ALIGN(4096);
+    _end = .;
+
+    /* We discard .note sections other than .note.ELFBoot,
+     * because some versions of GCC generates useless ones. */
+
+    /DISCARD/ : { *(.comment*) *(.note.*) }
+}
Index: openbios-devel/include/ofmem.h
===================================================================
--- openbios-devel.orig/include/ofmem.h	2008-12-20 20:51:41.000000000  
+0100
+++ openbios-devel/include/ofmem.h	2008-12-20 20:52:21.000000000 +0100
@@ -27,6 +27,6 @@
  extern int 	ofmem_map( ulong phys, ulong virt, ulong size, int mode );

  extern void  	ofmem_release( ulong virt, ulong size );
-extern ulong 	ofmem_translate( ulong virt, ulong *ret_mode );
+extern ulong 	ofmem_translate( ulong virt, int *ret_mode );

  #endif   /* _H_OFMEM */



More information about the OpenBIOS mailing list