summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sgi/stand/Makefile4
-rw-r--r--sys/arch/sgi/stand/Makefile.inc63
-rw-r--r--sys/arch/sgi/stand/boot/Makefile33
-rw-r--r--sys/arch/sgi/stand/boot/arcbios.c308
-rw-r--r--sys/arch/sgi/stand/boot/boot.c298
-rw-r--r--sys/arch/sgi/stand/boot/conf.c46
-rw-r--r--sys/arch/sgi/stand/boot/diskio.c134
-rw-r--r--sys/arch/sgi/stand/boot/filesystem.c44
-rw-r--r--sys/arch/sgi/stand/boot/start.S53
-rw-r--r--sys/arch/sgi/stand/libkern/Makefile40
-rw-r--r--sys/arch/sgi/stand/libsa/Makefile41
-rw-r--r--sys/arch/sgi/stand/libz/Makefile9
-rw-r--r--sys/arch/sgi/stand/sgivol/Makefile9
-rw-r--r--sys/arch/sgi/stand/sgivol/sgivol.c615
14 files changed, 1695 insertions, 2 deletions
diff --git a/sys/arch/sgi/stand/Makefile b/sys/arch/sgi/stand/Makefile
index 57afcf050d4..d93e9f212da 100644
--- a/sys/arch/sgi/stand/Makefile
+++ b/sys/arch/sgi/stand/Makefile
@@ -1,5 +1,5 @@
-# $OpenBSD: Makefile,v 1.1 2004/08/06 21:32:56 deraadt Exp $
+# $OpenBSD: Makefile,v 1.2 2004/08/23 14:22:40 pefo Exp $
-SUBDIR=
+SUBDIR= libsa libkern libz boot sgivol
.include <bsd.subdir.mk>
diff --git a/sys/arch/sgi/stand/Makefile.inc b/sys/arch/sgi/stand/Makefile.inc
new file mode 100644
index 00000000000..d86ab997210
--- /dev/null
+++ b/sys/arch/sgi/stand/Makefile.inc
@@ -0,0 +1,63 @@
+# $OpenBSD: Makefile.inc,v 1.1 2004/08/23 14:22:40 pefo Exp $
+# $NetBSD: Makefile.inc,v 1.7 2000/08/20 14:57:16 mrg Exp $
+
+.ifndef __INCLUDED_STAND_MAKEFILE_INC
+__INCLUDED_STAND_MAKEFILE_INC=
+
+#CEXTRAFLAGS?=-D_LP64
+
+BINDIR= /usr/mdec
+
+STANDALONE?= -D_STANDALONE
+
+.if ${MACHINE} == "sgi"
+CPPFLAGS+= ${STANDALONE}
+CPPFLAGS+= -I.
+CPPFLAGS+= -Derrno=errno
+
+CFLAGS+= -fno-stack-protector
+CFLAGS+= -fno-builtin-vprintf -fno-builtin-printf -fno-builtin-putchar
+.endif
+
+
+
+### Figure out what to use for libkern
+LIBKERNDIR= ${.CURDIR}/../libkern
+
+.if exists(${LIBKERNDIR}/obj.${MACHINE})
+LIBKERNOBJDIR= ${LIBKERNDIR}/obj.${MACHINE}
+.elif exists(${LIBKERNDIR}/obj)
+LIBKERNOBJDIR= ${LIBKERNDIR}/obj
+.else
+LIBKERNOBJDIR= ${LIBKERNDIR}
+.endif
+
+LIBKERN= ${LIBKERNOBJDIR}/libkern.a
+
+### Figure out what to use for libsa
+LIBSADIR= ${.CURDIR}/../libsa
+
+.if exists(${LIBSADIR}/obj.${MACHINE})
+LIBSAOBJDIR= ${LIBSADIR}/obj.${MACHINE}
+.elif exists(${LIBSADIR}/obj)
+LIBSAOBJDIR= ${LIBSADIR}/obj
+.else
+LIBSAOBJDIR= ${LIBSADIR}
+.endif
+
+LIBSA= ${LIBSAOBJDIR}/libsa.a
+
+### Figure out what to use for libz
+LIBZDIR= ${.CURDIR}/../libz
+
+.if exists(${LIBZDIR}/obj.${MACHINE})
+LIBZOBJDIR= ${LIBZDIR}/obj.${MACHINE}
+.elif exists(${LIBZDIR}/obj)
+LIBZOBJDIR= ${LIBZDIR}/obj
+.else
+LIBZOBJDIR= ${LIBZDIR}
+.endif
+
+LIBZ= ${LIBZOBJDIR}/libz.a
+
+.endif
diff --git a/sys/arch/sgi/stand/boot/Makefile b/sys/arch/sgi/stand/boot/Makefile
new file mode 100644
index 00000000000..f0a9a98c5c9
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/Makefile
@@ -0,0 +1,33 @@
+# $OpenBSD: Makefile,v 1.1 2004/08/23 14:22:40 pefo Exp $
+
+
+PROG= boot
+NOMAN= noman
+
+CFLAGS+= -O2 -mno-abicalls -D_NO_ABICALLS -nostdinc -D__sgi__ \
+ -I${.CURDIR}/../include -I${.CURDIR}/../../../.. \
+ -I${.CURDIR}/../../../../lib/libsa \
+ -I${.OBJDIR}
+CFLAGS+= -D__INTERNAL_LIBSA_CREAD ${STANDALONE}
+
+LDFLAGS+= ${SALDFLAGS} -T ${.CURDIR}/../../conf/ld.script -Ttext 80002000 -e __start
+
+SRCS= start.S boot.c filesystem.c conf.c diskio.c arcbios.c
+
+CLEANFILES+= machine mips64
+
+.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(kernlibdir) && !make(obj)
+.BEGIN:
+ @([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
+ @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64)
+.endif
+
+${PROG}: $(OBJS) $(LDADD)
+ $(LD) $(LDFLAGS) -o boot $(OBJS) -L${LIBSADIR} ${LIBSA} \
+ -L${LIBKERNDIR} ${LIBKERN} -L${LIBZDIR} ${LIBZ}
+
+
+install:
+ install -c -m 555 -g bin -o bin ${PROG} ${DESTDIR}/usr/mdec
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/sgi/stand/boot/arcbios.c b/sys/arch/sgi/stand/boot/arcbios.c
new file mode 100644
index 00000000000..d99592a6bc5
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/arcbios.c
@@ -0,0 +1,308 @@
+/* $OpenBSD: arcbios.c,v 1.1 2004/08/23 14:22:40 pefo Exp $ */
+/*-
+ * Copyright (c) 1996 M. Warner Losh. All rights reserved.
+ * Copyright (c) 1996-2004 Opsycon AB. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <lib/libkern/libkern.h>
+#include <machine/autoconf.h>
+#include <mips64/arcbios.h>
+#include <mips64/archtype.h>
+#include <stand.h>
+
+#define USE_SGI_PARTITIONS 1
+
+arc_param_blk_t *bios_base = ArcBiosBase;
+
+void bios_configure_memory(void);
+int bios_get_system_type(void);
+const char *bios_get_path_component(const char *, char *, int *);
+
+arc_dsp_stat_t displayinfo; /* Save area for display status info. */
+
+static struct systypes {
+ char *sys_vend; /* Vendor ID if name is ambigous */
+ char *sys_name; /* May be left NULL if name is sufficient */
+ int sys_type;
+} sys_types[] = {
+ { NULL, "PICA-61", ACER_PICA_61 },
+ { NULL, "NEC-R94", ACER_PICA_61 },
+ { NULL, "DESKTECH-TYNE", DESKSTATION_TYNE },
+ { NULL, "DESKTECH-ARCStation I", DESKSTATION_RPC44 },
+ { NULL, "Microsoft-Jazz", MAGNUM },
+ { NULL, "RM200PCI", SNI_RM200 },
+ { NULL, "SGI-IP17", SGI_CRIMSON },
+ { NULL, "SGI-IP19", SGI_ONYX },
+ { NULL, "SGI-IP20", SGI_INDIGO },
+ { NULL, "SGI-IP21", SGI_POWER },
+ { NULL, "SGI-IP22", SGI_INDY },
+ { NULL, "SGI-IP25", SGI_POWER10 },
+ { NULL, "SGI-IP26", SGI_POWERI },
+ { NULL, "SGI-IP32", SGI_O2 },
+};
+
+#define KNOWNSYSTEMS (sizeof(sys_types) / sizeof(struct systypes))
+
+/*
+ * ARC Bios trampoline code.
+ */
+#define ARC_Call(Name,Offset) \
+__asm__("\n" \
+" .text\n" \
+" .ent " #Name "\n" \
+" .align 3\n" \
+" .set noreorder\n" \
+" .globl " #Name "\n" \
+#Name":\n" \
+" lw $2, 0xffffffff80001020\n"\
+" lw $2," #Offset "($2)\n"\
+" jr $2\n" \
+" nop\n" \
+" .end " #Name "\n" );
+
+ARC_Call(Bios_Load, 0x00);
+ARC_Call(Bios_Invoke, 0x04);
+ARC_Call(Bios_Execute, 0x08);
+ARC_Call(Bios_Halt, 0x0c);
+ARC_Call(Bios_PowerDown, 0x10);
+ARC_Call(Bios_Restart, 0x14);
+ARC_Call(Bios_Reboot, 0x18);
+ARC_Call(Bios_EnterInteractiveMode, 0x1c);
+ARC_Call(Bios_Unused1, 0x20);
+ARC_Call(Bios_GetPeer, 0x24);
+ARC_Call(Bios_GetChild, 0x28);
+ARC_Call(Bios_GetParent, 0x2c);
+ARC_Call(Bios_GetConfigurationData, 0x30);
+ARC_Call(Bios_AddChild, 0x34);
+ARC_Call(Bios_DeleteComponent, 0x38);
+ARC_Call(Bios_GetComponent, 0x3c);
+ARC_Call(Bios_SaveConfiguration, 0x40);
+ARC_Call(Bios_GetSystemId, 0x44);
+ARC_Call(Bios_GetMemoryDescriptor, 0x48);
+ARC_Call(Bios_Unused2, 0x4c);
+ARC_Call(Bios_GetTime, 0x50);
+ARC_Call(Bios_GetRelativeTime, 0x54);
+ARC_Call(Bios_GetDirectoryEntry, 0x58);
+ARC_Call(Bios_Open, 0x5c);
+ARC_Call(Bios_Close, 0x60);
+ARC_Call(Bios_Read, 0x64);
+ARC_Call(Bios_GetReadStatus, 0x68);
+ARC_Call(Bios_Write, 0x6c);
+ARC_Call(Bios_Seek, 0x70);
+ARC_Call(Bios_Mount, 0x74);
+ARC_Call(Bios_GetEnvironmentVariable, 0x78);
+ARC_Call(Bios_SetEnvironmentVariable, 0x7c);
+ARC_Call(Bios_GetFileInformation, 0x80);
+ARC_Call(Bios_SetFileInformation, 0x84);
+ARC_Call(Bios_FlushAllCaches, 0x88);
+ARC_Call(Bios_TestUnicodeCharacter, 0x8c);
+ARC_Call(Bios_GetDisplayStatus, 0x90);
+
+/*
+ * Simple getchar/putchar interface.
+ */
+
+int
+getchar()
+{
+ char buf[4];
+ int cnt;
+
+ if (Bios_Read(0, &buf[0], 1, &cnt) != 0)
+ return(-1);
+ return(buf[0] & 255);
+}
+
+void
+putchar(c)
+char c;
+{
+ char buf[4];
+ int cnt;
+
+ if (c == '\n') {
+ buf[0] = '\r';
+ buf[1] = c;
+ cnt = 2;
+ if (displayinfo.CursorYPosition < displayinfo.CursorMaxYPosition)
+ displayinfo.CursorYPosition++;
+ }
+ else {
+ buf[0] = c;
+ cnt = 1;
+ }
+ Bios_Write(1, &buf[0], cnt, &cnt);
+}
+
+void
+bios_putstring(s)
+char *s;
+{
+ while (*s) {
+ putchar(*s++);
+ }
+}
+
+/*
+ * Find out system type.
+ */
+int
+bios_get_system_type()
+{
+ arc_config_t *cf;
+ arc_sid_t *sid;
+ int i;
+
+ if ((bios_base->magic != ARC_PARAM_BLK_MAGIC) &&
+ (bios_base->magic != ARC_PARAM_BLK_MAGIC_BUG)) {
+ return(-1); /* This is not an ARC system */
+ }
+
+ sid = (arc_sid_t *)Bios_GetSystemId();
+ cf = (arc_config_t *)Bios_GetChild(NULL);
+ if (cf) {
+ for (i = 0; i < KNOWNSYSTEMS; i++) {
+ if (strcmp(sys_types[i].sys_name, cf->id) != 0)
+ continue;
+ if (sys_types[i].sys_vend &&
+ strncmp(sys_types[i].sys_vend, sid->vendor, 8) != 0)
+ continue;
+ return (sys_types[i].sys_type); /* Found it. */
+ }
+ }
+
+ bios_putstring("UNIDENTIFIED SYSTEM `");
+ if (cf)
+ bios_putstring(cf->id);
+ else
+ bios_putstring("????????");
+ bios_putstring("' VENDOR `");
+ sid->vendor[8] = 0;
+ bios_putstring(sid->vendor);
+ bios_putstring("'. Please contact OpenBSD (www.openbsd.org).\n");
+ bios_putstring("Reset system to restart!\n");
+ while(1);
+}
+
+/*
+ * Return geometry of the display. Used by pccons.c to set up the
+ * display configuration.
+ */
+void
+bios_display_info(xpos, ypos, xsize, ysize)
+ int *xpos;
+ int *ypos;
+ int *xsize;
+ int *ysize;
+{
+#ifdef __arc__
+ *xpos = displayinfo.CursorXPosition;
+ *ypos = displayinfo.CursorYPosition;
+ *xsize = displayinfo.CursorMaxXPosition;
+ *ysize = displayinfo.CursorMaxYPosition;
+#endif
+}
+
+
+/*
+ * Decompose the device pathname and find driver.
+ * Returns pointer to remaining filename path in file.
+ */
+int
+devopen(struct open_file *f, const char *fname, char **file)
+{
+ const char *cp, *ncp, *ecp;
+ struct devsw *dp;
+ int partition = 0;
+ char namebuf[256];
+ char devname[32];
+ int rc, i, n;
+
+ ecp = cp = fname;
+
+ /*
+ * Scan the component list and find device and partition.
+ */
+ while (ncp = bios_get_path_component(cp, namebuf, &i)) {
+ if ((strcmp(namebuf, "partition") == 0) ||
+ (strcmp(namebuf, "partition") == 0)) {
+ partition = i;
+ if (USE_SGI_PARTITIONS)
+ ecp = ncp;
+ } else
+ ecp = ncp;
+
+ /* XXX do this with a table if more devs are added */
+ if (strcmp(namebuf, "scsi") == 0)
+ strncpy(devname, namebuf, sizeof(devname));
+
+ cp = ncp;
+ }
+
+ memcpy(namebuf, fname, ecp - fname);
+ namebuf[ecp - fname] = '\0';
+
+ /*
+ * Dig out the driver.
+ */
+printf("looking: %s, %s, %d\n", devname, namebuf, partition);
+ dp = devsw;
+ n = ndevs;
+ while(n--) {
+ if (strcmp (devname, dp->dv_name) == 0) {
+ rc = (dp->dv_open)(f, namebuf, partition, 0);
+ if (!rc) {
+ f->f_dev = dp;
+ if (file && *cp != '\0')
+ *file = (char *)cp;
+ }
+ return (rc);
+ }
+ dp++;
+ }
+ return ENXIO;
+}
+
+const char *
+bios_get_path_component(const char *p, char *comp, int *no)
+{
+ while (*p && *p != '(') {
+ *comp++ = *p++;
+ }
+ *comp = '\0';
+
+ if (*p == NULL)
+ return NULL;
+
+ *no = 0;
+ p++;
+ while (*p && *p != ')') {
+ if (*p >= '0' && *p <= '9')
+ *no = *no * 10 + *p++ - '0';
+ else
+ return NULL;
+ }
+ return ++p;
+}
diff --git a/sys/arch/sgi/stand/boot/boot.c b/sys/arch/sgi/stand/boot/boot.c
new file mode 100644
index 00000000000..b5db5c1ad6f
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/boot.c
@@ -0,0 +1,298 @@
+/* $OpenBSD: boot.c,v 1.1 2004/08/23 14:22:40 pefo Exp $ */
+
+/*
+ * Copyright (c) 2004 Opsycon AB, www.opsycon.se.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/exec.h>
+#include <sys/exec_elf.h>
+#include <stand.h>
+
+#include <mips64/arcbios.h>
+
+
+void gets(char *);
+ssize_t read(int, void *, size_t);
+int close(int);
+void pmon_write(int, char *, int);
+void pmon_synccache(void);
+
+int main(int, char **, char **);
+int loadfile(char *);
+int loadsymtab(int fd, Elf32_Ehdr *eh, int flags);
+
+unsigned long tablebase;
+
+static void *
+readtable (int fd, int offs, void *base, int size, char *name, int flags)
+{
+ if (olseek(fd, offs, SEEK_SET) != offs ||
+ oread(fd, base, size) != size) {
+ printf("\ncannot read %s table", name);
+ return 0;
+ }
+ return (void *) base;
+}
+
+static void *
+gettable (int size, char *name, int flags)
+{
+ long base;
+ /* Put table after loaded code to support kernel DDB */
+ tablebase = roundup(tablebase, sizeof(long));
+ base = tablebase;
+ tablebase += size;
+ return (void *) base;
+}
+
+/*
+ */
+int
+main(argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ char *cp;
+ int i, ask, entry;
+ char line[1024];
+
+ ask = 0;
+
+ cp = Bios_GetEnvironmentVariable("OSLoadPartition");
+ if (cp != NULL) {
+ strncpy(line, cp, sizeof(line));
+ i = strlen(line);
+ cp = Bios_GetEnvironmentVariable("OSLoadFilename");
+ if (cp != NULL)
+ strncpy(&line[i], cp, sizeof(line) - i -1);
+ else
+ ask = 1;
+ } else
+ ask = 1;
+
+ printf("\nOpenBSD/sgi Arcbios boot\n");
+
+ for (entry = 0; entry < argc; entry++)
+ printf("arg %d: %s\n", entry, argv[entry]);
+
+ while (1) {
+ do {
+ printf("Boot: ");
+ if (ask) {
+ gets(line);
+ }
+ else
+ printf("%s\n", line);
+ } while(ask && line[0] == '\0');
+
+ entry = loadfile(line);
+ if (entry != -1) {
+ ((void (*)())entry)(argc, argv);
+ }
+ ask = 1;
+ }
+ return(0);
+}
+
+/*
+ * Open 'filename', read in program and return the entry point or -1 if error.
+ */
+int
+loadfile(fname)
+ register char *fname;
+{
+ int fd, i;
+ Elf32_Ehdr eh;
+ Elf32_Phdr *ph;
+ char *errs = 0;
+ char buf[4096];
+
+ if ((fd = oopen(fname, 0)) < 0) {
+ errs="open err: %s\n";
+ goto err;
+ }
+
+ /* read the elf header */
+ if(oread(fd, (char *)&eh, sizeof(eh)) != sizeof(eh)) {
+ goto serr;
+ }
+
+ ph = (Elf32_Phdr *) buf;
+ olseek(fd, eh.e_phoff, 0);
+ if(oread(fd, (char *)ph, 4096) != 4096) {
+ goto serr;
+ }
+
+ tablebase = 0;
+
+ for(i = 0; i < eh.e_phnum; i++, ph++) {
+ if(ph->p_type == PT_LOAD) {
+ olseek(fd, ph->p_offset, 0);
+ printf("0x%x:0x%x, ",ph->p_paddr, ph->p_filesz);
+ if(oread(fd, (char *)ph->p_paddr, ph->p_filesz) != ph->p_filesz) {
+ goto serr;
+ }
+ if(ph->p_memsz > ph->p_filesz) {
+ printf("Zero 0x%x:0x%x, ",
+ ph->p_paddr + ph->p_filesz,
+ ph->p_memsz - ph->p_filesz);
+ bzero((void *)(ph->p_paddr + ph->p_filesz),
+ ph->p_memsz - ph->p_filesz);
+ }
+ if((ph->p_paddr + ph->p_memsz) > tablebase) {
+ tablebase = ph->p_paddr + ph->p_memsz;
+ }
+ }
+ }
+ printf("start at 0x%x\n", eh.e_entry);
+ memset(tablebase, 0, 4096);
+ loadsymtab(fd, &eh, 0);
+ return(eh.e_entry);
+serr:
+ errs = "%s sz err\n";
+err:
+ printf(errs, fname);
+ return (-1);
+}
+int
+loadsymtab(int fd, Elf32_Ehdr *eh, int flags)
+{
+ Elf32_Ehdr *keh;
+ Elf32_Shdr *shtab;
+ Elf32_Shdr *sh, *ksh, *shstrh, *strh;
+ Elf32_Sym *symtab;
+ int *symptr;
+ char *shstrtab, *strtab, *symend;
+ int i, nsym, offs, size;
+
+ size = eh->e_shnum * sizeof(Elf32_Shdr);
+ shtab = (Elf32_Shdr *) alloc(size);
+ if (olseek (fd, eh->e_shoff, SEEK_SET) != eh->e_shoff ||
+ oread (fd, shtab, size) != size) {
+ printf("Seek to section headers failed.\n");
+ return -1;
+ }
+
+ tablebase = roundup(tablebase, sizeof(long));
+ symptr = (int *)tablebase;
+ tablebase = roundup(tablebase, 4096);
+ keh = (Elf32_Ehdr *)tablebase;
+ tablebase += sizeof(Elf32_Ehdr);
+ tablebase = roundup(tablebase, sizeof(long));
+ ksh = (Elf32_Shdr *)tablebase;
+ tablebase += roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long));
+ memcpy(ksh, shtab, roundup((sizeof(Elf32_Shdr) * eh->e_shnum), sizeof(long)));
+ sh = ksh;
+
+ shstrh = &sh[eh->e_shstrndx];
+
+ for (i = 0; i < eh->e_shnum; sh++, i++) {
+ if (sh->sh_type == SHT_SYMTAB) {
+ break;
+ }
+ }
+ if (i >= eh->e_shnum) {
+ printf("No symbol table found!\n");
+ return -1;
+ }
+
+ strh = &ksh[sh->sh_link];
+ nsym = sh->sh_size / sh->sh_entsize;
+ offs = sh->sh_offset;
+ size = sh->sh_size;
+
+ /*
+ * Allocate tables in correct order so the kernel grooks it.
+ * Then we read them in the order they are in the ELF file.
+ */
+ shstrtab = gettable(shstrh->sh_size, "shstrtab", flags);
+ strtab = gettable(strh->sh_size, "strtab", flags);
+ symtab = gettable(size, "symtab", flags);
+ symend = (char *)symtab + size;
+
+ do {
+ if(shstrh->sh_offset < offs && shstrh->sh_offset < strh->sh_offset) {
+#if 0
+ /*
+ * We would like to read the shstrtab from the file but since this
+ * table is located in front of the shtab it is already gone. We can't
+ * position backwards outside the current segment when using tftp.
+ * Instead we create the names we need in the string table because
+ * it can be reconstructed from the info we now have access to.
+ */
+ if (!readtable (shstrh->sh_offset, (void *)shstrtab,
+ shstrh->sh_size, "shstring", flags)) {
+ return(0);
+ }
+#else
+ memset(shstrtab, 0, shstrh->sh_size);
+ strncpy(shstrtab + shstrh->sh_name, ".shstrtab", 10);
+ strncpy(shstrtab + strh->sh_name, ".strtab", 10);
+ strncpy(shstrtab + sh->sh_name, ".symtab", 10);
+#endif
+ shstrh->sh_offset = 0x7fffffff;
+ }
+
+ if (offs < strh->sh_offset && offs < shstrh->sh_offset) {
+ if (!(readtable(fd, offs, (void *)symtab, size, "sym", flags))) {
+ return (0);
+ }
+ offs = 0x7fffffff;
+ }
+
+ if (strh->sh_offset < offs && strh->sh_offset < shstrh->sh_offset) {
+ if (!(readtable (fd, strh->sh_offset, (void *)strtab,
+ strh->sh_size, "string", flags))) {
+ return (0);
+ }
+ strh->sh_offset = 0x7fffffff;
+ }
+ if (offs == 0x7fffffff && strh->sh_offset == 0x7fffffff &&
+ shstrh->sh_offset == 0x7fffffff) {
+ break;
+ }
+ } while(1);
+
+ /*
+ * Update the kernel headers with the current info.
+ */
+ shstrh->sh_offset = (Elf32_Off)shstrtab - (Elf32_Off)keh;
+ strh->sh_offset = (Elf32_Off)strtab - (Elf32_Off)keh;
+ sh->sh_offset = (Elf32_Off)symtab - (Elf32_Off)keh;
+ memcpy(keh, eh, sizeof(Elf32_Ehdr));
+ keh->e_phoff = 0;
+ keh->e_shoff = sizeof(Elf32_Ehdr);
+ keh->e_phentsize = 0;
+ keh->e_phnum = 0;
+
+ symptr[0] = (int)keh;
+ symptr[1] = roundup((int)symend, sizeof(int));
+
+ return(0);
+
+}
diff --git a/sys/arch/sgi/stand/boot/conf.c b/sys/arch/sgi/stand/boot/conf.c
new file mode 100644
index 00000000000..645283c946b
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/conf.c
@@ -0,0 +1,46 @@
+/* $OpenBSD: conf.c,v 1.1 2004/08/23 14:22:40 pefo Exp $ */
+
+/*
+ * Copyright (c) 1997 Per Fogelstrom
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <stand.h>
+
+int errno;
+
+extern void nullsys();
+extern int nodev();
+extern int noioctl();
+
+int diostrategy(void *, int, daddr_t, size_t, void *, size_t *);
+int dioopen(struct open_file *, ...);
+int dioclose(struct open_file *);
+
+#define dioioctl noioctl
+
+struct devsw devsw[] = {
+ { "scsi", diostrategy, dioopen, dioclose, dioioctl }, /*0*/
+};
+
+int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/sgi/stand/boot/diskio.c b/sys/arch/sgi/stand/boot/diskio.c
new file mode 100644
index 00000000000..b5b843710bc
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/diskio.c
@@ -0,0 +1,134 @@
+/* $OpenBSD: diskio.c,v 1.1 2004/08/23 14:22:40 pefo Exp $ */
+
+/*
+ * Copyright (c) 2000 Opsycon AB (www.opsycon.se)
+ * Copyright (c) 2000 Rtmx, Inc (www.rtmx.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for Rtmx, Inc by
+ * Opsycon Open System Consulting AB, Sweden.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <stand.h>
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <mips64/arcbios.h>
+
+
+struct dio_softc {
+ int sc_fd; /* PROM file id */
+ int sc_part; /* disk partition number */
+ struct disklabel sc_label; /* disk label for this disk */
+};
+
+int
+diostrategy(void *devdata, int rw, daddr_t bn, u_int reqcnt,
+ char *addr, u_int *cnt)
+{
+ struct dio_softc *sc = (struct dio_softc *)devdata;
+ struct partition *pp = &sc->sc_label.d_partitions[sc->sc_part];
+ int64_t offset;
+ int result;
+
+ offset = (pp->p_offset + bn) * DEV_BSIZE;
+
+ if ((Bios_Seek(sc->sc_fd, &offset, 0) < 0) ||
+ (Bios_Read(sc->sc_fd, addr, reqcnt, &result) < 0))
+ return EIO;
+
+ *cnt = result;
+ return (0);
+}
+
+int
+dioopen(struct open_file *f, ...)
+{
+ char *ctlr;
+ int partition;
+
+ struct dio_softc *sc;
+ struct disklabel *lp;
+ int i, fd;
+ char *msg = NULL;
+ char buf[DEV_BSIZE];
+ int cnt;
+ daddr_t labelsector;
+ va_list ap;
+
+ va_start(ap, f);
+
+ ctlr = va_arg(ap, char *);
+ partition = va_arg(ap, int);
+ if (partition >= MAXPARTITIONS)
+ return (ENXIO);
+
+ 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;
+
+ 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;
+
+ labelsector = LABELSECTOR;
+
+#if 0
+ /* try to read disk label and partition table information */
+ i = diostrategy(sc, F_READ, (daddr_t)labelsector, DEV_BSIZE, buf, &cnt);
+
+ if (i == 0 && cnt == DEV_BSIZE)
+ msg = getdisklabel(buf, lp);
+ else
+ msg = "rd err";
+
+ if (msg) {
+ printf("%s: %s\n", ctlr, msg);
+ return ENXIO;
+ }
+#endif
+
+ return 0;
+}
+
+int
+dioclose(f)
+ struct open_file *f;
+{
+ Bios_Close(((struct dio_softc *)f->f_devdata)->sc_fd);
+ free(f->f_devdata, sizeof(struct dio_softc));
+ f->f_devdata = NULL;
+ return 0;
+}
diff --git a/sys/arch/sgi/stand/boot/filesystem.c b/sys/arch/sgi/stand/boot/filesystem.c
new file mode 100644
index 00000000000..b35709b9ad2
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/filesystem.c
@@ -0,0 +1,44 @@
+/* $NetBSD: filesystem.c,v 1.2 1995/02/16 02:33:05 cgd Exp $ */
+
+/*
+ * Copyright (c) 1993 Philip A. Nelson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip A. Nelson.
+ * 4. The name of Philip A. Nelson may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * filesystem.c
+ */
+
+#include <stand.h>
+#include <ufs.h>
+
+struct fs_ops file_system[] = {
+ { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat },
+};
+
+int nfsys = sizeof(file_system)/sizeof(struct fs_ops);
+
diff --git a/sys/arch/sgi/stand/boot/start.S b/sys/arch/sgi/stand/boot/start.S
new file mode 100644
index 00000000000..36f6fcccf9b
--- /dev/null
+++ b/sys/arch/sgi/stand/boot/start.S
@@ -0,0 +1,53 @@
+/* $OpenBSD: start.S,v 1.1 2004/08/23 14:22:40 pefo Exp $ */
+
+/*
+ * Copyright (c) 2001 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Opsycon AB, Sweden (www.opsycon.com).
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define ABICALLS
+
+#include <machine/regdef.h>
+#include <machine/asm.h>
+
+/*
+ * Frame required for the debugger (if we have any)
+ */
+#define START_FRAME ((4 * 4) + 4 + 4)
+
+ .globl __start
+__start:
+ la gp, _gp
+
+ jal main
+
+1:
+ b 1b
+
diff --git a/sys/arch/sgi/stand/libkern/Makefile b/sys/arch/sgi/stand/libkern/Makefile
new file mode 100644
index 00000000000..98f37f63650
--- /dev/null
+++ b/sys/arch/sgi/stand/libkern/Makefile
@@ -0,0 +1,40 @@
+# $OpenBSD: Makefile,v 1.1 2004/08/23 14:22:40 pefo Exp $
+
+LIB= kern
+
+.PATH: ${.CURDIR}/../../../../lib/libkern
+.PATH: ${.CURDIR}/../../../../lib/libkern/arch/mips64
+
+.include "${.CURDIR}/../../../../lib/libkern/arch/mips64/Makefile.inc"
+
+CFLAGS= -O2 -mno-abicalls -D_NO_ABICALLS ${STANDALONE} \
+ -nostdinc -I${.CURDIR}/../include -I${.CURDIR}/../../../.. \
+ -I${.CURDIR}/../../../../lib/libkern \
+ -I${.CURDIR}/../../../../lib/libkern/arch/mips64 -I${.CURDIR} \
+ -I${.OBJDIR}
+
+AFLAGS= -x assembler-with-cpp -traditional-cpp -I${.CURDIR}/../include \
+ -I${.CURDIR}/../../../.. -I${.CURDIR}/../../../../lib/libkern \
+ -I${.CURDIR}/../../../../lib/libkern/arch/mips64 \
+ -I${.OBJDIR}
+
+# kern routines
+SRCS= __main.c ashrdi3.c bzero.S divdi3.c qdivrem.c strlen.S \
+ strcmp.c strlcat.c strlcpy.c strncmp.c umoddi3.c
+
+${OBJS}: ${.CURDIR}/../Makefile.inc
+
+CLEANFILES += machine mips64
+
+NOPROFILE=
+NOPIC=
+
+.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(kernlibdir) && !make(obj)
+.BEGIN:
+ @([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
+ @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64)
+.endif
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/sys/arch/sgi/stand/libsa/Makefile b/sys/arch/sgi/stand/libsa/Makefile
new file mode 100644
index 00000000000..83259b1c684
--- /dev/null
+++ b/sys/arch/sgi/stand/libsa/Makefile
@@ -0,0 +1,41 @@
+# $OpenBSD: Makefile,v 1.1 2004/08/23 14:22:40 pefo Exp $
+
+LIB= sa
+
+.PATH: ${.CURDIR}/../../../../lib/libsa
+
+CLEANFILES += machine mips64
+
+CFLAGS= ${CEXTRAFLAGS} -O2 -nostdinc -mno-abicalls -D_NO_ABICALLS \
+ -I${.CURDIR} -I${.CURDIR}/../include -I${.CURDIR}/../.. \
+ -I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. \
+ -I${.CURDIR}/../../../../lib/libsa \
+ -I${.OBJDIR}
+
+CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD ${STANDALONE}
+
+# stand routines
+SRCS= alloc.c exit.c exec.c getfile.c gets.c globals.c \
+ memcmp.c memcpy.c memset.c printf.c snprintf.c strerror.c strncpy.c
+
+# io routines
+SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c lseek.c \
+ open.c read.c stat.c write.c cread.c
+
+# boot filesystems
+SRCS+= ufs.c nfs.c cd9660.c
+
+${OBJS}: ${.CURDIR}/../Makefile.inc
+
+NOPROFILE=
+NOPIC=
+
+.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(kernlibdir) && !make(obj)
+.BEGIN:
+ @([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
+ @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64)
+.endif
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/sys/arch/sgi/stand/libz/Makefile b/sys/arch/sgi/stand/libz/Makefile
new file mode 100644
index 00000000000..0d872edf632
--- /dev/null
+++ b/sys/arch/sgi/stand/libz/Makefile
@@ -0,0 +1,9 @@
+# $OpenBSD: Makefile,v 1.1 2004/08/23 14:22:40 pefo Exp $
+
+S=${.CURDIR}/../../../..
+ZDST=${.OBJDIR}
+
+.PATH: ${S}/lib/libz
+
+.include "${S}/lib/libz/Makefile"
+CFLAGS+= -mno-abicalls -D_NO_ABICALLS ${CEXTRAFLAGS} ${AFLAGS} -I${S}
diff --git a/sys/arch/sgi/stand/sgivol/Makefile b/sys/arch/sgi/stand/sgivol/Makefile
new file mode 100644
index 00000000000..fc0f5cc4d8f
--- /dev/null
+++ b/sys/arch/sgi/stand/sgivol/Makefile
@@ -0,0 +1,9 @@
+# $OpenBSD: Makefile,v 1.1 2004/08/23 14:22:40 pefo Exp $
+# $NetBSD: Makefile,v 1.5 2002/12/13 02:36:37 lukem Exp $
+
+NOMAN= # defined
+
+PROG= sgivol
+LDADD+= -lutil
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/sgi/stand/sgivol/sgivol.c b/sys/arch/sgi/stand/sgivol/sgivol.c
new file mode 100644
index 00000000000..b2e51b1062b
--- /dev/null
+++ b/sys/arch/sgi/stand/sgivol/sgivol.c
@@ -0,0 +1,615 @@
+/* $NetBSD: sgivol.c,v 1.8 2003/11/08 04:59:00 sekiya Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Michael Hitch and Hubert Feyrer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/disklabel.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <util.h>
+#include <sys/endian.h>
+
+/*
+ * Some IRIX man pages refer to the size being a multiple of whole cylinders.
+ * Later ones only refer to the size being "typically" 2MB. IRIX fx(1)
+ * uses a default drive geometry if one can't be determined, suggesting
+ * that "whole cylinder" multiples are not required.
+ */
+
+#define SGI_SIZE_VOLHDR 3135 /* Can be overridden via -h parameter */
+
+struct local_devparms {
+ u_int8_t dp_skew;
+ u_int8_t dp_gap1;
+ u_int8_t dp_gap2;
+ u_int8_t dp_spares_cyl;
+ u_int16_t dp_cyls;
+ u_int16_t dp_shd0;
+ u_int16_t dp_trks0;
+ u_int8_t dp_ctq_depth;
+ u_int8_t dp_cylshi;
+ u_int16_t dp_unused;
+ u_int16_t dp_secs;
+ u_int16_t dp_secbytes;
+ u_int16_t dp_interleave;
+ u_int32_t dp_flags;
+ u_int32_t dp_datarate;
+ u_int32_t dp_nretries;
+ u_int32_t dp_mspw;
+ u_int16_t dp_xgap1;
+ u_int16_t dp_xsync;
+ u_int16_t dp_xrdly;
+ u_int16_t dp_xgap2;
+ u_int16_t dp_xrgate;
+ u_int16_t dp_xwcont;
+} __attribute__((__packed__));
+
+struct local_sgilabel {
+#define SGILABEL_MAGIC 0xbe5a941
+ u_int32_t magic;
+ int16_t root;
+ int16_t swap;
+ char bootfile[16];
+ struct local_devparms dp;
+ struct {
+ char name[8];
+ int32_t block;
+ int32_t bytes;
+ } voldir[15];
+ struct {
+ int32_t blocks;
+ int32_t first;
+ int32_t type;
+ } partitions[MAXPARTITIONS];
+ int32_t checksum;
+ int32_t _pad;
+} __attribute__((__packed__));
+
+#define SGI_PTYPE_VOLHDR 0
+#define SGI_PTYPE_RAW 3
+#define SGI_PTYPE_BSD 4
+#define SGI_PTYPE_VOLUME 6
+#define SGI_PTYPE_EFS 7
+#define SGI_PTYPE_LVOL 8
+#define SGI_PTYPE_RLVOL 9
+#define SGI_PTYPE_XFS 10
+#define SGI_PTYPE_XFSLOG 11
+#define SGI_PTYPE_XLV 12
+#define SGI_PTYPE_XVM 13
+
+int fd;
+int opt_i; /* Initialize volume header */
+int opt_r; /* Read a file from volume header */
+int opt_w; /* Write a file to volume header */
+int opt_d; /* Delete a file from volume header */
+int opt_p; /* Modify a partition */
+int opt_q; /* quiet mode */
+int opt_f; /* Don't ask, just do what you're told */
+int partno, partfirst, partblocks, parttype;
+struct local_sgilabel *volhdr;
+int32_t checksum;
+u_int32_t volhdr_size = SGI_SIZE_VOLHDR;
+
+const char *vfilename = "";
+const char *ufilename = "";
+
+struct disklabel lbl;
+
+unsigned char buf[512];
+
+const char *sgi_types[] = {
+ "Volume Header",
+ "Repl Trks",
+ "Repl Secs",
+ "Raw",
+ "BSD4.2",
+ "SysV",
+ "Volume",
+ "EFS",
+ "LVol",
+ "RLVol",
+ "XFS",
+ "XSFLog",
+ "XLV",
+ "XVM"
+};
+
+int main(int, char *[]);
+
+void display_vol(void);
+void init_volhdr(void);
+void read_file(void);
+void write_file(void);
+void delete_file(void);
+void modify_partition(void);
+void write_volhdr(void);
+int allocate_space(int);
+void checksum_vol(void);
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ while ((ch = getopt(argc, argv, "irwpdqfh:")) != -1) {
+ switch (ch) {
+ /* -i, -r, -w, -d and -p override each other */
+ /* -q implies -f */
+ case 'q':
+ ++opt_q;
+ ++opt_f;
+ break;
+ case 'f':
+ ++opt_f;
+ break;
+ case 'i':
+ ++opt_i;
+ opt_r = opt_w = opt_d = opt_p = 0;
+ break;
+ case 'h':
+ volhdr_size = atoi(optarg);
+ break;
+ case 'r':
+ ++opt_r;
+ opt_i = opt_w = opt_d = opt_p = 0;
+ break;
+ case 'w':
+ ++opt_w;
+ opt_i = opt_r = opt_d = opt_p = 0;
+ break;
+ case 'd':
+ ++opt_d;
+ opt_i = opt_r = opt_w = opt_p = 0;
+ break;
+ case 'p':
+ ++opt_p;
+ opt_i = opt_r = opt_w = opt_d = 0;
+ partno = atoi(argv[0]);
+ partfirst = atoi(argv[1]);
+ partblocks = atoi(argv[2]);
+ parttype = atoi(argv[3]);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (opt_r || opt_w) {
+ if (argc != 3)
+ usage();
+ vfilename = argv[0];
+ ufilename = argv[1];
+ argc -= 2;
+ argv += 2;
+ }
+ if (opt_d) {
+ if (argc != 2)
+ usage();
+ vfilename = argv[0];
+ argc--;
+ argv++;
+ }
+
+ if (opt_p) {
+ if (argc != 5)
+ usage();
+ partno = atoi(argv[0]);
+ partfirst = atoi(argv[1]);
+ partblocks = atoi(argv[2]);
+ parttype = atoi(argv[3]);
+ argc -= 4;
+ argv += 4;
+ }
+ if (argc != 1)
+ usage();
+
+ fd = open(argv[0], (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY);
+ if (fd < 0) {
+ sprintf(buf, "/dev/r%s%c", argv[0], 'a' + getrawpartition());
+ fd = open(buf, (opt_i | opt_w | opt_d | opt_p)
+ ? O_RDWR : O_RDONLY);
+ if (fd < 0) {
+ printf("Error opening device %s: %s\n",
+ argv[0], strerror(errno));
+ exit(1);
+ }
+ }
+ if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
+ perror("read volhdr");
+ exit(1);
+ }
+ if (ioctl(fd, DIOCGDINFO, &lbl) < 0) {
+ perror("DIOCGDINFO");
+ exit(1);
+ }
+ volhdr = (struct local_sgilabel *) buf;
+ if (opt_i) {
+ init_volhdr();
+ exit(0);
+ }
+ if (betoh32(volhdr->magic) != SGILABEL_MAGIC) {
+ printf("No Volume Header found, magic=%x. Use -i first.\n",
+ betoh32(volhdr->magic));
+ exit(1);
+ }
+ if (opt_r) {
+ read_file();
+ exit(0);
+ }
+ if (opt_w) {
+ write_file();
+ exit(0);
+ }
+ if (opt_d) {
+ delete_file();
+ exit(0);
+ }
+ if (opt_p) {
+ modify_partition();
+ exit(0);
+ }
+
+ if (!opt_q)
+ display_vol();
+
+ return 0;
+}
+
+void
+display_vol(void)
+{
+ int32_t *l;
+ int i;
+
+ printf("disklabel shows %d sectors\n", lbl.d_secperunit);
+ l = (int32_t *)buf;
+ checksum = 0;
+ for (i = 0; i < 512 / 4; ++i)
+ checksum += betoh32(l[i]);
+ printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*");
+ printf("root part: %d\n", betoh32(volhdr->root));
+ printf("swap part: %d\n", betoh32(volhdr->swap));
+ printf("bootfile: %s\n", volhdr->bootfile);
+ /* volhdr->devparams[0..47] */
+ printf("\nVolume header files:\n");
+ for (i = 0; i < 15; ++i)
+ if (volhdr->voldir[i].name[0])
+ printf("%-8s offset %4d blocks, length %8d bytes (%d blocks)\n",
+ volhdr->voldir[i].name, betoh32(volhdr->voldir[i].block),
+ betoh32(volhdr->voldir[i].bytes), (betoh32(volhdr->voldir[i].bytes) + 511) / 512);
+ printf("\nSGI partitions:\n");
+ for (i = 0; i < MAXPARTITIONS; ++i) {
+ if (betoh32(volhdr->partitions[i].blocks)) {
+ printf("%2d:%c blocks %8d first %8d type %2d (%s)\n",
+ i, i + 'a', betoh32(volhdr->partitions[i].blocks),
+ betoh32(volhdr->partitions[i].first),
+ betoh32(volhdr->partitions[i].type),
+ betoh32(volhdr->partitions[i].type) > 13 ? "???" :
+ sgi_types[betoh32(volhdr->partitions[i].type)]);
+ }
+ }
+}
+
+void
+init_volhdr(void)
+{
+ memset(buf, 0, sizeof(buf));
+ volhdr->magic = htobe32(SGILABEL_MAGIC);
+ volhdr->root = htobe16(0);
+ volhdr->swap = htobe16(1);
+ strcpy(volhdr->bootfile, "/bsd");
+ volhdr->dp.dp_skew = lbl.d_trackskew;
+ volhdr->dp.dp_gap1 = 1; /* XXX */
+ volhdr->dp.dp_gap2 = 1; /* XXX */
+ volhdr->dp.dp_cyls = htobe16(lbl.d_ncylinders);
+ volhdr->dp.dp_shd0 = 0;
+ volhdr->dp.dp_trks0 = htobe16(lbl.d_ntracks);
+ volhdr->dp.dp_secs = htobe16(lbl.d_nsectors);
+ volhdr->dp.dp_secbytes = htobe16(lbl.d_secsize);
+ volhdr->dp.dp_interleave = htobe16(lbl.d_interleave);
+ volhdr->dp.dp_nretries = htobe32(22);
+ volhdr->partitions[10].blocks = htobe32(lbl.d_secperunit);
+ volhdr->partitions[10].first = 0;
+ volhdr->partitions[10].type = htobe32(SGI_PTYPE_VOLUME);
+ volhdr->partitions[8].blocks = htobe32(volhdr_size);
+ volhdr->partitions[8].first = 0;
+ volhdr->partitions[8].type = htobe32(SGI_PTYPE_VOLHDR);
+ volhdr->partitions[0].blocks = htobe32(lbl.d_secperunit - volhdr_size);
+ volhdr->partitions[0].first = htobe32(volhdr_size);
+ volhdr->partitions[0].type = htobe32(SGI_PTYPE_BSD);
+ write_volhdr();
+}
+
+void
+read_file(void)
+{
+ FILE *fp;
+ int i;
+
+ if (!opt_q)
+ printf("Reading file %s\n", vfilename);
+ for (i = 0; i < 15; ++i) {
+ if (strncmp(vfilename, volhdr->voldir[i].name,
+ strlen(volhdr->voldir[i].name)) == 0)
+ break;
+ }
+ if (i >= 15) {
+ printf("file %s not found\n", vfilename);
+ exit(1);
+ }
+ /* XXX assumes volume header starts at 0? */
+ lseek(fd, betoh32(volhdr->voldir[i].block) * 512, SEEK_SET);
+ fp = fopen(ufilename, "w");
+ if (fp == NULL) {
+ perror("open write");
+ exit(1);
+ }
+ i = betoh32(volhdr->voldir[i].bytes);
+ while (i > 0) {
+ if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
+ perror("read file");
+ exit(1);
+ }
+ fwrite(buf, 1, i > sizeof(buf) ? sizeof(buf) : i, fp);
+ i -= i > sizeof(buf) ? sizeof(buf) : i;
+ }
+ fclose(fp);
+}
+
+void
+write_file(void)
+{
+ FILE *fp;
+ int slot;
+ size_t namelen;
+ int block, i;
+ struct stat st;
+ char fbuf[512];
+
+ if (!opt_q)
+ printf("Writing file %s\n", ufilename);
+ if (stat(ufilename, &st) < 0) {
+ perror("stat");
+ exit(1);
+ }
+ if (!opt_q)
+ printf("File %s has %lld bytes\n", ufilename, st.st_size);
+ slot = -1;
+ for (i = 0; i < 15; ++i) {
+ if (volhdr->voldir[i].name[0] == '\0' && slot < 0)
+ slot = i;
+ if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
+ slot = i;
+ break;
+ }
+ }
+ if (slot == -1) {
+ printf("No directory space for file %s\n", vfilename);
+ exit(1);
+ }
+ /* -w can overwrite, -a won't overwrite */
+ if (betoh32(volhdr->voldir[slot].block) > 0) {
+ if (!opt_q)
+ printf("File %s exists, removing old file\n",
+ vfilename);
+ volhdr->voldir[slot].name[0] = 0;
+ volhdr->voldir[slot].block = volhdr->voldir[slot].bytes = 0;
+ }
+ if (st.st_size == 0) {
+ printf("bad file size\n");
+ exit(1);
+ }
+ /* XXX assumes volume header starts at 0? */
+ block = allocate_space((int)st.st_size);
+ if (block < 0) {
+ printf("No space for file\n");
+ exit(1);
+ }
+
+ /*
+ * Make sure the name in the volume header is max. 8 chars,
+ * NOT including NUL.
+ */
+ namelen = strlen(vfilename);
+ if (namelen > sizeof(volhdr->voldir[slot].name)) {
+ printf("Warning: '%s' is too long for volume header, ",
+ vfilename);
+ namelen = sizeof(volhdr->voldir[slot].name);
+ printf("truncating to '%-8s'\n", vfilename);
+ }
+
+ /* Populate it w/ NULs */
+ memset(volhdr->voldir[slot].name, 0,
+ sizeof(volhdr->voldir[slot].name));
+ /* Then copy the name */
+ memcpy(volhdr->voldir[slot].name, vfilename, namelen);
+
+ volhdr->voldir[slot].block = htobe32(block);
+ volhdr->voldir[slot].bytes = htobe32(st.st_size);
+
+ write_volhdr();
+
+ /* write the file itself */
+ i = lseek(fd, block * 512, SEEK_SET);
+ if (i < 0) {
+ perror("lseek write");
+ exit(1);
+ }
+ i = st.st_size;
+ fp = fopen(ufilename, "r");
+ while (i > 0) {
+ fread(fbuf, 1, i > 512 ? 512 : i, fp);
+ if (write(fd, fbuf, 512) != 512) {
+ perror("write file");
+ exit(1);
+ }
+ i -= i > 512 ? 512 : i;
+ }
+}
+
+void
+delete_file(void)
+{
+ int i;
+
+ for (i = 0; i < 15; ++i) {
+ if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
+ break;
+ }
+ }
+ if (i >= 15) {
+ printf("File %s not found\n", vfilename);
+ exit(1);
+ }
+
+ /* XXX: we don't compact the file space, so get fragmentation */
+ volhdr->voldir[i].name[0] = '\0';
+ volhdr->voldir[i].block = volhdr->voldir[i].bytes = 0;
+ write_volhdr();
+}
+
+void
+modify_partition(void)
+{
+ if (!opt_q)
+ printf("Modify partition %d start %d length %d\n",
+ partno, partfirst, partblocks);
+ if (partno < 0 || partno > 15) {
+ printf("Invalid partition number: %d\n", partno);
+ exit(1);
+ }
+ volhdr->partitions[partno].blocks = htobe32(partblocks);
+ volhdr->partitions[partno].first = htobe32(partfirst);
+ volhdr->partitions[partno].type = htobe32(parttype);
+ write_volhdr();
+}
+
+void
+write_volhdr(void)
+{
+ int i;
+
+ checksum_vol();
+
+ if (!opt_q)
+ display_vol();
+ if (!opt_f) {
+ printf("\nDo you want to update volume (y/n)? ");
+ i = getchar();
+ if (i != 'Y' && i != 'y')
+ exit(1);
+ }
+ i = lseek(fd, 0, SEEK_SET);
+ if (i < 0) {
+ perror("lseek 0");
+ exit(1);
+ }
+ i = write(fd, buf, 512);
+ if (i < 0)
+ perror("write volhdr");
+}
+
+int
+allocate_space(int size)
+{
+ int n, blocks;
+ int first;
+
+ blocks = (size + 511) / 512;
+ first = 2;
+ n = 0;
+ while (n < 15) {
+ if (volhdr->voldir[n].name[0]) {
+ if (first < (betoh32(volhdr->voldir[n].block) +
+ (betoh32(volhdr->voldir[n].bytes) + 511) / 512) &&
+ (first + blocks) > betoh32(volhdr->voldir[n].block)) {
+ first = betoh32(volhdr->voldir[n].block) +
+ (betoh32(volhdr->voldir[n].bytes) + 511) / 512;
+#if 0
+ printf("allocate: n=%d first=%d blocks=%d size=%d\n", n, first, blocks, size);
+ printf("%s %d %d\n", volhdr->voldir[n].name, volhdr->voldir[n].block, volhdr->voldir[n].bytes);
+ printf("first=%d block=%d last=%d end=%d\n", first, volhdr->voldir[n].block,
+ first + blocks - 1, volhdr->voldir[n].block + (volhdr->voldir[n].bytes + 511) / 512);
+#endif
+ n = 0;
+ continue;
+ }
+ }
+ ++n;
+ }
+ if (first + blocks > lbl.d_secperunit)
+ first = -1;
+ /* XXX assumes volume header is partition 8 */
+ /* XXX assumes volume header starts at 0? */
+ if (first + blocks >= betoh32(volhdr->partitions[8].blocks))
+ first = -1;
+ return (first);
+}
+
+void
+checksum_vol(void)
+{
+ int32_t *l;
+ int i;
+
+ volhdr->checksum = checksum = 0;
+ l = (int32_t *)buf;
+ for (i = 0; i < 512 / 4; ++i)
+ checksum += betoh32(l[i]);
+ volhdr->checksum = htobe32(-checksum);
+}
+
+void
+usage(void)
+{
+ printf("Usage: sgivol [-qf] [-i] [-h vhsize] device\n"
+ " sgivol [-qf] [-r vhfilename diskfilename] device\n"
+ " sgivol [-qf] [-w vhfilename diskfilename] device\n"
+ " sgivol [-qf] [-d vhfilename] device\n"
+ );
+ exit(0);
+}