disk.c revision 104674
1141296Sdas/*
2141296Sdas * ----------------------------------------------------------------------------
32116Sjkh * "THE BEER-WARE LICENSE" (Revision 42):
42116Sjkh * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
52116Sjkh * can do whatever you want with this stuff. If we meet some day, and you think
62116Sjkh * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7141296Sdas * ----------------------------------------------------------------------------
82116Sjkh */
9141296Sdas
102116Sjkh#include <sys/cdefs.h>
112116Sjkh__FBSDID("$FreeBSD: head/lib/libdisk/disk.c 104674 2002-10-08 12:13:19Z nyan $");
122116Sjkh
132116Sjkh#include <stdio.h>
14176451Sdas#include <stdlib.h>
15176451Sdas#include <unistd.h>
162116Sjkh#include <fcntl.h>
172116Sjkh#include <string.h>
182116Sjkh#include <err.h>
192116Sjkh#include <sys/sysctl.h>
202116Sjkh#include <sys/types.h>
212116Sjkh#include <sys/stat.h>
222116Sjkh#include <sys/ioctl.h>
232116Sjkh#include <sys/disklabel.h>
242116Sjkh#include <sys/diskslice.h>
252116Sjkh#ifndef PC98
262116Sjkh#include <sys/diskmbr.h>
272116Sjkh#endif
282116Sjkh#include <paths.h>
292116Sjkh#include "libdisk.h"
302116Sjkh
312116Sjkh#ifndef PC98
322116Sjkh#define DOSPTYP_EXTENDED        5
332116Sjkh#define DOSPTYP_ONTRACK         84
342116Sjkh#endif
352116Sjkh
362116Sjkhconst char *chunk_n[] = {
37141296Sdas	"whole",
382116Sjkh	"unknown",
392116Sjkh	"fat",
402116Sjkh	"freebsd",
412116Sjkh	"extended",
42141296Sdas	"part",
432116Sjkh	"unused",
44141296Sdas	NULL
452116Sjkh};
46141296Sdas
472116Sjkhstruct disk *
482116SjkhOpen_Disk(const char *name)
492116Sjkh{
502116Sjkh	return Int_Open_Disk(name, 0);
512116Sjkh}
522116Sjkh
532116Sjkh#ifndef PC98
542116Sjkhstatic u_int32_t
552116SjkhRead_Int32(u_int32_t *p)
562116Sjkh{
572116Sjkh    u_int8_t *bp = (u_int8_t *)p;
582116Sjkh    return bp[0] | (bp[1] << 8) | (bp[2] << 16) | (bp[3] << 24);
592116Sjkh}
602116Sjkh#endif
612116Sjkh
622116Sjkhstruct disk *
632116SjkhInt_Open_Disk(const char *name, u_long size)
642116Sjkh{
652116Sjkh	int i,fd;
662116Sjkh	struct diskslices ds;
678870Srgrimes	struct disklabel dl;
682116Sjkh	char device[64], *buf;
692116Sjkh	struct disk *d;
702116Sjkh	u_long sector_size;
712116Sjkh#ifdef PC98
722116Sjkh	unsigned char *p;
732116Sjkh#else
742116Sjkh	struct dos_partition *dp;
752116Sjkh	void *p;
762116Sjkh#endif
772116Sjkh	u_long offset = 0;
782116Sjkh
792116Sjkh	strcpy(device, _PATH_DEV);
802116Sjkh	strcat(device, name);
812116Sjkh
822116Sjkh	d = (struct disk *)malloc(sizeof *d);
832116Sjkh	if(!d) return NULL;
842116Sjkh	memset(d, 0, sizeof *d);
8597413Salfred
8697413Salfred	fd = open(device, O_RDONLY);
872116Sjkh	if (fd < 0) {
882116Sjkh#ifdef DEBUG
892116Sjkh		warn("open(%s) failed", device);
902116Sjkh#endif
912116Sjkh		return 0;
922116Sjkh	}
932116Sjkh
942116Sjkh	memset(&dl, 0, sizeof dl);
952116Sjkh	ioctl(fd, DIOCGDINFO, &dl);
962116Sjkh	i = ioctl(fd, DIOCGSLICEINFO, &ds);
972116Sjkh	if (i < 0) {
982116Sjkh#ifdef DEBUG
992116Sjkh		warn("DIOCGSLICEINFO(%s) failed", device);
1002116Sjkh#endif
1012116Sjkh		close(fd);
1022116Sjkh		return 0;
1032116Sjkh	}
1042116Sjkh
1052116Sjkh#ifdef DEBUG
1062116Sjkh	for(i = 0; i < ds.dss_nslices; i++)
1072116Sjkh		if(ds.dss_slices[i].ds_openmask)
1082116Sjkh			printf("  open(%d)=0x%2x",
1092116Sjkh				i, ds.dss_slices[i].ds_openmask);
1102116Sjkh	printf("\n");
1112116Sjkh#endif
1122116Sjkh
1132116Sjkh/* XXX --- ds.dss_slice[WHOLE_DISK_SLICE].ds.size of MO disk is wrong!!! */
1142116Sjkh#ifdef PC98
1152116Sjkh	if (!size)
1162116Sjkh		size = dl.d_ncylinders * dl.d_ntracks * dl.d_nsectors;
1172116Sjkh#else
1182116Sjkh	if (!size)
1192116Sjkh		size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
1202116Sjkh#endif
1212116Sjkh
1222116Sjkh	/* determine media sector size */
1232116Sjkh	if ((buf = malloc(MAX_SEC_SIZE)) == NULL)
1242116Sjkh		return NULL;
1252116Sjkh	for (sector_size = MIN_SEC_SIZE; sector_size <= MAX_SEC_SIZE; sector_size *= 2) {
1262116Sjkh		if (read(fd, buf, sector_size) == sector_size) {
1272116Sjkh			d->sector_size = sector_size;
1282116Sjkh			break;
1292116Sjkh		}
1302116Sjkh	}
1312116Sjkh	free (buf);
1322116Sjkh	if (sector_size > MAX_SEC_SIZE)
1332116Sjkh		return NULL; /* could not determine sector size */
1342116Sjkh
1352116Sjkh#ifdef PC98
1362116Sjkh	p = (unsigned char*)read_block(fd, 1, sector_size);
1372116Sjkh#else
1382116Sjkh	p = read_block(fd, 0, sector_size);
1392116Sjkh	dp = (struct dos_partition*)(p + DOSPARTOFF);
1402116Sjkh	for (i = 0; i < NDOSPART; i++) {
1412116Sjkh		if (Read_Int32(&dp->dp_start) >= size)
14297413Salfred		    continue;
14397413Salfred		if (Read_Int32(&dp->dp_start) + Read_Int32(&dp->dp_size) >= size)
1442116Sjkh		    continue;
1452116Sjkh		if (!Read_Int32(&dp->dp_size))
1462116Sjkh		    continue;
1472116Sjkh
1482116Sjkh		if (dp->dp_typ == DOSPTYP_ONTRACK) {
1492116Sjkh			d->flags |= DISK_ON_TRACK;
1502116Sjkh			offset = 63;
151141296Sdas		}
1522116Sjkh
1532116Sjkh	}
1542116Sjkh	free(p);
1552116Sjkh#endif
1562116Sjkh
1572116Sjkh	d->bios_sect = dl.d_nsectors;
1582116Sjkh	d->bios_hd = dl.d_ntracks;
1592116Sjkh
1602116Sjkh	d->name = strdup(name);
1612116Sjkh
1622116Sjkh
1632116Sjkh	if (dl.d_ntracks && dl.d_nsectors)
1642116Sjkh		d->bios_cyl = size / (dl.d_ntracks * dl.d_nsectors);
1652116Sjkh
1662116Sjkh#ifdef PC98
1672116Sjkh	if (Add_Chunk(d, -offset, size, name, whole, 0, 0, "-"))
1682116Sjkh#else
1692116Sjkh	if (Add_Chunk(d, -offset, size, name, whole, 0, 0))
1702116Sjkh#endif
1712116Sjkh#ifdef DEBUG
1722116Sjkh		warn("Failed to add 'whole' chunk");
1732116Sjkh#else
1742116Sjkh		{}
1752116Sjkh#endif
1762116Sjkh
1772116Sjkh#ifdef __i386__
1782116Sjkh#ifdef PC98
1792116Sjkh	/* XXX -- Quick Hack!
1802116Sjkh	 * Check MS-DOS MO
181141296Sdas	 */
1822116Sjkh	if ((*p == 0xf0 || *p == 0xf8) &&
1832116Sjkh	    (*(p+1) == 0xff) &&
184141296Sdas	    (*(p+2) == 0xff)) {
1852116Sjkh		Add_Chunk(d, 0, size, name, fat, 0xa0a0, 0, name);
1862116Sjkh	    free(p);
1872116Sjkh	    goto pc98_mo_done;
1882116Sjkh	}
1892116Sjkh	free(p);
1902116Sjkh#endif /* PC98 */
1912116Sjkh	for(i=BASE_SLICE;i<ds.dss_nslices;i++) {
1922116Sjkh		char sname[20];
1932116Sjkh		chunk_e ce;
1942116Sjkh		u_long flags=0;
1952116Sjkh		int subtype=0;
1962116Sjkh
1972116Sjkh		if (! ds.dss_slices[i].ds_size)
1982116Sjkh			continue;
1992116Sjkh		ds.dss_slices[i].ds_offset -= offset;
2002116Sjkh		sprintf(sname, "%ss%d", name, i - 1);
2012116Sjkh#ifdef PC98
2022116Sjkh		subtype = ds.dss_slices[i].ds_type |
2032116Sjkh			ds.dss_slices[i].ds_subtype << 8;
2042116Sjkh		switch (ds.dss_slices[i].ds_type & 0x7f) {
2052116Sjkh			case 0x14:
2062116Sjkh				ce = freebsd;
2072116Sjkh				break;
2082116Sjkh			case 0x20:
2092116Sjkh			case 0x21:
2102116Sjkh			case 0x22:
2112116Sjkh			case 0x23:
2122116Sjkh			case 0x24:
2132116Sjkh				ce = fat;
2142116Sjkh				break;
2152116Sjkh#else /* IBM-PC */
2162116Sjkh		subtype = ds.dss_slices[i].ds_type;
2172116Sjkh		switch (ds.dss_slices[i].ds_type) {
2182116Sjkh			case 0xa5:
2192116Sjkh				ce = freebsd;
2202116Sjkh				break;
2212116Sjkh			case 0x1:
2222116Sjkh			case 0x6:
2232116Sjkh			case 0x4:
2242116Sjkh			case 0xb:
2252116Sjkh			case 0xc:
2262116Sjkh			case 0xe:
2272116Sjkh				ce = fat;
2282116Sjkh				break;
2292116Sjkh			case DOSPTYP_EXTENDED:
2302116Sjkh			case 0xf:
2312116Sjkh				ce = extended;
2322116Sjkh				break;
2332116Sjkh#endif
2342116Sjkh			default:
2352116Sjkh				ce = unknown;
2362116Sjkh				break;
2372116Sjkh		}
2382116Sjkh#ifdef PC98
2392116Sjkh		if (Add_Chunk(d, ds.dss_slices[i].ds_offset,
2402116Sjkh			ds.dss_slices[i].ds_size, sname, ce, subtype, flags,
2412116Sjkh			ds.dss_slices[i].ds_name))
2422116Sjkh#else
2432116Sjkh		if (Add_Chunk(d, ds.dss_slices[i].ds_offset,
2442116Sjkh			ds.dss_slices[i].ds_size, sname, ce, subtype, flags))
2452116Sjkh#endif
2462116Sjkh#ifdef DEBUG
2472116Sjkh			warn("failed to add chunk for slice %d", i - 1);
2482116Sjkh#else
2492116Sjkh			{}
2502116Sjkh#endif
2512116Sjkh
2522116Sjkh#ifdef PC98
2532116Sjkh		if ((ds.dss_slices[i].ds_type & 0x7f) != 0x14)
2542116Sjkh#else
2552116Sjkh		if (ds.dss_slices[i].ds_type != 0xa5)
2562116Sjkh#endif
2572116Sjkh			continue;
2582116Sjkh		{
2592116Sjkh		struct disklabel dl;
2602116Sjkh		char pname[20];
2612116Sjkh		int j, k;
2622116Sjkh
2632116Sjkh		strcpy(pname, _PATH_DEV);
2642116Sjkh		strcat(pname, sname);
2652116Sjkh		j = open(pname, O_RDONLY);
2662116Sjkh		if (j < 0) {
2672116Sjkh#ifdef DEBUG
2682116Sjkh			warn("open(%s)", pname);
2692116Sjkh#endif
2702116Sjkh			continue;
2712116Sjkh		}
2722116Sjkh		k = ioctl(j, DIOCGDINFO, &dl);
2732116Sjkh		if (k < 0) {
2742116Sjkh#ifdef DEBUG
2752116Sjkh			warn("ioctl(%s, DIOCGDINFO)", pname);
2762116Sjkh#endif
2772116Sjkh			close(j);
2782116Sjkh			continue;
2792116Sjkh		}
2802116Sjkh		close(j);
281141296Sdas
2822116Sjkh		for(j = 0; j <= dl.d_npartitions; j++) {
2832116Sjkh			if (j == RAW_PART)
2842116Sjkh				continue;
2852116Sjkh			if (j == 3)
2862116Sjkh				continue;
2872116Sjkh			if (j == dl.d_npartitions) {
2882116Sjkh				j = 3;
2892116Sjkh				dl.d_npartitions = 0;
2902116Sjkh			}
2912116Sjkh			if (!dl.d_partitions[j].p_size)
2922116Sjkh				continue;
2932116Sjkh			if (dl.d_partitions[j].p_size +
2942116Sjkh			    dl.d_partitions[j].p_offset >
2952116Sjkh			    ds.dss_slices[i].ds_size)
2962116Sjkh				continue;
2972116Sjkh			sprintf(pname, "%s%c", sname, j + 'a');
2982116Sjkh			if (Add_Chunk(d,
2992116Sjkh				dl.d_partitions[j].p_offset +
3002116Sjkh				ds.dss_slices[i].ds_offset,
3012116Sjkh				dl.d_partitions[j].p_size,
3022116Sjkh				pname,part,
3032116Sjkh				dl.d_partitions[j].p_fstype,
3042116Sjkh#ifdef PC98
3052116Sjkh				0,
3062116Sjkh				ds.dss_slices[i].ds_name) && j != 3)
3072116Sjkh#else
3082116Sjkh				0) && j != 3)
3092116Sjkh#endif
3102116Sjkh#ifdef DEBUG
3112116Sjkh				warn(
3122116Sjkh			"Failed to add chunk for partition %c [%lu,%lu]",
3132116Sjkh			j + 'a', dl.d_partitions[j].p_offset,
3142116Sjkh			dl.d_partitions[j].p_size);
3152116Sjkh#else
3162116Sjkh				{}
3172116Sjkh#endif
3182116Sjkh		}
3192116Sjkh		}
3202116Sjkh	}
3212116Sjkh#endif /* __i386__ */
3222116Sjkh#ifdef __alpha__
3232116Sjkh	{
3242116Sjkh		struct disklabel dl;
3252116Sjkh		char pname[20];
3262116Sjkh		int j,k;
3272116Sjkh
3282116Sjkh		strcpy(pname, _PATH_DEV);
3292116Sjkh		strcat(pname, name);
3302116Sjkh		j = open(pname, O_RDONLY);
3312116Sjkh		if (j < 0) {
3322116Sjkh#ifdef DEBUG
3332116Sjkh			warn("open(%s)", pname);
3342116Sjkh#endif
3352116Sjkh			goto nolabel;
3362116Sjkh		}
3372116Sjkh		k = ioctl(j, DIOCGDINFO, &dl);
3382116Sjkh		if (k < 0) {
3392116Sjkh#ifdef DEBUG
3402116Sjkh			warn("ioctl(%s, DIOCGDINFO)", pname);
3412116Sjkh#endif
3422116Sjkh			close(j);
3432116Sjkh			goto nolabel;
3442116Sjkh		}
3452116Sjkh		close(j);
3462116Sjkh		All_FreeBSD(d, 1);
3472116Sjkh
3482116Sjkh		for(j = 0; j <= dl.d_npartitions; j++) {
3492116Sjkh			if (j == RAW_PART)
3502116Sjkh				continue;
3512116Sjkh			if (j == 3)
3522116Sjkh				continue;
3532116Sjkh			if (j == dl.d_npartitions) {
3542116Sjkh				j = 3;
3552116Sjkh				dl.d_npartitions = 0;
3562116Sjkh			}
3572116Sjkh			if (!dl.d_partitions[j].p_size)
3582116Sjkh				continue;
3592116Sjkh			if (dl.d_partitions[j].p_size +
3602116Sjkh			    dl.d_partitions[j].p_offset >
3612116Sjkh			    ds.dss_slices[WHOLE_DISK_SLICE].ds_size)
3622116Sjkh				continue;
3632116Sjkh			sprintf(pname, "%s%c", name, j + 'a');
3642116Sjkh			if (Add_Chunk(d,
3652116Sjkh				      dl.d_partitions[j].p_offset,
3662116Sjkh				      dl.d_partitions[j].p_size,
3672116Sjkh				      pname,part,
3682116Sjkh				      dl.d_partitions[j].p_fstype,
3692116Sjkh				      0) && j != 3)
3702116Sjkh#ifdef DEBUG
3712116Sjkh				warn(
3722116Sjkh					"Failed to add chunk for partition %c [%lu,%lu]",
3732116Sjkh					j + 'a', dl.d_partitions[j].p_offset,
3742116Sjkh					dl.d_partitions[j].p_size);
3752116Sjkh#else
3762116Sjkh			{}
377#endif
378		}
379	nolabel:;
380	}
381#endif /* __alpha__ */
382#ifdef PC98
383pc98_mo_done:
384#endif
385	close(fd);
386	Fixup_Names(d);
387	return d;
388}
389
390void
391Debug_Disk(struct disk *d)
392{
393	printf("Debug_Disk(%s)", d->name);
394	printf("  flags=%lx", d->flags);
395#if 0
396	printf("  real_geom=%lu/%lu/%lu", d->real_cyl, d->real_hd, d->real_sect);
397#endif
398	printf("  bios_geom=%lu/%lu/%lu = %lu\n",
399		d->bios_cyl, d->bios_hd, d->bios_sect,
400		d->bios_cyl * d->bios_hd * d->bios_sect);
401#if defined(PC98)
402	printf("  boot1=%p, boot2=%p, bootipl=%p, bootmenu=%p\n",
403		d->boot1, d->boot2, d->bootipl, d->bootmenu);
404#elif defined(__i386__)
405	printf("  boot1=%p, boot2=%p, bootmgr=%p\n",
406		d->boot1, d->boot2, d->bootmgr);
407#elif defined(__alpha__)
408	printf("  boot1=%p, bootmgr=%p\n",
409		d->boot1, d->bootmgr);
410#endif
411	Debug_Chunk(d->chunks);
412}
413
414void
415Free_Disk(struct disk *d)
416{
417	if(d->chunks) Free_Chunk(d->chunks);
418	if(d->name) free(d->name);
419#ifdef PC98
420	if(d->bootipl) free(d->bootipl);
421	if(d->bootmenu) free(d->bootmenu);
422#else
423	if(d->bootmgr) free(d->bootmgr);
424#endif
425	if(d->boot1) free(d->boot1);
426#if defined(__i386__)
427	if(d->boot2) free(d->boot2);
428#endif
429	free(d);
430}
431
432struct disk *
433Clone_Disk(struct disk *d)
434{
435	struct disk *d2;
436
437	d2 = (struct disk*) malloc(sizeof *d2);
438	if(!d2) return NULL;
439	*d2 = *d;
440	d2->name = strdup(d2->name);
441	d2->chunks = Clone_Chunk(d2->chunks);
442#ifdef PC98
443	if(d2->bootipl) {
444		d2->bootipl = malloc(d2->bootipl_size);
445		memcpy(d2->bootipl, d->bootipl, d2->bootipl_size);
446	}
447	if(d2->bootmenu) {
448		d2->bootmenu = malloc(d2->bootmenu_size);
449		memcpy(d2->bootmenu, d->bootmenu, d2->bootmenu_size);
450	}
451#else
452	if(d2->bootmgr) {
453		d2->bootmgr = malloc(d2->bootmgr_size);
454		memcpy(d2->bootmgr, d->bootmgr, d2->bootmgr_size);
455	}
456#endif
457#if defined(__i386__)
458	if(d2->boot1) {
459		d2->boot1 = malloc(512);
460		memcpy(d2->boot1, d->boot1, 512);
461	}
462	if(d2->boot2) {
463		d2->boot2 = malloc(512 * 15);
464		memcpy(d2->boot2, d->boot2, 512 * 15);
465	}
466#elif defined(__alpha__)
467	if(d2->boot1) {
468		d2->boot1 = malloc(512 * 15);
469		memcpy(d2->boot1, d->boot1, 512 * 15);
470	}
471#endif
472	return d2;
473}
474
475#if 0
476void
477Collapse_Disk(struct disk *d)
478{
479
480	while(Collapse_Chunk(d, d->chunks))
481		;
482}
483#endif
484
485#ifdef PC98
486static char * device_list[] = {"wd", "aacd", "ad", "da", "afd", "fla", "idad", "mlxd", "amrd", "twed", "ar", "fd", 0};
487#else
488static char * device_list[] = {"aacd", "ad", "da", "afd", "fla", "idad", "mlxd", "amrd", "twed", "ar", "fd", 0};
489#endif
490
491int qstrcmp(const void* a, const void* b) {
492
493	char *str1 = *(char**)a;
494	char *str2 = *(char**)b;
495	return strcmp(str1, str2);
496
497}
498
499char **
500Disk_Names()
501{
502    int i,j,disk_cnt;
503    char disk[25];
504    char diskname[25];
505    struct stat st;
506    struct diskslices ds;
507    int fd;
508    static char **disks;
509    int error;
510    size_t listsize;
511    char *disklist, **dp;
512
513    disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS));
514    memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS));
515    error = sysctlbyname("kern.disks", NULL, &listsize, NULL, 0);
516    if (!error) {
517	    disklist = (char *)malloc(listsize);
518	    error = sysctlbyname("kern.disks", disklist, &listsize, NULL, 0);
519	    if (error)
520		    return NULL;
521	    disk_cnt = 0;
522	    for (dp = disks; ((*dp = strsep(&disklist, " ")) != NULL) &&
523			 disk_cnt < MAX_NO_DISKS; disk_cnt++, dp++);
524    } else {
525    warn("kern.disks sysctl not available");
526    disk_cnt = 0;
527	for (j = 0; device_list[j]; j++) {
528		if(disk_cnt >= MAX_NO_DISKS)
529			break;
530		for (i = 0; i < MAX_NO_DISKS; i++) {
531			sprintf(diskname, "%s%d", device_list[j], i);
532			sprintf(disk, _PATH_DEV"%s", diskname);
533			if (stat(disk, &st) || !(st.st_mode & S_IFCHR))
534				continue;
535			if ((fd = open(disk, O_RDWR)) == -1)
536				continue;
537			if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) {
538#ifdef DEBUG
539				warn("DIOCGSLICEINFO %s", disk);
540#endif
541				close(fd);
542				continue;
543			}
544			close(fd);
545			disks[disk_cnt++] = strdup(diskname);
546			if(disk_cnt >= MAX_NO_DISKS)
547				break;
548		}
549	}
550    }
551    qsort(disks, disk_cnt, sizeof(char*), qstrcmp);
552
553    return disks;
554}
555
556#ifdef PC98
557void
558Set_Boot_Mgr(struct disk *d, const u_char *bootipl, const size_t bootipl_size,
559	     const u_char *bootmenu, const size_t bootmenu_size)
560#else
561void
562Set_Boot_Mgr(struct disk *d, const u_char *b, const size_t s)
563#endif
564{
565#ifdef PC98
566	if (bootipl_size % d->sector_size != 0)
567		return;
568	if (d->bootipl)
569		free(d->bootipl);
570	if (!bootipl) {
571		d->bootipl = NULL;
572	} else {
573		d->bootipl_size = bootipl_size;
574		d->bootipl = malloc(bootipl_size);
575		if(!d->bootipl) return;
576		memcpy(d->bootipl, bootipl, bootipl_size);
577	}
578
579	if (bootmenu_size % d->sector_size != 0)
580		return;
581	if (d->bootmenu)
582		free(d->bootmenu);
583	if (!bootmenu) {
584		d->bootmenu = NULL;
585	} else {
586		d->bootmenu_size = bootmenu_size;
587		d->bootmenu = malloc(bootmenu_size);
588		if(!d->bootmenu) return;
589		memcpy(d->bootmenu, bootmenu, bootmenu_size);
590	}
591#else
592	if (s % d->sector_size != 0)
593		return;
594	if (d->bootmgr)
595		free(d->bootmgr);
596	if (!b) {
597		d->bootmgr = NULL;
598	} else {
599		d->bootmgr_size = s;
600		d->bootmgr = malloc(s);
601		if(!d->bootmgr) return;
602		memcpy(d->bootmgr, b, s);
603	}
604#endif
605}
606
607int
608Set_Boot_Blocks(struct disk *d, const u_char *b1, const u_char *b2)
609{
610#if defined(__i386__)
611	if (d->boot1) free(d->boot1);
612	d->boot1 = malloc(512);
613	if(!d->boot1) return -1;
614	memcpy(d->boot1, b1, 512);
615	if (d->boot2) free(d->boot2);
616	d->boot2 = malloc(15 * 512);
617	if(!d->boot2) return -1;
618	memcpy(d->boot2, b2, 15 * 512);
619#elif defined(__alpha__)
620	if (d->boot1) free(d->boot1);
621	d->boot1 = malloc(15 * 512);
622	if(!d->boot1) return -1;
623	memcpy(d->boot1, b1, 15 * 512);
624#endif
625	return 0;
626}
627
628const char *
629slice_type_name( int type, int subtype )
630{
631	switch (type) {
632		case 0:		return "whole";
633#ifndef	PC98
634		case 1:		switch (subtype) {
635					case 1:		return "fat (12-bit)";
636					case 2:		return "XENIX /";
637					case 3:		return "XENIX /usr";
638					case 4:         return "fat (16-bit,<=32Mb)";
639					case 5:		return "extended DOS";
640					case 6:         return "fat (16-bit,>32Mb)";
641					case 7:         return "NTFS/HPFS/QNX";
642					case 8:         return "AIX bootable";
643					case 9:         return "AIX data";
644					case 10:	return "OS/2 bootmgr";
645					case 11:        return "fat (32-bit)";
646					case 12:        return "fat (32-bit,LBA)";
647					case 14:        return "fat (16-bit,>32Mb,LBA)";
648					case 15:        return "extended DOS, LBA";
649					case 18:        return "Compaq Diagnostic";
650					case 84:	return "OnTrack diskmgr";
651					case 100:	return "Netware 2.x";
652					case 101:	return "Netware 3.x";
653					case 115:	return "SCO UnixWare";
654					case 128:	return "Minix 1.1";
655					case 129:	return "Minix 1.5";
656					case 130:	return "linux_swap";
657					case 131:	return "ext2fs";
658					case 166:	return "OpenBSD FFS";	/* 0xA6 */
659					case 169:	return "NetBSD FFS";	/* 0xA9 */
660					case 182:	return "OpenBSD";		/* dedicated */
661					case 183:	return "bsd/os";
662					case 184:	return "bsd/os swap";
663					case 238:	return "EFI GPT";
664					case 239:	return "EFI Sys. Part.";
665					default:	return "unknown";
666				}
667#endif
668		case 2:		return "fat";
669		case 3:		switch (subtype) {
670#ifdef	PC98
671					case 0xc494:	return "freebsd";
672#else
673					case 165:	return "freebsd";
674#endif
675					default:	return "unknown";
676				}
677#ifndef	PC98
678		case 4:		return "extended";
679		case 5:		return "part";
680		case 6:		return "unused";
681#endif
682		default:	return "unknown";
683	}
684}
685