From 56d3134bfb907d8de0fb4bd6e9e8b386ddc6010e Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Tue, 29 Oct 2002 12:13:36 +0000 Subject: [PATCH] Since make release is toast anyway, add wood to the pyre: This significantly rewamps libdisks discovery of existing disk layout. Please send me reports if this does not work as expected on i386 or sparc64 platforms. I need to sort out alpha, pc98 and ia64 (in that order) before testing on those platforms make a lot of sense. Belived to work for: i386 sparc64 Unknown state: pc98 alpha ia64 --- lib/libdisk/Makefile | 13 + lib/libdisk/chunk.c | 92 +++-- lib/libdisk/disk.c | 886 +++++++++--------------------------------- lib/libdisk/libdisk.h | 50 ++- lib/libdisk/rules.c | 21 +- 5 files changed, 316 insertions(+), 746 deletions(-) diff --git a/lib/libdisk/Makefile b/lib/libdisk/Makefile index 95e6444ff9e5..7ac80423962d 100644 --- a/lib/libdisk/Makefile +++ b/lib/libdisk/Makefile @@ -24,6 +24,10 @@ SRCS += write_ia64_disk.c SRCS += write_alpha_disk.c .endif +.if ${MACHINE_ARCH} == "sparc64" +SRCS += write_sparc64_disk.c +.endif + CLEANFILES+= tmp.c tst01 tst01.o NOPROFILE= yes NOPIC= yes @@ -34,3 +38,12 @@ MAN= libdisk.3 tst01: tst01.o libdisk.a cc ${CFLAGS} -static tst01.o -o tst01 libdisk.a + +ad0: all install tst01 + ./tst01 ad0 + +da0: all install tst01 + ./tst01 da0 + +da1: all install tst01 + ./tst01 da1 diff --git a/lib/libdisk/chunk.c b/lib/libdisk/chunk.c index 14e95005add5..9dfcad0be1d3 100644 --- a/lib/libdisk/chunk.c +++ b/lib/libdisk/chunk.c @@ -54,7 +54,6 @@ Find_Mother_Chunk(struct chunk *chunks, u_long offset, u_long end, chunk_e type) case whole: if (Chunk_Inside(chunks, &ct)) return chunks; -#ifndef PC98 case extended: for(c1 = chunks->part; c1; c1 = c1->next) { if (c1->type != type) @@ -63,7 +62,6 @@ Find_Mother_Chunk(struct chunk *chunks, u_long offset, u_long end, chunk_e type) return c1; } return 0; -#endif case freebsd: for(c1 = chunks->part; c1; c1 = c1->next) { if (c1->type == type) @@ -122,7 +120,7 @@ Clone_Chunk(const struct chunk *c1) return c2; } -static int +int Insert_Chunk(struct chunk *c2, u_long offset, u_long size, const char *name, chunk_e type, int subtype, u_long flags, const char *sname) { @@ -236,38 +234,68 @@ Add_Chunk(struct disk *d, long offset, u_long size, const char *name, c1->subtype = subtype; return 0; } - if (type == freebsd) -#ifdef PC98 - subtype = 0xc494; -#else - subtype = 0xa5; -#endif + c1 = 0; -#ifndef PC98 - if(!c1 && (type == freebsd || type == fat || type == unknown)) - c1 = Find_Mother_Chunk(d->chunks, offset, end, extended); -#endif - if(!c1 && (type == freebsd || type == fat || type == unknown)) - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); -#ifndef PC98 - if(!c1 && type == extended) - c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); -#endif - if(!c1 && type == part) - c1 = Find_Mother_Chunk(d->chunks, offset, end, freebsd); + /* PLATFORM POLICY BEGIN ------------------------------------- */ + switch(platform) { + case p_i386: + switch (type) { + case fat: + case mbr: + case extended: + case freebsd: + subtype = 0xa5; + c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); + break; + case part: + c1 = Find_Mother_Chunk(d->chunks, offset, end, freebsd); + break; + default: + return(-1); + } + break; + case p_pc98: + subtype = 0xc494; + break; + case p_sparc64: + case p_alpha: + switch (type) { + case freebsd: + c1 = Find_Mother_Chunk(d->chunks, offset, end, whole); + break; + case part: + c1 = Find_Mother_Chunk(d->chunks, offset, end, freebsd); + break; + default: + return(-1); + } + break; + default: + return (-1); + } + /* PLATFORM POLICY END ---------------------------------------- */ + if(!c1) return __LINE__; for(c2 = c1->part; c2; c2 = c2->next) { if (c2->type != unused) continue; - if(Chunk_Inside(c2, &ct)) { + if(!Chunk_Inside(c2, &ct)) + continue; +/* PLATFORM POLICY BEGIN ------------------------------------- */ + if (platform == p_sparc64) { + offset = Prev_Cyl_Aligned(d, offset); + size = Next_Cyl_Aligned(d, size); + break; + } + if (platform == p_i386) { if (type != freebsd) - goto doit; + break; if (!(flags & CHUNK_ALIGN)) - goto doit; + break; if (offset == d->chunks->offset && end == d->chunks->end) - goto doit; + break; /* Round down to prev cylinder */ offset = Prev_Cyl_Aligned(d,offset); @@ -279,7 +307,6 @@ Add_Chunk(struct disk *d, long offset, u_long size, const char *name, /* Keep one track clear in front of parent */ if (offset == c1->offset) offset = Next_Track_Aligned(d, offset + 1); - /* Work on the (end+1) */ size += offset; /* Round up to cylinder */ @@ -292,13 +319,14 @@ Add_Chunk(struct disk *d, long offset, u_long size, const char *name, /* Convert back to size */ size -= offset; - - doit: - return Insert_Chunk(c2, offset, size, name, - type, subtype, flags, sname); } + +/* PLATFORM POLICY END ------------------------------------- */ } - return __LINE__; + if (c2 == NULL) + return (__LINE__); + return Insert_Chunk(c2, offset, size, name, + type, subtype, flags, sname); } char * @@ -325,7 +353,7 @@ Print_Chunk(struct chunk *c1,int offset) for(; i < 10; i++) putchar(' '); printf("%p %8ld %8lu %8lu %-8s %-16s %-8s 0x%02x %s", c1, c1->offset, c1->size, c1->end, c1->name, c1->sname, - chunk_n[c1->type], c1->subtype, + chunk_name(c1->type), c1->subtype, ShowChunkFlags(c1)); putchar('\n'); Print_Chunk(c1->part, offset + 2); diff --git a/lib/libdisk/disk.c b/lib/libdisk/disk.c index 3675b4497dc6..267ea19163d1 100644 --- a/lib/libdisk/disk.c +++ b/lib/libdisk/disk.c @@ -15,30 +15,24 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include #include #include #include -#ifndef PC98 #include -#endif #include #include "libdisk.h" -#ifndef PC98 -#define HAVE_GEOM -#endif #include #include #include -#ifndef PC98 #define DOSPTYP_EXTENDED 5 -#endif - #ifdef DEBUG #define DPRINT(x) warn x #define DPRINTX(x) warnx x @@ -47,716 +41,219 @@ __FBSDID("$FreeBSD$"); #define DPRINTX(x) #endif -const char *chunk_n[] = { - "whole", - "unknown", - "fat", - "freebsd", - "extended", - "part", - "unused", - NULL +const char * +chunk_name(chunk_e type) +{ + switch(type) { + case unused: return ("unused"); + case mbr: return ("mbr"); + case part: return ("part"); + case gpt: return ("gpt"); + case pc98: return ("pc98"); + case sun: return ("sun"); + case freebsd: return ("freebsd"); + case fat: return ("fat"); + case spare: return ("spare"); + default: return ("??"); + } }; struct disk * Open_Disk(const char *name) { - return Int_Open_Disk(name, 0); + return Int_Open_Disk(name); } -#ifndef PC98 -static u_int32_t -Read_Int32(u_int32_t *p) -{ - u_int8_t *bp = (u_int8_t *)p; - return bp[0] | (bp[1] << 8) | (bp[2] << 16) | (bp[3] << 24); -} -#endif - -/* - * XXX BEGIN HACK XXX - * Scan/parse the XML geom data to retrieve what we need to - * carry out the work of Int_Open_Disk. This is a total hack - * and should be replaced with a real XML parser. - */ -typedef enum { - XML_MESH, - XML_MESH_END, - XML_CLASS, - XML_CLASS_END, - XML_GEOM, - XML_GEOM_END, - XML_CONFIG, - XML_CONFIG_END, - XML_PROVIDER, - XML_PROVIDER_END, - XML_NAME, - XML_NAME_END, - XML_INDEX, - XML_INDEX_END, - XML_SECLENGTH, - XML_SECLENGTH_END, - XML_SECOFFSET, - XML_SECOFFSET_END, - XML_TYPE, - XML_TYPE_END, - XML_MEDIASIZE, - XML_MEDIASIZE_END, - XML_SECTORSIZE, - XML_SECTORSIZE_END, - XML_FWHEADS, - XML_FWHEADS_END, - XML_FWSECTORS, - XML_FWSECTORS_END, - - XML_OTHER, - XML_OTHER_END -} XMLToken; - -const struct { - XMLToken t; - const char* token; - const char* name; -} xmltokens[] = { - { XML_MESH, "mesh", "XML_MESH" }, - { XML_CLASS, "class", "XML_CLASS" }, - { XML_GEOM, "geom", "XML_GEOM" }, - { XML_CONFIG, "config", "XML_CONFIG" }, - { XML_PROVIDER, "provider", "XML_PROVIDE" }, - { XML_NAME, "name", "XML_NAME" }, - { XML_INDEX, "index", "XML_INDEX" }, - { XML_SECLENGTH, "seclength", "XML_SECLENGTH" }, - { XML_SECOFFSET, "secoffset", "XML_SECOFFSET" }, - { XML_TYPE, "type", "XML_TYPE" }, - { XML_FWHEADS, "fwheads", "XML_FWHEADS" }, - { XML_FWSECTORS, "fwsectors", "XML_FWSECTORS" }, - { XML_MEDIASIZE, "mediasize", "XML_MEDIASIZE" }, - { XML_SECTORSIZE, "sectorsize", "XML_SECTORSIZE" }, - /* NB: this must be last */ - { XML_OTHER, NULL, "XML_OTHER" }, -}; -#define N(x) (sizeof (x) / sizeof (x[0])) - -#ifdef DEBUG -static const char* -xmltokenname(XMLToken t) -{ - int i; - - for (i = 0; i < N(xmltokens); i++) { - if (t == xmltokens[i].t) - return xmltokens[i].name; - if ((t-1) == xmltokens[i].t) { - static char tbuf[80]; - snprintf(tbuf, sizeof (tbuf), "%s_END", - xmltokens[i].name); - return tbuf; - } - } - return "???"; -} -#endif /*DEBUG*/ - -/* - * Parse the next XML token delimited by <..>. If the token - * has a "builtin terminator" (<... />) then just skip it and - * go the next token. - */ -static int -xmltoken(const char *start, const char **next, XMLToken *t) -{ - const char *cp = start; - const char *token; - int i; - -again: - while (*cp != '<') { - if (*cp == '\0') { - *next = cp; - DPRINTX(("xmltoken: EOD")); - return 0; - } - cp++; - } - token = ++cp; - for (; *cp && *cp != '>' && !isspace(*cp); cp++) - ; - if (*cp == '\0') { - *next = cp; - DPRINTX(("xmltoken: EOD")); - return 0; - } - *t = (*token == '/'); - if (*t) - token++; - for (i = 0; xmltokens[i].token != NULL; i++) - if (strncasecmp(token, xmltokens[i].token, cp-token) == 0) - break; - *t += xmltokens[i].t; - /* now collect the remainder of the string */ - for (; *cp != '>' && *cp != '\0'; cp++) - ; - if (*cp == '\0') { - *next = cp; - DPRINTX(("xmltoken: EOD")); - return 0; - } - if (cp > token && cp[-1] == '/') { - /* e.g. */ - start = cp+1; - goto again; - } - *next = cp+1; - DPRINTX(("xmltoken: %s \"%.*s\"", xmltokenname(*t), cp-token, token)); - return 1; -} - -/* - * Parse and discard XML up to the token terminator. - */ -static int -discardxml(const char **next, XMLToken terminator) -{ - const char *xml = *next; - XMLToken t; - - DPRINTX(("discard XML up to %s", xmltokenname(terminator))); - for (;;) { - if (xmltoken(xml, next, &t) == 0) - return EINVAL; - if (t == terminator) - break; - if ((t & 1) == 0) { - int error = discardxml(next, t+1); - if (error) - return error; - } - xml = *next; - } - return 0; -} - -/* - * Parse XML from between a range of markers; e.g. ... . - * When the specified class name is located we descend looking for the - * geometry information given by diskname. Once inside there we process - * tags calling f back for each useful one. The arg is passed into f - * for use in storing the parsed data. - */ -static int -parsexmlpair( - const char *xml, - const char **next, - const char *classname, - XMLToken terminator, - const char *diskname, - int (*f)(void *, XMLToken, u_int *, u_int64_t), - void *arg -) -{ - const char *cp; - XMLToken t; - int error; - u_int ix = (u_int) -1; - - DPRINTX(("parse XML up to %s", xmltokenname(terminator))); - do { - if (xmltoken(xml, next, &t) == 0) { - error = EINVAL; - break; - } - if (t == terminator) { - error = 0; - break; - } - if (t & 1) { /* w/o matching */ - DPRINTX(("Unexpected token %s", xmltokenname(t))); - error = EINVAL; - break; - } - switch ((int) t) { - case XML_NAME: - for (cp = *next; *cp && *cp != '<'; cp++) - ; - if (*cp == '\0') { - DPRINTX(("parsexmlpair: EOD")); - error = EINVAL; - goto done; - } - DPRINTX(("parsexmlpair: \"%.*s\"", cp-*next, *next)); - switch ((int) terminator) { - case XML_CLASS_END: - if (strncasecmp(*next, classname, cp-*next)) - return discardxml(next, terminator); - break; - case XML_GEOM_END: - if (strncasecmp(*next, diskname, cp-*next)) - return discardxml(next, terminator); - break; - } - break; - case XML_SECOFFSET: - case XML_SECLENGTH: - case XML_TYPE: - if (ix == (u_int) -1) { - DPRINTX(("parsexmlpair: slice data w/o " - "preceding index")); - error = EINVAL; - goto done; - } - /* fall thru... */ - case XML_INDEX: - case XML_FWHEADS: - case XML_FWSECTORS: - case XML_MEDIASIZE: - case XML_SECTORSIZE: - if (terminator != XML_CONFIG_END && - terminator != XML_PROVIDER_END) { - DPRINTX(("parsexmlpair: %s in unexpected " - "context: terminator %s", - xmltokenname(t), - xmltokenname(terminator))); - error = EINVAL; - goto done; - } - error = (*f)(arg, t, &ix, strtoull(*next, NULL, 10)); - if (error) - goto done; - break; - } - error = parsexmlpair(*next, &xml, classname, - t+1, diskname, f, arg); - } while (error == 0); -done: - return error; -} - -/* - * XML parser. Just barely smart enough to handle the - * gibberish that geom passed back from the kernel. - */ -static int -xmlparse( - const char *confxml, - const char *classname, - const char *diskname, - int (*f)(void *, XMLToken, u_int *, u_int64_t), - void *arg -) -{ - const char *next; - XMLToken t; - int error; - - next = confxml; - while (xmltoken(next, &next, &t) && t != XML_MESH) - ; - if (t == XML_MESH) - error = parsexmlpair(next, &next, classname, XML_MESH_END, diskname, f, arg); - else { - DPRINTX(("xmlparse: expecting mesh token, got %s", - xmltokenname(t))); - error = EINVAL; - } - - return (error ? -1 : 0); -} - -/* - * Callback to collect slice-related data. - */ -static int -assignToSlice(void *arg, XMLToken t, u_int *slice, u_int64_t v) -{ - struct diskslices *ds = (struct diskslices *) arg; - - switch ((int) t) { - case XML_INDEX: - *slice = BASE_SLICE + (u_int) v; - if (*slice >= MAX_SLICES) { - DPRINTX(("assignToSlice: invalid slice index %u > max %u", - *slice, MAX_SLICES)); - return EINVAL; - } - if (*slice >= ds->dss_nslices) - ds->dss_nslices = (*slice)+1; - break; - case XML_SECOFFSET: - ds->dss_slices[*slice].ds_offset = (u_long) v; - break; - case XML_SECLENGTH: - ds->dss_slices[*slice].ds_size = (u_long) v; - break; - case XML_TYPE: - ds->dss_slices[*slice].ds_type = (int) v; - break; - } - return 0; -} - -/* - * Callback to collect disk-related data. - */ -static int -assignToDisk(void *arg, XMLToken t, u_int *slice, u_int64_t v) -{ - struct disklabel *dl = (struct disklabel *) arg; - - switch ((int) t) { - case XML_FWHEADS: - dl->d_ntracks = (u_int32_t) v; - case XML_FWSECTORS: - dl->d_nsectors = (u_int32_t) v; - break; - case XML_MEDIASIZE: - /* store this temporarily; it gets moved later */ - dl->d_secpercyl = v >> 32; - dl->d_secperunit = v & 0xffffffff; - break; - case XML_SECTORSIZE: - dl->d_secsize = (u_int32_t) v; - break; - } - return 0; -} - -#ifdef __i386__ -/* - * Callback to collect partition-related data. - */ -static int -assignToPartition(void *arg, XMLToken t, u_int *part, u_int64_t v) -{ - struct disklabel *dl = (struct disklabel *) arg; - - switch ((int) t) { - case XML_INDEX: - *part = (u_int) v; - if (*part >= MAXPARTITIONS) { - DPRINTX(("assignToPartition: invalid partition index %u > max %u", - *part, MAXPARTITIONS)); - return EINVAL; - } - if (*part >= dl->d_npartitions) - dl->d_npartitions = (*part)+1; - break; - case XML_SECOFFSET: - dl->d_partitions[*part].p_offset = (u_int32_t) v; - break; - case XML_SECLENGTH: - dl->d_partitions[*part].p_size = (u_int32_t) v; - break; - case XML_TYPE: - dl->d_partitions[*part].p_fstype = (u_int8_t) v; - break; - } - return 0; -} -#endif /* __i386__ */ -#undef N - struct disk * -Int_Open_Disk(const char *name, u_long size) +Int_Open_Disk(const char *name) { - int i; - int fd = -1; - struct diskslices ds; - struct disklabel dl; - char device[64]; + char *conftxt = NULL; struct disk *d; -#ifdef PC98 - unsigned char *p; -#else - struct dos_partition *dp; - void *p; -#endif - char *confxml = NULL; - size_t xmlsize; - u_int64_t mediasize; - int error; + size_t txtsize; + int error, i; + char *p, *q, *r, *a, *b, *n, *t; + off_t o, len, off; + u_int l, s, ty, sc, hd, alt; + off_t lo[10]; - strlcpy(device, _PATH_DEV, sizeof(device)); - strlcat(device, name, sizeof(device)); - - d = (struct disk *)malloc(sizeof *d); - if(!d) return NULL; - memset(d, 0, sizeof *d); - - fd = open(device, O_RDONLY); - if (fd < 0) { - DPRINT(("open(%s) failed", device)); - goto bad; - } - - memset(&dl, 0, sizeof dl); - memset(&ds, 0, sizeof ds); - /* - * Read and hack-parse the XML that provides the info we need. - */ - error = sysctlbyname("kern.geom.confxml", NULL, &xmlsize, NULL, 0); + error = sysctlbyname("kern.geom.conftxt", NULL, &txtsize, NULL, 0); if (error) { - warn("kern.geom.confxml sysctl not available, giving up!"); - goto bad; + warn("kern.geom.conftxt sysctl not available, giving up!"); + return (NULL); } - confxml = (char *) malloc(xmlsize+1); - if (confxml == NULL) { - DPRINT(("cannot malloc memory for confxml")); - goto bad; + conftxt = (char *) malloc(txtsize+1); + if (conftxt == NULL) { + DPRINT(("cannot malloc memory for conftxt")); + return (NULL); } - error = sysctlbyname("kern.geom.confxml", confxml, &xmlsize, NULL, 0); + error = sysctlbyname("kern.geom.conftxt", conftxt, &txtsize, NULL, 0); if (error) { - DPRINT(("error reading kern.geom.confxml from the system")); - goto bad; + DPRINT(("error reading kern.geom.conftxt from the system")); + free(conftxt); + return (NULL); } - confxml[xmlsize] = '\0'; /* in case kernel bug is still there */ + conftxt[txtsize] = '\0'; /* in case kernel bug is still there */ - if (xmlparse(confxml, "MBR", name, assignToSlice, &ds) != 0) { - DPRINTX(("Error parsing MBR geometry specification.")); - goto bad; - } - if (xmlparse(confxml, "DISK", name, assignToDisk, &dl) != 0) { - DPRINTX(("Error parsing DISK geometry specification.")); - goto bad; - } - if (dl.d_nsectors == 0) { - DPRINTX(("No (zero) sector information in DISK geometry")); - goto bad; - } - if (dl.d_ntracks == 0) { - DPRINTX(("No (zero) track information in DISK geometry")); - goto bad; - } - if (dl.d_secsize == 0) { - DPRINTX(("No (zero) sector size information in DISK geometry")); - goto bad; - } - if (dl.d_secpercyl == 0 && dl.d_secperunit == 0) { - DPRINTX(("No (zero) media size information in DISK geometry")); - goto bad; - } - /* - * Now patch up disklabel and diskslice. - */ - d->sector_size = dl.d_secsize; - /* NB: media size was stashed in two parts while parsing */ - mediasize = (((u_int64_t) dl.d_secpercyl) << 32) + dl.d_secperunit; - dl.d_secpercyl = 0; - dl.d_secperunit = 0; - size = mediasize / d->sector_size; - dl.d_ncylinders = size / (dl.d_ntracks * dl.d_nsectors); - /* "whole disk" slice maintained for compatibility */ - ds.dss_slices[WHOLE_DISK_SLICE].ds_size = size; + for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) { + if (*p == '\n') + p++; + a = strsep(&p, " "); + if (strcmp(a, "0")) + continue; -#ifdef PC98 - p = (unsigned char*)read_block(fd, 1, d->sector_size); -#else - p = read_block(fd, 0, d->sector_size); - dp = (struct dos_partition*)(p + DOSPARTOFF); - for (i = 0; i < NDOSPART; i++) { - if (Read_Int32(&dp->dp_start) >= size) - continue; - if (Read_Int32(&dp->dp_start) + Read_Int32(&dp->dp_size) >= size) - continue; - if (!Read_Int32(&dp->dp_size)) - continue; - } - free(p); -#endif + a = strsep(&p, " "); + if (strcmp(a, "DISK")) + continue; - d->bios_sect = dl.d_nsectors; - d->bios_hd = dl.d_ntracks; + a = strsep(&p, " "); + if (strcmp(a, name)) + continue; + break; + } + + q = strchr(p, '\n'); + if (q != NULL) + *q++ = '\0'; + + d = (struct disk *)calloc(sizeof *d, 1); + if(d == NULL) + return NULL; d->name = strdup(name); + a = strsep(&p, " "); /* length in bytes */ + o = strtoimax(a, &r, 0); + if (*r) { printf("BARF %d <%d>\n", __LINE__, *r); exit (0); } - if (dl.d_ntracks && dl.d_nsectors) - d->bios_cyl = size / (dl.d_ntracks * dl.d_nsectors); + a = strsep(&p, " "); /* sectorsize */ + s = strtoul(a, &r, 0); + if (*r) { printf("BARF %d <%d>\n", __LINE__, *r); exit (0); } - if (Add_Chunk(d, 0, size, name, whole, 0, 0, "-")) + if (Add_Chunk(d, 0, o / s, name, whole, 0, 0, "-")) DPRINT(("Failed to add 'whole' chunk")); -#ifdef __i386__ -#ifdef PC98 - /* XXX -- Quick Hack! - * Check MS-DOS MO - */ - if ((*p == 0xf0 || *p == 0xf8) && - (*(p+1) == 0xff) && - (*(p+2) == 0xff)) { - Add_Chunk(d, 0, size, name, fat, 0xa0a0, 0, name); - free(p); - goto pc98_mo_done; - } - free(p); -#endif /* PC98 */ - for(i=BASE_SLICE;i\n", __LINE__, *r); exit (0); } + if (!strcmp(a, "hd")) + d->bios_hd = o; + else if (!strcmp(a, "sc")) + d->bios_sect = o; + else + printf("HUH ? <%s> <%s>\n", a, b); + } + + p = q; + lo[0] = 0; + + for (; p != NULL && *p; p = q) { + q = strchr(p, '\n'); + if (q != NULL) + *q++ = '\0'; + a = strsep(&p, " "); /* Index */ + if (!strcmp(a, "0")) + break; + l = strtoimax(a, &r, 0); + if (*r) { printf("BARF %d <%d>\n", __LINE__, *r); exit (0); } + t = strsep(&p, " "); /* Type {SUN, BSD, MBR, GPT} */ + n = strsep(&p, " "); /* name */ + a = strsep(&p, " "); /* len */ + len = strtoimax(a, &r, 0); + if (*r) { printf("BARF %d <%d>\n", __LINE__, *r); exit (0); } + a = strsep(&p, " "); /* secsize */ + s = strtoimax(a, &r, 0); + if (*r) { printf("BARF %d <%d>\n", __LINE__, *r); exit (0); } + for (;;) { + a = strsep(&p, " "); + if (a == NULL) + break; + b = strsep(&p, " "); + o = strtoimax(b, &r, 0); + if (*r) { printf("BARF %d <%d>\n", __LINE__, *r); exit (0); } + if (!strcmp(a, "o")) + off = o; + else if (!strcmp(a, "i")) + i = o; + else if (!strcmp(a, "ty")) + ty = o; + else if (!strcmp(a, "sc")) + sc = o; + else if (!strcmp(a, "hd")) + hd = o; + else if (!strcmp(a, "alt")) + alt = o; + } + + /* PLATFORM POLICY BEGIN ------------------------------------- */ + if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) continue; - snprintf(sname, sizeof(sname), "%ss%d", name, i - 1); -#ifdef PC98 - subtype = ds.dss_slices[i].ds_type | - ds.dss_slices[i].ds_subtype << 8; - switch (ds.dss_slices[i].ds_type & 0x7f) { - case 0x14: - ce = freebsd; - break; - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - ce = fat; - break; -#else /* IBM-PC */ - subtype = ds.dss_slices[i].ds_type; - switch (ds.dss_slices[i].ds_type) { - case 0xa5: - ce = freebsd; - break; - case 0x1: - case 0x6: - case 0x4: - case 0xb: - case 0xc: - case 0xe: - ce = fat; - break; - case DOSPTYP_EXTENDED: - case 0xf: - ce = extended; - break; -#endif - default: - ce = unknown; - break; + if (platform == p_sparc64 && !strcmp(t, "SUN") && + d->chunks->part->part == NULL) { + d->bios_hd = hd; + d->bios_sect = sc; + o = d->chunks->size / (hd * sc); + o *= (hd * sc); + o -= alt * hd * sc; + if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) + DPRINT(("Failed to add 'freebsd' chunk")); } -#ifdef PC98 - if (Add_Chunk(d, ds.dss_slices[i].ds_offset, - ds.dss_slices[i].ds_size, sname, ce, subtype, flags, - ds.dss_slices[i].ds_name)) -#else - if (Add_Chunk(d, ds.dss_slices[i].ds_offset, - ds.dss_slices[i].ds_size, sname, ce, subtype, flags, "")) -#endif - DPRINT(("failed to add chunk for slice %d", i - 1)); - -#ifdef PC98 - if ((ds.dss_slices[i].ds_type & 0x7f) != 0x14) -#else - if (ds.dss_slices[i].ds_type != 0xa5) -#endif + if (platform == p_alpha && !strcmp(t, "BSD") && + d->chunks->part->part == NULL) { + o = d->chunks->size; + if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 0, 0, "-")) + DPRINT(("Failed to add 'freebsd' chunk")); + } + if (platform == p_i386 && !strcmp(t, "BSD") && i == 2) continue; - if (xmlparse(confxml, "BSD", sname, assignToPartition, &dl) != 0) { - DPRINTX(("Error parsing MBR geometry specification.")); - goto bad; - } + /* PLATFORM POLICY END --------------------------------------- */ - for(j = 0; j <= dl.d_npartitions; j++) { - if (j == RAW_PART) - continue; - if (j == 3) - continue; - if (j == dl.d_npartitions) { - j = 3; - dl.d_npartitions = 0; - } - if (!dl.d_partitions[j].p_size) - continue; - if (dl.d_partitions[j].p_size + - dl.d_partitions[j].p_offset > - ds.dss_slices[i].ds_size) - continue; - snprintf(pname, sizeof(pname), "%s%c", sname, j + 'a'); - if (Add_Chunk(d, - dl.d_partitions[j].p_offset + - ds.dss_slices[i].ds_offset, - dl.d_partitions[j].p_size, - pname,part, - dl.d_partitions[j].p_fstype, -#ifdef PC98 - 0, - ds.dss_slices[i].ds_name) && j != 3) -#else - 0, "") && j != 3) -#endif - DPRINT(( - "Failed to add chunk for partition %c [%lu,%lu]", - j + 'a', dl.d_partitions[j].p_offset, - dl.d_partitions[j].p_size)); - } + off /= s; + len /= s; + off += lo[l - 1]; + lo[l] = off; + printf("%s [%s] %jd %jd\n", t, n, (intmax_t)(off / s), (intmax_t) (len / s)); + if (!strcmp(t, "SUN")) + i = Add_Chunk(d, off, len, n, part, 0, 0, 0); + else if (!strcmp(t, "MBR") && ty == 165) + i = Add_Chunk(d, off, len, n, freebsd, 0, 0, 0); + else if (!strcmp(t, "MBR")) + i = Add_Chunk(d, off, len, n, mbr, 0, 0, 0); + else if (!strcmp(t, "BSD")) + i = Add_Chunk(d, off, len, n, part, 0, 0, 0); + else if (!strcmp(t, "PC98")) + i = Add_Chunk(d, off, len, n, pc98, 0, 0, 0); + else if (!strcmp(t, "GPT")) + i = Add_Chunk(d, off, len, n, gpt, 0, 0, 0); + else + {printf("BARF %d\n", __LINE__); exit(0); } + printf("error = %d\n", i); } -#endif /* __i386__ */ -#ifdef __alpha__ - { - struct disklabel dl; - char pname[20]; - int j,k; - - strlcpy(pname, _PATH_DEV, sizeof(pname)); - strlcat(pname, name, sizeof(pname)); - j = open(pname, O_RDONLY); - if (j < 0) { - DPRINT(("open(%s)", pname)); - goto nolabel; - } - k = ioctl(j, DIOCGDINFO, &dl); - if (k < 0) { - DPRINT(("ioctl(%s, DIOCGDINFO)", pname)); - close(j); - goto nolabel; - } - close(j); - All_FreeBSD(d, 1); - - for(j = 0; j <= dl.d_npartitions; j++) { - if (j == RAW_PART) - continue; - if (j == 3) - continue; - if (j == dl.d_npartitions) { - j = 3; - dl.d_npartitions = 0; - } - if (!dl.d_partitions[j].p_size) - continue; - if (dl.d_partitions[j].p_size + - dl.d_partitions[j].p_offset > - ds.dss_slices[WHOLE_DISK_SLICE].ds_size) - continue; - snprintf(pname, sizeof(pname), "%s%c", name, j + 'a'); - if (Add_Chunk(d, - dl.d_partitions[j].p_offset, - dl.d_partitions[j].p_size, - pname,part, - dl.d_partitions[j].p_fstype, - 0, "") && j != 3) - DPRINT(( - "Failed to add chunk for partition %c [%lu,%lu]", - j + 'a', dl.d_partitions[j].p_offset, - dl.d_partitions[j].p_size)); - } - nolabel:; + /* PLATFORM POLICY BEGIN ------------------------------------- */ + /* We have a chance to do things on a blank disk here */ +printf("c %p\n", d->chunks); +printf("c->p %p\n", d->chunks->part); +printf("c->p->p %p\n", d->chunks->part->part); + if (platform == p_sparc64 && d->chunks->part->part == NULL) { +printf("HERE %d\n", __LINE__); + hd = d->bios_hd; + sc = d->bios_sect; + o = d->chunks->size / (hd * sc); + o *= (hd * sc); + o -= 2 * hd * sc; +printf("HERE %d\n", __LINE__); + if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) + DPRINT(("Failed to add 'freebsd' chunk")); } -#endif /* __alpha__ */ -#ifdef PC98 -pc98_mo_done: -#endif - close(fd); - Fixup_Names(d); - return d; -bad: - if (confxml != NULL) - free(confxml); - if (fd >= 0) - close(fd); - return NULL; + /* PLATFORM POLICY END --------------------------------------- */ + + return (d); + i = 0; } void @@ -769,10 +266,7 @@ Debug_Disk(struct disk *d) printf(" bios_geom=%lu/%lu/%lu = %lu\n", d->bios_cyl, d->bios_hd, d->bios_sect, d->bios_cyl * d->bios_hd * d->bios_sect); -#if defined(PC98) - printf(" boot1=%p, boot2=%p, bootipl=%p, bootmenu=%p\n", - d->boot1, d->boot2, d->bootipl, d->bootmenu); -#elif defined(__i386__) +#if defined(__i386__) printf(" boot1=%p, boot2=%p, bootmgr=%p\n", d->boot1, d->boot2, d->bootmgr); #elif defined(__alpha__) @@ -867,14 +361,8 @@ Disk_Names() return disks; } -#ifdef PC98 -void -Set_Boot_Mgr(struct disk *d, const u_char *bootipl, const size_t bootipl_size, - const u_char *bootmenu, const size_t bootmenu_size) -#else void Set_Boot_Mgr(struct disk *d, const u_char *b, const size_t s) -#endif { #if !defined(__ia64__) #ifdef PC98 @@ -950,7 +438,6 @@ slice_type_name( int type, int subtype ) { switch (type) { case 0: return "whole"; -#ifndef PC98 case 1: switch (subtype) { case 1: return "fat (12-bit)"; case 2: return "XENIX /"; @@ -984,21 +471,14 @@ slice_type_name( int type, int subtype ) case 239: return "EFI Sys. Part."; default: return "unknown"; } -#endif case 2: return "fat"; case 3: switch (subtype) { -#ifdef PC98 - case 0xc494: return "freebsd"; -#else case 165: return "freebsd"; -#endif default: return "unknown"; } -#ifndef PC98 case 4: return "extended"; case 5: return "part"; case 6: return "unused"; -#endif default: return "unknown"; } } diff --git a/lib/libdisk/libdisk.h b/lib/libdisk/libdisk.h index bf9b54d40a69..2a4cd1a30439 100644 --- a/lib/libdisk/libdisk.h +++ b/lib/libdisk/libdisk.h @@ -10,19 +10,61 @@ * */ +#define DEBUG 1 +/* You can define a particular architecture here if you are debugging. */ +/* #define P_DEBUG p_sparc64 */ + #define MAX_NO_DISKS 32 /* Max # of disks Disk_Names() will return */ #define MAX_SEC_SIZE 2048 /* maximum sector size that is supported */ #define MIN_SEC_SIZE 512 /* the sector size to end sensing at */ +const static enum platform { + p_any, /* for debugging ! */ + p_alpha, + p_i386, + p_pc98, + p_sparc64, + p_ia64, + p_ppc +} platform = +#if defined (P_DEBUG) + P_DEBUG +#elif defined (PC98) + p_pc98 +#elif defined(__i386__) + p_i386 +#elif defined(__alpha__) + p_alpha +#elif defined(__sparc64__) + p_sparc64 +#elif defined(__ia64__) + p_ia64 +#elif defined(__ppc__) + p_ppc +#else + IHAVENOIDEA +#endif + ; + + + + typedef enum { whole, unknown, + + sun, + pc98, + mbr, + gpt, + fat, freebsd, extended, part, + spare, unused } chunk_e; @@ -104,7 +146,7 @@ struct chunk { #define DELCHUNK_RECOVER 0x0001 -extern const char *chunk_n[]; +const char *chunk_name(chunk_e type); const char * slice_type_name( int type, int subtype ); @@ -136,6 +178,10 @@ Sanitize_Bios_Geom(struct disk *disk); /* Set the bios geometry to something sane */ +int +Insert_Chunk(struct chunk *c2, u_long offset, u_long size, const char *name, + chunk_e type, int subtype, u_long flags, const char *sname); + int Delete_Chunk2(struct disk *disk, struct chunk *, int flags); /* Free a chunk of disk_space modified by the passed @@ -256,7 +302,7 @@ int Add_Chunk(struct disk *, long, u_long, const char *, chunk_e, int, u_long, c void * read_block(int, daddr_t, u_long); int write_block(int, daddr_t, const void *, u_long); struct disklabel * read_disklabel(int, daddr_t, u_long); -struct disk * Int_Open_Disk(const char *name, u_long size); +struct disk * Int_Open_Disk(const char *name); int Fixup_Names(struct disk *); int MakeDevChunk(const struct chunk *c1, const char *path); __END_DECLS diff --git a/lib/libdisk/rules.c b/lib/libdisk/rules.c index a6a2255c852c..87846c999c59 100644 --- a/lib/libdisk/rules.c +++ b/lib/libdisk/rules.c @@ -233,15 +233,18 @@ Rule_004(const struct disk *d, const struct chunk *c, char *msg) static void Check_Chunk(const struct disk *d, const struct chunk *c, char *msg) { - Rule_000(d, c, msg); - Rule_001(d, c, msg); - Rule_002(d, c, msg); - Rule_003(d, c, msg); - Rule_004(d, c, msg); - if (c->part) - Check_Chunk(d, c->part, msg); - if (c->next) - Check_Chunk(d, c->next, msg); + + if (platform == p_i386) { + Rule_000(d, c, msg); + Rule_001(d, c, msg); + Rule_002(d, c, msg); + Rule_003(d, c, msg); + Rule_004(d, c, msg); + if (c->part) + Check_Chunk(d, c->part, msg); + if (c->next) + Check_Chunk(d, c->next, msg); + } } char *