bootxx: bootstrap code - installable by MI installboot.

Loads /boot using filesystem accesses (rather than a list of block numbers)
This commit is contained in:
dsl 2003-04-16 22:16:36 +00:00
parent 3bef3105ca
commit eb2692a8d2
13 changed files with 808 additions and 0 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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;
}

View File

@ -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 */

View File

@ -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

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
FS=ffsv1
.include <../Makefile.bootxx>

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
FS=ffsv2
.include <../Makefile.bootxx>

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
FS=lfsv1
.include <../Makefile.bootxx>

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
FS=lfsv2
.include <../Makefile.bootxx>

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
FS=ufs
.include <../Makefile.bootxx>

View File

@ -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>

View File

@ -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

View File

@ -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