summaryrefslogtreecommitdiff
path: root/sys/arch/hppa64/stand
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2005-04-01 10:40:50 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2005-04-01 10:40:50 +0000
commit086e003dd29b7c42921a44eb7af336bacfc10d4d (patch)
treea901551a395f9d10ee4d44cef80ec86a4dd5ae0c /sys/arch/hppa64/stand
parent4082d6812410636300be23e2010448febcf6e5d9 (diff)
small batch early bottling hppa64 port
matured in mighty ukrainian oak for 23 months
Diffstat (limited to 'sys/arch/hppa64/stand')
-rw-r--r--sys/arch/hppa64/stand/Makefile11
-rw-r--r--sys/arch/hppa64/stand/Makefile.inc44
-rw-r--r--sys/arch/hppa64/stand/boot/Makefile60
-rw-r--r--sys/arch/hppa64/stand/boot/boot.8342
-rw-r--r--sys/arch/hppa64/stand/boot/conf.c51
-rw-r--r--sys/arch/hppa64/stand/boot/exec.c42
-rw-r--r--sys/arch/hppa64/stand/boot/ld.script61
-rw-r--r--sys/arch/hppa64/stand/boot/srt0.S181
-rw-r--r--sys/arch/hppa64/stand/cdboot/Makefile55
-rw-r--r--sys/arch/hppa64/stand/cdboot/cdboot.c82
-rw-r--r--sys/arch/hppa64/stand/cdboot/ld.script49
-rw-r--r--sys/arch/hppa64/stand/libkern/Makefile29
-rw-r--r--sys/arch/hppa64/stand/libsa/Makefile43
-rw-r--r--sys/arch/hppa64/stand/libsa/cmd_hppa64.c819
-rw-r--r--sys/arch/hppa64/stand/libsa/ct.c71
-rw-r--r--sys/arch/hppa64/stand/libsa/dev_hppa64.c228
-rw-r--r--sys/arch/hppa64/stand/libsa/dev_hppa64.h43
-rw-r--r--sys/arch/hppa64/stand/libsa/dk.c101
-rw-r--r--sys/arch/hppa64/stand/libsa/itecons.c212
-rw-r--r--sys/arch/hppa64/stand/libsa/lf.c44
-rw-r--r--sys/arch/hppa64/stand/libsa/libsa.h72
-rw-r--r--sys/arch/hppa64/stand/libsa/lif.c261
-rw-r--r--sys/arch/hppa64/stand/libsa/machdep.c75
-rw-r--r--sys/arch/hppa64/stand/libsa/pdc.c448
-rw-r--r--sys/arch/hppa64/stand/libsa/time.c47
-rw-r--r--sys/arch/hppa64/stand/libz/Makefile10
-rw-r--r--sys/arch/hppa64/stand/mkboot/Makefile14
-rw-r--r--sys/arch/hppa64/stand/mkboot/mkboot.858
-rw-r--r--sys/arch/hppa64/stand/mkboot/mkboot.c430
29 files changed, 3983 insertions, 0 deletions
diff --git a/sys/arch/hppa64/stand/Makefile b/sys/arch/hppa64/stand/Makefile
new file mode 100644
index 00000000000..296da014aa6
--- /dev/null
+++ b/sys/arch/hppa64/stand/Makefile
@@ -0,0 +1,11 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $
+
+.if ${MACHINE} == "hppa64"
+SUBDIR= libsa libkern libz
+.endif
+SUBDIR+= mkboot boot
+.if ${MACHINE} == "hppa64"
+#SUBDIR+= cdboot
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/hppa64/stand/Makefile.inc b/sys/arch/hppa64/stand/Makefile.inc
new file mode 100644
index 00000000000..2f7a45dcf73
--- /dev/null
+++ b/sys/arch/hppa64/stand/Makefile.inc
@@ -0,0 +1,44 @@
+# $OpenBSD: Makefile.inc,v 1.1 2005/04/01 10:40:48 mickey Exp $
+
+CFLAGS=${DEBUG} -Os -Wall -Werror
+CPPFLAGS+=-I${S} -I. -I${.CURDIR} -Derrno=errno
+SACFLAGS=-nostdinc -fno-builtin -D_STANDALONE -I${STANDIR}/libsa
+SACFLAGS+=-mdisable-fpregs -fno-stack-protector
+#DEBUGFLAGS=-DDEBUG
+#DEBUGFLAGS+=-DPDCDEBUG
+#DEBUGFLAGS+=-DLIFDEBUG
+#DEBUGFLAGS+=-DEXEC_DEBUG
+#DEBUGFLAGS+=-DALLOC_TRACE
+LINKADDR=0x780000
+LOADADDR=0x780000
+HEAP_LIMIT=0x7f8000
+CLEANFILES+= machine
+DEBUGLIBS= no
+
+.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(kernlibdir) && !make(obj) && !(defined(PROG) && ${PROG} == "mkboot")
+.BEGIN:
+ @([ -h machine ] || ln -s $(S)/arch/hppa64/include machine)
+.endif
+
+.if exists(${STANDIR}/libsa/libsa.a)
+LIBSA=${STANDIR}/libsa/libsa.a
+.else
+LIBSA=${STANDIR}/libsa/${__objdir}/libsa.a
+.endif
+.if exists(${STANDIR}/libkern/libkern.a)
+LIBKERN=${STANDIR}/libkern/libkern.a
+.else
+LIBKERN=${STANDIR}/libkern/${__objdir}/libkern.a
+.endif
+.if exists(${STANDIR}/libz/libz.a)
+LIBZ=${STANDIR}/libz/libz.a
+.else
+LIBZ=${STANDIR}/libz/${__objdir}/libz.a
+.endif
+.if exists(${STANDIR}/mkboot/mkboot)
+MKBOOT=${STANDIR}/mkboot/mkboot
+.else
+MKBOOT=${STANDIR}/mkboot/${__objdir}/mkboot
+.endif
+
+BINDIR= /usr/mdec
diff --git a/sys/arch/hppa64/stand/boot/Makefile b/sys/arch/hppa64/stand/boot/Makefile
new file mode 100644
index 00000000000..dd9bc44c62f
--- /dev/null
+++ b/sys/arch/hppa64/stand/boot/Makefile
@@ -0,0 +1,60 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $
+
+MAN= boot.8
+MANSUBDIR=hppa64
+MLINKS= boot.8 boot.conf.8
+S =${.CURDIR}/../../../..
+CLEANFILES+= boot.gdb boot.map boot.lif
+
+.if ${MACHINE} == "hppa64"
+PROG= boot
+SRCS= srt0.S exec.c boot.c cmd.c vars.c bootarg.c conf.c
+LD?= ld
+LDFLAGS+=-Bstatic -nostartfiles -nostdlib -N -Ttext $(LINKADDR)
+LDFLAGS+=-T ${.CURDIR}/ld.script -Map boot.map
+LDFLAGS+=--warn-constructors --warn-common
+SIZE?= size
+STRIP?= strip
+STANDIR=${.CURDIR}/..
+CRTBEGIN=
+CRTEND=
+LINKS= ${BINDIR}/boot.lif ${BINDIR}/sdboot \
+ ${BINDIR}/boot.lif ${BINDIR}/stboot \
+ ${BINDIR}/boot.lif ${BINDIR}/xxboot
+
+LDADD= ${LIBSA} ${LIBZ} ${LIBKERN}
+DPADD= ${LIBSA} ${LIBZ} ${LIBKERN}
+
+.PATH: ${S}/stand/boot
+
+all: boot.lif
+
+realinstall:
+ ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ boot ${DESTDIR}${BINDIR}
+ ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ boot.lif ${DESTDIR}${BINDIR}
+
+.if exists(${.CURDIR}/../../compile/GENERIC/bsd)
+bsd: ${.CURDIR}/../../compile/GENERIC/bsd
+ gzip -9 -c ${.CURDIR}/../../compile/GENERIC/bsd > bsd
+ADDBOOT+=bsd
+.endif
+
+# probably we should check for 256k limit for ISL
+boot.lif: ${PROG} ${ADDBOOT}
+ -@cp ${PROG} ${PROG}.gdb
+ ${STRIP} ${PROG}
+ ${MKBOOT} -v ${PROG} ${ADDBOOT} boot.lif
+
+${PROG}: $(OBJS) $(DPADD)
+ $(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDADD)
+ @${SIZE} $(PROG)
+.else
+NOPROG=
+.endif
+
+.include <bsd.prog.mk>
+
+CPPFLAGS+=${DEBUGFLAGS} -DRELOC=${LOADADDR} -DHEAP_LIMIT=${HEAP_LIMIT}
+CFLAGS+=$(SACFLAGS)
diff --git a/sys/arch/hppa64/stand/boot/boot.8 b/sys/arch/hppa64/stand/boot/boot.8
new file mode 100644
index 00000000000..4b52dabbe02
--- /dev/null
+++ b/sys/arch/hppa64/stand/boot/boot.8
@@ -0,0 +1,342 @@
+.\" $OpenBSD: boot.8,v 1.1 2005/04/01 10:40:48 mickey Exp $
+.\"
+.\" Copyright (c) 2002 Miodrag Vallat
+.\" Copyright (c) 1997-2005 Michael Shalayeff
+.\" 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 AUTHOR OR HIS RELATIVES 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 MIND, 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.
+.\"
+.\"
+.Dd March 16, 2005
+.Dt BOOT 8 hppa
+.Os
+.Sh NAME
+.Nm boot ,
+.Nm boot.conf
+.Nd
+hppa-specific bootstrap
+.Sh DESCRIPTION
+The main purpose of this program is to load the system kernel while dealing
+with the various features of the PA-RISC hardware.
+.Pp
+As described in
+.Xr boot_hppa 8 ,
+this program is loaded by the PDC firmware
+and provides a convenient way to load the kernel.
+.Pp
+Basic operations include:
+.Pp
+.Bl -bullet -compact
+.It
+Loading kernels from any device supported by your system.
+.It
+Loading kernels compressed by
+.Xr gzip 1 .
+.It
+Providing an interactive command line.
+.It
+Detecting and switching between multiple consoles.
+.El
+.Pp
+The sequence of its operation is as follows: initialization,
+parsing the configuration file, then an interactive command line.
+While at the command line you have 5 seconds to type any commands, if needed.
+If time expires, the kernel will be loaded according to
+the current variable settings (see the
+.Nm set
+command).
+Each time a kernel load fails, the timeout is increased by one second.
+The sequence of
+.Nm
+operations is as follows:
+.Bl -enum
+.It
+If the file
+.Pa /etc/boot.conf
+exists on the filesystem or LIF image
+.Nm
+was loaded from, open and parse it.
+This file may contain any commands
+.Nm
+accepts at the interactive prompt.
+Though default settings usually suffice, they can be changed here.
+.It
+The header line
+.Pp
+.Dl >> OpenBSD/hppa BOOT [x.xx]
+.Pp
+is displayed to the active console, where
+.Ar x.xx
+is the version number of the
+.Nm
+program, followed by the
+.Pp
+.Dl boot>
+.Pp
+prompt, which means you are in interactive mode and may enter commands.
+If you do not,
+.Nm
+will proceed to load the kernel with the current parameters after the
+timeout period has expired.
+.El
+.Pp
+By default,
+.Nm
+attempts to load the kernel executable
+.Pa /bsd .
+If that fails, it will attempt to load
+.Pa /obsd
+and then
+.Pa /bsd.old .
+If it fails to find any of these files,
+and no alternative kernel image has been specified,
+the system will be unable to boot.
+.Sh COMMANDS
+The following commands are accepted at the
+.Nm
+prompt:
+.Bl -tag -width shorten
+.It boot Op Ar image Op Fl acds
+Boots the kernel image specified by
+.Ar image
+with any options given.
+Image specification consists of a pair
+.Ar device : Ns Ar filename ;
+either or both can be omitted (`:' is not needed if both are omitted),
+in which case values from
+.Nm
+variables will be used.
+.Bl -tag -width _a_
+.It Fl a
+Causes the kernel to ask for the
+.Nm root
+device to use.
+.It Fl c
+Causes the kernel to go into
+.Xr boot_config 8
+before performing
+.Xr autoconf 4
+procedures.
+.It Fl d
+Causes the kernel to drop into
+.Xr ddb 4
+at the earliest convenient point.
+.It Fl s
+Causes the kernel to boot single-user.
+.El
+.It echo Op Ar args
+Displays
+.Ar args
+on the console device.
+.It help
+Prints a list of available commands and machine dependent
+commands, if any.
+.It machine Op Ar command
+Issues machine-dependent commands.
+These are defined for hppa architecture:
+.Bl -tag -width keyboard
+.It Nm console
+Displays or sets the console path.
+.Pp
+When invoked with no argument, this command will display the configured
+console path found in the stable storage area.
+.Pp
+Otherwise, the argument will be interpreted as a console path
+definition string, and
+.Nm
+will attempt to switch the console configuration to the desired device.
+The console definition attempts to follow the PDC syntax,
+and would have a form of:
+.Pp
+.Bd -filled -compact
+graphics
+.Op _head
+.Op .mode
+.Ed
+for graphics console, and
+.Pp
+.Bd -filled -compact
+rs232
+.Op _2
+.Op .speed Op .bits Op .parity
+.Ed
+for serial console.
+.Pp
+The default head and mode for graphics console are 0, that is the default
+videomode of the first graphics device.
+The default serial settings are 9600 bps, 8 data bits, and no parity.
+.It Nm keyboard
+Displays or sets the keyboard path.
+.Pp
+When invoked with no argument, this command will display the configured
+keyboard path found in the stable storage area.
+.Pp
+Otherwise, the argument will be interpreted as a keyboard path definition
+string, and
+.Nm
+will attempt to switch the keyboard configuration to the desired port.
+The keyboard definition attempts to follow the PDC syntax,
+and would have a form of:
+.Pp
+.Bd -filled -compact
+hil
+.Ed
+for hil keyboard, and
+.Pp
+.Bd -filled -compact
+ps2
+.Ed
+for PS/2 keyboard.
+.El
+.Pp
+After changing any path settings, the machine usually has to be restarted for
+the changes to have effect.
+.It ls Op Ar directory
+Prints contents of the specified
+.Ar directory
+in long format including: attributes and file type, owner, group,
+size, filename.
+.It reboot
+Reboots the machine by initiating a warm boot procedure.
+.It set Op Ar varname Op Ar value
+If invoked without arguments, prints a list of variables and their values.
+If only
+.Ar varname
+is specified, displays contents of that variable.
+If
+.Ar varname
+and
+.Ar value
+are both specified, sets that variable to the given value.
+Variables include:
+.Pp
+.Bl -tag -compact -width boothow
+.It Nm addr
+Address at which to load the kernel.
+.It Nm debug
+Debug flag if
+.Nm
+was compiled with DEBUG defined.
+.It Nm device
+Boot device name (i.e.,
+.Li lf0a ,
+.Li sd0a ) .
+.It Nm howto
+Options to pass to the loaded kernel.
+.It Nm image
+File name containing the kernel image.
+.It Nm timeout
+Number of seconds boot will wait for human intervention before
+booting the default kernel image.
+.\" .It Nm tty
+.\" Active console device name (i.e.,
+.\" .Li ttya ,
+.\" .Li ttyb ,
+.\" .Li ite0) .
+.El
+.\" .It stty Op Ar device Op Ar speed
+.\" Displays or sets the
+.\" .Ar speed
+.\" for a console
+.\" .Ar device .
+.\" If changing the baudrate for the currently active console,
+.\" .Nm
+.\" offers you five seconds of grace time before committing the change
+.\" to allow you to change your terminal's speed to match.
+.\" If changing speed
+.\" .Em not
+.\" for the active console, the baudrate is set for the
+.\" .Em next
+.\" time you switch to a serial console.
+.\" The baudrate value is not used for the
+.\" .Li ite0
+.\" console.
+.\" .Pp
+.\" The default baudrate is 9600bps.
+.It time
+Displays system time and date.
+.El
+.Sh FILES
+.Bl -tag -width /etc/boot.conf -compact
+.It Pa /boot
+system bootstrap
+.It Pa /etc/boot.conf
+system bootstrap's startup file
+.It Pa /bsd
+kernel image
+.El
+.Sh EXAMPLES
+Boot the default kernel:
+.Pp
+.Dl boot> boot
+.Pp
+Remove the 5 second pause at boot-time permanently, causing
+.Nm
+to load the kernel immediately without prompting:
+.Pp
+.Dl # echo \&"boot\&" > /etc/boot.conf
+.Pp
+Use serial console on the first serial port, with the usual 9600 8N1 settings.
+A null modem cable should connect the specified serial port to a terminal.
+Useful for debugging.
+.Pp
+.Dl boot> machine console rs232.9600.8.none
+.Pp
+Boot the kernel named
+.Pa /bsd
+from the second SCSI disk in
+.Dq User Kernel Configuration
+mode (see
+.Xr boot_config 8 ) .
+This mechanism allows for the explicit enabling and disabling of devices
+during the current boot sequence, as well as the modification
+of device parameters.
+Once booted, such changes can be made permanent by using
+.Xr config 8 Ns 's
+.Fl e
+option.
+.Pp
+.Dl boot> boot sd1a:/bsd -c
+.Sh SEE ALSO
+.Xr gzip 1 ,
+.Xr autoconf 4 ,
+.Xr ddb 4 ,
+.Xr boot_config 8 ,
+.Xr boot_hppa 8 ,
+.\" .Xr installboot 8 ,
+.Xr reboot 8
+.Pp
+RFC 1950 describes the zlib library interface.
+.Pp
+The official home page for the version of zlib used in this
+operating system see http://quest.jpl.nasa.gov/zlib/.
+.Sh HISTORY
+This program was written by Michael Shalayeff for
+.Ox 2.1 .
+The hppa specific parts were written by Michael Shalayeff and Miodrag Vallat
+for
+.Ox 3.1 .
+.Sh CAVEATS
+Making mistakes in console paths may cost you a toupee.
+.Sh BUGS
+Changing the display resolution (mode) on a graphics console does not work
+correctly.
diff --git a/sys/arch/hppa64/stand/boot/conf.c b/sys/arch/hppa64/stand/boot/conf.c
new file mode 100644
index 00000000000..91ecd77b2b1
--- /dev/null
+++ b/sys/arch/hppa64/stand/boot/conf.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: conf.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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/types.h>
+#include <libsa.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libsa/cd9660.h>
+#include <dev/cons.h>
+
+const char version[] = "0.8";
+int debug = 0;
+
+struct fs_ops file_system[] = {
+ { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek,
+ ufs_stat, ufs_readdir },
+ { cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek,
+ cd9660_stat, cd9660_readdir },
+ { lif_open, lif_close, lif_read, lif_write, lif_seek,
+ lif_stat, lif_readdir },
+};
+int nfsys = NENTS(file_system);
+
+struct devsw devsw[] = {
+ { "dk", iodcstrategy, dkopen, dkclose, noioctl },
+ { "ct", iodcstrategy, ctopen, ctclose, noioctl },
+ { "lf", iodcstrategy, lfopen, lfclose, noioctl }
+};
+int ndevs = NENTS(devsw);
+
+struct consdev constab[] = {
+ { ite_probe, ite_init, ite_getc, ite_putc },
+ { NULL }
+};
+struct consdev *cn_tab;
+
diff --git a/sys/arch/hppa64/stand/boot/exec.c b/sys/arch/hppa64/stand/boot/exec.c
new file mode 100644
index 00000000000..adc206b3a19
--- /dev/null
+++ b/sys/arch/hppa64/stand/boot/exec.c
@@ -0,0 +1,42 @@
+/* $OpenBSD: exec.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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 <machine/pdc.h>
+#include "libsa.h"
+#include <lib/libsa/loadfile.h>
+#include <stand/boot/bootarg.h>
+#include "dev_hppa64.h"
+
+typedef void (*startfuncp)(int, int, int, int, int, int, caddr_t)
+ __attribute__ ((noreturn));
+
+void
+run_loadfile(u_long *marks, int howto)
+{
+ fcacheall();
+
+ __asm("mtctl %r0, %cr17");
+ __asm("mtctl %r0, %cr17");
+ /* stack and the gung is ok at this point, so, no need for asm setup */
+ (*(startfuncp)(marks[MARK_ENTRY]))((int)(long)(long)pdc, howto, bootdev,
+ marks[MARK_END], BOOTARG_APIVER, BOOTARG_LEN, (caddr_t)BOOTARG_OFF);
+
+ /* not reached */
+}
diff --git a/sys/arch/hppa64/stand/boot/ld.script b/sys/arch/hppa64/stand/boot/ld.script
new file mode 100644
index 00000000000..51aed14df19
--- /dev/null
+++ b/sys/arch/hppa64/stand/boot/ld.script
@@ -0,0 +1,61 @@
+/* $OpenBSD: ld.script,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+OUTPUT_FORMAT("elf64-hppa")
+OUTPUT_ARCH(hppa2.0w)
+ENTRY(begin)
+
+SECTIONS {
+
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .text : {
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata1)
+ *($CODE$)
+ etext = .;
+ } = 0x08000240
+
+ /* Read-write sections, merged into data segment: */
+ .data : {
+ $global$ = .;
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ edata = ABSOLUTE(.);
+ } = 0
+
+ .opd : { *(.opd) }
+ PROVIDE(__gp = .);
+ .plt : { *(.plt) }
+ .dlt : { *(.dlt) }
+
+ .bss : {
+ __bss_start = .;
+ *(.dynbss)
+ *(.bss)
+ *(.sbss)
+ *(.scommon)
+ *(COMMON)
+ end = ABSOLUTE(.);
+ __bss_end = .;
+ }
+
+ /* don't need an unwind in the boot, unless we'll have a boot-ddb (; */
+ /DISCARD/ :
+ {
+ *(.PARISC.unwind)
+ *(.exitcall.exit)
+ *(.interp)
+ *(.dynsym)
+ *(.dynstr)
+ *(.dynamic)
+ *(.hash)
+ *(.stub)
+ }
+}
+
diff --git a/sys/arch/hppa64/stand/boot/srt0.S b/sys/arch/hppa64/stand/boot/srt0.S
new file mode 100644
index 00000000000..99498dbf970
--- /dev/null
+++ b/sys/arch/hppa64/stand/boot/srt0.S
@@ -0,0 +1,181 @@
+/* $OpenBSD: srt0.S,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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.
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+;
+; Copyright (c) 1990 mt Xinu, Inc. All rights reserved.
+; Copyright (c) 1990 University of Utah. All rights reserved.
+;
+; This file may be freely distributed in any form as long as
+; this copyright notice is included.
+; THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+; IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+; WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;
+; Utah $Hdr: srt0.c 1.3 94/12/13$
+;
+
+#define _LOCORE
+#include <machine/iomod.h>
+#include <machine/asm.h>
+#include <machine/frame.h>
+
+/*
+ * This is the ending of the begin
+ */
+ENTRY(begin,0)
+
+ blr %r0,%r5 ; Get address of 'boff' into 'r5',
+ ldo begin-boff(%r5),%r5 ; and subtract to get 'begin'.
+boff
+ ldil L%RELOC,%r4
+ ldo R%RELOC(%r4),%r4
+ ldo start-begin(%r4),%rp
+ ldil L%edata,%r3
+ ldo R%edata(%r3),%r3 ; Get address of edata.
+ ldil L%begin,%r1
+ ldo R%begin(%r1),%r1 ; Get address of begin
+ sub %r3,%r1,%r3 ; Subtract to get # of bytes to copy
+copyloop ; do
+ ldwm 4(%r5),%r1 ; *r4++ = *r5++;
+ addib,>= -4,%r3,copyloop ; while (--r3 >= 0);
+ stwm %r1,4(%r4)
+
+ ; here we zero the .bss
+ ldil L%__bss_start, %r4
+ ldo R%__bss_start(%r4), %r4
+ ldil L%__bss_end, %r3
+ ldo R%__bss_end(%r3), %r3
+zeroloop
+ combf,<,n %r3,%r4, zeroloop ; while (r4 < r3);
+ stwm %r0,4(%r4) ; *r4++ = 0;
+
+ ldil L%$global$,%dp
+ ldo R%$global$(%dp),%dp
+ ldil L%start,%r1
+ ldo R%start(%r1),%r1
+ sub %dp,%r1,%dp ; Subtract to get difference
+ add %rp,%dp,%dp ; and relocate it.
+
+;
+; We have relocated ourself to RELOC. If we are running on a machine
+; with separate instruction and data caches, we must flush our data
+; cache before trying to execute the code starting at rp.
+;
+ ldil L%RELOC,%r22 ; Set %t1 to start of relocated code.
+ ldo R%RELOC(%r22),%r22
+ ldil L%edata,%r21 ; Set r21 to address of edata
+ ldo R%edata(%r21),%r21
+ ldil L%begin,%r1 ; set %r1 to address of begin
+ ldo R%begin(%r1),%r1
+ sub %r21,%r1,%r21 ; Subtract to get length
+ mtsp %r0,%sr0 ; Set sr0 to kernel space.
+ ldo -1(%r21),%r21
+ fdc %r21(0,%r22)
+loop addib,>,n -16,%r21,loop ; Decrement by cache line size (16).
+ fdc %r21(%sr0,%r22)
+ fdc 0(%sr0,%r22) ; Flush first word at addr to handle
+ sync ; arbitrary cache line boundary.
+ nop ; Prevent prefetching.
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ bv 0(%rp)
+ nop
+EXIT(begin) /* jump to relocated code */
+
+start
+ ldil L%HEAP_LIMIT, %sp
+ ldo R%HEAP_LIMIT(%sp), %sp
+
+ .import bootprompt, data
+ ldil L%bootprompt, %r1
+ stw %arg0, R%bootprompt(%r1)
+ b boot ; Call boot(),
+ copy %r0, %arg0 ; use default boot device
+ nop
+
+/*
+ * rtt - restart the box
+ */
+LEAF_ENTRY(_rtt)
+ ldil L%LBCAST_ADDR, %arg1
+ ldi CMD_RESET, %arg0
+ stw %arg0, R%iomod_command(%arg1)
+forever ; Loop until bus reset takes effect.
+ b,n forever
+
+ bv 0(%rp)
+ ldo -48(%sp),%sp
+EXIT(_rtt)
+
+ENTRY(pdc_call,96)
+ copy %r3, %r1
+ std %rp, HPPA_FRAME_RP(%sp)
+ copy %sp, %r3
+ std,ma %r1, HPPA_FRAME_SIZE+8*4(%sp)
+
+ copy %arg0, %r1
+ copy %arg1, %arg0
+ copy %arg2, %arg1
+ copy %arg3, %arg2
+ copy arg4, %arg3
+ stw arg5, -(32 + 4*(4 + 1))(%sp)
+ stw arg6, -(32 + 4*(5 + 1))(%sp)
+ stw arg7, -(32 + 4*(6 + 1))(%sp)
+ ldw 0(ap), arg5
+ ldw 8(ap), arg6
+ ldw 16(ap), arg7
+ stw arg5, -(32 + 4*(7 + 1))(%sp)
+ stw arg6, -(32 + 4*(8 + 1))(%sp)
+ stw arg7, -(32 + 4*(9 + 1))(%sp)
+
+ .call
+ blr %r0, %rp
+ bv,n %r0(%r1)
+ nop
+
+ ldd HPPA_FRAME_RP(%r3), %rp
+ bv %r0(%rp)
+ ldd,mb -(HPPA_FRAME_SIZE+8*4)(%sp), %r3
+EXIT(pdc_call)
+
+ .end
diff --git a/sys/arch/hppa64/stand/cdboot/Makefile b/sys/arch/hppa64/stand/cdboot/Makefile
new file mode 100644
index 00000000000..6ff9c00821a
--- /dev/null
+++ b/sys/arch/hppa64/stand/cdboot/Makefile
@@ -0,0 +1,55 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $
+
+NOMAN= no man
+S =${.CURDIR}/../../../..
+CLEANFILES+= cdboot.gdb cdboot.map
+
+.if ${MACHINE} == "hppa64"
+
+PROG= cdboot
+SRCS= srt0.S cdboot.c pdc.c itecons.c dev_hppa64.c dk.c
+LD?= ld
+LDFLAGS+=-Bstatic -nostartfiles -nostdlib -N -Ttext $(LINKADDR)
+LDFLAGS+=-T ${.CURDIR}/ld.script -Map cdboot.map
+SIZE?= size
+STRIP?= strip
+STANDIR=${.CURDIR}/..
+CRTBEGIN=
+CRTEND=
+
+SAREL=
+USE_LOADFILE=yes
+.include "${S}/lib/libsa/Makefile.inc"
+DPADD+= $(SALIB) $(LIBKERN)
+LDADD+= $(SALIB) $(LIBKERN)
+
+.PATH: ${S}/stand/boot
+.PATH: ${.CURDIR}/../boot
+.PATH: ${.CURDIR}/../libsa
+
+all: ${PROG}
+
+clean::
+ rm -f a.out [Ee]rrs mklog core *.core \
+ ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES}
+
+realinstall:
+ ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${PROG} ${DESTDIR}${BINDIR}
+
+# TODO check for <=32k
+${PROG}: $(OBJS) $(DPADD)
+ $(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDADD)
+ @cp ${PROG} ${PROG}.gdb
+ ${STRIP} ${PROG}
+ @${SIZE} $(PROG)
+ @${MKBOOT} -v ${PROG} ${PROG}.lif
+ @mv ${PROG}.lif ${PROG}
+.else
+NOPROG=
+.endif
+
+.include <bsd.prog.mk>
+
+CPPFLAGS+=-DRELOC=${LOADADDR} -DHEAP_LIMIT=${HEAP_LIMIT}
+CFLAGS+=$(SACFLAGS) -I../.. -I${.CURDIR}/../libsa -I${S}/stand/boot
diff --git a/sys/arch/hppa64/stand/cdboot/cdboot.c b/sys/arch/hppa64/stand/cdboot/cdboot.c
new file mode 100644
index 00000000000..2ceb33315df
--- /dev/null
+++ b/sys/arch/hppa64/stand/cdboot/cdboot.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: cdboot.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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/reboot.h>
+#include <sys/stat.h>
+#include <libsa.h>
+#include <lib/libsa/cd9660.h>
+#include <lib/libsa/loadfile.h>
+#include <dev/cons.h>
+#include <machine/pdc.h>
+#include <stand/boot/bootarg.h>
+#include "dev_hppa64.h"
+#include "cmd.h"
+
+dev_t bootdev;
+int debug = 1;
+int bootprompt = 1;
+
+struct fs_ops file_system[] = {
+ { cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek,
+ cd9660_stat, cd9660_readdir },
+};
+int nfsys = NENTS(file_system);
+
+struct devsw devsw[] = {
+ { "dk", iodcstrategy, dkopen, dkclose, noioctl },
+};
+int ndevs = NENTS(devsw);
+
+struct consdev constab[] = {
+ { ite_probe, ite_init, ite_getc, ite_putc },
+ { NULL }
+};
+struct consdev *cn_tab;
+
+typedef void (*startfuncp)(int, int, int, int, int, int, caddr_t)
+ __attribute__ ((noreturn));
+
+void
+boot(dev_t dev)
+{
+ u_long marks[MARK_MAX];
+ char path[128];
+
+ pdc_init();
+ cninit();
+ devboot(dev, path);
+ strncpy(path + strlen(path), ":/bsd.rd", 9);
+ printf(">> OpenBSD/" MACHINE " CDBOOT 0.1\n"
+ "booting %s: ", path);
+
+ marks[MARK_START] = (u_long)DEFAULT_KERNEL_ADDRESS;
+ if (!loadfile(path, marks, LOAD_KERNEL)) {
+ marks[MARK_END] = ALIGN(marks[MARK_END] -
+ (u_long)DEFAULT_KERNEL_ADDRESS);
+ fcacheall();
+
+ __asm("mtctl %r0, %cr17");
+ __asm("mtctl %r0, %cr17");
+ (*(startfuncp)(marks[MARK_ENTRY]))((int)(long)pdc, 0, bootdev,
+ marks[MARK_END], BOOTARG_APIVER, BOOTARG_LEN,
+ (caddr_t)BOOTARG_OFF);
+ /* not reached */
+ }
+}
diff --git a/sys/arch/hppa64/stand/cdboot/ld.script b/sys/arch/hppa64/stand/cdboot/ld.script
new file mode 100644
index 00000000000..b36df9be9e4
--- /dev/null
+++ b/sys/arch/hppa64/stand/cdboot/ld.script
@@ -0,0 +1,49 @@
+/* $OpenBSD: ld.script,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+OUTPUT_FORMAT("elf64-hppa")
+OUTPUT_ARCH(hppa2.0w)
+ENTRY(begin)
+
+SECTIONS {
+
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .text : {
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata1)
+ *($CODE$)
+ etext = .;
+ } = 0x08000240
+
+ /* Read-write sections, merged into data segment: */
+ .data : {
+ $global$ = .;
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ edata = ABSOLUTE(.);
+ } = 0
+
+ .bss : {
+ __bss_start = .;
+ *(.dynbss)
+ *(.bss)
+ *(.sbss)
+ *(.scommon)
+ *(COMMON)
+ end = ABSOLUTE(.);
+ __bss_end = .;
+ }
+
+ /* don't need an unwind in the boot, unless we'll have a boot-ddb (; */
+ /DISCARD/ :
+ {
+ *(.PARISC.unwind)
+ }
+}
+
diff --git a/sys/arch/hppa64/stand/libkern/Makefile b/sys/arch/hppa64/stand/libkern/Makefile
new file mode 100644
index 00000000000..6815b67c49b
--- /dev/null
+++ b/sys/arch/hppa64/stand/libkern/Makefile
@@ -0,0 +1,29 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $
+
+LIB= kern
+
+S= ${.CURDIR}/../../../..
+M= ${KERNDIR}/arch/${MACHINE_ARCH}
+SADIR= ${.CURDIR}/..
+KERNDIR=$S/lib/libkern
+
+NOPIC= nopic
+NOPROFILE= noprofile
+
+.PATH: ${KERNDIR}
+
+.include "arch/hppa64/Makefile.inc"
+
+# Quad support
+SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
+ lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
+ subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
+
+# Other stuff
+SRCS+= srandom.c bcd.c
+
+install:
+
+.include <bsd.lib.mk>
+CPPFLAGS+= ${DEBUGFLAGS}
+CFLAGS+= ${SACFLAGS}
diff --git a/sys/arch/hppa64/stand/libsa/Makefile b/sys/arch/hppa64/stand/libsa/Makefile
new file mode 100644
index 00000000000..eda10f3436e
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/Makefile
@@ -0,0 +1,43 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $
+
+.include "${.CURDIR}/../Makefile.inc"
+
+LIB= sa
+
+S=${.CURDIR}/../../../..
+SADIR=${.CURDIR}/..
+DIR_SA= $S/lib/libsa
+
+NOPROFILE=noprofile
+NOPIC=nopic
+
+#AS=cat ;
+#AS+= -R
+#AS+= -a
+
+# hppa64 stuff
+SRCS= machdep.c pdc.c itecons.c dev_hppa64.c time.c \
+ ct.c dk.c lf.c lif.c cmd_hppa64.c
+
+# stand routines
+SRCS+= alloc.c exit.c getfile.c gets.c globals.c \
+ printf.c strerror.c strtol.c strchr.c ctime.c loadfile.c snprintf.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 readdir.c cons.c
+
+# boot filesystems
+SRCS+= ufs.c cd9660.c
+
+.PATH: ${DIR_SA}
+
+all: ${SALIB}
+
+install:
+
+.include <bsd.lib.mk>
+
+CPPFLAGS+=-DHEAP_LIMIT=${HEAP_LIMIT} ${DEBUGFLAGS} -DNO_NET
+CPPFLAGS+=-I${S}/stand/boot
+CFLAGS+=${SACFLAGS} -D__INTERNAL_LIBSA_CREAD -DCOMPAT_UFS
diff --git a/sys/arch/hppa64/stand/libsa/cmd_hppa64.c b/sys/arch/hppa64/stand/libsa/cmd_hppa64.c
new file mode 100644
index 00000000000..1aa6117cb07
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/cmd_hppa64.c
@@ -0,0 +1,819 @@
+/* $OpenBSD: cmd_hppa64.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2002 Miodrag Vallat
+ * 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 AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*#define DEBUG*/
+
+#include <sys/param.h>
+/* would come from <sys/param.h> if -D_KERNEL */
+#define offsetof(s, e) ((size_t)&((s *)0)->e)
+
+#include <machine/iomod.h>
+#include <machine/pdc.h>
+
+#include <arch/hppa/dev/cpudevs.h>
+
+#include <libsa.h>
+#include "cmd.h"
+#include "dev_hppa64.h" /* pdc */
+
+extern struct stable_storage sstor;
+extern int sstorsiz;
+
+/* storage sizes we're interested in */
+#define CONSOLEOFFSET \
+ offsetof(struct stable_storage, ss_console)
+#define CONSOLESIZE \
+ (offsetof(struct stable_storage, ss_console) + \
+ sizeof(struct device_path))
+
+#define KEYBOARDOFFSET \
+ offsetof(struct stable_storage, ss_keyboard)
+#define KEYBOARDSIZE \
+ (offsetof(struct stable_storage, ss_keyboard) + \
+ sizeof(struct device_path))
+
+/*
+ * Table for the possible console devices found during the device walk.
+ */
+struct consoledev {
+ struct device_path dp;
+ int type;
+ int iodc_type;
+ int iodc_model;
+};
+
+#define PS2 1
+#define HIL 2
+#define SERIAL 3
+#define GRAPHICS 4
+
+/* max. serial ports */
+#define MAX_SERIALS 4
+/* max. HIL and PS2 */
+#define MAX_KEYBOARDS 2
+/* max. heads */
+#define MAX_GRAPHICS 4
+
+struct consoledev serials[MAX_SERIALS];
+struct consoledev keyboards[MAX_KEYBOARDS];
+struct consoledev graphics[MAX_GRAPHICS];
+
+/* Relaxed device comparison */
+#define MATCH(dev1, dev2) \
+ (dev1).dp_mod == (dev2).dp_mod && \
+ (dev1).dp_bc[0] == (dev2).dp_bc[0] && \
+ (dev1).dp_bc[1] == (dev2).dp_bc[1] && \
+ (dev1).dp_bc[2] == (dev2).dp_bc[2] && \
+ (dev1).dp_bc[3] == (dev2).dp_bc[3] && \
+ (dev1).dp_bc[4] == (dev2).dp_bc[4] && \
+ (dev1).dp_bc[5] == (dev2).dp_bc[5]
+
+int walked;
+
+void bus_walk(struct device_path *);
+void register_device(struct consoledev *, int,
+ struct device_path *, struct iodc_data *, int, int);
+
+int Xconsole(void);
+void print_console(void);
+int set_graphics(struct device_path *, int, char *);
+int set_serial(struct device_path *, int, char *);
+int set_console(struct device_path *);
+
+int Xkeyboard(void);
+void print_keyboard(void);
+int set_keyboard(struct device_path *);
+
+struct cmd_table cmd_machine[] = {
+ { "console", CMDT_CMD, Xconsole },
+ { "keyboard", CMDT_CMD, Xkeyboard },
+ { NULL, },
+};
+
+/* value to console speed table */
+int i_speeds[] = {
+ 50,
+ 75,
+ 110,
+ 150,
+ 300,
+ 600,
+ 1200,
+ 2400,
+ 4800,
+ 7200,
+ 9600,
+ 19200,
+ 38400,
+ 57600,
+ 115200,
+ 230400,
+};
+
+char *c_speeds[] = {
+ "50",
+ "75",
+ "110",
+ "150",
+ "300",
+ "600",
+ "1200",
+ "2400",
+ "4800",
+ "7200",
+ "9600",
+ "19200",
+ "38400",
+ "57600",
+ "115200",
+ "230400",
+};
+
+/* values to console parity table */
+char *parities[] = {
+ "none",
+ "odd",
+ "<unknown parity>",
+ "even",
+};
+
+/*
+ * C O N S O L E S E T T I N G S
+ */
+
+void
+print_console()
+{
+ int port, mode, speed, parity, bits;
+ int i;
+
+#ifdef DEBUG
+ printf("console flags %x mod %x bc %d/%d/%d/%d/%d/%d\n",
+ sstor.ss_console.dp_flags,
+ sstor.ss_console.dp_mod,
+ sstor.ss_console.dp_bc[0],
+ sstor.ss_console.dp_bc[1],
+ sstor.ss_console.dp_bc[2],
+ sstor.ss_console.dp_bc[3],
+ sstor.ss_console.dp_bc[4],
+ sstor.ss_console.dp_bc[5]);
+
+ printf("console path %x/%x/%x/%x/%x/%x\n",
+ sstor.ss_console.dp_layers[0],
+ sstor.ss_console.dp_layers[1],
+ sstor.ss_console.dp_layers[2],
+ sstor.ss_console.dp_layers[3],
+ sstor.ss_console.dp_layers[4],
+ sstor.ss_console.dp_layers[5]);
+#endif
+
+ printf("Console path: ");
+
+ /* look for a serial console */
+ for (port = i = 0; i < MAX_SERIALS; i++)
+ if (MATCH(serials[i].dp, sstor.ss_console)) {
+ port = i + 1;
+ break;
+ }
+
+ if (port == 0) {
+ /*
+ * Graphics console
+ */
+
+ for (port = i = 0; i < MAX_GRAPHICS; i++)
+ if (MATCH(graphics[i].dp, sstor.ss_console)) {
+ port = i;
+ break;
+ }
+
+ /*
+ * If the console could still not be identified, consider
+ * it is a simplified encoding for the default graphics
+ * console. Hence port == 0, no need to check.
+ */
+ if (port == 0)
+ printf("graphics");
+ else
+ printf("graphics_%d", port);
+
+ mode = sstor.ss_console.dp_layers[0];
+ if (mode != 0)
+ printf(".%d", mode);
+ } else {
+ /*
+ * Serial console
+ */
+
+ if (port == 1)
+ printf("rs232");
+ else
+ printf("rs232_%d", port);
+
+ speed = PZL_SPEED(sstor.ss_console.dp_layers[0]);
+ printf(".%d", i_speeds[speed]);
+
+ bits = PZL_BITS(sstor.ss_console.dp_layers[0]);
+ printf(".%d", bits);
+
+ parity = PZL_PARITY(sstor.ss_console.dp_layers[0]);
+ printf(".%s", parities[parity]);
+ }
+
+ printf("\n");
+}
+
+int
+set_graphics(console, port, arg)
+ struct device_path *console;
+ int port;
+ char *arg;
+{
+ int maxmode, mode = 0;
+ char *digit;
+
+ /* head */
+ if (graphics[port].type == 0) {
+ printf("no such device found\n");
+ return 0;
+ }
+
+ /* mode */
+ if (arg != NULL) {
+ for (digit = arg; *digit != '\0'; digit++) {
+ if (*digit >= '0' && *digit <= '9')
+ mode = 10 * mode + (*digit - '0');
+ else {
+ printf("invalid mode specification, %s\n",
+ arg);
+ return 0;
+ }
+ }
+
+ if (mode <= 0) {
+ printf("invalid mode specification, %s\n",
+ arg);
+ return 0;
+ }
+ }
+
+ /*
+ * If we are just changing the mode of the same graphics
+ * console, check that our mode is in the valid range.
+ */
+ if (MATCH(graphics[port].dp, sstor.ss_console)) {
+ maxmode = sstor.ss_console.dp_layers[1];
+
+ /* pick back same mode if unspecified */
+ if (mode == 0)
+ mode = sstor.ss_console.dp_layers[0];
+
+ if (mode > maxmode) {
+ printf("invalid mode value, available range is 1-%d\n",
+ maxmode);
+ return 0;
+ }
+ } else {
+ if (mode == 0)
+ mode = 1;
+ maxmode = mode;
+ }
+
+ *console = graphics[port].dp;
+ console->dp_layers[0] = mode;
+ console->dp_layers[1] = maxmode;
+ console->dp_layers[2] = console->dp_layers[3] =
+ console->dp_layers[4] = console->dp_layers[5] = 0;
+
+ return 1;
+}
+
+int
+set_serial(console, port, arg)
+ struct device_path *console;
+ int port;
+ char *arg;
+{
+ char *dot;
+ int i;
+ int speed, parity, bits;
+
+ /* port */
+ port--;
+ if (serials[port].type == 0) {
+ printf("no such device found\n");
+ return 0;
+ }
+
+ /* speed */
+ dot = strchr(arg, '.');
+ if (dot != NULL)
+ *dot++ = '\0';
+
+ speed = 0;
+ if (arg == NULL || *arg == '\0') {
+ for (i = 0; i < NENTS(i_speeds); i++)
+ if (i_speeds[i] == 9600) {
+ speed = i;
+ break;
+ }
+ } else {
+ for (i = 0; i < NENTS(c_speeds); i++)
+ if (strcmp(arg, c_speeds[i]) == 0) {
+ speed = i;
+ break;
+ }
+ if (speed == 0) {
+ printf("invalid speed specification, %s\n", arg);
+ return 0;
+ }
+ }
+
+ /* data bits */
+ arg = dot;
+ dot = strchr(arg, '.');
+
+ if (arg == NULL || *arg == '\0')
+ bits = 8;
+ else {
+ if (dot == arg + 1)
+ bits = *arg - '0';
+ else
+ bits = 0;
+
+ if (bits < 5 || bits > 8) {
+ printf("invalid bits specification, %s\n", arg);
+ return 0;
+ }
+ }
+ if (dot != NULL)
+ *dot++ = '\0';
+
+ /* parity */
+ arg = dot;
+ if (arg == NULL || *arg == '\0')
+ parity = 0; /* none */
+ else {
+ parity = -1;
+ for (i = 0; i <= 3; i++)
+ if (strcmp(arg, parities[i]) == 0) {
+ parity = i;
+ break;
+ }
+ if (parity == 2)
+ parity = -1; /* unknown parity */
+ }
+ if (parity < 0) {
+ printf("invalid parity specification, %s\n", arg);
+ return 0;
+ }
+
+ *console = serials[port].dp;
+ console->dp_layers[0] = PZL_ENCODE(bits, parity, speed);
+
+ return 1;
+}
+
+int
+set_console(console)
+ struct device_path *console;
+{
+ char *arg = cmd.argv[1], *dot;
+ int port;
+
+ /* extract first word */
+ dot = strchr(arg, '.');
+ if (dot != NULL)
+ *dot++ = '\0';
+
+ /*
+ * Graphics console
+ */
+ if (strcmp(arg, "graphics") == 0)
+ return set_graphics(console, 0, dot);
+ if (strncmp(arg, "graphics_", 9) == 0) {
+ port = arg[9] - '0';
+ if (port > 0 && port < MAX_GRAPHICS)
+ return set_graphics(console, port, dot);
+ }
+
+ /*
+ * Serial console
+ */
+ if (strcmp(arg, "rs232") == 0)
+ return set_serial(console, 1, dot);
+ if (strncmp(arg, "rs232_", 6) == 0) {
+ port = arg[6] - '0';
+ if (port > 0 && port <= MAX_SERIALS)
+ return set_serial(console, port, dot);
+ }
+
+ printf("invalid device specification, %s\n", arg);
+ return 0;
+}
+
+int
+Xconsole()
+{
+ struct device_path console;
+ int rc;
+
+ /* walk the device list if not already done */
+ if (walked == 0) {
+ bus_walk(NULL);
+ walked++;
+ }
+
+ if (sstorsiz < CONSOLESIZE) {
+ printf("no console information in stable storage\n");
+ return 0;
+ }
+
+ if (cmd.argc == 1) {
+ print_console();
+ } else {
+ console = sstor.ss_console;
+ if (set_console(&console)) {
+ if (memcmp(&sstor.ss_console, &console,
+ sizeof console) != 0) {
+ sstor.ss_console = console;
+
+ /* alea jacta est */
+ rc = (*pdc)(PDC_STABLE, PDC_STABLE_WRITE,
+ CONSOLEOFFSET, &sstor.ss_console,
+ sizeof(sstor.ss_console));
+ if (rc != 0) {
+ printf("failed to save console settings, error %d\n",
+ rc);
+ /* read sstor again for safety */
+ (*pdc)(PDC_STABLE, PDC_STABLE_READ,
+ CONSOLEOFFSET, &sstor.ss_console,
+ sizeof(sstor.ss_console));
+ } else
+ printf("you will need to power-cycle "
+ "your machine for the changes "
+ "to take effect.\n");
+ }
+ print_console();
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * K E Y B O A R D S E T T I N G S
+ */
+
+void
+print_keyboard()
+{
+ int type;
+ int i;
+
+#ifdef DEBUG
+ printf("keyboard flags %x mod %x bc %d/%d/%d/%d/%d/%d\n",
+ sstor.ss_keyboard.dp_flags,
+ sstor.ss_keyboard.dp_mod,
+ sstor.ss_keyboard.dp_bc[0],
+ sstor.ss_keyboard.dp_bc[1],
+ sstor.ss_keyboard.dp_bc[2],
+ sstor.ss_keyboard.dp_bc[3],
+ sstor.ss_keyboard.dp_bc[4],
+ sstor.ss_keyboard.dp_bc[5]);
+
+ printf("keyboard path %x/%x/%x/%x/%x/%x\n",
+ sstor.ss_keyboard.dp_layers[0],
+ sstor.ss_keyboard.dp_layers[1],
+ sstor.ss_keyboard.dp_layers[2],
+ sstor.ss_keyboard.dp_layers[3],
+ sstor.ss_keyboard.dp_layers[4],
+ sstor.ss_keyboard.dp_layers[5]);
+#endif
+
+ printf("Keyboard path: ");
+
+ for (type = i = 0; i < MAX_KEYBOARDS; i++)
+ if (MATCH(keyboards[i].dp, sstor.ss_keyboard)) {
+ type = keyboards[i].type;
+ break;
+ }
+
+ switch (type) {
+ case HIL:
+ printf("hil");
+ break;
+ case PS2:
+ printf("ps2");
+ break;
+ default:
+ printf("unknown");
+ break;
+ }
+
+ printf("\n");
+}
+
+int
+set_keyboard(keyboard)
+ struct device_path *keyboard;
+{
+ int i;
+ char *arg = cmd.argv[1];
+ int type;
+
+ if (strcmp(arg, "hil") == 0)
+ type = HIL;
+ else if (strcmp(arg, "ps2") == 0)
+ type = PS2;
+ else {
+ printf("invalid device specification, %s\n", arg);
+ return 0;
+ }
+
+ for (i = 0; i < MAX_KEYBOARDS; i++)
+ if (keyboards[i].type == type) {
+ *keyboard = keyboards[i].dp;
+ return 1;
+ }
+
+ printf("no such device found\n");
+ return 0;
+}
+
+int
+Xkeyboard()
+{
+ struct device_path keyboard;
+ int rc;
+
+ /* walk the device list if not already done */
+ if (walked == 0) {
+ bus_walk(NULL);
+ walked++;
+ }
+
+ if (sstorsiz < KEYBOARDSIZE) {
+ printf("no keyboard information in stable storage\n");
+ return 0;
+ }
+
+ if (cmd.argc == 1) {
+ print_keyboard();
+ } else {
+ keyboard = sstor.ss_keyboard;
+ if (set_keyboard(&keyboard)) {
+ if (memcmp(&sstor.ss_keyboard, &keyboard,
+ sizeof keyboard) != 0) {
+ sstor.ss_keyboard = keyboard;
+
+ /* alea jacta est */
+ rc = (*pdc)(PDC_STABLE, PDC_STABLE_WRITE,
+ KEYBOARDOFFSET, &sstor.ss_keyboard,
+ sizeof(sstor.ss_keyboard));
+ if (rc != 0) {
+ printf("failed to save keyboard settings, error %d\n",
+ rc);
+ /* read sstor again for safety */
+ (*pdc)(PDC_STABLE, PDC_STABLE_READ,
+ KEYBOARDOFFSET, &sstor.ss_keyboard,
+ sizeof(sstor.ss_keyboard));
+ } else
+ printf("you will need to power-cycle "
+ "your machine for the changes "
+ "to take effect.\n");
+ }
+ print_keyboard();
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * U T I L I T I E S
+ */
+
+/*
+ * Bus walker.
+ * This routine will walk all the modules on a given bus, registering
+ * serial ports, keyboard and graphics devices as they are found.
+ */
+void
+bus_walk(struct device_path *idp)
+{
+ struct device_path dp;
+ struct pdc_memmap memmap;
+ struct iodc_data mptr;
+ int err, i, kluge_ps2 = 0; /* kluge, see below */
+
+ for (i = 0; i < MAXMODBUS; i++) {
+
+ if (idp) {
+ dp.dp_bc[0] = idp->dp_bc[1];
+ dp.dp_bc[1] = idp->dp_bc[2];
+ dp.dp_bc[2] = idp->dp_bc[3];
+ dp.dp_bc[3] = idp->dp_bc[4];
+ dp.dp_bc[4] = idp->dp_bc[5];
+ dp.dp_bc[5] = idp->dp_mod;
+ } else {
+ dp.dp_bc[0] = dp.dp_bc[1] = dp.dp_bc[2] =
+ dp.dp_bc[3] = dp.dp_bc[4] = dp.dp_bc[5] = -1;
+ }
+
+ dp.dp_mod = i;
+ if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap, &dp) < 0 &&
+ (pdc)(PDC_SYSMAP, PDC_SYSMAP_HPA, &memmap, &dp) < 0)
+ continue;
+
+ if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, memmap.hpa,
+ IODC_DATA, &mptr, sizeof(mptr))) < 0)
+ continue;
+
+#ifdef DEBUG
+ printf("device %d/%d/%d/%d/%d/%d "
+ "flags %d mod %x type %x model %x\n",
+ dp.dp_bc[0], dp.dp_bc[1], dp.dp_bc[2], dp.dp_bc[3],
+ dp.dp_bc[4], dp.dp_bc[5], dp.dp_flags, dp.dp_mod,
+ mptr.iodc_type, mptr.iodc_sv_model);
+#endif
+ /*
+ * If the device can be considered as a valid rs232,
+ * graphics console or keyboard, register it.
+ *
+ * Unfortunately, devices which should be considered as
+ * ``main'' aren't necessarily seen first.
+ * The rules we try to enforce here are as follows:
+ * - GIO PS/2 ports wins over any other PS/2 port.
+ * - the first GIO serial found wins over any other
+ * serial port.
+ * The second rule is a bit tricky to achieve, since on
+ * some machines (for example, 715/100XC), the two serial
+ * ports are not seen as attached to the same busses...
+ */
+ switch (mptr.iodc_type) {
+ case HPPA_TYPE_BCPORT:
+ bus_walk(&dp);
+ break;
+ case HPPA_TYPE_BHA:
+ case HPPA_TYPE_BRIDGE:
+ /* if there was no phantomas here */
+ if (dp.dp_bc[5] == -1) {
+ dp.dp_bc[0] = dp.dp_bc[1];
+ dp.dp_bc[1] = dp.dp_bc[2];
+ dp.dp_bc[2] = dp.dp_bc[3];
+ dp.dp_bc[3] = dp.dp_bc[4];
+ dp.dp_bc[4] = dp.dp_bc[5];
+ dp.dp_bc[5] = dp.dp_mod;
+ dp.dp_mod = 0;
+ }
+ bus_walk(&dp);
+ break;
+ case HPPA_TYPE_ADIRECT:
+ switch (mptr.iodc_sv_model) {
+ case HPPA_ADIRECT_RS232:
+ register_device(serials, MAX_SERIALS,
+ &dp, &mptr, SERIAL, 0);
+ break;
+ case HPPA_ADIRECT_HIL:
+ register_device(keyboards, MAX_KEYBOARDS,
+ &dp, &mptr, HIL, 0);
+ break;
+ case HPPA_ADIRECT_PEACOCK:
+ case HPPA_ADIRECT_LEONARDO:
+ register_device(graphics, MAX_GRAPHICS,
+ &dp, &mptr, GRAPHICS, 0);
+ break;
+ }
+ break;
+ case HPPA_TYPE_FIO:
+ switch (mptr.iodc_sv_model) {
+ case HPPA_FIO_HIL:
+ register_device(keyboards, MAX_KEYBOARDS,
+ &dp, &mptr, HIL, 0);
+ break;
+ case HPPA_FIO_RS232:
+ register_device(serials, MAX_SERIALS,
+ &dp, &mptr, SERIAL, 0);
+ break;
+ case HPPA_FIO_DINOPCK:
+ register_device(keyboards, MAX_KEYBOARDS,
+ &dp, &mptr, PS2, 0);
+ break;
+ case HPPA_FIO_GPCIO:
+ /*
+ * KLUGE! At this point, there is no way to
+ * know if this port is the keyboard port or
+ * the mouse port.
+ * Let's assume the first port found is the
+ * keyboard, and ignore the others.
+ */
+ if (kluge_ps2 != 0)
+ break;
+ register_device(keyboards, MAX_KEYBOARDS,
+ &dp, &mptr, PS2, 1);
+ kluge_ps2++;
+ break;
+ case HPPA_FIO_GRS232:
+ {
+ int j, first;
+
+ /*
+ * If a GIO serial port is already registered,
+ * register as extra port...
+ */
+ first = 1;
+ for (j = 0; j < MAX_SERIALS; j++)
+ if (serials[j].type == SERIAL &&
+ serials[j].iodc_type ==
+ HPPA_TYPE_FIO &&
+ serials[j].iodc_model ==
+ HPPA_FIO_GRS232) {
+ first = 0;
+ break;
+ }
+
+ register_device(serials, MAX_SERIALS,
+ &dp, &mptr, SERIAL, first);
+ }
+ break;
+ case HPPA_FIO_SGC:
+ register_device(graphics, MAX_GRAPHICS,
+ &dp, &mptr, GRAPHICS, 0);
+ break;
+ case HPPA_FIO_GSGC:
+ register_device(graphics, MAX_GRAPHICS,
+ &dp, &mptr, GRAPHICS, 1);
+ break;
+ }
+ break;
+ }
+ }
+}
+
+void
+register_device(devlist, cnt, dp, mptr, type, first)
+ struct consoledev *devlist;
+ int cnt;
+ struct device_path *dp;
+ struct iodc_data *mptr;
+ int type;
+ int first;
+{
+ int i;
+ struct consoledev *dev;
+
+ for (i = 0, dev = devlist; i < cnt; i++, dev++)
+ if (dev->type == 0)
+ break;
+
+ if (i == cnt) {
+#ifdef DEBUG
+ printf("can't register device, need more room!\n");
+#endif
+ return;
+ }
+
+ /*
+ * If this is supposedly the main device, insert on top
+ */
+ if (first != 0) {
+ memcpy(devlist + 1, devlist,
+ (cnt - 1) * sizeof(struct consoledev));
+ dev = devlist;
+ }
+
+ dev->dp = *dp;
+ dev->type = type;
+ dev->iodc_type = mptr->iodc_type;
+ dev->iodc_model = mptr->iodc_sv_model;
+
+#ifdef DEBUG
+ printf("(registered as type %d)\n", type);
+#endif
+}
diff --git a/sys/arch/hppa64/stand/libsa/ct.c b/sys/arch/hppa64/stand/libsa/ct.c
new file mode 100644
index 00000000000..44316e10b12
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/ct.c
@@ -0,0 +1,71 @@
+/* $OpenBSD: ct.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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.
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "libsa.h"
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/reboot.h>
+
+#include <machine/pdc.h>
+#include <machine/iomod.h>
+
+#include "dev_hppa64.h"
+
+int
+ctopen(struct open_file *f, ...)
+{
+ struct hppa_dev *dp = f->f_devdata;
+
+ if (!(dp->pz_dev = pdc_findev(-1, PCL_SEQU)))
+ return (ENXIO);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+ctclose(f)
+ struct open_file *f;
+{
+ free (f->f_devdata, sizeof(struct hppa_dev));
+ f->f_devdata = NULL;
+ return 0;
+}
diff --git a/sys/arch/hppa64/stand/libsa/dev_hppa64.c b/sys/arch/hppa64/stand/libsa/dev_hppa64.c
new file mode 100644
index 00000000000..75eb87528e4
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/dev_hppa64.c
@@ -0,0 +1,228 @@
+/* $OpenBSD: dev_hppa64.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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 "libsa.h"
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/reboot.h>
+#include <dev/cons.h>
+
+#include <machine/iomod.h>
+
+#include "dev_hppa64.h"
+
+extern int debug;
+
+const char cdevs[][4] = {
+ "ite", "", "", "", "", "", "", "",
+ "", "", "", "", ""
+};
+const int ncdevs = NENTS(cdevs);
+
+const struct pdc_devs {
+ char name[3];
+ int dev_type;
+} pdc_devs[] = {
+ { "dk", 0 },
+ { "ct", 1 },
+ { "lf", 2 },
+ { "", -1 },
+ { "rd", -1 },
+ { "sw", -1 },
+ { "fl", -1 },
+};
+
+/* pass dev_t to the open routines */
+int
+devopen(f, fname, file)
+ struct open_file *f;
+ const char *fname;
+ char **file;
+{
+ struct hppa_dev *hpd;
+ const struct pdc_devs *dp = pdc_devs;
+ int rc = 1;
+
+ if (!(*file = strchr(fname, ':')))
+ return ENODEV;
+ else
+ (*file)++;
+
+#ifdef DEBUGBUG
+ if (debug)
+ printf("devopen: ");
+#endif
+
+ for (dp = pdc_devs; dp < &pdc_devs[NENTS(pdc_devs)]; dp++)
+ if (!strncmp(fname, dp->name, sizeof(dp->name)-1))
+ break;
+
+ if (dp >= &pdc_devs[NENTS(pdc_devs)] || dp->dev_type < 0)
+ return ENODEV;
+#ifdef DEBUGBUG
+ if (debug)
+ printf("%s\n", dp->name);
+#endif
+
+ if (!(hpd = alloc(sizeof *hpd))) {
+#ifdef DEBUG
+ printf ("devopen: no mem\n");
+#endif
+ } else {
+ bzero(hpd, sizeof *hpd);
+ hpd->bootdev = bootdev;
+ hpd->buf = (char *)(((u_long)hpd->ua_buf + IODC_MINIOSIZ-1) &
+ ~(IODC_MINIOSIZ-1));
+ f->f_devdata = hpd;
+ if ((rc = (*devsw[dp->dev_type].dv_open)(f, file)) == 0) {
+ f->f_dev = &devsw[dp->dev_type];
+ return 0;
+ }
+ free (hpd, 0);
+ f->f_devdata = NULL;
+ }
+
+ if (!(f->f_flags & F_NODEV))
+ f->f_dev = &devsw[dp->dev_type];
+
+ if (!f->f_devdata)
+ *file = NULL;
+
+ return rc;
+}
+
+void
+devboot(dev, p)
+ dev_t dev;
+ char *p;
+{
+ const char *q;
+ if (!dev) {
+ int type, unit;
+
+ switch (PAGE0->mem_boot.pz_class) {
+ case PCL_RANDOM:
+ type = 0;
+ unit = PAGE0->mem_boot.pz_layers[0];
+ break;
+ case PCL_SEQU:
+ type = 1;
+ unit = PAGE0->mem_boot.pz_layers[0];
+ break;
+ case PCL_NET_MASK|PCL_SEQU:
+ type = 2;
+ unit = 0;
+ break;
+ default:
+ type = 0;
+ unit = 0;
+ break;
+ }
+ dev = bootdev = MAKEBOOTDEV(type, 0, 0, unit, B_PARTITION(dev));
+ }
+#ifdef _TEST
+ *p++ = '/';
+ *p++ = 'd';
+ *p++ = 'e';
+ *p++ = 'v';
+ *p++ = '/';
+ *p++ = 'r';
+#endif
+ /* quick copy device name */
+ for (q = pdc_devs[B_TYPE(dev)].name; (*p++ = *q++););
+ p[-1] = '0' + B_UNIT(dev);
+ *p++ = 'a' + B_PARTITION(dev);
+ *p = '\0';
+}
+
+int pch_pos;
+
+void
+putchar(c)
+ int c;
+{
+ switch(c) {
+ case '\177': /* DEL erases */
+ cnputc('\b');
+ cnputc(' ');
+ case '\b':
+ cnputc('\b');
+ if (pch_pos)
+ pch_pos--;
+ break;
+ case '\t':
+ do
+ cnputc(' ');
+ while(++pch_pos % 8);
+ break;
+ case '\n':
+ case '\r':
+ cnputc(c);
+ pch_pos=0;
+ break;
+ default:
+ cnputc(c);
+ pch_pos++;
+ break;
+ }
+}
+
+int
+getchar()
+{
+ int c = cngetc();
+
+ if (c == '\r')
+ c = '\n';
+
+ if ((c < ' ' && c != '\n') || c == '\177')
+ return(c);
+
+ putchar(c);
+
+ return(c);
+}
+
+char ttyname_buf[8];
+char *
+ttyname(fd)
+ int fd;
+{
+ snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
+ cdevs[major(cn_tab->cn_dev)],
+ minor(cn_tab->cn_dev));
+ return (ttyname_buf);
+}
+
+dev_t
+ttydev(name)
+ char *name;
+{
+ int i, unit = -1;
+ char *no = name + strlen(name) - 1;
+
+ while (no >= name && *no >= '0' && *no <= '9')
+ unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
+ if (no < name || unit < 0)
+ return (NODEV);
+ for (i = 0; i < ncdevs; i++)
+ if (strncmp(name, cdevs[i], no - name + 1) == 0)
+ return (makedev(i, unit));
+ return (NODEV);
+}
diff --git a/sys/arch/hppa64/stand/libsa/dev_hppa64.h b/sys/arch/hppa64/stand/libsa/dev_hppa64.h
new file mode 100644
index 00000000000..a47daa2173a
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/dev_hppa64.h
@@ -0,0 +1,43 @@
+/* $OpenBSD: dev_hppa64.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+
+#define IOPGSHIFT 11
+#define IONBPG (1 << IOPGSHIFT)
+#define IOPGOFSET (IONBPG - 1)
+
+struct disklabel;
+struct hppa_dev {
+ dev_t bootdev;
+ struct pz_device *pz_dev; /* device descriptor */
+ daddr_t fsoff; /* offset to the file system */
+ daddr_t last_blk; /* byte offset for last read blk */
+ size_t last_read; /* amount read last time */
+ struct disklabel *label;
+ /* buffer to cache data (aligned properly) */
+ char *buf;
+ char ua_buf[IODC_IOSIZ + IODC_MINIOSIZ];
+};
+
+#ifdef PDCDEBUG
+#define DEVPATH_PRINT(dp) \
+ printf("%x, %d.%d.%d.%d.%d.%d, 0x%x, %x.%x.%x.%x.%x.%x\n", \
+ (dp)->dp_flags, (dp)->dp_bc[0], (dp)->dp_bc[1], (dp)->dp_bc[2], \
+ (dp)->dp_bc[3], (dp)->dp_bc[4], (dp)->dp_bc[5], (dp)->dp_mod, \
+ (dp)->dp_layers[0], (dp)->dp_layers[1], (dp)->dp_layers[2], \
+ (dp)->dp_layers[3], (dp)->dp_layers[4], (dp)->dp_layers[5]);
+#define PZDEV_PRINT(dp) \
+ printf("devpath={%x, %d.%d.%d.%d.%d.%d, 0x%x, %x.%x.%x.%x.%x.%x}," \
+ "\n\thpa=%p, spa=%p, io=%p, class=%u\n", \
+ (dp)->pz_flags, (dp)->pz_bc[0], (dp)->pz_bc[1], (dp)->pz_bc[2], \
+ (dp)->pz_bc[3], (dp)->pz_bc[4], (dp)->pz_bc[5], (dp)->pz_mod, \
+ (dp)->pz_layers[0], (dp)->pz_layers[1], (dp)->pz_layers[2], \
+ (dp)->pz_layers[3], (dp)->pz_layers[4], (dp)->pz_layers[5], \
+ (dp)->pz_hpa, (dp)->pz_spa, (dp)->pz_iodc_io, (dp)->pz_class);
+#endif
+
+extern pdcio_t pdc;
+extern int pdcbuf[]; /* PDC returns, pdc.c */
+
+int iodc_rw(char *, u_int, u_int, int func, struct pz_device *);
+const char *dk_disklabel(struct hppa_dev *dp, struct disklabel *label);
+int pdc_call(void *, ...);
diff --git a/sys/arch/hppa64/stand/libsa/dk.c b/sys/arch/hppa64/stand/libsa/dk.c
new file mode 100644
index 00000000000..d20d19d5b3f
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/dk.c
@@ -0,0 +1,101 @@
+/* $OpenBSD: dk.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "libsa.h"
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/reboot.h>
+#include <machine/pdc.h>
+#include <machine/iomod.h>
+
+#include "dev_hppa64.h"
+
+const char *
+dk_disklabel(struct hppa_dev *dp, struct disklabel *label)
+{
+ char buf[DEV_BSIZE];
+ size_t ret;
+
+ if (iodcstrategy(dp, F_READ, LABELSECTOR, DEV_BSIZE, buf, &ret))
+ if (ret != DEV_BSIZE)
+ return "cannot read disklabel";
+
+ return (getdisklabel(buf, label));
+}
+
+int
+dkopen(struct open_file *f, ...)
+{
+ struct disklabel *lp;
+ struct hppa_dev *dp = f->f_devdata;
+ const char *st;
+
+#ifdef DEBUG
+ if (debug)
+ printf("dkopen(%p)\n", f);
+#endif
+
+ if (!(dp->pz_dev = pdc_findev(-1, PCL_RANDOM)))
+ return ENXIO;
+
+ lp = dp->label;
+ st = NULL;
+
+#ifdef DEBUG
+ if (debug)
+ printf ("disklabel\n");
+#endif
+
+ if ((st = dk_disklabel(dp, lp)) != NULL) {
+#ifdef DEBUG
+ if (debug)
+ printf ("dkopen: %s\n", st);
+#endif
+ /* we do not know if it's a disk or net, but do not fail */
+ } else {
+ u_int i;
+
+ i = B_PARTITION(dp->bootdev);
+ if (i >= lp->d_npartitions || !lp->d_partitions[i].p_size)
+ return (EPART);
+
+ dp->fsoff = lp->d_partitions[i].p_offset;
+ }
+
+#ifdef DEBUGBUG
+ if (debug)
+ printf ("dkopen() ret\n");
+#endif
+ return (0);
+}
+
+int
+dkclose(f)
+ struct open_file *f;
+{
+ free (f->f_devdata, sizeof(struct hppa_dev));
+ f->f_devdata = NULL;
+ return 0;
+}
diff --git a/sys/arch/hppa64/stand/libsa/itecons.c b/sys/arch/hppa64/stand/libsa/itecons.c
new file mode 100644
index 00000000000..49e4413e2d2
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/itecons.c
@@ -0,0 +1,212 @@
+/* $OpenBSD: itecons.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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.
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "libsa.h"
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <machine/pdc.h>
+#include <machine/iomod.h>
+#include <dev/cons.h>
+
+#include "dev_hppa64.h"
+
+iodcio_t cniodc; /* console IODC entry point */
+iodcio_t kyiodc; /* keyboard IODC entry point */
+pz_device_t *cons_pzdev, *kbd_pzdev;
+
+/*
+ * Console.
+ */
+
+char cnbuf[IODC_MINIOSIZ] __attribute__ ((aligned (IODC_MINIOSIZ)));
+int kycode[IODC_MAXSIZE/sizeof(int)];
+
+int
+cnspeed(dev, sp)
+ dev_t dev;
+ int sp;
+{
+ return 9600;
+}
+
+void
+ite_probe(cn)
+ struct consdev *cn;
+{
+ cniodc = (iodcio_t)(u_long)PAGE0->mem_free;
+ cons_pzdev = &PAGE0->mem_cons;
+ kbd_pzdev = &PAGE0->mem_kbd;
+
+ if (pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, cons_pzdev->pz_hpa,
+ IODC_INIT, cniodc, IODC_MAXSIZE) < 0 ||
+ pdc_call(cniodc, cons_pzdev->pz_hpa,
+ (cons_pzdev->pz_hpa==PAGE0->mem_boot.pz_hpa)?
+ IODC_INIT_DEV: IODC_INIT_ALL, cons_pzdev->pz_spa,
+ cons_pzdev->pz_layers, pdcbuf, 0,0,0,0) < 0 ||
+ pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, cons_pzdev->pz_hpa,
+ IODC_IO, cniodc, IODC_MAXSIZE) < 0) {
+ /* morse code with the LED's?!! */
+ cons_pzdev->pz_iodc_io = kbd_pzdev->pz_iodc_io = NULL;
+ } else {
+ cn->cn_pri = CN_INTERNAL;
+ cn->cn_dev = makedev(0, 0);
+ }
+}
+
+void
+ite_init(cn)
+ struct consdev *cn;
+{
+ /*
+ * If the keyboard is separate from the console output device,
+ * we load the keyboard code at `kycode'.
+ *
+ * N.B. In this case, since the keyboard code is part of the
+ * boot code, it will be overwritten when we load a kernel.
+ */
+ if (cons_pzdev->pz_class != PCL_DUPLEX ||
+ kbd_pzdev->pz_class == PCL_KEYBD) {
+
+ kyiodc = (iodcio_t)kycode;
+
+ if (pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, kbd_pzdev->pz_hpa,
+ IODC_INIT, kyiodc, IODC_MAXSIZE) < 0 ||
+ pdc_call(kyiodc, kbd_pzdev->pz_hpa,
+ (kbd_pzdev->pz_hpa == PAGE0->mem_boot.pz_hpa ||
+ kbd_pzdev->pz_hpa == cons_pzdev->pz_hpa)?
+ IODC_INIT_DEV: IODC_INIT_ALL, kbd_pzdev->pz_spa,
+ kbd_pzdev->pz_layers, pdcbuf, 0, 0, 0, 0) < 0 ||
+ pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, kbd_pzdev->pz_hpa,
+ IODC_IO, kyiodc, IODC_MAXSIZE))
+ kyiodc = NULL;
+ } else {
+ kyiodc = cniodc;
+
+ bcopy((char *)&PAGE0->mem_cons, (char *)&PAGE0->mem_kbd,
+ sizeof(struct pz_device));
+ }
+
+ cons_pzdev->pz_iodc_io = (u_long)cniodc;
+ kbd_pzdev->pz_iodc_io = (u_long)kyiodc;
+#ifdef DEBUG
+ if (!kyiodc)
+ printf("ite_init: no kbd\n");
+#endif
+}
+
+void
+ite_putc(dev, c)
+ dev_t dev;
+ int c;
+{
+ if (cniodc == NULL)
+ return;
+
+ *cnbuf = c;
+
+ pdc_call(cniodc, cons_pzdev->pz_hpa, IODC_IO_CONSOUT,
+ cons_pzdev->pz_spa, cons_pzdev->pz_layers, pdcbuf, 0, cnbuf, 1, 0);
+}
+
+/*
+ * since i don't know how to 'just check the char available'
+ * i store the key into the stash removing on read op later;
+ */
+int
+ite_getc(dev)
+ dev_t dev;
+{
+ static int stash = 0;
+ int err, c, l, i;
+
+ if (kyiodc == NULL)
+ return(0x100);
+
+ if (stash) {
+ c = stash;
+ if (!(dev & 0x80))
+ stash = 0;
+ return c;
+ }
+
+ i = 16;
+ do {
+ err = pdc_call(kyiodc, kbd_pzdev->pz_hpa, IODC_IO_CONSIN,
+ kbd_pzdev->pz_spa, kbd_pzdev->pz_layers, pdcbuf,
+ 0, cnbuf, 1, 0);
+ l = pdcbuf[0];
+ c = cnbuf[0];
+#ifdef DEBUG
+ if (debug && err < 0)
+ printf("KBD input error: %d", err);
+#endif
+
+ /* if we are doing ischar() report immidiatelly */
+ if (!i-- && (dev & 0x80) && l == 0) {
+#ifdef DEBUG
+ if (debug > 2)
+ printf("ite_getc(0x%x): no char %d(%x)\n",
+ dev, l, c);
+#endif
+ return (0);
+ }
+ } while(!l);
+
+#if DEBUG
+ if (debug && l > 1)
+ printf("KBD input got too much (%d)\n", l);
+
+ if (debug > 3)
+ printf("kbd: \'%c\' (0x%x)\n", c, c);
+#endif
+ if (dev & 0x80)
+ stash = c;
+
+ return (c);
+}
+
+void
+ite_pollc(dev, on)
+ dev_t dev;
+ int on;
+{
+
+}
diff --git a/sys/arch/hppa64/stand/libsa/lf.c b/sys/arch/hppa64/stand/libsa/lf.c
new file mode 100644
index 00000000000..15b7a6c0957
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/lf.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: lf.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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 "libsa.h"
+#include <machine/pdc.h>
+#include <machine/iomod.h>
+#include <machine/param.h>
+
+#include "dev_hppa64.h"
+
+int
+lfopen(struct open_file *f, ...)
+{
+ struct hppa_dev *dp = f->f_devdata;
+
+ if (!(dp->pz_dev = pdc_findev(-1, PCL_NET_MASK|PCL_SEQU)))
+ return ENXIO;
+
+ return 0;
+}
+
+int
+lfclose(struct open_file *f)
+{
+ free(f->f_devdata, sizeof(struct hppa_dev));
+ f->f_devdata = NULL;
+ return 0;
+}
diff --git a/sys/arch/hppa64/stand/libsa/libsa.h b/sys/arch/hppa64/stand/libsa/libsa.h
new file mode 100644
index 00000000000..9952a35a383
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/libsa.h
@@ -0,0 +1,72 @@
+/* $OpenBSD: libsa.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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 <lib/libsa/stand.h>
+
+#define EXEC_ELF
+#define EXEC_SOM
+
+#define DEFAULT_KERNEL_ADDRESS 0
+
+extern dev_t bootdev;
+
+void pdc_init(void);
+struct pz_device;
+struct pz_device *pdc_findev(int, int);
+
+int iodcstrategy(void *, int, daddr_t, size_t, void *, size_t *);
+
+int ctopen(struct open_file *, ...);
+int ctclose(struct open_file *);
+
+int dkopen(struct open_file *, ...);
+int dkclose(struct open_file *);
+
+int lfopen(struct open_file *, ...);
+int lfstrategy(void *, int, daddr_t, size_t, void *, size_t *);
+int lfclose(struct open_file *);
+
+void ite_probe(struct consdev *);
+void ite_init(struct consdev *);
+int ite_getc(dev_t);
+void ite_putc(dev_t, int);
+void ite_pollc(dev_t, int);
+
+void machdep(void);
+void devboot(dev_t, char *);
+void fcacheall(void);
+void run_loadfile(u_long *marks, int howto);
+
+int lif_open(char *path, struct open_file *f);
+int lif_close(struct open_file *f);
+int lif_read(struct open_file *f, void *buf, size_t size, size_t *resid);
+int lif_write(struct open_file *f, void *buf, size_t size, size_t *resid);
+off_t lif_seek(struct open_file *f, off_t offset, int where);
+int lif_stat(struct open_file *f, struct stat *sb);
+int lif_readdir(struct open_file *f, char *name);
+
+union x_header;
+struct x_param;
+int som_probe(int, union x_header *);
+int som_load(int, struct x_param *);
+int som_ldsym(int, struct x_param *);
+
+extern int debug;
+
+#define MACHINE_CMD cmd_machine /* we have hppa specific commands */
diff --git a/sys/arch/hppa64/stand/libsa/lif.c b/sys/arch/hppa64/stand/libsa/lif.c
new file mode 100644
index 00000000000..25c25471f14
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/lif.c
@@ -0,0 +1,261 @@
+/* $OpenBSD: lif.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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 "libsa.h"
+
+extern int debug;
+
+struct file {
+ char f_buf[LIF_FILESTART];/* buffer for lif volume header and dir */
+ struct lifvol *f_lp; /* lif volume header pointer */
+ struct lifdir *f_ld; /* lif dir pointer */
+ int f_nfiles; /* gross number for lif dir entries */
+
+ off_t f_seek; /* seek pointer for file read */
+ struct lifdir *f_rd; /* lif dir pointer for readdir */
+
+ int f_isdir; /* special hacky flag for '.' dir */
+ int f_count; /* this file length */
+ int f_off; /* this file offset */
+};
+
+int
+lif_open (path, f)
+ char *path;
+ struct open_file *f;
+{
+ struct file *fp;
+ struct lifdir *dp;
+ char *p, *q;
+ struct lif_load load;
+ size_t buf_size;
+ int err, l;
+
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open(%s, %p)\n", path, f);
+#endif
+
+ fp = alloc(sizeof(*fp));
+ /* XXX we're assuming here that sizeof(fp->f_buf) >= LIF_FILESTART */
+ if ((err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0,
+ sizeof(fp->f_buf), &fp->f_buf, &buf_size)) ||
+ buf_size != sizeof(fp->f_buf)) {
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open: unable to read LIF header (%d)\n", err);
+#endif
+ } else if ((fp->f_lp = (struct lifvol *)fp->f_buf)->vol_id == LIF_VOL_ID) {
+ f->f_fsdata = fp;
+ fp->f_ld = (struct lifdir *)(fp->f_buf + LIF_DIRSTART);
+ fp->f_seek = 0;
+ fp->f_rd = fp->f_ld;
+ fp->f_nfiles = lifstob(fp->f_lp->vol_dirsize) /
+ sizeof(struct lifdir);
+
+ /* no dirs on the lif */
+ for (p = path + (l = strlen(path)); p >= path; p--)
+ if (*p == '/') {
+ p++;
+ break;
+ }
+ if (p > path)
+ path = p;
+ } else
+ err = EINVAL;
+
+ if (!err && *path != '.') {
+ fp->f_isdir = 0;
+ err = ENOENT;
+ for (dp = fp->f_ld; dp < &fp->f_ld[fp->f_nfiles]; dp++) {
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open: "
+ "%s <--> '%c%c%c%c%c%c%c%c%c%c'\n",
+ path, dp->dir_name[0], dp->dir_name[1],
+ dp->dir_name[2], dp->dir_name[3],
+ dp->dir_name[4], dp->dir_name[5],
+ dp->dir_name[6], dp->dir_name[7],
+ dp->dir_name[8], dp->dir_name[9]);
+#endif
+ for (p = path, q = dp->dir_name;
+ *q && *q != ' '; q++, p++)
+ if (tolower(*q) != tolower(*p))
+ break;
+ if ((!*q || *q == ' ') && !*p) {
+ err = 0;
+ break;
+ }
+ }
+ if (!err) {
+ fp->f_off = lifstodb(dp->dir_addr);
+ if (!(err =(f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fp->f_off, sizeof(load), &load, &buf_size)) &&
+ buf_size == sizeof(load)) {
+ /* no checksum */
+ fp->f_count = load.count - sizeof(int);
+ fp->f_off = dbtob(fp->f_off) + sizeof(load);
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open: %u @ %u [%x]\n",
+ fp->f_count, fp->f_off,
+ load.address);
+#endif
+ } else if (!err)
+ err = EIO;
+ }
+ } else
+ fp->f_isdir = 1;
+
+ if (err) {
+ free (fp, sizeof(*fp));
+ f->f_fsdata = NULL;
+ }
+#ifdef LIFDEBUG
+ if (debug)
+ printf("ret(%d)\n", err);
+#endif
+ return err;
+}
+
+int
+lif_close(f)
+ struct open_file *f;
+{
+ free (f->f_fsdata, sizeof(struct file));
+ f->f_fsdata = NULL;
+ return 0;
+}
+
+int
+lif_read(f, buf, size, resid)
+ struct open_file *f;
+ void *buf;
+ size_t size;
+ size_t *resid;
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ char *p;
+ char bbuf[DEV_BSIZE];
+ size_t bsize, count = sizeof(bbuf);
+ int err = 0;
+ int foff;
+
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_read(%p, %p, %u, %p)\n", f, buf, size, resid);
+#endif
+
+ for (p = bbuf; size; fp->f_seek += bsize, p += bsize) {
+ twiddle();
+ foff = fp->f_off + fp->f_seek;
+ if (fp->f_seek >= fp->f_count ||
+ (err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ btodb(foff), count, p, &bsize)))
+ break;
+ if (p == bbuf) {
+ bsize = sizeof(bbuf) - (foff & (sizeof(bbuf) - 1));
+ bsize = min(bsize, size);
+ bcopy(bbuf + (foff & (sizeof(bbuf) - 1)), buf, bsize);
+ p = buf;
+ }
+ count = size -= bsize;
+ }
+ if (resid)
+ *resid = size;
+
+ return err;
+}
+
+int
+lif_write(f, buf, size, resid)
+ struct open_file *f;
+ void *buf;
+ size_t size;
+ size_t *resid;
+{
+ return EOPNOTSUPP;
+}
+
+off_t
+lif_seek(f, offset, where)
+ struct open_file *f;
+ off_t offset;
+ int where;
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ switch (where) {
+ case SEEK_SET:
+ fp->f_seek = offset;
+ break;
+ case SEEK_CUR:
+ fp->f_seek += offset;
+ break;
+ case SEEK_END:
+ fp->f_seek = fp->f_count - offset;
+ break;
+ default:
+ return (-1);
+ }
+ return (fp->f_seek);
+}
+
+int
+lif_stat(f, sb)
+ struct open_file *f;
+ struct stat *sb;
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+
+ sb->st_mode = 0755 | (fp->f_isdir? S_IFDIR: 0); /* XXX */
+ sb->st_uid = 0;
+ sb->st_gid = 0;
+ sb->st_size = fp->f_count;
+ return 0;
+}
+
+int
+lif_readdir(f, name)
+ struct open_file *f;
+ char *name;
+{
+ struct file *fp = (struct file *)f->f_fsdata;
+ char *p;
+
+ if (name) {
+ while ((fp->f_rd->dir_name[0] == ' ' ||
+ !fp->f_rd->dir_name[0]) &&
+ (fp->f_rd - fp->f_ld) < fp->f_nfiles)
+ fp->f_rd++;
+ if ((fp->f_rd - fp->f_ld) >= fp->f_nfiles) {
+ *name = '\0';
+ return -1;
+ }
+ strncpy(name, fp->f_rd->dir_name, sizeof(fp->f_rd->dir_name));
+ if ((p = strchr(name, ' ')))
+ *p = '\0';
+ fp->f_rd++;
+ } else
+ fp->f_rd = fp->f_ld;
+
+ return 0;
+}
diff --git a/sys/arch/hppa64/stand/libsa/machdep.c b/sys/arch/hppa64/stand/libsa/machdep.c
new file mode 100644
index 00000000000..521488e2257
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/machdep.c
@@ -0,0 +1,75 @@
+/* $OpenBSD: machdep.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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 <sys/reboot.h>
+#include "libsa.h"
+#include <machine/iomod.h>
+#include <machine/pdc.h>
+
+#include "dev_hppa64.h"
+
+extern struct stable_storage sstor; /* contents of Stable Storage */
+int howto;
+dev_t bootdev;
+
+void
+machdep()
+{
+ pdc_init();
+#ifdef notyet
+ debug_init();
+#endif
+ cninit();
+
+#ifdef PDCDEBUG
+ if (debug) {
+ int i;
+
+ printf("SSTOR:\n");
+ printf("pri_boot="); DEVPATH_PRINT(&sstor.ss_pri_boot);
+ printf("alt_boot="); DEVPATH_PRINT(&sstor.ss_alt_boot);
+ printf("console ="); DEVPATH_PRINT(&sstor.ss_console);
+ printf("keyboard="); DEVPATH_PRINT(&sstor.ss_keyboard);
+ printf("mem=%d, fn=%s, osver=%d\nos={",
+ sstor.ss_fast_size, sstor.ss_filenames,
+ sstor.ss_os_version);
+ for (i = 0; i < sizeof(sstor.ss_os); i++)
+ printf ("%x%c", sstor.ss_os[i], (i%8)? ',' : '\n');
+
+ printf("}\nPAGE0:\n");
+ printf("ivec=%x, pf=%p[%u], toc=%p[%u], rndz=%p, clk/10ms=%u\n",
+ PAGE0->ivec_special, PAGE0->ivec_mempf,
+ PAGE0->ivec_mempflen, PAGE0->ivec_toc,
+ PAGE0->ivec_toclen, PAGE0->ivec_rendz,
+ PAGE0->mem_10msec);
+ printf ("mem: cont=%u, phys=%u, pdc_spa=%u, resv=%u, free=%x\n"
+ "cpu_hpa=%x, pdc=%p, imm_hpa=%p[%u,%u], soft=%u\n",
+ PAGE0->memc_cont, PAGE0->memc_phsize, PAGE0->memc_adsize,
+ PAGE0->memc_resv, PAGE0->mem_free, PAGE0->mem_hpa,
+ PAGE0->mem_pdc, PAGE0->imm_hpa, PAGE0->imm_spa_size,
+ PAGE0->imm_max_mem, PAGE0->imm_soft_boot);
+
+ printf("console: "); PZDEV_PRINT(&PAGE0->mem_cons);
+ printf("boot: "); PZDEV_PRINT(&PAGE0->mem_boot);
+ printf("keyboard: "); PZDEV_PRINT(&PAGE0->mem_kbd);
+ }
+#endif
+}
diff --git a/sys/arch/hppa64/stand/libsa/pdc.c b/sys/arch/hppa64/stand/libsa/pdc.c
new file mode 100644
index 00000000000..1569c52a1dd
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/pdc.c
@@ -0,0 +1,448 @@
+/* $OpenBSD: pdc.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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.
+ */
+/*
+ * Copyright 1996 1995 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * Copyright (c) 1990 mt Xinu, Inc. All rights reserved.
+ * Copyright (c) 1990 University of Utah. All rights reserved.
+ *
+ * This file may be freely distributed in any form as long as
+ * this copyright notice is included.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Utah $Hdr: pdc.c 1.8 92/03/14$
+ */
+
+#include <sys/time.h>
+#include "libsa.h"
+#include <sys/reboot.h>
+#include <sys/disklabel.h>
+
+#include <machine/trap.h>
+#include <machine/pdc.h>
+#include <machine/iomod.h>
+#include <machine/nvm.h>
+#include <machine/param.h>
+#include <machine/cpufunc.h>
+
+#include "dev_hppa64.h"
+
+/*
+ * Interface routines to initialize and access the PDC.
+ */
+
+pdcio_t pdc;
+int pdcbuf[64] PDC_ALIGNMENT;/* PDC return buffer */
+struct stable_storage sstor; /* contents of Stable Storage */
+int sstorsiz; /* size of Stable Storage */
+struct bootdata bd;
+int bdsize = sizeof(struct bootdata);
+
+/*
+ * Initialize PDC and related variables.
+ */
+void
+pdc_init()
+{
+ int err;
+
+ /*
+ * Initialize important global variables (defined above).
+ */
+ pdc = (pdcio_t)(u_long)PAGE0->mem_pdc;
+
+ err = pdc_call(pdc, PDC_STABLE, PDC_STABLE_SIZE, pdcbuf, 0, 0);
+ if (err >= 0) {
+ sstorsiz = min(pdcbuf[0],sizeof(sstor));
+ err = (*pdc)(PDC_STABLE, PDC_STABLE_READ, 0, &sstor, sstorsiz);
+ }
+
+ /*
+ * Now that we (may) have an output device, if we encountered
+ * an error reading Stable Storage (above), let them know.
+ */
+#ifdef DEBUG
+ if (debug && err)
+ printf("Stable storage PDC_STABLE Read Ret'd %d\n", err);
+#endif
+
+ /*
+ * Clear the FAULT light (so we know when we get a real one)
+ */
+ pdc_call(pdc, PDC_CHASSIS, PDC_CHASSIS_DISP,
+ PDC_OSTAT(PDC_OSTAT_BOOT) | 0xCEC0);
+}
+
+/*
+ * Generic READ/WRITE through IODC. Takes pointer to PDC device
+ * information, returns (positive) number of bytes actually read or
+ * the (negative) error condition, or zero if at "EOF".
+ */
+int
+iodcstrategy(devdata, rw, blk, size, buf, rsize)
+ void *devdata;
+ int rw;
+ daddr_t blk;
+ size_t size;
+ void *buf;
+ size_t *rsize;
+{
+ struct hppa_dev *dp = devdata;
+ struct pz_device *pzdev = dp->pz_dev;
+ iodcio_t iodc = (iodcio_t)(u_long)pzdev->pz_iodc_io;
+ int offset, xfer, ret;
+
+#ifdef PDCDEBUG
+ if (debug)
+ printf("iodcstrategy(%p, %s, %u, %u, %p, %p)\n", devdata,
+ rw==F_READ? "READ" : "WRITE", blk, size, buf, rsize);
+
+ if (debug > 1)
+ PZDEV_PRINT(pzdev);
+#endif
+
+ blk += dp->fsoff;
+ blk <<= DEV_BSHIFT;
+ if ((pzdev->pz_class & PCL_CLASS_MASK) == PCL_SEQU) {
+ /* rewind and re-read to seek */
+ if (blk < dp->last_blk) {
+#ifdef PDCDEBUG
+ if (debug)
+ printf("iodc: rewind ");
+#endif
+ if ((ret = ((iodcio_t)(long)pzdev->pz_iodc_io)(
+ pzdev->pz_hpa, IODC_IO_READ, pzdev->pz_spa,
+ pzdev->pz_layers, pdcbuf, 0, dp->buf, 0, 0)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("IODC_IO: %d\n", ret);
+#endif
+ return (EIO);
+ } else {
+ dp->last_blk = 0;
+ dp->last_read = 0;
+ }
+ }
+
+#ifdef PDCDEBUG
+ if (debug)
+ printf("seek %d ", dp->last_blk);
+#endif
+ for (; (dp->last_blk + dp->last_read) <= blk;
+ dp->last_read = ret) {
+ twiddle();
+ dp->last_blk += dp->last_read;
+ if ((ret = (iodc)(pzdev->pz_hpa,
+ IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers,
+ pdcbuf, dp->last_blk, dp->buf, IODC_IOSIZ,
+ IODC_IOSIZ)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("IODC_IO: %d\n", ret);
+#endif
+ return (EIO);
+ }
+ if ((ret = pdcbuf[0]) == 0)
+ break;
+#ifdef PDCDEBUG
+ if (debug)
+ printf("-");
+#endif
+ }
+#ifdef PDCDEBUG
+ if (debug)
+ printf("> %d[%d]\n", dp->last_blk, dp->last_read);
+#endif
+ }
+
+ xfer = 0;
+ /* see if we can scratch anything from buffer */
+ if (dp->last_blk <= blk && (dp->last_blk + dp->last_read) > blk) {
+ twiddle();
+ offset = blk - dp->last_blk;
+ xfer = min(dp->last_read - offset, size);
+ size -= xfer;
+ blk += xfer;
+#ifdef PDCDEBUG
+ if (debug)
+ printf("off=%d,xfer=%d,size=%d,blk=%d\n",
+ offset, xfer, size, blk);
+#endif
+ bcopy(dp->buf + offset, buf, xfer);
+ buf += xfer;
+ }
+
+ /*
+ * double buffer it all the time, to cache
+ */
+ for (; size; size -= ret, buf += ret, blk += ret, xfer += ret) {
+ offset = blk & IOPGOFSET;
+ if ((ret = (iodc)(pzdev->pz_hpa,
+ (rw == F_READ? IODC_IO_READ: IODC_IO_WRITE),
+ pzdev->pz_spa, pzdev->pz_layers, pdcbuf,
+ blk - offset, dp->buf, IODC_IOSIZ, IODC_IOSIZ)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("iodc_read(%d,%d): %d\n",
+ blk - offset, IODC_IOSIZ, ret);
+#endif
+ if (xfer)
+ break;
+ else
+ return (EIO);
+ }
+ if ((ret = pdcbuf[0]) <= 0)
+ break;
+ dp->last_blk = blk - offset;
+ dp->last_read = ret;
+ if ((ret -= offset) > size)
+ ret = size;
+ bcopy(dp->buf + offset, buf, ret);
+#ifdef PDCDEBUG
+ if (debug)
+ printf("read %d(%d,%d)@%x ", ret,
+ dp->last_blk, dp->last_read, (u_int)buf);
+#endif
+ }
+
+#ifdef PDCDEBUG
+ if (debug)
+ printf("\n");
+#endif
+
+ if (rsize)
+ *rsize = xfer;
+ return (0);
+}
+
+/*
+ * Find a device with specified unit number
+ * (any if unit == -1), and of specified class (PCL_*).
+ */
+struct pz_device *
+pdc_findev(unit, class)
+ int unit, class;
+{
+ static struct pz_device pz;
+ int layers[sizeof(pz.pz_layers)/sizeof(pz.pz_layers[0])];
+ iodcio_t iodc;
+ int err = 0;
+ u_int hpa, spa;
+
+#ifdef PDCDEBUG
+ if (debug)
+ printf("pdc_finddev(%d, %x)\n", unit, class);
+#endif
+ iodc = (iodcio_t)((u_long)PAGE0->mem_free + IODC_MAXSIZE);
+ hpa = PAGE0->mem_boot.pz_hpa;
+ spa = ((struct iomod *)(u_long)hpa)->io_spa;
+
+ /* quick hack for boot device */
+ if (PAGE0->mem_boot.pz_class == class &&
+ (unit == -1 || PAGE0->mem_boot.pz_layers[0] == unit)) {
+
+ bcopy (&PAGE0->mem_boot.pz_dp, &pz.pz_dp, sizeof(pz.pz_dp));
+ bcopy (pz.pz_layers, layers, sizeof(layers));
+ if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa,
+ IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("IODC_READ: %d\n", err);
+#endif
+ return NULL;
+ }
+ } else {
+ struct pdc_memmap memmap;
+ struct iodc_data mptr;
+ int i, stp;
+
+ for (i = 0; i < 0xf; i++) {
+ pz.pz_bc[0] = pz.pz_bc[1] =
+ pz.pz_bc[2] = pz.pz_bc[3] = -1;
+ pz.pz_bc[4] = 2;
+ pz.pz_bc[5] = 0; /* core bus */
+ pz.pz_mod = i;
+ if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap,
+ &pz.pz_dp) < 0)
+ continue;
+#ifdef PDCDEBUG
+ if (debug)
+ printf("memap: %d.%d.%d, hpa=%x, mpgs=%x\n",
+ pz.pz_bc[4], pz.pz_bc[5], pz.pz_mod,
+ memmap.hpa, memmap.morepages);
+#endif
+ hpa = memmap.hpa;
+
+ if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, hpa,
+ IODC_DATA, &mptr, sizeof(mptr))) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("IODC_DATA: %d\n", err);
+#endif
+ continue;
+ }
+
+ if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa,
+ IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("IODC_READ: %d\n", err);
+#endif
+ continue;
+ }
+
+ stp = IODC_INIT_FIRST;
+ do {
+ if ((err = (iodc)(hpa, stp, spa, layers,
+ pdcbuf, 0, 0, 0, 0)) < 0) {
+#ifdef DEBUG
+ if (debug && err != PDC_ERR_EOD)
+ printf("IODC_INIT_%s: %d\n",
+ stp==IODC_INIT_FIRST?
+ "FIRST":"NEXT", err);
+#endif
+ break;
+ }
+#ifdef PDCDEBUG
+ if (debug)
+ printf("[%x,%x,%x,%x,%x,%x], "
+ "[%x,%x,%x,%x,%x,%x]\n",
+ pdcbuf[0], pdcbuf[1], pdcbuf[2],
+ pdcbuf[3], pdcbuf[4], pdcbuf[5],
+ layers[0], layers[1], layers[2],
+ layers[3], layers[4], layers[5]);
+#endif
+ stp = IODC_INIT_NEXT;
+
+ } while (pdcbuf[1] != class &&
+ unit != -1 && unit != layers[0]);
+
+ if (err >= 0)
+ break;
+ }
+ }
+
+ if (err >= 0) {
+ /* init device */
+ if (0 && (err = (iodc)(hpa, IODC_INIT_DEV, spa,
+ layers, pdcbuf, 0, 0, 0, 0)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("INIT_DEV: %d\n", err);
+#endif
+ return NULL;
+ }
+
+ /* read i/o entry code */
+ if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa,
+ IODC_IO, iodc, IODC_MAXSIZE)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("IODC_READ: %d\n", err);
+#endif
+ return NULL;
+ }
+
+ pz.pz_flags = 0;
+ bcopy(layers, pz.pz_layers, sizeof(pz.pz_layers));
+ pz.pz_hpa = hpa;
+/* XXX pz.pz_spa = spa; */
+ pz.pz_iodc_io = (u_long)iodc;
+ pz.pz_class = class;
+
+ return &pz;
+ }
+
+ return NULL;
+}
+
+static __inline void
+fall(int c_base, int c_count, int c_loop, int c_stride, int data)
+{
+ int loop; /* Internal vars */
+
+ for (; c_count--; c_base += c_stride)
+ for (loop = c_loop; loop--; )
+ if (data)
+ fdce(0, c_base);
+ else
+ fice(0, c_base);
+}
+
+/*
+ * fcacheall - Flush all caches.
+ *
+ * This routine is just a wrapper around the real cache flush routine.
+ */
+struct pdc_cache pdc_cacheinfo PDC_ALIGNMENT;
+
+void
+fcacheall()
+{
+ int err;
+
+ if ((err = (*pdc)(PDC_CACHE, PDC_CACHE_DFLT, &pdc_cacheinfo)) < 0) {
+#ifdef DEBUG
+ if (debug)
+ printf("fcacheall: PDC_CACHE failed (%d).\n", err);
+#endif
+ return;
+ }
+#if PDCDEBUG
+ if (debug)
+ printf("pdc_cache:\nic={%u,%x,%x,%u,%u,%u}\n"
+ "dc={%u,%x,%x,%u,%u,%u}\n",
+ pdc_cacheinfo.ic_size, *(u_int *)&pdc_cacheinfo.ic_conf,
+ pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_stride,
+ pdc_cacheinfo.ic_count, pdc_cacheinfo.ic_loop,
+ pdc_cacheinfo.dc_size, *(u_int *)&pdc_cacheinfo.ic_conf,
+ pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_stride,
+ pdc_cacheinfo.dc_count, pdc_cacheinfo.dc_loop);
+#endif
+ /*
+ * Flush the instruction, then data cache.
+ */
+ fall(pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_count,
+ pdc_cacheinfo.ic_loop, pdc_cacheinfo.ic_stride, 0);
+ sync_caches();
+ fall(pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_count,
+ pdc_cacheinfo.dc_loop, pdc_cacheinfo.dc_stride, 1);
+ sync_caches();
+}
diff --git a/sys/arch/hppa64/stand/libsa/time.c b/sys/arch/hppa64/stand/libsa/time.c
new file mode 100644
index 00000000000..fd1fa22f1e7
--- /dev/null
+++ b/sys/arch/hppa64/stand/libsa/time.c
@@ -0,0 +1,47 @@
+/* $OpenBSD: time.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 2005 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 MIND, 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/types.h>
+#include <machine/pdc.h>
+#include <sys/disklabel.h>
+#include "libsa.h"
+#include "dev_hppa64.h"
+
+time_t
+getsecs()
+{
+ time_t tt;
+ int err;
+
+ if ((err = (*pdc)(PDC_TOD, PDC_TOD_READ, &pdcbuf)) < 0) {
+ tt = 0;
+#ifdef DEBUG
+ if (debug)
+ printf("getsecs: TOD read failed (%d)\n", err);
+#endif
+ } else {
+ tt = ((struct pdc_tod *)pdcbuf)->sec;
+#ifdef DEBUG
+ if (debug && tt < 800000000)
+ printf("getsecs: got %u seconds\n", tt);
+#endif
+ }
+
+ return tt;
+}
diff --git a/sys/arch/hppa64/stand/libz/Makefile b/sys/arch/hppa64/stand/libz/Makefile
new file mode 100644
index 00000000000..d6ed6c93837
--- /dev/null
+++ b/sys/arch/hppa64/stand/libz/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:49 mickey Exp $
+
+S=${.CURDIR}/../../../..
+ZDST=${.OBJDIR}
+SADIR=${.CURDIR}/..
+
+.PATH: ${S}/lib/libz
+
+.include "${S}/lib/libz/Makefile"
+CFLAGS+=${SACFLAGS} -I${S}/lib/libsa
diff --git a/sys/arch/hppa64/stand/mkboot/Makefile b/sys/arch/hppa64/stand/mkboot/Makefile
new file mode 100644
index 00000000000..e83c1dd1f66
--- /dev/null
+++ b/sys/arch/hppa64/stand/mkboot/Makefile
@@ -0,0 +1,14 @@
+# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:49 mickey Exp $
+
+MAN= mkboot.8
+MANSUBDIR=hppa64
+
+.if ${MACHINE} == "hppa64"
+PROG= mkboot
+CC= ${HOSTCC}
+LDSTATIC= -static
+.else
+NOPROG=
+.endif
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/hppa64/stand/mkboot/mkboot.8 b/sys/arch/hppa64/stand/mkboot/mkboot.8
new file mode 100644
index 00000000000..536bc587019
--- /dev/null
+++ b/sys/arch/hppa64/stand/mkboot/mkboot.8
@@ -0,0 +1,58 @@
+.\" $OpenBSD: mkboot.8,v 1.1 2005/04/01 10:40:49 mickey Exp $
+.\"
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. 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. 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.
+.\"
+.Dd November 11, 2002
+.Dt MKBOOT 8
+.Os
+.Sh NAME
+.Nm mkboot
+.Nd create LIF files
+.Sh SYNOPSIS
+.Nm mkboot
+.Op Fl v
+.Op Fl l Ar loadpoint
+.Ar program ... outfile
+.Sh DESCRIPTION
+Creates the LIF file containing the bootstrap
+.Ar program
+and possibly other programs to be used by the
+.Tn HP 9000/700
+and
+.Tn HP 9000/800
+systems.
+.Pp
+An argument to the
+.Fl l
+option specifies the load point for the boot program,
+with the default value of zero.
+.Sh HISTORY
+An
+.Nm
+utility first appeared in
+.Ox 2.4 .
diff --git a/sys/arch/hppa64/stand/mkboot/mkboot.c b/sys/arch/hppa64/stand/mkboot/mkboot.c
new file mode 100644
index 00000000000..ced89972b56
--- /dev/null
+++ b/sys/arch/hppa64/stand/mkboot/mkboot.c
@@ -0,0 +1,430 @@
+/* $OpenBSD: mkboot.c,v 1.1 2005/04/01 10:40:49 mickey Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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. 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.
+ *
+ * @(#)mkboot.c 8.1 (Berkeley) 7/15/93
+ */
+
+#if 0
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char rcsid[] = "$OpenBSD: mkboot.c,v 1.1 2005/04/01 10:40:49 mickey Exp $";
+#endif /* not lint */
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#ifdef __OpenBSD__
+#include <err.h>
+#endif
+
+#include <sys/exec_aout.h>
+#include <sys/exec_elf.h>
+
+#ifndef hppa
+/* hack for cross compile XXX */
+#include "../../include/disklabel.h"
+#else
+#include <sys/disklabel.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+int putfile(char *, int);
+void __dead usage(void);
+void bcddate(char *, char *);
+char *lifname(char *);
+int cksum(int, int *, int);
+
+char *to_file;
+int loadpoint, verbose;
+u_long entry;
+#ifndef __OpenBSD__
+char *__progname = "mkboot";
+#endif
+
+/*
+ * Old Format:
+ * sector 0: LIF volume header (40 bytes)
+ * sector 1: <unused>
+ * sector 2: LIF directory (8 x 32 == 256 bytes)
+ * sector 3-: LIF file 0, LIF file 1, etc.
+ * where sectors are 256 bytes.
+ *
+ * New Format:
+ * sector 0: LIF volume header (40 bytes)
+ * sector 1: <unused>
+ * sector 2: LIF directory (8 x 32 == 256 bytes)
+ * sector 3: <unused>
+ * sector 4-31: disklabel (~300 bytes right now)
+ * sector 32-: LIF file 0, LIF file 1, etc.
+ */
+int
+main(int argc, char **argv)
+{
+ int to;
+ register int n, pos, c;
+ char buf[LIF_FILESTART];
+ struct lifvol *lifv = (struct lifvol *)buf;
+ struct lifdir *lifd = (struct lifdir *)(buf + LIF_DIRSTART);
+
+ while ((c = getopt(argc, argv, "vl:")) != -1) {
+ switch (c) {
+ case 'v':
+ verbose++;
+ break;
+ case 'l':
+ sscanf(optarg, "0x%x", &loadpoint);
+ break;
+ default:
+ usage();
+ }
+ }
+ if (argc - optind < 2)
+ usage();
+ else if (argc - optind > 8)
+ errx(1, "too many boot programs (max 8 supported)");
+
+ to_file = argv[--argc];
+ if ((to = open(to_file, O_RDWR | O_TRUNC | O_CREAT, 0644)) < 0)
+ err(1, "%s: open", to_file);
+
+ bzero(buf, sizeof(buf));
+ /* clear possibly unused directory entries */
+ memset(lifd[1].dir_name, ' ', sizeof lifd[1].dir_name);
+ lifd[1].dir_type = -1;
+ lifd[1].dir_addr = 0;
+ lifd[1].dir_length = 0;
+ lifd[1].dir_flag = 0xFF;
+ lifd[1].dir_implement = 0;
+ lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];
+
+ /* record volume info */
+ lifv->vol_id = htobe16(LIF_VOL_ID);
+ strncpy(lifv->vol_label, "BOOT44", 6);
+ lifv->vol_addr = htobe32(btolifs(LIF_DIRSTART));
+ lifv->vol_oct = htobe16(LIF_VOL_OCT);
+ lifv->vol_dirsize = htobe32(btolifs(LIF_DIRSIZE));
+ lifv->vol_version = htobe16(1);
+ lifv->vol_lastvol = lifv->vol_number = htobe16(1);
+ lifv->vol_length = LIF_FILESTART;
+ bcddate(to_file, lifv->vol_toc);
+ lifv->ipl_addr = htobe32(LIF_FILESTART);
+ lifv->ipl_size = 0;
+ lifv->ipl_entry = 0;
+
+ argv += optind;
+ argc -= optind;
+ optind = 0;
+ for (pos = LIF_FILESTART; optind < argc; optind++) {
+
+ /* output bootfile */
+ lseek(to, pos, 0);
+ lifd[optind].dir_addr = htobe32(btolifs(pos));
+ n = btolifs(putfile(argv[optind], to));
+ if (lifv->ipl_entry == 0) {
+ lifv->ipl_entry = htobe32(loadpoint + entry);
+ lifv->ipl_size = htobe32(lifstob(n));
+ lifd[optind].dir_type = htobe16(LIF_DIR_ISL);
+ lifd[optind].dir_implement = 0;
+ } else {
+ lifd[optind].dir_type = htobe16(LIF_DIR_TYPE);
+ lifd[1].dir_implement = htobe32(loadpoint + entry);
+ }
+
+ strlcpy(lifd[optind].dir_name, lifname(argv[optind]),
+ sizeof lifd[optind].dir_name);
+ lifd[optind].dir_length = htobe32(n);
+ bcddate(argv[optind], lifd[optind].dir_toc);
+ lifd[optind].dir_flag = htobe16(LIF_DIR_FLAG);
+
+ lifv->vol_length += n;
+ pos += lifstob(n);
+ }
+
+ lifv->vol_length = htobe32(lifv->vol_length);
+
+ /* output volume/directory header info */
+ lseek(to, LIF_VOLSTART, 0);
+ if (write(to, buf, sizeof(buf)) != sizeof(buf))
+ err(1, "%s: write LIF volume", to_file);
+ lseek(to, 0, SEEK_END);
+
+ if (close(to) < 0)
+ err(1, "%s", to_file);
+
+ return(0);
+}
+
+int
+putfile(from_file, to)
+ char *from_file;
+ int to;
+{
+ struct exec ex;
+ register int n, total;
+ char buf[2048];
+ int from, check_sum = 0;
+ struct lif_load load;
+
+ if ((from = open(from_file, O_RDONLY)) < 0)
+ err(1, "%s", from_file);
+
+ n = read(from, &ex, sizeof(ex));
+ if (n != sizeof(ex))
+ err(1, "%s: reading file header", from_file);
+
+ entry = ex.a_entry;
+ if (N_GETMAGIC(ex) == OMAGIC || N_GETMAGIC(ex) == NMAGIC)
+ entry += sizeof(ex);
+ else if (IS_ELF(*(Elf64_Ehdr *)&ex)) {
+ Elf64_Ehdr elf_header;
+ Elf64_Phdr *elf_segments;
+ int i,header_count, memory_needed, elf_load_image_segment;
+
+ (void) lseek(from, 0, SEEK_SET);
+ n = read(from, &elf_header, sizeof (elf_header));
+ if (n != sizeof (elf_header))
+ err(1, "%s: reading ELF header", from_file);
+ header_count = betoh32(elf_header.e_phnum);
+ memory_needed = header_count * sizeof (*elf_segments);
+ elf_segments = malloc(memory_needed);
+ if (elf_segments == NULL)
+ err(1, "malloc");
+ (void) lseek(from, betoh32(elf_header.e_phoff), SEEK_SET);
+ n = read(from, elf_segments, memory_needed);
+ if (n != memory_needed)
+ err(1, "%s: reading ELF segments", from_file);
+ elf_load_image_segment = -1;
+ for (i = 0; i < header_count; i++) {
+ if (elf_segments[i].p_filesz &&
+ elf_segments[i].p_type == htobe32(PT_LOAD) &&
+ elf_segments[i].p_flags & htobe32(PF_X)) {
+ if (elf_load_image_segment != -1)
+ warnx("%s: more than one ELF program segment", from_file);
+ else
+ elf_load_image_segment = i;
+ }
+ }
+ if (elf_load_image_segment == -1)
+ errx(1, "%s: no suitable ELF program segment", from_file);
+ entry = betoh32(elf_header.e_entry) +
+ betoh32(elf_segments[elf_load_image_segment].p_offset) -
+ betoh32(elf_segments[elf_load_image_segment].p_vaddr);
+ } else if (*(u_char *)&ex == 0x1f && ((u_char *)&ex)[1] == 0x8b) {
+ entry = 0;
+ } else
+ errx(1, "%s: bad magic number", from_file);
+
+ entry += sizeof(load);
+ lseek(to, sizeof(load), SEEK_CUR);
+ total = 0;
+ n = sizeof(buf) - sizeof(load);
+ /* copy the whole file */
+ for (lseek(from, 0, 0); ; n = sizeof(buf)) {
+ bzero(buf, sizeof(buf));
+ if ((n = read(from, buf, n)) < 0)
+ err(1, "%s", from_file);
+ else if (n == 0)
+ break;
+
+ if (write(to, buf, n) != n)
+ err(1, "%s", to_file);
+
+ total += n;
+ check_sum = cksum(check_sum, (int *)buf, n);
+ }
+
+ /* load header */
+ load.address = htobe32(loadpoint + sizeof(load));
+ load.count = htobe32(4 + total);
+ check_sum = cksum(check_sum, (int *)&load, sizeof(load));
+
+ if (verbose)
+ warnx("wrote %d bytes of file \'%s\'", total, from_file);
+
+ total += sizeof(load);
+ /* insert the header */
+ lseek(to, -total, SEEK_CUR);
+ if (write(to, &load, sizeof(load)) != sizeof(load))
+ err(1, "%s", to_file);
+ lseek(to, total - sizeof(load), SEEK_CUR);
+
+ bzero(buf, sizeof(buf));
+ /* pad to int */
+ n = sizeof(int) - total % sizeof(int);
+ if (total % sizeof(int)) {
+ if (write(to, buf, n) != n)
+ err(1, "%s", to_file);
+ else
+ total += n;
+ }
+
+ /* pad to the blocksize */
+ n = sizeof(buf) - total % sizeof(buf);
+
+ if (n < sizeof(int)) {
+ n += sizeof(buf);
+ total += sizeof(buf);
+ } else
+ total += n;
+
+ /* TODO should pad here to the 65k boundary for tape boot */
+
+ if (verbose)
+ warnx("checksum is 0x%08x", -check_sum);
+
+ check_sum = htobe32(-check_sum);
+ if (write(to, &check_sum, sizeof(int)) != sizeof(int))
+ err(1, "%s", to_file);
+
+ n -= sizeof(int);
+
+ if (write(to, buf, n) != n)
+ err(1, "%s", to_file);
+
+ if (close(from) < 0 )
+ err(1, "%s", from_file);
+
+ return total;
+}
+
+int
+cksum(ck, p, size)
+ int ck;
+ int *p;
+ int size;
+{
+ /* we assume size is int-aligned */
+ for (size = (size + sizeof(int) - 1) / sizeof(int); size--; p++ )
+ ck += betoh32(*p);
+
+ return ck;
+}
+
+void __dead
+usage()
+{
+ extern char *__progname;
+ fprintf(stderr,
+ "usage: %s [-v] [-l loadpoint] prog1 {progN} outfile\n",
+ __progname);
+ exit(1);
+}
+
+char *
+lifname(str)
+ char *str;
+{
+ static char lname[10] = "XXXXXXXXXX";
+ register int i;
+
+ for (i = 0; i < 9; i++) {
+ if (islower(*str))
+ lname[i] = toupper(*str);
+ else if (isalnum(*str) || *str == '_')
+ lname[i] = *str;
+ else
+ break;
+ str++;
+ }
+ for ( ; i < 10; i++)
+ lname[i] = ' ';
+ return(lname);
+}
+
+
+void
+bcddate(file, toc)
+ char *file;
+ char *toc;
+{
+ struct stat statb;
+#ifndef __OpenBSD__
+ struct tm {
+ int tm_sec; /* second (0-61, allows for leap seconds) */
+ int tm_min; /* minute (0-59) */
+ int tm_hour; /* hour (0-23) */
+ int tm_mday; /* day of the month (1-31) */
+ int tm_mon; /* month (0-11) */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* day of the week (0-6) */
+ int tm_yday; /* day of the year (0-365) */
+ int tm_isdst; /* non-0 if daylight saving time is in effect */
+ } *tm;
+#else
+ struct tm *tm;
+#endif
+
+ stat(file, &statb);
+ tm = localtime(&statb.st_ctime);
+ *toc = (tm->tm_year / 10) << 4;
+ *toc++ |= tm->tm_year % 10;
+ *toc = ((tm->tm_mon+1) / 10) << 4;
+ *toc++ |= (tm->tm_mon+1) % 10;
+ *toc = (tm->tm_mday / 10) << 4;
+ *toc++ |= tm->tm_mday % 10;
+ *toc = (tm->tm_hour / 10) << 4;
+ *toc++ |= tm->tm_hour % 10;
+ *toc = (tm->tm_min / 10) << 4;
+ *toc++ |= tm->tm_min % 10;
+ *toc = (tm->tm_sec / 10) << 4;
+ *toc |= tm->tm_sec % 10;
+}
+
+#ifndef __OpenBSD__
+int
+err(ex, str)
+ int ex;
+ char *str;
+{
+ perror(str);
+ exit(ex);
+}
+
+int
+errx(ex, str)
+ int ex;
+ char *str;
+{
+ perror(str);
+ exit(ex);
+}
+#endif