code:
#	$OpenBSD: genfth.cf,v 1.5 2014/11/26 19:57:41 stsp Exp $
#	$NetBSD: genfth.cf,v 1.1 2000/08/20 14:58:46 mrg Exp $

#
# Copyright (c) 1997 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
# by Christos Zoulas.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Copyright (c) 1992, 1993
#	The Regents of the University of California.  All rights reserved.
#
# This software was developed by the Computer Systems Engineering group
# at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
# contributed to Berkeley.
#
# All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
#	This product includes software developed by the University of
#	California, Lawrence Berkeley Laboratory.
#
# 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. Neither the name of the University nor the names of its contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#	@(#)genassym.c	8.1 (Berkeley) 6/11/93
#

include <sys/param.h>
include <sys/disklabel.h>
include <sys/time.h>

include <dev/sun/disklabel.h>

include <ufs/ufs/dinode.h>
include <ufs/ufs/dir.h>
include <ufs/ffs/fs.h>

#ifdef SOFTRAID
include <sys/stdarg.h> /* XXX */
include <sys/device.h>
include <sys/sensors.h>
include <dev/softraidvar.h>
#endif

#
# sun disklabel
#
struct sun_disklabel
member sl_types
member sl_magic

define sun_dkmagic	SUN_DKMAGIC
define fs_bsdffs	FS_BSDFFS
define fs_raid		FS_RAID

#
# ufs sizing constants
#
define	dev_bsize	DEV_BSIZE
define	maxbsize	MAXBSIZE
define	bbsize		BBSIZE
define	sbsize		SBSIZE
define	bboff		BBOFF
define	sboff		SBOFF
define	bblock		BBLOCK
define	sblock		SBLOCK

#
# ufs superblock
#
struct	fs
member	fs_magic
member	fs_bsize
member	fs_npsect
member	fs_nsect
member	fs_interleave
member	fs_postblformat
member	fs_nrpos
member	fs_inodefmt
member	fs_maxfilesize
member	fs_qbmask
member	fs_qfmask
member	fs_bmask
member	fs_fmask
member	fs_ipg
member	fs_fpg
member	fs_inopb
member	fs_fragshift
member	fs_bshift
member	fs_fshift
member	fs_cgoffset
member	fs_cgmask
member	fs_dblkno
member	fs_iblkno
member	fs_sblkno
member	fs_cblkno
member  fs_fsbtodb
member	fs_nindir
member	fs_frag
member	fs_maxsymlinklen

#
# ufs dinode
#
struct	ufs1_dinode
member	di_size
member	di_mode
member	di_db
member	di_ib
member  di_shortlink

#
# ufs direct
#
struct	direct
member	d_ino
member	d_reclen
#member	d_type		# notused
member	d_namlen
member	d_name

define	fs_magic_value	FS_MAGIC
define	fs_42postblfmt	FS_42POSTBLFMT
define	fs_44inodefmt	FS_44INODEFMT
define	ndaddr		NDADDR
define	niaddr		NIADDR
define	rootino		ROOTINO
define	ifmt		IFMT
define	ifdir		IFDIR
define	iflnk		IFLNK

#
# softraid
#
#ifdef SOFTRAID
struct	sr_meta_invariant
member	ssd_magic
member	ssd_version
member	ssd_vol_flags

define	sr_magic1	(SR_MAGIC >> 32)
define	sr_magic2	(SR_MAGIC & 0xffffffff)
define	sr_meta_offset	SR_META_OFFSET
define	sr_meta_size	SR_META_SIZE
define	sr_boot_offset	SR_BOOT_LOADER_OFFSET
define	sr_boot_size	SR_BOOT_LOADER_SIZE

define	bioc_scbootable	BIOC_SCBOOTABLE
#endif


code:
#	$OpenBSD: Makefile,v 1.10 2014/11/19 20:01:36 miod Exp $

LIB=	sa

.PATH:	${.CURDIR}/../../../../lib/libsa

CLEANFILES += machine

CFLAGS= ${CEXTRAFLAGS} ${AFLAGS} -O2 -D__INTERNAL_LIBSA_CREAD -nostdinc \
	-fno-pie \
	-I${.CURDIR} -I${.CURDIR}/../include -I${.CURDIR}/../.. \
	-I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. \
	-I${.CURDIR}/../../../../lib/libsa \
	-I${.OBJDIR}

CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD

# stand routines
SRCS=	alloc.c exit.c getfile.c gets.c globals.c \
	memcmp.c memcpy.c memset.c printf.c snprintf.c strerror.c strncpy.c

# io routines
SRCS+=	close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c lseek.c \
	open.c read.c stat.c write.c cread.c

# network routines
SRCS+=	arp.c ether.c in_cksum.c net.c netif.c netudp.c rpc.c

# network info services
SRCS+=	bootp.c bootparam.c rarp.c

# boot filesystems
SRCS+=	ufs.c nfs.c cd9660.c

${OBJS}:	${.CURDIR}/../Makefile.inc

NOPROFILE=
NOPIC=

.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(obj)
.BEGIN:
	@([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
.endif

install:

.include <bsd.lib.mk>

license: unknown


code:
/Makefile/1.8/Thu Aug 30 19:29:14 2012//TOPENBSD_5_8_BASE
D


code:
#	$OpenBSD: Makefile,v 1.8 2012/08/30 19:29:14 pascal Exp $

S=${.CURDIR}/../../../..
ZDST=${.OBJDIR}

.PATH: ${S}/lib/libz

.include "${S}/lib/libz/Makefile"
CFLAGS+=${CEXTRAFLAGS} ${AFLAGS} -I${S} -fno-pie


code:
/Makefile/1.3/Thu Aug 30 19:29:14 2012//TOPENBSD_5_8_BASE
D


code:
#	$OpenBSD: Makefile,v 1.3 2012/08/30 19:29:14 pascal Exp $

CPPFLAGS+=	-DNETBOOT
PROG=		ofwboot.net
.include "../ofwboot/Makefile"

.PATH: ${.CURDIR}/../ofwboot


code:
/*	$OpenBSD: Locore.c,v 1.13 2014/12/11 10:52:07 stsp Exp $	*/
/*	$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>

static vaddr_t OF_claim_virt(vaddr_t vaddr, int len);
static vaddr_t OF_alloc_virt(int len, int align);
static int OF_free_virt(vaddr_t vaddr, int len);
static vaddr_t OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode);
static paddr_t OF_alloc_phys(int len, int align);
static int OF_free_phys(paddr_t paddr, int len);

extern int openfirmware(void *);

void setup(void);

__dead void
_rtt(void)
{
	struct {
		cell_t name;
		cell_t nargs;
		cell_t nreturns;
	} args;

#ifdef SOFTRAID
	sr_clear_keys();
#endif

	args.name = ADR2CELL("exit");
	args.nargs = 0;
	args.nreturns = 0;
	openfirmware(&args);
	while (1);			/* just in case */
}

void
OF_enter(void)
{
	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(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(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(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;
}

int
OF_open(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(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 = 0;
	args.handle = HDL2CELL(handle);
	openfirmware(&args);
}

int
OF_write(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(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(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 = HDQ2CELL_HI(pos);
	args.poslo = HDQ2CELL_LO(pos);
	if (openfirmware(&args) == -1) {
		return -1;
	}
	return args.status;
}

void
OF_release(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(void)
{
	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(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
{
	extern int64_t romp;

	entry(0, arg, len, (unsigned long)romp, (unsigned long)romp);
	panic("OF_chain: kernel returned!");
	__asm("ta 2" : :);
}

static u_int stdin;
static u_int stdout;
static u_int mmuh = -1;
static u_int memh = -1;

void
setup(void)
{
	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.
 */
static vaddr_t
OF_claim_virt(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;

	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 (vaddr_t)args.retaddr;
}

/*
 * Request some address space from the prom
 *
 * Only works while the prom is actively mapping us.
 */
static vaddr_t
OF_alloc_virt(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;

	args.name = ADR2CELL("call-method");
	args.nargs = 4;
	args.nreturns = 2;
	args.method = ADR2CELL("claim");
	args.ihandle = HDL2CELL(mmuh);
	args.align = align;
	args.len = len;
	args.retaddr = ADR2CELL(&retaddr);
	if (openfirmware(&args) != 0)
		return -1LL;
	return (vaddr_t)args.retaddr;
}

/*
 * Release some address space to the prom
 *
 * Only works while the prom is actively mapping us.
 */
static int
OF_free_virt(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;

	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);
}

/*
 * Have prom map in some memory
 *
 * Only works while the prom is actively mapping us.
 */
static vaddr_t
OF_map_phys(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;

	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 = HDQ2CELL_HI(paddr);
	args.paddr_lo = HDQ2CELL_LO(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.
 */
static paddr_t
OF_alloc_phys(int len, int align)
{
	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;

	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;
	return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo);
}

/*
 * Free some RAM to prom
 *
 * Only works while the prom is actively mapping us.
 */
static int
OF_free_phys(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;

	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 = HDQ2CELL_HI(phys);
	args.phys_lo = HDQ2CELL_LO(phys);
	return openfirmware(&args);
}

/*
 * Claim virtual memory -- does not map it in.
 */

void *
OF_claim(void *virt, u_int size, u_int align)
{
	/*
	 * 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) {
		virt = (void *)OF_alloc_virt(size, align);
		if (virt == (void *)-1LL) {
			printf("OF_alloc_virt(%d,%d) failed w/%x\n",
			       size, align, virt);
			return virt;
		}
	} else {
		newvirt = (void *)OF_claim_virt((vaddr_t)virt, size);
		if (newvirt == (void *)-1LL) {
			printf("OF_claim_virt(%x,%d) failed w/%x\n",
			       virt, size, newvirt);
			return newvirt;
		}
		virt = newvirt;
	}
	if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) {
		printf("OF_alloc_phys(%d,%d) failed\n", size, align);
		OF_free_virt((vaddr_t)virt, size);
		return (void *)-1LL;
	}
	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 *)-1LL;
	}
	return virt;
}

int
OF_peer(int phandle)
{
	struct {
		cell_t name;
		cell_t nargs;
		cell_t nreturns;
		cell_t phandle;
		cell_t sibling;
	} args;

	args.name = ADR2CELL("peer");
	args.nargs = 1;
	args.nreturns = 1;
	args.phandle = HDL2CELL(phandle);
	if (openfirmware(&args) == -1)
		return 0;
	return args.sibling;
}

int
OF_child(int phandle)
{
	struct {
		cell_t name;
		cell_t nargs;
		cell_t nreturns;
		cell_t phandle;
		cell_t child;
	} args;

	args.name = ADR2CELL("child");
	args.nargs = 1;
	args.nreturns = 1;
	args.phandle = HDL2CELL(phandle);
	if (openfirmware(&args) == -1)
		return 0;
	return args.child;
}

int
OF_package_to_path(int phandle, char *buf, int buflen)
{
	struct {
		cell_t name;
		cell_t nargs;
		cell_t nreturns;
		cell_t phandle;
		cell_t buf;
		cell_t buflen;
		cell_t length;
	} args;

	if (buflen > PAGE_SIZE)
		return -1;
	args.name = ADR2CELL("package-to-path");
	args.nargs = 3;
	args.nreturns = 1;
	args.phandle = HDL2CELL(phandle);
	args.buf = ADR2CELL(buf);
	args.buflen = buflen;
	if (openfirmware(&args) < 0)
		return -1;
	return args.length;
}

void
putchar(int c)
{
	char ch = c;

	if (c == '\n')
		putchar('\r');
	OF_write(stdout, &ch, 1);
}

int
getchar(void)
{
	unsigned char ch = '\0';
	int l;

	while ((l = OF_read(stdin, &ch, 1)) != 1)
		if (l != -2 && l != 0)
			return -1;
	return ch;
}


code:
#	$OpenBSD: Makefile,v 1.19 2014/11/26 20:30:41 stsp Exp $
#	$NetBSD: Makefile,v 1.2 2001/03/04 14:50:05 mrg Exp $

CURDIR=	${.CURDIR}
S=	${CURDIR}/../../../..

#
# Override normal settings
#

WARNS=		0

PROG?=		ofwboot
NOMAN=		ja, man!

.if ${PROG} == "ofwboot"
SOFTRAID?=	yes
.else
SOFTRAID?=	no
.endif

.PATH:		${S}/arch/sparc64/sparc64
SRCS=		srt0.s Locore.c alloc.c boot.c elf64_exec.c net.c netif_of.c \
		ofdev.c vers.c
.if ${SOFTRAID:L} == "yes"
SRCS+=		diskprobe.c softraid.c
.endif

.PATH:		${S}/lib/libkern/arch/sparc64 ${S}/lib/libkern
SRCS+=		strlcpy.c strcmp.c strlcat.c strlen.c

.if ${SOFTRAID:L} == "yes"
.PATH:		${S}/lib/libsa
SRCS+=		aes_xts.c explicit_bzero.c hmac_sha1.c sha1.c pbkdf2.c \
		rijndael.c
.endif

CWARNFLAGS+=	-Wno-main
AFLAGS+=	-Wa,-Av9a
AFLAGS+=	-x assembler-with-cpp -D_LOCORE -D__ELF__ -fno-pie
CFLAGS+=	${COPTS} -fno-pie
CPPFLAGS+=	-D_STANDALONE -DSUN4U -nostdinc
#CPPFLAGS+=	-DNETIF_DEBUG

BINMODE=	444

NEWVERSWHAT=	"OpenFirmware Boot"

#
# ELF64 defaults to 1MB
#
RELOC=		100000

ENTRY=		_start

CLEANFILES+=	sparc machine

CPPFLAGS+=	-I${CURDIR}/../../.. -I${CURDIR}/../../../.. -I${CURDIR} -I.
CPPFLAGS+=	-DRELOC=0x${RELOC}

#
# XXXXX FIXME
#
CPPFLAGS+=	-DSPARC_BOOT_UFS
#CPPFLAGS+=	-DSPARC_BOOT_HSFS
.if ${SOFTRAID:L} == "yes"
CPPFLAGS+=	-DSOFTRAID
.endif

.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(obj)
.BEGIN:
	@([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
.endif

${PROG}: ${OBJS} ${LIBSA} ${LIBZ}
	${LD} -N -Ttext ${RELOC} -e ${ENTRY} -o ${PROG} -nopie \
	    ${OBJS} -L${LIBSADIR} ${LIBSA} \
	    -L${LIBZDIR} ${LIBZ}

NORMAL_S=	${CC} ${AFLAGS} ${CPPFLAGS} -c $<
srt0.o: srt0.s
	${NORMAL_S}

.include <bsd.prog.mk>


code:
/*	$OpenBSD: alloc.c,v 1.7 2014/12/11 10:52:07 stsp Exp $	*/
/*	$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(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 */
	LIST_FOREACH(f, &freelist, list)
		if (f->size >= size)
			break;
	bestf = f;
	failed = (bestf == (struct fl *)0);
#else
	/* scan freelist */
	LIST_FOREACH(f, &freelist, list) {
		if (f->size >= size) {
			if (f->size == size)	/* exact match */
				goto found;

			if (f->size < bestsize) {
				/* keep best fit */
				bestf = f;
				bestsize = f->size;
			}
		}
	}

	/* 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, PAGE_SIZE);
		help = OF_claim(0, size, PAGE_SIZE);
		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(void *ptr, unsigned size)
{
	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);
}


code:
/*	$OpenBSD: boot.c,v 1.23 2014/12/11 10:52:07 stsp Exp $	*/
/*	$NetBSD: boot.c,v 1.3 2001/05/31 08:55:19 mrg Exp $	*/
/*
 * 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]
 */

#define ELFSIZE 64

#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>

#ifdef SOFTRAID
#include <sys/param.h>
#include <sys/queue.h>
#include <dev/biovar.h>
#include <dev/softraidvar.h>

#include "disk.h"
#include "softraid.h"
#endif

#include "ofdev.h"
#include "openfirm.h"

#ifdef BOOT_DEBUG
uint32_t	boot_debug = 0
		    /* | BOOT_D_OFDEV */
		    /* | BOOT_D_OFNET */
		;
#endif

#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[] = {
	"bsd",
	NULL
};

char bootdev[128];
char bootfile[128];
int boothowto;
int debug;

char rnddata[BOOTRANDOM_MAX];

int	elf64_exec(int, Elf64_Ehdr *, u_int64_t *, void **, void **);

/*
 *	parse:
 *		[kernel-name] [-options]
 *	leave kernel-name in passed-in string
 *	put options into *howtop
 *	return -1 iff syntax error (no - before options)
 */

static int
parseargs(char *str, int *howtop)
{
	char *cp;
	int i;

	*howtop = 0;
	cp = str;
	while (*cp == ' ')
		++cp;
	if (*cp != '-') {
		while (*cp && *cp != ' ')
			*str++ = *cp++;
		while (*cp == ' ')
			++cp;
	}
	*str = 0;
	switch(*cp) {
	default:
		printf ("boot options string <%s> must start with -\n", cp);
		return -1;
	case 0:
		return 0;
	case '-':
		break;
	}

	++cp;
	while (*cp) {
		BOOT_FLAG(*cp, *howtop);
		/* handle specialties */
		switch (*cp++) {
		case 'd':
			if (!debug) debug = 1;
			break;
		case 'D':
			debug = 2;
			break;
		}
	}
	return 0;
}

static void
chain(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;

	/*
	 * 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)+PAGE_SIZE)%PAGE_SIZE,
	    entry, args, l);
	panic("chain");
}

int
loadfile(int fd, char *args)
{
	union {
		Elf64_Ehdr elf64;
	} hdr;
	int rval;
	u_int64_t entry = 0;
	void *ssym;
	void *esym;

	ssym = NULL;
	esym = NULL;

	/* Load the header. */
#ifdef DEBUG
	printf("loadfile: reading header\n");
#endif
	if ((rval = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
		if (rval == -1)
			printf("read header: %s\n", strerror(errno));
		else
			printf("read header: short read (only %d of %d)\n",
			    rval, sizeof(hdr));
		rval = 1;
		goto err;
	}

	/* Determine file type, load kernel. */
	if (bcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
	    hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
		printf("Booting %s\n", opened_name);
		rval = elf64_exec(fd, &hdr.elf64, &entry, &ssym, &esym);
	} else {
		rval = 1;
		printf("unknown executable format\n");
	}

	if (rval)
		goto err;

	printf(" start=0x%lx\n", (unsigned long)entry);

	close(fd);

#ifdef SOFTRAID
	sr_clear_keys();
#endif
	chain(entry, args, ssym, esym);
	/* NOTREACHED */

 err:
	close(fd);
	return (rval);
}

int
loadrandom(char *path, char *buf, size_t buflen)
{
	struct stat sb;
	int fd, i;

#define O_RDONLY	0

	fd = open(path, O_RDONLY);
	if (fd == -1)
		return -1;
	if (fstat(fd, &sb) == -1 ||
	    sb.st_uid != 0 ||
	    (sb.st_mode & (S_IWOTH|S_IROTH)))
		goto fail;
	if (read(fd, buf, buflen) != buflen)
		goto fail;
	close(fd);
 	return 0;
fail:
	close(fd);
	return (-1);
}

#ifdef SOFTRAID
/* Set bootdev_dip to the software boot volume, if specified. */
static int
srbootdev(const char *bootline)
{
	struct sr_boot_volume *bv;
	struct diskinfo *dip;
	int unit;

	bootdev_dip = NULL;

	/*
	 * Look for softraid disks in bootline.
	 * E.g. 'sr0', 'sr0:bsd', or 'sr0a:/bsd'
	 */
	if (bootline[0] == 's' && bootline[1] == 'r' &&
	    '0' <= bootline[2] && bootline[2] <= '9') {
		unit = bootline[2] - '0';

		/* Create a fake diskinfo for this softraid volume. */
		SLIST_FOREACH(bv, &sr_volumes, sbv_link)
			if (bv->sbv_unit == unit)
				break;
		if (bv == NULL) {
			printf("Unknown device: sr%d\n", unit);
			return ENODEV;
		}

		if ((bv->sbv_flags & BIOC_SCBOOTABLE) == 0) {
			printf("device sr%d is not bootable\n", unit);
			return ENODEV;
		}

		if (bv->sbv_level == 'C' && bv->sbv_keys == NULL)
			if (sr_crypto_decrypt_keys(bv) != 0)
				return EPERM;

		if (bv->sbv_diskinfo == NULL) {
			dip = alloc(sizeof(struct diskinfo));
			bzero(dip, sizeof(*dip));
			dip->sr_vol = bv;
			bv->sbv_diskinfo = dip;
		}

		/* strategy() and devopen() will use bootdev_dip */
		bootdev_dip = bv->sbv_diskinfo;

		/* Attempt to read disklabel. */
		bv->sbv_part = 'c';
		if (sr_getdisklabel(bv, &dip->disklabel)) {
			free(bv->sbv_diskinfo, sizeof(struct diskinfo));
			bv->sbv_diskinfo = NULL;
			bootdev_dip = NULL;
			return ERDLAB;
		}
	}

	return 0;
}
#endif

int
main()
{
	extern char version[];
	int chosen;
	char bootline[512];		/* Should check size? */
	char *cp;
	int i, fd, len;
#ifdef SOFTRAID
	int err;
#endif
	char **bootlp;
	char *just_bootline[2];

	printf(">> OpenBSD BOOT %s\n", 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();
	}

#ifdef SOFTRAID
	diskprobe();
	srprobe();
	err = srbootdev(bootline);
	if (err) {
		printf("Cannot boot from softraid: %s\n", strerror(err));
		_rtt();
	}
#endif

	/*
	 * case 1:	boot net -a
	 *			-> gets loop
	 * case 2:	boot net kernel [options]
	 *			-> boot kernel, gets loop
	 * case 3:	boot net [options]
	 *			-> iterate boot list, gets loop
	 */

	bootlp = kernels;
	if (parseargs(bootline, &boothowto) == -1 ||
	    (boothowto & RB_ASKNAME)) {
		bootlp = 0;
	} else if (*bootline) {
		just_bootline[0] = bootline;
		just_bootline[1] = 0;
		bootlp = just_bootline;
	}
	for (;;) {
		if (bootlp) {
			cp = *bootlp++;
			if (!cp) {
				printf("\n");
				bootlp = 0;
				kernels[0] = 0;	/* no more iteration */
			} else if (cp != bootline) {
				printf("Trying %s...\n", cp);
				if (strlcpy(bootline, cp, sizeof bootline)
				    >= sizeof bootline) {
					printf("bootargs too long: %s\n",
					    bootline);
					_rtt();
				}
			}
		}
		if (!bootlp) {
			printf("Boot: ");
			gets(bootline);
			if (parseargs(bootline, &boothowto) == -1)
				continue;
			if (!*bootline) {
				bootlp = kernels;
				continue;
			}
			if (strcmp(bootline, "exit") == 0 ||
			    strcmp(bootline, "halt") == 0) {
				_rtt();
			}
		}
		if (loadrandom(BOOTRANDOM, rnddata, sizeof(rnddata)))
			printf("open %s: %s\n", opened_name, strerror(errno));
		if ((fd = open(bootline, 0)) < 0) {
			printf("open %s: %s\n", opened_name, strerror(errno));
			continue;
		}
		len = snprintf(bootline, sizeof bootline, "%s%s%s%s",
		    opened_name,
		    (boothowto & RB_ASKNAME) ? " -a" : "",
		    (boothowto & RB_SINGLE) ? " -s" : "",
		    (boothowto & RB_KDB) ? " -d" : "");
		if (len >= sizeof bootline) {
			printf("bootargs too long: %s\n", bootline);
			_rtt();
		}
		/* XXX void, for now */
#ifdef DEBUG
		if (debug)
			printf("main: Calling loadfile(fd, %s)\n", bootline);
#endif
		(void)loadfile(fd, bootline);
	}
	return 0;
}


code:
/*	$OpenBSD: disk.h,v 1.1 2014/11/26 20:30:41 stsp Exp $ */

/*
 * Copyright (c) 1997 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#ifndef _DISK_H
#define _DISK_H

#include <sys/queue.h>

/* All the info on a disk we've found */
struct diskinfo {
	char path[256];
	struct disklabel disklabel;
	struct sr_boot_volume *sr_vol;

	TAILQ_ENTRY(diskinfo) list;
};
TAILQ_HEAD(disklist_lh, diskinfo);

/* List of probed disks. */
extern struct disklist_lh disklist;

extern struct diskinfo *bootdev_dip;

#endif /* _DISK_H */


code:
/*	$OpenBSD: diskprobe.c,v 1.3 2014/12/09 18:05:16 stsp Exp $ */

/*
 * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org>
 * Copyright (c) 2014 Stefan Sperling <stsp@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/disklabel.h>

#include <lib/libsa/stand.h>

#include "ofdev.h"
#include "disk.h"
#include "openfirm.h"

/* List of disk devices we found/probed */
struct disklist_lh disklist;

struct diskinfo *bootdev_dip;

void
new_diskinfo(int node)
{
	struct diskinfo *dip;
	struct of_dev ofdev;
	int ihandle = -1;
	int len;
	const char *unit;
	int i;

	dip = alloc(sizeof(*dip));
	bzero(dip, sizeof(*dip));

	len = OF_package_to_path(node, dip->path, sizeof(dip->path));
	if (len < 0) {
		DPRINTF("could not get path for disk node %x\n", node);
		goto bad;
	} else if (len >= sizeof(dip->path)) {
		printf("disk device path too long: %s", dip->path);
		goto bad;
	}
	dip->path[len] = '\0';

	/* If no device unit was supplied by the firmware, add it. */
	unit = NULL;
	for (i = len - 1; i >= 0; i--) {
		if (dip->path[i] == '/')
			break;
		else if (dip->path[i] == '@') {
			unit = &dip->path[i];
			break;
		}
	}
	if (unit == NULL) {
		len = strlcat(dip->path, "@0", sizeof(dip->path));
		if (len >= sizeof(dip->path)) {
			printf("disk device path too long: %s", dip->path);
			goto bad;
		}
	}

	DPRINTF("found disk %s\n", dip->path);

	ihandle = OF_open(dip->path);
	if (ihandle == -1)
		goto bad;

	bzero(&ofdev, sizeof(ofdev));
	ofdev.handle = ihandle;
	ofdev.type = OFDEV_DISK;
	ofdev.bsize = DEV_BSIZE;
	if (load_disklabel(&ofdev, &dip->disklabel) != 0)
		goto bad;
	OF_close(ihandle);
	TAILQ_INSERT_TAIL(&disklist, dip, list);

	return;
bad:
	if (ihandle != -1)
		OF_close(ihandle);
	free(dip, sizeof(*dip));
}

#ifdef BOOT_DEBUG
void dump_node(int node)
{
	char buf[32];

	printf("node %x ", node);
	if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0)
		printf("type %s ", buf);
	if (OF_getprop(node, "name", buf, sizeof(buf)) > 0)
		printf("name %s ", buf);
	printf("\n");
}
#endif

/*
 * Hunt through the device tree for disks.  There should be no need to
 * go more than four levels deep.
 */
void
diskprobe(void)
{
	int node, child, stack[4], depth;
	char buf[32];

	stack[0] = OF_peer(0);
	if (stack[0] == 0)
		return;
	depth = 0;
	TAILQ_INIT(&disklist);

	for (;;) {
		node = stack[depth];

		if (node == 0 || node == -1) {
			if (--depth < 0)
				return;

			stack[depth] = OF_peer(stack[depth]);
			continue;
		}

#ifdef BOOT_DEBUG
		dump_node(node);
#endif
		if ((OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 &&
		    strcmp(buf, "block") == 0 &&
		    OF_getprop(node, "name", buf, sizeof(buf)) > 0 &&
		    strcmp(buf, "disk") == 0)) {
			new_diskinfo(node);
		}

		child = OF_child(node);
		if (child != 0 && child != -1 && depth < 3)
			stack[++depth] = child;
		else
			stack[depth] = OF_peer(stack[depth]);
	}
}


code:
/*	$OpenBSD: elf64_exec.c,v 1.7 2014/11/26 20:30:41 stsp Exp $	*/
/*	$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	ELFSIZE		64
#define	MB		(1024 * 1024)

#define ELF_ALIGN(x)	(((x) + 7) & (~7))

#include <lib/libsa/stand.h>

#include <sys/param.h>
#include <sys/exec_elf.h>

#include <machine/boot_flag.h>

#ifdef SOFTRAID
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/disklabel.h>
#include <dev/biovar.h>
#include <dev/softraidvar.h>

#include "disk.h"
#include "softraid.h"
#endif

#include "openfirm.h"

int
elf64_exec(int fd, Elf_Ehdr *elf, u_int64_t *entryp, void **ssymp, void **esymp){
	Elf_Shdr *shp;
	Elf_Off off;
	void *addr;
	size_t size;
	u_int align;
	int i, first = 1;
	int n;
	struct openbsd_bootdata *obd;
#ifdef SOFTRAID
	struct sr_boot_volume *bv;
#endif

	/*
	 * Don't display load address for ELF; it's encoded in
	 * each section.
	 */
	for (i = 0; i < elf->e_phnum; i++) {
		Elf_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_OPENBSD_BOOTDATA) {
			memset((void *) (long)phdr.p_paddr, 0, phdr.p_filesz);

			if (phdr.p_filesz < sizeof(struct openbsd_bootdata))
				continue;

			obd = (struct openbsd_bootdata *)(long)phdr.p_paddr;
			obd->version = BOOTDATA_VERSION;
			obd->len = sizeof(struct openbsd_bootdata);
#ifdef SOFTRAID
			/*
			 * If booting from softraid we must pass additional
			 * information to the kernel:
			 * 1) The uuid of the softraid volume we booted from.
			 * 2) The maskkey for decryption, if applicable.
			 */
			if (bootdev_dip && bootdev_dip->sr_vol) {
				bv = bootdev_dip->sr_vol;
				memcpy(obd->sr_uuid, bv->sbv_uuid.sui_id,
				    sizeof(obd->sr_uuid));
				if (bv->sbv_maskkey)
					memcpy(obd->sr_maskkey, bv->sbv_maskkey,
					    sizeof(obd->sr_maskkey));
			}

#endif
			continue;
		}

		if (phdr.p_type == PT_OPENBSD_RANDOMIZE) {
			int m, pos;

			/* Fill segment. */
			for (pos = 0; pos < phdr.p_filesz; pos += m) {
				m = MIN(phdr.p_filesz - pos, sizeof(rnddata));
				bcopy(rnddata, (void *)(long)phdr.p_paddr + pos, m);
			}
			continue;
		}

		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 * MB - 1)) == 0)
			align = 4 * MB;
		if (phdr.p_filesz < phdr.p_memsz)
			phdr.p_memsz = roundup(phdr.p_memsz, 4 * MB);
		phdr.p_memsz = roundup(phdr.p_memsz, PAGE_SIZE);
		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(Elf_Ehdr) + (elf->e_shnum * sizeof(Elf_Shdr));
	shp = addr = alloc(elf->e_shnum * sizeof(Elf_Shdr));
	(void)lseek(fd, (off_t)elf->e_shoff, SEEK_SET);
	if (read(fd, addr, (size_t)(elf->e_shnum * sizeof(Elf_Shdr))) !=
	    elf->e_shnum * sizeof(Elf_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;
			continue;
		}
		size += shp->sh_size;
	}
	shp = addr;

	/*
	 * Reserve memory for the symbols.
	 */
	if ((addr = OF_claim(0, roundup(size, PAGE_SIZE), PAGE_SIZE)) == (void *)-1)
		panic("no space for symbol table");

	/*
	 * Copy the headers.
	 */
	elf->e_phoff = 0;
	elf->e_shoff = sizeof(Elf_Ehdr);
	elf->e_phentsize = 0;
	elf->e_phnum = 0;
	bcopy(elf, addr, sizeof(Elf_Ehdr));
	bcopy(shp, addr + sizeof(Elf_Ehdr), elf->e_shnum * sizeof(Elf_Shdr));
	free(shp, elf->e_shnum * sizeof(Elf_Shdr));
	*ssymp = addr;

	/*
	 * Now load the symbol sections themselves.
	 */
	shp = addr + sizeof(Elf_Ehdr);
	size = sizeof(Elf_Ehdr) + (elf->e_shnum * sizeof(Elf_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


code:
/*	$OpenBSD: md5.h,v 1.3 2002/03/14 01:26:46 millert Exp $	*/
/*	$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(MD5_CTX *);
void	MD5Update(MD5_CTX *, const unsigned char *, unsigned int);
void	MD5Final(unsigned char[16], MD5_CTX *);
#ifndef _KERNEL
char	*MD5End(MD5_CTX *, char *);
char	*MD5File(const char *, char *);
char	*MD5Data(const unsigned char *, unsigned int, char *);
#endif /* _KERNEL */
__END_DECLS

#endif /* _SYS_MD5_H_ */


code:
/*	$OpenBSD: net.c,v 1.6 2014/08/21 14:24:08 mpi Exp $	*/
/*	$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 <lib/libsa/stand.h>
#include <lib/libsa/net.h>
#include <lib/libsa/netif.h>

#include "ofdev.h"

static int net_mountroot_bootparams(void);
static int net_mountroot_bootp(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(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(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(void)
{
	/* 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(void)
{
	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(void)
{
	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);
}


code:
/*	$OpenBSD: netif_of.c,v 1.7 2014/08/21 14:24:08 mpi Exp $	*/
/*	$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 <netinet/in.h>
#include <netinet/if_ether.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(int sock)
{
	if (sock != 0)
		return NULL;
	return sockets;
}

int
netif_open(void *machdep_hint)
{
	struct of_dev *op = machdep_hint;
	struct iodesc *io;
	int fd, error;
	char addr[32];

	DNPRINTF(BOOT_D_OFNET, "netif_open...");

	/* find a free socket */
	io = sockets;
	if (io->io_netif) {
		DNPRINTF(BOOT_D_OFNET, "device busy\n");
		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);

	DNPRINTF(BOOT_D_OFNET, "OK\n");
	return 0;
}

int
netif_close(int fd)
{
	struct iodesc *io;
	struct netif *ni;

	DNPRINTF(BOOT_D_OFNET, "netif_close(%x)...", fd);

	if (fd != 0) {
		DNPRINTF(BOOT_D_OFNET, "EBADF\n");
		errno = EBADF;
		return -1;
	}

	io = &sockets[fd];
	ni = io->io_netif;
	if (ni != NULL) {
		ni->nif_devdata = NULL;
		io->io_netif = NULL;
	}

	DNPRINTF(BOOT_D_OFNET, "OK\n");
	return 0;
}

/*
 * Send a packet.  The ether header is already there.
 * Return the length sent (or -1 on error).
 */
ssize_t
netif_put(struct iodesc *desc, void *pkt, size_t len)
{
	struct of_dev *op;
	ssize_t rv;
	size_t sendlen;

	op = desc->io_netif->nif_devdata;

	DNPRINTF(BOOT_D_OFNET, "netif_put: desc=0x%x pkt=0x%x len=%d\n",
	    desc, pkt, len);
	DNPRINTF(BOOT_D_OFNET, "dst: %s, src: %s, type: 0x%x\n",
	    ether_sprintf(((struct ether_header *)pkt)->ether_dhost),
	    ether_sprintf(((struct ether_header *)pkt)->ether_shost),
	    ((struct ether_header *)pkt)->ether_type & 0xFFFF);

	sendlen = len;
	if (sendlen < 60) {
		sendlen = 60;
		DNPRINTF(BOOT_D_OFNET, "netif_put: length padded to %d\n",
		    sendlen);
	}

	rv = OF_write(op->handle, pkt, sendlen);

	DNPRINTF(BOOT_D_OFNET, "netif_put: xmit returned %d\n", rv);

	return rv;
}

/*
 * Receive a packet, including the ether header.
 * Return the total length received (or -1 on error).
 */
ssize_t
netif_get(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;

	DNPRINTF(BOOT_D_OFNET, "netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n",
	    pkt, maxlen, timo);

	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));

	DNPRINTF(BOOT_D_OFNET, "netif_get: received len=%d\n", len);

	if (len < 12)
		return -1;

	DNPRINTF(BOOT_D_OFNET, "dst: %s, src: %s, type: 0x%x\n",
	    ether_sprintf(((struct ether_header *)pkt)->ether_dhost),
	    ether_sprintf(((struct ether_header *)pkt)->ether_shost),
	    ((struct ether_header *)pkt)->ether_type & 0xFFFF);

	return len;
}

/*
 * Shouldn't really be here, but is used solely for networking, so...
 */
time_t
getsecs(void)
{
	return OF_milliseconds() / 1000;
}


code:
/*	$OpenBSD: ofdev.c,v 1.24 2014/12/09 18:05:16 stsp Exp $	*/
/*	$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

#ifdef SOFTRAID
#include <sys/queue.h>
#include <dev/softraidvar.h>
#include "disk.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(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);
		DNPRINTF(BOOT_D_OFDEV, "filename: OF_finddevice(%s) says %x\n",
		    str, dhandle);
		*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 */
				DNPRINTF(BOOT_D_OFDEV, "filename: hunting for "
				    "arguments in %s\n", str);
				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;
				}
			}
			DNPRINTF(BOOT_D_OFDEV, "filename: found %s\n", lp);
			return lp;
		} else if (OF_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0)
			devtype[0] = 0;
	}
	DNPRINTF(BOOT_D_OFDEV, "filename: not found\n", lp);
	return 0;
}

int
strategy(void *devdata, int rw, daddr32_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;
#ifdef SOFTRAID
	/* Intercept strategy for softraid volumes. */
	if (dev->type == OFDEV_SOFTRAID)
		return sr_strategy(bootdev_dip->sr_vol, rw,
		    blk, size, buf, rsize);
#endif
	if (dev->type != OFDEV_DISK)
		panic("strategy");

	DNPRINTF(BOOT_D_OFDEV, "strategy: block %lx, partition offset %lx, "
	    "blksz %lx\n", (long)blk, (long)dev->partoff, (long)dev->bsize);
	DNPRINTF(BOOT_D_OFDEV, "strategy: seek position should be: %lx\n",
	    (long)((blk + dev->partoff) * dev->bsize));
	pos = (u_quad_t)(blk + dev->partoff) * dev->bsize;

	for (;;) {
		DNPRINTF(BOOT_D_OFDEV, "strategy: seeking to %lx\n", (long)pos);
		if (OF_seek(dev->handle, pos) < 0)
			break;
		DNPRINTF(BOOT_D_OFDEV, "strategy: reading %lx at %p\n",
		    (long)size, buf);
		n = OF_read(dev->handle, buf, size);
		if (n == -2)
			continue;
		if (n < 0)
			break;
		*rsize = n;
		return 0;
	}
	return EIO;
}

static int
devclose(struct open_file *of)
{
	struct of_dev *op = of->f_devdata;

#ifdef NETBOOT
	if (op->type == OFDEV_NET)
		net_close(op);
#endif
#ifdef SOFTRAID
	if (op->type == OFDEV_SOFTRAID) {
		op->handle = -1;
		return 0;
	}
#endif
	OF_close(op->handle);
	op->handle = -1;
	return 0;
}

struct devsw devsw[1] = {
	"OpenFirmware",
	strategy,
	(int (*)(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];

static u_long
get_long(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 struct sun_disklabel, assume it has an extended partition
 * table and compute the correct value for sl_xpsum.
 */
static __inline u_int
sun_extended_sum(struct sun_disklabel *sl, void *end)
{
	u_int sum, *xp, *ep;

	xp = (u_int *)&sl->sl_xpmag;
	ep = (u_int *)end;

	sum = 0;
	for (; xp < ep; xp++)
		sum += *xp;
	return (sum);
}

/*
 * Given a SunOS disk label, set lp to a BSD disk label.
 * The BSD label is cleared out before this is called.
 */
static int
disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp)
{
	struct sun_preamble *preamble = (struct sun_preamble *)sl;
	struct sun_partinfo *ppp;
	struct sun_dkpart *spp;
	struct partition *npp;
	u_short cksum = 0, *sp1, *sp2;
	int i, secpercyl;

	/* Verify the XOR check. */
	sp1 = (u_short *)sl;
	sp2 = (u_short *)(sl + 1);
	while (sp1 < sp2)
		cksum ^= *sp1++;
	if (cksum != 0)
		return (EINVAL);	/* SunOS disk label, bad checksum */

	/* Format conversion. */
	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_flags = D_VENDOR;
	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));

	lp->d_secsize = DEV_BSIZE;
	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;
	if (DL_GETDSIZE(lp) == 0)
		DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders);
	lp->d_version = 1;

	memcpy(&lp->d_uid, &sl->sl_uid, sizeof(lp->d_uid));

	lp->d_acylinders = sl->sl_acylinders;

	lp->d_npartitions = MAXPARTITIONS;
	/* 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];
		DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
		DL_SETPSIZE(npp, spp->sdkp_nsectors);
		if (DL_GETPSIZE(npp) == 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_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
			}
		}
	}

	/* Clear "extended" partition info, tentatively */
	for (i = 0; i < SUNXPART; i++) {
		npp = &lp->d_partitions[i+8];
		DL_SETPOFFSET(npp, 0);
		DL_SETPSIZE(npp, 0);
		npp->p_fstype = FS_UNUSED;
	}

	/* Check to see if there's an "extended" partition table
	 * SL_XPMAG partitions had checksums up to just before the
	 * (new) sl_types variable, while SL_XPMAGTYP partitions have
	 * checksums up to the just before the (new) sl_xxx1 variable.
	 * Also, disklabels created prior to the addition of sl_uid will
	 * have a checksum to just before the sl_uid variable.
	 */
	if ((sl->sl_xpmag == SL_XPMAG &&
	    sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_uid) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) {
		/*
		 * There is.  Copy over the "extended" partitions.
		 * This code parallels the loop for partitions a-h.
		 */
		for (i = 0; i < SUNXPART; i++) {
			spp = &sl->sl_xpart[i];
			npp = &lp->d_partitions[i+8];
			DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
			DL_SETPSIZE(npp, spp->sdkp_nsectors);
			if (DL_GETPSIZE(npp) == 0) {
				npp->p_fstype = FS_UNUSED;
				continue;
			}
			npp->p_fstype = FS_BSDFFS;
			npp->p_fragblock =
			    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
			npp->p_cpg = 16;
		}
		if (sl->sl_xpmag == SL_XPMAGTYP) {
			for (i = 0; i < MAXPARTITIONS; i++) {
				npp = &lp->d_partitions[i];
				npp->p_fstype = sl->sl_types[i];
				npp->p_fragblock = sl->sl_fragblock[i];
				npp->p_cpg = sl->sl_cpg[i];
			}
		}
	} else if (preamble->sl_nparts <= 8) {
		/*
		 * A more traditional Sun label.  Recognise certain filesystem
		 * types from it, if they are available.
		 */
		i = preamble->sl_nparts;
		if (i == 0)
			i = 8;

		npp = &lp->d_partitions[i-1];
		ppp = &preamble->sl_part[i-1];
		for (; i > 0; i--, npp--, ppp--) {
			if (npp->p_size == 0)
				continue;
			if ((ppp->spi_tag == 0) && (ppp->spi_flag == 0))
				continue;

			switch (ppp->spi_tag) {
			case SPTAG_SUNOS_ROOT:
			case SPTAG_SUNOS_USR:
			case SPTAG_SUNOS_VAR:
			case SPTAG_SUNOS_HOME:
				npp->p_fstype = FS_BSDFFS;
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
				break;
			case SPTAG_LINUX_EXT2:
				npp->p_fstype = FS_EXT2FS;
				break;
			default:
				/* FS_SWAP for _SUNOS_SWAP and _LINUX_SWAP? */
				npp->p_fstype = FS_UNUSED;
				break;
			}
		}
	}

	lp->d_checksum = 0;
	lp->d_checksum = dkcksum(lp);
	DNPRINTF(BOOT_D_OFDEV, "disklabel_sun_to_bsd: success!\n");
	return (0);
}

/*
 * Find a valid disklabel.
 */
static char *
search_label(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;

	struct disklabel *dlp;
	struct sun_disklabel *slp;
	int error;

	/* minimal requirements for archetypal disk label */
	if (DL_GETDSIZE(lp) == 0)
		DL_SETDSIZE(lp, 0x1fffffff);
	lp->d_npartitions = MAXPARTITIONS;
	if (DL_GETPSIZE(&lp->d_partitions[0]) == 0)
		DL_SETPSIZE(&lp->d_partitions[0], 0x1fffffff);
	DL_SETPOFFSET(&lp->d_partitions[0], 0);

	if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
	    || read != DEV_BSIZE)
		return ("Cannot read label");

	/* Check for a disk label. */
	dlp = (struct disklabel *) (buf + LABELOFFSET);
	if (dlp->d_magic == DISKMAGIC) {
		if (dkcksum(dlp))
			return ("corrupt disk label");
		*lp = *dlp;
		DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n");
		return (NULL);
	}

	/* Check for a Sun disk label (for PROM compatibility). */
	slp = (struct sun_disklabel *)buf;
	if (slp->sl_magic == SUN_DKMAGIC) {
		if (disklabel_sun_to_bsd(slp, lp) != 0)
			return ("corrupt disk label");
		DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n");
		return (NULL);
	}

	return ("no disk label");
}

int
load_disklabel(struct of_dev *ofdev, struct disklabel *label)
{
	char buf[DEV_BSIZE];
	size_t read;
	int error = 0;
	char *errmsg = NULL;

	/* First try to find a disklabel without MBR partitions */
	DNPRINTF(BOOT_D_OFDEV, "load_disklabel: trying to read disklabel\n");
	if (strategy(ofdev, F_READ,
		     LABELSECTOR, DEV_BSIZE, buf, &read) != 0
	    || read != DEV_BSIZE
	    || (errmsg = getdisklabel(buf, label))) {
#ifdef BOOT_DEBUG
		if (errmsg)
			DNPRINTF(BOOT_D_OFDEV,
			    "load_disklabel: getdisklabel says %s\n", errmsg);
#endif
		/* Else try MBR partitions */
		errmsg = search_label(ofdev, LABELSECTOR, buf,
		    label, 0);
		if (errmsg) {
			printf("load_disklabel: search_label says %s\n",
			    errmsg);
			error = ERDLAB;
		}
	}

	return (error);
}

int
devopen(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;
	int error = 0;
#ifdef SOFTRAID
	char volno;
#endif

	if (ofdev.handle != -1)
		panic("devopen");
	if (of->f_flags != F_READ)
		return EPERM;
	DNPRINTF(BOOT_D_OFDEV, "devopen: you want %s\n", name);
	if (strlcpy(fname, name, sizeof fname) >= sizeof fname)
		return ENAMETOOLONG;
#ifdef SOFTRAID
	if (bootdev_dip) {
		if (fname[0] == 's' && fname[1] == 'r' &&
		    '0' <= fname[2] && fname[2] <= '9') {
			volno = fname[2];
			if ('a' <= fname[3] &&
			    fname[3] <= 'a' + MAXPARTITIONS) {
				partition = fname[3];
				if (fname[4] == ':')
					cp = &fname[5];
				else
					cp = &fname[4];
			} else {
				partition = 'a';
				cp = &fname[3];
			}
		} else {
			volno = '0';
			partition = 'a';
			cp = &fname[0];
		}
		snprintf(buf, sizeof buf, "sr%c:%c", volno, partition);
		if (strlcpy(opened_name, buf, sizeof opened_name)
		    >= sizeof opened_name)
			return ENAMETOOLONG;
		*file = opened_name + strlen(opened_name);
		if (!*cp) {
			if (strlcpy(buf, DEFAULT_KERNEL, sizeof buf)
			    >= sizeof buf)
				return ENAMETOOLONG;
		} else {
			if (snprintf(buf, sizeof buf, "%s%s",
			    *cp == '/' ? "" : "/", cp) >= sizeof buf)
				return ENAMETOOLONG;
		}
		if (strlcat(opened_name, buf, sizeof opened_name) >=
		    sizeof opened_name)
			return ENAMETOOLONG;
	} else {
#endif
		cp = filename(fname, &partition);
		if (cp) {
			if (strlcpy(buf, cp, sizeof buf) >= sizeof buf)
				return ENAMETOOLONG;
			*cp = 0;
		}
		if (!cp || !*buf) {
			if (strlcpy(buf, DEFAULT_KERNEL, sizeof buf)
			    >= sizeof buf)
				return ENAMETOOLONG;
		}
		if (!*fname) {
			if (strlcpy(fname, bootdev, sizeof fname)
			    >= sizeof fname)
				return ENAMETOOLONG;
		}
		if (strlcpy(opened_name, fname,
		    partition ? (sizeof opened_name) - 2 : sizeof opened_name)
		    >= sizeof opened_name)
			return ENAMETOOLONG;
		if (partition) {
			cp = opened_name + strlen(opened_name);
			*cp++ = ':';
			*cp++ = partition;
			*cp = 0;
		}
		if (*buf != '/') {
			if (strlcat(opened_name, "/", sizeof opened_name) >=
			    sizeof opened_name)
				return ENAMETOOLONG;
		}
		if (strlcat(opened_name, buf, sizeof opened_name) >=
		    sizeof opened_name)
			return ENAMETOOLONG;
		*file = opened_name + strlen(fname) + 1;
#ifdef SOFTRAID
	}
#endif
	DNPRINTF(BOOT_D_OFDEV, "devopen: trying %s\n", fname);
#ifdef SOFTRAID
	if (bootdev_dip) {
		/* Redirect to the softraid boot volume. */
		struct partition *pp;

		bzero(&ofdev, sizeof ofdev);
		ofdev.type = OFDEV_SOFTRAID;

		if (partition) {
			if (partition < 'a' ||
			    partition >= 'a' + MAXPARTITIONS) {
			    	printf("invalid partition '%c'\n", partition);
				return EINVAL;
			}
			part = partition - 'a';
			pp = &bootdev_dip->disklabel.d_partitions[part];
			if (pp->p_fstype == FS_UNUSED || pp->p_size == 0) {
			    	printf("invalid partition '%c'\n", partition);
				return EINVAL;
			}
			bootdev_dip->sr_vol->sbv_part = partition;
		} else
			bootdev_dip->sr_vol->sbv_part = 'a';

		of->f_dev = devsw;
		of->f_devdata = &ofdev;

#ifdef SPARC_BOOT_UFS
		bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
#else
#error "-DSOFTRAID requires -DSPARC_BOOT_UFS"
#endif
		return 0;
	}
#endif
	if ((handle = OF_finddevice(fname)) == -1)
		return ENOENT;
	DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname);
	if (OF_getprop(handle, "name", buf, sizeof buf) < 0)
		return ENXIO;
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is called %s\n", fname, buf);
	if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0)
		return ENXIO;
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is a %s device\n", fname, buf);
	DNPRINTF(BOOT_D_OFDEV, "devopen: opening %s\n", fname);
	if ((handle = OF_open(fname)) == -1) {
		DNPRINTF(BOOT_D_OFDEV, "devopen: open of %s failed\n", fname);
		return ENXIO;
	}
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname);
	bzero(&ofdev, sizeof ofdev);
	ofdev.handle = handle;
	ofdev.type = OFDEV_DISK;
	ofdev.bsize = DEV_BSIZE;
	if (!strcmp(buf, "block")) {
		error = load_disklabel(&ofdev, &label);
		if (error && error != ERDLAB)
			goto bad;
		else 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;
			DNPRINTF(BOOT_D_OFDEV, "devopen: setting partition %d "
			    "offset %x\n", part, ofdev.partoff);
		}

		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
		DNPRINTF(BOOT_D_OFDEV, "devopen: return 0\n");
		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:
	DNPRINTF(BOOT_D_OFDEV, "devopen: error %d, cannot open device\n",
	    error);
	OF_close(handle);
	ofdev.handle = -1;
	return error;
}


code:
/*	$OpenBSD: ofdev.h,v 1.5 2014/11/26 20:30:41 stsp Exp $	*/
/*	$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_

/* #define BOOT_DEBUG */
#ifdef BOOT_DEBUG
extern u_int32_t boot_debug;
#define DPRINTF(x...)		do { if (boot_debug) printf(x); } while(0)
#define DNPRINTF(n,x...)	do { if (boot_debug & n) printf(x); } while(0)
#define BOOT_D_OFDEV		0x0001
#define BOOT_D_OFNET		0x0002
#else
#define DPRINTF(x...)
#define DNPRINTF(n,x...)
#endif

struct of_dev {
	int handle;
	int type;
	u_long partoff;
	int bsize;
};

/* Known types: */
#define	OFDEV_NET	1
#define	OFDEV_DISK	2
#define	OFDEV_SOFTRAID	3

#define	DEFAULT_KERNEL	"/bsd"

extern char opened_name[];
extern int floppyboot;

int load_disklabel(struct of_dev *, struct disklabel *);
int strategy(void *, int, daddr32_t, size_t, void *, size_t *);

#endif


code:
/*	$OpenBSD: openfirm.h,v 1.6 2014/11/26 19:47:03 stsp Exp $	*/
/*	$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/types.h>
#include <machine/openfirm.h>

#if 0
u_int OF_finddevice(char *name);
u_int OF_instance_to_package(u_int ihandle);
u_int OF_getprop(u_int handle, char *prop, void *buf, int buflen);
#ifdef	__notyet__
int OF_setprop(u_int handle, char *prop, void *buf, int len);
#endif
u_int OF_open(char *dname);
void OF_close(u_int handle);
int OF_write(u_int handle, void *addr, int len);
int OF_read(u_int handle, void *addr, int len);
int OF_seek(u_int handle, u_int64_t pos);
#endif
void *OF_claim(void *virt, u_int size, u_int align);
void OF_release(void *virt, u_int size);
int OF_milliseconds(void);
void OF_chain(void *addr, u_int size, void (*entry)(), void *parm, u_int parmlen);
int OF_peer(int);
int OF_child(int);
int OF_package_to_path(int, char *, int);