summaryrefslogtreecommitdiffstats
path: root/sys/boot/alpha/boot1/boot1.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/alpha/boot1/boot1.c')
-rw-r--r--sys/boot/alpha/boot1/boot1.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/sys/boot/alpha/boot1/boot1.c b/sys/boot/alpha/boot1/boot1.c
new file mode 100644
index 0000000..9454011
--- /dev/null
+++ b/sys/boot/alpha/boot1/boot1.c
@@ -0,0 +1,278 @@
+/*
+ * $FreeBSD$
+ * From $NetBSD: bootxx.c,v 1.4 1997/09/06 14:08:29 drochner Exp $
+ */
+
+/*
+ * Copyright (c) 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <string.h>
+#include <sys/param.h>
+#include <sys/dirent.h>
+
+#include <machine/prom.h>
+#include <machine/rpb.h>
+
+#define DEBUGxx
+
+void puts(const char *s);
+void puthex(u_long v);
+static int dskread(void *, u_int64_t, size_t);
+
+#define printf(...) \
+while (0)
+
+#define memcpy(dst, src, len) \
+bcopy(src, dst, len)
+
+#include "ufsread.c"
+
+extern end[];
+int errno;
+
+char *heap = (char*) end;
+
+void
+bcopy(const void *src, void *dst, size_t len)
+{
+ const char *s;
+ char *d;
+
+ for (d = dst, s = src; len; len--)
+ *d++ = *s++;
+}
+
+void
+putchar(int c)
+{
+ if (c == '\n')
+ prom_putchar('\r');
+ prom_putchar(c);
+}
+
+int
+getchar()
+{
+ return prom_getchar();
+}
+
+int
+ischar()
+{
+ return prom_poll();
+}
+
+void
+puts(const char *s)
+{
+ while (*s)
+ putchar(*s++);
+}
+
+void
+panic(const char *message, ...)
+{
+ puts(message);
+ puts("\r\n");
+ halt();
+}
+
+int prom_fd = 0;
+
+int
+devopen()
+{
+ prom_return_t ret;
+ char devname[64];
+
+ if (prom_fd)
+ return;
+
+ ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof devname);
+
+ ret.bits = prom_open(devname, ret.u.retval + 1);
+ if (ret.u.status)
+ panic("devopen: open failed\n");
+
+ prom_fd = ret.u.retval;
+
+ /* XXX read disklabel and setup partition offset */
+
+ return 0;
+}
+
+#ifdef DEBUG
+
+void
+puthex(u_long v)
+{
+ int digit;
+ char hex[] = "0123456789abcdef";
+
+ puts("0x");
+ if (!v) {
+ puts("0");
+ return;
+ }
+
+ for (digit = 0; v >= (0x10L << digit); digit += 4)
+ ;
+
+ for (; digit >= 0; digit -= 4)
+ putchar(hex[(v >> digit) & 0xf]);
+}
+
+#endif
+
+int
+dskread(void *buf, u_int64_t block, size_t size)
+{
+#ifdef DEBUG
+ puts("dskread(");
+ puthex((u_long)buf);
+ puts(",");
+ puthex(block);
+ puts(",");
+ puthex(size);
+ puts(")\n");
+#endif
+
+ prom_read(prom_fd, size * DEV_BSIZE, buf, block);
+ return (0);
+}
+
+static inline void
+devclose()
+{
+ if (prom_fd) {
+ prom_close(prom_fd);
+ prom_fd = 0;
+ }
+}
+
+static inline void
+getfilename(char *filename, const char *defname)
+{
+ int c;
+ char *p = filename;
+
+ puts("Boot: ");
+
+ while ((c = getchar()) != '\r') {
+ if (c == '\b' || c == 0177) {
+ if (p > filename) {
+ puts("\b \b");
+ p--;
+ }
+ } else {
+ putchar(c);
+ *p++ = c;
+ }
+ }
+ putchar('\n');
+ *p = '\0';
+ if (!*filename)
+ strcpy(filename, defname);
+ return;
+}
+
+static struct dmadat __dmadat;
+
+static inline void
+loadfile(char *name, char *addr)
+{
+ int n;
+ char *p;
+ ino_t ino;
+
+ puts("Loading ");
+ puts(name);
+ puts("\n");
+
+ dmadat = &__dmadat;
+
+ if (devopen() || (ino = lookup(name)) == 0) {
+ puts("Can't open file ");
+ puts(name);
+ puts("\n");
+ halt();
+ }
+
+ p = addr;
+ do {
+ n = fsread(ino, p, VBLKSIZE);
+ if (n < 0) {
+ puts("Can't read file ");
+ puts(name);
+ puts("\n");
+ halt();
+ }
+ p += n;
+ twiddle();
+ } while (n == VBLKSIZE);
+
+ devclose();
+}
+
+static inline u_long rpcc()
+{
+ u_long v;
+ __asm__ __volatile__ ("rpcc %0" : "=r"(v));
+ return v & 0xffffffff;
+}
+
+int
+main()
+{
+ char *loadaddr = (char*) SECONDARY_LOAD_ADDRESS;
+ char *name = "/boot/loader";
+ char *p;
+ char filename[512];
+ void (*entry)(void);
+ u_long start, freq;
+ int i;
+
+ init_prom_calls();
+
+ start = rpcc();
+ freq = ((struct rpb *)HWRPB_ADDR)->rpb_cc_freq;
+ while (((rpcc() - start) & 0xffffffff) < freq) {
+ twiddle();
+ if (ischar()) {
+ getfilename(filename, name);
+ name = filename;
+ break;
+ }
+ }
+
+ loadfile(name, loadaddr);
+
+ entry = (void (*)())loadaddr;
+ (*entry)();
+
+ return 0;
+}
OpenPOWER on IntegriCloud