summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUwe Stuehler <uwe@cvs.openbsd.org>2005-04-16 17:27:59 +0000
committerUwe Stuehler <uwe@cvs.openbsd.org>2005-04-16 17:27:59 +0000
commit9ece674622a863eb59f1b51f503bf9e5cea2b24f (patch)
tree2e5250c7636171b7f35294748fc1254bae8d81f8
parent1ed58a61cce6c5fa16d00401df96d8e2d76bb3ca (diff)
Look for OpenBSD disklabel on the first eight hd devices, and after a
timeout retry to open the first device which wasn't immediately ready. This should avoid the failures to read /etc/boot.conf that people have been seeing, and makes it possible to install OpenBSD on any of the four possible DOS MBR primary partitions.
-rw-r--r--sys/arch/zaurus/stand/zboot/devopen.c90
1 files changed, 87 insertions, 3 deletions
diff --git a/sys/arch/zaurus/stand/zboot/devopen.c b/sys/arch/zaurus/stand/zboot/devopen.c
index 609b8ac58b2..4d348700183 100644
--- a/sys/arch/zaurus/stand/zboot/devopen.c
+++ b/sys/arch/zaurus/stand/zboot/devopen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: devopen.c,v 1.1 2005/01/10 00:25:03 deraadt Exp $ */
+/* $OpenBSD: devopen.c,v 1.2 2005/04/16 17:27:58 uwe Exp $ */
/*
* Copyright (c) 1996-1999 Michael Shalayeff
@@ -28,6 +28,7 @@
#include "libsa.h"
#include <sys/param.h>
+#include <sys/disklabel.h>
#include <dev/cons.h>
extern int debug;
@@ -46,6 +47,8 @@ const char cdevs[][4] = {
};
const int ncdevs = NENTS(cdevs);
+int getbootdev(dev_t, char *);
+
/* pass dev_t to the open routines */
int
devopen(struct open_file *f, const char *fname, char **file)
@@ -86,11 +89,92 @@ devopen(struct open_file *f, const char *fname, char **file)
return rc;
}
+int
+getbootdev(dev_t bootdev, char *p)
+{
+ char buf[DEV_BSIZE];
+ struct dos_partition *dp;
+ struct disklabel label;
+ static int timeout = 10;
+ char *s;
+ int fd;
+ int n;
+ char *msg = "";
+
+ s = p;
+ *p++ = '/';
+ *p++ = 'd';
+ *p++ = 'e';
+ *p++ = 'v';
+ *p++ = '/';
+ *p++ = 'h';
+ *p++ = 'd';
+ *p++ = 'a' + (bootdev & 0xf); /* a - h */
+ *p = '\0';
+
+ /*
+ * Give disk devices some time to become ready when the first open
+ * fails. Even when open succeeds the disk is sometimes not ready.
+ */
+ if ((fd = uopen(s, O_RDONLY)) == -1 && errno == ENXIO) {
+ int t;
+ while (fd == -1 && timeout > 0) {
+ timeout--;
+ t = getsecs() + 1;
+ while (getsecs() < t);
+ fd = uopen(s, O_RDONLY);
+ }
+ if (fd != -1) {
+ t = getsecs() + 2;
+ while (getsecs() < t);
+ }
+ }
+ if (fd == -1)
+ return 0;
+
+ /* Read the disk's MBR. */
+ if (unixstrategy((void *)fd, F_READ, DOSBBSECTOR, DEV_BSIZE, buf,
+ &n) != 0 || n != DEV_BSIZE) {
+ uclose(fd);
+ return 0;
+ }
+
+ /* Find OpenBSD primary partition in the disk's MBR. */
+ dp = (struct dos_partition *)&buf[DOSPARTOFF];
+ for (n = 0; n < NDOSPART; n++)
+ if (dp[n].dp_typ == DOSPTYP_OPENBSD)
+ break;
+ if (n == NDOSPART) {
+ uclose(fd);
+ return 0;
+ }
+ *p++ = '1' + n;
+ *p = '\0';
+ uclose(fd);
+
+ /* Test if the OpenBSD partition has a valid disklabel. */
+ if ((fd = uopen(s, O_RDONLY)) != -1) {
+ if (unixstrategy((void *)fd, F_READ, LABELSECTOR,
+ DEV_BSIZE, buf, &n) == 0 && n == DEV_BSIZE)
+ msg = getdisklabel(buf, &label);
+ uclose(fd);
+ }
+ return msg == NULL;
+}
+
void
devboot(dev_t bootdev, char *p)
{
- /* XXX */
- strlcpy(p, "/dev/hda4", 10);
+
+ if (bootdev != 0 && getbootdev(bootdev, p))
+ return;
+
+ for (bootdev = 0; bootdev < 8; bootdev++)
+ if (getbootdev(bootdev, p))
+ return;
+
+ /* fall-back to the previous default device */
+ strlcpy(p, "/dev/hda4", 16);
}
int pch_pos = 0;