/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Bang Jun-Young.
*
* 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 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.
*/
/*
* This is a primary boot loader that loads a secondary boot loader
* directly from CD without performing floppy/hard disk emulation as
* described by the El Torito specification.
*/
real_start:
movb %dl, boot_drive /* Save boot drive number */
#ifndef DISABLE_KEYPRESS
/*
* We can skip boot wait when:
* - there's no hard disk present.
* - there's no active partition in the MBR of the 1st hard disk.
*/
/*
* Check presence of hard disks.
*/
movw $0x475, %si
movb (%si), %al
testb %al, %al
jz boot_cdrom
/*
* Find the active partition from the MBR.
*/
movw $0x0201, %ax /* %al = number of sectors to read */
movw $BOOT_ADDR, %bx /* %es:%bx = data buffer */
movw $0x0001, %cx /* %ch = low 8 bits of cylinder no */
/* %cl = high 2 bits of cyl no & */
/* sector number */
movw $0x0080, %dx /* %dh = head number */
/* %dl = disk number */
int $0x13 /* Read MBR into memory */
jc boot_cdrom /* CF set on error */
movb $1, mbr_loaded
movb $MBR_PART_COUNT, %cl
movw $BOOT_ADDR+MBR_PART_OFFSET, %si
1:
movb (%si), %al
testb $0x80, %al
jnz found_active
addw $MBR_PART_SIZE, %si
decb %cl
testb %cl, %cl
jnz 1b /* If 0, no active partition found */
jmp boot_cdrom
found_active:
movw $str_press_key, %si
call message
next_second:
movw $str_dot, %si
call message
decb wait_count
jz boot_hard_disk
xorb %ah, %ah /* Get system time */
int $0x1a
movw %dx, %di /* %cx:%dx = number of clock ticks */
addw $19, %di /* 19 ~= 18.2 Hz */
wait_key:
movb $1, %ah /* Check for keystroke */
int $0x16
jz not_avail /* ZF clear if keystroke available */
xorb %ah, %ah /* Read key to flush keyboard buf */
int $0x16
jmp boot_cdrom
not_avail:
xorb %ah, %ah /* Get system time */
int $0x1a
cmpw %dx, %di /* Compare with saved time */
jnz wait_key
jmp next_second
boot_hard_disk:
movw $str_crlf, %si
call message
cmpb $1, mbr_loaded
jz 1f
movw $0x0201, %ax /* %al = number of sectors to read */
movw $BOOT_ADDR, %bx /* %es:%bx = data buffer */
movw $0x0001, %cx /* %ch = low 8 bits of cylinder no */
/* %cl = high 2 bits of cyl no & */
/* sector number */
movw $0x0080, %dx /* %dh = head number */
/* %dl = disk number */
int $0x13 /* Read MBR into memory */
jc panic /* CF set on error */
1:
movw %cs, %ax /* Restore initial state */
movw %ax, %ds
movw %ax, %es
movw $0x0080, %dx /* %dl = boot drive number */
jmp $0, $BOOT_ADDR /* Jump to MBR! */
jmp panic /* This should be never executed */
#endif /* !DISABLE_KEYPRESS */
boot_cdrom:
movw $str_banner, %si
call message
/* Read volume descriptor sectors until Primary descriptor found */
movl $VD_LBA, %eax
next_block:
movb $1, %dh /* Number of sectors to read */
movl $PVD_ADDR, %ebx
call read_sectors
cmpb $VD_PRIMARY, (%bx) /* Is it Primary Volume Descriptor? */
jz pvd_found
incl %eax
cmpb $VD_TERMINATOR, (%bx)
jnz next_block
movw $str_no_pvd, %si
call message
jmp panic
/* Read all of root directory */
pvd_found:
movw $PVD_ADDR+PVD_ROOT_DR, %bx
movl DR_EXTENT(%bx), %eax /* LBA of the root directory */
movl DR_DATA_LEN(%bx), %edx
shrl $11, %edx /* Convert to number of sectors */
movb %dl, %dh /* ... and load it to %dh */
movl $ROOTDIR_ADDR, %ebx
call read_sectors