Building a 2.11BSD tape for Supnik's emulator

Steven M. Schultz sms at
Sat May 27 02:26:28 AEST 2000

Hi -

> From: Markus Leypold <leypold at>
> 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 ( 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

	Then "makesimtape -i -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

 *	@(#)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;
			case	'i':
				infile = optarg;
				/* NOTREACHED */
	if	(!outfile || !infile)
 * 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");

	mt = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
	if	(mt < 0)
		err(1, "Can not create %s", outfile);

	mf = fopen(infile, "r");
	if	(!mf)
		err(1, "Can not open %s", infile);

	tmark[0].iov_len = sizeof (long);
	tmark[0].iov_base = (char *)&zero;

	while	(1)
		if	((i = fscanf(mf, "%s %d", name, &blksz))== EOF)
		if	(i != 2) {
			fprintf(stderr,"Help! Scanf didn't read 2 things (%d)\n", i);
		if	(blksz <= 0 || blksz > MAXB)
			fprintf(stderr, "Block size %u is invalid\n", blksz);
		recsz = blksz * 512;	/* convert to bytes */
		iovec[0].iov_len = sizeof (recsz);
#ifdef	pdp11
		iovec[0].iov_base = (char *)&flipped;
		iovec[0].iov_base = (char *)&recsz;
		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");
		fd = open(name, 0);
		if	(fd < 0)
			err(1, "Can't open %s for reading", name);
		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)
#ifdef	pdp11
			flipped = trl(recsz);
			if	(writev(mt, iovec, 3) < 0)
				err(1, "writev #1");
				/* NOTREACHED */
		if	(cnt > 0)
			bzero(buf + cnt, (int)recsz - cnt);
#ifdef	pdp11
			flipped = trl(recsz);
			if	(writev(mt, iovec, 3) < 0)
				err(1, "writev #2");
				/* NOTREACHED */
 * Write two tape marks to simulate EOT
	writev(mt, tmark, 1);
	writev(mt, tmark, 1);

	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;

	fprintf(stderr, "usage: makesimtape -o outfilefile -i inputfile\n");

More information about the TUHS mailing list