disk.c revision 114329
1238438Sdteske/*
2238438Sdteske * ----------------------------------------------------------------------------
3238438Sdteske * "THE BEER-WARE LICENSE" (Revision 42):
4263980Sdteske * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
5238438Sdteske * can do whatever you want with this stuff. If we meet some day, and you think
6238438Sdteske * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7238438Sdteske * ----------------------------------------------------------------------------
8238438Sdteske */
9238438Sdteske
10238438Sdteske#include <sys/cdefs.h>
11238438Sdteske__FBSDID("$FreeBSD: head/lib/libdisk/disk.c 114329 2003-04-30 21:03:16Z peter $");
12238438Sdteske
13238438Sdteske#include <stdio.h>
14238438Sdteske#include <stdlib.h>
15238438Sdteske#include <unistd.h>
16238438Sdteske#include <fcntl.h>
17238438Sdteske#include <string.h>
18238438Sdteske#include <inttypes.h>
19238438Sdteske#include <err.h>
20238438Sdteske#include <sys/sysctl.h>
21238438Sdteske#include <sys/stdint.h>
22238438Sdteske#include <sys/types.h>
23238438Sdteske#include <sys/stat.h>
24238438Sdteske#include <sys/ioctl.h>
25238438Sdteske#include <sys/disklabel.h>
26238438Sdteske#include <sys/uuid.h>
27238438Sdteske#include <sys/gpt.h>
28238438Sdteske#include <paths.h>
29238438Sdteske#include "libdisk.h"
30238438Sdteske
31238438Sdteske#include <ctype.h>
32240684Sdteske#include <errno.h>
33240684Sdteske#include <assert.h>
34244675Sdteske#include <uuid.h>
35240684Sdteske
36240684Sdteske#ifdef DEBUG
37240684Sdteske#define	DPRINT(x)	warn x
38240684Sdteske#define	DPRINTX(x)	warnx x
39238438Sdteske#else
40238438Sdteske#define	DPRINT(x)
41238438Sdteske#define	DPRINTX(x)
42238438Sdteske#endif
43238438Sdteske
44238438Sdteskeconst enum platform platform =
45238438Sdteske#if defined (P_DEBUG)
46238438Sdteske	P_DEBUG
47238438Sdteske#elif defined (PC98)
48238438Sdteske	p_pc98
49238438Sdteske#elif defined(__i386__)
50238438Sdteske	p_i386
51263980Sdteske#elif defined(__alpha__)
52263980Sdteske	p_alpha
53263980Sdteske#elif defined(__sparc64__)
54263980Sdteske	p_sparc64
55263980Sdteske#elif defined(__ia64__)
56263980Sdteske	p_ia64
57263980Sdteske#elif defined(__ppc__)
58263980Sdteske	p_ppc
59263980Sdteske#elif defined(__amd64__)
60238438Sdteske	p_amd64
61263980Sdteske#else
62263980Sdteske	IHAVENOIDEA
63263980Sdteske#endif
64263980Sdteske	;
65263980Sdteske
66238438Sdteskeconst char *
67263980Sdteskechunk_name(chunk_e type)
68263980Sdteske{
69238438Sdteske	switch(type) {
70238438Sdteske	case unused:	return ("unused");
71249751Sdteske	case mbr:	return ("mbr");
72238438Sdteske	case part:	return ("part");
73249751Sdteske	case gpt:	return ("gpt");
74249751Sdteske	case pc98:	return ("pc98");
75238438Sdteske	case sun:	return ("sun");
76238438Sdteske	case freebsd:	return ("freebsd");
77238438Sdteske	case fat:	return ("fat");
78251264Sdteske	case spare:	return ("spare");
79251264Sdteske	case efi:	return ("efi");
80251264Sdteske	default:	return ("??");
81251264Sdteske	}
82249751Sdteske};
83238438Sdteske
84238438Sdteskestatic chunk_e
85238438Sdteskeuuid_type(uuid_t *uuid)
86238438Sdteske{
87263980Sdteske	static uuid_t _efi = GPT_ENT_TYPE_EFI;
88263980Sdteske	static uuid_t _mbr = GPT_ENT_TYPE_MBR;
89263980Sdteske	static uuid_t _fbsd = GPT_ENT_TYPE_FREEBSD;
90263980Sdteske	static uuid_t _swap = GPT_ENT_TYPE_FREEBSD_SWAP;
91263980Sdteske	static uuid_t _ufs = GPT_ENT_TYPE_FREEBSD_UFS;
92263980Sdteske	static uuid_t _vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
93263980Sdteske
94238438Sdteske	if (uuid_is_nil(uuid, NULL))
95251190Sdteske		return (unused);
96251190Sdteske	if (uuid_equal(uuid, &_efi, NULL))
97251190Sdteske		return (efi);
98251190Sdteske	if (uuid_equal(uuid, &_mbr, NULL))
99251264Sdteske		return (mbr);
100251190Sdteske	if (uuid_equal(uuid, &_fbsd, NULL))
101251190Sdteske		return (freebsd);
102238438Sdteske	if (uuid_equal(uuid, &_swap, NULL))
103251236Sdteske		return (part);
104251236Sdteske	if (uuid_equal(uuid, &_ufs, NULL))
105249751Sdteske		return (part);
106238438Sdteske	if (uuid_equal(uuid, &_vinum, NULL))
107238438Sdteske		return (part);
108238438Sdteske	return (spare);
109238438Sdteske}
110249751Sdteske
111251264Sdteskestruct disk *
112251190SdteskeOpen_Disk(const char *name)
113251190Sdteske{
114240768Sdteske
115240768Sdteske	return Int_Open_Disk(name);
116240768Sdteske}
117251236Sdteske
118240768Sdteskestruct disk *
119238438SdteskeInt_Open_Disk(const char *name)
120238438Sdteske{
121263980Sdteske	uuid_t uuid;
122238438Sdteske	char *conftxt = NULL;
123263980Sdteske	struct disk *d;
124263980Sdteske	size_t txtsize;
125263980Sdteske	int error, i;
126238438Sdteske	char *p, *q, *r, *a, *b, *n, *t, *sn;
127238438Sdteske	off_t o, len, off;
128238438Sdteske	u_int l, s, ty, sc, hd, alt;
129263980Sdteske	off_t lo[10];
130263980Sdteske
131238438Sdteske	error = sysctlbyname("kern.geom.conftxt", NULL, &txtsize, NULL, 0);
132238438Sdteske	if (error) {
133238438Sdteske		warn("kern.geom.conftxt sysctl not available, giving up!");
134263980Sdteske		return (NULL);
135238438Sdteske	}
136238438Sdteske	conftxt = (char *) malloc(txtsize+1);
137263980Sdteske	if (conftxt == NULL) {
138256181Sdteske		DPRINT(("cannot malloc memory for conftxt"));
139238438Sdteske		return (NULL);
140238438Sdteske	}
141263980Sdteske	error = sysctlbyname("kern.geom.conftxt", conftxt, &txtsize, NULL, 0);
142263980Sdteske	if (error) {
143256181Sdteske		DPRINT(("error reading kern.geom.conftxt from the system"));
144238438Sdteske		free(conftxt);
145238438Sdteske		return (NULL);
146238438Sdteske	}
147263980Sdteske	conftxt[txtsize] = '\0';	/* in case kernel bug is still there */
148252795Sdteske
149238438Sdteske	for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) {
150238438Sdteske		if (*p == '\n')
151238438Sdteske			p++;
152238438Sdteske		a = strsep(&p, " ");
153263980Sdteske		if (strcmp(a, "0"))
154252795Sdteske			continue;
155238438Sdteske
156263980Sdteske		a = strsep(&p, " ");
157238438Sdteske		if (strcmp(a, "DISK"))
158238438Sdteske			continue;
159263980Sdteske
160263980Sdteske		a = strsep(&p, " ");
161238438Sdteske		if (strcmp(a, name))
162238438Sdteske			continue;
163238438Sdteske		break;
164263980Sdteske	}
165238438Sdteske
166238438Sdteske	q = strchr(p, '\n');
167238438Sdteske	if (q != NULL)
168256181Sdteske		*q++ = '\0';
169238438Sdteske
170238438Sdteske	d = (struct disk *)calloc(sizeof *d, 1);
171263980Sdteske	if(d == NULL)
172238438Sdteske		return NULL;
173263980Sdteske
174263980Sdteske	d->name = strdup(name);
175263980Sdteske
176263980Sdteske	a = strsep(&p, " ");	/* length in bytes */
177263980Sdteske	len = strtoimax(a, &r, 0);
178238438Sdteske	if (*r) {
179238438Sdteske		printf("BARF %d <%d>\n", __LINE__, *r);
180238438Sdteske		exit (0);
181263980Sdteske	}
182263980Sdteske
183263980Sdteske	a = strsep(&p, " ");	/* sectorsize */
184263980Sdteske	s = strtoul(a, &r, 0);
185238438Sdteske	if (*r) {
186263980Sdteske		printf("BARF %d <%d>\n", __LINE__, *r);
187263980Sdteske		exit (0);
188238438Sdteske	}
189238438Sdteske
190263980Sdteske	if (s == 0)
191238438Sdteske		return (NULL);
192263980Sdteske	d->sector_size = s;
193238438Sdteske	len /= s;	/* media size in number of sectors. */
194263980Sdteske
195263980Sdteske	if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-"))
196238438Sdteske		DPRINT(("Failed to add 'whole' chunk"));
197238438Sdteske
198263980Sdteske	for (;;) {
199238438Sdteske		a = strsep(&p, " ");
200263980Sdteske		if (a == NULL)
201238438Sdteske			break;
202238438Sdteske		b = strsep(&p, " ");
203238438Sdteske		o = strtoul(b, &r, 0);
204238438Sdteske		if (*r) {
205263980Sdteske			printf("BARF %d <%d>\n", __LINE__, *r);
206238438Sdteske			exit (0);
207263980Sdteske		}
208251190Sdteske		if (!strcmp(a, "hd"))
209251190Sdteske			d->bios_hd = o;
210263980Sdteske		else if (!strcmp(a, "sc"))
211251190Sdteske			d->bios_sect = o;
212251190Sdteske		else
213251190Sdteske			printf("HUH ? <%s> <%s>\n", a, b);
214263980Sdteske	}
215263980Sdteske
216240768Sdteske	/*
217240768Sdteske	 * Calculate the number of cylinders this disk must have. If we have
218263980Sdteske	 * an obvious insanity, we set the number of cyclinders to zero.
219263980Sdteske	 */
220238438Sdteske	o = d->bios_hd * d->bios_sect;
221238438Sdteske	d->bios_cyl = (o != 0) ? len / o : 0;
222263980Sdteske
223238438Sdteske	p = q;
224263980Sdteske	lo[0] = 0;
225251190Sdteske
226251190Sdteske	for (; p != NULL && *p; p = q) {
227263980Sdteske		q = strchr(p, '\n');
228251190Sdteske		if (q != NULL)
229251190Sdteske			*q++ = '\0';
230251190Sdteske		a = strsep(&p, " ");	/* Index */
231263980Sdteske		if (!strcmp(a, "0"))
232263980Sdteske			break;
233240768Sdteske		l = strtoimax(a, &r, 0);
234240768Sdteske		if (*r) {
235263980Sdteske			printf("BARF %d <%d>\n", __LINE__, *r);
236263980Sdteske			exit (0);
237238438Sdteske		}
238238438Sdteske		t = strsep(&p, " ");	/* Type {SUN, BSD, MBR, PC98, GPT} */
239263980Sdteske		n = strsep(&p, " ");	/* name */
240238438Sdteske		a = strsep(&p, " ");	/* len */
241238438Sdteske		len = strtoimax(a, &r, 0);
242263980Sdteske		if (*r) {
243252795Sdteske			printf("BARF %d <%d>\n", __LINE__, *r);
244238438Sdteske			exit (0);
245238438Sdteske		}
246238438Sdteske		a = strsep(&p, " ");	/* secsize */
247238438Sdteske		s = strtoimax(a, &r, 0);
248263980Sdteske		if (*r) {
249251544Sdteske			printf("BARF %d <%d>\n", __LINE__, *r);
250263980Sdteske			exit (0);
251263980Sdteske		}
252263980Sdteske		for (;;) {
253263980Sdteske			a = strsep(&p, " ");
254263980Sdteske			if (a == NULL)
255251547Sdteske				break;
256251547Sdteske			/* XXX: Slice name may include a space. */
257251547Sdteske			if (!strcmp(a, "sn")) {
258238438Sdteske				sn = p;
259263980Sdteske				break;
260238438Sdteske			}
261238438Sdteske			b = strsep(&p, " ");
262263980Sdteske			o = strtoimax(b, &r, 0);
263238438Sdteske			if (*r) {
264238438Sdteske				uint32_t status;
265238438Sdteske
266256181Sdteske				uuid_from_string(b, &uuid, &status);
267238438Sdteske				if (status != uuid_s_ok) {
268238438Sdteske					printf("BARF %d <%d>\n", __LINE__, *r);
269263980Sdteske					exit (0);
270238438Sdteske				}
271238438Sdteske				o = uuid_type(&uuid);
272263980Sdteske			}
273238438Sdteske			if (!strcmp(a, "o"))
274238438Sdteske				off = o;
275238438Sdteske			else if (!strcmp(a, "i"))
276238438Sdteske				i = o;
277263980Sdteske			else if (!strcmp(a, "ty"))
278238438Sdteske				ty = o;
279238438Sdteske			else if (!strcmp(a, "sc"))
280263980Sdteske				sc = o;
281263980Sdteske			else if (!strcmp(a, "hd"))
282238438Sdteske				hd = o;
283263980Sdteske			else if (!strcmp(a, "alt"))
284256181Sdteske				alt = o;
285238438Sdteske		}
286238438Sdteske
287263980Sdteske		/* PLATFORM POLICY BEGIN ----------------------------------- */
288238438Sdteske		if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2)
289251266Sdteske			continue;
290263980Sdteske		if (platform == p_sparc64 && !strcmp(t, "SUN") &&
291263980Sdteske		    d->chunks->part->part == NULL) {
292238438Sdteske			d->bios_hd = hd;
293238438Sdteske			d->bios_sect = sc;
294238438Sdteske			o = d->chunks->size / (hd * sc);
295263980Sdteske			o *= (hd * sc);
296263980Sdteske			o -= alt * hd * sc;
297263980Sdteske			if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-"))
298238438Sdteske				DPRINT(("Failed to add 'freebsd' chunk"));
299238438Sdteske		}
300238438Sdteske		if (platform == p_alpha && !strcmp(t, "BSD") &&
301238438Sdteske		    d->chunks->part->part == NULL) {
302263980Sdteske			if (Add_Chunk(d, 0, d->chunks->size, name, freebsd,
303263980Sdteske				      0, 0, "-"))
304238438Sdteske				DPRINT(("Failed to add 'freebsd' chunk"));
305263980Sdteske		}
306263980Sdteske		if (!strcmp(t, "BSD") && i == RAW_PART)
307251190Sdteske			continue;
308251190Sdteske		/* PLATFORM POLICY END ------------------------------------- */
309263980Sdteske
310263980Sdteske		off /= s;
311263980Sdteske		len /= s;
312251190Sdteske		off += lo[l - 1];
313263980Sdteske		lo[l] = off;
314238438Sdteske		if (!strcmp(t, "SUN"))
315263980Sdteske			i = Add_Chunk(d, off, len, n, part, 0, 0, 0);
316238438Sdteske		else if (!strncmp(t, "MBR", 3)) {
317238438Sdteske			switch (ty) {
318263980Sdteske			case 0xa5:
319238438Sdteske				i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0);
320238438Sdteske				break;
321263980Sdteske			case 0x01:
322263980Sdteske			case 0x04:
323263980Sdteske			case 0x06:
324263980Sdteske			case 0x0b:
325240768Sdteske			case 0x0c:
326240768Sdteske			case 0x0e:
327263980Sdteske				i = Add_Chunk(d, off, len, n, fat, ty, 0, 0);
328263980Sdteske				break;
329263980Sdteske			case 0xef:	/* EFI */
330263980Sdteske				i = Add_Chunk(d, off, len, n, efi, ty, 0, 0);
331263980Sdteske				break;
332238438Sdteske			default:
333238438Sdteske				i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0);
334263980Sdteske				break;
335238438Sdteske			}
336263980Sdteske		} else if (!strcmp(t, "BSD"))
337263980Sdteske			i = Add_Chunk(d, off, len, n, part, ty, 0, 0);
338238438Sdteske		else if (!strcmp(t, "PC98")) {
339238438Sdteske			switch (ty & 0x7f) {
340238438Sdteske			case 0x14:
341263980Sdteske				i = Add_Chunk(d, off, len, n, freebsd, ty, 0,
342263980Sdteske					      sn);
343263980Sdteske				break;
344263980Sdteske			case 0x20:
345263980Sdteske			case 0x21:
346263980Sdteske			case 0x22:
347263980Sdteske			case 0x23:
348263980Sdteske			case 0x24:
349251264Sdteske				i = Add_Chunk(d, off, len, n, fat, ty, 0, sn);
350263980Sdteske				break;
351263980Sdteske			default:
352263980Sdteske				i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn);
353263980Sdteske				break;
354263980Sdteske			}
355263980Sdteske		} else if (!strcmp(t, "GPT"))
356263980Sdteske			i = Add_Chunk(d, off, len, n, ty, 0, 0, 0);
357263980Sdteske		else if (!strcmp(t, "BDE"))
358263980Sdteske			; /* nothing */
359263980Sdteske		else {
360238438Sdteske			printf("BARF %d\n", __LINE__);
361238438Sdteske			exit(0);
362263980Sdteske		}
363263980Sdteske	}
364263980Sdteske	/* PLATFORM POLICY BEGIN ------------------------------------- */
365263980Sdteske	/* We have a chance to do things on a blank disk here */
366263980Sdteske	if (platform == p_sparc64 && d->chunks->part->part == NULL) {
367263980Sdteske		hd = d->bios_hd;
368263980Sdteske		sc = d->bios_sect;
369263980Sdteske		o = d->chunks->size / (hd * sc);
370263980Sdteske		o *= (hd * sc);
371238438Sdteske		o -= 2 * hd * sc;
372238438Sdteske		if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-"))
373238438Sdteske			DPRINT(("Failed to add 'freebsd' chunk"));
374263980Sdteske	}
375238438Sdteske	/* PLATFORM POLICY END --------------------------------------- */
376238438Sdteske
377263980Sdteske	return (d);
378263980Sdteske	i = 0;
379263980Sdteske}
380240768Sdteske
381251236Sdteskevoid
382251236SdteskeDebug_Disk(struct disk *d)
383251236Sdteske{
384263980Sdteske
385251236Sdteske	printf("Debug_Disk(%s)", d->name);
386260678Sdteske#if 0
387251236Sdteske	printf("  real_geom=%lu/%lu/%lu",
388251236Sdteske	       d->real_cyl, d->real_hd, d->real_sect);
389251236Sdteske#endif
390260678Sdteske	printf("  bios_geom=%lu/%lu/%lu = %lu\n",
391263980Sdteske		d->bios_cyl, d->bios_hd, d->bios_sect,
392238438Sdteske		d->bios_cyl * d->bios_hd * d->bios_sect);
393238438Sdteske#if defined(PC98)
394263980Sdteske	printf("  boot1=%p, boot2=%p, bootipl=%p, bootmenu=%p\n",
395263980Sdteske		d->boot1, d->boot2, d->bootipl, d->bootmenu);
396238438Sdteske#elif defined(__i386__) || defined(__amd64__)
397263980Sdteske	printf("  boot1=%p, boot2=%p, bootmgr=%p\n",
398263980Sdteske		d->boot1, d->boot2, d->bootmgr);
399251242Sdteske#elif defined(__alpha__)
400251242Sdteske	printf("  boot1=%p, bootmgr=%p\n",
401251242Sdteske		d->boot1, d->bootmgr);
402238438Sdteske#elif defined(__ia64__)
403263980Sdteske	printf("\n");
404238438Sdteske#else
405238438Sdteske/* Should be: error "Debug_Disk: unknown arch"; */
406238438Sdteske#endif
407238438Sdteske	Debug_Chunk(d->chunks);
408263980Sdteske}
409256181Sdteske
410238438Sdteskevoid
411238438SdteskeFree_Disk(struct disk *d)
412263980Sdteske{
413263980Sdteske	if (d->chunks)
414263980Sdteske		Free_Chunk(d->chunks);
415263980Sdteske	if (d->name)
416263980Sdteske		free(d->name);
417263980Sdteske#ifdef PC98
418263980Sdteske	if (d->bootipl)
419263980Sdteske		free(d->bootipl);
420263980Sdteske	if (d->bootmenu)
421263980Sdteske		free(d->bootmenu);
422263980Sdteske#else
423263980Sdteske#if !defined(__ia64__)
424263980Sdteske	if (d->bootmgr)
425263980Sdteske		free(d->bootmgr);
426263980Sdteske#endif
427263980Sdteske#endif
428263980Sdteske#if !defined(__ia64__)
429263980Sdteske	if (d->boot1)
430263980Sdteske		free(d->boot1);
431263980Sdteske#endif
432263980Sdteske#if defined(__i386__) || defined(__amd64__)
433263980Sdteske	if (d->boot2)
434263980Sdteske		free(d->boot2);
435263980Sdteske#endif
436263980Sdteske	free(d);
437263980Sdteske}
438263980Sdteske
439263980Sdteske#if 0
440263980Sdteskevoid
441263980SdteskeCollapse_Disk(struct disk *d)
442263980Sdteske{
443263980Sdteske
444263980Sdteske	while (Collapse_Chunk(d, d->chunks))
445263980Sdteske		;
446263980Sdteske}
447263980Sdteske#endif
448263980Sdteske
449263980Sdteskestatic int
450263980Sdteskeqstrcmp(const void* a, const void* b)
451263980Sdteske{
452263980Sdteske	char *str1 = *(char**)a;
453263980Sdteske	char *str2 = *(char**)b;
454263980Sdteske
455263980Sdteske	return strcmp(str1, str2);
456263980Sdteske}
457263980Sdteske
458263980Sdteskechar **
459263980SdteskeDisk_Names()
460263980Sdteske{
461263980Sdteske	int disk_cnt;
462263980Sdteske	static char **disks;
463263980Sdteske	int error;
464263980Sdteske	size_t listsize;
465263980Sdteske	char *disklist;
466263980Sdteske
467263980Sdteske	error = sysctlbyname("kern.disks", NULL, &listsize, NULL, 0);
468263980Sdteske	if (error) {
469263980Sdteske		warn("kern.disks sysctl not available");
470263980Sdteske		return NULL;
471263980Sdteske	}
472263980Sdteske
473263980Sdteske	disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS));
474263980Sdteske	if (disks == NULL)
475263980Sdteske		return NULL;
476263980Sdteske	disklist = (char *)malloc(listsize + 1);
477263980Sdteske	if (disklist == NULL) {
478263980Sdteske		free(disks);
479263980Sdteske		return NULL;
480263980Sdteske	}
481263980Sdteske	memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS));
482263980Sdteske	memset(disklist, 0, listsize + 1);
483263980Sdteske	error = sysctlbyname("kern.disks", disklist, &listsize, NULL, 0);
484263980Sdteske	if (error) {
485263980Sdteske		free(disklist);
486263980Sdteske		free(disks);
487263980Sdteske		return NULL;
488263980Sdteske	}
489263980Sdteske	for (disk_cnt = 0; disk_cnt < MAX_NO_DISKS; disk_cnt++) {
490263980Sdteske		disks[disk_cnt] = strsep(&disklist, " ");
491263980Sdteske		if (disks[disk_cnt] == NULL)
492263980Sdteske			break;
493263980Sdteske	}
494263980Sdteske	qsort(disks, disk_cnt, sizeof(char*), qstrcmp);
495263980Sdteske	return disks;
496263980Sdteske}
497263980Sdteske
498263980Sdteske#ifdef PC98
499263980Sdteskevoid
500263980SdteskeSet_Boot_Mgr(struct disk *d, const u_char *bootipl, const size_t bootipl_size,
501263980Sdteske	const u_char *bootmenu, const size_t bootmenu_size)
502263980Sdteske#else
503263980Sdteskevoid
504263980SdteskeSet_Boot_Mgr(struct disk *d, const u_char *b, const size_t s)
505263980Sdteske#endif
506263980Sdteske{
507263980Sdteske#if !defined(__ia64__)
508263980Sdteske#ifdef PC98
509263980Sdteske	if (d->sector_size == 0)
510263980Sdteske		return;
511263980Sdteske	if (bootipl_size % d->sector_size != 0)
512263980Sdteske		return;
513263980Sdteske	if (d->bootipl)
514263980Sdteske		free(d->bootipl);
515263980Sdteske	if (!bootipl) {
516263980Sdteske		d->bootipl = NULL;
517263980Sdteske	} else {
518263980Sdteske		d->bootipl_size = bootipl_size;
519263980Sdteske		d->bootipl = malloc(bootipl_size);
520263980Sdteske		if (!d->bootipl)
521263980Sdteske			return;
522263980Sdteske		memcpy(d->bootipl, bootipl, bootipl_size);
523263980Sdteske	}
524263980Sdteske
525263980Sdteske	if (bootmenu_size % d->sector_size != 0)
526263980Sdteske		return;
527263980Sdteske	if (d->bootmenu)
528263980Sdteske		free(d->bootmenu);
529263980Sdteske	if (!bootmenu) {
530263980Sdteske		d->bootmenu = NULL;
531263980Sdteske	} else {
532263980Sdteske		d->bootmenu_size = bootmenu_size;
533263980Sdteske		d->bootmenu = malloc(bootmenu_size);
534263980Sdteske		if (!d->bootmenu)
535263980Sdteske			return;
536263980Sdteske		memcpy(d->bootmenu, bootmenu, bootmenu_size);
537263980Sdteske	}
538263980Sdteske#else
539263980Sdteske	if (d->sector_size == 0)
540263980Sdteske		return;
541263980Sdteske	if (s % d->sector_size != 0)
542263980Sdteske		return;
543263980Sdteske	if (d->bootmgr)
544263980Sdteske		free(d->bootmgr);
545263980Sdteske	if (!b) {
546263980Sdteske		d->bootmgr = NULL;
547263980Sdteske	} else {
548263980Sdteske		d->bootmgr_size = s;
549263980Sdteske		d->bootmgr = malloc(s);
550263980Sdteske		if (!d->bootmgr)
551263980Sdteske			return;
552263980Sdteske		memcpy(d->bootmgr, b, s);
553263980Sdteske	}
554263980Sdteske#endif
555263980Sdteske#endif
556263980Sdteske}
557263980Sdteske
558263980Sdteskeint
559263980SdteskeSet_Boot_Blocks(struct disk *d, const u_char *b1, const u_char *b2)
560263980Sdteske{
561263980Sdteske#if defined(__i386__) || defined(__amd64__)
562263980Sdteske	if (d->boot1)
563263980Sdteske		free(d->boot1);
564263980Sdteske	d->boot1 = malloc(512);
565263980Sdteske	if (!d->boot1)
566263980Sdteske		return -1;
567263980Sdteske	memcpy(d->boot1, b1, 512);
568263980Sdteske	if (d->boot2)
569263980Sdteske		free(d->boot2);
570263980Sdteske	d->boot2 = malloc(15 * 512);
571263980Sdteske	if (!d->boot2)
572263980Sdteske		return -1;
573263980Sdteske	memcpy(d->boot2, b2, 15 * 512);
574263980Sdteske#elif defined(__alpha__)
575263980Sdteske	if (d->boot1)
576263980Sdteske		free(d->boot1);
577263980Sdteske	d->boot1 = malloc(15 * 512);
578263980Sdteske	if (!d->boot1)
579263980Sdteske		return -1;
580263980Sdteske	memcpy(d->boot1, b1, 15 * 512);
581263980Sdteske#elif defined(__sparc64__)
582263980Sdteske	if (d->boot1 != NULL)
583263980Sdteske		free(d->boot1);
584263980Sdteske	d->boot1 = malloc(16 * 512);
585263980Sdteske	if (d->boot1 == NULL)
586263980Sdteske		return (-1);
587263980Sdteske	memcpy(d->boot1, b1, 16 * 512);
588263980Sdteske#elif defined(__ia64__)
589263980Sdteske	/* nothing */
590263980Sdteske#else
591263980Sdteske/* Should be: #error "Set_Boot_Blocks: unknown arch"; */
592244675Sdteske#endif
593244675Sdteske	return 0;
594244675Sdteske}
595244675Sdteske
596238438Sdteske#ifdef PC98
597const char *
598slice_type_name( int type, int subtype )
599{
600
601	switch (type) {
602	case whole:
603		return "whole";
604	case fat:
605		return "fat";
606	case freebsd:
607		switch (subtype) {
608		case 0xc494:	return "freebsd";
609		default:	return "unknown";
610		}
611	case unused:
612		return "unused";
613	default:
614		return "unknown";
615	}
616}
617#else /* PC98 */
618const char *
619slice_type_name( int type, int subtype )
620{
621
622	switch (type) {
623	case whole:
624		return "whole";
625	case mbr:
626		switch (subtype) {
627		case 1:		return "fat (12-bit)";
628		case 2:		return "XENIX /";
629		case 3:		return "XENIX /usr";
630		case 4:         return "fat (16-bit,<=32Mb)";
631		case 5:		return "extended DOS";
632		case 6:         return "fat (16-bit,>32Mb)";
633		case 7:         return "NTFS/HPFS/QNX";
634		case 8:         return "AIX bootable";
635		case 9:         return "AIX data";
636		case 10:	return "OS/2 bootmgr";
637		case 11:        return "fat (32-bit)";
638		case 12:        return "fat (32-bit,LBA)";
639		case 14:        return "fat (16-bit,>32Mb,LBA)";
640		case 15:        return "extended DOS, LBA";
641		case 18:        return "Compaq Diagnostic";
642		case 84:	return "OnTrack diskmgr";
643		case 100:	return "Netware 2.x";
644		case 101:	return "Netware 3.x";
645		case 115:	return "SCO UnixWare";
646		case 128:	return "Minix 1.1";
647		case 129:	return "Minix 1.5";
648		case 130:	return "linux_swap";
649		case 131:	return "ext2fs";
650		case 166:	return "OpenBSD FFS";	/* 0xA6 */
651		case 169:	return "NetBSD FFS";	/* 0xA9 */
652		case 182:	return "OpenBSD";	/* dedicated */
653		case 183:	return "bsd/os";
654		case 184:	return "bsd/os swap";
655		case 238:	return "EFI GPT";
656		case 239:	return "EFI Sys. Part.";
657		default:	return "unknown";
658		}
659	case fat:
660		return "fat";
661	case freebsd:
662		switch (subtype) {
663		case 165:	return "freebsd";
664		default:	return "unknown";
665		}
666	case extended:
667		return "extended";
668	case part:
669		return "part";
670	case efi:
671		return "efi";
672	case unused:
673		return "unused";
674	default:
675		return "unknown";
676	}
677}
678#endif /* PC98 */
679