diff options
Diffstat (limited to 'roms/openbios/packages')
| -rw-r--r-- | roms/openbios/packages/bootinfo-loader.c | 29 | ||||
| -rw-r--r-- | roms/openbios/packages/build.xml | 23 | ||||
| -rw-r--r-- | roms/openbios/packages/cmdline.c | 415 | ||||
| -rw-r--r-- | roms/openbios/packages/cmdline.fs | 41 | ||||
| -rw-r--r-- | roms/openbios/packages/deblocker.c | 221 | ||||
| -rw-r--r-- | roms/openbios/packages/disk-label.c | 245 | ||||
| -rw-r--r-- | roms/openbios/packages/disk-label.fs | 102 | ||||
| -rw-r--r-- | roms/openbios/packages/elf-loader.c | 31 | ||||
| -rw-r--r-- | roms/openbios/packages/init.c | 67 | ||||
| -rw-r--r-- | roms/openbios/packages/mac-parts.c | 447 | ||||
| -rw-r--r-- | roms/openbios/packages/mac-parts.h | 88 | ||||
| -rw-r--r-- | roms/openbios/packages/molvideo.c | 124 | ||||
| -rw-r--r-- | roms/openbios/packages/nvram.c | 308 | ||||
| -rw-r--r-- | roms/openbios/packages/packages.h | 36 | ||||
| -rw-r--r-- | roms/openbios/packages/pc-parts.c | 393 | ||||
| -rw-r--r-- | roms/openbios/packages/sun-parts.c | 343 | ||||
| -rw-r--r-- | roms/openbios/packages/xcoff-loader.c | 31 | 
17 files changed, 2944 insertions, 0 deletions
diff --git a/roms/openbios/packages/bootinfo-loader.c b/roms/openbios/packages/bootinfo-loader.c new file mode 100644 index 00000000..1497227c --- /dev/null +++ b/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/roms/openbios/packages/build.xml b/roms/openbios/packages/build.xml new file mode 100644 index 00000000..bf49099c --- /dev/null +++ b/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/roms/openbios/packages/cmdline.c b/roms/openbios/packages/cmdline.c new file mode 100644 index 00000000..ea6bca3d --- /dev/null +++ b/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/roms/openbios/packages/cmdline.fs b/roms/openbios/packages/cmdline.fs new file mode 100644 index 00000000..70d3aa2d --- /dev/null +++ b/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/roms/openbios/packages/deblocker.c b/roms/openbios/packages/deblocker.c new file mode 100644 index 00000000..50071854 --- /dev/null +++ b/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/roms/openbios/packages/disk-label.c b/roms/openbios/packages/disk-label.c new file mode 100644 index 00000000..1ca9bd86 --- /dev/null +++ b/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/roms/openbios/packages/disk-label.fs b/roms/openbios/packages/disk-label.fs new file mode 100644 index 00000000..8354f878 --- /dev/null +++ b/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/roms/openbios/packages/elf-loader.c b/roms/openbios/packages/elf-loader.c new file mode 100644 index 00000000..1665f0d0 --- /dev/null +++ b/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/roms/openbios/packages/init.c b/roms/openbios/packages/init.c new file mode 100644 index 00000000..bff8558a --- /dev/null +++ b/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/roms/openbios/packages/mac-parts.c b/roms/openbios/packages/mac-parts.c new file mode 100644 index 00000000..16c87caf --- /dev/null +++ b/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/roms/openbios/packages/mac-parts.h b/roms/openbios/packages/mac-parts.h new file mode 100644 index 00000000..acfcbe04 --- /dev/null +++ b/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/roms/openbios/packages/molvideo.c b/roms/openbios/packages/molvideo.c new file mode 100644 index 00000000..787c4dc0 --- /dev/null +++ b/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/roms/openbios/packages/nvram.c b/roms/openbios/packages/nvram.c new file mode 100644 index 00000000..3182edf5 --- /dev/null +++ b/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/roms/openbios/packages/packages.h b/roms/openbios/packages/packages.h new file mode 100644 index 00000000..1ed6f1ca --- /dev/null +++ b/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/roms/openbios/packages/pc-parts.c b/roms/openbios/packages/pc-parts.c new file mode 100644 index 00000000..771923ef --- /dev/null +++ b/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/roms/openbios/packages/sun-parts.c b/roms/openbios/packages/sun-parts.c new file mode 100644 index 00000000..16b281b6 --- /dev/null +++ b/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/roms/openbios/packages/xcoff-loader.c b/roms/openbios/packages/xcoff-loader.c new file mode 100644 index 00000000..5213cc10 --- /dev/null +++ b/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 ); +}  | 
