bootxx: bootstrap code - installable by MI installboot.
Loads /boot using filesystem accesses (rather than a list of block numbers)
This commit is contained in:
parent
3bef3105ca
commit
eb2692a8d2
|
@ -0,0 +1,6 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:17:44 dsl Exp $
|
||||
|
||||
SUBDIR= bootxx_ufs bootxx_ffsv1 bootxx_ffsv2 bootxx_lfsv1 bootxx_lfsv2
|
||||
SUBDIR+= bootxx_dosfs bootxx_ustarfs
|
||||
|
||||
.include <bsd.subdir.mk>
|
|
@ -0,0 +1,144 @@
|
|||
# $NetBSD: Makefile.bootxx,v 1.1 2003/04/16 22:17:44 dsl Exp $
|
||||
|
||||
S= ${.CURDIR}/../../../../../
|
||||
|
||||
NOMAN=
|
||||
STRIPFLAG=
|
||||
PROG= bootxx_${FS}
|
||||
PRIMARY_LOAD_ADDRESS=0x600
|
||||
SECONDARY_LOAD_ADDRESS=0x10000
|
||||
|
||||
# We ought (need?) to fit into track 0 of a 1.2M floppy.
|
||||
# This restricts us to 15 sectors (including pbr and label)
|
||||
BOOTXX_SECTORS?=15
|
||||
BOOTXX_MAXSIZE?= $$(( ${BOOTXX_SECTORS} * 512 ))
|
||||
|
||||
SRCS= pbr.S label.S bootxx.S boot1.c
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
LIBCRT0= # nothing
|
||||
LIBCRTBEGIN= # nothing
|
||||
LIBCRTEND= # nothing
|
||||
LIBC= # nothing
|
||||
|
||||
BINDIR=/usr/mdec
|
||||
BINMODE=444
|
||||
|
||||
.PATH: ${.CURDIR}/.. ${.CURDIR}/../../lib
|
||||
|
||||
LDFLAGS+= -N -e start
|
||||
CPPFLAGS+= -DBOOTXX
|
||||
# CPPFLAGS+= -D__daddr_t=int32_t
|
||||
CPPFLAGS+= -I ${.CURDIR}/../../lib -I ${.OBJDIR}
|
||||
CPPFLAGS+= -DBOOTXX_SECTORS=${BOOTXX_SECTORS}
|
||||
CPPFLAGS+= -DPRIMARY_LOAD_ADDRESS=${PRIMARY_LOAD_ADDRESS}
|
||||
CPPFLAGS+= -DSECONDARY_LOAD_ADDRESS=${SECONDARY_LOAD_ADDRESS}
|
||||
# Magic number also known by usr.sbin/installboot/arch/i386.c
|
||||
CPPFLAGS+= -DX86_BOOT_MAGIC_1="('x' << 24 | 0x86b << 12 | 'm' << 4 | 1)"
|
||||
CPPFLAGS+= -DXXfs_open=${FS}_open
|
||||
CPPFLAGS+= -DXXfs_close=${FS}_close
|
||||
CPPFLAGS+= -DXXfs_read=${FS}_read
|
||||
CPPFLAGS+= -DXXfs_stat=${FS}_stat
|
||||
|
||||
# Make sure we override any optimization options specified by the user
|
||||
COPTS= -Os
|
||||
|
||||
.if ${MACHINE} == "x86_64"
|
||||
LDFLAGS+= -m elf_i386
|
||||
AFLAGS+= -m32
|
||||
COPTS+= -m32
|
||||
LIBKERN_ARCH=i386
|
||||
KERNMISCMAKEFLAGS="LIBKERN_ARCH=i386"
|
||||
.else
|
||||
COPTS+= -mcpu=i386
|
||||
.endif
|
||||
|
||||
COPTS+= -ffreestanding
|
||||
CFLAGS+= -Wall -Wmissing-prototypes -Wstrict-prototypes
|
||||
CPPFLAGS+= -nostdinc -D_STANDALONE
|
||||
CPPFLAGS+= -I$S
|
||||
|
||||
CPPFLAGS+= -DLIBSA_SINGLE_FILESYSTEM=xxfs \
|
||||
-DLIBSA_NO_TWIDDLE \
|
||||
-DLIBSA_NO_FD_CHECKING \
|
||||
-DLIBSA_NO_RAW_ACCESS \
|
||||
-DLIBSA_NO_FS_WRITE \
|
||||
-DLIBSA_NO_FS_SEEK \
|
||||
-DLIBSA_USE_MEMCPY \
|
||||
-DLIBSA_USE_MEMSET \
|
||||
-DLIBSA_SINGLE_DEVICE=blkdev \
|
||||
-DLIBKERN_OPTIMISE_SPACE \
|
||||
-D"blkdevioctl(x,y,z)=EINVAL" \
|
||||
-D"blkdevclose(f)=0" \
|
||||
-D"devopen(f,n,fl)=(*(fl)=(void *)n,0)" \
|
||||
-DLIBSA_NO_DISKLABEL_MSGS
|
||||
|
||||
# -DLIBSA_FS_SINGLECOMPONENT
|
||||
|
||||
# CPPFLAGS+= -DBOOTXX_RAID1_SUPPORT
|
||||
|
||||
I386_STAND_DIR?= $S/arch/i386/stand
|
||||
|
||||
.if !make(obj) && !make(clean) && !make(cleandir)
|
||||
.BEGIN: machine
|
||||
.NOPATH: machine
|
||||
.endif
|
||||
|
||||
realdepend realall: machine
|
||||
CLEANFILES+= machine
|
||||
|
||||
machine::
|
||||
-rm -f $@
|
||||
ln -s $S/arch/i386/include $@
|
||||
|
||||
${OBJS}: machine
|
||||
|
||||
### find out what to use for libi386
|
||||
I386DIR= ${I386_STAND_DIR}/lib
|
||||
I386DST= ${.OBJDIR}/../lib/i386
|
||||
.include "${I386DIR}/Makefile.inc"
|
||||
LIBI386= ${I386LIB}
|
||||
|
||||
### find out what to use for libsa
|
||||
SA_AS= library
|
||||
SADST= ${.OBJDIR}/../lib/libsa
|
||||
SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
|
||||
.include "${S}/lib/libsa/Makefile.inc"
|
||||
LIBSA= ${SALIB}
|
||||
|
||||
### find out what to use for libkern
|
||||
KERN_AS= library
|
||||
KERNDST= ${.OBJDIR}/../lib/libkern
|
||||
.include "${S}/lib/libkern/Makefile.inc"
|
||||
LIBKERN= ${KERNLIB}
|
||||
|
||||
|
||||
cleandir distclean: cleanlibdir
|
||||
|
||||
cleanlibdir:
|
||||
rm -rf lib
|
||||
|
||||
LIBLIST= ${LIBI386} ${LIBSA} ${LIBKERN} ${LIBI386} ${LIBSA}
|
||||
|
||||
CLEANFILES+= ${PROG}.tmp ${PROG}.map
|
||||
|
||||
${PROG}: ${OBJS} ${LIBLIST}
|
||||
${LD} -o ${PROG}.tmp ${LDFLAGS} -Ttext ${PRIMARY_LOAD_ADDRESS} \
|
||||
-Map ${PROG}.map -cref ${OBJS} ${LIBLIST}
|
||||
${OBJCOPY} -O binary ${PROG}.tmp ${PROG}
|
||||
# rm -f ${PROG}.tmp
|
||||
@ sz=$$(ls -ln ${PROG}|tr -s ' '|cut -d' ' -f5); \
|
||||
if [ "$$sz" -gt "${BOOTXX_MAXSIZE}" ]; then \
|
||||
echo "### ${PROG} size $$sz is larger than ${BOOTXX_MAXSIZE}" >&2; \
|
||||
rm ${PROG}; \
|
||||
! :; \
|
||||
else \
|
||||
: pad to sector boundary; \
|
||||
pad=$$(( 512 - ( $$sz & 511 ) )); \
|
||||
[ $$pad != 512 ] && \
|
||||
dd if=/dev/zero bs=1 count=$$pad >>${PROG} 2>/dev/null; \
|
||||
echo "${PROG} size $$sz, $$((${BOOTXX_MAXSIZE} - $$sz)) free"; \
|
||||
fi
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,108 @@
|
|||
/* $NetBSD: boot1.c,v 1.1 2003/04/16 22:17:44 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David Laight.
|
||||
*
|
||||
* 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/cdefs.h>
|
||||
__RCSID("$NetBSD: boot1.c,v 1.1 2003/04/16 22:17:44 dsl Exp $");
|
||||
|
||||
#include <lib/libsa/stand.h>
|
||||
#include <lib/libkern/libkern.h>
|
||||
#include <biosdisk_ll.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bootblock.h>
|
||||
|
||||
static uint32_t bios_dev;
|
||||
static uint32_t bios_sector;
|
||||
|
||||
struct biosdisk_ll d;
|
||||
|
||||
const char *boot1(uint32_t biosdev, uint32_t sector);
|
||||
extern void putstr(const char *);
|
||||
|
||||
const char *
|
||||
boot1(uint32_t biosdev, uint32_t sector)
|
||||
{
|
||||
struct stat sb;
|
||||
int fd;
|
||||
|
||||
bios_sector = sector;
|
||||
bios_dev = biosdev;
|
||||
d.dev = biosdev;
|
||||
|
||||
putstr("\r\nNetBSD/i386 Primary Bootstrap\r\n");
|
||||
|
||||
if (set_geometry(&d, NULL))
|
||||
return "set_geometry\r\n";
|
||||
|
||||
fd = open("boot", 0);
|
||||
if (fd == -1 || fstat(fd, &sb) == -1)
|
||||
return "Can't open /boot.\r\n";
|
||||
|
||||
#if 0
|
||||
if (sb.st_size > SECONDARY_MAX_LOAD)
|
||||
return "/boot too large.\r\n";
|
||||
#endif
|
||||
|
||||
if (read(fd, (void *)SECONDARY_LOAD_ADDRESS, sb.st_size) != sb.st_size)
|
||||
return "/boot load failed.\r\n";
|
||||
|
||||
if (*(uint32_t *)(SECONDARY_LOAD_ADDRESS + 4) != X86_BOOT_MAGIC_2)
|
||||
return "Invalid /boot file format.\r\n";
|
||||
|
||||
/* We need to jump to the secondary bootstrap in realmode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
blkdevstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize)
|
||||
{
|
||||
if (flag != F_READ)
|
||||
return EROFS;
|
||||
|
||||
if (size & (BIOSDISK_SECSIZE - 1))
|
||||
return EINVAL;
|
||||
|
||||
if (rsize)
|
||||
*rsize = size;
|
||||
|
||||
if (size != 0 && readsects(&d, bios_sector + dblk,
|
||||
size / BIOSDISK_SECSIZE, buf, 1) != 0)
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* $NetBSD: boot_params.S,v 1.1 2003/04/16 22:17:44 dsl Exp $ */
|
||||
|
||||
/* Default boot parameters */
|
||||
|
||||
.long 0 /* flags */
|
||||
.long 5 /* timeout in seconds */
|
||||
.long 0 /* console device 0 => CONSDEV_PC */
|
||||
.long 9600 /* serial baud rate */
|
||||
.space 16 /* md5 boot password */
|
|
@ -0,0 +1,128 @@
|
|||
/* $NetBSD: bootxx.S,v 1.1 2003/04/16 22:17:44 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David Laight.
|
||||
*
|
||||
* 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 <machine/asm.h>
|
||||
#include <sys/disklabel_mbr.h>
|
||||
|
||||
/*
|
||||
* Code linked to 0xa00 and copied to sectors 2+ of the netbsd boot
|
||||
* partition by MI /usr/sbin/installboot.
|
||||
* Read into memory by code in pbr.S
|
||||
*
|
||||
* On entry:
|
||||
* %dl BIOS drive number
|
||||
* %esi Sector number of netbsd partition
|
||||
* %cs, %ds, %es, %ss All zero
|
||||
* %sp near 0xfffc
|
||||
*/
|
||||
.text
|
||||
.code16
|
||||
ENTRY(bootxx)
|
||||
jmp 1f
|
||||
.align 4
|
||||
ENTRY(bootxx_magic)
|
||||
.long X86_BOOT_MAGIC_1 /* checked by installboot & pbr code */
|
||||
bootparams: /* space for patchable variables */
|
||||
.long 1f - bootparams /* length of this data area */
|
||||
#include "boot_params.S"
|
||||
.space 4 * 4 /* some spare */
|
||||
|
||||
1: call gdt_fixup
|
||||
|
||||
calll real_to_prot
|
||||
.code32
|
||||
|
||||
movl $_end, %ecx /* zero bss */
|
||||
movl $__bss_start, %edi
|
||||
subl %edi, %ecx
|
||||
shr $2, %ecx /* _end and __bss_start are aligned */
|
||||
xor %eax, %eax
|
||||
rep
|
||||
stosl
|
||||
|
||||
and $0xff, %edx
|
||||
push %esi /* save args for secondary bootstrap */
|
||||
push %edx
|
||||
push %esi /* args for boot1 */
|
||||
push %edx
|
||||
call _C_LABEL(boot1) /* C code to load /boot */
|
||||
add $8, %esp
|
||||
call prot_to_real
|
||||
.code16
|
||||
|
||||
test %ax, %ax
|
||||
jnz boot_fail
|
||||
|
||||
pop %edx /* bios disk number */
|
||||
pop %ebx /* expected partition start sector */
|
||||
movl $bootparams, %esi
|
||||
lcall $SECONDARY_LOAD_ADDRESS/16, $0
|
||||
|
||||
boot_fail:
|
||||
push %ax
|
||||
movw $1f, %si
|
||||
call message
|
||||
pop %si
|
||||
call message
|
||||
jmp loopstop
|
||||
1: .asciz "Boot failed: "
|
||||
|
||||
ENTRY(_rtt)
|
||||
.code32
|
||||
call prot_to_real
|
||||
.code16
|
||||
loopstop:
|
||||
movb 0x86, %ah /* delay for about a second */
|
||||
movw $16, %cx
|
||||
int $0x15
|
||||
int $0x18 /* might be a boot fail entry */
|
||||
1: sti
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
/*
|
||||
* Vector the fs calls through here so we can support multiple
|
||||
* file system types with one copy of the library code and
|
||||
* multiple copies of this file.
|
||||
*/
|
||||
.global xxfs_open, xxfs_close, xxfs_read, xxfs_stat
|
||||
.code32
|
||||
xxfs_open: jmp XXfs_open
|
||||
xxfs_close: jmp XXfs_close
|
||||
xxfs_read: jmp XXfs_read
|
||||
xxfs_stat: jmp XXfs_stat
|
|
@ -0,0 +1,5 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
|
||||
|
||||
FS=ffsv1
|
||||
|
||||
.include <../Makefile.bootxx>
|
|
@ -0,0 +1,5 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
|
||||
|
||||
FS=ffsv2
|
||||
|
||||
.include <../Makefile.bootxx>
|
|
@ -0,0 +1,5 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
|
||||
|
||||
FS=lfsv1
|
||||
|
||||
.include <../Makefile.bootxx>
|
|
@ -0,0 +1,5 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
|
||||
|
||||
FS=lfsv2
|
||||
|
||||
.include <../Makefile.bootxx>
|
|
@ -0,0 +1,5 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
|
||||
|
||||
FS=ufs
|
||||
|
||||
.include <../Makefile.bootxx>
|
|
@ -0,0 +1,7 @@
|
|||
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
|
||||
|
||||
FS=ustarfs
|
||||
|
||||
BOOTXX_SECTORS=16
|
||||
|
||||
.include <../Makefile.bootxx>
|
|
@ -0,0 +1,13 @@
|
|||
/* $NetBSD: label.S,v 1.1 2003/04/16 22:17:44 dsl Exp $ */
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
/*
|
||||
* This fills in the space taken by the NetBSD disklabel in the first
|
||||
* NetBSD partition on the disk.
|
||||
* However it is possible that we are booting from a subsequent
|
||||
* NetBSD partition, so must not access the disklabe in this space.
|
||||
*/
|
||||
|
||||
.text
|
||||
label: .fill 512
|
|
@ -0,0 +1,368 @@
|
|||
/* $NetBSD: pbr.S,v 1.1 2003/04/16 22:16:36 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by David Laight.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i386 partition boot code
|
||||
*
|
||||
* This code resides in sector zero of the netbsd partition, or sector
|
||||
* zero of an unpartitioned disk (eg a floppy).
|
||||
* Sector 1 is assumed to contain the netbsd disklabel.
|
||||
* Sectors 2 until the end of the track contain the next phase of bootstrap.
|
||||
* Which know how to read the interactive 'boot' program from filestore.
|
||||
* The job of this code is to read in the phase 1 bootstrap.
|
||||
*
|
||||
* Makefile supplies:
|
||||
* PRIMARY_LOAD_ADDRESS: Address we load code toi (0x600).
|
||||
* BOOTXX_SECTORS: Number of sectors we load (15).
|
||||
* X86_BOOT_MAGIC_1: A random magic number.
|
||||
*
|
||||
* Although this code is executing at 0x7c00, it is linked to address 0x600.
|
||||
* All data references MUST be fixed up using R().
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include <sys/disklabel_mbr.h>
|
||||
|
||||
#define OURADDR 0x7c00 /* our address */
|
||||
#define BOOTADDR PRIMARY_LOAD_ADDRESS
|
||||
|
||||
#define R(a) (a - BOOTADDR + OURADDR)
|
||||
|
||||
#define lba_info R(_lba_info)
|
||||
#define lba_sector R(_lba_sector)
|
||||
#define errtxt R(_errtxt)
|
||||
#define errcod R(_errcod)
|
||||
#define newline R(_newline)
|
||||
|
||||
#define TABENTRYSIZE (PARTNAMESIZE + 1)
|
||||
#define NAMETABSIZE (4 * TABENTRYSIZE)
|
||||
|
||||
#ifdef TERSE_ERROR
|
||||
/*
|
||||
* Error codes. Done this way to save space.
|
||||
*/
|
||||
#define ERR_READ '2' /* Read error */
|
||||
#define ERR_NO_BOOTXX 'B' /* No bootxx_xfs in 3rd sector */
|
||||
#define ERR_PTN 'P' /* partition not defined */
|
||||
#define ERR_NO_LBA 'L' /* sector above chs limit */
|
||||
|
||||
#define set_err(err) movb $err, %al
|
||||
|
||||
#else
|
||||
#define set_err(err) mov $R(err), %ax
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This code is loaded to addresss 0:7c00 by either the system BIOS
|
||||
* (for a floppy) or the mbr boot code. Since the boot program will
|
||||
* be loaded to address 1000:0, we don't need to relocate ourselves
|
||||
* and can load the subsequent blocks (that load boot) to an address
|
||||
* of our choosing. 0:600 is a not unreasonable choice.
|
||||
*
|
||||
* On entry the bios drive number is in %dl and %esi may contain the
|
||||
* sector we were loaded from (if we were loaded by NetBSD mbr code).
|
||||
* In any case we have to re-read sector zero of the disk and hunt
|
||||
* through the BIOS partition table for the NetBSD partition.
|
||||
*/
|
||||
|
||||
.text
|
||||
.code16
|
||||
ENTRY(start)
|
||||
/*
|
||||
* The PC BIOS architecture defines a 'Boot Parameter Block' here.
|
||||
* The actual format varies between different dos versions, but
|
||||
* apparantly some system BIOS insist on patching this area
|
||||
* (especially on LS120 drives).
|
||||
* The initial jmp and nop are part of the standard and may be
|
||||
* tested for by the system BIOS.
|
||||
*/
|
||||
jmp start0
|
||||
nop
|
||||
.ascii "NetBSD20" /* OS name and version */
|
||||
|
||||
. = start + 0x25 /* rest all zeros for now */
|
||||
start0:
|
||||
mov %cs, %ax /* don't trust values of ds, es or ss */
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %ss
|
||||
mov $0xfffc, %sp
|
||||
|
||||
/* A 'reset disk system' request is traditional here... */
|
||||
xor %ax, %ax /* in particular ah = 0 */
|
||||
int $0x13
|
||||
|
||||
/* Read from start of disk */
|
||||
movw $0x0001, %cx /* track zero sector 1 */
|
||||
movb %ch, %dh /* dh = head = 0 */
|
||||
call chs_read
|
||||
|
||||
/* See if this is our code, if so we have already loaded the next stage */
|
||||
|
||||
movl (%bx), %eax /* mbr code shouldn't even have ... */
|
||||
cmpl R(start), %eax /* ... a jmp at the start. */
|
||||
je pbr_read_ok
|
||||
|
||||
/* Now scan the mbr partition table for a netbsd partition */
|
||||
|
||||
xorl %ebx, %ebx /* for base extended ptn chain */
|
||||
xorl %ecx, %ecx /* for next extended ptn */
|
||||
scan_ptn_tbl:
|
||||
movw $BOOTADDR + MBR_PARTOFF, %di
|
||||
1: movb 4(%di), %al /* mbrp_typ */
|
||||
movl 8(%di), %ebp /* mbrp_start == LBA sector */
|
||||
cmpb $MBR_PTYPE_NETBSD, %al
|
||||
jne 10f
|
||||
testl %esi, %esi /* looking for a specific sector? */
|
||||
je boot
|
||||
cmpl %ebp, %esi /* ptn we wanted? */
|
||||
je boot
|
||||
/* check for extended partition */
|
||||
10: cmpb $MBR_PTYPE_EXT, %al
|
||||
je 15f
|
||||
cmpb $MBR_PTYPE_EXT_LBA, %al
|
||||
je 15f
|
||||
cmpb $MBR_PTYPE_EXT_LNX, %al
|
||||
jne 20f
|
||||
15: movl 8(%di), %ecx /* sector of next ext. ptn */
|
||||
20: add $0x10, %di
|
||||
cmp $BOOTADDR + MBR_MAGICOFF, %di
|
||||
jne 1b
|
||||
|
||||
/* not in base partitions, check extended ones */
|
||||
jecxz no_netbsd_ptn
|
||||
testl %ebx, %ebx
|
||||
jne 30f
|
||||
xchgl %ebx, %ecx /* save base of ext ptn chain */
|
||||
30: addl %ebx, %ecx /* address this ptn */
|
||||
movl %ecx, lba_sector /* sector to read */
|
||||
call read_lba
|
||||
jmp scan_ptn_tbl
|
||||
|
||||
/*
|
||||
* Something went wrong,
|
||||
* Output error code,
|
||||
*/
|
||||
|
||||
read_err:
|
||||
set_err(ERR_READ)
|
||||
error:
|
||||
#ifdef TERSE_ERROR
|
||||
movb %al, errcod
|
||||
movw $errtxt, %si
|
||||
call message
|
||||
#else
|
||||
push %ax
|
||||
movw $errtxt, %si
|
||||
call message
|
||||
pop %si
|
||||
call message
|
||||
movw $newline, %si
|
||||
call message
|
||||
#endif
|
||||
1: sti
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
no_netbsd_ptn:
|
||||
/* Specific sector not found: try again looking for first NetBSD ptn */
|
||||
testl %esi, %esi
|
||||
set_err(ERR_PTN)
|
||||
jz error
|
||||
xorl %esi, %esi
|
||||
jmp start
|
||||
|
||||
/*
|
||||
* Active partition pointed to by di.
|
||||
*
|
||||
* We can either do a CHS (Cylinder Head Sector) or an LBA (Logical
|
||||
* Block Address) read. Always doing the LBA one
|
||||
* would be nice - unfortunately not all systems support it.
|
||||
* Also some may contain a separate (eg SCSI) bios that doesn't
|
||||
* support it even when the main bios does.
|
||||
*
|
||||
* The safest thing seems to be to find out whether the sector we
|
||||
* want is inside the CHS sector count. If it is we use CHS, if
|
||||
* outside we use LBA.
|
||||
*
|
||||
* Actually we check that the CHS values reference the LBA sector,
|
||||
* if not we assume that the LBA sector is above the limit, or that
|
||||
* the geometry used (by fdisk) isn't correct.
|
||||
*
|
||||
* There isn't much point checking if LBA support is present! We
|
||||
* only try to use it if it is necessary.
|
||||
*/
|
||||
boot:
|
||||
movl %ebp, lba_sector /* to control block */
|
||||
testl %ebx, %ebx /* was it an extended ptn? */
|
||||
jnz boot_lba /* yes - boot with LBA reads */
|
||||
|
||||
/* get maximum (bios) sector */
|
||||
push %dx /* save drive number */
|
||||
movb $8, %ah
|
||||
int $0x13 /* chs info */
|
||||
|
||||
/*
|
||||
* Validate geometry, if the CHS sector number doesn't match the LBA one
|
||||
* we'll do an LBA read.
|
||||
* calc: (cylinder * number_of_heads + head) * number_of_sectors + sector
|
||||
* and compare against LBA sector number.
|
||||
* Take a slight 'flier' and assume we can just check 16bits (very likely
|
||||
* to be true because the number of sectors per track is 63).
|
||||
*/
|
||||
movw 2(%di), %ax /* cylinder + sector */
|
||||
push %ax /* save for sector */
|
||||
shr $6, %al
|
||||
xchgb %al, %ah /* 10 bit cylinder number */
|
||||
shr $8, %dx /* last head */
|
||||
inc %dx /* number of heads */
|
||||
mul %dx
|
||||
mov 1(%di), %dl /* head we want */
|
||||
add %dx, %ax
|
||||
and $0x3f, %cx /* number of sectors */
|
||||
mul %cx
|
||||
pop %dx /* recover sector we want */
|
||||
and $0x3f, %dx
|
||||
add %dx, %ax
|
||||
dec %ax
|
||||
pop %dx /* recover drive nmber */
|
||||
|
||||
cmp %bp, %ax
|
||||
jne check_lba
|
||||
|
||||
/* Read using CHS */
|
||||
|
||||
/*
|
||||
* Sector below CHS limit
|
||||
* Do a cylinder-head-sector read instead
|
||||
* I believe the bios should do reads that cross track boundaries.
|
||||
* (but the read should start at the beginning of a track...)
|
||||
*/
|
||||
read_chs:
|
||||
movb 1(%di), %dh /* head */
|
||||
movw 2(%di), %cx /* ch=cyl, cl=sect */
|
||||
call chs_read
|
||||
jmp pbr_read_ok
|
||||
|
||||
chs_read:
|
||||
movw $BOOTADDR, %bx /* es:bx is buffer */
|
||||
movw $0x200 + BOOTXX_SECTORS, %ax /* command 2, xx sectors */
|
||||
int $0x13
|
||||
jc read_err
|
||||
ret
|
||||
|
||||
|
||||
check_lba:
|
||||
#ifndef NO_LBA_CHECK
|
||||
/* Determine whether we have int13-extensions, by calling
|
||||
* int 13, function 41. Check for the magic number returned,
|
||||
* and the disk packet capability.
|
||||
*/
|
||||
movw $0x55aa, %bx
|
||||
movb $0x41, %ah
|
||||
int $0x13
|
||||
jc 1f /* no int13 extensions */
|
||||
cmpw $0xaa55, %bx
|
||||
jnz 1f
|
||||
testb $1, %cl
|
||||
jnz boot_lba
|
||||
1: set_err(ERR_NO_LBA)
|
||||
jmp error
|
||||
#endif /* NO_LBA_CHECK */
|
||||
|
||||
boot_lba:
|
||||
call read_lba
|
||||
|
||||
/*
|
||||
* Check magic number for valid stage 2 bootcode
|
||||
* then jump into it.
|
||||
*/
|
||||
pbr_read_ok:
|
||||
cmpl $X86_BOOT_MAGIC_1, bootxx_magic
|
||||
set_err(ERR_NO_BOOTXX)
|
||||
jnz error
|
||||
|
||||
movl %ebp, %esi /* %esi ptn base, %dl disk id */
|
||||
jmp bootxx + BOOTADDR - OURADDR
|
||||
|
||||
/* Read disk using int13-extension parameter block */
|
||||
read_lba:
|
||||
push %si
|
||||
movw $lba_info, %si /* ds:si is ctl block */
|
||||
movb $0x42, %ah
|
||||
int $0x13
|
||||
pop %si
|
||||
|
||||
jc read_err
|
||||
ret
|
||||
|
||||
/* Control block for int-13 LBA read. */
|
||||
_lba_info:
|
||||
.word 0x10 /* control block length */
|
||||
.word BOOTXX_SECTORS /* sector count */
|
||||
.word BOOTADDR /* offset in segment */
|
||||
.word 0 /* segment */
|
||||
_lba_sector:
|
||||
.long 0x0000 /* sector # goes here... */
|
||||
.long 0x0000
|
||||
|
||||
_errtxt: .ascii "Error " /* runs into newline... */
|
||||
_errcod: .byte 0 /* ... if errcod set */
|
||||
_newline:
|
||||
.asciz "\r\n"
|
||||
|
||||
#ifndef TERSE_ERROR
|
||||
ERR_READ: .asciz "Disk read error"
|
||||
ERR_NO_BOOTXX: .asciz "Not a bootxx image"
|
||||
ERR_NO_LBA: .asciz "Invalid CHS read"
|
||||
ERR_PTN: .asciz "No NetBSD partition"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* I hate #including source files, but the stuff below has to be at
|
||||
* the correct absolute address.
|
||||
* Clearly this could be done with a linker script.
|
||||
*/
|
||||
|
||||
#include <message.S>
|
||||
#if 0
|
||||
#include <dump_eax.S>
|
||||
#endif
|
||||
|
||||
. = _C_LABEL(start) + MBR_MAGICOFF
|
||||
.word MBR_MAGIC
|
Loading…
Reference in New Issue