open_disk.c revision 127081
120253Sjoerg/* 220302Sjoerg * ---------------------------------------------------------------------------- 320302Sjoerg * "THE BEER-WARE LICENSE" (Revision 42): 420253Sjoerg * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 520253Sjoerg * can do whatever you want with this stuff. If we meet some day, and you think 620253Sjoerg * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 720253Sjoerg * ---------------------------------------------------------------------------- 820253Sjoerg */ 920302Sjoerg 1020253Sjoerg#include <sys/cdefs.h> 1120253Sjoerg__FBSDID("$FreeBSD: head/lib/libdisk/open_disk.c 127081 2004-03-16 17:07:06Z jhb $"); 1220253Sjoerg 1320253Sjoerg#include <stdio.h> 1420302Sjoerg#include <stdlib.h> 1520253Sjoerg#include <unistd.h> 1620253Sjoerg#include <fcntl.h> 1720302Sjoerg#include <string.h> 1820253Sjoerg#include <inttypes.h> 1920253Sjoerg#include <err.h> 2020253Sjoerg#include <sys/sysctl.h> 2120253Sjoerg#include <sys/stdint.h> 2220253Sjoerg#include <sys/types.h> 2320253Sjoerg#include <sys/stat.h> 2420253Sjoerg#include <sys/ioctl.h> 2544229Sdavidn#include <sys/disklabel.h> 2620253Sjoerg#include <sys/gpt.h> 2720253Sjoerg#include <paths.h> 2830259Scharnier#include "libdisk.h" 2930259Scharnier 3050479Speter#include <ctype.h> 3130259Scharnier#include <errno.h> 3230259Scharnier#include <assert.h> 33286201Sbapt 34286201Sbapt#ifdef DEBUG 35286201Sbapt#define DPRINT(x) warn x 36286201Sbapt#define DPRINTX(x) warnx x 37286201Sbapt#else 3830259Scharnier#define DPRINT(x) 39286201Sbapt#define DPRINTX(x) 4030259Scharnier#endif 4120253Sjoerg 42286201Sbaptstruct disk * 43286201SbaptInt_Open_Disk(const char *name, char *conftxt) 44286201Sbapt{ 45286201Sbapt struct disk *d; 4630259Scharnier int i; 47286201Sbapt char *p, *q, *r, *a, *b, *n, *t, *sn; 48286201Sbapt daddr_t o, len, off; 4920253Sjoerg u_int l, s, ty, sc, hd, alt; 50286201Sbapt daddr_t lo[10]; 51286201Sbapt 5220253Sjoerg for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) { 5320253Sjoerg if (*p == '\n') 54286201Sbapt p++; 5520253Sjoerg a = strsep(&p, " "); 5623318Sache if (strcmp(a, "0")) 5722394Sdavidn continue; 5852512Sdavidn 5924214Sache a = strsep(&p, " "); 60286196Sbapt if (strcmp(a, "DISK")) 61286196Sbapt continue; 62286196Sbapt 63286196Sbapt a = strsep(&p, " "); 64286196Sbapt if (strcmp(a, name)) 65286196Sbapt continue; 66286196Sbapt break; 67286196Sbapt } 68286196Sbapt 69286196Sbapt q = strchr(p, '\n'); 70286196Sbapt if (q != NULL) 71286196Sbapt *q++ = '\0'; 72286196Sbapt 7320253Sjoerg d = (struct disk *)calloc(sizeof *d, 1); 74286196Sbapt if(d == NULL) 75286196Sbapt return NULL; 76286196Sbapt 77286196Sbapt d->name = strdup(name); 78286196Sbapt 79286196Sbapt a = strsep(&p, " "); /* length in bytes */ 80286196Sbapt len = strtoimax(a, &r, 0); 81286196Sbapt if (*r) { 82286196Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 83286196Sbapt exit (0); 84286196Sbapt } 85286196Sbapt 86286196Sbapt a = strsep(&p, " "); /* sectorsize */ 87283961Sbapt s = strtoul(a, &r, 0); 88286196Sbapt if (*r) { 89286196Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 90283961Sbapt exit (0); 91285430Sbapt } 92283961Sbapt 93285430Sbapt if (s == 0) 94285434Sbapt return (NULL); 95285434Sbapt d->sector_size = s; 96285434Sbapt len /= s; /* media size in number of sectors. */ 97283961Sbapt 98283961Sbapt if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-")) 99286196Sbapt DPRINT(("Failed to add 'whole' chunk")); 100285430Sbapt 101286196Sbapt for (;;) { 102286196Sbapt a = strsep(&p, " "); 103283961Sbapt if (a == NULL) 104283961Sbapt break; 105285133Sbapt b = strsep(&p, " "); 106286196Sbapt o = strtoimax(b, &r, 0); 107285133Sbapt if (*r) { 108285133Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 109285133Sbapt exit (0); 110285133Sbapt } 111285133Sbapt if (!strcmp(a, "hd")) 112285133Sbapt d->bios_hd = o; 113285133Sbapt else if (!strcmp(a, "sc")) 114286196Sbapt d->bios_sect = o; 115285133Sbapt else 116285133Sbapt printf("HUH ? <%s> <%s>\n", a, b); 117285133Sbapt } 118285133Sbapt 119285133Sbapt /* 120285133Sbapt * Calculate the number of cylinders this disk must have. If we have 121285133Sbapt * an obvious insanity, we set the number of cyclinders to zero. 122286196Sbapt */ 123286196Sbapt o = d->bios_hd * d->bios_sect; 124285133Sbapt d->bios_cyl = (o != 0) ? len / o : 0; 125285133Sbapt 126285137Sbapt p = q; 127285133Sbapt lo[0] = 0; 128286196Sbapt 129285133Sbapt for (; p != NULL && *p; p = q) { 130285133Sbapt q = strchr(p, '\n'); 131286196Sbapt if (q != NULL) 132285133Sbapt *q++ = '\0'; 133285133Sbapt a = strsep(&p, " "); /* Index */ 134285133Sbapt if (!strcmp(a, "0")) 135285133Sbapt break; 136286196Sbapt l = strtoimax(a, &r, 0); 137285133Sbapt if (*r) { 138286196Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 139285133Sbapt exit (0); 140285133Sbapt } 141285133Sbapt t = strsep(&p, " "); /* Type {SUN, BSD, MBR, PC98, GPT} */ 142285133Sbapt n = strsep(&p, " "); /* name */ 143285133Sbapt a = strsep(&p, " "); /* len */ 144285133Sbapt len = strtoimax(a, &r, 0); 145286196Sbapt if (*r) { 146285133Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 147285133Sbapt exit (0); 148285133Sbapt } 149285133Sbapt a = strsep(&p, " "); /* secsize */ 150285133Sbapt s = strtoimax(a, &r, 0); 151286196Sbapt if (*r) { 152286196Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 153285133Sbapt exit (0); 154285137Sbapt } 155286196Sbapt for (;;) { 156285133Sbapt a = strsep(&p, " "); 157285133Sbapt if (a == NULL) 158285133Sbapt break; 159285133Sbapt /* XXX: Slice name may include a space. */ 160285133Sbapt if (!strcmp(a, "sn")) { 161285133Sbapt sn = p; 162285133Sbapt break; 163285133Sbapt } 164285133Sbapt b = strsep(&p, " "); 165285133Sbapt o = strtoimax(b, &r, 0); 166285133Sbapt if (*r) { 167285405Sbapt printf("BARF %d <%d>\n", __LINE__, *r); 168286196Sbapt exit (0); 169285405Sbapt } 170285405Sbapt if (!strcmp(a, "o")) 171286196Sbapt off = o; 172285405Sbapt else if (!strcmp(a, "i")) 173286196Sbapt i = o; 174286196Sbapt else if (!strcmp(a, "ty")) 175286196Sbapt ty = o; 176286196Sbapt else if (!strcmp(a, "sc")) 177285405Sbapt sc = o; 178285405Sbapt else if (!strcmp(a, "hd")) 179285405Sbapt hd = o; 180285405Sbapt else if (!strcmp(a, "alt")) 181285405Sbapt alt = o; 182285405Sbapt } 183286196Sbapt 184286196Sbapt /* PLATFORM POLICY BEGIN ----------------------------------- */ 185285405Sbapt if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) 186285405Sbapt continue; 187285984Sbapt if (platform == p_sparc64 && !strcmp(t, "SUN") && 188285405Sbapt d->chunks->part->part == NULL) { 189285405Sbapt d->bios_hd = hd; 190285405Sbapt d->bios_sect = sc; 191285405Sbapt o = d->chunks->size / (hd * sc); 192285405Sbapt o *= (hd * sc); 193285405Sbapt o -= alt * hd * sc; 194285405Sbapt if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) 195285405Sbapt DPRINT(("Failed to add 'freebsd' chunk")); 196285405Sbapt } 197285405Sbapt if (platform == p_alpha && !strcmp(t, "BSD") && 198285405Sbapt d->chunks->part->part == NULL) { 199285405Sbapt if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 200285405Sbapt 0, 0, "-")) 201285405Sbapt DPRINT(("Failed to add 'freebsd' chunk")); 202285405Sbapt } 203286196Sbapt if (!strcmp(t, "BSD") && i == RAW_PART) 204285405Sbapt continue; 205285405Sbapt /* PLATFORM POLICY END ------------------------------------- */ 206285405Sbapt 207286196Sbapt off /= s; 208285405Sbapt len /= s; 209286196Sbapt off += lo[l - 1]; 210285405Sbapt lo[l] = off; 211286196Sbapt if (!strcmp(t, "SUN")) 212286196Sbapt i = Add_Chunk(d, off, len, n, part, 0, 0, 0); 213286196Sbapt else if (!strncmp(t, "MBR", 3)) { 214286196Sbapt switch (ty) { 215285405Sbapt case 0xa5: 216285405Sbapt i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0); 217286259Sed break; 218286196Sbapt case 0x01: 219286196Sbapt case 0x04: 220286196Sbapt case 0x06: 221286196Sbapt case 0x0b: 222285405Sbapt case 0x0c: 223285405Sbapt case 0x0e: 224285405Sbapt i = Add_Chunk(d, off, len, n, fat, ty, 0, 0); 225286196Sbapt break; 226285405Sbapt case 0xef: /* EFI */ 227285405Sbapt i = Add_Chunk(d, off, len, n, efi, ty, 0, 0); 228285405Sbapt break; 229285405Sbapt default: 230285405Sbapt i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0); 231285405Sbapt break; 232285405Sbapt } 233285405Sbapt } else if (!strcmp(t, "BSD")) 234285405Sbapt i = Add_Chunk(d, off, len, n, part, ty, 0, 0); 235285405Sbapt else if (!strcmp(t, "PC98")) { 236285405Sbapt switch (ty & 0x7f) { 237285405Sbapt case 0x14: 238285405Sbapt i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 239285405Sbapt sn); 240285405Sbapt break; 241285405Sbapt case 0x20: 242285405Sbapt case 0x21: 243285405Sbapt case 0x22: 244285405Sbapt case 0x23: 245285405Sbapt case 0x24: 246285405Sbapt i = Add_Chunk(d, off, len, n, fat, ty, 0, sn); 247285405Sbapt break; 248286196Sbapt default: 249285405Sbapt i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn); 250285405Sbapt break; 251285405Sbapt } 252285405Sbapt } else if (!strcmp(t, "GPT")) 253285405Sbapt i = Add_Chunk(d, off, len, n, ty, 0, 0, 0); 254286196Sbapt else if (!strcmp(t, "BDE")) 255286196Sbapt ; /* nothing */ 25620253Sjoerg else if (!strcmp(t, "CCD")) 257286196Sbapt ; /* nothing */ 258286196Sbapt else { 259286196Sbapt printf("BARF %d\n", __LINE__); 26020253Sjoerg exit(0); 26120267Sjoerg } 262286196Sbapt } 26320253Sjoerg /* PLATFORM POLICY BEGIN ------------------------------------- */ 264286196Sbapt /* We have a chance to do things on a blank disk here */ 265286196Sbapt if (platform == p_sparc64 && d->chunks->part->part == NULL) { 26620253Sjoerg hd = d->bios_hd; 267286196Sbapt sc = d->bios_sect; 268286196Sbapt o = d->chunks->size / (hd * sc); 269286196Sbapt o *= (hd * sc); 270286196Sbapt o -= 2 * hd * sc; 27120253Sjoerg if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) 27221052Sdavidn DPRINT(("Failed to add 'freebsd' chunk")); 273286196Sbapt } 274286196Sbapt /* PLATFORM POLICY END --------------------------------------- */ 275286196Sbapt 27621052Sdavidn return (d); 277286196Sbapt i = 0; 278286196Sbapt} 279286196Sbapt