summaryrefslogtreecommitdiff
path: root/sys/arch/sgi/stand
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2016-10-05 11:55:46 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2016-10-05 11:55:46 +0000
commita5ceb9a2d94c5b29af31cafdc7a0dbda7ad4f47f (patch)
treeb8099f9b32afb70e5bf6224770340dffcf2ac283 /sys/arch/sgi/stand
parent7c15ec6997944fc7b8b6c3564e8ff037f19fc486 (diff)
Make the sgi boot blocks read the real OpenBSD disklabel instead of
assuming that the 'a' partition starts at the same location as the volume header partition #0. Diff from Miod Vallat
Diffstat (limited to 'sys/arch/sgi/stand')
-rw-r--r--sys/arch/sgi/stand/Makefile32.inc3
-rw-r--r--sys/arch/sgi/stand/boot/Makefile8
-rw-r--r--sys/arch/sgi/stand/boot/diskio.c174
-rw-r--r--sys/arch/sgi/stand/boot/version8
4 files changed, 165 insertions, 28 deletions
diff --git a/sys/arch/sgi/stand/Makefile32.inc b/sys/arch/sgi/stand/Makefile32.inc
index 1ab3306ff10..4b5e1977735 100644
--- a/sys/arch/sgi/stand/Makefile32.inc
+++ b/sys/arch/sgi/stand/Makefile32.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile32.inc,v 1.5 2012/10/19 13:51:59 miod Exp $
+# $OpenBSD: Makefile32.inc,v 1.6 2016/10/05 11:55:45 visa Exp $
.ifndef __INCLUDED_STAND_MAKEFILE32_INC
__INCLUDED_STAND_MAKEFILE32_INC=
@@ -18,6 +18,7 @@ AS+= -32
LD?= ld
LD+= -m elf32btsmip
LIBSA_CPPFLAGS=
+CFLAGS+= -DLIBSA_LONGLONG_PRINTF
.endif
### Figure out what to use for libsa and libz
diff --git a/sys/arch/sgi/stand/boot/Makefile b/sys/arch/sgi/stand/boot/Makefile
index f307404393f..a0f6fc970da 100644
--- a/sys/arch/sgi/stand/boot/Makefile
+++ b/sys/arch/sgi/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.16 2016/07/30 03:25:49 guenther Exp $
+# $OpenBSD: Makefile,v 1.17 2016/10/05 11:55:45 visa Exp $
NOMAN= noman
@@ -13,14 +13,14 @@ AFLAGS+= ${SAABI}
S= ${.CURDIR}/../../../..
SRCS= start.S arcbios.c boot.c conf.c diskio.c filesystem.c \
- netfs.c netio.c strchr.c strstr.c
+ netfs.c netio.c strstr.c
.PATH: ${S}/lib/libsa
SRCS+= loadfile.c
.PATH: ${S}/lib/libkern/arch/mips64 ${S}/lib/libkern
-SRCS+= strlcpy.c memcpy.c strlen.c strrchr.c strlcat.c strncmp.c \
- strcmp.S
+SRCS+= memcpy.c strchr.c strcmp.S strlcat.c strlcpy.c strlen.c \
+ strncmp.c strrchr.c
CLEANFILES+= machine mips64
diff --git a/sys/arch/sgi/stand/boot/diskio.c b/sys/arch/sgi/stand/boot/diskio.c
index c21690bd4a1..e145ac0417e 100644
--- a/sys/arch/sgi/stand/boot/diskio.c
+++ b/sys/arch/sgi/stand/boot/diskio.c
@@ -1,6 +1,21 @@
-/* $OpenBSD: diskio.c,v 1.10 2015/09/30 22:45:57 krw Exp $ */
+/* $OpenBSD: diskio.c,v 1.11 2016/10/05 11:55:45 visa Exp $ */
/*
+ * Copyright (c) 2016 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
* Copyright (c) 2000 Opsycon AB (www.opsycon.se)
* Copyright (c) 2000 Rtmx, Inc (www.rtmx.com)
*
@@ -33,11 +48,15 @@
*
*/
-#include <stand.h>
#include <sys/param.h>
+#include <lib/libkern/libkern.h>
+#include <stand.h>
+
#include <sys/disklabel.h>
#include <mips64/arcbios.h>
+char *strstr(char *, const char *); /* strstr.c */
+
struct dio_softc {
int sc_fd; /* PROM file ID */
int sc_part; /* Disk partition number. */
@@ -50,18 +69,20 @@ diostrategy(void *devdata, int rw, daddr32_t bn, size_t reqcnt, void *addr,
{
struct dio_softc *sc = (struct dio_softc *)devdata;
struct partition *pp = &sc->sc_label.d_partitions[sc->sc_part];
+ uint64_t blkoffset;
arc_quad_t offset;
long result;
- offset.hi = 0;
- offset.lo = (pp->p_offset + bn) * DEV_BSIZE;
+ blkoffset = (DL_GETPOFFSET(pp) + bn) * DEV_BSIZE;
+ offset.hi = blkoffset >> 32;
+ offset.lo = blkoffset;
- if ((Bios_Seek(sc->sc_fd, &offset, 0) < 0) ||
- (Bios_Read(sc->sc_fd, addr, reqcnt, &result) < 0))
- return (EIO);
+ if (Bios_Seek(sc->sc_fd, &offset, 0) < 0 ||
+ Bios_Read(sc->sc_fd, addr, reqcnt, &result) < 0)
+ return EIO;
*cnt = result;
- return (0);
+ return 0;
}
int
@@ -69,11 +90,18 @@ dioopen(struct open_file *f, ...)
{
char *ctlr;
int partition;
-
struct dio_softc *sc;
struct disklabel *lp;
+ struct sgilabel *sl;
long fd;
+ /* XXX getdisklabel() assumes DEV_BSIZE bytes available */
+ char buf[DEV_BSIZE + LABELOFFSET];
+ arc_quad_t offset;
+ daddr_t native_offset;
+ long result;
va_list ap;
+ char rawctlr[1 + MAXPATHLEN];
+ char *partptr;
va_start(ap, f);
ctlr = va_arg(ap, char *);
@@ -81,26 +109,130 @@ dioopen(struct open_file *f, ...)
va_end(ap);
if (partition >= MAXPARTITIONS)
- return (ENXIO);
-
- if (Bios_Open(ctlr, 0, &fd) < 0)
- return (ENXIO);
+ return ENXIO;
+
+ /*
+ * If booting from disk, `ctlr` is something like
+ * whatever()partition(0)
+ * or
+ * dksc(whatever,0)
+ * where 0 is the volume header #0 partition, which is the
+ * OpenBSD area, where the OpenBSD disklabel can be found.
+ *
+ * However, the OpenBSD `a' partition, where the kernel is to be
+ * found, may not start at the same offset.
+ *
+ * In order to be able to correctly load any file from the OpenBSD
+ * partitions, we need to access the volume header partition table
+ * and the OpenBSD label.
+ *
+ * Therefore, make sure we replace `partition(*)' with `partition(10)'
+ * before reaching ARCBios, in order to access the raw disk.
+ *
+ * We could use partition #8 and use the value of SystemPartition in
+ * the environment to avoid doing this, but this would prevent us
+ * from being able to boot from a different disk than the one
+ * pointed to by SystemPartition.
+ */
+
+ strlcpy(rawctlr, ctlr, sizeof rawctlr);
+ partptr = strstr(rawctlr, "partition(");
+ if (partptr != NULL) {
+ strlcpy(partptr, "partition(10)",
+ sizeof rawctlr - (partptr - rawctlr));
+ } else {
+ if ((partptr = strstr(rawctlr, "dksc(")) != NULL) {
+ partptr = strstr(partptr, ",0)");
+ if (partptr != NULL && partptr[3] == '\0')
+ strlcpy(partptr, ",10)",
+ sizeof rawctlr - (partptr - rawctlr));
+ }
+ }
+
+ sl = NULL; /* no volume header found yet */
+ if (partptr != NULL) {
+ if (Bios_Open(rawctlr, 0, &fd) < 0)
+ return ENXIO;
+
+ /*
+ * Read the volume header.
+ */
+ offset.hi = offset.lo = 0;
+ if (Bios_Seek(fd, &offset, 0) < 0 ||
+ Bios_Read(fd, buf, DEV_BSIZE, &result) < 0 ||
+ result != DEV_BSIZE)
+ return EIO;
+
+ sl = (struct sgilabel *)buf;
+ if (sl->magic != SGILABEL_MAGIC) {
+#ifdef DEBUG
+ printf("Invalid volume header magic %x\n", sl->magic);
+#endif
+ Bios_Close(fd);
+ sl = NULL;
+ }
+ }
+
+ if (sl == NULL) {
+ if (Bios_Open(ctlr, 0, &fd) < 0)
+ return ENXIO;
+ }
sc = alloc(sizeof(struct dio_softc));
bzero(sc, sizeof(struct dio_softc));
f->f_devdata = (void *)sc;
+ lp = &sc->sc_label;
sc->sc_fd = fd;
sc->sc_part = partition;
- lp = &sc->sc_label;
- lp->d_secsize = DEV_BSIZE;
- lp->d_secpercyl = 1;
- lp->d_npartitions = MAXPARTITIONS;
- lp->d_partitions[partition].p_offset = 0;
- lp->d_partitions[0].p_size = 0x7fff0000;
-
- return (0);
+ if (sl != NULL) {
+ native_offset = sl->partitions[0].first;
+ } else {
+ /*
+ * We could not read the volume header, or there isn't any.
+ * Stick to the device we were given, and assume the
+ * OpenBSD disklabel can be found at the beginning.
+ */
+ native_offset = 0;
+ }
+
+ /*
+ * Read the native OpenBSD label.
+ */
+#ifdef DEBUG
+ printf("OpenBSD label @%lld\n", native_offset + LABELSECTOR);
+#endif
+ offset.hi = ((native_offset + LABELSECTOR) * DEV_BSIZE) >> 32;
+ offset.lo = (native_offset + LABELSECTOR) * DEV_BSIZE;
+
+ if (Bios_Seek(fd, &offset, 0) < 0 ||
+ Bios_Read(fd, buf, DEV_BSIZE, &result) < 0 ||
+ result != DEV_BSIZE)
+ return EIO;
+
+ if (getdisklabel(buf + LABELOFFSET, lp) == NULL) {
+#ifdef DEBUG
+ printf("Found native disklabel, "
+ "partition %c starts at %lld\n",
+ 'a' + partition,
+ DL_GETPOFFSET(&lp->d_partitions[partition]));
+#endif
+ } else {
+ /*
+ * Assume the OpenBSD partition spans the whole device.
+ */
+#ifdef DEBUG
+ printf("No native disklabel found\n");
+#endif
+ lp->d_secsize = DEV_BSIZE;
+ lp->d_secpercyl = 1;
+ lp->d_npartitions = MAXPARTITIONS;
+ DL_SETPOFFSET(&lp->d_partitions[partition], native_offset);
+ DL_SETPSIZE(&lp->d_partitions[partition], -1ULL);
+ }
+
+ return 0;
}
int
diff --git a/sys/arch/sgi/stand/boot/version b/sys/arch/sgi/stand/boot/version
index bd3ec87a6ad..9fbbb89627d 100644
--- a/sys/arch/sgi/stand/boot/version
+++ b/sys/arch/sgi/stand/boot/version
@@ -1,4 +1,4 @@
-/* $OpenBSD: version,v 1.8 2016/09/13 18:27:49 jasper Exp $ */
+/* $OpenBSD: version,v 1.9 2016/10/05 11:55:45 visa Exp $ */
/* Public domain. Come on, this can hardly be considered as code. */
#if 0
@@ -34,6 +34,10 @@ No version strings up to 2012
1.7
Loadfile support for .SUNW_ctf section
+1.8
+ Use the OpenBSD disklabel instead of assuming OpenBSD partition `a`
+ starts at the beginning of the volume header partition #0.
+
#endif
-static const char version[] = "1.7";
+static const char version[] = "1.8";