summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64/stand/ofwboot
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2001-08-18 15:51:11 +0000
committerJason Wright <jason@cvs.openbsd.org>2001-08-18 15:51:11 +0000
commit4cbd011292f901d241cd3710eb7bcfff692b6be4 (patch)
treeea949af6af61769a2f9bfe288d3ff0b636828d29 /sys/arch/sparc64/stand/ofwboot
parent9c67302636a9447a5b801b9491c5aa6406fb88bc (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.c866
-rw-r--r--sys/arch/sparc64/stand/ofwboot/Makefile92
-rw-r--r--sys/arch/sparc64/stand/ofwboot/alloc.c214
-rw-r--r--sys/arch/sparc64/stand/ofwboot/boot.c623
-rw-r--r--sys/arch/sparc64/stand/ofwboot/elfXX_exec.c208
-rw-r--r--sys/arch/sparc64/stand/ofwboot/md5.h55
-rw-r--r--sys/arch/sparc64/stand/ofwboot/net.c194
-rw-r--r--sys/arch/sparc64/stand/ofwboot/netif_of.c240
-rw-r--r--sys/arch/sparc64/stand/ofwboot/ofdev.c527
-rw-r--r--sys/arch/sparc64/stand/ofwboot/ofdev.h52
-rw-r--r--sys/arch/sparc64/stand/ofwboot/openfirm.h58
-rw-r--r--sys/arch/sparc64/stand/ofwboot/srt0.s210
-rw-r--r--sys/arch/sparc64/stand/ofwboot/vers.c6
-rw-r--r--sys/arch/sparc64/stand/ofwboot/version1
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