Subject: Boot loader changes for RAID boot
To: NetBSD port-sparc mailing list <port-sparc@netbsd.org>
From: Julian Coleman <jdc@coris.org.uk>
List: port-sparc
Date: 06/17/2006 11:34:30
--f2QGlHpHGjS2mn6Y
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I've made some changse to the boot loader code to enable booting from RAID 1.
The code looks at the disklabel and checks if the boot partition is of type
RAID.  If so, it offsets the reads from the disk, so that it can read the
kernel image.

I've tested this on a SPARCstation 20, a SPARCstation 2 and a 4/330.  The
only caveat is that the 4/330 will only boot from RAID if the RAID partition
is the first one on the disk, because I can't see any easy way of reading the
disklabel for machines without OBP (the `ok' prompt).

Patches are attached. Can anyone see any problem with them?

Thanks,

J

-- 
  My other computer also runs NetBSD    /        Sailing at Newbiggin
        http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/

--f2QGlHpHGjS2mn6Y
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="common.diffs"

diff -ur /usr/src/sys/arch/sparc/stand/common/promdev.c common/promdev.c
--- /usr/src/sys/arch/sparc/stand/common/promdev.c	2005-05-01 09:08:39.000000000 +0100
+++ common/promdev.c	2006-06-17 10:51:46.000000000 +0100
@@ -48,6 +48,12 @@
 #include <lib/libkern/libkern.h>
 #include <sparc/stand/common/promdev.h>
 
+#ifndef BOOTXX
+#include <sys/disklabel.h>
+#include <dev/sun/disklabel.h>
+#include <dev/raidframe/raidframevar.h>
+#endif
+
 /* OBP V0-3 PROM vector */
 #define obpvec	((struct promvec *)romp)
 
@@ -94,6 +100,10 @@
 char	prom_bootdevice[MAX_PROM_PATH];
 static int	saveecho;
 
+#ifndef BOOTXX
+static daddr_t doffset = 0;
+#endif
+
 
 void
 putchar(c)
@@ -119,6 +129,15 @@
 {
 	int	error = 0, fd = 0;
 	struct	promdata *pd;
+#ifndef BOOTXX
+	char *partition;
+	int part = 0;
+	char rawpart[MAX_PROM_PATH];
+	struct promdata *disk_pd;
+	char buf[DEV_BSIZE];
+	struct disklabel *dlp;
+	size_t read;
+#endif
 
 	pd = (struct promdata *)alloc(sizeof *pd);
 	f->f_devdata = (void *)pd;
@@ -188,8 +207,78 @@
 				prom_bootdevice);
 			return (error);
 		}
-	} else
+	} else {
 		bcopy(file_system_ufs, file_system, sizeof(struct fs_ops));
+
+#ifdef NOTDEF_DEBUG
+	printf("devopen: Checking disklabel for RAID partition\n");
+#endif
+
+		/*
+		 * We need to read from the raw partition (i.e. the
+		 * beginning of the disk in order to check the NetBSD
+		 * disklabel to see if the boot partition is type RAID.
+		 *
+		 * For machines with prom_version() == PROM_OLDMON, we
+		 * only handle boot from RAID for the first disk partition.
+		 */
+		disk_pd = (struct promdata *)alloc(sizeof *disk_pd);
+		memcpy(disk_pd, pd, sizeof(struct promdata));
+		if (prom_version() != PROM_OLDMON) {
+			strcpy(rawpart, prom_bootdevice);
+			if ((partition = strchr(rawpart, ':')) != '\0' &&
+		    	    *++partition >= 'a' &&
+			    *partition <= 'a' +  MAXPARTITIONS) {
+				part = *partition - 'a';
+				*partition = RAW_PART + 'a';
+			} else
+				strcat(rawpart, ":c");
+			if ((disk_pd->fd = prom_open(rawpart)) == 0)
+				return 0;
+		}
+		error = f->f_dev->dv_strategy(disk_pd, F_READ, LABELSECTOR,
+		    DEV_BSIZE, &buf, &read);
+		if (prom_version() != PROM_OLDMON)
+			prom_close(disk_pd->fd);
+		if (error || (read != DEV_BSIZE))
+			return 0;
+#ifdef NOTDEF_DEBUG
+		{
+			int x = 0;
+			char *p = (char *) buf;
+
+			printf("  Sector %d:\n", LABELSECTOR);
+			printf("00000000  ");
+			while (x < DEV_BSIZE) {
+				if (*p >= 0x00 && *p < 0x10)
+					printf("0%x ", *p & 0xff);
+				else
+					printf("%x ", *p & 0xff);
+				x++;
+				if (x && !(x % 8))
+					printf(" ");
+				if (x && !(x % 16)) {
+					if(x < 0x100)
+						printf("\n000000%x  ", x);
+					else
+						printf("\n00000%x  ", x);
+				}
+				p++;
+			}
+			printf("\n");
+		}
+#endif
+		/* Check for NetBSD disk label. */
+		dlp = (struct disklabel *) (buf + LABELOFFSET);
+		if (dlp->d_magic == DISKMAGIC && !dkcksum(dlp) &&
+		    dlp->d_partitions[part].p_fstype == FS_RAID) {
+#ifdef NOTDEF_DEBUG
+			printf("devopen: found RAID partition, "
+			    "adjusting offset to %d\n", RF_PROTECTED_SECTORS);
+#endif
+			doffset = RF_PROTECTED_SECTORS;
+		}
+	}
 #endif /* BOOTXX */
 	return (0);
 }
@@ -208,6 +297,9 @@
 	struct	promdata *pd = (struct promdata *)devdata;
 	int	fd = pd->fd;
 
+#ifndef BOOTXX
+	dblk += doffset;
+#endif
 #ifdef DEBUG_PROM
 	printf("promstrategy: size=%d dblk=%d\n", size, dblk);
 #endif
@@ -249,6 +341,9 @@
 	struct	promdata *pd = (struct promdata *)devdata;
 	int	fd = pd->fd;
 
+#ifndef BOOTXX
+	dblk += doffset;
+#endif
 #ifdef DEBUG_PROM
 	printf("promstrategy: size=%d dblk=%d\n", size, dblk);
 #endif
@@ -290,6 +385,9 @@
 	si = pd->si;
 	ops = si->si_boottab;
 
+#ifndef BOOTXX
+	dblk += doffset;
+#endif
 #ifdef DEBUG_PROM
 	printf("prom_strategy: size=%d dblk=%d\n", size, dblk);
 #endif
Only in common: promdev.c.dist

--f2QGlHpHGjS2mn6Y--