diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2001-08-18 15:51:11 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2001-08-18 15:51:11 +0000 |
commit | 4cbd011292f901d241cd3710eb7bcfff692b6be4 (patch) | |
tree | ea949af6af61769a2f9bfe288d3ff0b636828d29 /sys/arch/sparc64/stand/ofwboot | |
parent | 9c67302636a9447a5b801b9491c5aa6406fb88bc (diff) |
Enough of NetBSD/sparc64 for ofwboot to compile/link
Diffstat (limited to 'sys/arch/sparc64/stand/ofwboot')
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/Locore.c | 866 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/Makefile | 92 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/alloc.c | 214 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/boot.c | 623 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/elfXX_exec.c | 208 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/md5.h | 55 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/net.c | 194 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/netif_of.c | 240 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/ofdev.c | 527 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/ofdev.h | 52 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/openfirm.h | 58 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/srt0.s | 210 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/vers.c | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/version | 1 |
14 files changed, 3346 insertions, 0 deletions
diff --git a/sys/arch/sparc64/stand/ofwboot/Locore.c b/sys/arch/sparc64/stand/ofwboot/Locore.c new file mode 100644 index 00000000000..955d909f34d --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/Locore.c @@ -0,0 +1,866 @@ +/* $NetBSD: Locore.c,v 1.1 2000/08/20 14:58:36 mrg Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 <lib/libsa/stand.h> +#include "openfirm.h" + +#include <machine/cpu.h> + +vaddr_t OF_claim_virt __P((vaddr_t vaddr, int len)); +vaddr_t OF_alloc_virt __P((int len, int align)); +int OF_free_virt __P((vaddr_t vaddr, int len)); +int OF_unmap_virt __P((vaddr_t vaddr, int len)); +vaddr_t OF_map_phys __P((paddr_t paddr, off_t size, vaddr_t vaddr, int mode)); +paddr_t OF_alloc_phys __P((int len, int align)); +paddr_t OF_claim_phys __P((paddr_t phys, int len)); +int OF_free_phys __P((paddr_t paddr, int len)); + +extern int openfirmware(void *); + +void setup __P((void)); + +#if 0 +#ifdef XCOFF_GLUE +asm (".text; .globl _entry; _entry: .long _start,0,0"); +#endif + +__dead void +_start(vpd, res, openfirm, arg, argl) + void *vpd; + int res; + int (*openfirm)(void *); + char *arg; + int argl; +{ + extern char etext[]; + +#ifdef FIRMWORKSBUGS + syncicache((void *)RELOC, etext - (char *)RELOC); +#endif + openfirmware = openfirm; /* Save entry to Open Firmware */ + setup(); + main(arg, argl); + exit(); +} +#endif + +__dead void +_rtt() +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + } args; + + args.name = ADR2CELL("exit"); + args.nargs = 0; + args.nreturns = 0; + openfirmware(&args); + while (1); /* just in case */ +} + +void +OF_enter() +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + } args; + + args.name = ADR2CELL("enter"); + args.nargs = 0; + args.nreturns = 0; + openfirmware(&args); +} + +int +OF_finddevice(name) + char *name; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t device; + cell_t phandle; + } args; + + args.name = ADR2CELL("finddevice"); + args.nargs = 1; + args.nreturns = 1; + args.device = ADR2CELL(name); + if (openfirmware(&args) == -1) + return -1; + return args.phandle; +} + +int +OF_instance_to_package(ihandle) + int ihandle; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t ihandle; + cell_t phandle; + } args; + + args.name = ADR2CELL("instance-to-package"); + args.nargs = 1; + args.nreturns = 1; + args.ihandle = HDL2CELL(ihandle); + if (openfirmware(&args) == -1) + return -1; + return args.phandle; +} + +int +OF_getprop(handle, prop, buf, buflen) + int handle; + char *prop; + void *buf; + int buflen; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t phandle; + cell_t prop; + cell_t buf; + cell_t buflen; + cell_t size; + } args; + + args.name = ADR2CELL("getprop"); + args.nargs = 4; + args.nreturns = 1; + args.phandle = HDL2CELL(handle); + args.prop = ADR2CELL(prop); + args.buf = ADR2CELL(buf); + args.buflen = buflen; + if (openfirmware(&args) == -1) + return -1; + return args.size; +} + +#ifdef __notyet__ /* Has a bug on FirePower */ +int +OF_setprop(handle, prop, buf, len) + u_int handle; + char *prop; + void *buf; + int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t phandle; + cell_t prop; + cell_t buf; + cell_t len; + cell_t size; + } args; + + args.name = ADR2CELL("setprop"); + args.nargs = 4; + args.nreturns = 1; + args.phandle = HDL2CELL(handle); + args.prop = ADR2CELL(prop); + args.buf = ADR2CELL(buf); + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.size; +} +#endif + +int +OF_open(dname) + char *dname; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t dname; + cell_t handle; + } args; + + args.name = ADR2CELL("open"); + args.nargs = 1; + args.nreturns = 1; + args.dname = ADR2CELL(dname); + if (openfirmware(&args) == -1 || + args.handle == 0) + return -1; + return args.handle; +} + +void +OF_close(handle) + int handle; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t handle; + } args; + + args.name = ADR2CELL("close"); + args.nargs = 1; + args.nreturns = 1; + args.handle = HDL2CELL(handle); + openfirmware(&args); +} + +int +OF_write(handle, addr, len) + int handle; + void *addr; + int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t ihandle; + cell_t addr; + cell_t len; + cell_t actual; + } args; + + args.name = ADR2CELL("write"); + args.nargs = 3; + args.nreturns = 1; + args.ihandle = HDL2CELL(handle); + args.addr = ADR2CELL(addr); + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.actual; +} + +int +OF_read(handle, addr, len) + int handle; + void *addr; + int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t ihandle; + cell_t addr; + cell_t len; + cell_t actual; + } args; + + args.name = ADR2CELL("read"); + args.nargs = 3; + args.nreturns = 1; + args.ihandle = HDL2CELL(handle); + args.addr = ADR2CELL(addr); + args.len = len; + if (openfirmware(&args) == -1) { + return -1; + } + return args.actual; +} + +int +OF_seek(handle, pos) + int handle; + u_quad_t pos; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t handle; + cell_t poshi; + cell_t poslo; + cell_t status; + } args; + + args.name = ADR2CELL("seek"); + args.nargs = 3; + args.nreturns = 1; + args.handle = HDL2CELL(handle); + args.poshi = HDL2CELL(pos >> 32); + args.poslo = HDL2CELL(pos); + if (openfirmware(&args) == -1) { + return -1; + } + return args.status; +} + +void +OF_release(virt, size) + void *virt; + u_int size; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t virt; + cell_t size; + } args; + + args.name = ADR2CELL("release"); + args.nargs = 2; + args.nreturns = 0; + args.virt = ADR2CELL(virt); + args.size = size; + openfirmware(&args); +} + +int +OF_milliseconds() +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t ms; + } args; + + args.name = ADR2CELL("milliseconds"); + args.nargs = 0; + args.nreturns = 1; + openfirmware(&args); + return args.ms; +} + +void +OF_chain(virt, size, entry, arg, len) + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; +{ + extern int64_t romp; + extern int debug; + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t virt; + cell_t size; + cell_t entry; + cell_t arg; + cell_t len; + } args; + + args.name = ADR2CELL("chain"); + args.nargs = 5; + args.nreturns = 0; + args.virt = ADR2CELL(virt); + args.size = size; + args.entry = ADR2CELL(entry); + args.arg = ADR2CELL(arg); + args.len = len; + openfirmware(&args); + if (debug) { + printf("OF_chain: prom returned!\n"); + + /* OK, firmware failed us. Try calling prog directly */ + printf("Calling entry(0, %p, %x, %lx, %lx)\n", arg, len, + (unsigned long)romp, (unsigned long)romp); + } + entry(0, arg, len, (unsigned long)romp, (unsigned long)romp); + panic("OF_chain: kernel returned!\n"); + __asm("ta 2" : :); +} + +static u_int stdin; +static u_int stdout; +static u_int mmuh = -1; +static u_int memh = -1; + +void +setup() +{ + u_int chosen; + + if ((chosen = OF_finddevice("/chosen")) == -1) + _rtt(); + if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) + || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout) + || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh) + || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh)) + _rtt(); +} + +/* + * The following need either the handle to memory or the handle to the MMU. + */ + +/* + * Grab some address space from the prom + * + * Only works while the prom is actively mapping us. + */ +vaddr_t +OF_claim_virt(vaddr, len) +vaddr_t vaddr; +int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t align; + cell_t len; + cell_t vaddr; + cell_t status; + cell_t retaddr; + } args; + +#ifdef __notyet + if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { + OF_printf("OF_claim_virt: cannot get mmuh\r\n"); + return -1LL; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 5; + args.nreturns = 2; + args.method = ADR2CELL("claim"); + args.ihandle = HDL2CELL(mmuh); + args.align = 0; + args.len = len; + args.vaddr = ADR2CELL(vaddr); + if(openfirmware(&args) != 0) + return -1LL; + return args.retaddr; /* Kluge till we go 64-bit */ +} + +/* + * Request some address space from the prom + * + * Only works while the prom is actively mapping us. + */ +vaddr_t +OF_alloc_virt(len, align) +int len; +int align; +{ + int retaddr=-1; + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t align; + cell_t len; + cell_t status; + cell_t retaddr; + } args; + +#ifdef __notyet + if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { + OF_printf("OF_alloc_virt: cannot get mmuh\r\n"); + return -1LL; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 4; + args.nreturns = 2; + args.method = ADR2CELL("claim"); + args.ihandle = mmuh; + args.align = align; + args.len = len; + args.retaddr = ADR2CELL(&retaddr); + if(openfirmware(&args) != 0) + return -1LL; + return (vaddr_t)args.retaddr; /* Kluge till we go 64-bit */ +} + +/* + * Release some address space to the prom + * + * Only works while the prom is actively mapping us. + */ +int +OF_free_virt(vaddr, len) +vaddr_t vaddr; +int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t len; + cell_t vaddr; + } args; + +#ifdef __notyet + if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { + OF_printf("OF_claim_virt: cannot get mmuh\r\n"); + return -1; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 4; + args.nreturns = 0; + args.method = ADR2CELL("release"); + args.ihandle = HDL2CELL(mmuh); + args.vaddr = ADR2CELL(vaddr); + args.len = len; + return openfirmware(&args); +} + + +/* + * Unmap some address space + * + * Only works while the prom is actively mapping us. + */ +int +OF_unmap_virt(vaddr, len) +vaddr_t vaddr; +int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t len; + cell_t vaddr; + } args; + +#ifdef __notyet + if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { + OF_printf("OF_claim_virt: cannot get mmuh\r\n"); + return -1; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 4; + args.nreturns = 0; + args.method = ADR2CELL("unmap"); + args.ihandle = HDL2CELL(mmuh); + args.vaddr = ADR2CELL(vaddr); + args.len = len; + return openfirmware(&args); +} + +/* + * Have prom map in some memory + * + * Only works while the prom is actively mapping us. + */ +vaddr_t +OF_map_phys(paddr, size, vaddr, mode) +paddr_t paddr; +off_t size; +vaddr_t vaddr; +int mode; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t mode; + cell_t size; + cell_t vaddr; + cell_t paddr_hi; + cell_t paddr_lo; + cell_t status; + cell_t retaddr; + } args; + +#ifdef __notyet + if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { + OF_printf("OF_map_phys: cannot get mmuh\r\n"); + return 0LL; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 7; + args.nreturns = 1; + args.method = ADR2CELL("map"); + args.ihandle = HDL2CELL(mmuh); + args.mode = mode; + args.size = size; + args.vaddr = ADR2CELL(vaddr); + args.paddr_hi = ADR2CELL(paddr>>32); + args.paddr_lo = ADR2CELL(paddr); + + if (openfirmware(&args) == -1) + return -1; + if (args.status) + return -1; + return (vaddr_t)args.retaddr; +} + + +/* + * Request some RAM from the prom + * + * Only works while the prom is actively mapping us. + */ +paddr_t +OF_alloc_phys(len, align) +int len; +int align; +{ + paddr_t paddr; + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t align; + cell_t len; + cell_t status; + cell_t phys_hi; + cell_t phys_lo; + } args; + +#ifdef __notyet + if (memh == -1 && ((memh = get_memory_handle()) == -1)) { + OF_printf("OF_alloc_phys: cannot get memh\r\n"); + return -1LL; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 4; + args.nreturns = 3; + args.method = ADR2CELL("claim"); + args.ihandle = HDL2CELL(memh); + args.align = align; + args.len = len; + if(openfirmware(&args) != 0) + return -1LL; + paddr = (paddr_t)(args.phys_hi<<32)|((unsigned int)(args.phys_lo)); + return paddr; /* Kluge till we go 64-bit */ +} + +/* + * Request some specific RAM from the prom + * + * Only works while the prom is actively mapping us. + */ +paddr_t +OF_claim_phys(phys, len) +paddr_t phys; +int len; +{ + paddr_t paddr; + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t align; + cell_t len; + cell_t phys_hi; + cell_t phys_lo; + cell_t status; + cell_t res; + cell_t rphys_hi; + cell_t rphys_lo; + } args; + +#ifdef __notyet + if (memh == -1 && ((memh = get_memory_handle()) == -1)) { + OF_printf("OF_alloc_phys: cannot get memh\r\n"); + return 0LL; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 6; + args.nreturns = 4; + args.method = ADR2CELL("claim"); + args.ihandle = HDL2CELL(memh); + args.align = 0; + args.len = len; + args.phys_hi = HDL2CELL(phys>>32); + args.phys_lo = HDL2CELL(phys); + if(openfirmware(&args) != 0) + return 0LL; + paddr = (paddr_t)(args.rphys_hi<<32)|((unsigned int)(args.rphys_lo)); + return paddr; +} + +/* + * Free some RAM to prom + * + * Only works while the prom is actively mapping us. + */ +int +OF_free_phys(phys, len) +paddr_t phys; +int len; +{ + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t method; + cell_t ihandle; + cell_t len; + cell_t phys_hi; + cell_t phys_lo; + } args; + +#ifdef __notyet + if (memh == -1 && ((memh = get_memory_handle()) == -1)) { + OF_printf("OF_free_phys: cannot get memh\r\n"); + return -1; + } +#endif + args.name = ADR2CELL("call-method"); + args.nargs = 5; + args.nreturns = 0; + args.method = ADR2CELL("release"); + args.ihandle = HDL2CELL(memh); + args.len = len; + args.phys_hi = HDL2CELL(phys>>32); + args.phys_lo = HDL2CELL(phys); + return openfirmware(&args); +} + + +/* + * Claim virtual memory -- does not map it in. + */ + +void * +OF_claim(virt, size, align) + void *virt; + u_int size; + u_int align; +{ +#define SUNVMOF +#ifndef SUNVMOF + struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t virt; + cell_t size; + cell_t align; + cell_t baseaddr; + } args; + + + args.name = ADR2CELL("claim"); + args.nargs = 3; + args.nreturns = 1; + args.virt = virt; + args.size = size; + args.align = align; + if (openfirmware(&args) == -1) + return (void *)-1; + return args.baseaddr; +#else +/* + * Sun Ultra machines run the firmware with VM enabled, + * so you need to handle allocating and mapping both + * virtual and physical memory. Ugh. + */ + + paddr_t paddr; + void* newvirt = NULL; + + if (virt == NULL) { + if ((virt = (void*)OF_alloc_virt(size, align)) == (void*)-1) { + printf("OF_alloc_virt(%d,%d) failed w/%x\n", size, align, virt); + return (void *)-1; + } + } else { + if ((newvirt = (void*)OF_claim_virt((vaddr_t)virt, size)) == (void*)-1) { + printf("OF_claim_virt(%x,%d) failed w/%x\n", virt, size, newvirt); + return (void *)-1; + } + } + if ((paddr = OF_alloc_phys(size, align)) == -1) { + printf("OF_alloc_phys(%d,%d) failed\n", size, align); + OF_free_virt((vaddr_t)virt, size); + return (void *)-1; + } + if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) { + printf("OF_map_phys(%x,%d,%x,%d) failed\n", paddr, size, virt, -1); + OF_free_phys((paddr_t)paddr, size); + OF_free_virt((vaddr_t)virt, size); + return (void *)-1; + } + return (void *)virt; +#endif +} + + +void +putchar(c) + int c; +{ + char ch = c; + + if (c == '\n') + putchar('\r'); + OF_write(stdout, &ch, 1); +} + +int +getchar() +{ + unsigned char ch = '\0'; + int l; + + while ((l = OF_read(stdin, &ch, 1)) != 1) + if (l != -2 && l != 0) + return -1; + return ch; +} diff --git a/sys/arch/sparc64/stand/ofwboot/Makefile b/sys/arch/sparc64/stand/ofwboot/Makefile new file mode 100644 index 00000000000..a25956891e0 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/Makefile @@ -0,0 +1,92 @@ +# $NetBSD: Makefile,v 1.2 2001/03/04 14:50:05 mrg Exp $ + +CURDIR= ${.CURDIR} +S= ${CURDIR}/../../../.. + +# +# Override normal settings +# + +WARNS= 0 + +PROG?= ofwboot +SRCS= srt0.s Locore.c boot.c ofdev.c alloc.c net.c netif_of.c vers.c +.PATH: ${S}/arch/sparc64/sparc64 + +CWARNFLAGS+= -Wno-main +CFLAGS+= ${COPTS} ${CEXTRAFLAGS} +CPPFLAGS+= -D_STANDALONE -DSUN4U +#CPPFLAGS+= -DNETIF_DEBUG + +MKMAN= no +STRIPFLAG= +BINMODE= 444 +OBJCOPY?= objcopy + +NEWVERSWHAT= "OpenFirmware Boot" + +# +# Elf64 defaults to 1MB +# +# We may get address conflicts with other bootloaders, say +# Sun's ufsboot, so we'll pick a reasonably empty address. +# +RELOC= 800000 + +ENTRY= _start + +CLEANFILES+= vers.c sparc machine + +CPPFLAGS+= -I${CURDIR}/../../.. -I${CURDIR}/../../../.. -I${CURDIR} -I. +CPPFLAGS+= -DRELOC=0x${RELOC} + +# +# XXXXX FIXME +# +CPPFLAGS+= -DSPARC_BOOT_AOUT +CPPFLAGS+= -DSPARC_BOOT_ELF +CPPFLAGS+= -DSPARC_BOOT_UFS +CPPFLAGS+= -DSPARC_BOOT_NFS +#CPPFLAGS+= -DSPARC_BOOT_HSFS + +.NOPATH: machine sparc64 +${SRCS}: machine sparc64 + +machine: + rm -f machine + ln -s sparc64 machine + +sparc64: + rm -f sparc64 + ln -s ${.CURDIR}/../../../sparc64/include sparc64 + +vers.c: version + sh ${S}/conf/newvers.sh ${CURDIR}/version "sparc64" ${NEWVERSWHAT} + +${PROG}: ${OBJS} ${LIBSA} ${LIBZ} ${LIBKERN} + ${LD} -N -p -Ttext ${RELOC} -e ${ENTRY} >lderr -o ${PROG} \ + ${OBJS} -L${LIBSADIR} ${LIBSA} -L${LIBKERNDIR} ${LIBKERN} \ + -L${LIBZDIR} ${LIBZ} + +.include <bsd.prog.mk> + +.if ${MACHINE_ARCH} == "sparc64" +AFLAGS+= -Wa,-Av9a +CEXTRAFLAGS?= -D_LP64 +.else +AFLAGS+= -Wa,-Av8plusa +.endif + +.if CROSS +AFLAGS+= -x assembler-with-cpp -traditional-cpp -D_LOCORE -D__ELF__ +CEXTRAFLAGS?= -D_LP64 +.else +AFLAGS+= -x assembler-with-cpp -traditional-cpp -D_LOCORE -D__ELF__ ${CEXTRAFLAGS} +.endif + +NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< +srt0.o: srt0.s + ${NORMAL_S} + +# Explicit dependency for this. +boot.o: boot.c elfXX_exec.c diff --git a/sys/arch/sparc64/stand/ofwboot/alloc.c b/sys/arch/sparc64/stand/ofwboot/alloc.c new file mode 100644 index 00000000000..161cd1129e6 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/alloc.c @@ -0,0 +1,214 @@ +/* $NetBSD: alloc.c,v 1.1 2000/08/20 14:58:37 mrg Exp $ */ + +/* + * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. + * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * Dynamic memory allocator suitable for use with OpenFirmware. + * + * Compile options: + * + * ALLOC_TRACE enable tracing of allocations/deallocations + * + * ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than + * the default best-fit algorithm. + * + * DEBUG enable debugging sanity checks. + */ + +#include <sys/param.h> +#include <sys/queue.h> + +#include <lib/libsa/stand.h> + +#include "openfirm.h" + +/* + * Each block actually has ALIGN(struct ml) + ALIGN(size) bytes allocated + * to it, as follows: + * + * 0 ... (sizeof(struct ml) - 1) + * allocated or unallocated: holds size of user-data part of block. + * + * sizeof(struct ml) ... (ALIGN(sizeof(struct ml)) - 1) + * allocated: unused + * unallocated: depends on packing of struct fl + * + * ALIGN(sizeof(struct ml)) ... (ALIGN(sizeof(struct ml)) + + * ALIGN(data size) - 1) + * allocated: user data + * unallocated: depends on packing of struct fl + * + * 'next' is only used when the block is unallocated (i.e. on the free list). + * However, note that ALIGN(sizeof(struct ml)) + ALIGN(data size) must + * be at least 'sizeof(struct fl)', so that blocks can be used as structures + * when on the free list. + */ + +/* + * Memory lists. + */ +struct ml { + unsigned size; + LIST_ENTRY(ml) list; +}; + +LIST_HEAD(, ml) freelist = LIST_HEAD_INITIALIZER(freelist); +LIST_HEAD(, ml) allocatedlist = LIST_HEAD_INITIALIZER(allocatedlist); + +#define OVERHEAD ALIGN(sizeof (struct ml)) /* shorthand */ + +void * +alloc(size) + unsigned size; +{ + struct ml *f, *bestf; + unsigned bestsize = 0xffffffff; /* greater than any real size */ + char *help; + int failed; + +#ifdef ALLOC_TRACE + printf("alloc(%u)", size); +#endif + + /* + * Account for overhead now, so that we don't get an + * "exact fit" which doesn't have enough space. + */ + size = ALIGN(size) + OVERHEAD; + +#ifdef ALLOC_FIRST_FIT + /* scan freelist */ + for (f = freelist.lh_first; f != NULL && f->size < size; + f = f->list.le_next) + /* noop */ ; + bestf = f; + failed = (bestf == (struct fl *)0); +#else + /* scan freelist */ + f = freelist.lh_first; + while (f != NULL) { + if (f->size >= size) { + if (f->size == size) /* exact match */ + goto found; + + if (f->size < bestsize) { + /* keep best fit */ + bestf = f; + bestsize = f->size; + } + } + f = f->list.le_next; + } + + /* no match in freelist if bestsize unchanged */ + failed = (bestsize == 0xffffffff); +#endif + + if (failed) { /* nothing found */ + /* + * Allocate memory from the OpenFirmware, rounded + * to page size, and record the chunk size. + */ + size = roundup(size, NBPG); + help = OF_claim(0, size, NBPG); + if (help == (char *)-1) + panic("alloc: out of memory"); + + f = (struct ml *)help; + f->size = size; +#ifdef ALLOC_TRACE + printf("=%lx (new chunk size %u)\n", + (u_long)(help + OVERHEAD), f->size); +#endif + goto out; + } + + /* we take the best fit */ + f = bestf; + + found: + /* remove from freelist */ + LIST_REMOVE(f, list); + help = (char *)f; +#ifdef ALLOC_TRACE + printf("=%lx (origsize %u)\n", (u_long)(help + OVERHEAD), f->size); +#endif + out: + /* place on allocated list */ + LIST_INSERT_HEAD(&allocatedlist, f, list); + return (help + OVERHEAD); +} + +void +free(ptr, size) + void *ptr; + unsigned size; /* only for consistenct check */ +{ + register struct ml *a = (struct ml *)((char*)ptr - OVERHEAD); + +#ifdef ALLOC_TRACE + printf("free(%lx, %u) (origsize %u)\n", (u_long)ptr, size, a->size); +#endif +#ifdef DEBUG + if (size > a->size) + printf("free %u bytes @%lx, should be <=%u\n", + size, (u_long)ptr, a->size); +#endif + + /* Remove from allocated list, place on freelist. */ + LIST_REMOVE(a, list); + LIST_INSERT_HEAD(&freelist, a, list); +} + +void +freeall() +{ +#ifdef __notyet__ /* Firmware bug ?! */ + struct ml *m; + + /* Release chunks on freelist... */ + while ((m = freelist.lh_first) != NULL) { + LIST_REMOVE(m, list); + OF_release(m, m->size); + } + + /* ...and allocated list. */ + while ((m = allocatedlist.lh_first) != NULL) { + LIST_REMOVE(m, list); + OF_release(m, m->size); + } +#endif /* __notyet__ */ +} diff --git a/sys/arch/sparc64/stand/ofwboot/boot.c b/sys/arch/sparc64/stand/ofwboot/boot.c new file mode 100644 index 00000000000..ff7f3820bb0 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/boot.c @@ -0,0 +1,623 @@ +/* $NetBSD: boot.c,v 1.3 2001/05/31 08:55:19 mrg Exp $ */ +#define DEBUG +/* + * Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved. + * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * ELF support derived from NetBSD/alpha's boot loader, written + * by Christopher G. Demetriou. + * + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * First try for the boot code + * + * Input syntax is: + * [promdev[{:|,}partition]]/[filename] [flags] + */ + +#ifdef ELFSIZE +#undef ELFSIZE /* We use both. */ +#endif + +#include <lib/libsa/stand.h> + +#include <sys/param.h> +#include <sys/exec.h> +#include <sys/exec_elf.h> +#include <sys/reboot.h> +#include <sys/disklabel.h> +#include <machine/boot_flag.h> + +#include <machine/cpu.h> + +#include "ofdev.h" +#include "openfirm.h" + +#define MEG (1024*1024) + +/* + * Boot device is derived from ROM provided information, or if there is none, + * this list is used in sequence, to find a kernel. + */ +char *kernels[] = { + "netbsd ", + "netbsd.gz ", + "netbsd.old ", + "netbsd.old.gz ", + "onetbsd ", + "onetbsd.gz ", + "vmunix ", +#ifdef notyet + "netbsd.pl ", + "netbsd.pl.gz ", + "netbsd.el ", + "netbsd.el.gz ", +#endif + NULL +}; + +char *kernelname; +char bootdev[128]; +char bootfile[128]; +int boothowto; +int debug; + + +#ifdef SPARC_BOOT_ELF +int elf32_exec __P((int, Elf32_Ehdr *, u_int64_t *, void **, void **)); +int elf64_exec __P((int, Elf64_Ehdr *, u_int64_t *, void **, void **)); +#endif + +#ifdef SPARC_BOOT_AOUT +int aout_exec __P((int, struct exec *, u_int64_t *, void **)); +#endif + +#if 0 +static void +prom2boot(dev) + char *dev; +{ + char *cp, *lp = 0; + int handle; + char devtype[16]; + + for (cp = dev; *cp; cp++) + if (*cp == ':') + lp = cp; + if (!lp) + lp = cp; + *lp = 0; +} +#endif + +static void +parseargs(str, howtop) + char *str; + int *howtop; +{ + char *cp; + int i; + + /* Allow user to drop back to the PROM. */ + if (strcmp(str, "exit") == 0 || strcmp(str, "halt") == 0) + _rtt(); + + /* Insert the kernel name if it is not there. */ + if (str[0] == 0 || str[0] == '-') { + /* Move args down the string */ + i=0; + for (cp = str + strlen(kernelname); str[i]; i++) + cp[i] = str[i]; + /* Copy over kernelname */ + for (i = 0; kernelname[i]; i++) + str[i] = kernelname[i]; + } + *howtop = 0; + for (cp = str; *cp; cp++) + if (*cp == ' ' || *cp == '-') + break; + if (!*cp) + return; + + *cp++ = 0; + while (*cp) { + BOOT_FLAG(*cp, *howtop); + /* handle specialties */ + switch (*cp++) { + case 'd': + if (!debug) debug = 1; + break; + case 'D': + debug = 2; + break; + default: + break; + } + } +} + + +static void +chain(pentry, args, ssym, esym) + u_int64_t pentry; + char *args; + void *ssym; + void *esym; +{ + extern char end[]; + void (*entry)(); + int l, machine_tag; + long newargs[3]; + + entry = (void*)(long)pentry; + + freeall(); + /* + * When we come in args consists of a pointer to the boot + * string. We need to fix it so it takes into account + * other params such as romp. + */ + + /* + * Stash pointer to end of symbol table after the argument + * strings. + */ + l = strlen(args) + 1; + bcopy(&esym, args + l, sizeof(esym)); + l += sizeof(esym); + + /* + * Tell the kernel we're an OpenFirmware system. + */ +#define SPARC_MACHINE_OPENFIRMWARE 0x44444230 + machine_tag = SPARC_MACHINE_OPENFIRMWARE; + bcopy(&machine_tag, args + l, sizeof(machine_tag)); + l += sizeof(machine_tag); + + /* + * Since we don't need the boot string (we can get it from /chosen) + * we won't pass it in. Just pass in esym and magic # + */ + newargs[0] = SPARC_MACHINE_OPENFIRMWARE; + newargs[1] = (long)esym; + newargs[2] = (long)ssym; + args = (char *)newargs; + l = sizeof(newargs); + +#ifdef DEBUG + printf("chain: calling OF_chain(%x, %x, %x, %x, %x)\n", + (void *)RELOC, end - (char *)RELOC, entry, args, l); +#endif + /* if -D is set then pause in the PROM. */ + if (debug > 1) OF_enter(); + OF_chain((void *)RELOC, ((end - (char *)RELOC)+NBPG)%NBPG, entry, args, l); + panic("chain"); +} + +int +loadfile(fd, args) + int fd; + char *args; +{ + union { +#ifdef SPARC_BOOT_AOUT + struct exec aout; +#endif +#ifdef SPARC_BOOT_ELF + Elf32_Ehdr elf32; + Elf64_Ehdr elf64; +#endif + } hdr; + int rval; + u_int64_t entry = 0; + void *ssym; + void *esym; + + rval = 1; + ssym = NULL; + esym = NULL; + + /* Load the header. */ +#ifdef DEBUG + printf("loadfile: reading header\n"); +#endif + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + printf("read header: %s\n", strerror(errno)); + goto err; + } + + /* Determine file type, load kernel. */ +#ifdef SPARC_BOOT_AOUT + if (N_BADMAG(hdr.aout) == 0 && N_GETMID(hdr.aout) == MID_SPARC) { + rval = aout_exec(fd, &hdr.aout, &entry, &esym); + } else +#endif +#ifdef SPARC_BOOT_ELF + if (bcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { + rval = elf32_exec(fd, &hdr.elf32, &entry, &ssym, &esym); + } else + if (bcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) { + rval = elf64_exec(fd, &hdr.elf64, &entry, &ssym, &esym); + } else +#endif + { + printf("unknown executable format\n"); + } + + if (rval) + goto err; + + printf(" start=0x%lx\n", (unsigned long)entry); + + close(fd); + + /* XXX this should be replaced w/ a mountroothook. */ + if (floppyboot) { + printf("Please insert root disk and press ENTER "); + getchar(); + printf("\n"); + } + + chain(entry, args, ssym, esym); + /* NOTREACHED */ + + err: + close(fd); + return (rval); +} + +#ifdef SPARC_BOOT_AOUT +int +aout_exec(fd, hdr, entryp, esymp) + int fd; + struct exec *hdr; + u_int64_t *entryp; + void **esymp; +{ + void *addr; + int n, *paddr; + +#ifdef DEBUG + printf("auout_exec: "); +#endif + /* Display the load address (entry point) for a.out. */ + printf("Booting %s @ 0x%lx\n", opened_name, hdr->a_entry); + addr = (void *)((u_int64_t)hdr->a_entry); + + /* + * Determine memory needed for kernel and allocate it from + * the firmware. + */ + n = hdr->a_text + hdr->a_data + hdr->a_bss + hdr->a_syms + sizeof(int); + if ((paddr = OF_claim(addr, n, 0)) == (int *)-1) + panic("cannot claim memory"); + + /* Load text. */ + lseek(fd, N_TXTOFF(*hdr), SEEK_SET); + printf("%lu", hdr->a_text); + if (read(fd, paddr, hdr->a_text) != hdr->a_text) { + printf("read text: %s\n", strerror(errno)); + return (1); + } + syncicache((void *)paddr, hdr->a_text); + + /* Load data. */ + printf("+%lu", hdr->a_data); + if (read(fd, (void *)paddr + hdr->a_text, hdr->a_data) != hdr->a_data) { + printf("read data: %s\n", strerror(errno)); + return (1); + } + + /* Zero BSS. */ + printf("+%lu", hdr->a_bss); + bzero((void *)paddr + hdr->a_text + hdr->a_data, hdr->a_bss); + + /* Symbols. */ + *esymp = paddr; + paddr = (int *)((void *)paddr + hdr->a_text + hdr->a_data + hdr->a_bss); + *paddr++ = hdr->a_syms; + if (hdr->a_syms) { + printf(" [%lu", hdr->a_syms); + if (read(fd, paddr, hdr->a_syms) != hdr->a_syms) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + paddr = (int *)((void *)paddr + hdr->a_syms); + if (read(fd, &n, sizeof(int)) != sizeof(int)) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + if (OF_claim((void *)paddr, n + sizeof(int), 0) == (void *)-1) + panic("cannot claim memory"); + *paddr++ = n; + if (read(fd, paddr, n - sizeof(int)) != n - sizeof(int)) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + printf("+%d]", n - sizeof(int)); + *esymp = paddr + (n - sizeof(int)); + } + + *entryp = hdr->a_entry; + return (0); +} +#endif /* SPARC_BOOT_AOUT */ + +#ifdef SPARC_BOOT_ELF +#if 1 +/* New style */ + +#ifdef ELFSIZE +#undef ELFSIZE +#endif + +#define ELFSIZE 32 +#include "elfXX_exec.c" + +#undef ELFSIZE +#define ELFSIZE 64 +#include "elfXX_exec.c" + +#else +/* Old style */ +int +elf32_exec(fd, elf, entryp, ssymp, esymp) + int fd; + Elf32_Ehdr *elf; + u_int64_t *entryp; + void **ssymp; + void **esymp; +{ + Elf32_Shdr *shp; + Elf32_Off off; + void *addr; + size_t size; + int i, first = 1; + long align; + int n; + + /* + * Don't display load address for ELF; it's encoded in + * each section. + */ +#ifdef DEBUG + printf("elf_exec: "); +#endif + printf("Booting %s\n", opened_name); + + for (i = 0; i < elf->e_phnum; i++) { + Elf32_Phdr phdr; + (void)lseek(fd, elf->e_phoff + sizeof(phdr) * i, SEEK_SET); + if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { + printf("read phdr: %s\n", strerror(errno)); + return (1); + } + if (phdr.p_type != PT_LOAD || + (phdr.p_flags & (PF_W|PF_X)) == 0) + continue; + + /* Read in segment. */ + printf("%s%lu@0x%lx", first ? "" : "+", phdr.p_filesz, + (u_long)phdr.p_vaddr); + (void)lseek(fd, phdr.p_offset, SEEK_SET); + + /* + * If the segment's VA is aligned on a 4MB boundary, align its + * request 4MB aligned physical memory. Otherwise use default + * alignment. + */ + align = phdr.p_align; + if ((phdr.p_vaddr & (4*MEG-1)) == 0) + align = 4*MEG; + if (OF_claim((void *)phdr.p_vaddr, phdr.p_memsz, phdr.p_align) == + (void *)-1) + panic("cannot claim memory"); + if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) != + phdr.p_filesz) { + printf("read segment: %s\n", strerror(errno)); + return (1); + } + syncicache((void *)phdr.p_vaddr, phdr.p_filesz); + + /* Zero BSS. */ + if (phdr.p_filesz < phdr.p_memsz) { + printf("+%lu@0x%lx", phdr.p_memsz - phdr.p_filesz, + (u_long)(phdr.p_vaddr + phdr.p_filesz)); + bzero((void*)phdr.p_vaddr + phdr.p_filesz, + phdr.p_memsz - phdr.p_filesz); + } + first = 0; + } + + printf(" \n"); + +#if 1 /* I want to rethink this... --thorpej@netbsd.org */ + /* + * Compute the size of the symbol table. + */ + size = sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); + shp = addr = alloc(elf->e_shnum * sizeof(Elf32_Shdr)); + (void)lseek(fd, elf->e_shoff, SEEK_SET); + if (read(fd, addr, elf->e_shnum * sizeof(Elf32_Shdr)) != + elf->e_shnum * sizeof(Elf32_Shdr)) { + printf("read section headers: %s\n", strerror(errno)); + return (1); + } + for (i = 0; i < elf->e_shnum; i++, shp++) { + if (shp->sh_type == SHT_NULL) + continue; + if (shp->sh_type != SHT_SYMTAB + && shp->sh_type != SHT_STRTAB) { + shp->sh_offset = 0; + shp->sh_type = SHT_NOBITS; + continue; + } + size += shp->sh_size; + } + shp = addr; + + /* + * Reserve memory for the symbols. + */ + if ((addr = OF_claim(0, size, NBPG)) == (void *)-1) + panic("no space for symbol table"); + + /* + * Copy the headers. + */ + elf->e_phoff = 0; + elf->e_shoff = sizeof(Elf32_Ehdr); + elf->e_phentsize = 0; + elf->e_phnum = 0; + bcopy(elf, addr, sizeof(Elf32_Ehdr)); + bcopy(shp, addr + sizeof(Elf32_Ehdr), elf->e_shnum * sizeof(Elf32_Shdr)); + free(shp, elf->e_shnum * sizeof(Elf32_Shdr)); + *ssymp = addr; + + /* + * Now load the symbol sections themselves. + */ + shp = addr + sizeof(Elf32_Ehdr); + addr += sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); + off = sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr)); + for (first = 1, i = 0; i < elf->e_shnum; i++, shp++) { + if (shp->sh_type == SHT_SYMTAB + || shp->sh_type == SHT_STRTAB) { + if (first) + printf("symbols @ 0x%lx ", (u_long)addr); + printf("%s%d", first ? "" : "+", shp->sh_size); + (void)lseek(fd, shp->sh_offset, SEEK_SET); + if (read(fd, addr, shp->sh_size) != shp->sh_size) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + addr += (shp->sh_size+3)&(~3); + shp->sh_offset = off; + off += (shp->sh_size+3)&(~3); + first = 0; + } + } + *esymp = addr; +#endif /* 0 */ + + *entryp = elf->e_entry; + return (0); +} +#endif +#endif /* SPARC_BOOT_ELF */ + +void +main() +{ + extern char version[]; + int chosen; + char bootline[512]; /* Should check size? */ + char *cp; + int i, fd; + + /* Initialize kernelname */ + kernelname = kernels[0]; + + printf(">> %s", version); + + /* + * Get the boot arguments from Openfirmware + */ + if ((chosen = OF_finddevice("/chosen")) == -1 + || OF_getprop(chosen, "bootpath", bootdev, sizeof bootdev) < 0 + || OF_getprop(chosen, "bootargs", bootline, sizeof bootline) < 0) { + printf("Invalid Openfirmware environment\n"); + exit(); + } + /*prom2boot(bootdev);*/ + kernelname = kernels[0]; + parseargs(bootline, &boothowto); + for (i=0;;) { + kernelname = kernels[i]; + if (boothowto & RB_ASKNAME) { + printf("Boot: "); + gets(bootline); + parseargs(bootline, &boothowto); + } + if ((fd = open(bootline, 0)) >= 0) + break; + if (errno) + printf("open %s: %s\n", opened_name, strerror(errno)); + /* + * if we have are not in askname mode, and we aren't using the + * prom bootfile, try the next one (if it exits). otherwise, + * go into askname mode. + */ + if ((boothowto & RB_ASKNAME) == 0 && + i != -1 && kernels[++i]) { + printf(": trying %s...\n", kernels[i]); + } else { + printf("\n"); + boothowto |= RB_ASKNAME; + } + } +#ifdef __notyet__ + OF_setprop(chosen, "bootpath", opened_name, strlen(opened_name) + 1); + cp = bootline; +#else + strcpy(bootline, opened_name); + cp = bootline + strlen(bootline); + *cp++ = ' '; +#endif + *cp = '-'; + if (boothowto & RB_ASKNAME) + *++cp = 'a'; + if (boothowto & RB_SINGLE) + *++cp = 's'; + if (boothowto & RB_KDB) + *++cp = 'd'; + if (*cp == '-') +#ifdef __notyet__ + *cp = 0; +#else + *--cp = 0; +#endif + else + *++cp = 0; +#ifdef __notyet__ + OF_setprop(chosen, "bootargs", bootline, strlen(bootline) + 1); +#endif + /* XXX void, for now */ +#ifdef DEBUG + if (debug) + printf("main: Calling loadfile(fd, %s)\n", bootline); +#endif + (void)loadfile(fd, bootline); + + _rtt(); +} diff --git a/sys/arch/sparc64/stand/ofwboot/elfXX_exec.c b/sys/arch/sparc64/stand/ofwboot/elfXX_exec.c new file mode 100644 index 00000000000..076dbc5e812 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/elfXX_exec.c @@ -0,0 +1,208 @@ +/* $NetBSD: elfXX_exec.c,v 1.2 2001/08/15 20:08:15 eeh Exp $ */ + +/* + * Copyright (c) 1998-2000 Eduardo Horvath. All rights reserved. + * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * ELF support derived from NetBSD/alpha's boot loader, written + * by Christopher G. Demetriou. + * + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * First try for the boot code + * + * Input syntax is: + * [promdev[{:|,}partition]]/[filename] [flags] + */ + +#define CONCAT(x,y) __CONCAT(x,y) +#define CAT3(s,m,e) CONCAT(s,CONCAT(m,e)) +#define MEG (1024*1024) + +#if 0 +int CAT3(elf,ELFSIZE,_exec) __P((int, CAT3(Elf,ELFSIZE,_Ehdr) *, u_int64_t *, void **, void **)); +#endif +#if defined(ELFSIZE) && (ELFSIZE == 32) +#define ELF_ALIGN(x) (((x)+3)&(~3)) +#elif defined(ELFSIZE) && (ELFSIZE == 64) +#define ELF_ALIGN(x) (((x)+7)&(~7)) +#else +#error ELFSIZE must be either 32 or 64! +#endif + +int +CAT3(elf, ELFSIZE, _exec)(fd, elf, entryp, ssymp, esymp) + int fd; + CAT3(Elf,ELFSIZE,_Ehdr) *elf; + u_int64_t *entryp; + void **ssymp; + void **esymp; +{ + CAT3(Elf,ELFSIZE,_Shdr) *shp; + CAT3(Elf,ELFSIZE,_Off) off; + void *addr; + size_t size; + u_int align; + int i, first = 1; + int n; + + /* + * Don't display load address for ELF; it's encoded in + * each section. + */ +#ifdef DEBUG + printf("elf%d_exec: ", ELFSIZE); +#endif + printf("Booting %s\n", opened_name); + + for (i = 0; i < elf->e_phnum; i++) { + CAT3(Elf,ELFSIZE,_Phdr) phdr; + size = lseek(fd, (size_t)(elf->e_phoff + sizeof(phdr) * i), SEEK_SET); + if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { + printf("read phdr: %s\n", strerror(errno)); + return (1); + } + if (phdr.p_type != PT_LOAD || + (phdr.p_flags & (PF_W|PF_X)) == 0) + continue; + + /* Read in segment. */ + printf("%s%lu@0x%lx", first ? "" : "+", (u_long)phdr.p_filesz, + (u_long)phdr.p_vaddr); + (void)lseek(fd, (size_t)phdr.p_offset, SEEK_SET); + /* + * If the segment's VA is aligned on a 4MB boundary, align its + * request 4MB aligned physical memory. Otherwise use default + * alignment. Make sure BSS is extended to a 4MB boundary, too. + */ + align = phdr.p_align; + if ((phdr.p_vaddr & (4*MEG-1)) == 0) + align = 4*MEG; + if (phdr.p_filesz < phdr.p_memsz) + phdr.p_memsz = 4*MEG; + if (OF_claim((void *)(long)phdr.p_vaddr, phdr.p_memsz, align) == + (void *)-1) + panic("cannot claim memory"); + if (read(fd, (void *)(long)phdr.p_vaddr, phdr.p_filesz) != + phdr.p_filesz) { + printf("read segment: %s\n", strerror(errno)); + return (1); + } + syncicache((void *)(long)phdr.p_vaddr, phdr.p_filesz); + + /* Zero BSS. */ + if (phdr.p_filesz < phdr.p_memsz) { + printf("+%lu@0x%lx", (u_long)phdr.p_memsz - phdr.p_filesz, + (u_long)(phdr.p_vaddr + phdr.p_filesz)); + bzero((void*)(long)phdr.p_vaddr + phdr.p_filesz, + (size_t)phdr.p_memsz - phdr.p_filesz); + } + first = 0; + } + + printf(" \n"); + + /* + * Compute the size of the symbol table. + */ + size = sizeof(CAT3(Elf,ELFSIZE,_Ehdr)) + (elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr))); + shp = addr = alloc(elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr))); + (void)lseek(fd, (off_t)elf->e_shoff, SEEK_SET); + if (read(fd, addr, (size_t)(elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr)))) != + elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr))) { + printf("read section headers: %s\n", strerror(errno)); + return (1); + } + for (i = 0; i < elf->e_shnum; i++, shp++) { + if (shp->sh_type == SHT_NULL) + continue; + if (shp->sh_type != SHT_SYMTAB + && shp->sh_type != SHT_STRTAB) { + shp->sh_offset = 0; + shp->sh_type = SHT_NOBITS; + continue; + } + size += shp->sh_size; + } + shp = addr; + + /* + * Reserve memory for the symbols. + */ + if ((addr = OF_claim(0, size, NBPG)) == (void *)-1) + panic("no space for symbol table"); + + /* + * Copy the headers. + */ + elf->e_phoff = 0; + elf->e_shoff = sizeof(CAT3(Elf,ELFSIZE,_Ehdr)); + elf->e_phentsize = 0; + elf->e_phnum = 0; + bcopy(elf, addr, sizeof(CAT3(Elf,ELFSIZE,_Ehdr))); + bcopy(shp, addr + sizeof(CAT3(Elf,ELFSIZE,_Ehdr)), + elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr))); + free(shp, elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr))); + *ssymp = addr; + + /* + * Now load the symbol sections themselves. + */ + shp = addr + sizeof(CAT3(Elf,ELFSIZE,_Ehdr)); + size = sizeof(CAT3(Elf,ELFSIZE,_Ehdr)) + + (elf->e_shnum * sizeof(CAT3(Elf,ELFSIZE,_Shdr))); + size = ELF_ALIGN(size); + addr += size; + off = size; + for (first = 1, i = 0; i < elf->e_shnum; i++, shp++) { + if (shp->sh_type == SHT_SYMTAB + || shp->sh_type == SHT_STRTAB) { + if (first) + printf("symbols @ 0x%lx ", (u_long)addr); + printf("%s%d", first ? "" : "+", (int)shp->sh_size); + (void)lseek(fd, shp->sh_offset, SEEK_SET); + if (read(fd, addr, shp->sh_size) != shp->sh_size) { + printf("read symbols: %s\n", strerror(errno)); + return (1); + } + addr += ELF_ALIGN(shp->sh_size); + shp->sh_offset = off; + off += ELF_ALIGN(shp->sh_size); + first = 0; + } + } + *esymp = addr; + + *entryp = elf->e_entry; + return (0); +} + +#undef ELF_ALIGN diff --git a/sys/arch/sparc64/stand/ofwboot/md5.h b/sys/arch/sparc64/stand/ofwboot/md5.h new file mode 100644 index 00000000000..77ffc77c6ed --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/md5.h @@ -0,0 +1,55 @@ +/* $NetBSD: md5.h,v 1.1 2000/08/20 14:58:38 mrg Exp $ */ + +/* + * This file is derived from the RSA Data Security, Inc. MD5 Message-Digest + * Algorithm and has been modified by Jason R. Thorpe <thorpej@NetBSD.ORG> + * for portability and formatting. + */ + +/* + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +#ifndef _SYS_MD5_H_ +#define _SYS_MD5_H_ + +#include <sys/types.h> + +/* MD5 context. */ +typedef struct MD5Context { + u_int32_t state[4]; /* state (ABCD) */ + u_int32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +__BEGIN_DECLS +void MD5Init __P((MD5_CTX *)); +void MD5Update __P((MD5_CTX *, const unsigned char *, unsigned int)); +void MD5Final __P((unsigned char[16], MD5_CTX *)); +#ifndef _KERNEL +char *MD5End __P((MD5_CTX *, char *)); +char *MD5File __P((const char *, char *)); +char *MD5Data __P((const unsigned char *, unsigned int, char *)); +#endif /* _KERNEL */ +__END_DECLS + +#endif /* _SYS_MD5_H_ */ diff --git a/sys/arch/sparc64/stand/ofwboot/net.c b/sys/arch/sparc64/stand/ofwboot/net.c new file mode 100644 index 00000000000..b9260681fac --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/net.c @@ -0,0 +1,194 @@ +/* $NetBSD: net.c,v 1.1 2000/08/20 14:58:38 mrg Exp $ */ + +/* + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * This module implements a "raw device" interface suitable for + * use by the stand-alone I/O library NFS code. This interface + * does not support any "block" access, and exists only for the + * purpose of initializing the network interface, getting boot + * parameters, and performing the NFS mount. + * + * At open time, this does: + * + * find interface - netif_open() + * BOOTP - bootp() + * RPC/mountd - nfs_mount() + * + * The root file handle from mountd is saved in a global + * for use by the NFS open code (NFS/lookup). + * + * Note: this is based in part on sys/arch/sparc/stand/net.c + */ + +#include <sys/param.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> + +#include <lib/libsa/stand.h> +#include <lib/libsa/net.h> +#include <lib/libsa/netif.h> + + +static int net_mountroot_bootparams __P((void)); +static int net_mountroot_bootp __P((void)); + +char rootpath[FNAME_SIZE]; + +static int netdev_sock = -1; +static int open_count; + +/* + * Called by devopen after it sets f->f_dev to our devsw entry. + * This opens the low-level device and sets f->f_devdata. + */ +int +net_open(op) + struct of_dev *op; +{ + int error = 0; + + /* + * On first open, do netif open, mount, etc. + */ + if (open_count == 0) { + /* Find network interface. */ + if ((netdev_sock = netif_open(op)) < 0) { + error = errno; + goto bad; + } + if ((error = net_mountroot()) != 0) + goto bad; + } + open_count++; +bad: + if (netdev_sock >= 0 && open_count == 0) { + netif_close(netdev_sock); + netdev_sock = -1; + } + return error; +} + +int +net_close(op) + struct of_dev *op; +{ + /* + * On last close, do netif close, etc. + */ + if (open_count > 0) + if (--open_count == 0) { + netif_close(netdev_sock); + netdev_sock = -1; + } +} + +int +net_mountroot_bootparams() +{ + /* Get our IP address. (rarp.c) */ + if (rarp_getipaddress(netdev_sock) == -1) + return (errno); + + printf("Using BOOTPARAMS protocol: "); + printf("ip address: %s", inet_ntoa(myip)); + + /* Get our hostname, server IP address. */ + if (bp_whoami(netdev_sock)) + return (errno); + + printf(", hostname: %s\n", hostname); + + /* Get the root pathname. */ + if (bp_getfile(netdev_sock, "root", &rootip, rootpath)) + return (errno); + + return (0); +} + +int +net_mountroot_bootp() +{ + bootp(netdev_sock); + + if (myip.s_addr == 0) + return(ENOENT); + + printf("Using BOOTP protocol: "); + printf("ip address: %s", inet_ntoa(myip)); + + if (hostname[0]) + printf(", hostname: %s", hostname); + if (netmask) + printf(", netmask: %s", intoa(netmask)); + if (gateip.s_addr) + printf(", gateway: %s", inet_ntoa(gateip)); + printf("\n"); + + return (0); +} + +int +net_mountroot() +{ + int error; + +#ifdef DEBUG + printf("net_mountroot\n"); +#endif + + /* + * Get info for NFS boot: our IP address, our hostname, + * server IP address, and our root path on the server. + * There are two ways to do this: The old, Sun way, + * and the more modern, BOOTP way. (RFC951, RFC1048) + */ + + /* Historically, we've used BOOTPARAMS, so try that first */ + error = net_mountroot_bootparams(); + if (error != 0) + /* Next, try BOOTP */ + error = net_mountroot_bootp(); + if (error != 0) + return (error); + + printf("root addr=%s path=%s\n", inet_ntoa(rootip), rootpath); + + /* Get the NFS file handle (mount). */ + if (nfs_mount(netdev_sock, rootip, rootpath) != 0) + return (errno); + + return (0); +} diff --git a/sys/arch/sparc64/stand/ofwboot/netif_of.c b/sys/arch/sparc64/stand/ofwboot/netif_of.c new file mode 100644 index 00000000000..e5d02bdf297 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/netif_of.c @@ -0,0 +1,240 @@ +/* $NetBSD: netif_of.c,v 1.1 2000/08/20 14:58:39 mrg Exp $ */ + +/* + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * Open Firmware does most of the job for interfacing to the hardware, + * so it is easiest to just replace the netif module with + * this adaptation to the PROM network interface. + * + * Note: this is based in part on sys/arch/sparc/stand/netif_sun.c + */ + +#include <sys/param.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_ether.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> + +#include <lib/libsa/stand.h> +#include <lib/libsa/net.h> +#include <lib/libsa/netif.h> + +#include "ofdev.h" +#include "openfirm.h" + +static struct netif netif_of; + +struct iodesc sockets[SOPEN_MAX]; + +struct iodesc * +socktodesc(sock) + int sock; +{ + if (sock != 0) + return NULL; + return sockets; +} + +int +netif_open(machdep_hint) + void *machdep_hint; +{ + struct of_dev *op = machdep_hint; + struct iodesc *io; + int fd, error; + char addr[32]; + +#ifdef NETIF_DEBUG + printf("netif_open..."); +#endif + /* find a free socket */ + io = sockets; + if (io->io_netif) { +#ifdef NETIF_DEBUG + printf("device busy\n"); +#endif + errno = ENFILE; + return -1; + } + bzero(io, sizeof *io); + + netif_of.nif_devdata = op; + io->io_netif = &netif_of; + + /* Put our ethernet address in io->myea */ + OF_getprop(OF_instance_to_package(op->handle), + "mac-address", io->myea, sizeof io->myea); + +#ifdef NETIF_DEBUG + printf("OK\n"); +#endif + return 0; +} + +int +netif_close(fd) + int fd; +{ + struct iodesc *io; + struct netif *ni; + +#ifdef NETIF_DEBUG + printf("netif_close(%x)...", fd); +#endif + if (fd != 0) { +#ifdef NETIF_DEBUG + printf("EBADF\n"); +#endif + errno = EBADF; + return -1; + } + + io = &sockets[fd]; + ni = io->io_netif; + if (ni != NULL) { + ni->nif_devdata = NULL; + io->io_netif = NULL; + } +#ifdef NETIF_DEBUG + printf("OK\n"); +#endif + return 0; +} + +/* + * Send a packet. The ether header is already there. + * Return the length sent (or -1 on error). + */ +ssize_t +netif_put(desc, pkt, len) + struct iodesc *desc; + void *pkt; + size_t len; +{ + struct of_dev *op; + ssize_t rv; + size_t sendlen; + + op = desc->io_netif->nif_devdata; + +#ifdef NETIF_DEBUG + { + struct ether_header *eh; + + printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", + desc, pkt, len); + eh = pkt; + printf("dst: %s ", ether_sprintf(eh->ether_dhost)); + printf("src: %s ", ether_sprintf(eh->ether_shost)); + printf("type: 0x%x\n", eh->ether_type & 0xFFFF); + } +#endif + + sendlen = len; + if (sendlen < 60) { + sendlen = 60; +#ifdef NETIF_DEBUG + printf("netif_put: length padded to %d\n", sendlen); +#endif + } + + rv = OF_write(op->handle, pkt, sendlen); + +#ifdef NETIF_DEBUG + printf("netif_put: xmit returned %d\n", rv); +#endif + + return rv; +} + +/* + * Receive a packet, including the ether header. + * Return the total length received (or -1 on error). + */ +ssize_t +netif_get(desc, pkt, maxlen, timo) + struct iodesc *desc; + void *pkt; + size_t maxlen; + time_t timo; +{ + struct of_dev *op; + int tick0, tmo_ms; + int len; + + op = desc->io_netif->nif_devdata; + +#ifdef NETIF_DEBUG + printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", + pkt, maxlen, timo); +#endif + + tmo_ms = timo * 1000; + tick0 = OF_milliseconds(); + + do { + len = OF_read(op->handle, pkt, maxlen); + } while ((len == -2 || len == 0) && + (OF_milliseconds() - tick0 < tmo_ms)); + +#ifdef NETIF_DEBUG + printf("netif_get: received len=%d\n", len); +#endif + + if (len < 12) + return -1; + +#ifdef NETIF_DEBUG + { + struct ether_header *eh = pkt; + + printf("dst: %s ", ether_sprintf(eh->ether_dhost)); + printf("src: %s ", ether_sprintf(eh->ether_shost)); + printf("type: 0x%x\n", eh->ether_type & 0xFFFF); + } +#endif + + return len; +} + +/* + * Shouldn't really be here, but is used solely for networking, so... + */ +time_t +getsecs() +{ + return OF_milliseconds() / 1000; +} diff --git a/sys/arch/sparc64/stand/ofwboot/ofdev.c b/sys/arch/sparc64/stand/ofwboot/ofdev.c new file mode 100644 index 00000000000..e130193c771 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/ofdev.c @@ -0,0 +1,527 @@ +/* $NetBSD: ofdev.c,v 1.1 2000/08/20 14:58:41 mrg Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Device I/O routines using Open Firmware + */ +#include <sys/param.h> +#include <sys/disklabel.h> +#ifdef NETBOOT +#include <netinet/in.h> +#endif + +#include <lib/libsa/stand.h> +#include <lib/libsa/ufs.h> +#include <lib/libsa/cd9660.h> +#ifdef NETBOOT +#include <lib/libsa/nfs.h> +#endif + +#include <dev/sun/disklabel.h> +#include "ofdev.h" + +extern char bootdev[]; + +/* + * This is ugly. A path on a sparc machine is something like this: + * + * [device] [-<options] [path] [-options] [otherstuff] [-<more options] + * + */ + +static char * +filename(str, ppart) + char *str; + char *ppart; +{ + char *cp, *lp; + char savec; + int dhandle; + char devtype[16]; + + lp = str; + devtype[0] = 0; + *ppart = 0; + for (cp = str; *cp; lp = cp) { + /* For each component of the path name... */ + while (*++cp && *cp != '/'); + savec = *cp; + *cp = 0; + /* ...look whether there is a device with this name */ + dhandle = OF_finddevice(str); +#ifdef NOTDEF_DEBUG + printf("filename: OF_finddevice(%s) sez %x\n", + str, dhandle); +#endif + *cp = savec; + if (dhandle == -1) { + /* if not, lp is the delimiter between device and path */ + /* if the last component was a block device... */ + if (!strcmp(devtype, "block")) { + /* search for arguments */ +#ifdef NOTDEF_DEBUG + printf("filename: hunting for arguments in %s\n", str); +#endif + for (cp = lp; + --cp >= str && *cp != '/' && *cp != '-';); + if (cp >= str && *cp == '-') { + /* found arguments, make firmware ignore them */ + *cp = 0; + for (cp = lp; *--cp && *cp != ',';); + if (*++cp >= 'a' && *cp <= 'a' + MAXPARTITIONS) + *ppart = *cp; + } + } +#ifdef NOTDEF_DEBUG + printf("filename: found %s\n",lp); +#endif + return lp; + } else if (OF_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0) + devtype[0] = 0; + } +#ifdef NOTDEF_DEBUG + printf("filename: not found\n",lp); +#endif + return 0; +} + +static int +strategy(devdata, rw, blk, size, buf, rsize) + void *devdata; + int rw; + daddr_t blk; + size_t size; + void *buf; + size_t *rsize; +{ + struct of_dev *dev = devdata; + u_quad_t pos; + int n; + + if (rw != F_READ) + return EPERM; + if (dev->type != OFDEV_DISK) + panic("strategy"); + +#ifdef NON_DEBUG + printf("strategy: block %lx, partition offset %lx, blksz %lx\n", + (long)blk, (long)dev->partoff, (long)dev->bsize); + printf("strategy: seek position should be: %lx\n", + (long)((blk + dev->partoff) * dev->bsize)); +#endif + pos = (u_quad_t)(blk + dev->partoff) * dev->bsize; + + for (;;) { +#ifdef NON_DEBUG + printf("strategy: seeking to %lx\n", (long)pos); +#endif + if (OF_seek(dev->handle, pos) < 0) + break; +#ifdef NON_DEBUG + printf("strategy: reading %lx at %p\n", (long)size, buf); +#endif + n = OF_read(dev->handle, buf, size); + if (n == -2) + continue; + if (n < 0) + break; + *rsize = n; + return 0; + } + return EIO; +} + +static int +devclose(of) + struct open_file *of; +{ + struct of_dev *op = of->f_devdata; + +#ifdef NETBOOT + if (op->type == OFDEV_NET) + net_close(op); +#endif + OF_close(op->handle); + op->handle = -1; +} + +static struct devsw devsw[1] = { + "OpenFirmware", + strategy, + (int (*)__P((struct open_file *, ...)))nodev, + devclose, + noioctl +}; +int ndevs = sizeof devsw / sizeof devsw[0]; + +#ifdef SPARC_BOOT_UFS +static struct fs_ops file_system_ufs = { + ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat +}; +#endif +#ifdef SPARC_BOOT_HSFS +static struct fs_ops file_system_cd9660 = { + cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, + cd9660_stat +}; +#endif +#ifdef NETBOOT +static struct fs_ops file_system_nfs = { + nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat +}; +#endif + +struct fs_ops file_system[3]; +int nfsys; + +static struct of_dev ofdev = { + -1, +}; + +char opened_name[256]; +int floppyboot; + +static u_long +get_long(p) + const void *p; +{ + const unsigned char *cp = p; + + return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); +} +/************************************************************************ + * + * The rest of this was taken from arch/sparc64/scsi/sun_disklabel.c + * and then substantially rewritten by Gordon W. Ross + * + ************************************************************************/ + +/* What partition types to assume for Sun disklabels: */ +static u_char +sun_fstypes[8] = { + FS_BSDFFS, /* a */ + FS_SWAP, /* b */ + FS_OTHER, /* c - whole disk */ + FS_BSDFFS, /* d */ + FS_BSDFFS, /* e */ + FS_BSDFFS, /* f */ + FS_BSDFFS, /* g */ + FS_BSDFFS, /* h */ +}; + +/* + * Given a SunOS disk label, set lp to a BSD disk label. + * Returns NULL on success, else an error string. + * + * The BSD label is cleared out before this is called. + */ +static char * +disklabel_sun_to_bsd(cp, lp) + char *cp; + struct disklabel *lp; +{ + struct sun_disklabel *sl; + struct partition *npp; + struct sun_dkpart *spp; + int i, secpercyl; + u_short cksum, *sp1, *sp2; + + sl = (struct sun_disklabel *)cp; + + /* Verify the XOR check. */ + sp1 = (u_short *)sl; + sp2 = (u_short *)(sl + 1); + cksum = 0; + while (sp1 < sp2) + cksum ^= *sp1++; + if (cksum != 0) + return("SunOS disk label, bad checksum"); + + /* Format conversion. */ + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); + + lp->d_secsize = 512; + lp->d_nsectors = sl->sl_nsectors; + lp->d_ntracks = sl->sl_ntracks; + lp->d_ncylinders = sl->sl_ncylinders; + + secpercyl = sl->sl_nsectors * sl->sl_ntracks; + lp->d_secpercyl = secpercyl; + lp->d_secperunit = secpercyl * sl->sl_ncylinders; + + lp->d_sparespercyl = sl->sl_sparespercyl; + lp->d_acylinders = sl->sl_acylinders; + lp->d_rpm = sl->sl_rpm; + lp->d_interleave = sl->sl_interleave; + + lp->d_npartitions = 8; + /* These are as defined in <ufs/ffs/fs.h> */ + lp->d_bbsize = 8192; /* XXX */ + lp->d_sbsize = 8192; /* XXX */ + + for (i = 0; i < 8; i++) { + spp = &sl->sl_part[i]; + npp = &lp->d_partitions[i]; + npp->p_offset = spp->sdkp_cyloffset * secpercyl; + npp->p_size = spp->sdkp_nsectors; +#ifdef NOTDEF_DEBUG + printf("partition %d start %x size %x\n", i, (int)npp->p_offset, (int)npp->p_size); +#endif + if (npp->p_size == 0) { + npp->p_fstype = FS_UNUSED; + } else { + npp->p_fstype = sun_fstypes[i]; + if (npp->p_fstype == FS_BSDFFS) { + /* + * The sun label does not store the FFS fields, + * so just set them with default values here. + */ + npp->p_fsize = 1024; + npp->p_frag = 8; + npp->p_cpg = 16; + } + } + } + + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); +#ifdef NOTDEF_DEBUG + printf("disklabel_sun_to_bsd: success!\n"); +#endif + return (NULL); +} + +/* + * Find a valid disklabel. + */ +static char * +search_label(devp, off, buf, lp, off0) + struct of_dev *devp; + u_long off; + char *buf; + struct disklabel *lp; + u_long off0; +{ + size_t read; + struct mbr_partition *p; + int i; + u_long poff; + static int recursion; + + struct disklabel *dlp; + struct sun_disklabel *slp; + int error; + + /* minimal requirements for archtypal disk label */ + if (lp->d_secperunit == 0) + lp->d_secperunit = 0x1fffffff; + lp->d_npartitions = 1; + if (lp->d_partitions[0].p_size == 0) + lp->d_partitions[0].p_size = 0x1fffffff; + lp->d_partitions[0].p_offset = 0; + + if (strategy(devp, F_READ, LABELSECTOR, DEV_BSIZE, buf, &read) + || read != DEV_BSIZE) + return ("Cannot read label"); + /* Check for a NetBSD disk label. */ + dlp = (struct disklabel *) (buf + LABELOFFSET); + if (dlp->d_magic == DISKMAGIC) { + if (dkcksum(dlp)) + return ("NetBSD disk label corrupted"); + *lp = *dlp; +#ifdef NOTDEF_DEBUG + printf("search_label: found NetBSD label\n"); +#endif + return (NULL); + } + + /* Check for a Sun disk label (for PROM compatibility). */ + slp = (struct sun_disklabel *) buf; + if (slp->sl_magic == SUN_DKMAGIC) + return (disklabel_sun_to_bsd(buf, lp)); + + + bzero(buf, sizeof(buf)); + return ("no disk label"); +} + +int +devopen(of, name, file) + struct open_file *of; + const char *name; + char **file; +{ + char *cp; + char partition; + char fname[256]; + char buf[DEV_BSIZE]; + struct disklabel label; + int handle, part; + size_t read; + char *errmsg = NULL; + int error = 0; + + if (ofdev.handle != -1) + panic("devopen"); + if (of->f_flags != F_READ) + return EPERM; +#ifdef NOTDEF_DEBUG + printf("devopen: you want %s\n", name); +#endif + strcpy(fname, name); + cp = filename(fname, &partition); + if (cp) { + strcpy(buf, cp); + *cp = 0; + } + if (!cp || !*buf) + strcpy(buf, DEFAULT_KERNEL); + if (!*fname) + strcpy(fname, bootdev); + strcpy(opened_name, fname); + if (partition) { + cp = opened_name + strlen(opened_name); + *cp++ = ':'; + *cp++ = partition; + *cp = 0; + } + if (*buf != '/') + strcat(opened_name, "/"); + strcat(opened_name, buf); + *file = opened_name + strlen(fname) + 1; +#ifdef NOTDEF_DEBUG + printf("devopen: trying %s\n", fname); +#endif + if ((handle = OF_finddevice(fname)) == -1) + return ENOENT; +#ifdef NOTDEF_DEBUG + printf("devopen: found %s\n", fname); +#endif + if (OF_getprop(handle, "name", buf, sizeof buf) < 0) + return ENXIO; +#ifdef NOTDEF_DEBUG + printf("devopen: %s is called %s\n", fname, buf); +#endif + floppyboot = !strcmp(buf, "floppy"); + if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0) + return ENXIO; +#ifdef NOTDEF_DEBUG + printf("devopen: %s is a %s device\n", fname, buf); +#endif +#ifdef NOTDEF_DEBUG + printf("devopen: opening %s\n", fname); +#endif + if ((handle = OF_open(fname)) == -1) { +#ifdef NOTDEF_DEBUG + printf("devopen: open of %s failed\n", fname); +#endif + return ENXIO; + } +#ifdef NOTDEF_DEBUG + printf("devopen: %s is now open\n", fname); +#endif + bzero(&ofdev, sizeof ofdev); + ofdev.handle = handle; + if (!strcmp(buf, "block")) { + ofdev.type = OFDEV_DISK; + ofdev.bsize = DEV_BSIZE; + /* First try to find a disklabel without MBR partitions */ +#ifdef NOTDEF_DEBUG + printf("devopen: trying to read disklabel\n"); +#endif + if (strategy(&ofdev, F_READ, + LABELSECTOR, DEV_BSIZE, buf, &read) != 0 + || read != DEV_BSIZE + || (errmsg = getdisklabel(buf, &label))) { + if (errmsg) printf("devopen: getdisklabel sez %s\n", errmsg); + /* Else try MBR partitions */ + errmsg = search_label(&ofdev, 0, buf, &label, 0); + if (errmsg) { + printf("devopen: search_label sez %s\n", errmsg); + error = ERDLAB; + } + if (error && error != ERDLAB) + goto bad; + } + + if (error == ERDLAB) { + if (partition) + /* User specified a parititon, but there is none */ + goto bad; + /* No, label, just use complete disk */ + ofdev.partoff = 0; + } else { + part = partition ? partition - 'a' : 0; + ofdev.partoff = label.d_partitions[part].p_offset; +#ifdef NOTDEF_DEBUG + printf("devopen: setting partition %d offset %x\n", + part, ofdev.partoff); +#endif + } + + of->f_dev = devsw; + of->f_devdata = &ofdev; +#ifdef SPARC_BOOT_UFS + bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]); +#endif +#ifdef SPARC_BOOT_HSFS + bcopy(&file_system_cd9660, &file_system[nfsys++], + sizeof file_system[0]); +#endif +#ifdef NOTDEF_DEBUG + printf("devopen: return 0\n"); +#endif + return 0; + } +#ifdef NETBOOT + if (!strcmp(buf, "network")) { + ofdev.type = OFDEV_NET; + of->f_dev = devsw; + of->f_devdata = &ofdev; + bcopy(&file_system_nfs, file_system, sizeof file_system[0]); + nfsys = 1; + if (error = net_open(&ofdev)) + goto bad; + return 0; + } +#endif + error = EFTYPE; +bad: +#ifdef NOTDEF_DEBUG + printf("devopen: error %d, cannot open device\n", error); +#endif + OF_close(handle); + ofdev.handle = -1; + return error; +} diff --git a/sys/arch/sparc64/stand/ofwboot/ofdev.h b/sys/arch/sparc64/stand/ofwboot/ofdev.h new file mode 100644 index 00000000000..cf913178e79 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/ofdev.h @@ -0,0 +1,52 @@ +/* $NetBSD: ofdev.h,v 1.1 2000/08/20 14:58:41 mrg Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +#ifndef _STAND_DEV_H_ +#define _STAND_DEV_H_ + +struct of_dev { + int handle; + int type; + u_long partoff; + int bsize; +}; + +/* Known types: */ +#define OFDEV_NET 1 +#define OFDEV_DISK 2 + +#define DEFAULT_KERNEL "/netbsd" + +extern char opened_name[]; +extern int floppyboot; + +#endif diff --git a/sys/arch/sparc64/stand/ofwboot/openfirm.h b/sys/arch/sparc64/stand/ofwboot/openfirm.h new file mode 100644 index 00000000000..6e92dea9285 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/openfirm.h @@ -0,0 +1,58 @@ +/* $NetBSD: openfirm.h,v 1.1 2000/08/20 14:58:42 mrg Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ +/* + * Prototypes for Openfirmware Interface Routines + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <machine/openfirm.h> + +#if 0 +u_int OF_finddevice __P((char *name)); +u_int OF_instance_to_package __P((u_int ihandle)); +u_int OF_getprop __P((u_int handle, char *prop, void *buf, int buflen)); +#ifdef __notyet__ +int OF_setprop __P((u_int handle, char *prop, void *buf, int len)); +#endif +u_int OF_open __P((char *dname)); +void OF_close __P((u_int handle)); +int OF_write __P((u_int handle, void *addr, int len)); +int OF_read __P((u_int handle, void *addr, int len)); +int OF_seek __P((u_int handle, u_int64_t pos)); +#endif +void *OF_claim __P((void *virt, u_int size, u_int align)); +void OF_release __P((void *virt, u_int size)); +int OF_milliseconds __P((void)); +void OF_chain __P((void *addr, u_int size, void (*entry)(), void *parm, u_int parmlen)); + diff --git a/sys/arch/sparc64/stand/ofwboot/srt0.s b/sys/arch/sparc64/stand/ofwboot/srt0.s new file mode 100644 index 00000000000..fcad4ad4d3e --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/srt0.s @@ -0,0 +1,210 @@ +/* $NetBSD: srt0.s,v 1.1 2000/08/20 14:58:42 mrg Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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 <machine/psl.h> +#include <machine/param.h> +#include <machine/frame.h> +#include <machine/asm.h> + +/* + * Globals + */ + .globl _esym + .data +_esym: .word 0 /* end of symbol table */ + .globl _C_LABEL(romp) + .align 8 +_C_LABEL(romp): .xword 0 /* openfirmware entry point */ + +/* + * Startup entry + */ + .text + .globl _start, _C_LABEL(kernel_text) + _C_LABEL(kernel_text) = _start +_start: + nop ! For some reason this is needed to fixup the text section + + /* + * Step 1: Save rom entry pointer -- NOTE this probably needs to change + */ + + mov %o4, %g7 ! save prom vector pointer + set _C_LABEL(romp), %g1 + stx %o4, [%g1] ! It's initialized data, I hope + + /* + * Start by creating a stack for ourselves. + */ +#ifdef _LP64 + /* 64-bit stack */ + btst 1, %sp + set CC64FSZ, %g1 ! Frame Size (negative) + bnz 1f + set BIAS, %g2 ! Bias (negative) + andn %sp, 0x0f, %sp ! 16 byte align, per ELF spec. + add %g1, %g2, %g1 ! Frame + Bias +1: + sub %sp, %g1, %g1 + save %g1, %g0, %sp +#else + /* 32-bit stack */ + btst 1, %sp + set CC64FSZ, %g1 ! Frame Size (negative) + bz 1f + set BIAS, %g2 + sub %g1, %g2, %g1 +1: + sub %sp, %g1, %g1 ! This is so we properly sign-extend things + andn %g1, 0x7, %g1 + save %g1, %g0, %sp +#endif + +! mov %i0, %i4 ! Apparenty we get our CIF in i0 + + /* + * Set the psr into a known state: + * Set supervisor mode, interrupt level >= 13, traps enabled + */ + wrpr %g0, 0, %pil ! So I lied + wrpr %g0, PSTATE_PRIV+PSTATE_IE, %pstate + + clr %g4 ! Point %g4 to start of data segment + ! only problem is that apparently the + ! start of the data segment is 0 + + /* + * XXXXXXXX Need to determine what params are passed + */ + call _C_LABEL(setup) + nop + mov %i1, %o1 + call _C_LABEL(main) + mov %i2, %o0 + call _C_LABEL(exit) + nop + call _C_LABEL(_rtt) + nop + +/* + * void syncicache(void* start, int size) + * + * I$ flush. Really simple. Just flush over the whole range. + */ + .align 8 + .globl _C_LABEL(syncicache) +_C_LABEL(syncicache): + dec 4, %o1 + flush %o0 + brgz,a,pt %o1, _C_LABEL(syncicache) + inc 4, %o0 + retl + nop + +/* + * openfirmware(cell* param); + * + * OpenFirmware entry point + * + * If we're running in 32-bit mode we need to convert to a 64-bit stack + * and 64-bit cells. The cells we'll allocate off the stack for simplicity. + */ + .align 8 + .globl _C_LABEL(openfirmware) + .proc 1 + FTYPE(openfirmware) +_C_LABEL(openfirmware): + andcc %sp, 1, %g0 + bz,pt %icc, 1f + sethi %hi(_C_LABEL(romp)), %o1 + + ldx [%o1+%lo(_C_LABEL(romp))], %o4 ! v9 stack, just load the addr and callit + save %sp, -CC64FSZ, %sp + mov %i0, %o0 ! Copy over our parameter + mov %g1, %l1 + mov %g2, %l2 + mov %g3, %l3 + mov %g4, %l4 + mov %g5, %l5 + mov %g6, %l6 + mov %g7, %l7 + rdpr %pstate, %l0 + jmpl %i4, %o7 + wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate + wrpr %l0, %g0, %pstate + mov %l1, %g1 + mov %l2, %g2 + mov %l3, %g3 + mov %l4, %g4 + mov %l5, %g5 + mov %l6, %g6 + mov %l7, %g7 + ret + restore %o0, %g0, %o0 + +1: ! v8 -- need to screw with stack & params + save %sp, -CC64FSZ, %sp ! Get a new 64-bit stack frame + add %sp, -BIAS, %sp + sethi %hi(_C_LABEL(romp)), %o1 + rdpr %pstate, %l0 + ldx [%o1+%lo(_C_LABEL(romp))], %o1 ! Do the actual call + srl %sp, 0, %sp + mov %i0, %o0 + mov %g1, %l1 + mov %g2, %l2 + mov %g3, %l3 + mov %g4, %l4 + mov %g5, %l5 + mov %g6, %l6 + mov %g7, %l7 + jmpl %o1, %o7 + wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate ! Enable 64-bit addresses for the prom + wrpr %l0, 0, %pstate + mov %l1, %g1 + mov %l2, %g2 + mov %l3, %g3 + mov %l4, %g4 + mov %l5, %g5 + mov %l6, %g6 + mov %l7, %g7 + ret + restore %o0, %g0, %o0 + +#if 0 + .data + .align 8 +bootstack: +#define STACK_SIZE 0x14000 + .skip STACK_SIZE +ebootstack: ! end (top) of boot stack +#endif diff --git a/sys/arch/sparc64/stand/ofwboot/vers.c b/sys/arch/sparc64/stand/ofwboot/vers.c new file mode 100644 index 00000000000..2a9ab06447e --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/vers.c @@ -0,0 +1,6 @@ +char ostype[] = "OpenBSD"; +char osrelease[] = "2.9"; +char osversion[] = "ofwboot#0"; +char sccs[8] = { ' ', ' ', ' ', ' ', '@', '(', '#', ')' }; +char version[] = + "OpenBSD 2.9-current (ofwboot) #0: Fri Aug 17 23:15:34 PDT 2001\n root@u5:/usr/openbsd/src/sys/arch/sparc64/stand/ofwboot\n"; diff --git a/sys/arch/sparc64/stand/ofwboot/version b/sys/arch/sparc64/stand/ofwboot/version new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/version @@ -0,0 +1 @@ +1 |