Initial commit of cdboot, 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.
This commit is contained in:
parent
13f898cc84
commit
0da67fb4ba
|
@ -0,0 +1,63 @@
|
|||
# $NetBSD: Makefile,v 1.1 2005/06/15 06:38:45 junyoung Exp $
|
||||
|
||||
S= ${.CURDIR}/../../../../../
|
||||
|
||||
NOMAN= # defined
|
||||
STRIPFLAG= # nothing
|
||||
|
||||
LIBCRT0= # nothing
|
||||
LIBCRTBEGIN= # nothing
|
||||
LIBCRTEND= # nothing
|
||||
LIBC= # nothing
|
||||
|
||||
PRIMARY_LOAD_ADDRESS=0x600
|
||||
SECONDARY_LOAD_ADDRESS=0x10000
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= cdboot
|
||||
SRCS?= cdboot.S
|
||||
|
||||
BINDIR= /usr/mdec
|
||||
BINMODE=444
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
|
||||
LDFLAGS+= -e start
|
||||
CPPFLAGS+= -I. -I${.CURDIR}/../lib -I${S}
|
||||
CPPFLAGS+= -DPRIMARY_LOAD_ADDRESS=${PRIMARY_LOAD_ADDRESS}
|
||||
CPPFLAGS+= -DSECONDARY_LOAD_ADDRESS=${SECONDARY_LOAD_ADDRESS}
|
||||
|
||||
.if ${MACHINE} == "amd64"
|
||||
LDFLAGS+= -m elf_i386
|
||||
AFLAGS+= -m32
|
||||
.endif
|
||||
|
||||
.if !make(obj) && !make(clean) && !make(cleandir)
|
||||
.BEGIN: machine x86
|
||||
.NOPATH: machine x86
|
||||
.endif
|
||||
|
||||
realdepend realall: machine x86
|
||||
CLEANFILES+= machine x86
|
||||
|
||||
machine::
|
||||
-rm -f $@
|
||||
ln -s $S/arch/i386/include $@
|
||||
|
||||
x86::
|
||||
-rm -f $@
|
||||
ln -s $S/arch/x86/include $@
|
||||
|
||||
${OBJS}: machine x86
|
||||
|
||||
CLEANFILES+= ${PROG}.tmp
|
||||
|
||||
${PROG}: ${OBJS}
|
||||
${LD} -o ${PROG}.tmp ${LDFLAGS} -Ttext ${PRIMARY_LOAD_ADDRESS} ${OBJS}
|
||||
@ set -- $$( ${NM} -t d ${PROG}.tmp | grep '\<free_space\>' | sed 's/^0*//' ); \
|
||||
echo "#### There are $$1 free bytes in ${PROG}"
|
||||
${OBJCOPY} -O binary ${PROG}.tmp ${PROG}
|
||||
rm -f ${PROG}.tmp
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,277 @@
|
|||
/* $NetBSD: cdboot.S,v 1.1 2005/06/15 06:38:45 junyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* TODO:
|
||||
* - Support for loading secondary boot loader > 64kB
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
#define BOOT_ADDR 0x7c00
|
||||
#define BLOCK_SIZE 2048 /* Default for ISO 9660 */
|
||||
#define VD_LBA 16 /* LBA of Volume Descriptor (VD) */
|
||||
#define PVD_ADDR 0x1000 /* Where Primary VD is loaded */
|
||||
#define ROOTDIR_ADDR 0x1800 /* Where Root Directory is loaded */
|
||||
#define LOADER_ADDR SECONDARY_LOAD_ADDRESS
|
||||
|
||||
/*
|
||||
* Disk error codes
|
||||
*/
|
||||
#define ERROR_TIMEOUT 0x80
|
||||
|
||||
/*
|
||||
* Volume Descriptor types.
|
||||
*/
|
||||
#define VD_PRIMARY 1
|
||||
#define VD_SUPPLEMENTARY 2
|
||||
#define VD_TERMINATOR 255
|
||||
|
||||
/* Only actually used entries are listed below */
|
||||
|
||||
/*
|
||||
* Format of Primary Volume Descriptor (8.4)
|
||||
*/
|
||||
#define PVD_ROOT_DR 156 /* Offset of Root Directory Record */
|
||||
|
||||
/*
|
||||
* Format of Directory Record (9.1)
|
||||
*/
|
||||
#define DR_LEN 0
|
||||
#define DR_EXTENT 2
|
||||
#define DR_DATA_LEN 10
|
||||
#define DR_NAME_LEN 32
|
||||
#define DR_NAME 33
|
||||
|
||||
.text
|
||||
.code16
|
||||
ENTRY(start)
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %ss
|
||||
movw $BOOT_ADDR, %sp
|
||||
movw %sp, %si
|
||||
movw $start, %di
|
||||
movw $BLOCK_SIZE/2, %cx
|
||||
rep
|
||||
movsw
|
||||
ljmp $0, $real_start
|
||||
|
||||
real_start:
|
||||
movb %dl, boot_drive /* Save boot drive number */
|
||||
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
|
||||
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 */
|
||||
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! */
|
||||
|
||||
panic:
|
||||
hlt
|
||||
jmp panic
|
||||
|
||||
boot_cdrom:
|
||||
movw $str_banner, %si
|
||||
call message
|
||||
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
|
||||
|
||||
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
|
||||
next_entry:
|
||||
cmpb $0, DR_LEN(%bx)
|
||||
jz last_entry
|
||||
movw %bx, %si
|
||||
addw $DR_NAME, %si
|
||||
movb DR_NAME_LEN(%bx), %cl
|
||||
movw $str_loader, %di
|
||||
1:
|
||||
movb (%si), %al
|
||||
cmpb %al, (%di)
|
||||
jnz fail
|
||||
incw %si
|
||||
incw %di
|
||||
decb %cl
|
||||
jnz 1b
|
||||
jmp load_loader
|
||||
fail:
|
||||
addw DR_LEN(%bx), %bx
|
||||
jmp next_entry
|
||||
last_entry:
|
||||
movw $str_no_loader, %si
|
||||
call message
|
||||
jmp panic
|
||||
|
||||
load_loader:
|
||||
movl DR_EXTENT(%bx), %eax
|
||||
movl DR_DATA_LEN(%bx), %edx
|
||||
addl $(BLOCK_SIZE-1), %edx /* Convert file length to */
|
||||
shrl $11, %edx /* ... number of sectors */
|
||||
movb %dl, %dh
|
||||
movl $LOADER_ADDR, %ebx
|
||||
call read_sectors
|
||||
xorl %esi, %esi /* Don't provide boot_params */
|
||||
xorl %edx, %edx
|
||||
movb boot_drive, %dl
|
||||
xorl %ebx, %ebx /* Zero sector number */
|
||||
lcall $LOADER_ADDR/16, $0
|
||||
jmp panic
|
||||
|
||||
/*
|
||||
* Read disk sector(s) into memory
|
||||
*
|
||||
* %eax = LBA of starting sector
|
||||
* %ebx = buffer to store sectors
|
||||
* %dh = number of sectors to read
|
||||
*/
|
||||
read_sectors:
|
||||
pusha
|
||||
movl %eax, edd_lba /* Convert LBA to segment */
|
||||
shrl $4, %ebx
|
||||
movw %bx, edd_segment
|
||||
movb %dh, edd_nsecs
|
||||
movb boot_drive, %dl
|
||||
movw $edd_packet, %si
|
||||
read_again:
|
||||
movb $0x42, %ah
|
||||
int $0x13
|
||||
jc read_fail
|
||||
popa
|
||||
ret
|
||||
read_fail:
|
||||
cmpb $ERROR_TIMEOUT, %ah
|
||||
jz read_again
|
||||
movw $str_read_error, %si
|
||||
call message
|
||||
jmp panic
|
||||
|
||||
/*
|
||||
* For debugging purpose
|
||||
*/
|
||||
put_char:
|
||||
pusha
|
||||
movb $0x0e, %ah
|
||||
movw $0x0001, %bx
|
||||
int $0x10
|
||||
popa
|
||||
ret
|
||||
|
||||
#include <message.S>
|
||||
|
||||
edd_packet:
|
||||
edd_len: .word 16
|
||||
edd_nsecs: .word 0 /* Number of sectors to transfer */
|
||||
edd_offset: .word 0
|
||||
edd_segment: .word 0
|
||||
edd_lba: .quad 0
|
||||
|
||||
wait_count: .byte 6
|
||||
boot_drive: .byte 0
|
||||
|
||||
str_banner: .ascii "\r\nNetBSD/i386 cd9660 Primary Bootstrap"
|
||||
str_crlf: .asciz "\r\n"
|
||||
str_press_key: .asciz "\r\nPress any key to boot from CD"
|
||||
str_dot: .asciz "."
|
||||
str_read_error: .asciz "Can't read CD"
|
||||
str_no_pvd: .asciz "Can't find Primary Volume Descriptor"
|
||||
str_no_loader: .asciz "Can't find /boot"
|
||||
str_loader: .asciz "BOOT.;1"
|
||||
|
||||
/* Used to calculate free bytes */
|
||||
free_space = end - .
|
||||
|
||||
. = start + BLOCK_SIZE
|
||||
end:
|
Loading…
Reference in New Issue