open_disk.c revision 127595
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 127595 2004-03-30 01:39:00Z kuriyama $"); 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 q = strchr(p, '\n'); 132 if (q != NULL) 133 *q++ = '\0'; 134 a = strsep(&p, " "); /* Index */ 135 if (!strcmp(a, "0")) 136 break; 137 l = strtoimax(a, &r, 0); 138 if (*r) { 139 printf("BARF %d <%d>\n", __LINE__, *r); 140 exit (0); 141 } 142 t = strsep(&p, " "); /* Type {SUN, BSD, MBR, PC98, GPT} */ 143 n = strsep(&p, " "); /* name */ 144 a = strsep(&p, " "); /* len */ 145 len = strtoimax(a, &r, 0); 146 if (*r) { 147 printf("BARF %d <%d>\n", __LINE__, *r); 148 exit (0); 149 } 150 a = strsep(&p, " "); /* secsize */ 151 s = strtoimax(a, &r, 0); 152 if (*r) { 153 printf("BARF %d <%d>\n", __LINE__, *r); 154 exit (0); 155 } 156 for (;;) { 157 a = strsep(&p, " "); 158 if (a == NULL) 159 break; 160 /* XXX: Slice name may include a space. */ 161 if (!strcmp(a, "sn")) { 162 sn = p; 163 break; 164 } 165 b = strsep(&p, " "); 166 o = strtoimax(b, &r, 0); 167 if (*r) { 168 printf("BARF %d <%d>\n", __LINE__, *r); 169 exit (0); 170 } 171 if (!strcmp(a, "o")) 172 off = o; 173 else if (!strcmp(a, "i")) 174 i = o; 175 else if (!strcmp(a, "ty")) 176 ty = o; 177 else if (!strcmp(a, "sc")) 178 sc = o; 179 else if (!strcmp(a, "hd")) 180 hd = o; 181 else if (!strcmp(a, "alt")) 182 alt = o; 183 } 184 185 /* PLATFORM POLICY BEGIN ----------------------------------- */ 186 if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) 187 continue; 188 if (platform == p_sparc64 && !strcmp(t, "SUN") && 189 d->chunks->part->part == NULL) { 190 d->bios_hd = hd; 191 d->bios_sect = sc; 192 o = d->chunks->size / (hd * sc); 193 o *= (hd * sc); 194 o -= alt * hd * sc; 195 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 196 DPRINT(("Failed to add 'freebsd' chunk")); 197 } 198 } 199 if (platform == p_alpha && !strcmp(t, "BSD") && 200 d->chunks->part->part == NULL) { 201 if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 202 0, 0, "-")) { 203 DPRINT(("Failed to add 'freebsd' chunk")); 204 } 205 } 206 if (!strcmp(t, "BSD") && i == RAW_PART) 207 continue; 208 /* PLATFORM POLICY END ------------------------------------- */ 209 210 off /= s; 211 len /= s; 212 off += lo[l - 1]; 213 lo[l] = off; 214 if (!strcmp(t, "SUN")) 215 i = Add_Chunk(d, off, len, n, part, 0, 0, 0); 216 else if (!strncmp(t, "MBR", 3)) { 217 switch (ty) { 218 case 0xa5: 219 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0); 220 break; 221 case 0x01: 222 case 0x04: 223 case 0x06: 224 case 0x0b: 225 case 0x0c: 226 case 0x0e: 227 i = Add_Chunk(d, off, len, n, fat, ty, 0, 0); 228 break; 229 case 0xef: /* EFI */ 230 i = Add_Chunk(d, off, len, n, efi, ty, 0, 0); 231 break; 232 default: 233 i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0); 234 break; 235 } 236 } else if (!strcmp(t, "BSD")) 237 i = Add_Chunk(d, off, len, n, part, ty, 0, 0); 238 else if (!strcmp(t, "PC98")) { 239 switch (ty & 0x7f) { 240 case 0x14: 241 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 242 sn); 243 break; 244 case 0x20: 245 case 0x21: 246 case 0x22: 247 case 0x23: 248 case 0x24: 249 i = Add_Chunk(d, off, len, n, fat, ty, 0, sn); 250 break; 251 default: 252 i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn); 253 break; 254 } 255 } else if (!strcmp(t, "GPT")) 256 i = Add_Chunk(d, off, len, n, ty, 0, 0, 0); 257 else if (!strcmp(t, "BDE")) 258 ; /* nothing */ 259 else if (!strcmp(t, "CCD")) 260 ; /* nothing */ 261 else { 262 printf("BARF %d\n", __LINE__); 263 exit(0); 264 } 265 } 266 /* PLATFORM POLICY BEGIN ------------------------------------- */ 267 /* We have a chance to do things on a blank disk here */ 268 if (platform == p_sparc64 && d->chunks->part->part == NULL) { 269 hd = d->bios_hd; 270 sc = d->bios_sect; 271 o = d->chunks->size / (hd * sc); 272 o *= (hd * sc); 273 o -= 2 * hd * sc; 274 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 275 DPRINT(("Failed to add 'freebsd' chunk")); 276 } 277 } 278 /* PLATFORM POLICY END --------------------------------------- */ 279 280 return (d); 281 i = 0; 282} 283