Files
open-simh.simtools/extracters/rstsflx/dohook.c
Paul Koning bf7c17ab4a Add RSTSFLX V2.6. This is a file system access utility for RSTS
file systems.  It supports reading and writing as well as a number
of other operations, such as octal dump, file system initialize,
and file system check ("clean").

This was originally maintained as a Subversion repository at
svn://akdesign.dyndns.org/flx/branches/V2.6.
as suggested by Timothe Litt on the SIMH mailing list.
2016-04-27 15:00:42 -04:00

351 lines
9.1 KiB
C

/* handler for the "hook" command */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "flx.h"
#include "fldef.h"
#include "silfmt.h"
#include "dohook.h"
#include "fip.h"
#include "filename.h"
#include "fileio.h"
#include "diskio.h"
typedef struct { /* boot data pointer in boot block */
word16 lbn[2]; /* block number, LSW first */
word16 wcnt; /* word count */
} bdesc;
typedef struct { /* header of boot block */
word16 nop; /* nop required for boot */
word16 setup_br; /* go do setup and relocation code */
word16 trap4_vec[2]; /* if trap to 4, halt @ 6 w/ 10 in lights */
word16 trap10_vec[2]; /* if trap to 10, halt @ 12 w/ 14 in lights */
word16 clustr; /* 14 cluster size */
word16 csr; /* 16 csr base */
word16 devnam; /* 20 device name */
word16 jmp; /* 22 jump to start address */
word16 transfer; /* 24 transfer address (set by hook) */
byte unit; /* 26 unit # in bits <2:0> (set by boot) */
byte flags; /* 27 flags (definitions are in inidfn) */
word16 unit_csr; /* 30 unit # in bits for csr (set by boot) */
byte rc, wc; /* 32 read and write codes */
word16 function; /* 34 function code: read */
word16 blknum[2]; /* 36-40 block number to read, also spec func. */
word16 memadr[2]; /* 42-44 memory address to read into */
word16 wcnt; /* 46 word count, also spec function parameter */
word16 reset; /* 50 do a device reset */
word16 read; /* 52 do a single transfer */
word16 spec; /* 54 do a magtape special function */
} bhdr;
int stbcnt, ovrcnt; /* SIL STB and OVR table entry count */
stbent *stb = NULL; /* pointer to STB buffer */
ovrent *ovr = NULL; /* pointer to OVR buffer */
/* note 0 rather than NULL because NULL is generally defined wrong
* (causing a warning that is a nuisance though it does no harm)
*/
const char disks[][3] = { "dv","df","ds","dk","dl","dm",
"dp","db","dr","dz","dw","du",
0 };
long findsym (const char *sym)
{
word16 r50[2];
int n;
stbent *s;
ovrent *o;
cvtnametor50 (sym, r50); /* convert symbol to rad50 */
s = stb; /* point to start of stb */
for (n = 0; n < stbcnt; n++, s++)
{
if (s->name[0] == r50[0] && s->name[1] == r50[1])
{
if (s->ovnum >= ovrcnt)
{
printf ("Bad STB entry for %s\n", sym);
return (-1);
}
if (s->ovnum == 0) return (s->value);
o = &ovr[s->ovnum];
return (s->value - o->base +
(o->offset[0] << 16) + o->offset[1]);
}
}
return (-1);
}
void setptr (long blk, long size, void *buf)
{
bdesc *b;
b = (bdesc *) buf; /* point to where descriptor goes */
b->wcnt = size / 2; /* set word count */
b->lbn[0] = blk & 0xffff; /* low order LBN */
b->lbn[1] = blk >> 16; /* and high order */
}
#define SIL 074064 /* rad50 "SIL" */
int silchk (firqb *f, savsilindex *x)
{
word16 cs;
word16 *p;
p = &(x->si_sil);
if (*p != SIL) /* verify SIL marker */
{
printcurname (f);
printf (" is not a SIL\n");
return (FALSE);
}
cs = 0; /* initialize checksum */
do cs ^= *--p; /* XOR checksum of the rest */
while (p != (word16 *)x);
if (cs != 0)
{
printf ("checksum error in SIL ");
printcurname (f);
printf ("\n");
return (FALSE);
}
return (TRUE); /* it's ok */
}
/* read file data for some given byte address, and return a pointer to
* where it is. There's at least 512 valid bytes after that point.
*/
/* this routine reads data from the file, doing the full count requested
* even if it requires multiple calls to seqio. (note that seqio only
* reads a single contiguous piece of file.)
*/
void readfile (firqb *f, long count, void *buf)
{
long rcnt;
byte *b; /* workaround cc bug */
b = (byte *) buf;
while (count)
{
rcnt = seqio (f, count, rread, b);
if (rcnt == 0) return; /* eof??? */
b += rcnt; /* adjust by what we read */
count -= rcnt; /* and count also */
}
}
void *getdata (firqb *f, long address)
{
fileseek (f, address / BLKSIZE); /* seek to the right start block */
readfile (f, BLKSIZE * 2, iobuf);
return (iobuf + (address % BLKSIZE));
}
void cleanup ()
{
rumountrw ();
if (ovr != NULL) free (ovr);
ovr = NULL;
if (stb != NULL) free (stb);
stb = NULL;
return;
}
void dohook (int argc, char **argv)
{
savsilindex idx; /* SIL index buffer */
int n;
firqb hf; /* file to be hooked */
firqb bf; /* file where bootstraps are */
char *disk; /* bootstrap name */
byte bbuf[BLKSIZE]; /* boot block buffer */
bdesc *bd; /* pointer to current boot data desc */
bhdr *bh; /* pointer to boot header */
int dskio, dskioe, xxboot; /* symbols from SIL */
int dskidx; /* disk index for boot disk name */
void *btop; /* pointer to end of boot code */
short int xxent; /* xxboot table entry */
int pcoffset; /* offset to apply to entry point */
char *p;
if (argc == 0) disk = "dl";
else
{
disk = argv[0]; /* disk is first argument */
if (strlen (disk) != 2 ) {
printf ("Invalid disk name %s\n", disk);
return;
}
disk[0] = tolower (disk[0]);
if (disk[0] == 'r') disk[0] = 'd';
disk[1] = tolower (disk[1]);
}
for (dskidx = 0; ; dskidx++)
{
if (disks[dskidx] == NULL)
{
printf ("Unknown disk name %s\n", disk);
return;
}
if (strcmp (disks[dskidx], disk) == 0) break;
}
if (sw.odt != NULL) pcoffset = 2;
else if (sw.offset == NULL) pcoffset = 0;
else
{
pcoffset = strtol (sw.offset, &p, 10);
if (*p != '\0' || (pcoffset & 1) != 0)
{
printf ("Invalid offset %s\n", sw.offset);
return;
}
}
dskidx *= 2; /* make even (byte offset) */
rmountrw (); /* mount disk for read/write */
if (argc < 2) parse ("[0,1]init.sys", &hf);
else
{
if (!parse (argv[1], &hf) || hf.flags & F_WILD)
{
cleanup ();
printf ("Invalid filespec %s\n", argv[1]);
return;
}
if ((hf.flags & f_ppn) == 0)
{
hf.proj = 0;
hf.prog = 1;
}
}
if (argc < 3) memcpy (&bf, &hf, sizeof (firqb));
else {
if (!parse (argv[2], &bf) || bf.flags & F_WILD)
{
cleanup ();
printf ("Invalid filespec %s\n", argv[2]);
return;
}
if ((bf.flags & f_ppn) == 0)
{
bf.proj = 0;
bf.prog = 1;
}
}
if (initfilescan (&bf, gfddcntbl) == 0 ||
nextfile (&bf) == 0)
{
printfqbname (&bf);
printf (" not found\n");
cleanup ();
return;
}
initrandom (&bf); /* set up random access to bootfile */
seqio (&bf, sizeof(idx), rread, &idx); /* read sil index */
if (!silchk (&bf, &idx))
{
cleanup ();
return; /* quit if bad sil index */
}
stbcnt = idx.si_ent.se_stn; /* copy STB and OVR sizes */
ovrcnt = idx.si_ent.se_ovn;
if ((stb = (stbent *) malloc (UP(stbcnt * sizeof (stbent),BLKSIZE))) == NULL)
{
cleanup ();
rabort(NOMEM);
}
if ((ovr = (ovrent *) malloc (UP(ovrcnt * sizeof (ovrent),BLKSIZE))) == NULL)
{
cleanup ();
rabort(NOMEM);
}
fileseek (&bf, idx.si_ent.se_stb); /* read symbol table */
readfile (&bf, UP(stbcnt * sizeof (stbent),BLKSIZE), stb);
fileseek (&bf, idx.si_ent.se_ovb); /* read symbol table */
readfile (&bf, UP(ovrcnt * sizeof (ovrent),BLKSIZE), ovr);
memset (bbuf, 0, BLKSIZE); /* zero out boot buffer */
if ((xxboot = findsym ("xxboot")) < 0)
{
cleanup ();
printf ("Symbol XXBOOT not found\n");
return;
}
if ((dskioe = findsym ("dskioe")) < 0)
{
cleanup ();
printf ("Symbol DSKIOE not found\n");
return;
}
if ((dskio = findsym ("dskio")) < 0) dskio = dskioe - 72;
xxboot += dskidx; /* point to entry for selected disk */
xxent = *(short int *)(getdata (&bf, xxboot));
if (xxent == 0)
{
cleanup ();
printf ("No bootstrap for %s\n", disk);
return;
}
xxboot += xxent; /* point to bootstrap */
bh = (bhdr *)(getdata (&bf, xxboot)); /* read it */
n = bh->wcnt; /* get bootstrap size in bytes */
memcpy (bbuf, bh, n); /* copy that into boot buffer */
memcpy (bbuf + n, getdata (&bf, dskio), dskioe - dskio);
/* append boot mainline */
btop = bbuf + n + (dskioe - dskio);
if (initfilescan (&hf, gfddcntbl) == 0 ||
nextfile (&hf) == 0)
{
printcurname (&hf);
printf (" not found\n");
}
openfile (&hf); /* set up to read file to hook */
seqio (&bf, sizeof(idx), rread, &idx); /* read sil index */
if (!silchk (&hf, &idx))
{
cleanup ();
return; /* quit if bad sil index */
}
openfile (&hf); /* reset to start over at VBN 0 */
if (idx.usertop >= 0157000)
{
cleanup ();
printcurname (&hf);
printf (" high limit is too high (%06o)\n", idx.usertop);
return;
}
n = UP(idx.usertop + 2,BLKSIZE); /* compute byte count to boot */
((bhdr *) bbuf)->transfer = idx.initpc + pcoffset;
/* set transfer address in bootstrap */
((bhdr *) bbuf)->clustr = dcs; /* set clustersize */
bd = (bdesc *)(&bbuf[0772]); /* initialize boot desc pointer */
while (n)
{
if (--bd < (bdesc *)btop) /* check for bootstrap full */
{
cleanup ();
printcurname (&hf);
printf (" is too fragmented to hook\n");
return;
}
n -= seqio (&hf, n, setptr, bd);
}
rwrite (0, BLKSIZE, bbuf); /* write boot block */
if (sw.verbose != NULL)
{
printcurname (&hf);
if (sw.offset == NULL && sw.odt == NULL)
printf (" hooked, start PC = %06o\n", idx.initpc);
else printf (" hooked, start PC = %06o, offset %d\n",
idx.initpc + pcoffset, pcoffset);
}
cleanup (); /* clean up now */
return; /* and we're done */
}