diff options
author | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
---|---|---|
committer | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
commit | 5ba95fdb07ddc2c32111a1b2f57f17aa27fcbbf5 (patch) | |
tree | c1ec54cb9ecff85b0b820a26d26a10a32a118d0c /sys/src/9/xen/dpart.c | |
parent | fa03455b5057675b18d1c87aef2d1071b2088de0 (diff) |
import xen 32 bit paravirtual kernel from /n/sources/xen.
Diffstat (limited to 'sys/src/9/xen/dpart.c')
-rw-r--r-- | sys/src/9/xen/dpart.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/sys/src/9/xen/dpart.c b/sys/src/9/xen/dpart.c new file mode 100644 index 000000000..17d3e4a3a --- /dev/null +++ b/sys/src/9/xen/dpart.c @@ -0,0 +1,248 @@ +#include <u.h> +#include <libc.h> +#include <disk.h> + +typedef void Fs; +#include "/sys/src/boot/pc/dosfs.h" + +enum { + Npart = 32 +}; + +#define GSHORT(p) (((p)[1]<<8)|(p)[0]) +#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p)) + +int +readdisk(Disk *d, void *buf, vlong off, int len) +{ + if(seek(d->fd, off, 0) == -1 + || read(d->fd, buf, len) != len) + return -1; + return 0; +} + +void +addpart(Disk *d, char *name, ulong s, ulong e) +{ + print("%s: part %s %lud %lud\n", d->prefix, name, s, e); + fprint(d->ctlfd, "part %s %lud %lud\n", name, s, e); +} + +int +isdos(int t) +{ + return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X; +} + +int +isextend(int t) +{ + return t==EXTEND || t==EXTHUGE || t==LEXTEND; +} + + + +/* build a cdboot partition if there is an embedded boot floppy image */ +int +cdpart(Disk *d) +{ + uchar buf[2048]; + ulong a, n; + uchar *p; + + if(readdisk(d, buf, 17*2048, 2048) == -1 + || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0) + return 0; + + p = buf + 0x47; + a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); + + if(readdisk(d, buf, a*2048, 2048) == -1 + || memcmp((char*)buf, "\x01\x00\x00\x00", 4) != 0 + || memcmp((char*)buf+30, "\x55\xAA", 2) != 0 + || buf[0x20] != 0x88) + return 0; + + p = buf+0x28; + a = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); + + switch(buf[0x21]) { + case 1: n = 1200*1024; break; + case 2: n = 1440*1024; break; + case 3: n = 2880*1024; break; + default: return 0; + } + + a = a * (uvlong)2048 / d->secsize; + n /= d->secsize; + addpart(d, "cdboot", a, a+n); + return 1; +} + +int +p9part(Disk *d, char *name, ulong pstart) +{ + char partbuf[512]; + char *field[4], *line[Npart+1], *name2; + ulong start, end; + int i, n; + + name2 = smprint("%s%s", d->prefix, name); + d = opendisk(name2, 1, 0); + if(!d) { + fprint(2, "%s: %r\n", name2); + free(name2); + return 0; + } + free(name2); + + if(readdisk(d, partbuf, 512, sizeof partbuf) == -1) + return 0; + partbuf[sizeof partbuf - 1] = '\0'; + if(strncmp(partbuf, "part ", 5) != 0 + || (n = getfields(partbuf, line, Npart+1, 0, "\n")) == 0) + return 0; + for(i = 0; i < n; i++) { + if(strncmp(line[i], "part ", 5) != 0) + break; + if(getfields(line[i], field, 4, 0, " ") != 4) + break; + start = strtoul(field[2], 0, 0); + end = strtoul(field[3], 0, 0); + if(start >= end) + break; + addpart(d, field[1], pstart+start, pstart+end); + } + return 0; +} + +int +mbrpart(Disk *d) +{ + uchar mbrbuf[512]; + char name[10]; + Dospart *dp; + ulong taboffset, start, end; + ulong firstxpart, nxtxpart; + int i, nplan9, havedos; + +#define readmbr() \ + if(readdisk(d, mbrbuf, (uvlong)taboffset*512, sizeof mbrbuf) == -1 \ + || mbrbuf[0x1FE] != 0x55 || mbrbuf[0x1FF] != 0xAA) \ + return 0 + + if(d->secsize > 512) + return 0; + dp = (Dospart*)&mbrbuf[0x1BE]; + taboffset = 0; + + if(1) { + /* get the MBR (allowing for DMDDO) */ + readmbr(); + for(i = 0; i < 4; i++) { + if(dp[i].type == DMDDO) { + taboffset = 63; + readmbr(); + i = -1; /* start over */ + } + } + } + + /* + * Read the partitions, first from the MBR and then + * from successive extended partition tables. + */ + nplan9 = 0; + havedos = 0; + firstxpart = 0; + for(;;) { + readmbr(); + nxtxpart = 0; + for(i = 0; i < 4; i++) { + /* partition offsets are relative to taboffset */ + start = taboffset+GLONG(dp[i].start); + end = start+GLONG(dp[i].len); + if(dp[i].type == PLAN9) { + if(nplan9 == 0) + strcpy(name, "plan9"); + else + sprint(name, "plan9.%d", nplan9); + addpart(d, name, start, end); + p9part(d, name, start); + nplan9++; + } + + if(!havedos && isdos(dp[i].type)) { + havedos = 1; + addpart(d, "dos", start, end); + } + + /* nxtxpart is relative to firstxpart (or 0), not taboffset */ + if(isextend(dp[i].type)) + nxtxpart = start-taboffset+firstxpart; + } + if(!nxtxpart) + break; + if(!firstxpart) + firstxpart = nxtxpart; + taboffset = nxtxpart; + } + return nplan9 + havedos; +} + +void +partall(void) +{ + Disk *d; + Dir *ent; + char *name; + int fd, i, n; + + fd = open("#S", OREAD); + if(fd == -1) { + fprint(2, "No disk\n"); + return; + } + + while((n = dirread(fd, &ent)) > 0) { + for(i = 0; i < n; i++) { + if(ent[i].mode & DMDIR) { + name = smprint("#S/%s/data", ent[i].name); + d = opendisk(name, 1, 0); + if(!d) { + fprint(2, "%s: %r\n", name); + continue; + } + // XXX not safe yet: if(!mbrpart(d) && !cdpart(d) && !p9part(d, "data", 0)) + if(!mbrpart(d) && !cdpart(d)) + fprint(2, "%s: no partitions\n", name); + close(d->fd); + } + } + } + close(fd); +} + + +void +main(int argc, char **argv) +{ + USED(argc, argv); + + fmtinstall('r', errfmt); + + bind("#c", "/dev", MBEFORE); + open("/dev/cons", OREAD); + open("/dev/cons", OWRITE); + open("/dev/cons", OWRITE); + + partall(); + + close(0); + close(1); + close(2); + + exec("/boot/boot2", argv); + + exits(0); +} |