/********************************************************************	Loader program for a F68K image file			This loader tries to open a file F68K.CFG which	holds information about the F68K system to be loaded.	It is possible to use another CFG-File by invoking its name	in command line: os9lader [ xxx.CFG ].		Works only correct if FORTH-Kernel lays address of FORTH-Paras 	down on stack before calling I/O 	(see CHANGES.TXT 14.11.91)	26FEB92 TB********************************************************************/#define DEBUG#include <stdio.h> #define CODESIZE 0x20000L#define DATASIZE 0x20000L#define TIBSIZE  2048#define MAX_DEVICES 10#define BPB  2048                 /* Bytes Per Block */#define FILENAME_MAX 64#define FALSE (0)#define TRUE (-1)long key_quest();long key();void emit();long r_w();long writesys();long readsys();void read_paras();void read_segments();void keymode();void linemode();char devicename[MAX_DEVICES][FILENAME_MAX];FILE* device[MAX_DEVICES];FILE* infile;long roottable[MAX_DEVICES * 2 + 1]; long codesz = CODESIZE;long datasz = DATASIZE; char imagename[FILENAME_MAX]   = "F68K.IMG";char outfilename[FILENAME_MAX] = "F68K.OUT";char cfgname[FILENAME_MAX]     = "F68K.CFG";char key_buffer;handle_signal(signum)int signum;{	linemode();	exit(0);}void main(argc,argv)int argc;char *argv[];{char *codeseg,*dataseg;void (*f68k)();static long _keytable[]		= {1, key};static long _keyqtable[]	= {1, key_quest};static long _emittable[]	= {1, emit};static long _r_wtable[]		= {1, r_w};static long _readsystable[]	= {1, readsys};static long _writesystable[]	= {1, writesys};struct _forthparas{	long registers[16];	/* to be filled by F68K *//*	void *forthregs[4]; */	/* A3,A5,A6,A7 for F68K */	void *data;		/* A3 */	void *code;		/* A5 */	void *datastack;	/* A6 */	void *retstack;  	/* A7 */	void *TIBptr;	long codelen;	long datalen;	void *emittable;	void *keytable;	long *keyqtable;	long *r_wtable;	long *readsystable;	long *writesystable;	long *roottable;} forthparas;  	forthparas.emittable 	= _emittable;	forthparas.keytable 	= _keytable;	forthparas.keyqtable 	= _keyqtable;	forthparas.r_wtable 	= _r_wtable;	forthparas.readsystable = _readsystable;	forthparas.writesystable= _writesystable;	forthparas.roottable 	= roottable;	if(argc==2)  strcpy(cfgname,argv[1]);        read_paras(roottable);        forthparas.codelen	= codesz;        forthparas.datalen	= datasz;                read_segments(&codeseg,&dataseg);        forthparas.code		= codeseg;        forthparas.data		= dataseg;        forthparas.datastack = (void*)((long)dataseg+datasz-TIBSIZE);        forthparas.retstack	 = (void*)((long)dataseg+datasz);        forthparas.TIBptr	 = (void*)((long)dataseg+datasz-TIBSIZE);		keymode();		intercept(handle_signal);		f68k=(void*)codeseg;                (*f68k)(0,0,&forthparas);#asm		movea.l 56(a7),a6#endasm		linemode();		exit(0);}/*************************************************************************                                                                       **       the F68K I/O-functions                                          **                                                                       *************************************************************************/long key_quest()   {#asm		movea.l 20(a7),a6		movea.l 56(a6),a6#endasm		return (_gs_rdy(fileno(stdin)) != -1) ? TRUE : FALSE ;}long key()   {  #asm		movea.l 20(a7),a6		movea.l 56(a6),a6#endasm		read(fileno(stdin),&key_buffer,1);		return (key_buffer);}void emit(chars)   char chars;{#asm		move.l	20(a7),(a7)		movea.l 24(a7),a6		movea.l 56(a6),a6#endasm		chars &= 0x7f;		write(1,&chars,1);}#include <sgstat.h>struct sgbuf  ttys, ttysnew;    /* for terminal mode setting */static lmode = 0;#define M_KEY 1#define M_LINE 2void initline(){	if (lmode)		return;	if (_gs_opt(0, &ttys) < 0)		return;	_strass(&ttysnew, &ttys, sizeof(struct sgbuf));	ttysnew.sg_echo = 0; 	/* set for no echoing */ 	ttysnew.sg_case = 0; 	/* allow either case */	ttysnew.sg_delete = 0;	/* no crt line erasing */	ttysnew.sg_pause = 0;	/* no page mode */	ttysnew.sg_bspch = 0;	/* no backspace editing */	ttysnew.sg_dlnch = 0;	/* no delete line */	ttysnew.sg_eorch = 20;	/* end of record character ^T in case of bomb */	ttysnew.sg_eofch = 0;	/* no end of file character */	ttysnew.sg_rlnch = 0;	/* no repeat line character */	ttysnew.sg_dulnch = 0;	/* no duplicate line character */	ttysnew.sg_psch = 0;	/* no pause character */	ttysnew.sg_kbich = 3;	/* ^C keyboard interrupt character */	ttysnew.sg_kbach = 0;	/* no keyboard abort character */	ttysnew.sg_xon = 0;		/* no XON character */	ttysnew.sg_xoff = 0;	/* no XOFF character */	ttysnew.sg_tabcr = 0;	/* no tab character */}void linemode(){	initline();	if (lmode != M_LINE) 	{		_ss_opt(0, &ttys);		lmode = M_LINE;	}}void keymode(){	initline();	if (lmode != M_KEY) 	{		_ss_opt(0, &ttysnew);		lmode = M_KEY;	}}long r_w(buffer,block,flg)   long buffer,block,flg;{int i, dev;long rootblk=0L, maxblock=0L;#asm		move.l	20(a7),(a7)		move.l  24(a7),4(a7)		move.l  28(a7),20(a7)		movea.l 32(a7),a6		movea.l 56(a6),a6#endasm        for(i=0; i<roottable[0]; i++)  /* find device */                if( (roottable[2*i+1] >= rootblk) && (block >= roottable[2*i+1]))                        {                        maxblock += roottable[2*i+2];                        rootblk = roottable[2*i+1];                        dev = i;                        }                                               if(block >= maxblock)   /* block in range? */        	{         	goto bad;         	}        if( fseek(device[dev],(block-rootblk)*BPB,0))                {				goto bad;                }        if(flg!=0L)                  {                if( !fwrite(buffer,BPB,1,device[dev]))                        {                        goto bad;                        }                }        else                {                if( !fread(buffer,BPB,1,device[dev]))                        {                        goto bad;                        }                }                return TRUE;        bad:        #ifdef DEBUGprintf("%ld\n*** F68K loader warning: tried to reach physical block: ",block," ***\n");#endif	return FALSE;  }long readsys(buffer,count)unsigned long buffer, count;{#asm		move.l	20(a7),(a7)		move.l  24(a7),4(a7)		movea.l 28(a7),a6		movea.l 56(a6),a6#endasm          if ( fread(buffer,count,1,infile) != 1)                {                return FALSE;                }                                return TRUE;}long writesys(buffer,count)unsigned long buffer, count;{static FILE *out = NULL;#asm		move.l	20(a7),(a7)		move.l  24(a7),4(a7)		movea.l 28(a7),a6		movea.l 56(a6),a6#endasm        if(!out)       	if( (out = fopen(outfilename,"w"))== NULL)                   	{               	return FALSE;               	}        if ( fwrite(buffer,count,1,out) != 1)                {                return FALSE;                }		fflush(out);                                return TRUE;}/*************************************************************************       end of I/O functions                                            *************************************************************************/void read_paras(roottable)long *roottable;{FILE *paras;int devices, dev;long devicesize[MAX_DEVICES];char infilename[FILENAME_MAX];int i;long startblock = 0;        if( (paras=fopen(cfgname,"r"))==NULL)                  {                fprintf(stderr,"*** F68K loader warning: configuration file F68K.CFG not found\n");                return;                }        if( !fscanf(paras,"image: %s%*d\n",imagename))                fprintf(stderr,"*** F68K loader warning: no imagefile given in F68K.CFG, suppose F68K.IMG\n");        if( !fscanf(paras,"code: 0x%lx%*d\n",&codesz))                fprintf(stderr,"*** F68K loader warning: no codesize given in F68K.CFG, suppose %ld\n",CODESIZE);        if( !fscanf(paras,"data: 0x%lx%*d\n",&datasz))                fprintf(stderr,"*** F68K loader warning: no datasize given in F68K.CFG, suppose %ld\n",DATASIZE);        if( !fscanf(paras,"input: %s%*d\n", infilename))                {                fprintf(stderr,"*** F68K loader warning: no input file given in F68K.CFG, suppose F68K.IN\n");                strcpy(infilename,"F68K.IN");                }        if( (infile = fopen(infilename,"r"))==NULL)                fprintf(stderr,"*** F68K loader warning: cannot open input file, READSYS not available\n");        if( !fscanf(paras,"output: %s%*d\n", outfilename))                fprintf(stderr,"*** F68K loader warning: no output file given in F68K.CFG, suppose F68K.OUT\n");        if( !fscanf(paras,"devices: %d%*d\n",&devices))                fprintf(stderr,"*** F68K loader warning: no number of devices given in F68K.CFG\n");        if( devices == 0)                fprintf(stderr,"*** F68K loader warning: no block storage device available\n");        if( devices > MAX_DEVICES )                {                fprintf(stderr,"*** F68K loader error: too much devices (max. %d devices available)\n");                 exit(0);                }        for(i=0; i<devices; i++)                {                if( fscanf(paras,"d%d: ",&dev) && (dev>=0) && (dev<MAX_DEVICES))                        fscanf(paras,"%s%*d\n",devicename[dev]);                else                        {                        fprintf(stderr,"*** F68K loader error: invalid device specification\n");                        exit(0);                        }                if( (devicesize[dev]=fsize(devicename[dev])) != -1L)                        {                        device[dev] = fopen(devicename[dev],"r+");                        roottable[2*dev+1] = startblock;                        roottable[2*(dev+1)] = devicesize[dev]/BPB;                        startblock += devicesize[dev]/BPB;                              }                else                        {                        fprintf(stderr,"*** F68K loader warning: device D%d: cannot be accessed\n",dev);                                roottable[2*dev+1] = -1;                        roottable[2*(dev+1)] = 0;                        }                }        roottable[0] = devices;}long fsize(filename)char *filename;{FILE *fnr;long size;	if((fnr=fopen(filename,"r")) == 0) return(-1L);	size=lseek(fileno(fnr),0,2);	fclose(fnr);	return(size);}void read_segments(codeseg,dataseg)char **codeseg, **dataseg;{       FILE *image;struct header{        short magic;        unsigned long codesize;        unsigned long datasize;        short dont_care[9];} header;        if( ((*codeseg = malloc(codesz)) == NULL) |             ((*dataseg = malloc(datasz)) == NULL))                   {                fprintf(stderr,"*** F68K loader error:  segments allocation fault\n");                exit(-1);                }        if( (image=fopen(imagename,"r")) == NULL )                {                fprintf(stderr,"*** F68K loader error:  image file not found\n");                exit(-1);                }                if( fread(&header,(long)sizeof(header),1,image) != 1)                {                fprintf(stderr,"*** F68K loader error:  image file read error (header)\n");                exit(-1);                }	if(header.magic != (256*'J'+'P')) 		{		fprintf(stderr,"*** F68K loader error:  this is not an F68K image\n");		exit(-1);		}        if( fread(*codeseg,header.codesize,1,image) != 1)                {                fprintf(stderr,"*** F68K loader error:  image file read error (code)\n");                exit(-1);                }        if( fread(*dataseg,header.datasize,1,image) != 1)                {                fprintf(stderr,"*** F68K loader error:  image file read error (data)\n");                exit(-1);                }}