Fix booting from an IDE block device on the Sun Blade 100. Apparently
authorkettenis <kettenis@openbsd.org>
Wed, 1 Dec 2021 17:25:35 +0000 (17:25 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 1 Dec 2021 17:25:35 +0000 (17:25 +0000)
writing to disk using the Open Firmware interfaces is buggy and causes
corruption of the disk.  While it isn't entirely clear what versions
of Open Firmware are affected, but it seems to only affect IDE drives.
So if we detect an IDE drive, disable writing to it.  This results in
a small lose of bootloader functionality (bsd.upgrade loop prevention
and flagging /etc/random.seed re-use) but that is better than losing
the ability to run OpenBSD at all.

Based on a diff by Ted Bullock (who did all the hard work of debugging
this and coming up with a viable fix).

ok deraadt@

sys/arch/sparc64/stand/ofwboot/ofdev.c
sys/arch/sparc64/stand/ofwboot/vers.c
sys/lib/libsa/fchmod.c
sys/lib/libsa/stand.h

index c23b412..2a4a37e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ofdev.c,v 1.31 2020/12/09 18:10:19 krw Exp $  */
+/*     $OpenBSD: ofdev.c,v 1.32 2021/12/01 17:25:35 kettenis Exp $     */
 /*     $NetBSD: ofdev.c,v 1.1 2000/08/20 14:58:41 mrg Exp $    */
 
 /*
@@ -520,7 +520,7 @@ devopen(struct open_file *of, const char *name, char **file)
        char fname[256];
        char buf[DEV_BSIZE];
        struct disklabel label;
-       int handle, part;
+       int dhandle, ihandle, part, parent;
        int error = 0;
 #ifdef SOFTRAID
        char volno;
@@ -647,23 +647,24 @@ devopen(struct open_file *of, const char *name, char **file)
                return 0;
        }
 #endif
-       if ((handle = OF_finddevice(fname)) == -1)
+       if ((dhandle = OF_finddevice(fname)) == -1)
                return ENOENT;
+
        DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname);
-       if (OF_getprop(handle, "name", buf, sizeof buf) < 0)
+       if (OF_getprop(dhandle, "name", buf, sizeof buf) < 0)
                return ENXIO;
        DNPRINTF(BOOT_D_OFDEV, "devopen: %s is called %s\n", fname, buf);
-       if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0)
+       if (OF_getprop(dhandle, "device_type", buf, sizeof buf) < 0)
                return ENXIO;
        DNPRINTF(BOOT_D_OFDEV, "devopen: %s is a %s device\n", fname, buf);
        DNPRINTF(BOOT_D_OFDEV, "devopen: opening %s\n", fname);
-       if ((handle = OF_open(fname)) == -1) {
+       if ((ihandle = OF_open(fname)) == -1) {
                DNPRINTF(BOOT_D_OFDEV, "devopen: open of %s failed\n", fname);
                return ENXIO;
        }
        DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname);
        bzero(&ofdev, sizeof ofdev);
-       ofdev.handle = handle;
+       ofdev.handle = ihandle;
        ofdev.type = OFDEV_DISK;
        ofdev.bsize = DEV_BSIZE;
        if (!strcmp(buf, "block")) {
@@ -685,6 +686,16 @@ devopen(struct open_file *of, const char *name, char **file)
 
                of->f_dev = devsw;
                of->f_devdata = &ofdev;
+
+               /* Some PROMS have buggy writing code for IDE block devices */
+               parent = OF_parent(dhandle);
+               if (parent && OF_getprop(parent, "device_type", buf,
+                   sizeof(buf)) > 0 && strcmp(buf, "ide") == 0) {
+                       DNPRINTF(BOOT_D_OFDEV, 
+                           "devopen: Disable writing for IDE block device\n");
+                       of->f_flags |= F_NOWRITE;
+               }
+
 #ifdef SPARC_BOOT_UFS
                bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
                bcopy(&file_system_ufs2, &file_system[nfsys++], sizeof file_system[0]);
@@ -712,7 +723,7 @@ devopen(struct open_file *of, const char *name, char **file)
 bad:
        DNPRINTF(BOOT_D_OFDEV, "devopen: error %d, cannot open device\n",
            error);
-       OF_close(handle);
+       OF_close(ihandle);
        ofdev.handle = -1;
        return error;
 }
index 3ca4ec8..78466ba 100644 (file)
@@ -1 +1 @@
-const char version[] = "1.21";
+const char version[] = "1.22";
index 7d9bc9c..f6252ca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fchmod.c,v 1.1 2019/08/03 15:22:17 deraadt Exp $      */
+/*     $OpenBSD: fchmod.c,v 1.2 2021/12/01 17:25:35 kettenis Exp $     */
 /*     $NetBSD: stat.c,v 1.3 1994/10/26 05:45:07 cgd Exp $     */
 
 /*-
@@ -53,6 +53,11 @@ fchmod(int fd, mode_t m)
                errno = EOPNOTSUPP;
                return (-1);
        }
+       /* writing is broken or unsupported */
+       if (f->f_flags & F_NOWRITE) {
+               errno = EOPNOTSUPP;
+               return (-1);
+       }
 
        errno = (f->f_ops->fchmod)(f, m);
        return (0);
index 9720fe6..cad63ea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: stand.h,v 1.71 2021/10/24 17:49:19 deraadt Exp $      */
+/*     $OpenBSD: stand.h,v 1.72 2021/12/01 17:25:35 kettenis Exp $     */
 /*     $NetBSD: stand.h,v 1.18 1996/11/30 04:35:51 gwr Exp $   */
 
 /*-
@@ -107,10 +107,11 @@ struct open_file {
 extern struct open_file files[];
 
 /* f_flags values */
-#define        F_READ          0x0001  /* file opened for reading */
-#define        F_WRITE         0x0002  /* file opened for writing */
-#define        F_RAW           0x0004  /* raw device open - no file system */
-#define F_NODEV                0x0008  /* network open - no device */
+#define F_READ          0x0001 /* file opened for reading */
+#define F_WRITE         0x0002 /* file opened for writing */
+#define F_RAW           0x0004 /* raw device open - no file system */
+#define F_NODEV         0x0008 /* network open - no device */
+#define F_NOWRITE       0x0010 /* bootblock writing broken or unsupported */
 
 #define isupper(c)     ((c) >= 'A' && (c) <= 'Z')
 #define islower(c)     ((c) >= 'a' && (c) <= 'z')