open_disk.c revision 171734
165793Smsmith/* 265793Smsmith * ---------------------------------------------------------------------------- 381150Sscottl * "THE BEER-WARE LICENSE" (Revision 42): 465793Smsmith * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 581082Sscottl * can do whatever you want with this stuff. If we meet some day, and you think 665793Smsmith * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 765793Smsmith * ---------------------------------------------------------------------------- 865793Smsmith */ 965793Smsmith 1065793Smsmith#include <sys/cdefs.h> 1165793Smsmith__FBSDID("$FreeBSD: head/lib/libdisk/open_disk.c 171734 2007-08-05 16:55:40Z rink $"); 1265793Smsmith 1365793Smsmith#include <stdio.h> 1465793Smsmith#include <stdlib.h> 1565793Smsmith#include <unistd.h> 1665793Smsmith#include <fcntl.h> 1765793Smsmith#include <string.h> 1865793Smsmith#include <inttypes.h> 1965793Smsmith#include <err.h> 2065793Smsmith#include <sys/sysctl.h> 2165793Smsmith#include <sys/stdint.h> 2265793Smsmith#include <sys/types.h> 2365793Smsmith#include <sys/stat.h> 2465793Smsmith#include <sys/ioctl.h> 2565793Smsmith#include <sys/disklabel.h> 2665793Smsmith#include <sys/gpt.h> 2765793Smsmith#include <paths.h> 2865793Smsmith#include "libdisk.h" 2965793Smsmith 3065793Smsmith#include <ctype.h> 3165793Smsmith#include <errno.h> 3265793Smsmith#include <assert.h> 3365793Smsmith 3465793Smsmith#ifdef DEBUG 3565793Smsmith#define DPRINT(x) warn x 3665793Smsmith#define DPRINTX(x) warnx x 3765793Smsmith#else 3865793Smsmith#define DPRINT(x) 3983114Sscottl#define DPRINTX(x) 4065793Smsmith#endif 4165793Smsmith 4265793Smsmithstruct disk * 4365793SmsmithInt_Open_Disk(const char *name, char *conftxt) 4465793Smsmith{ 4583114Sscottl struct disk *d; 4665793Smsmith int i, line = 1; 4765793Smsmith char *p, *q, *r, *a, *b, *n, *t, *sn; 4865793Smsmith daddr_t o, len, off; 4965793Smsmith u_int l, s, ty, sc, hd, alt; 5065793Smsmith daddr_t lo[10]; 5165793Smsmith 5265793Smsmith /* 5365793Smsmith * Locate the disk (by name) in our sysctl output 5465793Smsmith */ 5565793Smsmith for (p = conftxt; p != NULL && *p; p = strchr(p, '\n'), line++) { 5681082Sscottl if (*p == '\n') 5781082Sscottl p++; 5881082Sscottl a = strsep(&p, " "); 5981082Sscottl /* Skip anything not with index 0 */ 6081082Sscottl if (strcmp(a, "0")) 6181082Sscottl continue; 6281082Sscottl 6381082Sscottl /* Skip anything not a disk */ 6481082Sscottl a = strsep(&p, " "); 6581082Sscottl if (strcmp(a, "DISK")) 6681082Sscottl continue; 6781082Sscottl 6881082Sscottl a = strsep(&p, " "); 6981082Sscottl if (strcmp(a, name)) 7081082Sscottl continue; 7181082Sscottl break; 7265793Smsmith } 7365793Smsmith 7465793Smsmith q = strchr(p, '\n'); 7565793Smsmith if (q != NULL) 7665793Smsmith *q++ = '\0'; 7765793Smsmith 7865793Smsmith d = (struct disk *)calloc(sizeof *d, 1); 7965793Smsmith if(d == NULL) 8065793Smsmith return NULL; 8165793Smsmith 8265793Smsmith d->name = strdup(name); 8365793Smsmith 8465793Smsmith a = strsep(&p, " "); /* length in bytes */ 8583114Sscottl len = strtoimax(a, &r, 0); 8683114Sscottl if (*r) { 87103870Salfred printf("libdisk: Int_Open_Disk(%s): can't parse length in line %d (r='%s')\n", 8865793Smsmith name, line, r); 8965793Smsmith return NULL; 9065793Smsmith } 9165793Smsmith 9265793Smsmith a = strsep(&p, " "); /* sectorsize */ 9365793Smsmith s = strtoul(a, &r, 0); 9465793Smsmith if (*r) { 9565793Smsmith printf("libdisk: Int_Open_Disk(%s): can't parse sector size in line %d (r='%s')\n", 9665793Smsmith name, line, r); 9783114Sscottl return NULL; 9883114Sscottl } 9965793Smsmith 10083114Sscottl if (s == 0) 10183114Sscottl return (NULL); 10283114Sscottl d->sector_size = s; 10383114Sscottl len /= s; /* media size in number of sectors. */ 10483114Sscottl 10583114Sscottl if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-")) { 10683114Sscottl DPRINT(("Failed to add 'whole' chunk")); 10783114Sscottl } 10883114Sscottl 109103870Salfred /* Try to parse any fields after the sector size in the DISK entry line */ 11065793Smsmith for (;;) { 11165793Smsmith a = strsep(&p, " "); 11265793Smsmith if (a == NULL) 11365793Smsmith break; 11465793Smsmith b = strsep(&p, " "); 11565793Smsmith o = strtoimax(b, &r, 0); 11665793Smsmith if (*r) { 11765793Smsmith printf("libdisk: Int_Open_Disk(%s): can't parse parameter '%s' in line %d (r='%s')\n", 11865793Smsmith name, a, line, r); 11965793Smsmith return NULL; 12065793Smsmith } 12165793Smsmith if (!strcmp(a, "hd")) 12265793Smsmith d->bios_hd = o; 12365793Smsmith else if (!strcmp(a, "sc")) 12465793Smsmith d->bios_sect = o; 12565793Smsmith else 12665793Smsmith printf("libdisk: Int_Open_Disk(%s): unknown parameter '%s' with value '%s' in line %d, ignored\n", 12765793Smsmith name, a, b, line); 12865793Smsmith } 12965793Smsmith 13065793Smsmith /* 131109088Sscottl * Calculate the number of cylinders this disk must have. If we have 132109088Sscottl * an obvious insanity, we set the number of cylinders to zero. 133103870Salfred */ 13465793Smsmith o = d->bios_hd * d->bios_sect; 13565793Smsmith d->bios_cyl = (o != 0) ? len / o : 0; 13665793Smsmith 13765793Smsmith p = q; line++; /* p is now the start of the line _after_ the DISK entry */ 13865793Smsmith lo[0] = 0; 13965793Smsmith 14083114Sscottl for (; p != NULL && *p; p = q, line++) { 14183114Sscottl sn = NULL; 14283114Sscottl q = strchr(p, '\n'); 14383114Sscottl if (q != NULL) 14483114Sscottl *q++ = '\0'; 14583114Sscottl a = strsep(&p, " "); /* Index */ 14683114Sscottl /* 14783114Sscottl * If we find index 0 again, this means we've encountered another disk, so it's safe to assume this disk 14883114Sscottl * has been processed. 14983114Sscottl */ 15083114Sscottl if (!strcmp(a, "0")) 15183114Sscottl break; 15283114Sscottl l = strtoimax(a, &r, 0); 15383114Sscottl if (*r) { 15483114Sscottl printf("libdisk: Int_Open_Disk(%s): can't parse depth '%s' in line %d (r='%s')\n", 15583114Sscottl name, a, line, r); 156103870Salfred return NULL; 15765793Smsmith 15865793Smsmith } 15965793Smsmith t = strsep(&p, " "); /* Type {SUN, BSD, MBR, PC98, GPT} */ 16065793Smsmith n = strsep(&p, " "); /* name */ 16183114Sscottl a = strsep(&p, " "); /* len */ 16283114Sscottl len = strtoimax(a, &r, 0); 163103870Salfred if (*r) { 16465793Smsmith printf("libdisk: Int_Open_Disk(%s): can't parse length '%s' in line %d (r='%s')\n", 16565793Smsmith name, a, line, r); 16665793Smsmith continue; 16765793Smsmith } 16865793Smsmith a = strsep(&p, " "); /* secsize */ 16983114Sscottl s = strtoimax(a, &r, 0); 17083114Sscottl if (*r) { 17165793Smsmith printf("libdisk: Int_Open_Disk(%s): can't parse sector size '%s' in line %d (r='%s')\n", 17283114Sscottl name, a, line, r); 17383114Sscottl continue; 17483114Sscottl } 17583114Sscottl for (;;) { 17683114Sscottl a = strsep(&p, " "); 17783114Sscottl if (a == NULL) 17883114Sscottl break; 17983114Sscottl /* XXX: Slice name may include a space. */ 18083114Sscottl if (!strcmp(a, "sn")) { 18183114Sscottl sn = p; 18283114Sscottl break; 18383114Sscottl } 18483114Sscottl b = strsep(&p, " "); 18583114Sscottl o = strtoimax(b, &r, 0); 18683114Sscottl /* APPLE have ty as a string */ 18783114Sscottl if ((*r) && (strcmp(t, "APPLE") && strcmp(t, "GPT"))) { 18883114Sscottl printf("libdisk: Int_Open_Disk(%s): can't parse parameter '%s' in line %d (r='%s')\n", 18983114Sscottl name, a, line, r); 19083114Sscottl break; 19183114Sscottl } 19283114Sscottl if (!strcmp(a, "o")) 19365793Smsmith off = o; 19483114Sscottl else if (!strcmp(a, "i")) 19583114Sscottl i = o; 19683114Sscottl else if (!strcmp(a, "ty")) 19783114Sscottl ty = o; 19883114Sscottl else if (!strcmp(a, "sc")) 19965793Smsmith sc = o; 20083114Sscottl else if (!strcmp(a, "hd")) 20183114Sscottl hd = o; 20283114Sscottl else if (!strcmp(a, "alt")) 203151086Sscottl alt = o; 20465793Smsmith } 20583114Sscottl 20683114Sscottl /* PLATFORM POLICY BEGIN ----------------------------------- */ 20765793Smsmith if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2) 20883114Sscottl continue; 20983114Sscottl if (platform == p_sparc64 && !strcmp(t, "SUN") && 210151086Sscottl d->chunks->part->part == NULL) { 211151086Sscottl d->bios_hd = hd; 212151086Sscottl d->bios_sect = sc; 213151086Sscottl o = d->chunks->size / (hd * sc); 21465793Smsmith o *= (hd * sc); 21583114Sscottl o -= alt * hd * sc; 21683114Sscottl if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 21783114Sscottl DPRINT(("Failed to add 'freebsd' chunk")); 21883114Sscottl } 21983114Sscottl } 22083114Sscottl if (platform == p_alpha && !strcmp(t, "BSD") && 22183114Sscottl d->chunks->part->part == NULL) { 222151086Sscottl if (Add_Chunk(d, 0, d->chunks->size, name, freebsd, 223206534Semaste 0, 0, "-")) { 224151086Sscottl DPRINT(("Failed to add 'freebsd' chunk")); 225151086Sscottl } 226206534Semaste } 227206534Semaste if (!strcmp(t, "BSD") && i == RAW_PART) 228206534Semaste continue; 229151086Sscottl /* PLATFORM POLICY END ------------------------------------- */ 230151086Sscottl 231151086Sscottl off /= s; 232151086Sscottl len /= s; 233151086Sscottl off += lo[l - 1]; 234151086Sscottl lo[l] = off; 235206534Semaste if (!strcmp(t, "SUN")) 236206534Semaste i = Add_Chunk(d, off, len, n, part, 0, 0, 0); 23765793Smsmith else if (!strncmp(t, "MBR", 3)) { 23865793Smsmith switch (ty) { 23965793Smsmith case 0xa5: 24065793Smsmith i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0); 24165793Smsmith break; 24265793Smsmith case 0x01: 24365793Smsmith case 0x04: 24465793Smsmith case 0x06: 24565793Smsmith case 0x0b: 24665793Smsmith case 0x0c: 24765793Smsmith case 0x0e: 24865793Smsmith i = Add_Chunk(d, off, len, n, fat, ty, 0, 0); 24981082Sscottl break; 25081082Sscottl case 0xef: /* EFI */ 25181082Sscottl i = Add_Chunk(d, off, len, n, efi, ty, 0, 0); 25281082Sscottl break; 25381082Sscottl default: 25481082Sscottl i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0); 25581082Sscottl break; 25681082Sscottl } 25781082Sscottl } else if (!strcmp(t, "BSD")) 25881082Sscottl i = Add_Chunk(d, off, len, n, part, ty, 0, 0); 25981082Sscottl else if (!strcmp(t, "PC98")) { 26081082Sscottl switch (ty & 0x7f) { 26181082Sscottl case 0x14: 26281082Sscottl i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 26381082Sscottl sn); 26481082Sscottl break; 26581082Sscottl case 0x20: 26681082Sscottl case 0x21: 26781082Sscottl case 0x22: 26881082Sscottl case 0x23: 26981082Sscottl case 0x24: 27081082Sscottl i = Add_Chunk(d, off, len, n, fat, ty, 0, sn); 27165793Smsmith break; 27265793Smsmith default: 27365793Smsmith i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn); 27465793Smsmith break; 27565793Smsmith } 27665793Smsmith } else if (!strcmp(t, "GPT")) 27765793Smsmith i = Add_Chunk(d, off, len, n, gpt, 0, 0, b); 27865793Smsmith else if (!strcmp(t, "APPLE")) 27965793Smsmith i = Add_Chunk(d, off, len, n, apple, 0, 0, sn); 28065793Smsmith else 28165793Smsmith ; /* Ignore unknown classes. */ 28265793Smsmith } 28365793Smsmith /* PLATFORM POLICY BEGIN ------------------------------------- */ 28465793Smsmith /* We have a chance to do things on a blank disk here */ 28565793Smsmith if (platform == p_sparc64 && d->chunks->part->part == NULL) { 286206534Semaste hd = d->bios_hd; 28765793Smsmith sc = d->bios_sect; 28865793Smsmith o = d->chunks->size / (hd * sc); 28965793Smsmith o *= (hd * sc); 29083114Sscottl o -= 2 * hd * sc; 291109088Sscottl if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) { 292151086Sscottl DPRINT(("Failed to add 'freebsd' chunk")); 29383114Sscottl } 294109088Sscottl } 29583114Sscottl /* PLATFORM POLICY END --------------------------------------- */ 29683114Sscottl 29783114Sscottl return (d); 29883114Sscottl i = 0; 299109088Sscottl} 30083114Sscottl