henesyinit from p9f47575dc5 years agoHistory
456 lines · 10.7 KB · C
RawDownload
#include <u.h>#include <libc.h> /* *  floppy types (all MFM encoding) */typedef struct Type	Type;struct Type{	char	*name;	int	bytes;		/* bytes/sector */	int	sectors;	/* sectors/track */	int	heads;		/* number of heads */	int	tracks;		/* tracks/disk */	int	media;		/* media descriptor byte */	int	cluster;	/* default cluster size */};Type floppytype[] ={ { "3½HD",	512, 18, 2, 80,	0xf0, 1, }, { "3½DD",	512,  9, 2, 80,	0xf9, 2, }, { "5¼HD",	512, 15, 2, 80,	0xf9, 1, }, { "5¼DD",	512,  9, 2, 40,	0xfd, 2, },};#define NTYPES (sizeof(floppytype)/sizeof(Type)) typedef struct Dosboot	Dosboot;struct Dosboot{	uchar	magic[3];	/* really an xx86 JMP instruction */	uchar	version[8];	uchar	sectsize[2];	uchar	clustsize;	uchar	nresrv[2];	uchar	nfats;	uchar	rootsize[2];	uchar	volsize[2];	uchar	mediadesc;	uchar	fatsize[2];	uchar	trksize[2];	uchar	nheads[2];	uchar	nhidden[4];	uchar	bigvolsize[4];	uchar	driveno;	uchar	reserved0;	uchar	bootsig;	uchar	volid[4];	uchar	label[11];	uchar	reserved1[8];};#define	PUTSHORT(p, v) { (p)[1] = (v)>>8; (p)[0] = (v); }#define	PUTLONG(p, v) { PUTSHORT((p), (v)); PUTSHORT((p)+2, (v)>>16); } typedef struct Dosdir	Dosdir;struct Dosdir{	uchar	name[8];	uchar	ext[3];	uchar	attr;	uchar	reserved[10];	uchar	time[2];	uchar	date[2];	uchar	start[2];	uchar	length[4];}; #define	DRONLY	0x01#define	DHIDDEN	0x02#define	DSYSTEM	0x04#define	DVLABEL	0x08#define	DDIR	0x10#define	DARCH	0x20 /* *  the boot program for the boot sector.  it should probably *  be assembled code, but this is easier. * *  it includes the signiture of the ping-pong virus just to *  drive people crazy. */uchar bootprog[512] ={[0x00]	0xeb, 0x3c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,[0x10]	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,[0x20]	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,[0x30]	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x33,[0x40]	0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x16, 0x07,	0xbb, 0x78, 0x00, 0x36, 0xc5, 0x37, 0x1e, 0x56,[0x50]	0x16, 0x53, 0xbf, 0x3e, 0x7c, 0xb9, 0x0b, 0x00,	0xfc, 0xf3, 0xa4, 0x06, 0x1f, 0xc6, 0x45, 0xfe,[0x60]	0x0f, 0x8b, 0x0e, 0x18, 0x7c, 0x88, 0x4d, 0xf9,	0x89, 0x47, 0x02, 0xc7, 0x07, 0x3e, 0x7c, 0xfb,[0x70]	0xcd, 0x13, 0x72, 0x79, 0x33, 0xc0, 0x39, 0x06,	0x13, 0x7c, 0x74, 0x08, 0x8b, 0x0e, 0x13, 0x7c,[0x80]	0x89, 0x0e, 0x20, 0x7c, 0xa0, 0x10, 0x7c, 0xf7,	0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13,[0x90]	0x16, 0x1e, 0x7c, 0x03, 0x06, 0x0e, 0x7c, 0x83,	0xd2, 0x00, 0xa3, 0x50, 0x7c, 0x89, 0x16, 0x52,[0xa0]	0x7c, 0xa3, 0x49, 0x7c, 0x89, 0x16, 0x4b, 0x7c,	0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b,[0xb0]	0x1e, 0x0b, 0x7c, 0x03, 0xc3, 0x48, 0xf7, 0xf3,	0x01, 0x06, 0x49, 0x7c, 0x83, 0x16, 0x4b, 0x7c,[0xc0]	0x00, 0xbb, 0x00, 0x05, 0x8b, 0x16, 0x52, 0x7c,	0xa1, 0x50, 0x7c, 0xe8, 0x92, 0x00, 0x72, 0x1d,[0xd0]	0xb0, 0x01, 0xe8, 0xac, 0x00, 0x72, 0x16, 0x8b,	0xfb, 0xb9, 0x0b, 0x00, 0xbe, 0xe6, 0x7d, 0xf3,[0xe0]	0xa6, 0x75, 0x0a, 0xb8, 0x00, 0x08, 0x50, 0x07,	0x90, 0x90, 0x90, 0xeb, 0x18, 0xbe, 0x9e, 0x7d,[0xf0]	0xe8, 0x5f, 0x00, 0x33, 0xc0, 0xcd, 0x16, 0x5e,	0x1f, 0x8f, 0x04, 0x8f, 0x44, 0x02, 0xcd, 0x19,[0x100]	0x58, 0x58, 0x58, 0xeb, 0xe8, 0x8b, 0x47, 0x1a,	0x48, 0x48, 0x8a, 0x1e, 0x0d, 0x7c, 0x32, 0xff,[0x110]	0xf7, 0xe3, 0x03, 0x06, 0x49, 0x7c, 0x13, 0x16,	0x4b, 0x7c, 0xbb, 0x00, 0x00, 0xb9, 0x80, 0x00,[0x120]	0x50, 0x52, 0x51, 0xe8, 0x3a, 0x00, 0x72, 0xd8,	0xb0, 0x01, 0xe8, 0x54, 0x00, 0x59, 0x5a, 0x58,[0x130]	0x72, 0xbb, 0x05, 0x01, 0x00, 0x83, 0xd2, 0x00,	0x03, 0x1e, 0x0b, 0x7c, 0xe2, 0xe2, 0xb8, 0x00,[0x140]	0x08, 0x50, 0x1f, 0x90, 0x90, 0x90, 0x90, 0x90,	0x90, 0x90, 0x90, 0x90, 0x90, 0xea, 0x00, 0x00,[0x150]	0x00, 0x08, 0xac, 0x0a, 0xc0, 0x74, 0x29, 0xb4,	0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xf2,[0x160]	0x3b, 0x16, 0x18, 0x7c, 0x73, 0x19, 0xf7, 0x36,	0x18, 0x7c, 0xfe, 0xc2, 0x88, 0x16, 0x4f, 0x7c,[0x170]	0x33, 0xd2, 0xf7, 0x36, 0x1a, 0x7c, 0x88, 0x16,	0x25, 0x7c, 0xa3, 0x4d, 0x7c, 0xf8, 0xc3, 0xf9,[0x180]	0xc3, 0xb4, 0x02, 0x8b, 0x16, 0x4d, 0x7c, 0xb1,	0x06, 0xd2, 0xe6, 0x0a, 0x36, 0x4f, 0x7c, 0x8b,[0x190]	0xca, 0x86, 0xe9, 0x8a, 0x16, 0x24, 0x7c, 0x8a,	0x36, 0x25, 0x7c, 0xcd, 0x13, 0xc3, 0x0d, 0x0a,[0x1a0]	0x4e, 0x6f, 0x6e, 0x2d, 0x53, 0x79, 0x73, 0x74,	0x65, 0x6d, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x20,[0x1b0]	0x6f, 0x72, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x20,	0x65, 0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x52,[0x1c0]	0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x61,	0x6e, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73,[0x1d0]	0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79,	0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65,[0x1e0]	0x61, 0x64, 0x79, 0x0d, 0x0a, 0x00, 'P',  'L',	'A',  'N',  '9',  ' ',  ' ',  ' ',  'S',  'Y',[0x1f0]	'S',  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x57, 0x13, 0x55, 0xaa,}; char *dev;int clustersize;uchar *fat;	/* the fat */int fatbits;int fatsecs;int fatlast;	/* last cluster allocated */int clusters;int fatsecs;int volsecs;uchar *root;	/* first block of root */int rootsecs;int rootfiles;int rootnext;Type *t; enum{	Sof = 1,	/* start of file */	Eof = 2,	/* end of file */};  void	dosfs(int, int, char*);void	dosfile(int, char*, char*, char*);ulong	clustalloc(int);  voidusage(void){	fprint(2, "usage: format [-d] floppy\n");	exits("usage");} voidfatal(char *fmt, ...){	int n;	char err[128]; 	n = doprint(err, err+sizeof(err), fmt, &fmt+1) - err;	err[n] = 0;	fprint(2, "format: %s\n", err);	exits(err);} voidmain(int argc, char **argv){	int n, dos, sys;	int cfd;	char buf[512];	char label[11];	char *a;	int doformat; 	sys = 0;	dos = 0;	clustersize = 0;	doformat = 1;	memmove(label, "NO NAME    ", sizeof(label));	ARGBEGIN {	case 'd':		dos = 1;		break;	case 'c':		clustersize = atoi(ARGF());		break;	case 'l':		a = ARGF();		n = strlen(a);		if(n > sizeof(label))			n = sizeof(label);		memmove(label, a, n);		break;	case 'n':		doformat = 0;		break;	case 's':		sys = 1;		break;	default:		usage();	} ARGEND 	if(argc < 1)		usage();	n = strlen(argv[0]);	if(n > 4 && strcmp(argv[0]+n-4, "disk") == 0)		*(argv[0]+n-4) = 0;	else if(n > 4 && strcmp(argv[0]+n-4, "ctl") == 0)		*(argv[0]+n-3) = 0;	dev = argv[0]; 	sprint(buf, "%sctl", dev);	cfd = open(buf, ORDWR);	if(cfd < 0)		fatal("opening %s: %r", buf);	if(doformat){		print("Formatting floppy %s\n", dev);		if(argc > 1)			sprint(buf, "format %s", argv[1]);		else			strcpy(buf, "format");		if(write(cfd, buf, strlen(buf)) < 0)			fatal("formatting tracks: %r");	} 	if(dos)		dosfs(cfd, sys, label);	close(cfd);	exits(0);} voiddosfs(int cfd, int sys, char *label){	char file[64];	char r[16];	Dosboot *b;	uchar *buf;	Dir d;	int n, fd;	ulong x; 	print("Adding DOS file system\n"); 	sprint(file, "%sdisk", dev);	fd = open(file, ORDWR);	if(fd < 0)		fatal("opening %s: %r", file);	if(dirfstat(fd, &d) < 0)		fatal("stating %s: %r", file); 	t = 0;	seek(cfd, 0, 0);	n = read(cfd, file, sizeof(file)-1);	if(n < 0)		fatal("reading floppy type");	else {		file[n] = 0;		for(t = floppytype; t < &floppytype[NTYPES]; t++)			if(strcmp(file, t->name) == 0)				break;		if(t == &floppytype[NTYPES])			fatal("unknown floppy type %s", file);	}	print("floppy type %s, %d tracks, %d heads, %d sectors/track, %d bytes/sec\n",		t->name, t->tracks, t->heads, t->sectors, t->bytes); 	if(clustersize == 0)		clustersize = t->cluster;	clusters = d.length/(t->bytes*clustersize);	if(clusters < 4087)		fatbits = 12;	else		fatbits = 16;	volsecs = d.length/t->bytes;	fatsecs = (fatbits*clusters + 8*t->bytes - 1)/(8*t->bytes);	rootsecs = volsecs/200;	rootfiles = rootsecs * (t->bytes/32);	buf = malloc(t->bytes);	if(buf == 0)		fatal("out of memory"); 	/*	 *  write bootstrap & parameter block	 */	memmove(buf, bootprog, sizeof(bootprog));	b = (Dosboot*)buf;	memmove(b->version, "Plan9   ", sizeof(b->version));	PUTSHORT(b->sectsize, t->bytes);	b->clustsize = clustersize;	PUTSHORT(b->nresrv, 1);	b->nfats = 2;	PUTSHORT(b->rootsize, rootfiles);	if(volsecs < (1<<16)){		PUTSHORT(b->volsize, volsecs);	}	PUTLONG(b->bigvolsize, volsecs);	b->mediadesc = t->media;	PUTSHORT(b->fatsize, fatsecs);	PUTSHORT(b->trksize, t->sectors);	PUTSHORT(b->nheads, t->heads);	PUTLONG(b->nhidden, 0);	b->driveno = 0;	b->bootsig = 0x29;	x = time(0);	PUTLONG(b->volid, x);	memmove(b->label, label, sizeof(b->label));	sprint(r, "FAT%d    ", fatbits);	memmove(b->reserved1, r, sizeof(b->reserved1));	if(write(fd, buf, t->bytes) != t->bytes)		fatal("writing boot sector: %r");	free(buf); 	/*	 *  allocate an in memory fat	 */	fat = malloc(fatsecs*t->bytes);	if(fat == 0)		fatal("out of memory");	fat[0] = t->media;	fat[1] = 0xff;	fat[2] = 0xff;	if(fatbits == 16)		fat[3] = 0xff;	fatlast = 1;	seek(fd, 2*fatsecs*t->bytes, 1);	/* 2 fats */ 	/*	 *  allocate an in memory root	 */	root = malloc(rootsecs*t->bytes);	if(root == 0)		fatal("out of memory");	seek(fd, rootsecs*t->bytes, 1); 	/*	 *  add system files	 */	if(sys)		dosfile(fd, "/386/b.com", "PLAN9", "SYS"); 	/*	 *  write the fats and root	 */	seek(fd, t->bytes, 0);	if(write(fd, fat, fatsecs*t->bytes) < 0)		fatal("writing fat #1: %r");	if(write(fd, fat, fatsecs*t->bytes) < 0)		fatal("writing fat #2: %r");	if(write(fd, root, rootsecs*t->bytes) < 0)		fatal("writing root: %r");} /* *  allocate a cluster */ulongclustalloc(int flag){	ulong o, x; 	if(flag != Sof){		x = (flag == Eof) ? 0xffff : (fatlast+1);		if(fatbits == 12){			x &= 0xfff;			o = (3*fatlast)/2;			if(fatlast & 1){				fat[o] = (fat[o]&0x0f) | (x<<4);				fat[o+1] = x>>4;			} else {				fat[o] = x;				fat[o+1] = (fat[0+1]&0xf0) | (x>>8);			}		} else {			o = 2*fatlast;			fat[o] = x;			fat[o+1] = x>>8;		}	}			if(flag == Eof)		return 0;	else		return ++fatlast;} /* *  copy in a file */voiddosfile(int ffd, char *file, char *name, char *ext){	Dosdir *dp;	int fd, len, n, start;	char *buf; 	fd = open(file, OREAD);	if(fd < 0)		fatal("can't open %s: %r", file);	buf = malloc(clustersize*t->bytes);	if(buf == 0)		fatal("out of memory");	start = fatlast + 1;	for(len = 0; ; len += n){		n = read(fd, buf, clustersize*t->bytes);		if(n < 0)			fatal("can't read %s: %r", file);		if(n == 0)			break;		clustalloc(len == 0 ? Sof : 0);		if(write(ffd, buf, clustersize*t->bytes) < 0)			fatal("writing system file %s %s: %r", name, ext);	}	clustalloc(Eof);	free(buf); 	dp = (void*)root;	dp += rootnext++;	memmove(dp->name, "        ", 8);	memmove(dp->name, name, strlen(name));	memmove(dp->ext, "   ", 3);	memmove(dp->ext, ext, strlen(ext));	dp->attr = DRONLY | DHIDDEN | DSYSTEM;	PUTSHORT(dp->start, start);	PUTLONG(dp->length, len);}