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