Module Name:    src
Committed By:   phx
Date:           Sun Aug 21 13:08:58 UTC 2011

Modified Files:
        src/sys/arch/ofppc/stand/ofwboot: mbr.c

Log Message:
When there is no NetBSD MBR partition with a valid disklabel, look for
the first FAT partition and construct a disklabel with an MSDOS filesystem
in partition 'a'.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/ofppc/stand/ofwboot/mbr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/ofppc/stand/ofwboot/mbr.c
diff -u src/sys/arch/ofppc/stand/ofwboot/mbr.c:1.2 src/sys/arch/ofppc/stand/ofwboot/mbr.c:1.3
--- src/sys/arch/ofppc/stand/ofwboot/mbr.c:1.2	Thu Aug 18 09:03:28 2011
+++ src/sys/arch/ofppc/stand/ofwboot/mbr.c	Sun Aug 21 13:08:57 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: mbr.c,v 1.2 2011/08/18 09:03:28 phx Exp $	*/
+/*	$NetBSD: mbr.c,v 1.3 2011/08/21 13:08:57 phx Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -39,14 +39,9 @@
 
 #include "mbr.h"
 
-
-static u_long
-get_long(const void *p)
-{
-	const unsigned char *cp = p;
-
-	return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
-}
+static int find_mbr_part(struct of_dev *, uint32_t, char *,
+    struct disklabel *, uint32_t, uint8_t, int);
+static void make_dos_label(struct disklabel *, uint32_t);
 
 /*
  * Find a valid MBR disklabel.
@@ -55,58 +50,109 @@
 search_mbr_label(struct of_dev *devp, u_long off, char *buf,
     struct disklabel *lp, u_long off0)
 {
+	static uint8_t fat_types[] = {
+		MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, MBR_PTYPE_FAT16B,
+		MBR_PTYPE_FAT32, MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L
+	};
+	size_t read;
+	uint32_t poff;
+	int i;
+
+	/* Find a disklabel in a NetBSD or 386BSD partition. */
+	poff = find_mbr_part(devp, off, buf, lp, 0, MBR_PTYPE_NETBSD, 0);
+#ifdef COMPAT_386BSD_MBRPART
+	if (poff == 0) {
+		poff = find_mbr_part(devp, off, buf, lp, 0,
+		    MBR_PTYPE_386BSD, 0);
+		if (poff != 0)
+			printf("WARNING: old BSD partition ID!\n");
+	}
+#endif
+	if (poff != 0) {
+		if (strategy(devp, F_READ, poff + MBR_LABELSECTOR, DEV_BSIZE,
+		    buf, &read) == 0 && read == DEV_BSIZE)
+			if (getdisklabel(buf, lp) == NULL)
+				return 0;
+	}
+
+	/*
+	 * No BSD partition with a valid disklabel found, so try to
+	 * construct a label from a DOS partition.
+	 */
+	for (i = 0; i < sizeof(fat_types); i++) {
+		poff = find_mbr_part(devp, off, buf, lp, 0, fat_types[i], 0);
+		if (poff != 0) {
+			make_dos_label(lp, poff);
+			return 0;
+		}
+	}
+
+	return ERDLAB;
+}
+
+static int
+find_mbr_part(struct of_dev *devp, uint32_t off, char *buf,
+    struct disklabel *lp, uint32_t off0, uint8_t ptype, int recursion)
+{
 	size_t read;
 	struct mbr_partition *p;
 	int i;
-	u_long poff;
-	static int recursion;
+	uint32_t poff;
 
 	if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
 	    || read != DEV_BSIZE)
-		return ERDLAB;
+		return 0;
 
-	if (*(u_int16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC))
-		return ERDLAB;
+	if (*(uint16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC))
+		return 0;
 
 	if (recursion++ <= 1)
 		off0 += off;
+
 	for (p = (struct mbr_partition *)(buf + MBR_PART_OFFSET), i = 0;
 	     i < MBR_PART_COUNT; i++, p++) {
-		if (p->mbrp_type == MBR_PTYPE_NETBSD
-#ifdef COMPAT_386BSD_MBRPART
-		    || (p->mbrp_type == MBR_PTYPE_386BSD &&
-			(printf("WARNING: old BSD partition ID!\n"), 1)
-			/* XXX XXX - libsa printf() is void */ )
-#endif
-		    ) {
-			poff = get_long(&p->mbrp_start) + off0;
-			if (strategy(devp, F_READ, poff + MBR_LABELSECTOR,
-				     DEV_BSIZE, buf, &read) == 0
-			    && read == DEV_BSIZE) {
-				if (getdisklabel(buf, lp) == NULL) {
-					recursion--;
-					return 0;
-				}
-			}
-			if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
-			    || read != DEV_BSIZE) {
-				recursion--;
-				return ERDLAB;
-			}
-		} else if (p->mbrp_type == MBR_PTYPE_EXT) {
-			poff = get_long(&p->mbrp_start);
-			if (!search_mbr_label(devp, poff, buf, lp, off0)) {
+		if (p->mbrp_type == ptype) {
+			recursion--;
+			return sa_le32toh(p->mbrp_start) + off0;
+		}
+		else if (p->mbrp_type == MBR_PTYPE_EXT) {
+			poff = find_mbr_part(devp, sa_le32toh(p->mbrp_start),
+			    buf, lp, off0, ptype, recursion);
+			if (poff != 0) {
 				recursion--;
-				return 0;
+				return poff;
 			}
 			if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
 			    || read != DEV_BSIZE) {
 				recursion--;
-				return ERDLAB;
+				return 0;
 			}
 		}
 	}
 
 	recursion--;
-	return ERDLAB;
+	return 0;
+}
+
+static void
+make_dos_label(struct disklabel *lp, uint32_t poff)
+{
+	int i;
+
+	/* clear all partitions */
+	lp->d_npartitions = RAW_PART + 1;
+	for (i = 0; i < MAXPARTITIONS; i++) {
+		lp->d_partitions[i].p_size = 0;
+		lp->d_partitions[i].p_offset = 0;
+		lp->d_partitions[i].p_fstype = 0;
+	}
+
+	/* set DOS partition as root partition */
+	lp->d_partitions[0].p_offset = poff;
+	lp->d_partitions[0].p_fstype = FS_MSDOS;
+
+	/* disklabel is valid */
+	lp->d_magic = lp->d_magic2 = DISKMAGIC;
+	lp->d_checksum = 0;
+	lp->d_checksum = dkcksum(lp);
 }

Reply via email to