open_disk.c revision 133028
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 */ 9 10#include <sys/cdefs.h> 11__FBSDID("$FreeBSD: head/lib/libdisk/open_disk.c 133028 2004-08-02 19:14:58Z le $"); 12 13#include <stdio.h> 14#include <stdlib.h> 15#include <unistd.h> 16#include <fcntl.h> 17#include <string.h> 18#include <inttypes.h> 19#include <err.h> 20#include <sys/sysctl.h> 21#include <sys/stdint.h> 22#include <sys/types.h> 23#include <sys/stat.h> 24#include <sys/ioctl.h> 25#include <sys/disklabel.h> 26#include <sys/gpt.h> 27#include <paths.h> 28#include "libdisk.h" 29 30#include <ctype.h> 31#include <errno.h> 32#include <assert.h> 33 34#ifdef DEBUG 35#define DPRINT(x) warn x 36#define DPRINTX(x) warnx x 37#else 38#define DPRINT(x) 39#define DPRINTX(x) 40#endif 41 42struct disk * 43Int_Open_Disk(const char *name, char *conftxt) 44{ 45 struct disk *d; 46 int i; 47 char *p, *q, *r, *a, *b, *n, *t, *sn; 48 daddr_t o, len, off; 49 u_int l, s, ty, sc, hd, alt; 50 daddr_t lo[10]; 51 52 for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) { 53 if (*p == '\n') 54 p++; 55 a = strsep(&p, " "); 56 if (strcmp(a, "0")) 57 continue; 58 59 a = strsep(&p, " "); 60 if (strcmp(a, "DISK")) 61 continue; 62 63 a = strsep(&p, " "); 64 if (strcmp(a, name)) 65 continue; 66 break; 67 } 68 69 q = strchr(p, '\n'); 70 if (q != NULL) 71 *q++ = '\0'; 72 73 d = (struct disk *)calloc(sizeof *d, 1); 74 if(d == NULL) 75 return NULL; 76 77 d->name = strdup(name); 78 79 a = strsep(&p, " "); /* length in bytes */ 80 len = strtoimax(a, &r, 0); 81 if (*r) { 82 printf("BARF %d <%d>\n", __LINE__, *r); 83 exit (0); 84 } 85 86 a = strsep(&p, " "); /* sectorsize */ 87 s = strtoul(a, &r, 0); 88 if (*r) { 89 printf("BARF %d <%d>\n", __LINE__, *r); 90 exit (0); 91 } 92 93 if (s == 0) 94 return (NULL); 95 d->sector_size = s; 96 len /= s; /* media size in number of sectors. */ 97 98 if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-")) { 99 DPRINT(("Failed to add 'whole' chunk")); 100 } 101 102 for (;;) { 103 a = strsep(&p, " "); 104 if (a == NULL) 105 break; 106 b = strsep(&p, " "); 107 o = strtoimax(b, &r, 0); 108 if (*r) { 109 printf("BARF %d <%d>\n", __LINE__, *r); 110 exit (0); 111 } 112 if (!strcmp(a, "hd")) 113 d->bios_hd = o; 114 else if (!strcmp(a, "sc")) 115 d->bios_sect = o; 116 else 117 printf("HUH ? <%s> <%s>\n", a, b); 118 } 119 120 /* 121 * Calculate the number of cylinders this disk must have. If we have 122 * an obvious insanity, we set the number of cyclinders to zero. 123 */ 124 o = d->bios_hd * d->bios_sect; 125 d->bios_cyl = (o != 0) ? len / o : 0; 126 127 p = q; 128 lo[0] = 0; 129 130 for (; p != NULL && *p; p = q) { 131 if (sn) 132 sn = NULL; 133 q = strchr(p, '\n'); 134 if (q != NULL) 135 *q++ = '\0'; 136 a = strsep(&p, " "); /* Index */ 137 if (!strcmp(a, "0")) 138 break; 139 l = strtoimax(a, &r, 0); 140 if (*r) { 141 printf("BARF %d <%d>\n", __LINE__, *r); 142 exit (0); 143 } 144 t = strsep(&p, " "); /* Type {SUN, BSD, MBR, PC98, GPT} */ 145 n = strsep(&p, " "); /* name */ 146 a = strsep(&p, " "); /* len */ 147 len = strtoimax(a, &r, 0); 148 if (*r) { 149 printf("BARF %d <%d>\n", __LINE__, *r); 150 exit (0); 151 } 152 a = strsep(&p, " "); /* secsize */ 153 s = strtoimax(a, &r, 0); 154 if (*r) { 155 printf("BARF %d <%d>\n", __LINE__, *r); 156 exit (0); 157 } 158 for (;;) { 159 a = strsep(&p, " "); 160 if (a == NULL) 161 break; 162 /* XXX: Slice name may include a space. */ 163 if (!strcmp(a, "sn")) { 164 sn = p; 165 break; 166 } 167 b = strsep(&p, " "); 168 o = strtoimax(b, &r, 0); 169 /* APPLE have ty as a string */ 170 if ((*r) && strcmp(t, "APPLE")) { 171 printf("BARF %d <%d>\n", __LINE__, *r); 172 exit (0); 173 } 174 if (!strcmp(a, "o")) 175 off = o; 176 else if (!strcmp(a, "i")) 177 i = o; 178 else if (!strcmp(a, "ty")) 179 ty = o; 180 else if (!strcmp(a, "sc")) 181 sc = o; 182 else if (!strcmp(a, "hd")) 183 hd = o; 184 else if (!strcmp(a, "alt")) 185 alt = o; 186 } 187 188 /* PLATFORM POLICY BEGIN ----------------------------------- */ 189 if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) 190 continue; 191 if (platform == p_sparc64 && !strcmp(t, "SUN") && 192 d->chunks->part->part == NULL) { 193 d->bios_hd = hd; 194 d->bios_sect = sc; 195 o = d->chunks->size / (hd * sc); 196 o *= (hd * sc); 197 o -= alt * hd * sc; 198 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 199 DPRINT(("Failed to add 'freebsd' chunk")); 200 } 201 } 202 if (platform == p_alpha && !strcmp(t, "BSD") && 203 d->chunks->part->part == NULL) { 204 if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 205 0, 0, "-")) { 206 DPRINT(("Failed to add 'freebsd' chunk")); 207 } 208 } 209 if (!strcmp(t, "BSD") && i == RAW_PART) 210 continue; 211 /* PLATFORM POLICY END ------------------------------------- */ 212 213 off /= s; 214 len /= s; 215 off += lo[l - 1]; 216 lo[l] = off; 217 if (!strcmp(t, "SUN")) 218 i = Add_Chunk(d, off, len, n, part, 0, 0, 0); 219 else if (!strncmp(t, "MBR", 3)) { 220 switch (ty) { 221 case 0xa5: 222 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0); 223 break; 224 case 0x01: 225 case 0x04: 226 case 0x06: 227 case 0x0b: 228 case 0x0c: 229 case 0x0e: 230 i = Add_Chunk(d, off, len, n, fat, ty, 0, 0); 231 break; 232 case 0xef: /* EFI */ 233 i = Add_Chunk(d, off, len, n, efi, ty, 0, 0); 234 break; 235 default: 236 i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0); 237 break; 238 } 239 } else if (!strcmp(t, "BSD")) 240 i = Add_Chunk(d, off, len, n, part, ty, 0, 0); 241 else if (!strcmp(t, "PC98")) { 242 switch (ty & 0x7f) { 243 case 0x14: 244 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 245 sn); 246 break; 247 case 0x20: 248 case 0x21: 249 case 0x22: 250 case 0x23: 251 case 0x24: 252 i = Add_Chunk(d, off, len, n, fat, ty, 0, sn); 253 break; 254 default: 255 i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn); 256 break; 257 } 258 } else if (!strcmp(t, "GPT")) 259 i = Add_Chunk(d, off, len, n, ty, 0, 0, 0); 260 else if (!strcmp(t, "BDE")) 261 ; /* nothing */ 262 else if (!strcmp(t, "CCD")) 263 ; /* nothing */ 264 else if (!strcmp(t, "APPLE")) 265 i = Add_Chunk(d, off, len, n, apple, 0, 0, sn); 266 else if (strstr(t, "VINUM") != NULL) 267 ; /* nothing */ 268 else { 269 printf("BARF %d\n", __LINE__); 270 exit(0); 271 } 272 } 273 /* PLATFORM POLICY BEGIN ------------------------------------- */ 274 /* We have a chance to do things on a blank disk here */ 275 if (platform == p_sparc64 && d->chunks->part->part == NULL) { 276 hd = d->bios_hd; 277 sc = d->bios_sect; 278 o = d->chunks->size / (hd * sc); 279 o *= (hd * sc); 280 o -= 2 * hd * sc; 281 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 282 DPRINT(("Failed to add 'freebsd' chunk")); 283 } 284 } 285 /* PLATFORM POLICY END --------------------------------------- */ 286 287 return (d); 288 i = 0; 289} 290