open_disk.c revision 143306
1273929Sjmmv/* 2240116Smarcel * ---------------------------------------------------------------------------- 3240116Smarcel * "THE BEER-WARE LICENSE" (Revision 42): 4240116Smarcel * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5240116Smarcel * can do whatever you want with this stuff. If we meet some day, and you think 6240116Smarcel * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7240116Smarcel * ---------------------------------------------------------------------------- 8240116Smarcel */ 9240116Smarcel 10240116Smarcel#include <sys/cdefs.h> 11240116Smarcel__FBSDID("$FreeBSD: head/lib/libdisk/open_disk.c 143306 2005-03-08 21:46:18Z stefanf $"); 12240116Smarcel 13240116Smarcel#include <stdio.h> 14240116Smarcel#include <stdlib.h> 15240116Smarcel#include <unistd.h> 16240116Smarcel#include <fcntl.h> 17240116Smarcel#include <string.h> 18240116Smarcel#include <inttypes.h> 19240116Smarcel#include <err.h> 20240116Smarcel#include <sys/sysctl.h> 21240116Smarcel#include <sys/stdint.h> 22240116Smarcel#include <sys/types.h> 23240116Smarcel#include <sys/stat.h> 24273929Sjmmv#include <sys/ioctl.h> 25240116Smarcel#include <sys/disklabel.h> 26240116Smarcel#include <sys/gpt.h> 27240116Smarcel#include <paths.h> 28240116Smarcel#include "libdisk.h" 29240116Smarcel 30240116Smarcel#include <ctype.h> 31240116Smarcel#include <errno.h> 32240116Smarcel#include <assert.h> 33240116Smarcel 34240116Smarcel#ifdef DEBUG 35240116Smarcel#define DPRINT(x) warn x 36240116Smarcel#define DPRINTX(x) warnx x 37240116Smarcel#else 38240116Smarcel#define DPRINT(x) 39240116Smarcel#define DPRINTX(x) 40240116Smarcel#endif 41240116Smarcel 42240116Smarcelstruct disk * 43240116SmarcelInt_Open_Disk(const char *name, char *conftxt) 44240116Smarcel{ 45240116Smarcel struct disk *d; 46240116Smarcel int i; 47240116Smarcel char *p, *q, *r, *a, *b, *n, *t, *sn; 48240116Smarcel daddr_t o, len, off; 49240116Smarcel u_int l, s, ty, sc, hd, alt; 50240116Smarcel daddr_t lo[10]; 51240116Smarcel 52240116Smarcel for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) { 53240116Smarcel if (*p == '\n') 54240116Smarcel p++; 55240116Smarcel a = strsep(&p, " "); 56240116Smarcel if (strcmp(a, "0")) 57240116Smarcel continue; 58240116Smarcel 59240116Smarcel a = strsep(&p, " "); 60240116Smarcel if (strcmp(a, "DISK")) 61240116Smarcel continue; 62240116Smarcel 63240116Smarcel a = strsep(&p, " "); 64240116Smarcel if (strcmp(a, name)) 65240116Smarcel continue; 66240116Smarcel break; 67240116Smarcel } 68240116Smarcel 69240116Smarcel q = strchr(p, '\n'); 70240116Smarcel if (q != NULL) 71240116Smarcel *q++ = '\0'; 72240116Smarcel 73240116Smarcel d = (struct disk *)calloc(sizeof *d, 1); 74240116Smarcel if(d == NULL) 75240116Smarcel return NULL; 76240116Smarcel 77240116Smarcel d->name = strdup(name); 78240116Smarcel 79240116Smarcel a = strsep(&p, " "); /* length in bytes */ 80240116Smarcel len = strtoimax(a, &r, 0); 81240116Smarcel if (*r) { 82240116Smarcel printf("BARF %d <%d>\n", __LINE__, *r); 83240116Smarcel exit (0); 84240116Smarcel } 85240116Smarcel 86240116Smarcel a = strsep(&p, " "); /* sectorsize */ 87240116Smarcel s = strtoul(a, &r, 0); 88240116Smarcel if (*r) { 89240116Smarcel printf("BARF %d <%d>\n", __LINE__, *r); 90240116Smarcel exit (0); 91240116Smarcel } 92240116Smarcel 93240116Smarcel if (s == 0) 94240116Smarcel return (NULL); 95240116Smarcel d->sector_size = s; 96240116Smarcel len /= s; /* media size in number of sectors. */ 97240116Smarcel 98240116Smarcel if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-")) { 99240116Smarcel DPRINT(("Failed to add 'whole' chunk")); 100240116Smarcel } 101240116Smarcel 102240116Smarcel for (;;) { 103240116Smarcel a = strsep(&p, " "); 104240116Smarcel if (a == NULL) 105240116Smarcel break; 106240116Smarcel b = strsep(&p, " "); 107240116Smarcel o = strtoimax(b, &r, 0); 108240116Smarcel if (*r) { 109240116Smarcel printf("BARF %d <%d>\n", __LINE__, *r); 110240116Smarcel exit (0); 111240116Smarcel } 112240116Smarcel if (!strcmp(a, "hd")) 113240116Smarcel d->bios_hd = o; 114240116Smarcel else if (!strcmp(a, "sc")) 115240116Smarcel d->bios_sect = o; 116240116Smarcel else 117240116Smarcel printf("HUH ? <%s> <%s>\n", a, b); 118240116Smarcel } 119240116Smarcel 120240116Smarcel /* 121240116Smarcel * Calculate the number of cylinders this disk must have. If we have 122240116Smarcel * an obvious insanity, we set the number of cylinders to zero. 123240116Smarcel */ 124240116Smarcel o = d->bios_hd * d->bios_sect; 125240116Smarcel d->bios_cyl = (o != 0) ? len / o : 0; 126240116Smarcel 127240116Smarcel p = q; 128240116Smarcel lo[0] = 0; 129240116Smarcel 130240116Smarcel for (; p != NULL && *p; p = q) { 131240116Smarcel sn = NULL; 132240116Smarcel q = strchr(p, '\n'); 133240116Smarcel if (q != NULL) 134240116Smarcel *q++ = '\0'; 135240116Smarcel a = strsep(&p, " "); /* Index */ 136273929Sjmmv if (!strcmp(a, "0")) 137 break; 138 l = strtoimax(a, &r, 0); 139 if (*r) { 140 printf("BARF %d <%d>\n", __LINE__, *r); 141 exit (0); 142 } 143 t = strsep(&p, " "); /* Type {SUN, BSD, MBR, PC98, GPT} */ 144 n = strsep(&p, " "); /* name */ 145 a = strsep(&p, " "); /* len */ 146 len = strtoimax(a, &r, 0); 147 if (*r) { 148 printf("BARF %d <%d>\n", __LINE__, *r); 149 exit (0); 150 } 151 a = strsep(&p, " "); /* secsize */ 152 s = strtoimax(a, &r, 0); 153 if (*r) { 154 printf("BARF %d <%d>\n", __LINE__, *r); 155 exit (0); 156 } 157 for (;;) { 158 a = strsep(&p, " "); 159 if (a == NULL) 160 break; 161 /* XXX: Slice name may include a space. */ 162 if (!strcmp(a, "sn")) { 163 sn = p; 164 break; 165 } 166 b = strsep(&p, " "); 167 o = strtoimax(b, &r, 0); 168 /* APPLE have ty as a string */ 169 if ((*r) && (strcmp(t, "APPLE") && strcmp(t, "GPT"))) { 170 printf("BARF %d <%d>\n", __LINE__, *r); 171 exit (0); 172 } 173 if (!strcmp(a, "o")) 174 off = o; 175 else if (!strcmp(a, "i")) 176 i = o; 177 else if (!strcmp(a, "ty")) 178 ty = o; 179 else if (!strcmp(a, "sc")) 180 sc = o; 181 else if (!strcmp(a, "hd")) 182 hd = o; 183 else if (!strcmp(a, "alt")) 184 alt = o; 185 } 186 187 /* PLATFORM POLICY BEGIN ----------------------------------- */ 188 if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) 189 continue; 190 if (platform == p_sparc64 && !strcmp(t, "SUN") && 191 d->chunks->part->part == NULL) { 192 d->bios_hd = hd; 193 d->bios_sect = sc; 194 o = d->chunks->size / (hd * sc); 195 o *= (hd * sc); 196 o -= alt * hd * sc; 197 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 198 DPRINT(("Failed to add 'freebsd' chunk")); 199 } 200 } 201 if (platform == p_alpha && !strcmp(t, "BSD") && 202 d->chunks->part->part == NULL) { 203 if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 204 0, 0, "-")) { 205 DPRINT(("Failed to add 'freebsd' chunk")); 206 } 207 } 208 if (!strcmp(t, "BSD") && i == RAW_PART) 209 continue; 210 /* PLATFORM POLICY END ------------------------------------- */ 211 212 off /= s; 213 len /= s; 214 off += lo[l - 1]; 215 lo[l] = off; 216 if (!strcmp(t, "SUN")) 217 i = Add_Chunk(d, off, len, n, part, 0, 0, 0); 218 else if (!strncmp(t, "MBR", 3)) { 219 switch (ty) { 220 case 0xa5: 221 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0); 222 break; 223 case 0x01: 224 case 0x04: 225 case 0x06: 226 case 0x0b: 227 case 0x0c: 228 case 0x0e: 229 i = Add_Chunk(d, off, len, n, fat, ty, 0, 0); 230 break; 231 case 0xef: /* EFI */ 232 i = Add_Chunk(d, off, len, n, efi, ty, 0, 0); 233 break; 234 default: 235 i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0); 236 break; 237 } 238 } else if (!strcmp(t, "BSD")) 239 i = Add_Chunk(d, off, len, n, part, ty, 0, 0); 240 else if (!strcmp(t, "PC98")) { 241 switch (ty & 0x7f) { 242 case 0x14: 243 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 244 sn); 245 break; 246 case 0x20: 247 case 0x21: 248 case 0x22: 249 case 0x23: 250 case 0x24: 251 i = Add_Chunk(d, off, len, n, fat, ty, 0, sn); 252 break; 253 default: 254 i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn); 255 break; 256 } 257 } else if (!strcmp(t, "GPT")) 258 i = Add_Chunk(d, off, len, n, gpt, 0, 0, b); 259 else if (!strcmp(t, "APPLE")) 260 i = Add_Chunk(d, off, len, n, apple, 0, 0, sn); 261 else 262 ; /* Ignore unknown classes. */ 263 } 264 /* PLATFORM POLICY BEGIN ------------------------------------- */ 265 /* We have a chance to do things on a blank disk here */ 266 if (platform == p_sparc64 && d->chunks->part->part == NULL) { 267 hd = d->bios_hd; 268 sc = d->bios_sect; 269 o = d->chunks->size / (hd * sc); 270 o *= (hd * sc); 271 o -= 2 * hd * sc; 272 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 273 DPRINT(("Failed to add 'freebsd' chunk")); 274 } 275 } 276 /* PLATFORM POLICY END --------------------------------------- */ 277 278 return (d); 279 i = 0; 280} 281