svn commit: r237596 - user/ae/bootcode/sys/boot/common

Andrey V. Elsukov ae at FreeBSD.org
Tue Jun 26 10:48:48 UTC 2012


Author: ae
Date: Tue Jun 26 10:48:48 2012
New Revision: 237596
URL: http://svn.freebsd.org/changeset/base/237596

Log:
  Reimplement code in the disk.c to work with partition tables using
  new API. Since there is no way to know the disk size and sector size
  from this layer, change the disk_open() function to take 3 arguments.
  Also add the disk_close() function to freeing dynamically allocated
  recources.

Modified:
  user/ae/bootcode/sys/boot/common/disk.c
  user/ae/bootcode/sys/boot/common/disk.h

Modified: user/ae/bootcode/sys/boot/common/disk.c
==============================================================================
--- user/ae/bootcode/sys/boot/common/disk.c	Tue Jun 26 10:40:48 2012	(r237595)
+++ user/ae/bootcode/sys/boot/common/disk.c	Tue Jun 26 10:48:48 2012	(r237596)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1998 Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2012 Andrey V. Elsukov <ae at FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,26 +28,11 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-/*
- * MBR/GPT partitioned disk device handling.
- *
- * Ideas and algorithms from:
- *
- * - NetBSD libi386/biosdisk.c
- * - FreeBSD biosboot/disk.c
- *
- */
-
+#include <sys/disk.h>
 #include <stand.h>
-
-#include <sys/diskmbr.h>
-#include <sys/disklabel.h>
-#include <sys/gpt.h>
-
 #include <stdarg.h>
-#include <uuid.h>
-
 #include <bootstrap.h>
+#include <part.h>
 
 #include "disk.h"
 
@@ -56,53 +42,26 @@ __FBSDID("$FreeBSD$");
 # define DEBUG(fmt, args...)
 #endif
 
-/*
- * Search for a slice with the following preferences:
- *
- * 1: Active FreeBSD slice
- * 2: Non-active FreeBSD slice
- * 3: Active Linux slice
- * 4: non-active Linux slice
- * 5: Active FAT/FAT32 slice
- * 6: non-active FAT/FAT32 slice
- */
-#define PREF_RAWDISK	0
-#define PREF_FBSD_ACT	1
-#define PREF_FBSD	2
-#define PREF_LINUX_ACT	3
-#define PREF_LINUX	4
-#define PREF_DOS_ACT	5
-#define PREF_DOS	6
-#define PREF_NONE	7
-
-#ifdef LOADER_GPT_SUPPORT
-
-struct gpt_part {
-	int		gp_index;
-	uuid_t		gp_type;
-	uint64_t	gp_start;
-	uint64_t	gp_end;
+struct open_disk {
+	struct ptable		*table;
+	off_t			mediasize;
+	u_int			sectorsize;
 };
 
-static uuid_t efi = GPT_ENT_TYPE_EFI;
-static uuid_t freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
-static uuid_t freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
-static uuid_t freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
-static uuid_t freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
-static uuid_t ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
-
-#endif
-
-#if defined(LOADER_GPT_SUPPORT) || defined(LOADER_MBR_SUPPORT)
+struct print_args {
+	struct disk_devdesc	*dev;
+	const char		*prefix;
+	int			verbose;
+};
 
-/* Given a size in 512 byte sectors, convert it to a human-readable number. */
+/* Convert size to a human-readable number. */
 static char *
-display_size(uint64_t size)
+display_size(uint64_t size, u_int sectorsize)
 {
 	static char buf[80];
 	char unit;
 
-	size /= 2;
+	size = size * sectorsize / 1024;
 	unit = 'K';
 	if (size >= 10485760000LL) {
 		size /= 1073741824;
@@ -118,683 +77,168 @@ display_size(uint64_t size)
 	return (buf);
 }
 
-#endif
-
-#ifdef LOADER_MBR_SUPPORT
-
-static void
-disk_checkextended(struct disk_devdesc *dev,
-    struct dos_partition *slicetab, int slicenum, int *nslicesp)
-{
-	uint8_t			buf[DISK_SECSIZE];
-	struct dos_partition	*dp;
-	uint32_t		base;
-	int			rc, i, start, end;
-
-	dp = &slicetab[slicenum];
-	start = *nslicesp;
-
-	if (dp->dp_size == 0)
-		goto done;
-	if (dp->dp_typ != DOSPTYP_EXT)
-		goto done;
-	rc = dev->d_dev->dv_strategy(dev, F_READ, dp->dp_start, DISK_SECSIZE,
-		(char *) buf, NULL);
-	if (rc)
-		goto done;
-	if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) {
-		DEBUG("no magic in extended table");
-		goto done;
-	}
-	base = dp->dp_start;
-	dp = (struct dos_partition *) &buf[DOSPARTOFF];
-	for (i = 0; i < NDOSPART; i++, dp++) {
-		if (dp->dp_size == 0)
-			continue;
-		if (*nslicesp == NEXTDOSPART)
-			goto done;
-		dp->dp_start += base;
-		bcopy(dp, &slicetab[*nslicesp], sizeof(*dp));
-		(*nslicesp)++;
-	}
-	end = *nslicesp;
-
-	/*
-	 * now, recursively check the slices we just added
-	 */
-	for (i = start; i < end; i++)
-		disk_checkextended(dev, slicetab, i, nslicesp);
-done:
-	return;
-}
-
 static int
-disk_readslicetab(struct disk_devdesc *dev,
-    struct dos_partition **slicetabp, int *nslicesp)
-{
-	struct dos_partition	*slicetab = NULL;
-	int			nslices, i;
-	int			rc;
-	uint8_t			buf[DISK_SECSIZE];
-
-	/*
-	 * Find the slice in the DOS slice table.
-	 */
-	rc = dev->d_dev->dv_strategy(dev, F_READ, 0, DISK_SECSIZE,
-		(char *) buf, NULL);
-	if (rc) {
-		DEBUG("error reading MBR");
-		return (rc);
-	}
-
-	/*
-	 * Check the slice table magic.
-	 */
-	if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) {
-		DEBUG("no slice table/MBR (no magic)");
-		return (rc);
-	}
-
-	/*
-	 * copy the partition table, then pick up any extended partitions.
-	 */
-	slicetab = malloc(NEXTDOSPART * sizeof(struct dos_partition));
-	bcopy(buf + DOSPARTOFF, slicetab,
-		sizeof(struct dos_partition) * NDOSPART);
-	nslices = NDOSPART;		/* extended slices start here */
-	for (i = 0; i < NDOSPART; i++)
-		disk_checkextended(dev, slicetab, i, &nslices);
-
-	*slicetabp = slicetab;
-	*nslicesp = nslices;
-	return (0);
-}
-
-/*
- * Search for the best MBR slice (typically the first FreeBSD slice).
- */
-static int
-disk_bestslice(struct dos_partition *slicetab, int nslices)
-{
-	struct dos_partition *dp;
-	int pref, preflevel;
-	int i, prefslice;
-
-	prefslice = 0;
-	preflevel = PREF_NONE;
-
-	dp = &slicetab[0];
-	for (i = 0; i < nslices; i++, dp++) {
-		switch (dp->dp_typ) {
-		case DOSPTYP_386BSD:		/* FreeBSD */
-			pref = dp->dp_flag & 0x80 ? PREF_FBSD_ACT : PREF_FBSD;
-			break;
-
-		case DOSPTYP_LINUX:
-			pref = dp->dp_flag & 0x80 ? PREF_LINUX_ACT : PREF_LINUX;
-			break;
-
-		case 0x01:		/* DOS/Windows */
-		case 0x04:
-		case 0x06:
-		case 0x0b:
-		case 0x0c:
-		case 0x0e:
-			pref = dp->dp_flag & 0x80 ? PREF_DOS_ACT : PREF_DOS;
-			break;
-
-		default:
-		        pref = PREF_NONE;
-		}
-		if (pref < preflevel) {
-			preflevel = pref;
-			prefslice = i + 1;
-		}
-	}
-	return (prefslice);
-}
-
-static int
-disk_openmbr(struct disk_devdesc *dev)
-{
-	struct dos_partition	*slicetab = NULL, *dptr;
-	int			nslices, sector, slice;
-	int			rc;
-	uint8_t			buf[DISK_SECSIZE];
-	struct disklabel	*lp;
-
-	/*
-	 * Following calculations attempt to determine the correct value
-	 * for dev->d_offset by looking for the slice and partition specified,
-	 * or searching for reasonable defaults.
-	 */
-	rc = disk_readslicetab(dev, &slicetab, &nslices);
-	if (rc)
-		return (rc);
-
-	/*
-	 * if a slice number was supplied but not found, this is an error.
-	 */
-	if (dev->d_slice > 0) {
-		slice = dev->d_slice - 1;
-		if (slice >= nslices) {
-			DEBUG("slice %d not found", slice);
-			rc = EPART;
-			goto out;
-		}
-	}
-
-	/*
-	 * Check for the historically bogus MBR found on true dedicated disks
-	 */
-	if (slicetab[3].dp_typ == DOSPTYP_386BSD &&
-	    slicetab[3].dp_start == 0 && slicetab[3].dp_size == 50000) {
-		sector = 0;
-		goto unsliced;
-	}
-
-	/*
-	 * Try to auto-detect the best slice; this should always give
-	 * a slice number
-	 */
-	if (dev->d_slice == 0) {
-		slice = disk_bestslice(slicetab, nslices);
-		if (slice == -1) {
-			rc = ENOENT;
-			goto out;
-		}
-		dev->d_slice = slice;
-	}
-
-	/*
-	 * Accept the supplied slice number unequivocally (we may be looking
-	 * at a DOS partition).
-	 * Note: we number 1-4, offsets are 0-3
-	 */
-	dptr = &slicetab[dev->d_slice - 1];
-	sector = dptr->dp_start;
-	DEBUG("slice entry %d at %d, %d sectors",
-		dev->d_slice - 1, sector, dptr->dp_size);
-
-unsliced:
-	/*
-	 * Now we have the slice offset, look for the partition in the
-	 * disklabel if we have a partition to start with.
-	 *
-	 * XXX we might want to check the label checksum.
-	 */
-	if (dev->d_partition < 0) {
-		/* no partition, must be after the slice */
-		DEBUG("opening raw slice");
-		dev->d_offset = sector;
-		rc = 0;
-		goto out;
-	}
-
-	rc = dev->d_dev->dv_strategy(dev, F_READ, sector + LABELSECTOR,
-            DISK_SECSIZE, (char *) buf, NULL);
-	if (rc) {
-		DEBUG("error reading disklabel");
-		goto out;
-	}
-
-	lp = (struct disklabel *) buf;
-
-	if (lp->d_magic != DISKMAGIC) {
-		DEBUG("no disklabel");
-		rc = ENOENT;
-		goto out;
-	}
-	if (dev->d_partition >= lp->d_npartitions) {
-		DEBUG("partition '%c' exceeds partitions in table (a-'%c')",
-		  'a' + dev->d_partition,
-		  'a' + lp->d_npartitions);
-		rc = EPART;
-		goto out;
-	}
-
-	dev->d_offset =
-		lp->d_partitions[dev->d_partition].p_offset -
-		lp->d_partitions[RAW_PART].p_offset +
-		sector;
-	rc = 0;
-
-out:
-	if (slicetab)
-		free(slicetab);
-	return (rc);
-}
-
-/*
- * Print out each valid partition in the disklabel of a FreeBSD slice.
- * For size calculations, we assume a 512 byte sector size.
- */
-static void
-disk_printbsdslice(struct disk_devdesc *dev, daddr_t offset,
-    char *prefix, int verbose)
+ptblread(void *d, void *buf, size_t blocks, off_t offset)
 {
-	char			line[80];
-	char			buf[DISK_SECSIZE];
-	struct disklabel	*lp;
-	int			i, rc, fstype;
-
-	/* read disklabel */
-	rc = dev->d_dev->dv_strategy(dev, F_READ, offset + LABELSECTOR,
-		DISK_SECSIZE, (char *) buf, NULL);
-	if (rc)
-		return;
-	lp =(struct disklabel *)(&buf[0]);
-	if (lp->d_magic != DISKMAGIC) {
-		sprintf(line, "%s: FFS  bad disklabel\n", prefix);
-		pager_output(line);
-		return;
-	}
+	struct disk_devdesc *dev;
+	struct open_disk *od;
 
-	/* Print partitions */
-	for (i = 0; i < lp->d_npartitions; i++) {
-		/*
-		 * For each partition, make sure we know what type of fs it
-		 * is.  If not, then skip it.
-		 */
-		fstype = lp->d_partitions[i].p_fstype;
-		if (fstype != FS_BSDFFS &&
-		    fstype != FS_SWAP &&
-		    fstype != FS_VINUM)
-			continue;
-
-		/* Only print out statistics in verbose mode */
-		if (verbose)
-			sprintf(line, "  %s%c: %s %s (%d - %d)\n",
-				prefix, 'a' + i,
-			    (fstype == FS_SWAP) ? "swap " :
-			    (fstype == FS_VINUM) ? "vinum" :
-			    "FFS  ",
-			    display_size(lp->d_partitions[i].p_size),
-			    lp->d_partitions[i].p_offset,
-			    (lp->d_partitions[i].p_offset
-			     + lp->d_partitions[i].p_size));
-		else
-			sprintf(line, "  %s%c: %s\n", prefix, 'a' + i,
-			    (fstype == FS_SWAP) ? "swap" :
-			    (fstype == FS_VINUM) ? "vinum" :
-			    "FFS");
-		pager_output(line);
-	}
+	dev = (struct disk_devdesc *)d;
+	od = (struct open_disk *)dev->d_opendata;
+	return (dev->d_dev->dv_strategy(dev, F_READ, offset,
+	    blocks * od->sectorsize, (char *)buf, NULL));
 }
 
 static void
-disk_printslice(struct disk_devdesc *dev, int slice,
-    struct dos_partition *dp, char *prefix, int verbose)
+ptable_print(void *arg, const char *pname, const struct ptable_entry *part)
 {
-	char stats[80];
+	struct print_args *pa, bsd;
+	struct open_disk *od;
+	struct ptable *table;
 	char line[80];
 
-	if (verbose)
-		sprintf(stats, " %s (%d - %d)", display_size(dp->dp_size),
-		    dp->dp_start, dp->dp_start + dp->dp_size);
-	else
-		stats[0] = '\0';
-
-	switch (dp->dp_typ) {
-	case DOSPTYP_386BSD:
-		disk_printbsdslice(dev, (daddr_t)dp->dp_start,
-		     prefix, verbose);
-		return;
-	case DOSPTYP_LINSWP:
-		sprintf(line, "%s: Linux swap%s\n", prefix, stats);
-		break;
-	case DOSPTYP_LINUX:
-		/*
-		 * XXX
-		 * read the superblock to confirm this is an ext2fs partition?
-		 */
-		sprintf(line, "%s: ext2fs%s\n", prefix, stats);
-		break;
-	case 0x00:				/* unused partition */
-	case DOSPTYP_EXT:
-		return;
-	case 0x01:
-		sprintf(line, "%s: FAT-12%s\n", prefix, stats);
-		break;
-	case 0x04:
-	case 0x06:
-	case 0x0e:
-		sprintf(line, "%s: FAT-16%s\n", prefix, stats);
-		break;
-	case 0x07:
-		sprintf(line, "%s: NTFS/HPFS%s\n", prefix, stats);
-		break;
-	case 0x0b:
-	case 0x0c:
-		sprintf(line, "%s: FAT-32%s\n", prefix, stats);
-		break;
-	default:
-		sprintf(line, "%s: Unknown fs: 0x%x %s\n", prefix, dp->dp_typ,
-		    stats);
-	}
+	pa = (struct print_args *)arg;
+	od = (struct open_disk *)pa->dev->d_opendata;
+	sprintf(line, "  %s%s: %s %s\n", pa->prefix, pname,
+	    parttype2str(part->type), pa->verbose == 0 ? "":
+	    display_size(part->end - part->start + 1, od->sectorsize));
 	pager_output(line);
-}
-
-static int
-disk_printmbr(struct disk_devdesc *dev, char *prefix, int verbose)
-{
-	struct dos_partition	*slicetab;
-	int			nslices, i;
-	int			rc;
-	char			line[80];
-
-	rc = disk_readslicetab(dev, &slicetab, &nslices);
-	if (rc)
-		return (rc);
-	for (i = 0; i < nslices; i++) {
-		sprintf(line, "%ss%d", prefix, i + 1);
-		disk_printslice(dev, i, &slicetab[i], line, verbose);
-	}
-	free(slicetab);
-	return (0);
-}
-
-#endif
-
-#ifdef LOADER_GPT_SUPPORT
-
-static int
-disk_readgpt(struct disk_devdesc *dev, struct gpt_part **gptp, int *ngptp)
-{
-	struct dos_partition	*dp;
-	struct gpt_hdr		*hdr;
-	struct gpt_ent		*ent;
-	struct gpt_part		*gptab = NULL;
-	int			entries_per_sec, rc, i, part;
-	daddr_t			lba, elba;
-	uint8_t			gpt[DISK_SECSIZE], tbl[DISK_SECSIZE];
-
-	/*
-	 * Following calculations attempt to determine the correct value
-	 * for dev->d_offset by looking for the slice and partition specified,
-	 * or searching for reasonable defaults.
-	 */
-	rc = 0;
-
-	/* First, read the MBR and see if we have a PMBR. */
-	rc = dev->d_dev->dv_strategy(dev, F_READ, 0, DISK_SECSIZE,
-		(char *) tbl, NULL);
-	if (rc) {
-		DEBUG("error reading MBR");
-		return (EIO);
-	}
-
-	/* Check the slice table magic. */
-	if (tbl[0x1fe] != 0x55 || tbl[0x1ff] != 0xaa)
-		return (ENXIO);
-
-	/* Check for GPT slice. */
-	part = 0;
-	dp = (struct dos_partition *)(tbl + DOSPARTOFF);
-	for (i = 0; i < NDOSPART; i++) {
-		if (dp[i].dp_typ == 0xee)
-			part++;
-		else if ((part != 1) && (dp[i].dp_typ != 0x00))
-			return (EINVAL);
-	}
-	if (part != 1)
-		return (EINVAL);
-
-	/* Read primary GPT table header. */
-	rc = dev->d_dev->dv_strategy(dev, F_READ, 1, DISK_SECSIZE,
-		(char *) gpt, NULL);
-	if (rc) {
-		DEBUG("error reading GPT header");
-		return (EIO);
-	}
-	hdr = (struct gpt_hdr *)gpt;
-	if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 ||
-	    hdr->hdr_lba_self != 1 || hdr->hdr_revision < 0x00010000 ||
-	    hdr->hdr_entsz < sizeof(*ent) ||
-	    DISK_SECSIZE % hdr->hdr_entsz != 0) {
-		DEBUG("Invalid GPT header\n");
-		return (EINVAL);
-	}
-
-	/* Walk the partition table to count valid partitions. */
-	part = 0;
-	entries_per_sec = DISK_SECSIZE / hdr->hdr_entsz;
-	elba = hdr->hdr_lba_table + hdr->hdr_entries / entries_per_sec;
-	for (lba = hdr->hdr_lba_table; lba < elba; lba++) {
-		rc = dev->d_dev->dv_strategy(dev, F_READ, lba, DISK_SECSIZE,
-			(char *) tbl, NULL);
-		if (rc) {
-			DEBUG("error reading GPT table");
-			return (EIO);
-		}
-		for (i = 0; i < entries_per_sec; i++) {
-			ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz);
-			if (uuid_is_nil(&ent->ent_type, NULL) ||
-			    ent->ent_lba_start == 0 ||
-			    ent->ent_lba_end < ent->ent_lba_start)
-				continue;
-			part++;
-		}
-	}
-
-	/* Save the important information about all the valid partitions. */
-	if (part != 0) {
-		gptab = malloc(part * sizeof(struct gpt_part));
-		part = 0;
-		for (lba = hdr->hdr_lba_table; lba < elba; lba++) {
-			rc = dev->d_dev->dv_strategy(dev, F_READ, lba, DISK_SECSIZE,
-				(char *) tbl, NULL);
-			if (rc) {
-				DEBUG("error reading GPT table");
-				free(gptab);
-				return (EIO);
-			}
-			for (i = 0; i < entries_per_sec; i++) {
-				ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz);
-				if (uuid_is_nil(&ent->ent_type, NULL) ||
-				    ent->ent_lba_start == 0 ||
-				    ent->ent_lba_end < ent->ent_lba_start)
-					continue;
-				gptab[part].gp_index = (lba - hdr->hdr_lba_table) *
-					entries_per_sec + i + 1;
-				gptab[part].gp_type = ent->ent_type;
-				gptab[part].gp_start = ent->ent_lba_start;
-				gptab[part].gp_end = ent->ent_lba_end;
-				part++;
-			}
-		}
+	if (part->type == PART_FREEBSD) {
+		/* Open slice with BSD label */
+		pa->dev->d_offset = part->start;
+		table = ptable_open(pa->dev, part->end - part->start + 1,
+		    od->sectorsize, ptblread);
+		if (table == NULL)
+			return;
+		sprintf(line, "  %s%s", pa->prefix, pname);
+		bsd.dev = pa->dev;
+		bsd.prefix = line;
+		bsd.verbose = pa->verbose;
+		ptable_iterate(table, &bsd, ptable_print);
+		ptable_close(table);
 	}
-
-	*gptp = gptab;
-	*ngptp = part;
-	return (0);
 }
 
-static struct gpt_part *
-disk_bestgpt(struct gpt_part *gpt, int ngpt)
+void
+disk_print(struct disk_devdesc *dev, char *prefix, int verbose)
 {
-	struct gpt_part *gp, *prefpart;
-	int i, pref, preflevel;
-
-	prefpart = NULL;
-	preflevel = PREF_NONE;
+	struct open_disk *od;
+	struct print_args pa;
 
-	gp = gpt;
-	for (i = 0; i < ngpt; i++, gp++) {
-		/* Windows. XXX: Also Linux. */
-		if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL))
-			pref = PREF_DOS;
-		/* FreeBSD */
-		else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL) ||
-		         uuid_equal(&gp->gp_type, &freebsd_zfs, NULL))
-			pref = PREF_FBSD;
-		else
-			pref = PREF_NONE;
-		if (pref < preflevel) {
-			preflevel = pref;
-			prefpart = gp;
-		}
-	}
-	return (prefpart);
+	/* Disk should be opened */
+	od = (struct open_disk *)dev->d_opendata;
+	pa.dev = dev;
+	pa.prefix = prefix;
+	pa.verbose = verbose;
+	ptable_iterate(od->table, &pa, ptable_print);
 }
 
-static int
-disk_opengpt(struct disk_devdesc *dev)
+int
+disk_open(struct disk_devdesc *dev, off_t mediasize, u_int sectorsize)
 {
-	struct gpt_part		*gpt = NULL, *gp;
-	int			rc, ngpt, i;
+	struct open_disk *od;
+	struct ptable *table;
+	struct ptable_entry part;
+	int rc;
 
-	rc = disk_readgpt(dev, &gpt, &ngpt);
-	if (rc)
-		return (rc);
-
-	/* Is this a request for the whole disk? */
-	if (dev->d_slice < 0) {
-		dev->d_offset = 0;
-		rc = 0;
-		goto out;
+	od = (struct open_disk *)malloc(sizeof(struct open_disk));
+	if (od == NULL) {
+		DEBUG("no memory");
+		return (ENOMEM);
 	}
-
 	/*
-	 * If a partition number was supplied, then the user is trying to use
-	 * an MBR address rather than a GPT address, so fail.
+	 * While we are reading disk metadata, make sure we do it relative
+	 * to the start of the disk
 	 */
-	if (dev->d_partition != 0xff) {
-		rc = ENOENT;
+	rc = 0;
+	table = NULL;
+	dev->d_offset = 0;
+	dev->d_opendata = od;
+	od->mediasize = mediasize;
+	od->sectorsize = sectorsize;
+	DEBUG("open '%s', unit %d slice %d partition %d",
+	    disk_fmtdev(dev), dev->d_unit, dev->d_slice, dev->d_partition);
+
+	/* Determine disk layout. */
+	od->table = ptable_open(dev, mediasize / sectorsize, sectorsize,
+	    ptblread);
+	if (od->table == NULL) {
+		DEBUG("Can't read partition table");
+		rc = ENXIO;
 		goto out;
 	}
-
-	/* If a slice number was supplied but not found, this is an error. */
-	gp = NULL;
 	if (dev->d_slice > 0) {
-		for (i = 0; i < ngpt; i++) {
-			if (gpt[i].gp_index == dev->d_slice) {
-				gp = &gpt[i];
-				break;
-			}
-		}
-		if (gp == NULL) {
-			DEBUG("partition %d not found", dev->d_slice);
-			rc = ENOENT;
+		/* Try to get information about partition */
+		rc = ptable_getpart(od->table, &part, dev->d_slice);
+		if (rc != 0) /* Partition doesn't exist */
 			goto out;
-		}
-	}
-
-	/* Try to auto-detect the best partition. */
-	if (dev->d_slice == 0) {
-		gp = disk_bestgpt(gpt, ngpt);
-		if (gp == NULL) {
-			rc = ENOENT;
+		dev->d_offset = part.start;
+		if (dev->d_partition == -1 ||
+		    dev->d_partition == 255)
+			goto out; /* Nothing more to do */
+
+		/* Try to read BSD label */
+		table = ptable_open(dev, part.end - part.start + 1,
+		    od->sectorsize, ptblread);
+		if (table == NULL) {
+			DEBUG("Can't read BSD label");
+			rc = ENXIO;
 			goto out;
 		}
-		dev->d_slice = gp->gp_index;
+		rc = ptable_getpart(table, &part, dev->d_partition);
+		if (rc != 0)
+			goto out;
+		dev->d_offset += part.start;
+	} else if (dev->d_slice == 0) {
+		rc = ptable_getbestpart(od->table, &part);
+		if (rc != 0)
+			goto out;
+		/* Save the slice number of best partition to dev */
+		dev->d_slice = part.index;
+		dev->d_offset = part.start;
 	}
-
-	dev->d_offset = gp->gp_start;
-	rc = 0;
-
 out:
-	if (gpt)
-		free(gpt);
-	return (rc);
-}
-
-static void
-disk_printgptpart(struct disk_devdesc *dev, struct gpt_part *gp,
-    char *prefix, int verbose)
-{
-	char stats[80];
-	char line[96];
-
-	if (verbose)
-		sprintf(stats, " %s",
-			display_size(gp->gp_end + 1 - gp->gp_start));
-	else
-		stats[0] = '\0';
-
-	if (uuid_equal(&gp->gp_type, &efi, NULL))
-		sprintf(line, "%s: EFI         %s\n", prefix, stats);
-	else if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL))
-		sprintf(line, "%s: FAT/NTFS    %s\n", prefix, stats);
-	else if (uuid_equal(&gp->gp_type, &freebsd_boot, NULL))
-		sprintf(line, "%s: FreeBSD boot%s\n", prefix, stats);
-	else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL))
-		sprintf(line, "%s: FreeBSD UFS %s\n", prefix, stats);
-	else if (uuid_equal(&gp->gp_type, &freebsd_zfs, NULL))
-		sprintf(line, "%s: FreeBSD ZFS %s\n", prefix, stats);
-	else if (uuid_equal(&gp->gp_type, &freebsd_swap, NULL))
-		sprintf(line, "%s: FreeBSD swap%s\n", prefix, stats);
-	else
-		sprintf(line,
-		    "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n",
-		    prefix,
-		    gp->gp_type.time_low, gp->gp_type.time_mid,
-		    gp->gp_type.time_hi_and_version,
-		    gp->gp_type.clock_seq_hi_and_reserved,
-		    gp->gp_type.clock_seq_low,
-		    gp->gp_type.node[0],
-		    gp->gp_type.node[1],
-		    gp->gp_type.node[2],
-		    gp->gp_type.node[3],
-		    gp->gp_type.node[4],
-		    gp->gp_type.node[5],
-		    stats);
-	pager_output(line);
-}
-
-static int
-disk_printgpt(struct disk_devdesc *dev, char *prefix, int verbose)
-{
-	struct gpt_part		*gpt = NULL;
-	int			rc, ngpt, i;
-	char			line[80];
-
-	rc = disk_readgpt(dev, &gpt, &ngpt);
-	if (rc)
-		return (rc);
-	for (i = 0; i < ngpt; i++) {
-		sprintf(line, "%sp%d", prefix, i + 1);
-		disk_printgptpart(dev, &gpt[i], line, verbose);
+	if (table != NULL)
+		ptable_close(table);
+	if (rc != 0) {
+		if (od->table != NULL)
+			ptable_close(od->table);
+		free(od);
 	}
-	free(gpt);
-	return (0);
+	return (rc);
 }
 
-#endif
-
 int
-disk_open(struct disk_devdesc *dev)
+disk_close(struct disk_devdesc *dev)
 {
-	int rc;
-
-	rc = 0;
-	/*
-	 * While we are reading disk metadata, make sure we do it relative
-	 * to the start of the disk
-	 */
-	dev->d_offset = 0;
+	struct open_disk *od;
 
-#ifdef LOADER_GPT_SUPPORT
-	rc = disk_opengpt(dev);
-	if (rc == 0)
-		return (0);
-#endif
-#ifdef LOADER_MBR_SUPPORT
-	rc = disk_openmbr(dev);
-#endif
-
-	return (rc);
+	od = (struct open_disk *)dev->d_opendata;
+	ptable_close(od->table);
+	free(od);
+	return (0);
 }
 
-void
-disk_print(struct disk_devdesc *dev, char *prefix, int verbose)
+char*
+disk_fmtdev(struct disk_devdesc *dev)
 {
+	static char buf[128];
+	char *cp;
 
+	cp = buf + sprintf(buf, "%s%d", dev->d_dev->dv_name, dev->d_unit);
+	if (dev->d_slice > 0) {
 #ifdef LOADER_GPT_SUPPORT
-	if (disk_printgpt(dev, prefix, verbose) == 0)
-		return;
+		if (dev->d_partition == 255) {
+			sprintf(cp, "p%d:", dev->d_slice);
+			return (buf);
+		} else
 #endif
 #ifdef LOADER_MBR_SUPPORT
-	disk_printmbr(dev, prefix, verbose);
+			cp += sprintf(cp, "s%d", dev->d_slice);
 #endif
+		if (dev->d_partition >= 0)
+			cp += sprintf(cp, "%c", dev->d_partition + 'a');
+	}
+	strcat(cp, ":");
+	return (buf);
 }

Modified: user/ae/bootcode/sys/boot/common/disk.h
==============================================================================
--- user/ae/bootcode/sys/boot/common/disk.h	Tue Jun 26 10:40:48 2012	(r237595)
+++ user/ae/bootcode/sys/boot/common/disk.h	Tue Jun 26 10:48:48 2012	(r237596)
@@ -90,10 +90,14 @@ struct disk_devdesc
 /*
  * Parse disk metadata and initialise dev->d_offset.
  */
-extern int disk_open(struct disk_devdesc * dev);
+extern int disk_open(struct disk_devdesc *dev, off_t mediasize,
+    u_int sectorsize);
+extern int disk_close(struct disk_devdesc *dev);
 
 /*
  * Print information about slices on a disk.  For the size calculations we
  * assume a 512 byte sector.
  */
 extern void disk_print(struct disk_devdesc *dev, char *prefix, int verbose);
+extern char* disk_fmtdev(struct disk_devdesc *dev);
+


More information about the svn-src-user mailing list