summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-02-14 22:39:34 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-02-14 22:39:34 +0000
commitae0f5dc9f4a885cd2584fecf1b24ef3aa13a5d2c (patch)
tree2fcbfe0ba854ebfa8a33a9012c32c06f18bb3021
parentde434f28fb4d51b0f595c337047c7fe9c689ed09 (diff)
Work in progress standalone boot blocks for OpenBSD/loongson systems. Will
load a kernel from the OpenBSD partition, with symbols. However: - does not work on gdium (usb i/o errors) - no countdown due to PMON limitations, so either `bsd' in the PMON environment contains a kernel filename to load, and it will get loaded immediately, or it doesn't (e.g. the variable does no exist) and you get a prompt and can pass options to the kernel. Note that /etc/boot.conf commands can still be used in both cases. - does not work for me when loaded automatically from PMON (put in the `al' environment variable). However, `boot $al' works fine. Need to investigate.
-rw-r--r--sys/arch/loongson/Makefile37
-rw-r--r--sys/arch/loongson/include/loadfile_machdep.h49
-rw-r--r--sys/arch/loongson/include/pmon.h8
-rw-r--r--sys/arch/loongson/loongson/autoconf.c29
-rw-r--r--sys/arch/loongson/loongson/locore.S6
-rw-r--r--sys/arch/loongson/loongson/machdep.c40
-rw-r--r--sys/arch/loongson/loongson/pmon.c7
-rw-r--r--sys/arch/loongson/loongson/pmon32.S51
-rw-r--r--sys/arch/loongson/stand/Makefile8
-rw-r--r--sys/arch/loongson/stand/Makefile.inc49
-rw-r--r--sys/arch/loongson/stand/boot/Makefile51
-rw-r--r--sys/arch/loongson/stand/boot/conf.c74
-rw-r--r--sys/arch/loongson/stand/boot/cons.c95
-rw-r--r--sys/arch/loongson/stand/boot/dev.c219
-rw-r--r--sys/arch/loongson/stand/boot/devopen.c121
-rw-r--r--sys/arch/loongson/stand/boot/exec.c75
-rw-r--r--sys/arch/loongson/stand/boot/ld.script28
-rw-r--r--sys/arch/loongson/stand/boot/libsa.h56
-rw-r--r--sys/arch/loongson/stand/boot/machdep.c258
-rw-r--r--sys/arch/loongson/stand/boot/start.S55
-rw-r--r--sys/arch/loongson/stand/libsa/Makefile52
21 files changed, 1322 insertions, 46 deletions
diff --git a/sys/arch/loongson/Makefile b/sys/arch/loongson/Makefile
new file mode 100644
index 00000000000..698ee4de761
--- /dev/null
+++ b/sys/arch/loongson/Makefile
@@ -0,0 +1,37 @@
+# $OpenBSD: Makefile,v 1.1 2010/02/14 22:39:31 miod Exp $
+
+# Makefile for loongson tags file and boot blocks
+
+S=${.CURDIR}/../..
+.include "$S/kern/Make.tags.inc"
+
+SUBDIR= stand
+
+NOPROG= noprog
+NOMAN= noman
+
+TLOONGSON= $S/arch/loongson/tags
+
+SLOONGSON= $S/arch/loongson/dev/*.[ch] $S/arch/loongson/include/*.h \
+ $S/arch/loongson/loongson/*.[ch] \
+ $S/arch/mips64/dev/*.[ch] $S/arch/mips64/include/*.h \
+ $S/arch/mips64/mips64/*.[ch]
+ALOONGSON= $S/arch/loongson/loongson/*.S $S/arch/mips64/mips64/*.S
+
+# Directories in which to place tags links
+DLOONGSON= dev include loongson
+
+tags:
+ -ctags -wdtf ${TLOONGSON} ${SLOONGSON} ${COMM}
+ egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${ALOONGSON} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> ${TLOONGSON}
+ sort -o ${TLOONGSON} ${TLOONGSON}
+
+links:
+ -for i in ${DLOONGSON}; do \
+ (cd $$i && { rm -f tags; ln -s ${TLOONGSON} tags; }) done
+
+obj: _SUBDIRUSE
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/loongson/include/loadfile_machdep.h b/sys/arch/loongson/include/loadfile_machdep.h
new file mode 100644
index 00000000000..1319aae11e0
--- /dev/null
+++ b/sys/arch/loongson/include/loadfile_machdep.h
@@ -0,0 +1,49 @@
+/* $OpenBSD: loadfile_machdep.h,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+/* $NetBSD: loadfile_machdep.h,v 1.2 2001/10/31 17:20:49 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define BOOT_ELF
+#define ELFSIZE 64
+
+#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA)
+#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA)
+
+#define LOADADDR(a) (((u_long)(a)) + offset)
+#define ALIGNENTRY(a) ((u_long)(a))
+#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c))
+#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c))
+#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c))
+#define WARN(a) (void)(printf a, \
+ printf((errno ? ": %s\n" : "\n"), \
+ strerror(errno)))
+#define PROGRESS(a) (void) printf a
+#define ALLOC(a) alloc(a)
+#define FREE(a, b) free(a, b)
diff --git a/sys/arch/loongson/include/pmon.h b/sys/arch/loongson/include/pmon.h
index d946686b24b..ae110446374 100644
--- a/sys/arch/loongson/include/pmon.h
+++ b/sys/arch/loongson/include/pmon.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmon.h,v 1.1 2009/08/04 20:29:35 miod Exp $ */
+/* $OpenBSD: pmon.h,v 1.2 2010/02/14 22:39:33 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -19,7 +19,7 @@
#ifndef _MACHINE_PMON_H_
#define _MACHINE_PMON_H_
-#if defined(_KERNEL) || defined(STANDALONE)
+#if defined(_KERNEL) || defined(_STANDALONE)
/*
* PMON2000 callvec definitions
@@ -34,7 +34,7 @@ int pmon_open(const char *, int, ...);
int pmon_close(int);
int pmon_read(int, void *, pmon_size_t);
pmon_ssize_t pmon_write(int, const void *, pmon_size_t);
-pmon_off_t pmon_lseek(int, quad_t /* off_t */, int);
+pmon_off_t pmon_lseek(int, pmon_off_t, int);
int pmon_printf(const char *, ...);
void pmon_cacheflush(void);
char * pmon_gets(char *);
@@ -47,6 +47,6 @@ const char *pmon_getarg(const int);
const char *pmon_getenv(const char *);
void pmon_init(int32_t, int32_t, int32_t, int32_t);
-#endif /* _KERNEL || STANDALONE */
+#endif /* _KERNEL || _STANDALONE */
#endif /* _MACHINE_PMON_H_ */
diff --git a/sys/arch/loongson/loongson/autoconf.c b/sys/arch/loongson/loongson/autoconf.c
index ba016b1e411..9f59c8537b1 100644
--- a/sys/arch/loongson/loongson/autoconf.c
+++ b/sys/arch/loongson/loongson/autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.c,v 1.3 2010/02/11 20:14:08 otto Exp $ */
+/* $OpenBSD: autoconf.c,v 1.4 2010/02/14 22:39:33 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
*
@@ -22,7 +22,7 @@
#include <sys/reboot.h>
extern void dumpconf(void);
-void parsepmonbp(void);
+void parsepmonbp(void);
int cold = 1;
struct device *bootdv = NULL;
@@ -56,14 +56,23 @@ parsepmonbp(void)
}
strlcpy(bootdev, "unknown", sizeof bootdev);
- p = strchr(pmon_bootp, '@');
- if (p == NULL)
- return;
- p++;
- q = strchr(p, '/');
- if (q == NULL)
- return;
- len = q - p;
+ if (strncmp(pmon_bootp, "/dev/disk/", 10) == 0) {
+ /* kernel loaded by our boot blocks */
+ p = pmon_bootp + 10;
+ len = strlen(p);
+ } else {
+ /* kernel loaded by PMON */
+ p = strchr(pmon_bootp, '@');
+ if (p == NULL)
+ return;
+ p++;
+
+ q = strchr(p, '/');
+ if (q == NULL)
+ return;
+ len = q - p;
+ }
+
if (len <= 2 || len >= sizeof bootdev - 1)
return;
memcpy(bootdev, p, len);
diff --git a/sys/arch/loongson/loongson/locore.S b/sys/arch/loongson/loongson/locore.S
index 8c19e302084..f84a72d5f5d 100644
--- a/sys/arch/loongson/loongson/locore.S
+++ b/sys/arch/loongson/loongson/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.1 2009/12/11 05:14:52 miod Exp $ */
+/* $OpenBSD: locore.S,v 1.2 2010/02/14 22:39:33 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -57,8 +57,8 @@ start:
PTR_S ra, CF_RA_OFFS(t0) # save pmon return address
PTR_S sp, 0(t0) # and stack
move sp, t0
- jal mips_init # mips_init(argc, argv, envp, callvec)
- nop
+ jal mips_init # mips_init(argc, argv, envp,
+ nop # callvec, esym)
beqz v0, 1f # upon failure, return to pmon
nop
diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c
index 60a8494df18..b97dba05c9c 100644
--- a/sys/arch/loongson/loongson/machdep.c
+++ b/sys/arch/loongson/loongson/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.14 2010/02/12 19:39:27 otto Exp $ */
+/* $OpenBSD: machdep.c,v 1.15 2010/02/14 22:39:33 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -125,7 +125,7 @@ void build_trampoline(vaddr_t, vaddr_t);
void dumpsys(void);
void dumpconf(void);
extern void parsepmonbp(void);
-vaddr_t mips_init(int32_t, int32_t, int32_t, int32_t);
+vaddr_t mips_init(int32_t, int32_t, int32_t, int32_t, char *);
extern void loongson2e_setup(u_long, u_long);
extern void loongson2f_setup(u_long, u_long);
@@ -176,7 +176,8 @@ const struct bonito_flavour bonito_flavours[] = {
*/
vaddr_t
-mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv)
+mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv,
+ char *boot_esym)
{
uint prid, loongson_ver;
u_long memlo, memhi, cpuspeed;
@@ -205,22 +206,31 @@ mips_init(int32_t argc, int32_t argv, int32_t envp, int32_t cv)
cn_tab = &pmoncons;
/*
- * Attempt to locate ELF header and symbol table after kernel,
- * and reserve space for the symbol table, if it exists.
+ * Reserve space for the symbol table, if it exists.
*/
- ssym = (char *)(vaddr_t)*(int32_t *)end;
- if (((long)ssym - (long)end) >= 0 &&
- ((long)ssym - (long)end) <= 0x1000 &&
- ssym[0] == ELFMAG0 && ssym[1] == ELFMAG1 &&
- ssym[2] == ELFMAG2 && ssym[3] == ELFMAG3 ) {
- /* Pointers exist directly after kernel. */
- esym = (char *)(vaddr_t)*((int32_t *)end + 1);
+ /* Attempt to locate ELF header and symbol table after kernel. */
+ if (end[0] == ELFMAG0 && end[1] == ELFMAG1 &&
+ end[2] == ELFMAG2 && end[3] == ELFMAG3) {
+ /* ELF header exists directly after kernel. */
+ ssym = end;
+ esym = boot_esym;
ekern = esym;
} else {
- /* Pointers aren't setup either... */
- ssym = esym = NULL;
- ekern = end;
+ ssym = (char *)(vaddr_t)*(int32_t *)end;
+ if (((long)ssym - (long)end) >= 0 &&
+ ((long)ssym - (long)end) <= 0x1000 &&
+ ssym[0] == ELFMAG0 && ssym[1] == ELFMAG1 &&
+ ssym[2] == ELFMAG2 && ssym[3] == ELFMAG3) {
+ /* Pointers exist directly after kernel. */
+ esym = (char *)(vaddr_t)*((int32_t *)end + 1);
+ ekern = esym;
+ } else {
+ /* Pointers aren't setup either... */
+ ssym = NULL;
+ esym = NULL;
+ ekern = end;
+ }
}
/*
diff --git a/sys/arch/loongson/loongson/pmon.c b/sys/arch/loongson/loongson/pmon.c
index 9268dacf873..073c650fb51 100644
--- a/sys/arch/loongson/loongson/pmon.c
+++ b/sys/arch/loongson/loongson/pmon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmon.c,v 1.2 2010/02/05 20:51:22 miod Exp $ */
+/* $OpenBSD: pmon.c,v 1.3 2010/02/14 22:39:33 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -20,6 +20,7 @@
#include <sys/systm.h>
#include <sys/proc.h>
+#include <machine/cpu.h>
#include <machine/pmon.h>
int pmon_argc;
@@ -77,8 +78,12 @@ pmon_getenv(const char *var)
(vaddr_t)envstr >= CKSSEG_BASE) {
pmon_printf("WARNING! CORRUPTED ENVIRONMENT!\n");
pmon_printf("Unable to search for %s.\n", var);
+#ifdef _STANDALONE
+ pmon_printf("If boot fails, power-cycle the machine.\n");
+#else
pmon_printf("If the kernel fails to identify the system"
" type, please boot it again with `-k' option.\n");
+#endif
/* terminate environment for further calls */
*envptr = 0;
diff --git a/sys/arch/loongson/loongson/pmon32.S b/sys/arch/loongson/loongson/pmon32.S
index 5394bfa3143..14786928465 100644
--- a/sys/arch/loongson/loongson/pmon32.S
+++ b/sys/arch/loongson/loongson/pmon32.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmon32.S,v 1.2 2010/02/03 21:45:48 miod Exp $ */
+/* $OpenBSD: pmon32.S,v 1.3 2010/02/14 22:39:33 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -37,7 +37,9 @@
#include <machine/param.h>
#include <machine/asm.h>
+#ifndef _STANDALONE
#include "assym.h"
+#endif
.set mips3
@@ -101,7 +103,7 @@ PMON_WRAP(pmon_gets)
dsra32 v0, 0
PMON_END(pmon_gets)
-#if 0
+#ifdef _STANDALONE
PMON_WRAP(pmon_cacheflush)
lw t0, pmon_callvec
@@ -110,10 +112,6 @@ PMON_WRAP(pmon_cacheflush)
nop
PMON_END(pmon_cacheflush)
-/*
- * The following routines are untested.
- */
-
PMON_WRAP(pmon_open)
lw t0, pmon_callvec
lw t0, 0 * 4 (t0)
@@ -135,18 +133,29 @@ PMON_WRAP(pmon_read)
nop
PMON_END(pmon_read)
-PMON_WRAP(pmon_write)
- lw t0, pmon_callvec
- lw t0, 3 * 4 (t0)
- jalr t0
- nop
-PMON_END(pmon_write)
-
PMON_WRAP(pmon_lseek)
lw t0, pmon_callvec
lw t0, 4 * 4 (t0)
+#if 0
+ /*
+ * Setup arguments the way 32-bit PMON expects them.
+ * 64-bit mode: a0 = fd, a1 = off, a2 = whence
+ * 32-bit mode: a0 = fd, a2:a3 = off, 16(sp) = whence
+ */
+ sw a2, 16(sp)
+#ifdef __MIPSEB__
+ dsll32 a3, a1, 0
+ dsrl32 a2, a1, 0 /* a2 = hi */
+ dsrl32 a3, a3, 0 /* a3 = low */
+#else
+ dsll32 a2, a1, 0
+ dsrl32 a3, a1, 0 /* a3 = hi */
+ dsrl32 a2, a2, 0 /* a2 = low */
+#endif
+#endif
jalr t0
nop
+#if 0
/* rebuild the 64 bit return value */
dsll32 v0, 0
dsll32 v1, 0
@@ -158,6 +167,22 @@ PMON_WRAP(pmon_lseek)
dsrl32 v0, 0
#endif
or v0, v1, v0
+#endif
PMON_END(pmon_lseek)
#endif
+
+/*
+ * The following routines are untested.
+ */
+
+#if 0
+
+PMON_WRAP(pmon_write)
+ lw t0, pmon_callvec
+ lw t0, 3 * 4 (t0)
+ jalr t0
+ nop
+PMON_END(pmon_write)
+
+#endif
diff --git a/sys/arch/loongson/stand/Makefile b/sys/arch/loongson/stand/Makefile
new file mode 100644
index 00000000000..8cbe204d471
--- /dev/null
+++ b/sys/arch/loongson/stand/Makefile
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile,v 1.1 2010/02/14 22:39:33 miod Exp $
+
+.if ${MACHINE} == "loongson"
+SUBDIR+= libsa
+.endif
+SUBDIR+= boot
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/loongson/stand/Makefile.inc b/sys/arch/loongson/stand/Makefile.inc
new file mode 100644
index 00000000000..1bf6cfac139
--- /dev/null
+++ b/sys/arch/loongson/stand/Makefile.inc
@@ -0,0 +1,49 @@
+# $OpenBSD: Makefile.inc,v 1.1 2010/02/14 22:39:33 miod Exp $
+
+BINDIR= /usr/mdec
+
+STANDALONE?= -D_STANDALONE
+
+.if ${MACHINE} == "loongson"
+CPPFLAGS+= ${STANDALONE}
+CPPFLAGS+= -I.
+CFLAGS+= -fno-stack-protector -Wall
+CFLAGS+= -fno-builtin-vprintf -fno-builtin-printf -fno-builtin-putchar
+# Silence warnings
+CFLAGS+= -fno-builtin-snprintf
+CFLAGS+= -fno-builtin-memcpy
+CFLAGS+= -fno-builtin-memcmp
+CFLAGS+= -fno-builtin-memset
+CFLAGS+= -fno-builtin-strncpy
+CFLAGS+= -fno-builtin-strncmp
+CFLAGS+= -Wa,-mfix-loongson2f-btb
+SAABI= -mips3 -mno-abicalls -G 0 -fno-pic -fno-common
+AS?= as
+LD?= ld
+.endif
+
+### Figure out what to use for libsa
+LIBSADIR?= ${.CURDIR}/../libsa
+
+.if exists(${LIBSADIR}/obj.${MACHINE})
+LIBSAOBJDIR= ${LIBSADIR}/obj.${MACHINE}
+.elif exists(${LIBSADIR}/obj)
+LIBSAOBJDIR= ${LIBSADIR}/obj
+.else
+LIBSAOBJDIR= ${LIBSADIR}
+.endif
+
+LIBSA= ${LIBSAOBJDIR}/libsa.a
+
+### Figure out what to use for libz
+LIBZDIR?= ${.CURDIR}/../libz
+
+.if exists(${LIBZDIR}/obj.${MACHINE})
+LIBZOBJDIR= ${LIBZDIR}/obj.${MACHINE}
+.elif exists(${LIBZDIR}/obj)
+LIBZOBJDIR= ${LIBZDIR}/obj
+.else
+LIBZOBJDIR= ${LIBZDIR}
+.endif
+
+LIBZ= ${LIBZOBJDIR}/libz.a
diff --git a/sys/arch/loongson/stand/boot/Makefile b/sys/arch/loongson/stand/boot/Makefile
new file mode 100644
index 00000000000..0fec43e523f
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/Makefile
@@ -0,0 +1,51 @@
+# $OpenBSD: Makefile,v 1.1 2010/02/14 22:39:33 miod Exp $
+
+.include "${.CURDIR}/../Makefile.inc"
+
+NOMAN=
+#MAN= boot.8
+#MLINKS= boot.8 boot.conf.5
+
+.if ${MACHINE} == "loongson"
+PROG= boot
+
+S= ${.CURDIR}/../../../..
+
+CPPFLAGS+= ${SAABI} -mno-abicalls -D_NO_ABICALLS \
+ -nostdinc -D__loongson__ \
+ -I${S} -I${S}/lib/libsa \
+ -I${.OBJDIR} -I${.CURDIR}
+
+LDSCRIPT= ${.CURDIR}/ld.script
+LDFLAGS+= ${SALDFLAGS} -T ${LDSCRIPT} -e __start
+
+AFLAGS+= ${SAABI}
+
+SRCS= start.S
+SRCS+= conf.c cons.c dev.c devopen.c exec.c machdep.c
+.PATH: ${S}/arch/loongson/loongson
+SRCS+= pmon.c pmon32.S
+
+#### MI boot code
+.PATH: ${S}/stand/boot
+SRCS+= boot.c cmd.c vars.c
+
+#### libkern
+.PATH: ${S}/lib/libkern/arch/mips64 ${S}/lib/libkern
+SRCS+= strlcat.c strlcpy.c strlen.c
+SRCS+= udivdi3.c qdivrem.c
+
+.if !make(obj)
+.BEGIN:
+ @([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
+ @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64)
+CLEANFILES+= machine mips64
+.endif
+
+${PROG}: ${OBJS} ${LIBSA}
+ ${LD} ${LDFLAGS} -o ${PROG} ${OBJS} -L${LIBSADIR} ${LIBSA}
+.else
+NOPROG=
+.endif
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/loongson/stand/boot/conf.c b/sys/arch/loongson/stand/boot/conf.c
new file mode 100644
index 00000000000..4f365911838
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/conf.c
@@ -0,0 +1,74 @@
+/* $OpenBSD: conf.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 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.
+ *
+ * @(#)conf.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+
+#include <dev/cons.h>
+
+#include "libsa.h"
+#include <lib/libsa/ufs.h>
+#include <lib/libsa/cd9660.h>
+
+const char version[] = "0.1";
+#if 0 /* network code not compiled in */
+int debug = 0;
+#endif
+
+/*
+ * Device configuration
+ */
+struct devsw devsw[] = {
+ { "wd", pmon_iostrategy, pmon_ioopen, pmon_ioclose, noioctl },
+ { "usbg", pmon_iostrategy, pmon_ioopen, pmon_ioclose, noioctl }
+};
+int ndevs = NENTS(devsw);
+
+/*
+ * Filesystem configuration
+ */
+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 }
+};
+int nfsys = NENTS(file_system);
+
+/*
+ * Console configuration
+ */
+struct consdev constab[] = {
+ { pmon_cnprobe, pmon_cninit, pmon_cngetc, pmon_cnputc },
+ { NULL }
+};
+struct consdev *cn_tab;
diff --git a/sys/arch/loongson/stand/boot/cons.c b/sys/arch/loongson/stand/boot/cons.c
new file mode 100644
index 00000000000..fe6dc685d63
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/cons.c
@@ -0,0 +1,95 @@
+/* $OpenBSD: cons.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <lib/libkern/libkern.h>
+#include "libsa.h"
+#include <dev/cons.h>
+#include <machine/cpu.h>
+#include <machine/pmon.h>
+
+/*
+ * PMON console
+ */
+
+void
+pmon_cnprobe(struct consdev *cn)
+{
+ cn->cn_pri = CN_HIGHPRI;
+}
+
+void
+pmon_cninit(struct consdev *cn)
+{
+}
+
+int
+pmon_cngetc(dev_t dev)
+{
+ /*
+ * PMON does not give us a getc routine. So try to get a whole line
+ * and return it char by char, trying not to lose the \n. Kind
+ * of ugly but should work.
+ *
+ * Note that one could theoretically use pmon_read(STDIN, &c, 1)
+ * but the value of STDIN within PMON is not a constant and there
+ * does not seem to be a way of letting us know which value to use.
+ */
+ static char buf[1 + PMON_MAXLN];
+ static char *bufpos = buf;
+
+ int c;
+
+ /*
+ * Neither pmon_gets() nor pmon_read() from stdin seem to work
+ * on the Gdium...
+ */
+ if (pmon_quirks & PQ_GDIUM) {
+ for (;;) ;
+ }
+
+ if (*bufpos == '\0') {
+ bufpos = buf;
+ if (pmon_gets(buf) == NULL) {
+ /* either an empty line or EOF, assume the former */
+ strlcpy(buf, "\n", sizeof buf);
+ } else {
+ /* put back the \n sign */
+ buf[strlen(buf)] = '\n';
+ }
+ }
+
+ c = (int)*bufpos;
+ if ((dev & 0x80) == 0) {
+ bufpos++;
+ if (bufpos - buf > PMON_MAXLN) {
+ bufpos = buf;
+ *bufpos = '\0';
+ }
+ }
+
+ return c;
+}
+
+void
+pmon_cnputc(dev_t dev, int c)
+{
+ if (c == '\n')
+ pmon_printf("\n");
+ else
+ pmon_printf("%c", c);
+}
diff --git a/sys/arch/loongson/stand/boot/dev.c b/sys/arch/loongson/stand/boot/dev.c
new file mode 100644
index 00000000000..ed8f8c070c4
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/dev.c
@@ -0,0 +1,219 @@
+/* $OpenBSD: dev.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include "libsa.h"
+#include <sys/disklabel.h>
+#include <machine/param.h>
+#include <machine/cpu.h>
+#include <machine/pmon.h>
+
+/*
+ * PMON I/O
+ */
+
+char pmon_bootdev[1 + 256];
+
+struct pmon_iodata {
+ int fd;
+ struct disklabel label;
+ off_t partoff;
+ off_t curpos;
+};
+
+int pmon_getdisklabel(struct pmon_iodata *pi);
+
+int
+pmon_iostrategy(void *f, int rw, daddr_t dblk, size_t size, void *buf,
+ size_t *rsize)
+{
+ struct pmon_iodata *pi = (struct pmon_iodata *)f;
+ off_t offs, pos;
+ int rc;
+
+ if (size == 0)
+ return 0;
+
+ if (rw != F_READ)
+ return EOPNOTSUPP;
+
+ offs = ((daddr64_t)dblk + pi->partoff) * DEV_BSIZE;
+ if (offs != pi->curpos) {
+ pos = pmon_lseek(pi->fd, offs, 0 /* SEEK_SET */);
+ if (pos != offs)
+ return EINVAL;
+ }
+
+ /* note this expects size to fit in 32 bits */
+ rc = pmon_read(pi->fd, buf, size);
+ if (rc >= 0) {
+ pi->curpos += rc;
+ *rsize = rc;
+ } else
+ *rsize = 0;
+
+ if (rc != size)
+ return EIO;
+ return 0;
+}
+
+int
+pmon_ioopen(struct open_file *f, ...)
+{
+ struct pmon_iodata *pi;
+ int rc;
+ va_list ap;
+ uint unit, part;
+
+ pi = alloc(sizeof *pi);
+ if (pi == NULL)
+ return ENOMEM;
+ bzero(pi, sizeof *pi);
+ f->f_devdata = pi;
+
+ va_start(ap, f);
+ unit = va_arg(ap, uint);
+ part = va_arg(ap, uint);
+ va_end(ap);
+
+ /*
+ * Open the raw device through PMON.
+ */
+
+ snprintf(pmon_bootdev, sizeof pmon_bootdev, "/dev/disk/%s%d",
+ f->f_dev->dv_name, unit);
+ rc = pmon_open(pmon_bootdev, 0 /* O_RDONLY */);
+ if (rc < 0)
+ return ENXIO;
+
+ pi->fd = rc;
+
+ /*
+ * Read disklabel.
+ */
+
+ if (pmon_getdisklabel(pi) != 0) {
+ pmon_ioclose(f);
+ return ENXIO;
+ }
+
+ if (part >= pi->label.d_npartitions) {
+ pmon_ioclose(f);
+ return EPART;
+ }
+
+ pi->partoff = DL_GETPOFFSET(&pi->label.d_partitions[part]);
+ pi->curpos = 0;
+
+ return 0;
+}
+
+int
+pmon_ioclose(struct open_file *f)
+{
+ struct pmon_iodata *pi;
+ int rc;
+
+ if (f->f_devdata != NULL) {
+ pi = (struct pmon_iodata *)f->f_devdata;
+ rc = pmon_close(pi->fd);
+ free(pi, sizeof *pi);
+ f->f_devdata = NULL;
+ } else
+ rc = 0;
+
+ return rc;
+}
+
+/*
+ * Read disk label from the device.
+ */
+int
+pmon_getdisklabel(struct pmon_iodata *pi)
+{
+ char *msg;
+ int sector;
+ size_t rsize;
+ struct disklabel *lp = &pi->label;
+ char buf[DEV_BSIZE];
+
+ bzero(lp, sizeof *lp);
+
+ /*
+ * Find OpenBSD Partition in DOS partition table.
+ */
+ sector = 0;
+ if (pmon_iostrategy(pi, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize))
+ return ENXIO;
+
+ if (*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF] == DOSMBR_SIGNATURE) {
+ int i;
+ struct dos_partition *dp = (struct dos_partition *)buf;
+
+ /*
+ * Lookup OpenBSD slice. If there is none, go ahead
+ * and try to read the disklabel off sector #0.
+ */
+ memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp));
+ for (i = 0; i < NDOSPART; i++) {
+ if (dp[i].dp_typ == DOSPTYP_OPENBSD) {
+ sector = letoh32(dp[i].dp_start);
+ break;
+ }
+ }
+ }
+
+ if (pmon_iostrategy(pi, F_READ, sector + LABELSECTOR, DEV_BSIZE,
+ buf, &rsize))
+ return ENXIO;
+
+ if ((msg = getdisklabel(buf + LABELOFFSET, lp))) {
+ printf("getdisklabel: %s\n", msg);
+ return ENXIO;
+ }
+
+ return 0;
+}
diff --git a/sys/arch/loongson/stand/boot/devopen.c b/sys/arch/loongson/stand/boot/devopen.c
new file mode 100644
index 00000000000..96fb75af979
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/devopen.c
@@ -0,0 +1,121 @@
+/* $OpenBSD: devopen.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Rolf Grossmann.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "libsa.h"
+
+#define MAXDEVNAME 16
+
+/*
+ * Parse a device spec.
+ *
+ * [A-Za-z]*[0-9]*[A-Za-z]:file
+ * dev uint part
+ */
+int
+devparse(const char *fname, int *dev, int *unit, int *part, const char **file)
+{
+ const char *s;
+
+ *unit = 0; /* default to wd0a */
+ *part = 0;
+ *dev = 0;
+
+ s = strchr(fname, ':');
+ if (s != NULL) {
+ int devlen;
+ int i, u, p = 0;
+ struct devsw *dp;
+ char devname[MAXDEVNAME];
+
+ devlen = s - fname;
+ if (devlen > MAXDEVNAME)
+ return (EINVAL);
+
+ /* extract device name */
+ for (i = 0; isalpha(fname[i]) && (i < devlen); i++)
+ devname[i] = fname[i];
+ devname[i] = 0;
+
+ if (!isdigit(fname[i]))
+ return (EUNIT);
+
+ /* device number */
+ for (u = 0; isdigit(fname[i]) && (i < devlen); i++)
+ u = u * 10 + (fname[i] - '0');
+
+ if (!isalpha(fname[i]))
+ return (EPART);
+
+ /* partition number */
+ if (i < devlen)
+ p = fname[i++] - 'a';
+
+ if (i != devlen)
+ return (ENXIO);
+
+ /* check device name */
+ for (dp = devsw, i = 0; i < ndevs; dp++, i++) {
+ if (dp->dv_name && !strcmp(devname, dp->dv_name))
+ break;
+ }
+
+ if (i >= ndevs)
+ return (ENXIO);
+
+ *unit = u;
+ *part = p;
+ *dev = i;
+ fname = ++s;
+ }
+
+ *file = fname;
+
+ return (0);
+}
+
+int
+devopen(struct open_file *f, const char *fname, char **file)
+{
+ struct devsw *dp;
+ int dev, unit, part, error;
+
+ error = devparse(fname, &dev, &unit, &part, (const char **)file);
+ if (error)
+ return (error);
+
+ dp = &devsw[dev];
+ if ((void *)dp->dv_open == (void *)nodev)
+ return (ENXIO);
+
+ f->f_dev = dp;
+
+ return (*dp->dv_open)(f, unit, part);
+}
diff --git a/sys/arch/loongson/stand/boot/exec.c b/sys/arch/loongson/stand/boot/exec.c
new file mode 100644
index 00000000000..37bd6488279
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/exec.c
@@ -0,0 +1,75 @@
+/* $OpenBSD: exec.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <machine/cpu.h>
+#include <machine/pmon.h>
+#include "libsa.h"
+#include <lib/libsa/loadfile.h>
+#include <machine/cpu.h>
+
+typedef void (*program)(int32_t, int32_t, int32_t *, int32_t, uint64_t *);
+
+#define PTR_TO_CKSEG1(ptr) (int32_t)(CKSEG1_BASE | (uint64_t)(ptr))
+
+void
+run_loadfile(u_long *marks, int howto)
+{
+ int32_t newargc;
+ int32_t *newargv;
+ char kernelflags[8];
+ char *c;
+ const char *arg;
+
+ /*
+ * Build a new commandline:
+ * boot <device kernel is loaded from> -<kernel options>
+ */
+
+ newargc = howto == 0 ? 2 : 3;
+ newargv = alloc(newargc * sizeof(int32_t));
+ if (newargv == NULL)
+ panic("out of memory");
+
+ arg = "boot"; /* kernel needs this. */
+ newargv[0] = PTR_TO_CKSEG1(arg);
+ newargv[1] = PTR_TO_CKSEG1(&pmon_bootdev);
+ if (howto != 0) {
+ c = kernelflags;
+ *c++ = '-';
+ if (howto & RB_ASKNAME)
+ *c++ = 'a';
+ if (howto & RB_CONFIG)
+ *c++ = 'c';
+ if (howto & RB_KDB)
+ *c++ = 'd';
+ if (howto & RB_SINGLE)
+ *c++ = 's';
+ *c = '\0';
+ newargv[2] = PTR_TO_CKSEG1(&kernelflags);
+ }
+
+ pmon_cacheflush();
+
+ (*(program)(marks[MARK_ENTRY]))(newargc, PTR_TO_CKSEG1(newargv),
+ pmon_envp, pmon_callvec,
+ (uint64_t *)PHYS_TO_CKSEG0(marks[MARK_END]));
+
+ _rtt();
+}
diff --git a/sys/arch/loongson/stand/boot/ld.script b/sys/arch/loongson/stand/boot/ld.script
new file mode 100644
index 00000000000..50977c3f8df
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/ld.script
@@ -0,0 +1,28 @@
+OUTPUT_FORMAT("elf64-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(__start)
+
+SECTIONS
+{
+ /*
+ * Load at 30MB; should be more than enough to be able to load the
+ * kernel image without overwriting ourselves.
+ */
+ . = 0xffffffff81e20000 + SIZEOF_HEADERS;
+ .text : { *(.text .text.* .gnu.linkonce.t.*) }
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ _gp = ALIGN(16) + 0x7ff0;
+ .data : { *(.data .data.* .gnu.linkonce.d.*) }
+ PROVIDE (edata = .);
+ .sbss : { *(.sbss .sbss.* .gnu.linkonce.sb.* .scommon) }
+ .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) }
+ PROVIDE (_end = .);
+ PROVIDE (end = .);
+ /DISCARD/ :
+ {
+ *(.pdr)
+ *(.mdebug.abi64)
+ *(.MIPS.options)
+ }
+}
diff --git a/sys/arch/loongson/stand/boot/libsa.h b/sys/arch/loongson/stand/boot/libsa.h
new file mode 100644
index 00000000000..55b3b223a92
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/libsa.h
@@ -0,0 +1,56 @@
+/* $OpenBSD: libsa.h,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <lib/libsa/stand.h>
+
+#define DEFAULT_KERNEL_ADDRESS 0
+
+/*
+ * MD interfaces for MI boot(9)
+ */
+void devboot(dev_t, char *);
+void machdep(void);
+void run_loadfile(u_long *, int);
+
+/*
+ * PMON console
+ */
+void pmon_cnprobe(struct consdev *);
+void pmon_cninit(struct consdev *);
+int pmon_cngetc(dev_t);
+void pmon_cnputc(dev_t, int);
+
+/*
+ * PMON I/O
+ */
+int pmon_iostrategy(void *, int, daddr_t, size_t, void *, size_t *);
+int pmon_ioopen(struct open_file *, ...);
+int pmon_ioclose(struct open_file *);
+
+extern int pmon_argc;
+extern int32_t *pmon_argv;
+extern int32_t *pmon_envp;
+extern int32_t pmon_callvec;
+
+/*
+ * Mask of PMON workarounds required due to castration by the vendor.
+ */
+#define PQ_GDIUM 0x00000001
+extern int pmon_quirks;
+
+extern char pmon_bootdev[];
diff --git a/sys/arch/loongson/stand/boot/machdep.c b/sys/arch/loongson/stand/boot/machdep.c
new file mode 100644
index 00000000000..9aea20bd3f4
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/machdep.c
@@ -0,0 +1,258 @@
+/* $OpenBSD: machdep.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 1998-2004 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.
+ */
+
+#include <sys/param.h>
+#include <lib/libkern/libkern.h>
+#include "libsa.h"
+#include <machine/cpu.h>
+#include <machine/pmon.h>
+#include <stand/boot/cmd.h>
+
+int pmon_quirks = 0;
+
+/*
+ * Console
+ */
+
+int
+cnspeed(dev_t dev, int sp)
+{
+ return 9600;
+}
+
+int
+getchar()
+{
+ int c = cngetc();
+
+ if (c == '\r')
+ c = '\n';
+
+ if ((c < ' ' && c != '\n') || c == '\177')
+ return c;
+
+ putchar(c);
+
+ return c;
+}
+
+int pch_pos;
+
+void
+putchar(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;
+ }
+}
+
+char *
+ttyname(int fd)
+{
+ return "pmon console";
+}
+
+dev_t
+ttydev(char *name)
+{
+ /* we do not support any other console than pmon */
+ return NODEV;
+}
+
+/*
+ * Configuration and device path aerobics
+ */
+
+/*
+ * Return the default boot device.
+ */
+void
+devboot(dev_t dev, char *path)
+{
+ const char *bootpath = NULL;
+ size_t bootpathlen;
+ const char *tmp;
+ int i;
+
+ /*
+ * First, try to figure where we have been loaded from; we'll assume
+ * the default device to load the kernel from is the same.
+ *
+ * We may have been loaded in three different ways:
+ * - automatic load from `al' environment variable.
+ * - manual `boot' command, with path on the commandline.
+ * - manual `load' and `go' commands, with no path on the commandline.
+ */
+
+ if (pmon_argc > 0) {
+ /* manual load */
+ tmp = (const char *)pmon_getarg(0);
+ if (tmp[0] != 'g') {
+ for (i = 1; i < pmon_argc; i++) {
+ tmp = (const char *)pmon_getarg(i);
+ if (tmp[0] != '-') {
+ bootpath = tmp;
+ break;
+ }
+ }
+ }
+ } else {
+ /* automatic load */
+ bootpath = pmon_getenv("al");
+ }
+
+ /*
+ * If the bootblocks have been loaded from the network,
+ * use the default disk.
+ */
+
+ if (bootpath != NULL && strncmp(bootpath, "tftp://", 7) == 0)
+ bootpath = NULL;
+
+ /*
+ * Now extract the device name from the bootpath.
+ */
+
+ if (bootpath != NULL) {
+ tmp = strchr(bootpath, '@');
+ if (tmp == NULL) {
+ bootpath = NULL;
+ } else {
+ bootpath = tmp + 1;
+ tmp = strchr(bootpath, '/');
+ if (tmp == NULL) {
+ bootpath = NULL;
+ } else {
+ bootpathlen = tmp - bootpath;
+ }
+ }
+ }
+
+ if (bootpath != NULL) {
+ if (bootpathlen >= BOOTDEVLEN)
+ bootpathlen = BOOTDEVLEN - 1;
+ strncpy(path, bootpath, bootpathlen);
+ path[bootpathlen] = '\0';
+ } else {
+ tmp = pmon_getenv("Version");
+ if (tmp != NULL && strncmp(tmp, "Gdium", 5) == 0)
+ strlcpy(path, "usbg0", BOOTDEVLEN);
+ else
+ strlcpy(path, "wd0", BOOTDEVLEN);
+ }
+ strlcat(path, "a", BOOTDEVLEN);
+}
+
+/*
+ * Ugly clock routines
+ */
+
+time_t
+getsecs()
+{
+ return 0;
+}
+
+/*
+ * Initialization
+ */
+
+void
+machdep()
+{
+ const char *envvar;
+
+ /*
+ * Figure out whether we are running on a Gdium system, which
+ * has an horribly castrated PMON.
+ */
+ envvar = pmon_getenv("Version");
+ if (envvar != NULL && strncmp(envvar, "Gdium", 5) == 0)
+ pmon_quirks |= PQ_GDIUM;
+
+ cninit();
+
+ /*
+ * Since we can't have non-blocking input, we will try to
+ * autoload the kernel pointed to by the `bsd' environment
+ * variable, and fallback to interactive mode if the variable
+ * is empty or the load fails.
+ */
+
+ envvar = pmon_getenv("bsd");
+ if (envvar != NULL) {
+ extern int bootprompt;
+ extern char *kernelfile;
+
+ bootprompt = 0;
+ kernelfile = (char *)envvar;
+ }
+}
+
+int
+main()
+{
+ boot(0);
+ return 0;
+}
diff --git a/sys/arch/loongson/stand/boot/start.S b/sys/arch/loongson/stand/boot/start.S
new file mode 100644
index 00000000000..b6023e2bea5
--- /dev/null
+++ b/sys/arch/loongson/stand/boot/start.S
@@ -0,0 +1,55 @@
+/* $OpenBSD: start.S,v 1.1 2010/02/14 22:39:33 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <machine/asm.h>
+#include <machine/regdef.h>
+
+ .set noreorder
+ .set mips3
+
+ .data
+pmon_ra:
+ .dword 0
+pmon_sp:
+ .dword 0
+
+ .text
+
+ .globl __start
+ .ent __start, 0
+__start:
+ LA t0, __start - FRAMESZ(CF_SZ)
+ LA gp, _gp
+ PTR_S ra, pmon_ra # save pmon return address
+ PTR_S sp, pmon_sp # and stack
+ move sp, t0
+ jal pmon_init # pmon_init(argc, argv, envp, callvec)
+ nop
+ jal main
+ nop
+ /* FALLTHROUGH */
+ .end __start
+
+ .globl _rtt
+ .ent _rtt,0
+_rtt:
+ PTR_L ra, pmon_ra
+ PTR_L sp, pmon_sp
+ jr ra
+ nop
+ .end _rtt
diff --git a/sys/arch/loongson/stand/libsa/Makefile b/sys/arch/loongson/stand/libsa/Makefile
new file mode 100644
index 00000000000..b35614048be
--- /dev/null
+++ b/sys/arch/loongson/stand/libsa/Makefile
@@ -0,0 +1,52 @@
+# $OpenBSD: Makefile,v 1.1 2010/02/14 22:39:33 miod Exp $
+
+.include "${.CURDIR}/../Makefile.inc"
+
+LIB= sa
+
+.PATH: ${.CURDIR}/../../../../lib/libsa
+
+CLEANFILES += machine mips64
+
+CFLAGS+= ${CEXTRAFLAGS} ${SAABI} -nostdinc -mno-abicalls -D_NO_ABICALLS \
+ -I${.CURDIR} -I${.CURDIR}/../include -I${.CURDIR}/../.. \
+ -I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. \
+ -I${.CURDIR}/../../../../lib/libsa \
+ -I${.OBJDIR}
+
+# stand routines
+SRCS= alloc.c cons.c ctime.c exit.c exec.c getfile.c gets.c globals.c \
+ memcmp.c memcpy.c memset.c printf.c \
+ snprintf.c strchr.c strcmp.c strerror.c strncmp.c strncpy.c strtol.c
+
+# io routines
+SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c \
+ lseek.c open.c read.c readdir.c stat.c write.c
+#SRCS+= nullfs.c
+
+#SRCS+= cread.c
+#CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD
+
+# boot filesystems
+SRCS+= ufs.c cd9660.c
+
+CFLAGS+=-DNO_NET
+
+SRCS+= loadfile.c
+
+${OBJS}: ${.CURDIR}/../Makefile.inc
+
+NOPROFILE=
+NOPIC=
+WANTLINT= no
+
+.if !make(obj)
+.BEGIN:
+ @([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
+ @([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64)
+CLEANFILES+= machine mips64
+.endif
+
+install:
+
+.include <bsd.lib.mk>