diff options
author | Per Fogelstrom <pefo@cvs.openbsd.org> | 2004-08-23 14:22:41 +0000 |
---|---|---|
committer | Per Fogelstrom <pefo@cvs.openbsd.org> | 2004-08-23 14:22:41 +0000 |
commit | 734774568039991fce29dd03476f90c2bfaaefcc (patch) | |
tree | 8c65793de161b5f097c22f10eee4b1e5e84f75bc | |
parent | 16b13f1c5161dc4e740cf2ff1620dd1f58ef321c (diff) |
disk boot and tools for sgi
-rw-r--r-- | sys/arch/sgi/stand/Makefile | 4 | ||||
-rw-r--r-- | sys/arch/sgi/stand/Makefile.inc | 63 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/Makefile | 33 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/arcbios.c | 308 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/boot.c | 298 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/conf.c | 46 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/diskio.c | 134 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/filesystem.c | 44 | ||||
-rw-r--r-- | sys/arch/sgi/stand/boot/start.S | 53 | ||||
-rw-r--r-- | sys/arch/sgi/stand/libkern/Makefile | 40 | ||||
-rw-r--r-- | sys/arch/sgi/stand/libsa/Makefile | 41 | ||||
-rw-r--r-- | sys/arch/sgi/stand/libz/Makefile | 9 | ||||
-rw-r--r-- | sys/arch/sgi/stand/sgivol/Makefile | 9 | ||||
-rw-r--r-- | sys/arch/sgi/stand/sgivol/sgivol.c | 615 |
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); +} |