Add NetBSD/newsmips native boot loader.

This commit is contained in:
tsubai 1999-07-08 11:48:03 +00:00
parent e1ef4ddcb5
commit 95faaaec9d
12 changed files with 1173 additions and 0 deletions

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 1999/07/08 11:48:03 tsubai Exp $
SUBDIR= boot bootxx installboot
.include <bsd.subdir.mk>

View File

@ -0,0 +1,3 @@
# $NetBSD: Makefile.inc,v 1.1 1999/07/08 11:48:04 tsubai Exp $
BINDIR= /usr/mdec

View File

@ -0,0 +1,60 @@
# $NetBSD: Makefile,v 1.1 1999/07/08 11:48:05 tsubai Exp $
.PATH: ../bootxx
S= ${.CURDIR}/../../../..
PROG= boot
SRCS= locore.S romcalls.S boot.c devopen.c
MKMAN= no
STRIPFLAG=
BINMODE= 444
OBJCOPY?= objcopy
SIZE?= size
STRIP?= strip
CLEANFILES+= ${PROG}.elf ${PROG}.tmp
CLEANFILES+= ${.OBJDIR}/machine ${.OBJDIR}/mips
LDFLAGS= -x -N -Ttext a0700000
CFLAGS= -Os -G 0 -mno-abicalls -Wall
CPPFLAGS+= -D_STANDALONE #-DBOOT_DEBUG
CPPFLAGS+= -I. -I../../../..
AFLAGS= -D_LOCORE
### find out what to use for libkern
#KERNDST= ${.OBJDIR}/../lib/kern
KERN_AS= library
.include "${S}/lib/libkern/Makefile.inc"
LIBKERN= ${KERNLIB}
### find out what to use for libz
#ZDST= ${.OBJDIR}/../lib/z
Z_AS= library
.include "${S}/lib/libz/Makefile.inc"
LIBZ= ${ZLIB}
### find out what to use for libsa
#SADST= ${.OBJDIR}/../lib/sa
SA_AS= library
SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes
.include "${S}/lib/libsa/Makefile.inc"
LIBSA= ${SALIB}
.BEGIN:
@[ -h machine ] || ln -s ${S}/arch/${MACHINE}/include machine
@[ -h mips ] || ln -s ${S}/arch/mips/include mips
${PROG}: ${OBJS} ${LIBSA} ${LIBZ} ${LIBKERN}
${LD} ${LDFLAGS} -o ${PROG} ${OBJS} ${LIBSA} ${LIBZ} ${LIBKERN}
-${SIZE} ${PROG}
cp ${PROG} ${PROG}.elf
${STRIP} ${PROG}
tail -c +177 ${PROG} > ${PROG}.tmp
mv ${PROG}.tmp ${PROG}
# ${OBJCOPY} -O binary ${PROG}.elf ${PROG} # XXX
.include <bsd.prog.mk>

View File

@ -0,0 +1,123 @@
/* $NetBSD: boot.c,v 1.1 1999/07/08 11:48:05 tsubai Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>
#include <lib/libsa/loadfile.h>
#include <machine/romcall.h>
void flushicache __P((void *, int));
extern char _edata[], _end[];
char *devs[] = { "sd", "fh", "fd", NULL, NULL, "rd", "st" };
char *kernels[] = { "/netbsd", "/netbsd.gz", NULL };
#ifdef BOOT_DEBUG
# define DPRINTF printf
#else
# define DPRINTF while (0) printf
#endif
void
boot(a0, a1, a2, a3, a4, a5)
int a0, a1, a2, a3, a4, a5;
{
int fd, i;
int ctlr, unit, part, type;
int bootdev = a1;
char *netbsd = (char *)a2;
u_long marks[MARK_MAX];
char devname[32], file[32];
void (*entry)();
/* Clear BSS. */
bzero(_edata, _end - _edata);
printf("\n");
printf("NetBSD/newsmips Secondary Boot\n");
/* bootname is "/boot" by default. */
if (netbsd == NULL || strcmp(netbsd, "/boot") == 0)
netbsd = "";
DPRINTF("howto = 0x%x\n", a0);
DPRINTF("bootdev = 0x%x\n", bootdev);
DPRINTF("bootname = %s\n", netbsd);
DPRINTF("maxmem = 0x%x\n", a3);
ctlr = BOOTDEV_CTLR(bootdev);
unit = BOOTDEV_UNIT(bootdev);
part = BOOTDEV_PART(bootdev);
type = BOOTDEV_TYPE(bootdev);
marks[MARK_START] = 0;
if (devs[type] == NULL) {
printf("unknown bootdev (0x%x)\n", bootdev);
return;
}
sprintf(devname, "%s(%d,%d,%d)", devs[type], ctlr, unit, part);
printf("Booting %s%s\n", devname, netbsd);
/* use user specified kernel name if exists */
if (*netbsd) {
kernels[0] = netbsd;
kernels[1] = NULL;
}
for (i = 0; kernels[i]; i++) {
sprintf(file, "%s%s", devname, kernels[i]);
DPRINTF("trying %s...\n", file);
fd = loadfile(file, marks, LOAD_ALL);
if (fd != -1)
break;
}
if (fd == -1)
return;
DPRINTF("entry = 0x%x\n", (int)marks[MARK_ENTRY]);
DPRINTF("ssym = 0x%x\n", (int)marks[MARK_SYM]);
DPRINTF("esym = 0x%x\n", (int)marks[MARK_END]);
entry = (void *)marks[MARK_ENTRY];
flushicache(entry, marks[MARK_SYM] - marks[MARK_ENTRY]);
printf("\n");
(*entry)(a0, a1, a2, a3, a4, a5);
}
void
putchar(x)
int x;
{
char c = x;
rom_write(1, &c, 1);
}

View File

@ -0,0 +1,124 @@
/* $NetBSD: devopen.c,v 1.1 1999/07/08 11:48:05 tsubai Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>
#include <lib/libsa/ufs.h>
#include <machine/romcall.h>
#ifdef BOOT_DEBUG
# define DPRINTF printf
#else
# define DPRINTF while (0) printf
#endif
int dkopen __P((struct open_file *, ...));
int dkclose __P((struct open_file *));
int dkstrategy __P((void *, int, daddr_t, size_t, void *, size_t *));
struct devsw devsw[] = {
{ "dk", dkstrategy, dkopen, dkclose, noioctl }
};
int ndevs = sizeof(devsw) / sizeof(devsw[0]);
struct fs_ops file_system[] = {
{ ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat }
};
int nfsys = sizeof(file_system) / sizeof(file_system[0]);
struct romdev {
int fd;
} romdev;
int
devopen(f, fname, file)
struct open_file *f;
const char *fname;
char **file; /* out */
{
int fd;
char devname[32];
char *cp;
DPRINTF("devopen: %s\n", fname);
strcpy(devname, fname);
cp = strchr(devname, ')') + 1;
*cp = 0;
fd = rom_open(devname, 0);
DPRINTF("devname = %s, fd = %d\n", devname, fd);
if (fd == -1)
return -1;
romdev.fd = fd;
f->f_dev = devsw;
f->f_devdata = &romdev;
*file = strchr(fname, ')') + 1;
return 0;
}
int
dkopen(struct open_file *f, ...)
{
DPRINTF("dkopen\n");
return 0;
}
int
dkclose(f)
struct open_file *f;
{
struct romdev *dev = f->f_devdata;
DPRINTF("dkclose\n");
rom_close(dev->fd);
return 0;
}
int
dkstrategy(devdata, rw, blk, size, buf, rsize)
void *devdata;
int rw;
daddr_t blk;
size_t size;
void *buf;
size_t *rsize; /* out: number of bytes transfered */
{
struct romdev *dev = devdata;
/* XXX should use partition offset */
rom_lseek(dev->fd, blk * 512, 0);
rom_read(dev->fd, buf, size);
*rsize = size;
return 0;
}

View File

@ -0,0 +1,64 @@
/* $NetBSD: locore.S,v 1.1 1999/07/08 11:48:05 tsubai Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 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 <mips/asm.h>
#include <mips/cpuregs.h>
.set noreorder
.text
.align 2
.globl _start
_start:
j boot
nop
/* void flushicache(addr, len); */
.globl flushicache
flushicache:
mfc0 v0, MIPS_COP_0_STATUS # save SR
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
la v1, 1f
or v1, MIPS_KSEG1_START # run uncached
j v1
nop
1:
li v1, MIPS_SR_ISOL_CACHES | MIPS_SR_SWAP_CACHES
mtc0 v1, MIPS_COP_0_STATUS
nop
addu a1, a1, a0 # compute ending address
2:
sb zero, -4(a0)
bne a0, a1, 2b
addu a0, a0, 4
mtc0 v0, MIPS_COP_0_STATUS # enable interrupts
j ra # return and run cached
nop

View File

@ -0,0 +1,24 @@
# $NetBSD: Makefile,v 1.1 1999/07/08 11:48:06 tsubai Exp $
PROG= bootxx
SRCS= start.S romcalls.S bootxx.c
MKMAN= no
STRIPFLAG=
BINMODE= 444
SIZE?= size
LDFLAGS= -x -N -Ttext a0000000
CFLAGS= -Os -mno-abicalls -G 0 -Wall
CPPFLAGS+= -D_STANDALONE #-DBOOTXX_DEBUG
CPPFLAGS+= -I../../../..
AFLAGS= -D_LOCORE
L= ../boot/lib
LIBS= ${L}/sa/libsa.a ${L}/kern/libkern.a
${PROG}: ${OBJS}
${LD} ${LDFLAGS} -o ${PROG} ${OBJS} ${LIBS}
${SIZE} ${PROG}
.include <bsd.prog.mk>

View File

@ -0,0 +1,118 @@
/* $NetBSD: bootxx.c,v 1.1 1999/07/08 11:48:06 tsubai Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>
#include <machine/romcall.h>
#define MAXBLOCKNUM 64
void (*entry_point)() = (void *)0;
int block_size = 8192;
int block_count = MAXBLOCKNUM;
int block_table[MAXBLOCKNUM] = { 0 };
#ifdef BOOTXX_DEBUG
# define DPRINTF printf
#else
# define DPRINTF while (0) printf
#endif
char *devs[] = { "sd", "fh", "fd", NULL, NULL, "rd", "st" };
void
bootxx(a0, a1, a2, a3, a4, a5)
int a0, a1, a2, a3, a4, a5;
{
int fd, blk, bs;
int ctlr, unit, part, type;
int i;
int bootdev = a1;
char *addr;
char devname[32];
printf("NetBSD/newsmips Primary Boot\n");
DPRINTF("\n");
DPRINTF("a0 %x\n", a0);
DPRINTF("a1 %x\n", a1);
DPRINTF("a2 %x (%s)\n", a2, (char *)a2);
DPRINTF("a3 %x\n", a3);
DPRINTF("a4 %x\n", a4);
DPRINTF("a5 %x\n", a5);
DPRINTF("block_size = %d\n", block_size);
DPRINTF("block_count = %d\n", block_count);
DPRINTF("entry_point = %x\n", (int)entry_point);
/* sd(ctlr, lun, part, bus?, host) */
ctlr = BOOTDEV_CTLR(bootdev);
unit = BOOTDEV_UNIT(bootdev);
part = BOOTDEV_PART(bootdev);
type = BOOTDEV_TYPE(bootdev);
if (devs[type] == NULL) {
printf("unknown bootdev (0x%x)\n", bootdev);
return;
}
sprintf(devname, "%s(%d,%d,%d)", devs[type], ctlr, unit, part);
fd = rom_open(devname, 0);
if (fd == -1) {
printf("cannot open %s\n", devname);
return;
}
addr = (char *)entry_point;
bs = block_size;
DPRINTF("reading block:");
for (i = 0; i < block_count; i++) {
blk = block_table[i];
DPRINTF(" %d", blk);
rom_lseek(fd, blk * 512, 0);
rom_read(fd, addr, bs);
addr += bs;
}
DPRINTF(" done\n");
rom_close(fd);
(*entry_point)(a0, a1, a2, a3);
}
void
putchar(x)
int x;
{
char c = x;
rom_write(1, &c, 1);
}

View File

@ -0,0 +1,138 @@
/* $NetBSD: romcalls.S,v 1.1 1999/07/08 11:48:07 tsubai Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 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 <mips/asm.h>
#include <mips/cpuregs.h>
#include <machine/romcall.h>
.text
.align 2
.set noreorder
.globl halt
halt:
addu sp, sp, -16
li a0, 8 # RB_HALT
sw a0, 0(sp)
li a0, SYS_reboot
move a1, sp
syscall
nop
.globl rom_open
rom_open:
addu sp, sp, -32
sw ra, 28(sp)
sw a0, 16(sp)
sw a1, 20(sp)
li a0, SYS_open
addu a1, sp, 16
syscall
nop
lw ra, 28(sp)
addu sp, sp, 32
j ra
nop
.globl rom_close
rom_close:
addu sp, sp, -32
sw ra, 28(sp)
sw a0, 16(sp)
li a0, SYS_close
addu a1, sp, 16
syscall
nop
lw ra, 28(sp)
addu sp, sp, 32
j ra
nop
.globl rom_read
rom_read:
addu sp, sp, -32
sw ra, 28(sp)
sw a0, 16(sp)
sw a1, 20(sp)
sw a2, 24(sp)
li a0, SYS_read
addu a1, sp, 16
syscall
nop
lw ra, 28(sp)
addu sp, sp, 32
j ra
nop
.globl rom_write
rom_write:
addu sp, sp, -32
sw ra, 28(sp)
sw a0, 16(sp)
sw a1, 20(sp)
sw a2, 24(sp)
li a0, SYS_write
addu a1, sp, 16
syscall
nop
lw ra, 28(sp)
addu sp, sp, 32
j ra
nop
.globl rom_lseek
rom_lseek:
addu sp, sp, -32
sw ra, 28(sp)
sw a0, 16(sp)
sw a1, 20(sp)
sw a2, 24(sp)
li a0, SYS_lseek
addu a1, sp, 16
syscall
nop
lw ra, 28(sp)
addu sp, sp, 32
j ra
nop

View File

@ -0,0 +1,54 @@
/* $NetBSD: start.S,v 1.1 1999/07/08 11:48:07 tsubai Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 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 <mips/asm.h>
#include <mips/cpuregs.h>
.text
.align 2
.set noreorder
.globl _start
_start:
b 1f
nop
.word 0x19900106 /* version? */
.word 0
/* disklabel here */
.space 0x1f0
1:
li sp, 0x7fff0000
addu sp, sp, a3 /* sp = 0x7fff0000 + maxmem */
jal bootxx
nop
jal halt
nop

View File

@ -0,0 +1,8 @@
# $NetBSD: Makefile,v 1.1 1999/07/08 11:48:07 tsubai Exp $
PROG= installboot
MKMAN= no
LDSTATIC= -static
.include <bsd.prog.mk>

View File

@ -0,0 +1,452 @@
/* $NetBSD: installboot.c,v 1.1 1999/07/08 11:48:08 tsubai Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Paul Kranenburg.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 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/param.h>
#include <sys/mount.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#ifdef BOOT_AOUT
#include <a.out.h>
#endif
#include <sys/exec_elf.h>
#include <fcntl.h>
#include <nlist.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int verbose, nowrite;
char *boot, *proto, *dev;
#define BOOTSECTOR_OFFSET 512
#ifndef DEFAULT_ENTRY
#define DEFAULT_ENTRY 0xa0700000
#endif
struct nlist nl[] = {
#define X_BLOCKTABLE 0
{"_block_table"},
#define X_BLOCKCOUNT 1
{"_block_count"},
#define X_BLOCKSIZE 2
{"_block_size"},
#define X_ENTRY_POINT 3
{"_entry_point"},
{NULL}
};
daddr_t *block_table; /* block number array in prototype image */
int32_t *block_count_p; /* size of this array */
int32_t *block_size_p; /* filesystem block size */
int32_t *entry_point_p; /* entry point */
int32_t max_block_count;
char *loadprotoblocks __P((char *, long *));
int loadblocknums __P((char *, int));
static void devread __P((int, void *, daddr_t, size_t, char *));
static void usage __P((void));
int main __P((int, char *[]));
static void
usage()
{
fprintf(stderr,
"usage: installboot [-n] [-v] <boot> <proto> <device>\n");
exit(1);
}
int
main(argc, argv)
int argc;
char *argv[];
{
int c;
int devfd;
char *protostore;
long protosize;
size_t size;
int boot00[512/4];
while ((c = getopt(argc, argv, "vn")) != EOF) {
switch (c) {
case 'n':
/* Do not actually write the bootblock to disk */
nowrite = 1;
break;
case 'v':
/* Chat */
verbose = 1;
break;
default:
usage();
}
}
if (argc - optind < 3) {
usage();
}
boot = argv[optind];
proto = argv[optind + 1];
dev = argv[optind + 2];
if (verbose) {
printf("boot: %s\n", boot);
printf("proto: %s\n", proto);
printf("device: %s\n", dev);
}
/* Load proto blocks into core */
if ((protostore = loadprotoblocks(proto, &protosize)) == NULL)
exit(1);
/* Open and check raw disk device */
if ((devfd = open(dev, O_RDONLY, 0)) < 0)
err(1, "open: %s", dev);
/* Extract and load block numbers */
if (loadblocknums(boot, devfd) != 0)
exit(1);
(void)close(devfd);
if (nowrite)
return 0;
/* Write patched proto bootblocks into the superblock */
if (protosize > SBSIZE - DEV_BSIZE)
errx(1, "proto bootblocks too big");
if ((devfd = open(dev, O_RDWR, 0)) < 0)
err(1, "open: %s", dev);
if (lseek(devfd, BOOTSECTOR_OFFSET, SEEK_SET) != BOOTSECTOR_OFFSET)
err(1, "lseek bootstrap");
/* Sync filesystems (to clean in-memory superblock?) */
sync(); sync(); sync();
if (write(devfd, protostore, protosize) != protosize)
err(1, "write bootstrap");
/* Write boot00 */
if (lseek(devfd, 0, SEEK_SET) != 0)
err(1, "lseek 0a");
if (read(devfd, boot00, sizeof(boot00)) != sizeof(boot00))
err(1, "read boot00");
bzero(boot00, 64);
boot00[0] = 0x1000007f; /* b .+0x200 */
boot00[2] = 0x19900106;
if (lseek(devfd, 0, SEEK_SET) != 0)
err(1, "lseek 0b");
if (write(devfd, boot00, sizeof(boot00)) != sizeof(boot00))
err(1, "write boot00");
(void)close(devfd);
return 0;
}
char *
loadprotoblocks(fname, size)
char *fname;
long *size;
{
int fd, sz;
char *bp;
struct stat statbuf;
#ifdef BOOT_AOUT
struct exec *hp;
#endif
long off;
Elf32_Ehdr *eh;
Elf32_Phdr *ph;
/* Locate block number array in proto file */
if (nlist(fname, nl) != 0) {
warnx("nlist: %s: symbols not found", fname);
return NULL;
}
#ifdef BOOT_AOUT
if (nl[X_BLOCKTABLE].n_type != N_DATA + N_EXT) {
warnx("nlist: %s: wrong type", nl[X_BLOCKTABLE].n_un.n_name);
return NULL;
}
if (nl[X_BLOCKCOUNT].n_type != N_DATA + N_EXT) {
warnx("nlist: %s: wrong type", nl[X_BLOCKCOUNT].n_un.n_name);
return NULL;
}
if (nl[X_BLOCKSIZE].n_type != N_DATA + N_EXT) {
warnx("nlist: %s: wrong type", nl[X_BLOCKSIZE].n_un.n_name);
return NULL;
}
#endif
if ((fd = open(fname, O_RDONLY)) < 0) {
warn("open: %s", fname);
return NULL;
}
if (fstat(fd, &statbuf) != 0) {
warn("fstat: %s", fname);
close(fd);
return NULL;
}
if ((bp = calloc(roundup(statbuf.st_size, DEV_BSIZE), 1)) == NULL) {
warnx("malloc: %s: no memory", fname);
close(fd);
return NULL;
}
if (read(fd, bp, statbuf.st_size) != statbuf.st_size) {
warn("read: %s", fname);
free(bp);
close(fd);
return NULL;
}
close(fd);
#ifdef BOOT_AOUT
hp = (struct exec *)bp;
#endif
eh = (Elf32_Ehdr *)bp;
ph = (Elf32_Phdr *)(bp + eh->e_phoff);
sz = 1024*7;
/* Find first executable psect */
while ((ph->p_flags & Elf_pf_x) == 0) {
ph++; /* XXX check overrun (eh->e_phnum) */
eh->e_phnum--;
if (eh->e_phnum == 0) {
warn("%s: no executable psect", fname);
return NULL;
}
}
/* Calculate the symbols' location within the proto file */
off = ph->p_offset - eh->e_entry;
block_table = (daddr_t *)(bp + nl[X_BLOCKTABLE].n_value + off);
block_count_p = (int32_t *)(bp + nl[X_BLOCKCOUNT].n_value + off);
block_size_p = (int32_t *)(bp + nl[X_BLOCKSIZE].n_value + off);
entry_point_p = (int32_t *)(bp + nl[X_ENTRY_POINT].n_value + off);
if ((int)block_table & 3) {
warn("%s: invalid address: block_table = %x",
fname, block_table);
free(bp);
close(fd);
return NULL;
}
if ((int)block_count_p & 3) {
warn("%s: invalid address: block_count_p = %x",
fname, block_count_p);
free(bp);
close(fd);
return NULL;
}
if ((int)block_size_p & 3) {
warn("%s: invalid address: block_size_p = %x",
fname, block_size_p);
free(bp);
close(fd);
return NULL;
}
if ((int)entry_point_p & 3) {
warn("%s: invalid address: entry_point_p = %x",
fname, entry_point_p);
free(bp);
close(fd);
return NULL;
}
max_block_count = *block_count_p;
if (verbose) {
printf("proto bootblock size: %ld\n", sz);
}
/*
* We convert the a.out header in-vitro into something that
* Sun PROMs understand.
* Old-style (sun4) ROMs do not expect a header at all, so
* we turn the first two words into code that gets us past
* the 32-byte header where the actual code begins. In assembly
* speak:
* .word MAGIC ! a NOP
* ba,a start !
* .skip 24 ! pad
* start:
*/
*size = sz;
return bp + ph->p_offset + 0x200; /* XXX 0x200 */
}
static void
devread(fd, buf, blk, size, msg)
int fd;
void *buf;
daddr_t blk;
size_t size;
char *msg;
{
if (lseek(fd, dbtob(blk), SEEK_SET) != dbtob(blk))
err(1, "%s: devread: lseek", msg);
if (read(fd, buf, size) != size)
err(1, "%s: devread: read", msg);
}
static char sblock[SBSIZE];
int
loadblocknums(boot, devfd)
char *boot;
int devfd;
{
int i, fd;
struct stat statbuf;
struct statfs statfsbuf;
struct fs *fs;
char *buf;
daddr_t blk, *ap;
struct dinode *ip;
int ndb;
/*
* Open 2nd-level boot program and record the block numbers
* it occupies on the filesystem represented by `devfd'.
*/
if ((fd = open(boot, O_RDONLY)) < 0)
err(1, "open: %s", boot);
if (fstatfs(fd, &statfsbuf) != 0)
err(1, "statfs: %s", boot);
if (strncmp(statfsbuf.f_fstypename, "ffs", MFSNAMELEN) &&
strncmp(statfsbuf.f_fstypename, "ufs", MFSNAMELEN)) {
errx(1, "%s: must be on an FFS filesystem", boot);
}
if (fsync(fd) != 0)
err(1, "fsync: %s", boot);
if (fstat(fd, &statbuf) != 0)
err(1, "fstat: %s", boot);
close(fd);
/* Read superblock */
devread(devfd, sblock, btodb(SBOFF), SBSIZE, "superblock");
fs = (struct fs *)sblock;
/* Read inode */
if ((buf = malloc(fs->fs_bsize)) == NULL)
errx(1, "No memory for filesystem block");
blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino));
devread(devfd, buf, blk, fs->fs_bsize, "inode");
ip = (struct dinode *)(buf) + ino_to_fsbo(fs, statbuf.st_ino);
/*
* Register filesystem block size.
*/
*block_size_p = fs->fs_bsize;
/*
* Get the block numbers; we don't handle fragments
*/
ndb = howmany(ip->di_size, fs->fs_bsize);
if (ndb > max_block_count)
errx(1, "%s: Too many blocks", boot);
/*
* Register block count.
*/
*block_count_p = ndb;
/*
* Register entry point.
*/
*entry_point_p = DEFAULT_ENTRY;
if (verbose)
printf("entry point: 0x%08x\n", *entry_point_p);
if (verbose)
printf("%s: block numbers: ", boot);
ap = ip->di_db;
for (i = 0; i < NDADDR && *ap && ndb; i++, ap++, ndb--) {
blk = fsbtodb(fs, *ap);
block_table[i] = blk;
if (verbose)
printf("%d ", blk);
}
if (verbose)
printf("\n");
if (ndb == 0)
return 0;
/*
* Just one level of indirections; there isn't much room
* for more in the 1st-level bootblocks anyway.
*/
if (verbose)
printf("%s: block numbers (indirect): ", boot);
blk = ip->di_ib[0];
devread(devfd, buf, blk, fs->fs_bsize, "indirect block");
ap = (daddr_t *)buf;
for (; i < NINDIR(fs) && *ap && ndb; i++, ap++, ndb--) {
blk = fsbtodb(fs, *ap);
block_table[i] = blk;
if (verbose)
printf("%d ", blk);
}
if (verbose)
printf("\n");
if (ndb)
errx(1, "%s: Too many blocks", boot);
return 0;
}