Building a 2.11BSD tape for Supnik's emulator
Steven M. Schultz
sms at moe.2bsd.com
Sat May 27 02:26:28 AEST 2000
Hi -
> From: Markus Leypold <leypold at informatik.uni-tuebingen.de>
> I never worked with a real PDP-11. I tried to build a V7 Boot tape for
> the Supnick and still did not succeed, but I got the following impressions:
>
> * It seems, a tape also needs to contain labels for the files
> (512 Byte Records), kind of directory.
Not exactly. The boot tape consists of files with different block
sizes but has no "labels".
> Original Message:
> ---------------------------------
> I'm trying to build a 2.11BSD boot tape for Bob Supnik's emulator. I
> downloaded the tape files from Distributions/ucb/2.11BSD, and put them
> together with the following commands (on Linux):
>
> cat mtboot mtboot boot | dd of=file0 obs=512
> dd if=disklabel of=file1 obs=1024
> dd if=mkfs of=file2 obs=1024
> dd if=restor of=file3 obs=1024
> dd if=icheck of=file4 obs=1024
> dd if=root.dump of=file5 obs=10240
> dd if=file6.tar of=file6 obs=10240
> dd if=file7.tar of=file7 obs=10240
> dd if=file8.tar of=file8 obs=10240
> cat file? > boot.tape [I've verified the shell expands this
> expression to the correct file order]
So close yet so far.
You do not need to "reblock" the files - they already have the correct
sizes. What you do need to do is run a program to add the record
length information for the emulator. The emulator needs to have
"virtual" file and record mark information added.
If you look in the "usr/src/sys/pdpstand" directory you will find
a source file "makesimtape.c". This is a slightly modified version
of the 'maketape' program which 2.11 uses to create its own boot tapes.
The modifications consist of changes to add the virtual tape marks
for Bob's emulator.
I will include a copy of makesimtape.c below in case anyone has trouble
finding it in the source tree.
makesimtape should compile on almost anything (I've used it on
2.11BSD, BSD/OS, and I think FreeBSD). Compile that program. Then
create a small file (maketape.data) containing:
mtboot 1
mtboot 1
boot 1
* 1
disklabel 2
* 1
mkfs 2
* 1
restor 2
* 1
icheck 2
* 1
root.dump 20
* 1
file6.tar 20
* 1
file7.tar 20
* 1
file8.tar 20
*1
Then "makesimtape -i maketape.data -o your_tape_file" will create
the virtual tape file in 'your_tape_file'.
Actually to make sure things work (and the tape is bootable and can
run the standalone programs) all you need are the files up thru
root.dump - that is enough to load the root filesystem.
With a real tape drive you use the "maketape" program that comes
with 2.11 of course since it wants to issue ioctl calls to place
real tape marks, etc on a tape.
> It's like the bootstrap code isn't working. Or possibly I've completely
> misunderstood the proper way to build a tape image. Is there a better
> way to go about it?
Hopefully the method described above will be closer to what's
needed. it has been quite a while since I've actually created a
simulated tape so I might have left out a step or something.
Good Luck!
Steven Schultz
sms at moe.2bsd.com
=====================makesimtape.c=========================
/*
* @(#)makesimtape.c 2.1 (2.11BSD) 1998/12/31
* Hacked 'maketape.c' to write a file in a format suitable for
* use with Bob Supnik's PDP-11 simulator (V2.3) emulated tape
* driver.
*
* NOTE: a PDP-11 has to flip the shorts within the long when writing out
* the record size. Seems a PDP-11 is neither a little-endian
* machine nor a big-endian one.
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#define MAXB 30
char buf[MAXB * 512];
char name[50];
long recsz, flipped, trl();
int blksz;
int mt, fd, cnt;
struct iovec iovec[3];
struct iovec tmark[2];
void usage();
main(argc, argv)
int argc;
char *argv[];
{
int i, j = 0, k = 0;
long zero = 0;
register char *outfile = NULL, *infile = NULL;
FILE *mf;
struct stat st;
while ((i = getopt(argc, argv, "i:o:")) != EOF)
{
switch (i)
{
case 'o':
outfile = optarg;
break;
case 'i':
infile = optarg;
break;
default:
usage();
/* NOTREACHED */
}
}
if (!outfile || !infile)
usage();
/* NOTREACHED */
/*
* Stat the outfile and make sure it either 1) Does not exist, or
* 2) Exists but is a regular file.
*/
if (stat(outfile, &st) != -1 && !(S_ISREG(st.st_mode)))
errx(1, "outfile must either not exist or be a regular file");
/* NOTREACHED */
mt = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
if (mt < 0)
err(1, "Can not create %s", outfile);
/* NOTREACHED */
mf = fopen(infile, "r");
if (!mf)
err(1, "Can not open %s", infile);
/* NOTREACHED*/
tmark[0].iov_len = sizeof (long);
tmark[0].iov_base = (char *)&zero;
while (1)
{
if ((i = fscanf(mf, "%s %d", name, &blksz))== EOF)
exit(0);
if (i != 2) {
fprintf(stderr,"Help! Scanf didn't read 2 things (%d)\n", i);
exit(1);
}
if (blksz <= 0 || blksz > MAXB)
{
fprintf(stderr, "Block size %u is invalid\n", blksz);
exit(1);
}
recsz = blksz * 512; /* convert to bytes */
iovec[0].iov_len = sizeof (recsz);
#ifdef pdp11
iovec[0].iov_base = (char *)&flipped;
#else
iovec[0].iov_base = (char *)&recsz;
#endif
iovec[1].iov_len = (int)recsz;
iovec[1].iov_base = buf;
iovec[2].iov_len = iovec[0].iov_len;
iovec[2].iov_base = iovec[0].iov_base;
if (strcmp(name, "*") == 0)
{
if (writev(mt, tmark, 1) < 0)
warn(1, "writev of pseudo tapemark failed");
k++;
continue;
}
fd = open(name, 0);
if (fd < 0)
err(1, "Can't open %s for reading", name);
/* NOTREACHED */
printf("%s: block %d, file %d\n", name, j, k);
/*
* we pad the last record with nulls
* (instead of the bell std. of padding with trash).
* this allows you to access text files on the
* tape without garbage at the end of the file.
* (note that there is no record length associated
* with tape files)
*/
while ((cnt=read(fd, buf, (int)recsz)) == (int)recsz)
{
j++;
#ifdef pdp11
flipped = trl(recsz);
#endif
if (writev(mt, iovec, 3) < 0)
err(1, "writev #1");
/* NOTREACHED */
}
if (cnt > 0)
{
j++;
bzero(buf + cnt, (int)recsz - cnt);
#ifdef pdp11
flipped = trl(recsz);
#endif
if (writev(mt, iovec, 3) < 0)
err(1, "writev #2");
/* NOTREACHED */
}
close(fd);
}
/*
* Write two tape marks to simulate EOT
*/
writev(mt, tmark, 1);
writev(mt, tmark, 1);
}
long
trl(l)
long l;
{
union {
long l;
short s[2];
} foo;
register short x;
foo.l = l;
x = foo.s[0];
foo.s[0] = foo.s[1];
foo.s[1] = x;
return(foo.l);
}
void
usage()
{
fprintf(stderr, "usage: makesimtape -o outfilefile -i inputfile\n");
exit(1);
}
More information about the TUHS
mailing list