summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/packages
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/packages')
-rw-r--r--qemu/roms/openbios/packages/bootinfo-loader.c29
-rw-r--r--qemu/roms/openbios/packages/build.xml23
-rw-r--r--qemu/roms/openbios/packages/cmdline.c415
-rw-r--r--qemu/roms/openbios/packages/cmdline.fs41
-rw-r--r--qemu/roms/openbios/packages/deblocker.c221
-rw-r--r--qemu/roms/openbios/packages/disk-label.c245
-rw-r--r--qemu/roms/openbios/packages/disk-label.fs102
-rw-r--r--qemu/roms/openbios/packages/elf-loader.c31
-rw-r--r--qemu/roms/openbios/packages/init.c67
-rw-r--r--qemu/roms/openbios/packages/mac-parts.c447
-rw-r--r--qemu/roms/openbios/packages/mac-parts.h88
-rw-r--r--qemu/roms/openbios/packages/molvideo.c124
-rw-r--r--qemu/roms/openbios/packages/nvram.c308
-rw-r--r--qemu/roms/openbios/packages/packages.h36
-rw-r--r--qemu/roms/openbios/packages/pc-parts.c393
-rw-r--r--qemu/roms/openbios/packages/sun-parts.c343
-rw-r--r--qemu/roms/openbios/packages/xcoff-loader.c31
17 files changed, 2944 insertions, 0 deletions
diff --git a/qemu/roms/openbios/packages/bootinfo-loader.c b/qemu/roms/openbios/packages/bootinfo-loader.c
new file mode 100644
index 000000000..1497227cb
--- /dev/null
+++ b/qemu/roms/openbios/packages/bootinfo-loader.c
@@ -0,0 +1,29 @@
+/*
+ *
+ * <bootinfo-loader.c>
+ *
+ * bootinfo file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * 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 "libopenbios/bootinfo_load.h"
+#include "packages.h"
+
+DECLARE_NODE(bootinfo_loader, INSTALL_OPEN, 0, "+/packages/bootinfo-loader" );
+
+NODE_METHODS( bootinfo_loader ) = {
+ { "init-program", bootinfo_init_program },
+};
+
+void bootinfo_loader_init( void )
+{
+ REGISTER_NODE( bootinfo_loader );
+}
diff --git a/qemu/roms/openbios/packages/build.xml b/qemu/roms/openbios/packages/build.xml
new file mode 100644
index 000000000..bf49099c3
--- /dev/null
+++ b/qemu/roms/openbios/packages/build.xml
@@ -0,0 +1,23 @@
+<build>
+
+ <library name="packages" type="static" target="target">
+ <object source="bootinfo-loader.c" condition="LOADER_BOOTINFO"/>
+ <object source="cmdline.c" condition="CMDLINE"/>
+ <object source="deblocker.c" condition="DEBLOCKER"/>
+ <object source="disk-label.c" condition="DISK_LABEL"/>
+ <object source="elf-loader.c" condition="LOADER_ELF"/>
+ <object source="init.c"/>
+ <object source="mac-parts.c" condition="MAC_PARTS"/>
+ <object source="nvram.c"/>
+ <object source="pc-parts.c" condition="PC_PARTS"/>
+ <object source="sun-parts.c" condition="SUN_PARTS"/>
+ <object source="molvideo.c" condition="MOL"/>
+ <object source="xcoff-loader.c" condition="LOADER_XCOFF"/>
+ </library>
+
+ <dictionary name="openbios" target="forth">
+ <object source="cmdline.fs"/>
+ <object source="disk-label.fs"/>
+ </dictionary>
+
+</build>
diff --git a/qemu/roms/openbios/packages/cmdline.c b/qemu/roms/openbios/packages/cmdline.c
new file mode 100644
index 000000000..ea6bca3db
--- /dev/null
+++ b/qemu/roms/openbios/packages/cmdline.c
@@ -0,0 +1,415 @@
+/*
+ * Creation Date: <2003/12/28 14:16:31 samuel>
+ * Time-stamp: <2004/01/07 10:37:40 samuel>
+ *
+ * <cmdline.c>
+ *
+ * OpenFirmwware User 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 "packages.h"
+#include "libc/vsprintf.h"
+
+typedef struct {
+ char *buf; /* size: ncol+1 */
+ char *killbuf; /* size: ncol+1 */
+ char *history;
+ int hsize; /* size of history buffer */
+ int ncol; /* #columns */
+} cmdline_info_t;
+
+DECLARE_NODE( cmdline, INSTALL_OPEN, sizeof(cmdline_info_t),
+ "+/packages/cmdline" );
+
+static void
+emit( int ch )
+{
+ PUSH( ch );
+ fword("emit");
+}
+
+static int
+emit_str( const char *str )
+{
+ int n = 0;
+ while( *str ) {
+ n++;
+ emit( *str++ );
+ }
+ return n;
+}
+
+static void
+move_cursor( int n )
+{
+ if( n >= 0 ) {
+ while( n-- )
+ emit( '\f' );
+ } else {
+ while( n++ )
+ emit( 8 );
+ }
+}
+
+static void
+clear( int n )
+{
+ int i;
+ for( i=0; i<n; i++ )
+ emit(' ');
+ move_cursor( -n );
+}
+
+static void
+clearline( int pos, int n )
+{
+ move_cursor( -pos );
+ clear( n );
+}
+
+static int
+key( void )
+{
+ fword("key");
+ return POP();
+}
+
+/* ( -- flag ) */
+static void
+cmdline_open( cmdline_info_t *ci )
+{
+ ci->ncol = 80;
+ ci->buf = malloc( ci->ncol + 1 );
+ ci->killbuf = malloc( ci->ncol + 1 );
+
+ ci->hsize = 40;
+ ci->history = malloc( ci->hsize );
+ ci->history[0] = 0;
+
+ RET( -1 );
+}
+
+/* ( -- ) */
+static void
+cmdline_close( cmdline_info_t *ci )
+{
+ free( ci->buf );
+ free( ci->killbuf );
+ free( ci->history );
+}
+
+
+static char *
+history_get( cmdline_info_t *ci, int n )
+{
+ char *p = ci->history;
+ int len;
+
+ while( n-- && p )
+ if( (p=strchr(p,'\n')) )
+ p++;
+
+ ci->buf[0] = 0;
+ if( !p )
+ return NULL;
+
+ for( len=0; len <= ci->ncol && p[len] != '\n' && p[len] ; len++ )
+ ;
+ memcpy( ci->buf, p, len );
+ ci->buf[len] = 0;
+ return p;
+}
+
+static int
+history_remove( cmdline_info_t *ci, int line )
+{
+ char *s, *p = history_get( ci, line );
+
+ if( !p || !(s=strchr(p, '\n')) )
+ return 1;
+ s++;
+ memmove( p, s, strlen(s)+1 );
+ return 0;
+}
+
+static int /* ( -- ) */
+add_to_history( cmdline_info_t *ci, char *str )
+{
+ int n, len;
+
+ if( !ci->history )
+ return 0;
+ len = strlen(str);
+ if( !len )
+ return 0;
+
+ /* make room for line in history */
+ for( ;; ) {
+ char *p;
+ n = strlen(ci->history) + 1;
+
+ if( n + len + 1 <= ci->hsize )
+ break;
+
+ if( !(p=strrchr(ci->history,'\n')) )
+ return 0;
+ *p = 0;
+ if( !(p=strrchr(ci->history, '\n')) )
+ p = ci->history-1;
+ p[1] = 0;
+ }
+
+ memmove( ci->history + len + 1, ci->history, n );
+ memcpy( ci->history, str, len );
+ ci->history[ len ] = '\n';
+ return 1;
+}
+
+static void /* ( -- ) */
+cmdline_prompt( cmdline_info_t *ci )
+{
+ int cur_added=0, histind=0, ch, i, pos=0, n=0, prompt=1;
+ char *buf;
+ int terminate = 0;
+
+ buf = ci->buf;
+ selfword("prepare");
+
+ emit('\n');
+#ifdef NOLEAVE
+ for (;;)
+#else
+ while (rstackcnt && !terminate)
+#endif
+ {
+ int drop = 0;
+ terminate = 0;
+
+ if( prompt ) {
+ fword("print-prompt");
+ buf[0] = 0;
+ cur_added = prompt = histind = pos = n = 0;
+ }
+
+ ch = key();
+ switch( ch ) {
+ case 27:
+ switch( key() ) {
+ case 'f':
+ while( buf[pos] == ' ' )
+ emit( buf[pos++] );
+ while( buf[pos] && buf[pos] != ' ' )
+ emit( buf[pos++] );
+ break;
+
+ case 'b':
+ while( pos && buf[pos-1] == ' ' ) {
+ move_cursor( -1 );
+ pos--;
+ }
+ while( pos && buf[pos-1] != ' ' ) {
+ move_cursor( -1 );
+ pos--;
+ }
+ break;
+ case '[':
+ switch( key() ) {
+ case 'A':
+ goto go_up;
+ case 'B':
+ goto go_down;
+ case 'C':
+ goto go_right;
+ case 'D':
+ goto go_left;
+ case '3':
+ key();
+ goto delete;
+ }
+ break;
+ case 'O':
+ switch(key()) {
+ case 'F':
+ goto go_end;
+ case 'H':
+ goto go_home;
+ }
+ break;
+ }
+ break;
+ case '\n':
+ case '\r':
+ if( cur_added )
+ history_remove( ci, 0 );
+ add_to_history( ci, ci->buf );
+
+ emit_str( &buf[pos] );
+ emit(' ');
+ PUSH( feval(buf) );
+ fword("print-status");
+
+ /* Leave the interpreter if terminate? value set */
+ fword("terminate?");
+ if (POP())
+ terminate = 1;
+
+ prompt = 1;
+ break;
+
+ case 3: /* ^c */
+ emit_str("\n");
+ prompt = 1;
+ if( cur_added )
+ history_remove( ci, 0 );
+ break;
+
+ case 4: /* ^d */
+delete:
+ if( pos == n )
+ break;
+ emit( buf[pos++] );
+ /* fall through */
+
+ case 8: /* ^h */
+ case 127: /* backspace */
+ drop = 1;
+ if( !pos )
+ break;
+ move_cursor( -1 );
+ emit_str( &buf[pos] );
+ emit(' ');
+ memmove( &buf[pos-1], &buf[pos], n+1-pos );
+ move_cursor( pos-n-1 );
+ pos--;
+ n--;
+ break;
+
+ case 1: /* ^a */
+go_home:
+ move_cursor( -pos );
+ pos = 0;
+ break;
+
+ case 5: /* ^e */
+go_end:
+ pos += emit_str( &buf[pos] );
+ break;
+
+ //case 68: /* left */
+ // drop = 1;
+ case 2: /* ^b */
+go_left:
+ if( pos ) {
+ move_cursor( -1 );
+ pos--;
+ }
+ break;
+
+ //case 67: /* right */
+ // drop = 1;
+ case 6: /* ^f */
+go_right:
+ if( pos < n )
+ emit( buf[pos++] );
+ break;
+
+ case 11: /* ^k */
+ strcpy( ci->killbuf, &buf[pos] );
+ clear( n-pos );
+ n = pos;
+ buf[pos] = 0;
+ break;
+
+ case 25: /* ^y */
+ for( i=0; n < ci->ncol && ci->killbuf[i] ; i++, n++ ) {
+ memmove( &buf[pos+1], &buf[pos], n+1-pos );
+ buf[pos] = ci->killbuf[i];
+ move_cursor( 1-emit_str(&buf[pos++]) );
+ }
+ break;
+
+ case 9: /* TAB */
+ for( i=0; n < ci->ncol && (!i || (pos%4)) ; i++, n++ ) {
+ memmove( &buf[pos+1], &buf[pos], n+1-pos );
+ buf[pos] = ' ';
+ move_cursor( 1-emit_str(&buf[pos++]) );
+ }
+ break;
+
+ case 12: /* ^l */
+ move_cursor( -ci->ncol -pos );
+ fword("print-prompt");
+ move_cursor( pos-emit_str(buf) );
+ break;
+
+ //case 66: /* down */
+ // drop = 1;
+ case 14: /* ^n */
+go_down:
+ if( !histind )
+ break;
+ history_get( ci, --histind - 1);
+ clearline( pos, n );
+ emit_str( buf );
+ pos = n = strlen( buf );
+ if( !histind && cur_added ) {
+ cur_added = 0;
+ history_remove( ci, 0 );
+ }
+ break;
+
+ //case 65: /* up */
+ // drop = 1;
+ case 16: /* ^p */
+go_up:
+ if( !histind && add_to_history(ci, ci->buf) ) {
+ cur_added = 1;
+ histind++;
+ }
+ if( history_get(ci, histind) )
+ histind++;
+ clearline( pos, n );
+ emit_str( buf );
+ pos = n = strlen( buf );
+ break;
+ }
+ if( (unsigned int)ch < 32 )
+ drop = 1;
+
+ if( !drop && n < ci->ncol ) {
+ memmove( &buf[pos+1], &buf[pos], n+1-pos );
+ n++;
+ buf[pos] = ch;
+ move_cursor( 1-emit_str(&buf[pos++]) );
+ }
+ }
+
+ /* we only get here if terminate? is non-zero; this should
+ * only ever be done for a subordinate forth interpreter
+ * e.g. for debugging */
+
+ /* Reset stack and terminate? */
+ rstackcnt = dbgrstackcnt;
+ feval("0 to terminate?");
+}
+
+NODE_METHODS( cmdline ) = {
+ { "open", cmdline_open },
+ { "close", cmdline_close },
+ { "cmdline", cmdline_prompt },
+};
+
+void
+cmdline_init( void )
+{
+ REGISTER_NODE( cmdline );
+}
diff --git a/qemu/roms/openbios/packages/cmdline.fs b/qemu/roms/openbios/packages/cmdline.fs
new file mode 100644
index 000000000..70d3aa2d5
--- /dev/null
+++ b/qemu/roms/openbios/packages/cmdline.fs
@@ -0,0 +1,41 @@
+\ tag: Utility functions
+\
+\ deblocker / filesystem support
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ -------------------------------------------------------------
+\ command line editor (/packages/cmdline)
+\ -------------------------------------------------------------
+
+[IFDEF] CONFIG_CMDLINE
+
+dev /packages
+new-device
+ " cmdline" device-name
+
+ :noname
+ " " [active-package], open-package
+ ?dup if
+ " cmdline" rot $call-method
+ else
+ ." cmdline is missing!" cr
+ then
+ \ cmdline must close itself upon return
+ ;
+
+ :noname
+ [ ['] (lit) , swap , ] to outer-interpreter
+ ; SYSTEM-initializer
+
+ external
+ : prepare 0 to my-self ;
+
+finish-device
+
+[THEN]
+device-end
diff --git a/qemu/roms/openbios/packages/deblocker.c b/qemu/roms/openbios/packages/deblocker.c
new file mode 100644
index 000000000..50071854c
--- /dev/null
+++ b/qemu/roms/openbios/packages/deblocker.c
@@ -0,0 +1,221 @@
+/*
+ * Creation Date: <2003/12/03 21:20:58 samuel>
+ * Time-stamp: <2004/01/07 19:34:50 samuel>
+ *
+ * <deblocker.c>
+ *
+ * deblocker implementation
+ *
+ * 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/diskio.h"
+#include "packages.h"
+
+typedef struct {
+ ucell mark_hi, mark_lo;
+ xt_t read_xt;
+ xt_t write_xt;
+
+ int max_xfer;
+ int blksize;
+ char *buf;
+} deblk_info_t;
+
+DECLARE_NODE( deblocker, 0, sizeof(deblk_info_t), "+/packages/deblocker" );
+
+/* ( -- flag ) */
+static void
+deblk_open( deblk_info_t *di )
+{
+ xt_t xt;
+
+ di->read_xt = find_parent_method("read-blocks");
+ di->write_xt = find_parent_method("write-blocks");
+
+ if( !di->read_xt )
+ RET(0);
+
+ di->blksize = di->max_xfer = 512;
+ if( (xt=find_parent_method("block-size")) ) {
+ call_parent( xt );
+ di->blksize = POP();
+ }
+ if( (xt=find_parent_method("max-transfer")) ) {
+ call_parent( xt );
+ di->max_xfer = POP();
+ }
+ /* printk("block-size: %x max_xfer: %x read_xt %x write_xt %x\n",
+ di->blksize, di->max_xfer, di->write_xt, di->read_xt ); */
+
+ di->buf = malloc( di->blksize );
+ PUSH(-1);
+}
+
+/* ( -- ) */
+static void
+deblk_close( deblk_info_t *di )
+{
+ free( di->buf );
+}
+
+/* ( pos_lo pos_hi -- status ) */
+static void
+deblk_seek( deblk_info_t *di )
+{
+ ucell pos_hi = POP();
+ ucell pos_lo = POP();
+ ducell mark = ((ducell)pos_hi << BITS) | pos_lo;
+
+ /* printk("deblk_seek %x %08x\n", pos_hi, pos_lo ); */
+
+ /* -1 means seek to EOF (at least in our implementation) */
+ if( (dcell)mark == -1 )
+ RET(-1);
+ di->mark_hi = pos_hi;
+ di->mark_lo = pos_lo;
+
+ /* 0,1 == success, -1 == error */
+ PUSH(0);
+}
+
+/* ( -- mark.d ) */
+static void
+deblk_tell( deblk_info_t *di )
+{
+ PUSH( di->mark_lo );
+ PUSH( di->mark_hi );
+}
+
+
+#define DO_IO( xt, buf, blk, n ) \
+ ({ PUSH3(pointer2cell(buf), blk, n); call_parent(xt); POP(); })
+
+typedef struct {
+ /* block operation */
+ char *blk_buf;
+ int nblks;
+
+ /* byte operation */
+ cell offs;
+ int len;
+ char *data; /* start of data */
+} work_t;
+
+static void
+split( deblk_info_t *di, char *data, int len, work_t w[3] )
+{
+ ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo;
+ memset( w, 0, sizeof(work_t[3]) );
+
+ w[0].offs = mark % di->blksize;
+ w[0].blk_buf = di->buf;
+ w[0].data = data;
+ if( w[0].offs ) {
+ w[0].len = MIN( len, di->blksize - w[0].offs );
+ w[0].nblks = w[0].len ? 1:0;
+ data += w[0].len;
+ len -= w[0].len;
+ }
+
+ w[1].blk_buf = data;
+ w[1].nblks = (len / di->blksize);
+ w[1].len = w[1].nblks * di->blksize;
+ data += w[1].len;
+ len -= w[1].len;
+
+ w[2].blk_buf = di->buf;
+ w[2].data = data;
+ w[2].len = len;
+ w[2].nblks = len ? 1:0;
+}
+
+static int
+do_readwrite( deblk_info_t *di, int is_write, xt_t xt )
+{
+ int blk, i, n, len = POP();
+ char *dest = (char*)cell2pointer(POP());
+ int last=0, retlen=0;
+ work_t w[3];
+ ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo;
+
+ /* printk("read: %x %x\n", (int)dest, len ); */
+
+ if( !xt )
+ return -1;
+
+ blk = mark / di->blksize;
+ split( di, dest, len, w );
+
+ for( i=0; !last && i<3; i++ ) {
+ if( !w[i].nblks )
+ continue;
+
+ if( is_write && i != 1 ) {
+ DO_IO( di->read_xt, w[i].blk_buf, blk, w[i].nblks );
+ memcpy( w[i].blk_buf + w[i].offs, w[i].data, w[i].len );
+ }
+
+ n = DO_IO( xt, w[i].blk_buf, blk, w[i].nblks );
+ if( n < 0 ) {
+ if( !retlen )
+ retlen = -1;
+ break;
+ }
+ if( n != w[i].nblks ) {
+ w[i].len = MIN( n*di->blksize, w[i].len );
+ last = 1;
+ }
+ if( !is_write && i != 1 )
+ memcpy( w[i].data, w[i].blk_buf + w[i].offs, w[i].len );
+ retlen += w[i].len;
+ blk += n;
+ }
+ if( retlen > 0 ) {
+ mark += retlen;
+ di->mark_hi = mark >> BITS;
+ di->mark_lo = mark & (ucell) -1;
+ }
+ return retlen;
+}
+
+/* ( addr len -- actual ) */
+static void
+deblk_read( deblk_info_t *di )
+{
+ /* printk("deblk_read\n"); */
+ int ret = do_readwrite( di, 0, di->read_xt );
+ PUSH( ret );
+}
+
+/* ( buf len --- actlen ) */
+static void
+deblk_write( deblk_info_t *di )
+{
+ int ret = do_readwrite( di, 1, di->write_xt );
+ PUSH( ret );
+}
+
+/* remember to fix is-deblocker if new methods are added */
+NODE_METHODS( deblocker ) = {
+ { "open", deblk_open },
+ { "close", deblk_close },
+ { "read", deblk_read },
+ { "write", deblk_write },
+ { "seek", deblk_seek },
+ { "tell", deblk_tell },
+};
+
+
+void
+deblocker_init( void )
+{
+ REGISTER_NODE( deblocker );
+}
diff --git a/qemu/roms/openbios/packages/disk-label.c b/qemu/roms/openbios/packages/disk-label.c
new file mode 100644
index 000000000..1ca9bd867
--- /dev/null
+++ b/qemu/roms/openbios/packages/disk-label.c
@@ -0,0 +1,245 @@
+/*
+ * Creation Date: <2003/12/03 22:10:45 samuel>
+ * Time-stamp: <2004/01/07 19:17:45 samuel>
+ *
+ * <disk-label.c>
+ *
+ * Partition support
+ *
+ * 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 "libopenbios/load.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define DEBUG_DISK_LABEL
+
+#ifdef DEBUG_DISK_LABEL
+#define DPRINTF(fmt, args...) \
+do { printk("DISK-LABEL - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+typedef struct {
+ xt_t parent_seek_xt;
+ xt_t parent_tell_xt;
+ xt_t parent_read_xt;
+
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ int block_size;
+ int type; /* partition type or -1 */
+
+ ihandle_t part_ih;
+ phandle_t filesystem_ph;
+} dlabel_info_t;
+
+DECLARE_NODE( dlabel, 0, sizeof(dlabel_info_t), "/packages/disk-label" );
+
+
+/* ( -- ) */
+static void
+dlabel_close( __attribute__((unused))dlabel_info_t *di )
+{
+}
+
+/* ( -- success? ) */
+static void
+dlabel_open( dlabel_info_t *di )
+{
+ char *path;
+ char block0[512];
+ phandle_t ph;
+ int success=0;
+ cell status;
+
+ path = my_args_copy();
+
+ DPRINTF("dlabel-open '%s'\n", path );
+
+ di->part_ih = 0;
+
+ /* Find parent methods */
+ di->filesystem_ph = 0;
+ di->parent_seek_xt = find_parent_method("seek");
+ di->parent_tell_xt = find_parent_method("tell");
+ di->parent_read_xt = find_parent_method("read");
+
+ /* If arguments have been passed, determine the partition/filesystem type */
+ if (path && strlen(path)) {
+
+ /* Read first block from parent device */
+ DPUSH(0);
+ call_package(di->parent_seek_xt, my_parent());
+ POP();
+
+ PUSH(pointer2cell(block0));
+ PUSH(sizeof(block0));
+ call_package(di->parent_read_xt, my_parent());
+ status = POP();
+ if (status != sizeof(block0))
+ goto out;
+
+ /* Find partition handler */
+ PUSH( pointer2cell(block0) );
+ selfword("find-part-handler");
+ ph = POP_ph();
+ if( ph ) {
+ /* We found a suitable partition handler, so interpose it */
+ DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph);
+
+ push_str(path);
+ PUSH_ph(ph);
+ fword("interpose");
+
+ success = 1;
+ } else {
+ /* unknown (or missing) partition map,
+ * try the whole disk
+ */
+
+ DPRINTF("Unknown or missing partition map; trying whole disk\n");
+
+ /* Probe for filesystem from start of device */
+ DPUSH ( 0 );
+ PUSH_ih( my_self() );
+ selfword("find-filesystem");
+ ph = POP_ph();
+ if( ph ) {
+ /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */
+ di->filesystem_ph = ph;
+
+ DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph);
+ DPRINTF("path: %s length: %d\n", path, strlen(path));
+
+ if (path && strlen(path)) {
+ DPRINTF("INTERPOSE!\n");
+
+ push_str( path );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+ } else if (path && strcmp(path, "%BOOT") != 0) {
+ goto out;
+ }
+
+ success = 1;
+ }
+ } else {
+ /* No arguments were passed, so we just use the parent raw device directly */
+ success = 1;
+ }
+
+out:
+ if( path )
+ free( path );
+ if( !success ) {
+ dlabel_close( di );
+ RET(0);
+ }
+ PUSH(-1);
+}
+
+/* ( addr len -- actual ) */
+static void
+dlabel_read( dlabel_info_t *di )
+{
+ /* Call back up to parent */
+ call_package(di->parent_read_xt, my_parent());
+}
+
+/* ( pos.d -- status ) */
+static void
+dlabel_seek( dlabel_info_t *di )
+{
+ /* Call back up to parent */
+ call_package(di->parent_seek_xt, my_parent());
+}
+
+/* ( -- filepos.d ) */
+static void
+dlabel_tell( dlabel_info_t *di )
+{
+ /* Call back up to parent */
+ call_package(di->parent_tell_xt, my_parent());
+}
+
+/* ( addr len -- actual ) */
+static void
+dlabel_write( __attribute__((unused)) dlabel_info_t *di )
+{
+ DDROP();
+ PUSH( -1 );
+}
+
+/* ( addr -- size ) */
+static void
+dlabel_load( __attribute__((unused)) dlabel_info_t *di )
+{
+ /* Try the load method of the part package */
+ xt_t xt;
+
+ /* If we have a partition handle, invoke the load word on it */
+ if (di->part_ih) {
+ xt = find_ih_method("load", di->part_ih);
+ if (!xt) {
+ forth_printf("load currently not implemented for ihandle " FMT_ucellx "\n", di->part_ih);
+ PUSH(0);
+ return;
+ }
+
+ DPRINTF("calling load on ihandle " FMT_ucellx "\n", di->part_ih);
+
+ call_package(xt, di->part_ih);
+ } else {
+ /* Otherwise attempt load directly on the raw disk */
+ DPRINTF("calling load on raw disk ihandle " FMT_ucellx "\n", my_self());
+
+ load(my_self());
+ }
+}
+
+/* ( pathstr len -- ) */
+static void
+dlabel_dir( dlabel_info_t *di )
+{
+ if ( di->filesystem_ph ) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("disk-label: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( dlabel ) = {
+ { "open", dlabel_open },
+ { "close", dlabel_close },
+ { "load", dlabel_load },
+ { "read", dlabel_read },
+ { "write", dlabel_write },
+ { "seek", dlabel_seek },
+ { "tell", dlabel_tell },
+ { "dir", dlabel_dir },
+};
+
+void
+disklabel_init( void )
+{
+ REGISTER_NODE( dlabel );
+}
diff --git a/qemu/roms/openbios/packages/disk-label.fs b/qemu/roms/openbios/packages/disk-label.fs
new file mode 100644
index 000000000..8354f878e
--- /dev/null
+++ b/qemu/roms/openbios/packages/disk-label.fs
@@ -0,0 +1,102 @@
+\ tag: Utility functions
+\
+\ deblocker / filesystem support
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+dev /packages
+
+\ -------------------------------------------------------------
+\ /packages/disk-label (partition handling)
+\ -------------------------------------------------------------
+
+[IFDEF] CONFIG_DISK_LABEL
+
+new-device
+ " disk-label" device-name
+ external
+
+ variable part-handlers \ list with (probe-xt, phandle) elements
+ variable fs-handlers \ list with (fs-probe-xt, phandle) elements
+
+ : find-part-handler ( block0 -- phandle | 0 )
+ >r part-handlers
+ begin list-get while
+ ( nextlist dictptr )
+ r@ over @ execute if
+ ( nextlist dictptr )
+ na1+ @ r> rot 2drop exit
+ then
+ drop
+ repeat
+ r> drop 0
+ ;
+
+ : find-filesystem ( offs.d ih -- ph | 0 )
+ >r fs-handlers ( offs.d listhead )
+ begin list-get while
+ 2over ( offs.d nextlist dictptr offs.d )
+ r@ ( offs.d nextlist dictptr offs.d ih )
+ 3 pick ( offs.d nextlist dictptr offs.d ih dictptr )
+ @ ( offs.d nextlist dictptr offs.d ih probe-xt )
+ execute ( offs.d nextlist dictptr flag? )
+ if
+ ( offs.d nextlist dictptr )
+ na1+ ( offs.d nextlist dictptr+1 )
+ @ ( offs.d nextlist phandle )
+ r> ( offs.d nextlist phandle ih )
+ rot ( offs.d phandle ih nextlist )
+ 2drop ( offs.d phandle )
+ -rot ( phandle offs.d )
+ 2drop ( phandle )
+ exit
+ then
+ drop ( offs.d nextlist )
+ repeat
+ 2drop ( offs.d )
+ r> drop 0
+ ;
+
+
+ : register-part-handler ( handler-ph -- )
+ dup " probe" rot find-method
+ 0= abort" Missing probe method!"
+ ( phandle probe-xt )
+ part-handlers list-add , ,
+ ;
+
+ : register-fs-handler ( handler-ph -- )
+ dup " probe" rot find-method
+ 0= abort" Missing probe method!"
+ ( phandle probe-xt )
+ fs-handlers list-add , ,
+ ;
+finish-device
+
+\ ---------------------------------------------------------------------------
+\ methods to register partion and filesystem packages used by disk-label
+\ ---------------------------------------------------------------------------
+
+device-end
+: register-partition-package ( -- )
+ " register-part-handler" " disk-label" $find-package-method ?dup if
+ active-package swap execute
+ else
+ ." [disk-label] internal error" cr
+ then
+;
+
+: register-fs-package ( -- )
+ " register-fs-handler" " disk-label" $find-package-method ?dup if
+ active-package swap execute
+ else
+ ." [misc-files] internal error" cr
+ then
+;
+
+[THEN]
+device-end
diff --git a/qemu/roms/openbios/packages/elf-loader.c b/qemu/roms/openbios/packages/elf-loader.c
new file mode 100644
index 000000000..1665f0d0b
--- /dev/null
+++ b/qemu/roms/openbios/packages/elf-loader.c
@@ -0,0 +1,31 @@
+/*
+ *
+ * <elf-loader.c>
+ *
+ * ELF file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * Some parts 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
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elf_load.h"
+#include "packages.h"
+
+DECLARE_NODE(elf_loader, INSTALL_OPEN, 0, "+/packages/elf-loader" );
+
+NODE_METHODS( elf_loader ) = {
+ { "init-program", elf_init_program },
+};
+
+void elf_loader_init( void )
+{
+ REGISTER_NODE( elf_loader );
+}
diff --git a/qemu/roms/openbios/packages/init.c b/qemu/roms/openbios/packages/init.c
new file mode 100644
index 000000000..bff8558ab
--- /dev/null
+++ b/qemu/roms/openbios/packages/init.c
@@ -0,0 +1,67 @@
+/*
+ * Creation Date: <2003/12/23 00:28:05 samuel>
+ * Time-stamp: <2003/12/28 19:43:41 samuel>
+ *
+ * <init.c>
+ *
+ * Module intialization
+ *
+ * Copyright (C) 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
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "packages.h"
+
+void
+modules_init( void )
+{
+#ifdef CONFIG_CMDLINE
+ cmdline_init();
+#endif
+#ifdef CONFIG_DEBLOCKER
+ deblocker_init();
+#endif
+#ifdef CONFIG_DISK_LABEL
+ disklabel_init();
+#endif
+#ifdef CONFIG_HFSP
+ hfsp_init();
+#endif
+#ifdef CONFIG_HFS
+ hfs_init();
+#endif
+#ifdef CONFIG_EXT2
+ ext2_init();
+#endif
+#ifdef CONFIG_ISO9660
+ iso9660_init();
+#endif
+#ifdef CONFIG_GRUBFS
+ grubfs_init();
+#endif
+#ifdef CONFIG_MAC_PARTS
+ macparts_init();
+#endif
+#ifdef CONFIG_PC_PARTS
+ pcparts_init();
+#endif
+#ifdef CONFIG_SUN_PARTS
+ sunparts_init();
+#endif
+#ifdef CONFIG_LOADER_XCOFF
+ xcoff_loader_init();
+#endif
+#ifdef CONFIG_LOADER_ELF
+ elf_loader_init();
+#endif
+#ifdef CONFIG_LOADER_BOOTINFO
+ bootinfo_loader_init();
+#endif
+
+}
diff --git a/qemu/roms/openbios/packages/mac-parts.c b/qemu/roms/openbios/packages/mac-parts.c
new file mode 100644
index 000000000..16c87caf8
--- /dev/null
+++ b/qemu/roms/openbios/packages/mac-parts.c
@@ -0,0 +1,447 @@
+/*
+ * Creation Date: <2003/12/04 17:07:05 samuel>
+ * Time-stamp: <2004/01/07 19:36:09 samuel>
+ *
+ * <mac-parts.c>
+ *
+ * macintosh partition support
+ *
+ * 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 "libopenbios/load.h"
+#include "mac-parts.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define CONFIG_DEBUG_MAC_PARTS
+
+#ifdef CONFIG_DEBUG_MAC_PARTS
+#define DPRINTF(fmt, args...) \
+do { printk("MAC-PARTS: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+typedef struct {
+ xt_t seek_xt, read_xt;
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ ucell bootcode_addr, bootcode_entry;
+ unsigned int blocksize;
+ phandle_t filesystem_ph;
+} macparts_info_t;
+
+DECLARE_NODE( macparts, INSTALL_OPEN, sizeof(macparts_info_t), "+/packages/mac-parts" );
+
+#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
+#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
+
+/* ( open -- flag ) */
+static void
+macparts_open( macparts_info_t *di )
+{
+ char *str = my_args_copy();
+ char *parstr = NULL, *argstr = NULL;
+ char *tmpstr;
+ int bs, parnum=-1, apple_parnum=-1;
+ int parlist[2], parlist_size = 0;
+ desc_map_t dmap;
+ part_entry_t par;
+ int ret = 0, i = 0, j = 0;
+ int want_bootcode = 0;
+ phandle_t ph;
+ ducell offs = 0, size = -1;
+
+ DPRINTF("macparts_open '%s'\n", str );
+
+ /*
+ Arguments that we accept:
+ id: [0-7]
+ [(id)][,][filespec]
+ */
+
+ if ( str && strlen(str) ) {
+ /* Detect the arguments */
+ if ((*str >= '0' && *str <= '9') || (*str == ',')) {
+ push_str(str);
+ PUSH(',');
+ fword("left-parse-string");
+ parstr = pop_fstr_copy();
+ argstr = pop_fstr_copy();
+ } else {
+ argstr = str;
+ }
+
+ /* Make sure argstr is not null */
+ if (argstr == NULL)
+ argstr = strdup("");
+
+ /* Convert the id to a partition number */
+ if (parstr && strlen(parstr))
+ parnum = atol(parstr);
+
+ /* Detect if we are looking for the bootcode */
+ if (strcmp(argstr, "%BOOT") == 0) {
+ want_bootcode = 1;
+ }
+ }
+
+ DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
+
+ DPRINTF("want_bootcode %d\n", want_bootcode);
+ DPRINTF("macparts_open %d\n", parnum);
+
+ di->filesystem_ph = 0;
+ di->read_xt = find_parent_method("read");
+ di->seek_xt = find_parent_method("seek");
+
+ SEEK( 0 );
+ if( READ(&dmap, sizeof(dmap)) != sizeof(dmap) )
+ goto out;
+
+ /* partition maps might support multiple block sizes; in this case,
+ * pmPyPartStart is typically given in terms of 512 byte blocks.
+ */
+ bs = __be16_to_cpu(dmap.sbBlockSize);
+ if( bs != 512 ) {
+ SEEK( 512 );
+ READ( &par, sizeof(par) );
+ if( __be16_to_cpu(par.pmSig) == DESC_PART_SIGNATURE )
+ bs = 512;
+ }
+ SEEK( bs );
+ if( READ(&par, sizeof(par)) != sizeof(par) )
+ goto out;
+ if (__be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE)
+ goto out;
+
+ /*
+ * Implement partition selection as per the PowerPC Microprocessor CHRP bindings
+ */
+
+ if (argstr == NULL || parnum == 0) {
+ /* According to the spec, partition 0 as well as no arguments means the whole disk */
+ offs = (long long)0;
+ size = (long long)__be32_to_cpu(dmap.sbBlkCount) * bs;
+
+ di->blocksize = (unsigned int)bs;
+
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ ret = -1;
+ goto out;
+
+ } else if (parnum == -1) {
+
+ DPRINTF("mac-parts: counted %d partitions\n", __be32_to_cpu(par.pmMapBlkCnt));
+
+ /* No partition was explicitly requested so let's find a suitable partition... */
+ for (i = 1; i <= __be32_to_cpu(par.pmMapBlkCnt); i++) {
+ SEEK( bs * i );
+ READ( &par, sizeof(par) );
+ if ( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE ||
+ !__be32_to_cpu(par.pmPartBlkCnt) )
+ continue;
+
+ DPRINTF("found partition %d type: %s with status %x\n", i, par.pmPartType, __be32_to_cpu(par.pmPartStatus));
+
+ /* If we have a valid, allocated and readable partition... */
+ if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) {
+
+ /* Unfortunately Apple's OF implementation doesn't follow the OF PowerPC CHRP bindings
+ * and instead will brute-force boot the first valid partition it finds with a
+ * type of either "Apple_Boot", "Apple_HFS" or "DOS_FAT_". Here we store the id
+ * of the first partition that matches these criteria to use as a fallback later
+ * if required. */
+
+ if (apple_parnum == -1 &&
+ (strcmp(par.pmPartType, "Apple_Boot") == 0 ||
+ strcmp(par.pmPartType, "Apple_Bootstrap") == 0 ||
+ strcmp(par.pmPartType, "Apple_HFS") == 0 ||
+ strcmp(par.pmPartType, "DOS_FAT_") == 0)) {
+ apple_parnum = i;
+
+ DPRINTF("Located Apple OF fallback partition %d\n", apple_parnum);
+ }
+
+ /* If the partition is also bootable and the pmProcessor field matches "PowerPC" (insensitive
+ * match), then according to the CHRP bindings this is our chosen partition */
+ for (j = 0; j < strlen(par.pmProcessor); j++) {
+ par.pmProcessor[j] = tolower(par.pmProcessor[j]);
+ }
+
+ if ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid) &&
+ strcmp(par.pmProcessor, "powerpc") == 0) {
+ parnum = i;
+
+ DPRINTF("Located CHRP-compliant boot partition %d\n", parnum);
+ }
+ }
+ }
+
+ /* If we found a valid CHRP partition, add it to the list */
+ if (parnum > 0) {
+ parlist[parlist_size++] = parnum;
+ }
+
+ /* If we found an Apple OF fallback partition, add it to the list */
+ if (apple_parnum > 0 && apple_parnum != parnum) {
+ parlist[parlist_size++] = apple_parnum;
+ }
+
+ } else {
+ /* Another partition was explicitly requested */
+ parlist[parlist_size++] = parnum;
+
+ DPRINTF("Partition %d explicitly requested\n", parnum);
+ }
+
+ /* Attempt to use our CHRP partition, optionally followed by our Apple OF fallback partition */
+ for (j = 0; j < parlist_size; j++) {
+
+ /* Make sure our partition is valid */
+ parnum = parlist[j];
+
+ DPRINTF("Selected partition %d\n", parnum);
+
+ SEEK( bs * parnum );
+ READ( &par, sizeof(par) );
+
+ if(! ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable)) ) {
+ DPRINTF("Partition %d is not valid, allocated and readable\n", parnum);
+ goto out;
+ }
+
+ ret = -1;
+
+ offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
+ size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;
+
+ if (want_bootcode) {
+
+ /* If size == 0 then fail because we requested bootcode but it doesn't exist */
+ size = (long long)__be32_to_cpu(par.pmBootSize);
+ if (!size) {
+ ret = 0;
+ goto out;
+ }
+
+ /* Adjust seek position so 0 = start of bootcode */
+ offs += (long long)__be32_to_cpu(par.pmLgBootStart) * bs;
+
+ di->bootcode_addr = __be32_to_cpu(par.pmBootLoad);
+ di->bootcode_entry = __be32_to_cpu(par.pmBootEntry);
+ }
+
+ di->blocksize = (unsigned int)bs;
+
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ /* If we're trying to execute bootcode then we're all done */
+ if (want_bootcode) {
+ goto out;
+ }
+
+ /* We have a valid partition - so probe for a filesystem at the current offset */
+ DPRINTF("mac-parts: about to probe for fs\n");
+ DPUSH( offs );
+ PUSH_ih( my_parent() );
+ parword("find-filesystem");
+ DPRINTF("mac-parts: done fs probe\n");
+
+ ph = POP_ph();
+ if( ph ) {
+ DPRINTF("mac-parts: filesystem found on partition %d with ph " FMT_ucellx " and args %s\n", parnum, ph, argstr);
+ di->filesystem_ph = ph;
+
+ /* In case no partition was specified, set a special selected-partition-args property
+ giving the device parameters that we can use to generate bootpath */
+ tmpstr = malloc(strlen(argstr) + 2 + 1);
+ if (strlen(argstr)) {
+ sprintf(tmpstr, "%d,%s", parnum, argstr);
+ } else {
+ sprintf(tmpstr, "%d", parnum);
+ }
+
+ push_str(tmpstr);
+ feval("strdup encode-string \" selected-partition-args\" property");
+
+ free(tmpstr);
+
+ /* If we have been asked to open a particular file, interpose the filesystem package with
+ the passed filename as an argument */
+ if (strlen(argstr)) {
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+
+ goto out;
+ } else {
+ DPRINTF("mac-parts: no filesystem found on partition %d; bypassing misc-files interpose\n", parnum);
+
+ /* Here we have a valid partition; however if we tried to pass in a file argument for a
+ partition that doesn't contain a filesystem, then we must fail */
+ if (strlen(argstr)) {
+ ret = 0;
+ }
+ }
+ }
+
+ free( str );
+
+out:
+ PUSH( ret );
+}
+
+/* ( block0 -- flag? ) */
+static void
+macparts_probe( macparts_info_t *dummy )
+{
+ desc_map_t *dmap = (desc_map_t*)cell2pointer(POP());
+
+ DPRINTF("macparts_probe %x ?= %x\n", dmap->sbSig, DESC_MAP_SIGNATURE);
+ if( __be16_to_cpu(dmap->sbSig) != DESC_MAP_SIGNATURE )
+ RET(0);
+ RET(-1);
+}
+
+/* ( -- type offset.d size.d ) */
+static void
+macparts_get_info( macparts_info_t *di )
+{
+ DPRINTF("macparts_get_info");
+
+ PUSH( -1 ); /* no type */
+ PUSH( di->offs_lo );
+ PUSH( di->offs_hi );
+ PUSH( di->size_lo );
+ PUSH( di->size_hi );
+}
+
+/* ( -- size entry addr ) */
+static void
+macparts_get_bootcode_info( macparts_info_t *di )
+{
+ DPRINTF("macparts_get_bootcode_info");
+
+ PUSH( di->size_lo );
+ PUSH( di->bootcode_entry );
+ PUSH( di->bootcode_addr );
+}
+
+static void
+macparts_block_size( macparts_info_t *di )
+{
+ DPRINTF("macparts_block_size = %x\n", di->blocksize);
+ PUSH(di->blocksize);
+}
+
+static void
+macparts_initialize( macparts_info_t *di )
+{
+ fword("register-partition-package");
+}
+
+/* ( pos.d -- status ) */
+static void
+macparts_seek(macparts_info_t *di )
+{
+ long long pos = DPOP();
+ long long offs, size;
+
+ DPRINTF("macparts_seek %llx:\n", pos);
+
+ /* Seek is invalid if we reach the end of the device */
+ size = ((ducell)di->size_hi << BITS) | di->size_lo;
+ if (pos > size)
+ RET( -1 );
+
+ /* Calculate the seek offset for the parent */
+ offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
+ offs += pos;
+ DPUSH(offs);
+
+ DPRINTF("macparts_seek parent offset %llx:\n", offs);
+
+ call_package(di->seek_xt, my_parent());
+}
+
+/* ( buf len -- actlen ) */
+static void
+macparts_read(macparts_info_t *di )
+{
+ DPRINTF("macparts_read\n");
+
+ /* Pass the read back up to the parent */
+ call_package(di->read_xt, my_parent());
+}
+
+/* ( addr -- size ) */
+static void
+macparts_load( __attribute__((unused))macparts_info_t *di )
+{
+ /* Invoke the loader */
+ load(my_self());
+}
+
+/* ( pathstr len -- ) */
+static void
+macparts_dir( macparts_info_t *di )
+{
+ /* On PPC Mac, the first partition chosen according to the CHRP boot
+ specification (i.e. marked as bootable) may not necessarily contain
+ a valid FS */
+ if ( di->filesystem_ph ) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("mac-parts: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( macparts ) = {
+ { "probe", macparts_probe },
+ { "open", macparts_open },
+ { "seek", macparts_seek },
+ { "read", macparts_read },
+ { "load", macparts_load },
+ { "dir", macparts_dir },
+ { "get-info", macparts_get_info },
+ { "get-bootcode-info", macparts_get_bootcode_info },
+ { "block-size", macparts_block_size },
+ { NULL, macparts_initialize },
+};
+
+void
+macparts_init( void )
+{
+ REGISTER_NODE( macparts );
+}
diff --git a/qemu/roms/openbios/packages/mac-parts.h b/qemu/roms/openbios/packages/mac-parts.h
new file mode 100644
index 000000000..acfcbe04b
--- /dev/null
+++ b/qemu/roms/openbios/packages/mac-parts.h
@@ -0,0 +1,88 @@
+/*
+ * Creation Date: <1999/07/06 15:45:12 samuel>
+ * Time-stamp: <2002/10/20 16:31:48 samuel>
+ *
+ * <partition_table.h>
+ *
+ * Headers describing the partition table
+ *
+ * Copyright (C) 1999, 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_PARTITION_TABLE
+#define _H_PARTITION_TABLE
+
+/* This information is based upon IM vol V. */
+
+#define DESC_MAP_SIGNATURE 0x4552
+#define DESC_PART_SIGNATURE 0x504d
+
+enum {
+ kPartitionAUXIsValid = 0x00000001,
+ kPartitionAUXIsAllocated = 0x00000002,
+ kPartitionAUXIsInUse = 0x00000004,
+ kPartitionAUXIsBootValid = 0x00000008,
+ kPartitionAUXIsReadable = 0x00000010,
+ kPartitionAUXIsWriteable = 0x00000020,
+ kPartitionAUXIsBootCodePositionIndependent = 0x00000040,
+ kPartitionISMountedAtStartup = 0x40000000,
+ kPartitionIsStartup = 0x80000000,
+ kPartitionIsChainCompatible = 0x00000100,
+ kPartitionIsRealDeviceDriver = 0x00000200,
+ kPartitionCanChainToNext = 0x00000400,
+};
+
+typedef struct {
+ u32 ddBlock; /* first block of driver */
+ u16 ddSize; /* driver size in blocks */
+ s16 ddType; /* 1 & -1 for SCSI */
+} driver_entry_t;
+
+typedef struct { /* Block 0 of a device */
+ u16 sbSig; /* always 0x4552 */
+ u16 sbBlockSize; /* 512 */
+ s32 sbBlkCount; /* #blocks on device */
+ u16 sbDevType; /* 0 */
+ u16 sbDevID; /* 0 */
+ u32 sbData; /* 0 */
+ s16 sbDrvrCount; /* #driver descriptors */
+
+ /* driver entries goes here */
+ driver_entry_t drivers[61] __attribute__ ((packed));
+
+ u16 filler1;
+ u32 filler2;
+} desc_map_t;
+
+typedef struct { /* Partition descriptor */
+ u16 pmSig; /* always 0x504d 'PM' */
+ u16 pmSigPad; /* 0 */
+ u32 pmMapBlkCnt; /* #blocks in partition map */
+ u32 pmPyPartStart; /* first physical block of part. */
+ u32 pmPartBlkCnt; /* #blocks in partition */
+ char pmPartName[32]; /* partition name */
+ char pmPartType[32]; /* partition type */
+
+ /* these fields may or may not be used */
+ u32 pmLgDataStart;
+ u32 pmDataCnt;
+ u32 pmPartStatus;
+ u32 pmLgBootStart;
+ u32 pmBootSize;
+ u32 pmBootLoad;
+ u32 pmBootLoad2;
+ u32 pmBootEntry;
+ u32 pmBootEntry2;
+ u32 pmBootCksum;
+ char pmProcessor[16];
+
+ char filler[376]; /* might contain extra information */
+} part_entry_t;
+
+
+#endif /* _H_PARTITION_TABLE */
diff --git a/qemu/roms/openbios/packages/molvideo.c b/qemu/roms/openbios/packages/molvideo.c
new file mode 100644
index 000000000..787c4dc08
--- /dev/null
+++ b/qemu/roms/openbios/packages/molvideo.c
@@ -0,0 +1,124 @@
+/*
+ * Creation Date: <2002/10/23 20:26:40 samuel>
+ * Time-stamp: <2004/01/07 19:39:15 samuel>
+ *
+ * <molvideo.c>
+ *
+ * Mac-on-Linux display node
+ *
+ * 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 "libc/diskio.h"
+#include "libopenbios/ofmem.h"
+#include "drivers/drivers.h"
+#include "packages/video.h"
+#include "libopenbios/video.h"
+#include "drivers/vga.h"
+
+
+/************************************************************************/
+/* OF methods */
+/************************************************************************/
+
+DECLARE_NODE( video, 0, 0, "Tdisplay" );
+
+/* ( r g b index -- ) */
+static void
+molvideo_color_bang( void )
+{
+ int index = POP();
+ int b = POP();
+ int g = POP();
+ int r = POP();
+ unsigned long col = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0xff);
+ /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */
+
+ if( VIDEO_DICT_VALUE(video.depth) == 8 ) {
+ OSI_SetColor( index, col );
+ OSI_RefreshPalette();
+ }
+}
+
+/* ( -- ) - really should be reworked as draw-logo */
+static void
+molvideo_startup_splash( void )
+{
+ int fd, s, i, y, x, dx, dy;
+ int width, height;
+ char *pp, *p;
+ char buf[64];
+
+ /* only draw logo in 24-bit mode (for now) */
+ if( VIDEO_DICT_VALUE(video.depth) < 15 )
+ return;
+
+ for( i=0; i<2; i++ ) {
+ if( !BootHGetStrResInd("bootlogo", buf, sizeof(buf), 0, i) )
+ return;
+ *(!i ? &width : &height) = atol(buf);
+ }
+
+ if( (s=width * height * 3) > 0x20000 )
+ return;
+
+ if( (fd=open_io("pseudo:,bootlogo")) >= 0 ) {
+ p = malloc( s );
+ if( read_io(fd, p, s) != s )
+ printk("bootlogo size error\n");
+ close_io( fd );
+
+ dx = (VIDEO_DICT_VALUE(video.w) - width)/2;
+ dy = (VIDEO_DICT_VALUE(video.h) - height)/3;
+
+ pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + dy * VIDEO_DICT_VALUE(video.rb) + dx * (VIDEO_DICT_VALUE(video.depth) >= 24 ? 4 : 2);
+
+ for( y=0 ; y<height; y++, pp += VIDEO_DICT_VALUE(video.rb) ) {
+ if( VIDEO_DICT_VALUE(video.depth) >= 24 ) {
+ unsigned long *d = (unsigned long*)pp;
+ for( x=0; x<width; x++, p+=3, d++ )
+ *d = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
+ } else if( VIDEO_DICT_VALUE(video.depth) == 15 ) {
+ unsigned short *d = (unsigned short*)pp;
+ for( x=0; x<width; x++, p+=3, d++ ) {
+ int col = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
+ *d = ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
+ }
+ }
+ }
+ free( p );
+ }
+
+ /* No bootlogo support yet on other platforms */
+ return;
+}
+
+
+NODE_METHODS( video ) = {
+ {"mol-startup-splash", molvideo_startup_splash },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+molvideo_init(void)
+{
+ xt_t color_bang;
+
+ REGISTER_NODE( video );
+
+ /* Bind the MOL graphic routines to the mol-color! defer */
+ color_bang = bind_noname_func(molvideo_color_bang);
+ PUSH(color_bang);
+ feval(" to mol-color!");
+}
diff --git a/qemu/roms/openbios/packages/nvram.c b/qemu/roms/openbios/packages/nvram.c
new file mode 100644
index 000000000..3182edf58
--- /dev/null
+++ b/qemu/roms/openbios/packages/nvram.c
@@ -0,0 +1,308 @@
+/*
+ * Creation Date: <2003/12/01 00:26:13 samuel>
+ * Time-stamp: <2004/01/07 19:59:53 samuel>
+ *
+ * <nvram.c>
+ *
+ * medium-level NVRAM handling
+ *
+ * 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 "arch/common/nvram.h"
+#include "packages/nvram.h"
+
+//#define CONFIG_DEBUG_NVRAM 1
+
+#ifdef CONFIG_DEBUG_NVRAM
+#define DPRINTF(fmt, args...) \
+do { printk("NVRAM: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+#define DEF_SYSTEM_SIZE 0xc10
+
+#define NV_SIG_SYSTEM 0x70
+#define NV_SIG_FREE 0x7f
+
+
+typedef struct {
+ unsigned char signature;
+ unsigned char checksum;
+ unsigned char len_hi;
+ unsigned char len_lo;
+ char name[12];
+ char data[0];
+} nvpart_t;
+
+static struct {
+ char *data;
+ int size;
+
+ nvpart_t *config;
+ int config_size;
+} nvram;
+
+
+/************************************************************************/
+/* generic */
+/************************************************************************/
+
+static unsigned int
+nvpart_checksum( nvpart_t* hdr )
+{
+ unsigned char *p = (unsigned char*)hdr;
+ int i, val = p[0];
+
+ for( i=2; i<16; i++ ) {
+ val += p[i];
+ if( val > 255 )
+ val = (val - 256 + 1) & 0xff;
+ }
+ return val;
+}
+
+static inline int
+nvpart_size( nvpart_t *p )
+{
+ return (p->len_lo | ((int)p->len_hi<<8)) * 16;
+}
+
+static int
+next_nvpart( nvpart_t **p )
+{
+ nvpart_t *end = (nvpart_t*)(nvram.data + nvram.size);
+ int len;
+
+ if( !*p ) {
+ *p = (nvpart_t*)nvram.data;
+ return 1;
+ }
+
+ if( !(len=nvpart_size(*p)) ) {
+ printk("invalid nvram partition length\n");
+ return -1;
+ }
+ *p = (nvpart_t*)((char*)*p + len);
+ if( *p < end )
+ return 1;
+ if( *p == end )
+ return 0;
+ return -1;
+}
+
+static void
+create_free_part( char *ptr, int size )
+{
+ nvpart_t *nvp = (nvpart_t*)ptr;
+ memset( nvp, 0, size );
+
+ strncpy( nvp->name, "777777777777", sizeof(nvp->name) );
+ nvp->signature = NV_SIG_FREE;
+ nvp->len_hi = (size /16) >> 8;
+ nvp->len_lo = size /16;
+ nvp->checksum = nvpart_checksum(nvp);
+}
+
+static int
+create_nv_part( int signature, const char *name, int size )
+{
+ nvpart_t *p = NULL;
+ int fs;
+
+ while( next_nvpart(&p) > 0 ) {
+ if( p->signature != NV_SIG_FREE )
+ continue;
+
+ fs = nvpart_size( p );
+ if( fs < size )
+ size = fs;
+ p->signature = signature;
+ memset( p->name, 0, sizeof(p->name) );
+ strncpy( p->name, name, sizeof(p->name) );
+ p->len_hi = (size>>8)/16;
+ p->len_lo = size/16;
+ p->checksum = nvpart_checksum(p);
+ if( fs > size ) {
+ char *fp = (char*)p + size;
+ create_free_part( fp, fs-size );
+ }
+ return size;
+ }
+ printk("create-failed\n");
+ return -1;
+}
+
+static void
+zap_nvram( void )
+{
+ create_free_part( nvram.data, nvram.size );
+ create_nv_part( NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE );
+}
+
+#if 0
+static void
+show_partitions( void )
+{
+ nvpart_t *p = NULL;
+ char buf[13];
+
+ while( next_nvpart(&p) > 0 ) {
+ memcpy( buf, p->name, sizeof(p->name) );
+ buf[12] = 0;
+ printk("[%02x] %-13s: %03x\n",
+ p->signature, buf, nvpart_size(p));
+ }
+}
+#endif
+
+void
+update_nvram( void )
+{
+ PUSH( pointer2cell(nvram.config->data) );
+ PUSH( nvram.config_size );
+ fword("nvram-store-configs");
+ arch_nvram_put( nvram.data );
+}
+
+void
+nvconf_init( void )
+{
+ int once=0;
+
+ /* initialize nvram structure completely */
+ nvram.config = NULL;
+ nvram.config_size = 0;
+
+ nvram.size = arch_nvram_size();
+ nvram.data = malloc( nvram.size );
+ arch_nvram_get( nvram.data );
+
+ bind_func( "update-nvram", update_nvram );
+
+ for( ;; ) {
+ nvpart_t *p = NULL;
+ int err;
+
+ while( (err=next_nvpart(&p)) > 0 ) {
+ if( nvpart_checksum(p) != p->checksum ) {
+ err = -1;
+ break;
+ }
+ if( p->signature == NV_SIG_SYSTEM ) {
+ nvram.config = p;
+ nvram.config_size = nvpart_size(p) - 0x10;
+
+ if( !once++ ) {
+ PUSH( pointer2cell(p->data) );
+ PUSH( nvram.config_size );
+ fword("nvram-load-configs");
+ }
+ }
+ }
+ if( err || !nvram.config ) {
+ printk("nvram error detected, zapping pram\n");
+ zap_nvram();
+ if( !once++ )
+ fword("set-defaults");
+ continue;
+ }
+ break;
+ }
+}
+
+
+/************************************************************************/
+/* nvram */
+/************************************************************************/
+
+typedef struct {
+ unsigned int mark_hi;
+ unsigned int mark_lo;
+} nvram_ibuf_t;
+
+DECLARE_UNNAMED_NODE( nvram, INSTALL_OPEN, sizeof(nvram_ibuf_t ));
+
+/* ( pos_lo pos_hi -- status ) */
+static void
+nvram_seek( nvram_ibuf_t *nd )
+{
+ int pos_hi = POP();
+ int pos_lo = POP();
+
+ DPRINTF("seek %08x %08x\n", pos_hi, pos_lo );
+ nd->mark_lo = pos_lo;
+ nd->mark_hi = pos_hi;
+
+ if( nd->mark_lo >= nvram.size ) {
+ PUSH(-1);
+ return;
+ }
+
+ /* 0=success, -1=failure (1=legacy success) */
+ PUSH(0);
+}
+
+/* ( addr len -- actual ) */
+static void
+nvram_read( nvram_ibuf_t *nd )
+{
+ int len = POP();
+ char *p = (char*)cell2pointer(POP());
+ int n=0;
+
+ while( nd->mark_lo < nvram.size && n < len ) {
+ *p++ = nvram.data[nd->mark_lo++];
+ n++;
+ }
+ PUSH(n);
+ DPRINTF("read %p %x -- %x\n", p, len, n);
+}
+
+/* ( addr len -- actual ) */
+static void
+nvram_write( nvram_ibuf_t *nd )
+{
+ int len = POP();
+ char *p = (char*)cell2pointer(POP());
+ int n=0;
+
+ while( nd->mark_lo < nvram.size && n < len ) {
+ nvram.data[nd->mark_lo++] = *p++;
+ n++;
+ }
+ PUSH(n);
+ DPRINTF("write %p %x -- %x\n", p, len, n );
+}
+
+/* ( -- size ) */
+static void
+nvram_size( __attribute__((unused)) nvram_ibuf_t *nd )
+{
+ DPRINTF("nvram_size %d\n", nvram.size);
+ PUSH( nvram.size );
+}
+
+NODE_METHODS( nvram ) = {
+ { "size", (void*)nvram_size },
+ { "read", (void*)nvram_read },
+ { "write", (void*)nvram_write },
+ { "seek", (void*)nvram_seek },
+};
+
+
+void
+nvram_init( const char *path )
+{
+ nvconf_init();
+
+ REGISTER_NAMED_NODE( nvram, path );
+}
diff --git a/qemu/roms/openbios/packages/packages.h b/qemu/roms/openbios/packages/packages.h
new file mode 100644
index 000000000..1ed6f1caa
--- /dev/null
+++ b/qemu/roms/openbios/packages/packages.h
@@ -0,0 +1,36 @@
+/*
+ * Creation Date: <2003/12/23 00:32:12 samuel>
+ * Time-stamp: <2003/12/28 14:47:02 samuel>
+ *
+ * <packages.h>
+ *
+ * Package initialization
+ *
+ * Copyright (C) 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
+ * version 2
+ *
+ */
+
+#ifndef _H_MODULES
+#define _H_MODULES
+
+extern void deblocker_init( void );
+extern void disklabel_init( void );
+extern void files_init( void );
+extern void iso9660_init( void );
+extern void hfsp_init( void );
+extern void hfs_init( void );
+extern void ext2_init( void );
+extern void grubfs_init( void );
+extern void macparts_init( void );
+extern void pcparts_init( void );
+extern void sunparts_init( void );
+extern void cmdline_init( void );
+extern void elf_loader_init( void );
+extern void xcoff_loader_init( void );
+extern void bootinfo_loader_init( void );
+
+#endif /* _H_MODULES */
diff --git a/qemu/roms/openbios/packages/pc-parts.c b/qemu/roms/openbios/packages/pc-parts.c
new file mode 100644
index 000000000..771923efe
--- /dev/null
+++ b/qemu/roms/openbios/packages/pc-parts.c
@@ -0,0 +1,393 @@
+/*
+ * pc partition support
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This code is based (and copied in many places) from
+ * mac partition support by 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 "libopenbios/load.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define DEBUG_PC_PARTS
+
+#ifdef DEBUG_PC_PARTS
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct {
+ xt_t seek_xt, read_xt;
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ phandle_t filesystem_ph;
+} pcparts_info_t;
+
+DECLARE_NODE( pcparts, INSTALL_OPEN, sizeof(pcparts_info_t), "+/packages/pc-parts" );
+
+#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
+#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
+
+/* three helper functions */
+
+static inline int has_pc_valid_partition(unsigned char *sect)
+{
+ /* Make sure the partition table contains at least one valid entry */
+ return (sect[0x1c2] != 0 || sect[0x1d2] != 0 || sect[0x1e2] != 0);
+}
+
+static inline int has_pc_part_magic(unsigned char *sect)
+{
+ return sect[0x1fe]==0x55 && sect[0x1ff]==0xAA;
+}
+
+static inline int is_pc_extended_part(unsigned char type)
+{
+ return type==5 || type==0xf || type==0x85;
+}
+
+/* ( open -- flag ) */
+static void
+pcparts_open( pcparts_info_t *di )
+{
+ char *str = my_args_copy();
+ char *argstr = strdup("");
+ char *parstr = strdup("");
+ int bs, parnum=-1;
+ int found = 0;
+ phandle_t ph;
+ ducell offs, size;
+
+ /* Layout of PC partition table */
+ struct pc_partition {
+ unsigned char boot;
+ unsigned char head;
+ unsigned char sector;
+ unsigned char cyl;
+ unsigned char type;
+ unsigned char e_head;
+ unsigned char e_sector;
+ unsigned char e_cyl;
+ u32 start_sect; /* unaligned little endian */
+ u32 nr_sects; /* ditto */
+ } *p, *partition;
+
+ unsigned char buf[512];
+
+ DPRINTF("pcparts_open '%s'\n", str );
+
+ /*
+ Arguments that we accept:
+ id: [0-7]
+ [(id)][,][filespec]
+ */
+
+ if ( strlen(str) ) {
+ /* Detect the arguments */
+ if ((*str >= '0' && *str <= '7') || (*str == ',')) {
+ push_str(str);
+ PUSH(',');
+ fword("left-parse-string");
+ parstr = pop_fstr_copy();
+ argstr = pop_fstr_copy();
+ } else {
+ argstr = str;
+ }
+
+ /* Convert the id to a partition number */
+ if (parstr && strlen(parstr))
+ parnum = atol(parstr);
+ }
+
+ /* Make sure argstr is not null */
+ if (argstr == NULL)
+ argstr = strdup("");
+
+ DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
+ free(parstr);
+
+ if( parnum < 0 )
+ parnum = 0;
+
+ di->filesystem_ph = 0;
+ di->read_xt = find_parent_method("read");
+ di->seek_xt = find_parent_method("seek");
+
+ SEEK( 0 );
+ if( READ(buf, 512) != 512 )
+ RET(0);
+
+ /* Check Magic */
+ if (!has_pc_part_magic(buf)) {
+ DPRINTF("pc partition magic not found.\n");
+ RET(0);
+ }
+
+ /* Actual partition data */
+ partition = (struct pc_partition *) (buf + 0x1be);
+
+ /* Make sure we use a copy accessible from an aligned pointer (some archs
+ e.g. SPARC will crash otherwise) */
+ p = malloc(sizeof(struct pc_partition));
+
+ bs = 512;
+
+ if (parnum < 4) {
+ /* primary partition */
+ partition += parnum;
+ memcpy(p, partition, sizeof(struct pc_partition));
+
+ if (p->type == 0 || is_pc_extended_part(p->type)) {
+ DPRINTF("partition %d does not exist\n", parnum+1 );
+ RET( 0 );
+ }
+
+ offs = (long long)(__le32_to_cpu(p->start_sect)) * bs;
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ size = (long long)(__le32_to_cpu(p->nr_sects)) * bs;
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ DPRINTF("Primary partition at sector %x\n", __le32_to_cpu(p->start_sect));
+
+ found = 1;
+ } else {
+ /* Extended partition */
+ int i, cur_part;
+ unsigned long ext_start, cur_table;
+
+ /* Search for the extended partition
+ * which contains logical partitions */
+ for (i = 0; i < 4; i++) {
+ if (is_pc_extended_part(p[i].type))
+ break;
+ }
+
+ if (i >= 4) {
+ DPRINTF("Extended partition not found\n");
+ RET( 0 );
+ }
+
+ DPRINTF("Extended partition at %d\n", i+1);
+
+ /* Visit each logical partition labels */
+ ext_start = __le32_to_cpu(p[i].start_sect);
+ cur_table = ext_start;
+ cur_part = 4;
+
+ while (cur_part <= parnum) {
+ DPRINTF("cur_part=%d at %lx\n", cur_part, cur_table);
+
+ SEEK( cur_table * bs );
+ if( READ(buf, sizeof(512)) != sizeof(512) )
+ RET( 0 );
+
+ if (!has_pc_part_magic(buf)) {
+ DPRINTF("Extended partition has no magic\n");
+ break;
+ }
+
+ /* Read the extended partition, making sure we are aligned again */
+ partition = (struct pc_partition *) (buf + 0x1be);
+ memcpy(p, partition, sizeof(struct pc_partition));
+
+ /* First entry is the logical partition */
+ if (cur_part == parnum) {
+ if (p->type == 0) {
+ DPRINTF("Partition %d is empty\n", parnum+1);
+ RET( 0 );
+ }
+
+ offs = (long long)(cur_table+__le32_to_cpu(p->start_sect)) * bs;
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ size = (long long)__le32_to_cpu(p->nr_sects) * bs;
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ found = 1;
+ break;
+ }
+
+ /* Second entry is link to next partition */
+ if (!is_pc_extended_part(p[1].type)) {
+ DPRINTF("no link\n");
+ break;
+ }
+
+ cur_table = ext_start + __le32_to_cpu(p[1].start_sect);
+ cur_part++;
+ }
+
+ if (!found) {
+ DPRINTF("Logical partition %d does not exist\n", parnum+1);
+ RET( 0 );
+ }
+ }
+
+ free(p);
+
+ if (found) {
+ /* We have a valid partition - so probe for a filesystem at the current offset */
+ DPRINTF("pc-parts: about to probe for fs\n");
+ DPUSH( offs );
+ PUSH_ih( my_parent() );
+ parword("find-filesystem");
+ DPRINTF("pc-parts: done fs probe\n");
+
+ ph = POP_ph();
+ if( ph ) {
+ DPRINTF("pc-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
+ di->filesystem_ph = ph;
+
+ /* If we have been asked to open a particular file, interpose the filesystem package with
+ the passed filename as an argument */
+ if (strlen(argstr)) {
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+ } else {
+ DPRINTF("pc-parts: no filesystem found; bypassing misc-files interpose\n");
+ }
+
+ free( str );
+ RET( -1 );
+ } else {
+ DPRINTF("pc-parts: unable to locate partition\n");
+
+ free( str );
+ RET( 0 );
+ }
+}
+
+/* ( block0 -- flag? ) */
+static void
+pcparts_probe( pcparts_info_t *dummy )
+{
+ unsigned char *buf = (unsigned char *)cell2pointer(POP());
+
+ DPRINTF("probing for PC partitions\n");
+
+ /* We also check that at least one valid partition exists; this is because
+ some CDs seem broken in that they have a partition table but it is empty
+ e.g. MorphOS. */
+ RET ( has_pc_part_magic(buf) && has_pc_valid_partition(buf) );
+}
+
+/* ( -- type offset.d size.d ) */
+static void
+pcparts_get_info( pcparts_info_t *di )
+{
+ DPRINTF("PC get_info\n");
+ PUSH( -1 ); /* no type */
+ PUSH( di->offs_lo );
+ PUSH( di->offs_hi );
+ PUSH( di->size_lo );
+ PUSH( di->size_hi );
+}
+
+static void
+pcparts_block_size( __attribute__((unused))pcparts_info_t *di )
+{
+ PUSH(512);
+}
+
+static void
+pcparts_initialize( pcparts_info_t *di )
+{
+ fword("register-partition-package");
+}
+
+/* ( pos.d -- status ) */
+static void
+pcparts_seek(pcparts_info_t *di )
+{
+ long long pos = DPOP();
+ long long offs, size;
+
+ DPRINTF("pcparts_seek %llx:\n", pos);
+
+ /* Seek is invalid if we reach the end of the device */
+ size = ((ducell)di->size_hi << BITS) | di->size_lo;
+ if (pos > size)
+ RET( -1 );
+
+ /* Calculate the seek offset for the parent */
+ offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
+ offs += pos;
+ DPUSH(offs);
+
+ DPRINTF("pcparts_seek parent offset %llx:\n", offs);
+
+ call_package(di->seek_xt, my_parent());
+}
+
+/* ( buf len -- actlen ) */
+static void
+pcparts_read(pcparts_info_t *di )
+{
+ DPRINTF("pcparts_read\n");
+
+ /* Pass the read back up to the parent */
+ call_package(di->read_xt, my_parent());
+}
+
+/* ( addr -- size ) */
+static void
+pcparts_load( __attribute__((unused))pcparts_info_t *di )
+{
+ /* Invoke the loader */
+ load(my_self());
+}
+
+/* ( pathstr len -- ) */
+static void
+pcparts_dir( pcparts_info_t *di )
+{
+ if ( di->filesystem_ph ) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("pc-parts: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( pcparts ) = {
+ { "probe", pcparts_probe },
+ { "open", pcparts_open },
+ { "seek", pcparts_seek },
+ { "read", pcparts_read },
+ { "load", pcparts_load },
+ { "dir", pcparts_dir },
+ { "get-info", pcparts_get_info },
+ { "block-size", pcparts_block_size },
+ { NULL, pcparts_initialize },
+};
+
+void
+pcparts_init( void )
+{
+ REGISTER_NODE( pcparts );
+}
diff --git a/qemu/roms/openbios/packages/sun-parts.c b/qemu/roms/openbios/packages/sun-parts.c
new file mode 100644
index 000000000..16b281b6e
--- /dev/null
+++ b/qemu/roms/openbios/packages/sun-parts.c
@@ -0,0 +1,343 @@
+/*
+ * Sun (Sparc32/64) partition support
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This code is based (and copied in many places) from
+ * mac partition support by 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 "libopenbios/load.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define DEBUG_SUN_PARTS
+
+#ifdef DEBUG_SUN_PARTS
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct {
+ xt_t seek_xt, read_xt;
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ int type;
+ phandle_t filesystem_ph;
+} sunparts_info_t;
+
+DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" );
+
+#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
+#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
+
+/* Layout of SUN partition table */
+struct sun_disklabel {
+ uint8_t info[128]; /* Informative text string */
+ uint8_t spare0[14];
+ struct sun_info {
+ uint16_t id;
+ uint16_t flags;
+ } infos[8];
+ uint8_t spare[246]; /* Boot information etc. */
+ uint16_t rspeed; /* Disk rotational speed */
+ uint16_t pcylcount; /* Physical cylinder count */
+ uint16_t sparecyl; /* extra sects per cylinder */
+ uint8_t spare2[4]; /* More magic... */
+ uint16_t ilfact; /* Interleave factor */
+ uint16_t ncyl; /* Data cylinder count */
+ uint16_t nacyl; /* Alt. cylinder count */
+ uint16_t ntrks; /* Tracks per cylinder */
+ uint16_t nsect; /* Sectors per track */
+ uint8_t spare3[4]; /* Even more magic... */
+ struct sun_partition {
+ uint32_t start_cylinder;
+ uint32_t num_sectors;
+ } partitions[8];
+ uint16_t magic; /* Magic number */
+ uint16_t csum; /* Label xor'd checksum */
+};
+
+/* two helper functions */
+
+static inline int
+has_sun_part_magic(unsigned char *sect)
+{
+ struct sun_disklabel *p = (struct sun_disklabel *)sect;
+ uint16_t csum, *ush, tmp16;
+
+ if (__be16_to_cpu(p->magic) != 0xDABE)
+ return 0;
+
+ csum = 0;
+ for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) {
+ tmp16 = __be16_to_cpu(*ush);
+ csum ^= tmp16;
+ }
+ return csum == 0;
+}
+
+/* ( open -- flag ) */
+static void
+sunparts_open( sunparts_info_t *di )
+{
+ char *str = my_args_copy();
+ char *argstr = NULL;
+ char *parstr = NULL;
+ int parnum = -1;
+ unsigned char buf[512];
+ struct sun_disklabel *p;
+ unsigned int i, bs;
+ ducell offs, size;
+ phandle_t ph;
+
+ DPRINTF("sunparts_open '%s'\n", str );
+
+ /*
+ Arguments that we accept:
+ id: [0-7] | [a-h]
+ [(id)][,][filespec]
+ */
+
+ if ( str && strlen(str) ) {
+ /* Detect the arguments */
+ if ((*str >= '0' && *str <= '9') || (*str >= 'a' && *str < ('a' + 8)) || (*str == ',')) {
+ push_str(str);
+ PUSH(',');
+ fword("left-parse-string");
+ parstr = pop_fstr_copy();
+ argstr = pop_fstr_copy();
+ } else {
+ argstr = str;
+ }
+
+ /* Convert the id to a partition number */
+ if (parstr && strlen(parstr)) {
+ if (parstr[0] >= 'a' && parstr[0] < ('a' + 8))
+ parnum = parstr[0] - 'a';
+ else
+ parnum = atol(parstr);
+ }
+ }
+
+ /* Make sure argstr is not null */
+ if (argstr == NULL)
+ argstr = strdup("");
+
+ DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
+
+ di->filesystem_ph = 0;
+ di->read_xt = find_parent_method("read");
+ di->seek_xt = find_parent_method("seek");
+
+ SEEK( 0 );
+ if (READ(buf, 512) != 512) {
+ free(str);
+ RET(0);
+ }
+
+ /* Check Magic */
+ if (!has_sun_part_magic(buf)) {
+ DPRINTF("Sun partition magic not found.\n");
+ free(str);
+ RET(0);
+ }
+
+ bs = 512;
+ /* get partition data */
+ p = (struct sun_disklabel *)buf;
+
+ for (i = 0; i < 8; i++) {
+ DPRINTF("%c: %d + %d, id %x, flags %x\n", 'a' + i,
+ __be32_to_cpu(p->partitions[i].start_cylinder),
+ __be32_to_cpu(p->partitions[i].num_sectors),
+ __be16_to_cpu(p->infos[i].id),
+ __be16_to_cpu(p->infos[i].flags));
+ }
+
+ if (parnum < 0)
+ parnum = 0;
+
+ DPRINTF("Selected partition %d\n", parnum);
+
+ offs = (long long)__be32_to_cpu(p->partitions[parnum].start_cylinder) *
+ __be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs;
+
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+ size = (long long)__be32_to_cpu(p->partitions[parnum].num_sectors) * bs;
+ if (size == 0) {
+ DPRINTF("Partition size is 0, exiting\n");
+ free(str);
+ RET(0);
+ }
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+ di->type = __be16_to_cpu(p->infos[parnum].id);
+
+ DPRINTF("Found Sun partition, offs %lld size %lld\n",
+ (long long)offs, (long long)size);
+
+ /* Probe for filesystem at current offset */
+ DPRINTF("sun-parts: about to probe for fs\n");
+ DPUSH( offs );
+ PUSH_ih( my_parent() );
+ parword("find-filesystem");
+ DPRINTF("sun-parts: done fs probe\n");
+
+ ph = POP_ph();
+ if( ph ) {
+ DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
+ di->filesystem_ph = ph;
+
+ /* If we have been asked to open a particular file, interpose the filesystem package with
+ the passed filename as an argument */
+ if (argstr && strlen(argstr)) {
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+ } else {
+ DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
+
+ /* Solaris Fcode boot blocks assume that the disk-label package will always
+ automatically interpose the "ufs-file-system" package if it exists! We
+ need to mimic this behaviour in order for the boot to work. */
+ push_str("ufs-file-system");
+ feval("find-package");
+ ph = POP_ph();
+
+ if (argstr && strlen(argstr) && ph) {
+ ph = POP_ph();
+ push_str(argstr);
+ PUSH_ph(ph);
+ fword("interpose");
+ }
+ }
+
+ free( str );
+ RET( -1 );
+}
+
+/* ( block0 -- flag? ) */
+static void
+sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
+{
+ unsigned char *buf = (unsigned char *)POP();
+
+ DPRINTF("probing for Sun partitions\n");
+
+ RET ( has_sun_part_magic(buf) );
+}
+
+/* ( -- type offset.d size.d ) */
+static void
+sunparts_get_info( sunparts_info_t *di )
+{
+ DPRINTF("Sun get_info\n");
+ PUSH( di->type );
+ PUSH( di->offs_lo );
+ PUSH( di->offs_hi );
+ PUSH( di->size_lo );
+ PUSH( di->size_hi );
+}
+
+static void
+sunparts_block_size( __attribute__((unused))sunparts_info_t *di )
+{
+ PUSH(512);
+}
+
+static void
+sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
+{
+ fword("register-partition-package");
+}
+
+/* ( pos.d -- status ) */
+static void
+sunparts_seek(sunparts_info_t *di )
+{
+ long long pos = DPOP();
+ long long offs, size;;
+
+ DPRINTF("sunparts_seek %llx:\n", pos);
+
+ /* Seek is invalid if we reach the end of the device */
+ size = ((ducell)di->size_hi << BITS) | di->size_lo;
+ if (pos > size)
+ RET( -1 );
+
+ /* Calculate the seek offset for the parent */
+ offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
+ offs += pos;
+ DPUSH(offs);
+
+ DPRINTF("sunparts_seek parent offset %llx:\n", offs);
+
+ call_package(di->seek_xt, my_parent());
+}
+
+/* ( buf len -- actlen ) */
+static void
+sunparts_read(sunparts_info_t *di )
+{
+ DPRINTF("sunparts_read\n");
+
+ /* Pass the read back up to the parent */
+ call_package(di->read_xt, my_parent());
+}
+
+/* ( addr -- size ) */
+static void
+sunparts_load( __attribute__((unused))sunparts_info_t *di )
+{
+ /* Invoke the loader */
+ load(my_self());
+}
+
+/* ( pathstr len -- ) */
+static void
+sunparts_dir( sunparts_info_t *di )
+{
+ if ( di->filesystem_ph) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("sun-parts: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( sunparts ) = {
+ { "probe", sunparts_probe },
+ { "open", sunparts_open },
+ { "get-info", sunparts_get_info },
+ { "block-size", sunparts_block_size },
+ { "seek", sunparts_seek },
+ { "read", sunparts_read },
+ { "load", sunparts_load },
+ { "dir", sunparts_dir },
+ { NULL, sunparts_initialize },
+};
+
+void
+sunparts_init( void )
+{
+ REGISTER_NODE( sunparts );
+}
diff --git a/qemu/roms/openbios/packages/xcoff-loader.c b/qemu/roms/openbios/packages/xcoff-loader.c
new file mode 100644
index 000000000..5213cc104
--- /dev/null
+++ b/qemu/roms/openbios/packages/xcoff-loader.c
@@ -0,0 +1,31 @@
+/*
+ *
+ * <xcoff-loader.c>
+ *
+ * XCOFF file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * from original XCOFF loader by Steven Noonan <steven@uplinklabs.net>
+ *
+ * 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 "libopenbios/xcoff_load.h"
+#include "packages.h"
+
+DECLARE_NODE(xcoff_loader, INSTALL_OPEN, 0, "+/packages/xcoff-loader" );
+
+NODE_METHODS( xcoff_loader ) = {
+ { "init-program", xcoff_init_program },
+};
+
+void xcoff_loader_init( void )
+{
+ REGISTER_NODE( xcoff_loader );
+}