diff options
Diffstat (limited to 'qemu/roms/openbios/packages')
-rw-r--r-- | qemu/roms/openbios/packages/bootinfo-loader.c | 29 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/build.xml | 23 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/cmdline.c | 415 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/cmdline.fs | 41 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/deblocker.c | 221 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/disk-label.c | 245 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/disk-label.fs | 102 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/elf-loader.c | 31 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/init.c | 67 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/mac-parts.c | 447 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/mac-parts.h | 88 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/molvideo.c | 124 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/nvram.c | 308 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/packages.h | 36 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/pc-parts.c | 393 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/sun-parts.c | 343 | ||||
-rw-r--r-- | qemu/roms/openbios/packages/xcoff-loader.c | 31 |
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 ); +} |