Module Name:    src
Committed By:   jdc
Date:           Mon Jan 13 14:37:30 UTC 2025

Modified Files:
        src/sys/arch/sparc/stand/common: promdev.c

Log Message:
Move the check for RAID boot into the strategy routines.
This avoids a Data Access Exception at boot time on older PROM versions.


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/sparc/stand/common/promdev.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/sparc/stand/common/promdev.c
diff -u src/sys/arch/sparc/stand/common/promdev.c:1.29 src/sys/arch/sparc/stand/common/promdev.c:1.30
--- src/sys/arch/sparc/stand/common/promdev.c:1.29	Sun Feb  3 11:58:38 2019
+++ src/sys/arch/sparc/stand/common/promdev.c	Mon Jan 13 14:37:30 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: promdev.c,v 1.29 2019/02/03 11:58:38 mrg Exp $ */
+/*	$NetBSD: promdev.c,v 1.30 2025/01/13 14:37:30 jdc Exp $ */
 
 /*
  * Copyright (c) 1993 Paul Kranenburg
@@ -78,6 +78,11 @@ static char	*oldmon_mapin(u_long, int, i
 #ifndef BOOTXX
 static char	*mygetpropstring(int, char *);
 static int	getdevtype(int, char *);
+void	israidlabel(char* buf);
+
+static daddr_t doffset = 0;
+static int raidchecked = 0;
+
 #endif
 
 extern struct fs_ops file_system_nfs[];
@@ -103,8 +108,69 @@ char	prom_bootdevice[MAX_PROM_PATH];
 static int	saveecho;
 
 #ifndef BOOTXX
-static daddr_t doffset = 0;
+void
+israidlabel(char *buf)
+{
+	char *partition;
+	int part = 0;
+	struct disklabel *dlp;
+
+	/* Check the 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
+	 * because we only know the boot device but not the partition.
+	 */
+	if (prom_version() != PROM_OLDMON) {
+		if ((partition = strchr(prom_bootdevice, ':')) != NULL &&
+		    *++partition >= 'a' &&
+		    *partition <= 'a' +  MAXPARTITIONS)
+			part = *partition - 'a';
+	}
+
+#ifdef DEBUG_PROM
+	printf("israidlabel: Checking disklabel for RAID partition (%c)\n",
+	    'a' + part);
+#endif
+
+#ifdef NOTDEF_DEBUG
+	{
+		int x = 0;
+		char *p = (char *) buf;
+
+		printf("Disklabel 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 DEBUG_PROM
+		printf("israidlabel: found RAID partition, "
+		    "adjusting offset to %ld\n", RF_PROTECTED_SECTORS);
+#endif
+		doffset = RF_PROTECTED_SECTORS;
+	}
+}
+#endif	/* BOOTXX */
 
 void
 putchar(int c)
@@ -127,21 +193,15 @@ devopen(struct open_file *f, const char 
 {
 	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;
 
 	switch (prom_version()) {
 	case PROM_OLDMON:
+#ifdef DEBUG_PROM
+		printf("devopen: PROM_OLDMON\n");
+#endif
 		error = oldmon_iopen(pd);
 #ifndef BOOTXX
 		pd->xmit = oldmon_xmit;
@@ -168,6 +228,9 @@ devopen(struct open_file *f, const char 
 		pd->fd = fd;
 		switch (prom_version()) {
 		case PROM_OBP_V0:
+#ifdef DEBUG_PROM
+			printf("devopen: PROM_OBP_V0\n");
+#endif
 #ifndef BOOTXX
 			pd->xmit = obp_v0_xmit;
 			pd->recv = obp_v0_recv;
@@ -177,6 +240,9 @@ devopen(struct open_file *f, const char 
 		case PROM_OBP_V2:
 		case PROM_OBP_V3:
 		case PROM_OPENFIRM:
+#ifdef DEBUG_PROM
+			printf("devopen: PROM_OBP_V2+\n");
+#endif
 #ifndef BOOTXX
 			pd->xmit = obp_v2_xmit;
 			pd->recv = obp_v2_recv;
@@ -207,86 +273,13 @@ devopen(struct open_file *f, const char 
 				prom_bootdevice);
 			return (error);
 		}
-	} else {
+	} else
 		memcpy(file_system, file_system_ufs,
 		    sizeof(struct fs_ops) * nfsys);
 
-#ifdef NOTDEF_DEBUG
-	printf("devopen: Checking disklabel for RAID partition\n");
-#endif
-
-		/*
-		 * Don't check disklabel on floppy boot since
-		 * reopening it could cause Data Access Exception later.
-		 */
-		if (bootdev_isfloppy(prom_bootdevice))
-			return 0;
-
-		/*
-		 * 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, ':')) != NULL &&
-		    	    *++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;
-		}
-	}
+	/* Don't check disklabel for RAID on floppy boot */
+	if (bootdev_isfloppy(prom_bootdevice))
+		raidchecked = 1;
 #endif /* BOOTXX */
 	return (0);
 }
@@ -299,11 +292,12 @@ obp_v0_strategy(void *devdata, int flag,
 	int	n, error = 0;
 	struct	promdata *pd = (struct promdata *)devdata;
 	int	fd = pd->fd;
-
 #ifndef BOOTXX
-	dblk += doffset;
+	char	labelbuf[DEV_BSIZE];
 #endif
+
 #ifdef DEBUG_PROM
+if (dblk < 3000)
 	printf("promstrategy: size=%zd dblk=%d\n", size, (int)dblk);
 #endif
 
@@ -317,6 +311,13 @@ obp_v0_strategy(void *devdata, int flag,
 		printf("promstrategy: non-block device not supported\n");
 		error = EINVAL;
 	}
+
+	if (!raidchecked && flag == F_READ) {
+		prom_bread(fd, btodb(DEV_BSIZE), LABELSECTOR, &labelbuf[0]);
+		israidlabel(&labelbuf[0]);
+		raidchecked = 1;
+	}
+	dblk += doffset;
 #endif
 
 	n = (flag == F_READ)
@@ -326,6 +327,7 @@ obp_v0_strategy(void *devdata, int flag,
 	*rsize = dbtob(n);
 
 #ifdef DEBUG_PROM
+if (dblk < 3000)
 	printf("rsize = %zx\n", *rsize);
 #endif
 	return (error);
@@ -338,15 +340,25 @@ obp_v2_strategy(void *devdata, int flag,
 	int	error = 0;
 	struct	promdata *pd = (struct promdata *)devdata;
 	int	fd = pd->fd;
-
 #ifndef BOOTXX
-	dblk += doffset;
+	char	labelbuf[DEV_BSIZE];
 #endif
+
 #ifdef DEBUG_PROM
+if (dblk < 3000)
 	printf("promstrategy: size=%zd dblk=%d\n", size, (int)dblk);
 #endif
 
-#ifndef BOOTXX	/* We know it's a block device, so save some space */
+#ifndef BOOTXX
+	if (!raidchecked && flag == F_READ) {
+		prom_seek(fd, dbtob(LABELSECTOR));
+		prom_read(fd, &labelbuf[0], DEV_BSIZE);
+		israidlabel(&labelbuf[0]);
+		raidchecked = 1;
+	}
+	dblk += doffset;
+
+	/* We know it's a block device, so save some space */
 	if (pd->devtype == DT_BLOCK)
 #endif
 		prom_seek(fd, dbtob(dblk));
@@ -356,6 +368,7 @@ obp_v2_strategy(void *devdata, int flag,
 		: prom_write(fd, buf, size);
 
 #ifdef DEBUG_PROM
+if (dblk < 3000)
 	printf("rsize = %zx\n", *rsize);
 #endif
 	return (error);
@@ -374,6 +387,9 @@ oldmon_strategy(void *devdata, int flag,
 	char	*dmabuf;
 	int	si_flag;
 	size_t	xcnt;
+#ifndef BOOTXX
+	char	labelbuf[DEV_BSIZE];
+#endif
 
 	si = pd->si;
 	ops = si->si_boottab;
@@ -382,11 +398,26 @@ oldmon_strategy(void *devdata, int flag,
 	dblk += doffset;
 #endif
 #ifdef DEBUG_PROM
+if (dblk < 3000)
 	printf("prom_strategy: size=%zd dblk=%d\n", size, (int)dblk);
 #endif
+	
+#ifndef BOOTXX
+	if (!raidchecked && flag == F_READ) {
+		dmabuf = dvma_mapin(&labelbuf[0], DEV_BSIZE);
+		si->si_bn = LABELSECTOR;
+		si->si_cc = DEV_BSIZE;
+		si_flag = SAIO_F_READ;
+		xcnt = (*ops->b_strategy)(si, si_flag);
+		dvma_mapout(dmabuf, DEV_BSIZE);
+		israidlabel(&labelbuf[0]);
+		raidchecked = 1;
+	}
+	dblk += doffset;
+#endif
 
 	dmabuf = dvma_mapin(buf, size);
-	
+
 	si->si_bn = dblk;
 	si->si_ma = dmabuf;
 	si->si_cc = size;
@@ -396,6 +427,7 @@ oldmon_strategy(void *devdata, int flag,
 	dvma_mapout(dmabuf, size);
 
 #ifdef DEBUG_PROM
+if (dblk < 3000)
 	printf("disk_strategy: xcnt = %zx\n", xcnt);
 #endif
 

Reply via email to