Index: head/stand/mips/beri/boot2/Makefile =================================================================== --- head/stand/mips/beri/boot2/Makefile (revision 326446) +++ head/stand/mips/beri/boot2/Makefile (revision 326447) @@ -1,83 +1,81 @@ #- # Copyright (c) 2013-2014 Robert N. M. Watson # All rights reserved. # # This software was developed by SRI International and the University of # Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) # ("CTSRD"), as part of the DARPA CRASH research programme. # # 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 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 AUTHOR 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. # # $FreeBSD$ .include INSTALLFLAGS= -b LOADERS= flashboot jtagboot FILES= ${LOADERS} ${LOADERS:S/$/.md5/} SRCS= relocate.S \ start.S \ boot2.c \ altera_jtag_uart.c \ cfi.c \ sdcard.c MAN= AFLAGS= -G0 -CFLAGS+= -I${.CURDIR} \ - -I${LDRSRC} \ - -D_KERNEL \ +CFLAGS+= -I${LDRSRC} \ -Wall \ -G0 \ -fno-pic -mno-abicalls \ -g LDFLAGS= -nostdlib \ -static \ -Wl,-N \ -G0 \ -L${.CURDIR} .PATH: ${BOOTSRC}/mips/beri/common CFLAGS+= -I${BOOTSRC}/mips/beri/common flashboot.elf: relocate.o start.o boot2.o altera_jtag_uart.o cfi.o sdcard.o ${CC} ${LDFLAGS} -T ${.CURDIR}/flashboot.ldscript -o ${.TARGET} \ ${.ALLSRC} ${LIBSA} flashboot: flashboot.elf ${OBJCOPY} -S -O binary ${.TARGET}.elf ${.TARGET} flashboot.md5: flashboot md5 flashboot > flashboot.md5 jtagboot: start.o boot2.o altera_jtag_uart.o cfi.o sdcard.o ${CC} ${LDFLAGS} -T ${.CURDIR}/jtagboot.ldscript -o ${.TARGET} \ ${.ALLSRC} ${LIBSA} jtagboot.md5: jtagboot md5 jtagboot > jtagboot.md5 CLEANFILES+= flashboot.elf .include Index: head/stand/mips/beri/boot2/boot2.c =================================================================== --- head/stand/mips/beri/boot2/boot2.c (revision 326446) +++ head/stand/mips/beri/boot2/boot2.c (revision 326447) @@ -1,661 +1,661 @@ /*- * Copyright (c) 2013-2014 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * 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 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 AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Copyright (c) 1998 Robert Nordier * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "paths.h" #include "rbx.h" static int beri_argc; static const char **beri_argv, **beri_envv; static uint64_t beri_memsize; #define IO_KEYBOARD 1 #define IO_SERIAL 2 #define SECOND 1 /* Circa that many ticks in a second. */ #define ARGS 0x900 #define NOPT 14 #define MEM_BASE 0x12 #define MEM_EXT 0x15 /* * XXXRW: I think this has to do with whether boot2 expects a partition * table? */ #define DRV_HARD 0x80 #define DRV_MASK 0x7f /* Default to using CFI flash. */ #define TYPE_DEFAULT BOOTINFO_DEV_TYPE_SDCARD /* Hard-coded assumption about location of JTAG-loaded kernel. */ #define DRAM_KERNEL_ADDR ((void *)mips_phys_to_cached(0x20000)) extern uint32_t _end; static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ static const unsigned char flags[NOPT] = { RBX_DUAL, RBX_SERIAL, RBX_ASKNAME, RBX_CDROM, RBX_CONFIG, RBX_KDB, RBX_GDB, RBX_MUTE, RBX_NOINTR, RBX_PAUSE, RBX_QUIET, RBX_DFLTROOT, RBX_SINGLE, RBX_VERBOSE }; /* These must match BOOTINFO_DEV_TYPE constants. */ static const char *const dev_nm[] = {"dram", "cfi", "sdcard"}; static const u_int dev_nm_count = nitems(dev_nm); static struct dmadat __dmadat; static struct dsk { unsigned type; /* BOOTINFO_DEV_TYPE_x object type. */ uintptr_t unitptr; /* Unit number or pointer to object. */ uint8_t slice; uint8_t part; #if 0 unsigned start; int init; #endif } dsk; static char cmd[512], cmddup[512], knamebuf[1024]; static const char *kname; uint32_t opts; #if 0 static int comspeed = SIOSPD; #endif struct bootinfo bootinfo; static uint8_t ioctrl = IO_KEYBOARD; void exit(int); void putchar(int); static void boot_fromdram(void); static void boot_fromfs(void); static void load(void); static int parse(void); static int dskread(void *, unsigned, unsigned); static int xputc(int); static int xgetc(int); #define UFS_SMALL_CGBASE #include "ufsread.c" static inline int xfsread(ufs_ino_t inode, void *buf, size_t nbyte) { if ((size_t)fsread(inode, buf, nbyte) != nbyte) { printf("Invalid %s\n", "format"); return -1; } return 0; } static inline void getstr(void) { char *s; int c; s = cmd; for (;;) { switch (c = xgetc(0)) { case 0: break; case '\177': case '\b': if (s > cmd) { s--; printf("\b \b"); } break; case '\n': case '\r': putchar('\n'); *s = 0; return; default: if (s - cmd < sizeof(cmd) - 1) *s++ = c; putchar(c); } } } int main(u_int argc, const char *argv[], const char *envv[], uint64_t memsize) { uint8_t autoboot; ufs_ino_t ino; size_t nbyte; /* Arguments from Miniboot. */ beri_argc = argc; beri_argv = argv; beri_envv = envv; beri_memsize = memsize; dmadat = &__dmadat; #if 0 /* XXXRW: more here. */ v86.ctl = V86_FLAGS; v86.efl = PSL_RESERVED_DEFAULT | PSL_I; dsk.drive = *(uint8_t *)PTOV(ARGS); #endif dsk.type = TYPE_DEFAULT; #if 0 dsk.unit = dsk.drive & DRV_MASK; dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; #endif bootinfo.bi_version = BOOTINFO_VERSION; bootinfo.bi_size = sizeof(bootinfo); /* Process configuration file */ autoboot = 1; if ((ino = lookup(PATH_CONFIG)) || (ino = lookup(PATH_DOTCONFIG))) { nbyte = fsread(ino, cmd, sizeof(cmd) - 1); cmd[nbyte] = '\0'; } if (*cmd) { memcpy(cmddup, cmd, sizeof(cmd)); if (parse()) autoboot = 0; if (!OPT_CHECK(RBX_QUIET)) printf("%s: %s", PATH_CONFIG, cmddup); /* Do not process this command twice */ *cmd = 0; } /* * Try to exec stage 3 boot loader. If interrupted by a keypress, * or in case of failure, try to load a kernel directly instead. */ if (!kname) { kname = PATH_LOADER; if (autoboot && !keyhit(3*SECOND)) { boot_fromfs(); kname = PATH_KERNEL; } } /* Present the user with the boot2 prompt. */ for (;;) { if (!autoboot || !OPT_CHECK(RBX_QUIET)) printf("\nFreeBSD/mips boot\n" "Default: %s%ju:%s\n" "boot: ", dev_nm[dsk.type], dsk.unitptr, kname); #if 0 if (ioctrl & IO_SERIAL) sio_flush(); #endif if (!autoboot || keyhit(3*SECOND)) getstr(); else if (!autoboot || !OPT_CHECK(RBX_QUIET)) putchar('\n'); autoboot = 0; if (parse()) putchar('\a'); else load(); } } /* XXX - Needed for btxld to link the boot2 binary; do not remove. */ void exit(int x) { } static void boot(void *entryp, int argc, const char *argv[], const char *envv[]) { bootinfo.bi_kernelname = (bi_ptr_t)kname; bootinfo.bi_boot2opts = opts & RBX_MASK; bootinfo.bi_boot_dev_type = dsk.type; bootinfo.bi_boot_dev_unitptr = dsk.unitptr; bootinfo.bi_memsize = beri_memsize; #if 0 /* * XXXRW: A possible future way to distinguish Miniboot passing a memory * size vs DTB..? */ if (beri_memsize <= BERI_MEMVSDTB) bootinfo.bi_memsize = beri_memsize; else bootinfo.bi_dtb = beri_memsize; #endif ((void(*)(int, const char **, const char **, void *))entryp)(argc, argv, envv, &bootinfo); } /* * Boot a kernel that has mysteriously (i.e., by JTAG) appeared in DRAM; * assume that it is already properly relocated, etc, and invoke its entry * address without question or concern. */ static void boot_fromdram(void) { void *kaddr = DRAM_KERNEL_ADDR; /* XXXRW: Something better here. */ Elf64_Ehdr *ehp = kaddr; if (!IS_ELF(*ehp)) { printf("Invalid %s\n", "format"); return; } boot((void *)ehp->e_entry, beri_argc, beri_argv, beri_envv); } static void boot_fromfs(void) { union { Elf64_Ehdr eh; } hdr; static Elf64_Phdr ep[2]; #if 0 static Elf64_Shdr es[2]; #endif caddr_t p; ufs_ino_t ino; uint64_t addr; int i, j; if (!(ino = lookup(kname))) { if (!ls) printf("No %s\n", kname); return; } if (xfsread(ino, &hdr, sizeof(hdr))) return; if (IS_ELF(hdr.eh)) { fs_off = hdr.eh.e_phoff; for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { if (xfsread(ino, ep + j, sizeof(ep[0]))) return; if (ep[j].p_type == PT_LOAD) j++; } for (i = 0; i < 2; i++) { p = (caddr_t)ep[i].p_paddr; fs_off = ep[i].p_offset; if (xfsread(ino, p, ep[i].p_filesz)) return; } p += roundup2(ep[1].p_memsz, PAGE_SIZE); #if 0 bootinfo.bi_symtab = VTOP(p); if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { fs_off = hdr.eh.e_shoff + sizeof(es[0]) * (hdr.eh.e_shstrndx + 1); if (xfsread(ino, &es, sizeof(es))) return; for (i = 0; i < 2; i++) { *(Elf32_Word *)p = es[i].sh_size; p += sizeof(es[i].sh_size); fs_off = es[i].sh_offset; if (xfsread(ino, p, es[i].sh_size)) return; p += es[i].sh_size; } } #endif addr = hdr.eh.e_entry; #if 0 bootinfo.bi_esymtab = VTOP(p); #endif } else { printf("Invalid %s\n", "format"); return; } boot((void *)addr, beri_argc, beri_argv, beri_envv); } static void load(void) { switch (dsk.type) { case BOOTINFO_DEV_TYPE_DRAM: boot_fromdram(); break; default: boot_fromfs(); break; } } static int parse() { char *arg = cmd; char *ep, *p, *q; char unit; size_t len; const char *cp; #if 0 int c, i, j; #else int c, i; #endif while ((c = *arg++)) { if (c == ' ' || c == '\t' || c == '\n') continue; for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); ep = p; if (*p) *p++ = 0; if (c == '-') { while ((c = *arg++)) { if (c == 'P') { cp = "yes"; #if 0 } else { opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL); cp = "no"; } #endif printf("Keyboard: %s\n", cp); continue; #if 0 } else if (c == 'S') { j = 0; while ((unsigned int)(i = *arg++ - '0') <= 9) j = j * 10 + i; if (j > 0 && i == -'0') { comspeed = j; break; } /* Fall through to error below ('S' not in optstr[]). */ #endif } for (i = 0; c != optstr[i]; i++) if (i == NOPT - 1) return -1; opts ^= OPT_SET(flags[i]); } ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; #if 0 if (ioctrl & IO_SERIAL) { if (sio_init(115200 / comspeed) != 0) ioctrl &= ~IO_SERIAL; } #endif } else { /*- * Parse a device/kernel name. Format(s): * * path * deviceX:path * * NB: Utterly incomprehensible but space-efficient ARM/i386 * parsing removed in favour of larger but easier-to-read C. This * is still not great, however -- e.g., relating to unit handling. * * TODO: it would be nice if a DRAM pointer could be specified * here. * * XXXRW: Pick up pieces here. */ /* * Search for a parens; if none, then it's just a path. * Otherwise, it's a devicename. */ arg--; q = strsep(&arg, ":"); if (arg != NULL) { len = strlen(q); if (len < 2) { printf("Invalid device: name too short\n"); return (-1); } /* * First, handle one-digit unit. */ unit = q[len-1]; if (unit < '0' || unit > '9') { - printf("Invalid device: invalid unit\n", q, + printf("Invalid device: invalid unit %c\n", unit); return (-1); } unit -= '0'; q[len-1] = '\0'; /* * Next, find matching device. */ for (i = 0; i < dev_nm_count; i++) { if (strcmp(q, dev_nm[i]) == 0) break; } if (i == dev_nm_count) { printf("Invalid device: no driver match\n"); return (-1); } dsk.type = i; dsk.unitptr = unit; /* Someday: also a DRAM pointer? */ } else arg = q; if ((i = ep - arg)) { if ((size_t)i >= sizeof(knamebuf)) return -1; memcpy(knamebuf, arg, i + 1); kname = knamebuf; } } arg = p; } return 0; } static int drvread(void *buf, unsigned lba, unsigned nblk) { /* XXXRW: eventually, we may want to pass 'drive' and 'unit' here. */ switch (dsk.type) { case BOOTINFO_DEV_TYPE_CFI: return (cfi_read(buf, lba, nblk)); case BOOTINFO_DEV_TYPE_SDCARD: return (altera_sdcard_read(buf, lba, nblk)); default: return (-1); } } static int dskread(void *buf, unsigned lba, unsigned nblk) { #if 0 /* * XXXRW: For now, assume no partition table around the file system; it's * just in raw flash. */ struct dos_partition *dp; struct disklabel *d; char *sec; unsigned i; uint8_t sl; if (!dsk_meta) { sec = dmadat->secbuf; dsk.start = 0; if (drvread(sec, DOSBBSECTOR, 1)) return -1; dp = (void *)(sec + DOSPARTOFF); sl = dsk.slice; if (sl < BASE_SLICE) { for (i = 0; i < NDOSPART; i++) if (dp[i].dp_typ == DOSPTYP_386BSD && (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { sl = BASE_SLICE + i; if (dp[i].dp_flag & 0x80 || dsk.slice == COMPATIBILITY_SLICE) break; } if (dsk.slice == WHOLE_DISK_SLICE) dsk.slice = sl; } if (sl != WHOLE_DISK_SLICE) { if (sl != COMPATIBILITY_SLICE) dp += sl - BASE_SLICE; if (dp->dp_typ != DOSPTYP_386BSD) { printf("Invalid %s\n", "slice"); return -1; } dsk.start = le32toh(dp->dp_start); } if (drvread(sec, dsk.start + LABELSECTOR, 1)) return -1; d = (void *)(sec + LABELOFFSET); if (le32toh(d->d_magic) != DISKMAGIC || le32toh(d->d_magic2) != DISKMAGIC) { if (dsk.part != RAW_PART) { printf("Invalid %s\n", "label"); return -1; } } else { if (!dsk.init) { if (le16toh(d->d_type) == DTYPE_SCSI) dsk.type = TYPE_DA; dsk.init++; } if (dsk.part >= le16toh(d->d_npartitions) || !(le32toh(d->d_partitions[dsk.part].p_size))) { printf("Invalid %s\n", "partition"); return -1; } dsk.start += le32toh(d->d_partitions[dsk.part].p_offset); dsk.start -= le32toh(d->d_partitions[RAW_PART].p_offset); } } return drvread(buf, dsk.start + lba, nblk); #else return drvread(buf, lba, nblk); #endif } void putchar(int c) { if (c == '\n') xputc('\r'); xputc(c); } static int xputc(int c) { if (ioctrl & IO_KEYBOARD) putc(c); #if 0 if (ioctrl & IO_SERIAL) sio_putc(c); #endif return c; } static int xgetc(int fn) { if (OPT_CHECK(RBX_NOINTR)) return 0; for (;;) { if (ioctrl & IO_KEYBOARD && keyhit(0)) return fn ? 1 : getc(); #if 0 if (ioctrl & IO_SERIAL && sio_ischar()) return fn ? 1 : sio_getc(); #endif if (fn) return 0; } } Index: head/stand/mips/beri/common/altera_jtag_uart.c =================================================================== --- head/stand/mips/beri/common/altera_jtag_uart.c (revision 326446) +++ head/stand/mips/beri/common/altera_jtag_uart.c (revision 326447) @@ -1,182 +1,175 @@ /*- * Copyright (c) 2011, 2013 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * 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 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 AUTHOR 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. * * $FreeBSD$ */ #include "util.h" #include "mips.h" /*- * Routines for interacting with the CHERI console UART. Programming details * from the June 2011 "Embedded Peripherals User Guide" by Altera * Corporation, tables 6-2 (JTAG UART Core Register Map), 6-3 (Data Register * Bits), and 6-4 (Control Register Bits). * * Hard-coded physical address for the first JTAG UART -- true on all BERI and * CHERI boards. */ #define CHERI_UART_BASE 0x7f000000 /* JTAG UART */ /* * * Offsets of data and control registers relative to the base. Altera * conventions are maintained in CHERI. */ #define ALTERA_JTAG_UART_DATA_OFF 0x00000000 #define ALTERA_JTAG_UART_CONTROL_OFF 0x00000004 /* * Offset 0: 'data' register -- bits 31-16 (RAVAIL), 15 (RVALID), * 14-8 (Reserved), 7-0 (DATA). * * DATA - One byte read or written. * RAVAIL - Bytes available to read (excluding the current byte). * RVALID - Whether the byte in DATA is valid. */ #define ALTERA_JTAG_UART_DATA_DATA 0x000000ff #define ALTERA_JTAG_UART_DATA_RESERVED 0x00007f00 #define ALTERA_JTAG_UART_DATA_RVALID 0x00008000 #define ALTERA_JTAG_UART_DATA_RAVAIL 0xffff0000 #define ALTERA_JTAG_UART_DATA_RAVAIL_SHIFT 16 /*- * Offset 1: 'control' register -- bits 31-16 (WSPACE), 15-11 (Reserved), * 10 (AC), 9 (WI), 8 (RI), 7..2 (Reserved), 1 (WE), 0 (RE). * * RE - Enable read interrupts. * WE - Enable write interrupts. * RI - Read interrupt pending. * WI - Write interrupt pending. * AC - Activity bit; set to '1' to clear to '0'. * WSPACE - Space available in the write FIFO. */ #define ALTERA_JTAG_UART_CONTROL_RE 0x00000001 #define ALTERA_JTAG_UART_CONTROL_WE 0x00000002 #define ALTERA_JTAG_UART_CONTROL_RESERVED0 0x000000fc #define ALTERA_JTAG_UART_CONTROL_RI 0x00000100 #define ALTERA_JTAG_UART_CONTROL_WI 0x00000200 #define ALTERA_JTAG_UART_CONTROL_AC 0x00000400 #define ALTERA_JTAG_UART_CONTROL_RESERVED1 0x0000f800 #define ALTERA_JTAG_UART_CONTROL_WSPACE 0xffff0000 #define ALTERA_JTAG_UART_CONTROL_WSPACE_SHIFT 16 /* * One-byte buffer as we can't check whether the UART is readable without * actually reading from it. */ static char buffer_data; static int buffer_valid; /* * Low-level read and write register routines; the Altera UART is little * endian, so we byte swap 32-bit reads and writes. */ static inline uint32_t uart_data_read(void) { return (mips_ioread_uint32le(mips_phys_to_uncached(CHERI_UART_BASE + ALTERA_JTAG_UART_DATA_OFF))); } static inline void uart_data_write(uint32_t v) { mips_iowrite_uint32le(mips_phys_to_uncached(CHERI_UART_BASE + ALTERA_JTAG_UART_DATA_OFF), v); } static inline uint32_t uart_control_read(void) { return (mips_ioread_uint32le(mips_phys_to_uncached(CHERI_UART_BASE + ALTERA_JTAG_UART_CONTROL_OFF))); } static inline void uart_control_write(uint32_t v) { mips_iowrite_uint32le(mips_phys_to_uncached(CHERI_UART_BASE + ALTERA_JTAG_UART_DATA_OFF), v); } static int -uart_writable(void) -{ - - return ((uart_control_read() & ALTERA_JTAG_UART_CONTROL_WSPACE) != 0); -} - -static int uart_readable(void) { uint32_t v; if (buffer_valid) return (1); v = uart_data_read(); if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) { buffer_valid = 1; buffer_data = (v & ALTERA_JTAG_UART_DATA_DATA); } return (0); } int keyhit(int seconds) { register_t stoptime; stoptime = cp0_count_get() + seconds * 100000000; /* 100 MHz. */ do { if (uart_readable()) return (1); } while (cp0_count_get() < stoptime); return (0); } int getc(void) { while (!(uart_readable())); buffer_valid = 0; return (buffer_data); } void putc(int ch) { uart_data_write(ch); } Index: head/stand/mips/beri/loader/Makefile =================================================================== --- head/stand/mips/beri/loader/Makefile (revision 326446) +++ head/stand/mips/beri/loader/Makefile (revision 326447) @@ -1,110 +1,110 @@ #- # Copyright (c) 2013-2014 Robert N. M. Watson # All rights reserved. # # This software was developed by SRI International and the University of # Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) # ("CTSRD"), as part of the DARPA CRASH research programme. # # 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 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 AUTHOR 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. # # $FreeBSD$ LOADER_MSDOS_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_CD9660_SUPPORT?= no LOADER_EXT2FS_SUPPORT?= no LOADER_GZIP_SUPPORT?= yes LOADER_BZIP2_SUPPORT?= yes .include MK_SSP= no MAN= PROG?= loader NEWVERSWHAT= "BERI loader" ${MACHINE_CPUARCH} INSTALLFLAGS= -b # Architecture-specific loader code SRCS= start.S \ main.c \ devicename.c \ exec.c \ metadata.c \ vers.c \ arch.c # libstand front-ends for shared driver code SRCS+= beri_console.c \ beri_disk_cfi.c \ beri_disk_sdcard.c # Common code with boot2 SRCS+= altera_jtag_uart.c \ cfi.c \ sdcard.c # Since we don't have a backward compatibility issue, default to this on BERI. CFLAGS+= -DBOOT_PROMPT_123 -HELP_FILES+= help.mips +HELP_FILES+= ${.CURDIR}/help.mips # Always add MI sources .include "${BOOTSRC}/loader.mk" # BERI files common to boot2 and loader .PATH: ${BOOTSRC}/mips/beri/common CFLAGS+= -I${BOOTSRC}/mips/beri/common # Loader-specific MD headers CFLAGS+= -I${.CURDIR} # Generate code appropriate for the loader environment CFLAGS+= -G0 \ -fno-pic \ -mno-abicalls \ -g LDFLAGS= -nostdlib \ -static \ -T ${.CURDIR}/loader.ldscript \ -L${.CURDIR} \ -e __start DPADD= ${LIBFICL} ${LIBSA} LDADD= ${LIBFICL} ${LIBSA} .if defined(LOADER_USB_SUPPORT) # Do garbage collection CFLAGS+= -ffunction-sections -fdata-sections CFLAGS+= -Wl,--gc-sections # Link USB BOOT library LDADD+= ${BOOTOBJ}/usb/libusbboot.a CFLAGS+= -I${BOOTSRC}/usb # Define USB SUPPORT CFLAGS+= -DLOADER_USB_SUPPORT .endif all: loader .include Index: head/stand/mips/beri/loader/devicename.c =================================================================== --- head/stand/mips/beri/loader/devicename.c (revision 326446) +++ head/stand/mips/beri/loader/devicename.c (revision 326447) @@ -1,205 +1,207 @@ /*- * Copyright (c) 1998 Michael Smith * 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 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 AUTHOR 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 __FBSDID("$FreeBSD$"); #include #include #include "bootstrap.h" #include "disk.h" static int beri_arch_parsedev(struct disk_devdesc **dev, const char *devspec, const char **path); /* * Point (dev) at an allocated device specifier for the device matching the * path in (devspec). If it contains an explicit device specification, * use that. If not, use the default device. */ int beri_arch_getdev(void **vdev, const char *devspec, const char **path) { struct disk_devdesc **dev = (struct disk_devdesc **)vdev; int rv; /* * If it looks like this is just a path and no * device, go with the current device. */ if ((devspec == NULL) || (devspec[0] == '/') || (strchr(devspec, ':') == NULL)) { if (((rv = beri_arch_parsedev(dev, getenv("currdev"), NULL)) == 0) && (path != NULL)) *path = devspec; return(rv); } /* * Try to parse the device name off the beginning of the devspec */ return(beri_arch_parsedev(dev, devspec, path)); } /* * Point (dev) at an allocated device specifier matching the string version * at the beginning of (devspec). Return a pointer to the remaining * text in (path). * * In all cases, the beginning of (devspec) is compared to the names * of known devices in the device switch, and then any following text * is parsed according to the rules applied to the device type. * * For disk-type devices, the syntax is: * * disk[s][]: * */ static int beri_arch_parsedev(struct disk_devdesc **dev, const char *devspec, const char **path) { struct disk_devdesc *idev; struct devsw *dv; int i, unit, err; - const char *cp; + char *cp; const char *np; /* minimum length check */ if (strlen(devspec) < 2) return(EINVAL); /* look for a device that matches */ for (i = 0, dv = NULL; devsw[i] != NULL; i++) { if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { dv = devsw[i]; break; } } if (dv == NULL) return(ENOENT); idev = malloc(sizeof(struct disk_devdesc)); err = 0; np = (devspec + strlen(dv->dv_name)); switch(dv->dv_type) { case DEVT_NONE: /* XXX what to do here? Do we care? */ break; case DEVT_DISK: err = disk_parsedev(idev, np, path); if (err != 0) goto fail; break; case DEVT_CD: case DEVT_NET: case DEVT_ZFS: unit = 0; if (*np && (*np != ':')) { unit = strtol(np, &cp, 0); /* get unit number if present */ if (cp == np) { err = EUNIT; goto fail; } } else { - cp = np; + err = EUNIT; + goto fail; } + if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->d_unit = unit; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; default: err = EINVAL; goto fail; } idev->d_dev = dv; idev->d_type = dv->dv_type; if (dev == NULL) { free(idev); } else { *dev = idev; } return(0); fail: free(idev); return(err); } char * beri_arch_fmtdev(void *vdev) { struct disk_devdesc *dev = (struct disk_devdesc *)vdev; static char buf[128]; /* XXX device length constant? */ switch(dev->d_type) { case DEVT_NONE: strcpy(buf, "(no device)"); break; case DEVT_CD: sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); break; case DEVT_DISK: return (disk_fmtdev(vdev)); case DEVT_NET: case DEVT_ZFS: sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); break; } return(buf); } /* * Set currdev to suit the value being supplied in (value) */ int beri_arch_setcurrdev(struct env_var *ev, int flags, const void *value) { struct disk_devdesc *ncurr; int rv; if ((rv = beri_arch_parsedev(&ncurr, value, NULL)) != 0) return(rv); free(ncurr); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return(0); } Index: head/stand/mips/beri/loader/exec.c =================================================================== --- head/stand/mips/beri/loader/exec.c (revision 326446) +++ head/stand/mips/beri/loader/exec.c (revision 326447) @@ -1,125 +1,125 @@ /*- * Copyright (c) 2013-2014 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * 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 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 AUTHOR 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include static int beri_elf64_loadfile(char *, uint64_t, struct preloaded_file **); static int beri_elf64_exec(struct preloaded_file *fp); struct file_format beri_elf = { .l_load = beri_elf64_loadfile, .l_exec = beri_elf64_exec, }; /* * bootinfo that we will pass onto the kernel; some fields derived from * *boot2_bootinfop, others filled in by loader. */ struct bootinfo bootinfo; static int beri_elf64_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) { /* * Some platforms require invalidation of instruction caches here; we * don't need that currently. */ return (__elfN(loadfile)(filename, dest, result)); } static int beri_elf64_exec(struct preloaded_file *fp) { void (*entry)(register_t, register_t, register_t, register_t); struct file_metadata *md; vm_offset_t mdp; Elf_Ehdr *ehdr; int error; md = file_findmetadata(fp, MODINFOMD_ELFHDR); if (md == NULL) { printf("%s: file_findmetadata failed\n"); return (EFTYPE); } ehdr = (Elf_Ehdr *)md->md_data; error = md_load64(fp->f_args, &mdp); if (error) { printf("%s: md_load64 failed\n"); return (error); } entry = (void *)ehdr->e_entry; printf("Kernel entry at %p\n", entry); dev_cleanup(); /* XXXRW: Required? */ printf("Kernel args: %s\n", fp->f_args); /* * Configure bootinfo for the loaded kernel. Some values are * inherited from the bootinfo passed to us by boot2 (e.g., DTB * pointer); others are local to the loader (e.g., kernel boot flags). */ bzero(&bootinfo, sizeof(bootinfo)); bootinfo.bi_version = BOOTINFO_VERSION; bootinfo.bi_size = sizeof(bootinfo); bootinfo.bi_boot2opts = boot2_bootinfo.bi_boot2opts; /* NB: bi_kernelname used only by boot2. */ /* NB: bi_nfs_diskless not yet. */ bootinfo.bi_dtb = boot2_bootinfo.bi_dtb; bootinfo.bi_memsize = boot2_bootinfo.bi_memsize; bootinfo.bi_modulep = mdp; /* * XXXRW: For now, pass 'memsize' rather than dtb or bootinfo. This * is the 'old' ABI spoken by Miniboot and the kernel. To pass in * boot2opts, modules, etc, we will need to fix this to pass in at * least bootinfop. */ (*entry)(boot2_argc, (register_t)boot2_argv, (register_t)boot2_envv, - &bootinfo); + (register_t)&bootinfo); panic("exec returned"); } Index: head/stand/mips/beri/loader/loader.h =================================================================== --- head/stand/mips/beri/loader/loader.h (revision 326446) +++ head/stand/mips/beri/loader/loader.h (revision 326447) @@ -1,63 +1,64 @@ /*- * Copyright (c) 2013-2014 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * 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 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 AUTHOR 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. * * $FreeBSD$ */ #ifndef _BOOT_LOADER_H_ #define _BOOT_LOADER_H_ /* beri_console.c */ extern struct console altera_jtag_uart_console; /* beri_disk.c */ extern struct devsw beri_cfi_disk; extern struct devsw beri_sdcard_disk; /* devicename.c */ +struct env_var; int beri_arch_setcurrdev(struct env_var *, int, const void *); char *beri_arch_fmtdev(void *); int beri_arch_getdev(void **, const char *, const char **); /* exec.c */ extern struct file_format beri_elf; /* main.c */ extern int boot2_argc; extern char **boot2_argv; extern char **boot2_envv; extern struct bootinfo boot2_bootinfo; /* metadata.c */ int md_load64(char *args, vm_offset_t *modulep); /* vers.c */ extern char bootprog_info[]; #endif /* !_BOOT_LOADER_H_ */