open_disk.c revision 121888
1199989Srdivacky/* 2199989Srdivacky * ---------------------------------------------------------------------------- 3199989Srdivacky * "THE BEER-WARE LICENSE" (Revision 42): 4199989Srdivacky * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5199989Srdivacky * can do whatever you want with this stuff. If we meet some day, and you think 6199989Srdivacky * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7199989Srdivacky * ---------------------------------------------------------------------------- 8199989Srdivacky */ 9199989Srdivacky 10199989Srdivacky#include <sys/cdefs.h> 11199989Srdivacky__FBSDID("$FreeBSD: head/lib/libdisk/open_disk.c 121888 2003-11-02 08:39:08Z marcel $"); 12199989Srdivacky 13199989Srdivacky#include <stdio.h> 14199989Srdivacky#include <stdlib.h> 15199989Srdivacky#include <unistd.h> 16249423Sdim#include <fcntl.h> 17234353Sdim#include <string.h> 18207618Srdivacky#include <inttypes.h> 19249423Sdim#include <err.h> 20199989Srdivacky#include <sys/sysctl.h> 21199989Srdivacky#include <sys/stdint.h> 22199989Srdivacky#include <sys/types.h> 23199989Srdivacky#include <sys/stat.h> 24249423Sdim#include <sys/ioctl.h> 25249423Sdim#include <sys/disklabel.h> 26249423Sdim#include <sys/gpt.h> 27249423Sdim#include <paths.h> 28249423Sdim#include "libdisk.h" 29249423Sdim 30249423Sdim#include <ctype.h> 31249423Sdim#include <errno.h> 32249423Sdim#include <assert.h> 33249423Sdim 34249423Sdim#ifdef DEBUG 35199989Srdivacky#define DPRINT(x) warn x 36263765Sdim#define DPRINTX(x) warnx x 37199989Srdivacky#else 38199989Srdivacky#define DPRINT(x) 39249423Sdim#define DPRINTX(x) 40199989Srdivacky#endif 41199989Srdivacky 42199989Srdivackystruct disk * 43199989SrdivackyInt_Open_Disk(const char *name, char *conftxt) 44199989Srdivacky{ 45199989Srdivacky struct disk *d; 46207618Srdivacky int i; 47207618Srdivacky char *p, *q, *r, *a, *b, *n, *t, *sn; 48199989Srdivacky off_t o, len, off; 49207618Srdivacky u_int l, s, ty, sc, hd, alt; 50207618Srdivacky off_t lo[10]; 51210299Sed 52210299Sed for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) { 53210299Sed if (*p == '\n') 54199989Srdivacky p++; 55210299Sed a = strsep(&p, " "); 56199989Srdivacky if (strcmp(a, "0")) 57199989Srdivacky continue; 58199989Srdivacky 59263765Sdim a = strsep(&p, " "); 60263765Sdim if (strcmp(a, "DISK")) 61263508Sdim continue; 62199989Srdivacky 63199989Srdivacky a = strsep(&p, " "); 64199989Srdivacky if (strcmp(a, name)) 65199989Srdivacky continue; 66199989Srdivacky break; 67210299Sed } 68210299Sed 69263508Sdim q = strchr(p, '\n'); 70263508Sdim if (q != NULL) 71263508Sdim *q++ = '\0'; 72263508Sdim 73210299Sed d = (struct disk *)calloc(sizeof *d, 1); 74199989Srdivacky if(d == NULL) 75199989Srdivacky return NULL; 76199989Srdivacky 77207618Srdivacky d->name = strdup(name); 78207618Srdivacky 79207618Srdivacky a = strsep(&p, " "); /* length in bytes */ 80207618Srdivacky len = strtoimax(a, &r, 0); 81226633Sdim if (*r) { 82263508Sdim printf("BARF %d <%d>\n", __LINE__, *r); 83199989Srdivacky exit (0); 84263508Sdim } 85199989Srdivacky 86199989Srdivacky a = strsep(&p, " "); /* sectorsize */ 87199989Srdivacky s = strtoul(a, &r, 0); 88199989Srdivacky if (*r) { 89212904Sdim printf("BARF %d <%d>\n", __LINE__, *r); 90212904Sdim exit (0); 91212904Sdim } 92212904Sdim 93212904Sdim if (s == 0) 94212904Sdim return (NULL); 95234353Sdim d->sector_size = s; 96212904Sdim len /= s; /* media size in number of sectors. */ 97199989Srdivacky 98234353Sdim if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-")) 99243830Sdim DPRINT(("Failed to add 'whole' chunk")); 100199989Srdivacky 101199989Srdivacky for (;;) { 102199989Srdivacky a = strsep(&p, " "); 103234353Sdim if (a == NULL) 104234353Sdim break; 105263765Sdim b = strsep(&p, " "); 106263765Sdim o = strtoul(b, &r, 0); 107263765Sdim if (*r) { 108263765Sdim printf("BARF %d <%d>\n", __LINE__, *r); 109263765Sdim exit (0); 110263765Sdim } 111263765Sdim if (!strcmp(a, "hd")) 112263765Sdim d->bios_hd = o; 113263765Sdim else if (!strcmp(a, "sc")) 114263765Sdim d->bios_sect = o; 115263765Sdim else 116263765Sdim printf("HUH ? <%s> <%s>\n", a, b); 117263765Sdim } 118263765Sdim 119263765Sdim /* 120263765Sdim * Calculate the number of cylinders this disk must have. If we have 121263765Sdim * an obvious insanity, we set the number of cyclinders to zero. 122263765Sdim */ 123263765Sdim o = d->bios_hd * d->bios_sect; 124263765Sdim d->bios_cyl = (o != 0) ? len / o : 0; 125263765Sdim 126263765Sdim p = q; 127263765Sdim lo[0] = 0; 128263765Sdim 129263765Sdim for (; p != NULL && *p; p = q) { 130263765Sdim q = strchr(p, '\n'); 131263765Sdim if (q != NULL) 132263765Sdim *q++ = '\0'; 133263765Sdim a = strsep(&p, " "); /* Index */ 134263765Sdim if (!strcmp(a, "0")) 135263765Sdim break; 136263765Sdim l = strtoimax(a, &r, 0); 137263765Sdim if (*r) { 138263765Sdim printf("BARF %d <%d>\n", __LINE__, *r); 139263765Sdim exit (0); 140263765Sdim } 141263765Sdim t = strsep(&p, " "); /* Type {SUN, BSD, MBR, PC98, GPT} */ 142212904Sdim n = strsep(&p, " "); /* name */ 143212904Sdim a = strsep(&p, " "); /* len */ 144207618Srdivacky len = strtoimax(a, &r, 0); 145199989Srdivacky if (*r) { 146199989Srdivacky printf("BARF %d <%d>\n", __LINE__, *r); 147199989Srdivacky exit (0); 148199989Srdivacky } 149212904Sdim a = strsep(&p, " "); /* secsize */ 150212904Sdim s = strtoimax(a, &r, 0); 151212904Sdim if (*r) { 152212904Sdim printf("BARF %d <%d>\n", __LINE__, *r); 153212904Sdim exit (0); 154263508Sdim } 155263508Sdim for (;;) { 156263508Sdim a = strsep(&p, " "); 157212904Sdim if (a == NULL) 158263508Sdim break; 159212904Sdim /* XXX: Slice name may include a space. */ 160212904Sdim if (!strcmp(a, "sn")) { 161212904Sdim sn = p; 162212904Sdim break; 163212904Sdim } 164212904Sdim b = strsep(&p, " "); 165212904Sdim o = strtoimax(b, &r, 0); 166212904Sdim if (*r) { 167212904Sdim printf("BARF %d <%d>\n", __LINE__, *r); 168212904Sdim exit (0); 169212904Sdim } 170212904Sdim if (!strcmp(a, "o")) 171212904Sdim off = o; 172212904Sdim else if (!strcmp(a, "i")) 173212904Sdim i = o; 174212904Sdim else if (!strcmp(a, "ty")) 175212904Sdim ty = o; 176212904Sdim else if (!strcmp(a, "sc")) 177212904Sdim sc = o; 178212904Sdim else if (!strcmp(a, "hd")) 179212904Sdim hd = o; 180212904Sdim else if (!strcmp(a, "alt")) 181199989Srdivacky alt = o; 182199989Srdivacky } 183199989Srdivacky 184207618Srdivacky /* PLATFORM POLICY BEGIN ----------------------------------- */ 185199989Srdivacky if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) 186199989Srdivacky continue; 187199989Srdivacky if (platform == p_sparc64 && !strcmp(t, "SUN") && 188199989Srdivacky d->chunks->part->part == NULL) { 189199989Srdivacky d->bios_hd = hd; 190199989Srdivacky d->bios_sect = sc; 191199989Srdivacky o = d->chunks->size / (hd * sc); 192199989Srdivacky o *= (hd * sc); 193199989Srdivacky o -= alt * hd * sc; 194199989Srdivacky if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) 195199989Srdivacky DPRINT(("Failed to add 'freebsd' chunk")); 196199989Srdivacky } 197207618Srdivacky if (platform == p_alpha && !strcmp(t, "BSD") && 198207618Srdivacky d->chunks->part->part == NULL) { 199207618Srdivacky if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 200199989Srdivacky 0, 0, "-")) 201223017Sdim DPRINT(("Failed to add 'freebsd' chunk")); 202223017Sdim } 203223017Sdim if (!strcmp(t, "BSD") && i == RAW_PART) 204223017Sdim continue; 205207618Srdivacky /* PLATFORM POLICY END ------------------------------------- */ 206199989Srdivacky 207199989Srdivacky off /= s; 208199989Srdivacky len /= s; 209199989Srdivacky off += lo[l - 1]; 210263508Sdim lo[l] = off; 211199989Srdivacky if (!strcmp(t, "SUN")) 212199989Srdivacky i = Add_Chunk(d, off, len, n, part, 0, 0, 0); 213263508Sdim else if (!strncmp(t, "MBR", 3)) { 214199989Srdivacky switch (ty) { 215199989Srdivacky case 0xa5: 216203954Srdivacky i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0); 217199989Srdivacky break; 218199989Srdivacky case 0x01: 219199989Srdivacky case 0x04: 220199989Srdivacky case 0x06: 221207618Srdivacky case 0x0b: 222207618Srdivacky case 0x0c: 223207618Srdivacky case 0x0e: 224207618Srdivacky i = Add_Chunk(d, off, len, n, fat, ty, 0, 0); 225207618Srdivacky break; 226199989Srdivacky case 0xef: /* EFI */ 227199989Srdivacky i = Add_Chunk(d, off, len, n, efi, ty, 0, 0); 228199989Srdivacky break; 229199989Srdivacky default: 230199989Srdivacky i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0); 231199989Srdivacky break; 232207618Srdivacky } 233207618Srdivacky } else if (!strcmp(t, "BSD")) 234207618Srdivacky i = Add_Chunk(d, off, len, n, part, ty, 0, 0); 235199989Srdivacky else if (!strcmp(t, "PC98")) { 236199989Srdivacky switch (ty & 0x7f) { 237199989Srdivacky case 0x14: 238199989Srdivacky i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 239199989Srdivacky sn); 240199989Srdivacky break; 241199989Srdivacky case 0x20: 242199989Srdivacky case 0x21: 243219077Sdim case 0x22: 244207618Srdivacky case 0x23: 245212904Sdim case 0x24: 246210299Sed i = Add_Chunk(d, off, len, n, fat, ty, 0, sn); 247199989Srdivacky break; 248199989Srdivacky default: 249210299Sed i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn); 250249423Sdim break; 251263508Sdim } 252263508Sdim } else if (!strcmp(t, "GPT")) 253199989Srdivacky i = Add_Chunk(d, off, len, n, ty, 0, 0, 0); 254199989Srdivacky else if (!strcmp(t, "BDE")) 255210299Sed ; /* nothing */ 256199989Srdivacky else if (!strcmp(t, "CCD")) 257199989Srdivacky ; /* nothing */ 258199989Srdivacky else { 259199989Srdivacky printf("BARF %d\n", __LINE__); 260199989Srdivacky exit(0); 261199989Srdivacky } 262226633Sdim } 263263508Sdim /* PLATFORM POLICY BEGIN ------------------------------------- */ 264263508Sdim /* We have a chance to do things on a blank disk here */ 265199989Srdivacky if (platform == p_sparc64 && d->chunks->part->part == NULL) { 266263508Sdim hd = d->bios_hd; 267199989Srdivacky sc = d->bios_sect; 268199989Srdivacky o = d->chunks->size / (hd * sc); 269199989Srdivacky o *= (hd * sc); 270199989Srdivacky o -= 2 * hd * sc; 271263508Sdim if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) 272199989Srdivacky DPRINT(("Failed to add 'freebsd' chunk")); 273263508Sdim } 274199989Srdivacky /* PLATFORM POLICY END --------------------------------------- */ 275210299Sed 276199989Srdivacky return (d); 277199989Srdivacky i = 0; 278199989Srdivacky} 279199989Srdivacky