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