diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-04-16 17:27:59 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-04-16 17:27:59 +0000 |
commit | 9ece674622a863eb59f1b51f503bf9e5cea2b24f (patch) | |
tree | 2e5250c7636171b7f35294748fc1254bae8d81f8 /sys/arch | |
parent | 1ed58a61cce6c5fa16d00401df96d8e2d76bb3ca (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.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/zaurus/stand/zboot/devopen.c | 90 |
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; |