henesyinit from p9fd787fda5 years agoHistory
367 lines · 7.3 KB · C
RawDownload
#include	"u.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h" #include	"sd.h"#include	"dosfs.h" enum {	Npart = 32}; uchar *mbrbuf, *partbuf;int nbuf;#define trace 0 inttsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr){	uchar *b; 	if(sdbio(unit, part, a, unit->secsize, off) != unit->secsize){		if(trace)			print("%s: read %lud at %lld failed\n", unit->name,				unit->secsize, (vlong)part->start*unit->secsize+off);		return -1;	}	b = a;	if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){		if(trace)			print("%s: bad magic %.2ux %.2ux at %lld\n",				unit->name, b[0x1FE], b[0x1FF],				(vlong)part->start*unit->secsize+off);		return -1;	}	return 0;} /* *  read partition table.  The partition table is just ascii strings. */#define MAGIC "plan9 partitions"static voidoldp9part(SDunit *unit){	SDpart *pp;	char *field[3], *line[Npart+1];	ulong n, start, end;	int i; 	/*	 *  We have some partitions already.	 */	pp = &unit->part[unit->npart]; 	/*	 * We prefer partition tables on the second to last sector,	 * but some old disks use the last sector instead.	 */	strcpy(pp->name, "partition");	pp->start = unit->sectors - 2;	pp->end = unit->sectors - 1; 	if(tsdbio(unit, pp, partbuf, 0, 0) < 0)		return; 	if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) {		/* not found on 2nd last sector; look on last sector */		pp->start++;		pp->end++;		if(tsdbio(unit, pp, partbuf, 0, 0) < 0)			return;		if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0)			return;		print("%s: using old plan9 partition table on last sector\n", unit->name);	}else		print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->name); 	/* we found a partition table, so add a partition partition */	unit->npart++;	partbuf[unit->secsize-1] = '\0'; 	/*	 * parse partition table	 */	n = getfields((char*)partbuf, line, Npart+1, '\n');	if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){		for(i = 1; i < n && unit->npart < SDnpart; i++){			if(getfields(line[i], field, 3, ' ') != 3)				break;			start = strtoul(field[1], 0, 0);			end = strtoul(field[2], 0, 0);			if(start >= end || end > unit->sectors)				break;			sdaddpart(unit, field[0], start, end);		}	}	} static voidp9part(SDunit *unit, char *name){	SDpart *p;	char *field[4], *line[Npart+1];	ulong start, end;	int i, n;		p = sdfindpart(unit, name);	if(p == nil)		return; 	if(tsdbio(unit, p, partbuf, unit->secsize, 0) < 0)		return;	partbuf[unit->secsize-1] = '\0'; 	if(strncmp((char*)partbuf, "part ", 5) != 0)		return; 	n = getfields((char*)partbuf, line, Npart+1, '\n');	if(n == 0)		return;	for(i = 0; i < n && unit->npart < SDnpart; i++){		if(strncmp(line[i], "part ", 5) != 0)			break;		if(getfields(line[i], field, 4, ' ') != 4)			break;		start = strtoul(field[2], 0, 0);		end = strtoul(field[3], 0, 0);		if(start >= end || end > unit->sectors)			break;		sdaddpart(unit, field[1], p->start+start, p->start+end);	}} intisdos(int t){	return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;} intisextend(int t){	return t==EXTEND || t==EXTHUGE || t==LEXTEND;} /*  * Fetch the first dos and all plan9 partitions out of the MBR partition table. * We return -1 if we did not find a plan9 partition. */static intmbrpart(SDunit *unit){	ulong mbroffset;	Dospart *dp;	ulong start, end;	ulong epart, outer, inner;	int havedos, i, nplan9;	char name[10]; 	if(tsdbio(unit, &unit->part[0], mbrbuf, 0, 1) < 0)		return -1; 	mbroffset = 0;	dp = (Dospart*)&mbrbuf[0x1BE];	for(i=0; i<4; i++, dp++)		if(dp->type == DMDDO) {			mbroffset = 63*512;			if(trace)				print("DMDDO partition found\n");			if(tsdbio(unit, &unit->part[0], mbrbuf, mbroffset, 1) < 0)				return -1;			i = -1;	/* start over */		} 	nplan9 = 0;	havedos = 0;	epart = 0;	dp = (Dospart*)&mbrbuf[0x1BE];	if(trace)		print("%s mbr ", unit->name);	for(i=0; i<4; i++, dp++) {		if(trace)			print("dp %d...", dp->type);		start = mbroffset+GLONG(dp->start);		end = start+GLONG(dp->len); 		if(dp->type == PLAN9) {			if(nplan9 == 0)				strcpy(name, "plan9");			else				sprint(name, "plan9.%d", nplan9);			sdaddpart(unit, name, start, end);			p9part(unit, name);			nplan9++;		} 		/*		 * We used to take the active partition (and then the first		 * when none are active).  We have to take the first here,		 * so that the partition we call ``dos'' agrees with the		 * partition disk/fdisk calls ``dos''. 		 */		if(havedos==0 && isdos(dp->type)){			havedos = 1;			sdaddpart(unit, "dos", start, end);		}		if(isextend(dp->type)){			epart = start;			if(trace)				print("link %lud...", epart);		}	}	if(trace)		print("\n"); 	/*	 * Search through the chain of extended partition tables.	 */	outer = epart;	while(epart != 0) {		if(trace)			print("%s ext %lud ", unit->name, epart);		if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)epart*unit->secsize, 1) < 0)			break;		inner = epart;		epart = 0;		dp = (Dospart*)&mbrbuf[0x1BE];		for(i=0; i<4; i++, dp++) {			if(trace)				print("dp %d...", dp->type);			start = GLONG(dp->start);			if(dp->type == PLAN9){				start += inner;				end = start+GLONG(dp->len);				if(nplan9 == 0)					strcpy(name, "plan9");				else					sprint(name, "plan9.%d", nplan9);				sdaddpart(unit, name, start, end);				p9part(unit, name);				nplan9++;			}			if(havedos==0 && isdos(dp->type)){				start += inner;				end = start+GLONG(dp->len);				havedos = 1;				sdaddpart(unit, "dos", start, end);			}			if(isextend(dp->type)){				epart = start + outer;				if(trace)					print("link %lud...", epart);			}		}		if(trace)			print("\n");	}			return nplan9 ? 0 : -1;} /* * To facilitate booting from CDs, we create a partition for * the boot floppy image embedded in a bootable CD. */static intpart9660(SDunit *unit){	uchar buf[2048];	ulong a, n;	uchar *p; 	if(unit->secsize != 2048)		return -1; 	if(sdbio(unit, &unit->part[0], buf, 2048, 17*2048) < 0)		return -1; 	if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)		return -1; 		p = buf+0x47;	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 	if(sdbio(unit, &unit->part[0], buf, 2048, a*2048) < 0)		return -1; 	if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0	|| memcmp(buf+30, "\x55\xAA", 2) != 0	|| buf[0x20] != 0x88)		return -1; 	p = buf+0x28;	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 	switch(buf[0x21]){	case 0x01:		n = 1200*1024;		break;	case 0x02:		n = 1440*1024;		break;	case 0x03:		n = 2880*1024;		break;	default:		return -1;	}	n /= 2048; 	print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n);	sdaddpart(unit, "cdboot", a, a+n);	return 0;} enum {	NEW = 1<<0,	OLD = 1<<1}; voidpartition(SDunit *unit){	int type;	char *p; 	if(unit->part == 0)		return; 	if(part9660(unit) == 0)		return; 	p = getconf("partition");	if(p == nil)		p = defaultpartition; 	if(p != nil && strncmp(p, "new", 3) == 0)		type = NEW;	else if(p != nil && strncmp(p, "old", 3) == 0)		type = OLD;	else		type = NEW|OLD; 	if(nbuf < unit->secsize) {		free(mbrbuf);		free(partbuf);		mbrbuf = malloc(unit->secsize);		partbuf = malloc(unit->secsize);		if(mbrbuf==nil || partbuf==nil) {			free(mbrbuf);			free(partbuf);			partbuf = mbrbuf = nil;			nbuf = 0;			return;		}		nbuf = unit->secsize;	} 	if((type & NEW) && mbrpart(unit) >= 0){		/* nothing to do */;	}	else if(type & OLD)		oldp9part(unit);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t