Home | History | Annotate | Line # | Download | only in cdboot
cdboot.S revision 1.1
      1 /*	$NetBSD: cdboot.S,v 1.1 2005/06/15 06:38:45 junyoung Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2005 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Bang Jun-Young.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * This is a primary boot loader that loads a secondary boot loader
     41  * directly from CD without performing floppy/hard disk emulation as
     42  * described by the El Torito specification.
     43  *
     44  * TODO:
     45  *  - Support for loading secondary boot loader > 64kB
     46  */
     47 
     48 #include <machine/asm.h>
     49 
     50 #define BOOT_ADDR	0x7c00
     51 #define BLOCK_SIZE	2048		/* Default for ISO 9660 */
     52 #define VD_LBA		16		/* LBA of Volume Descriptor (VD) */
     53 #define PVD_ADDR	0x1000		/* Where Primary VD is loaded */
     54 #define ROOTDIR_ADDR	0x1800		/* Where Root Directory is loaded */
     55 #define LOADER_ADDR	SECONDARY_LOAD_ADDRESS
     56 
     57 /*
     58  * Disk error codes
     59  */
     60 #define ERROR_TIMEOUT	0x80
     61 
     62 /*
     63  * Volume Descriptor types.
     64  */
     65 #define VD_PRIMARY		1
     66 #define VD_SUPPLEMENTARY	2
     67 #define VD_TERMINATOR		255
     68 
     69 /* Only actually used entries are listed below */
     70 
     71 /*
     72  * Format of Primary Volume Descriptor (8.4)
     73  */
     74 #define PVD_ROOT_DR	156	/* Offset of Root Directory Record */
     75 
     76 /*
     77  * Format of Directory Record (9.1)
     78  */
     79 #define DR_LEN		0
     80 #define DR_EXTENT	2
     81 #define DR_DATA_LEN	10
     82 #define DR_NAME_LEN	32
     83 #define DR_NAME		33
     84 
     85 	.text
     86 	.code16
     87 ENTRY(start)
     88 	xorw	%ax, %ax
     89 	movw	%ax, %ds
     90 	movw	%ax, %es
     91 	movw	%ax, %ss
     92 	movw	$BOOT_ADDR, %sp
     93 	movw	%sp, %si
     94 	movw	$start, %di
     95 	movw	$BLOCK_SIZE/2, %cx
     96 	rep
     97 	movsw
     98 	ljmp	$0, $real_start
     99 
    100 real_start:
    101 	movb	%dl, boot_drive		/* Save boot drive number */
    102 	movw	$str_press_key, %si
    103 	call	message
    104 next_second:
    105 	movw	$str_dot, %si
    106 	call	message
    107 	decb	wait_count
    108 	jz	boot_hard_disk
    109 	xorb	%ah, %ah		/* Get system time */
    110 	int	$0x1a
    111 	movw	%dx, %di		/* %cx:%dx = number of clock ticks */
    112 	addw	$19, %di		/* 19 ~= 18.2 Hz */
    113 wait_key:
    114 	movb	$1, %ah			/* Check for keystroke */
    115 	int	$0x16
    116 	jz	not_avail		/* ZF clear if keystroke available */
    117 	xorb	%ah, %ah		/* Read key to flush keyboard buf */
    118 	int	$0x16
    119 	jmp	boot_cdrom
    120 not_avail:
    121 	xorb	%ah, %ah		/* Get system time */
    122 	int	$0x1a
    123 	cmpw	%dx, %di		/* Compare with saved time */
    124 	jnz	wait_key
    125 	jmp	next_second
    126 
    127 boot_hard_disk:
    128 	movw	$str_crlf, %si
    129 	call	message
    130 	movw	$0x0201, %ax		/* %al = number of sectors to read */
    131 	movw	$BOOT_ADDR, %bx		/* %es:%bx = data buffer */
    132 	movw	$0x0001, %cx		/* %ch = low 8 bits of cylinder no */
    133 					/* %cl = high 2 bits of cyl no & */
    134 					/*       sector number */
    135 	movw	$0x0080, %dx		/* %dh = head number */
    136 					/* %dl = disk number */
    137 	int	$0x13			/* Read MBR into memory */
    138 	jc	panic			/* CF set on error */
    139 	movw	%cs, %ax		/* Restore initial state */
    140 	movw	%ax, %ds
    141 	movw	%ax, %es
    142 	movw	$0x0080, %dx		/* %dl = boot drive number */
    143 	jmp	$0, $BOOT_ADDR		/* Jump to MBR! */
    144 
    145 panic:
    146 	hlt
    147 	jmp	panic
    148 
    149 boot_cdrom:
    150 	movw	$str_banner, %si
    151 	call	message
    152 	movl	$VD_LBA, %eax
    153 next_block:
    154 	movb	$1, %dh			/* Number of sectors to read */
    155 	movl	$PVD_ADDR, %ebx
    156 	call	read_sectors
    157 	cmpb	$VD_PRIMARY, (%bx)	/* Is it Primary Volume Descriptor? */
    158 	jz	pvd_found
    159 	incl	%eax
    160 	cmpb	$VD_TERMINATOR, (%bx)
    161 	jnz	next_block
    162 	movw	$str_no_pvd, %si
    163 	call	message
    164 	jmp	panic
    165 
    166 pvd_found:
    167 	movw	$PVD_ADDR+PVD_ROOT_DR, %bx
    168 	movl	DR_EXTENT(%bx), %eax	/* LBA of the root directory */
    169 	movl	DR_DATA_LEN(%bx), %edx
    170 	shrl	$11, %edx		/* Convert to number of sectors */
    171 	movb	%dl, %dh		/*  ... and load it to %dh */
    172 	movl	$ROOTDIR_ADDR, %ebx
    173 	call	read_sectors
    174 next_entry:
    175 	cmpb	$0, DR_LEN(%bx)
    176 	jz	last_entry
    177 	movw	%bx, %si
    178 	addw	$DR_NAME, %si
    179 	movb	DR_NAME_LEN(%bx), %cl
    180 	movw	$str_loader, %di
    181 1:
    182 	movb	(%si), %al
    183 	cmpb	%al, (%di)
    184 	jnz	fail
    185 	incw	%si
    186 	incw	%di
    187 	decb	%cl
    188 	jnz	1b
    189 	jmp	load_loader
    190 fail:
    191 	addw	DR_LEN(%bx), %bx
    192 	jmp	next_entry
    193 last_entry:
    194 	movw	$str_no_loader, %si
    195 	call	message
    196 	jmp	panic
    197 
    198 load_loader:
    199 	movl	DR_EXTENT(%bx), %eax
    200 	movl	DR_DATA_LEN(%bx), %edx
    201 	addl	$(BLOCK_SIZE-1), %edx	/* Convert file length to */
    202 	shrl	$11, %edx		/*  ... number of sectors */
    203 	movb	%dl, %dh
    204 	movl	$LOADER_ADDR, %ebx
    205 	call	read_sectors
    206 	xorl	%esi, %esi		/* Don't provide boot_params */
    207 	xorl	%edx, %edx
    208 	movb	boot_drive, %dl
    209 	xorl	%ebx, %ebx		/* Zero sector number */
    210 	lcall	$LOADER_ADDR/16, $0
    211 	jmp	panic
    212 
    213 /*
    214  * Read disk sector(s) into memory
    215  *
    216  * %eax = LBA of starting sector
    217  * %ebx = buffer to store sectors
    218  * %dh = number of sectors to read
    219  */
    220 read_sectors:
    221 	pusha
    222 	movl	%eax, edd_lba		/* Convert LBA to segment */
    223 	shrl	$4, %ebx
    224 	movw	%bx, edd_segment
    225 	movb	%dh, edd_nsecs
    226 	movb	boot_drive, %dl
    227 	movw	$edd_packet, %si
    228 read_again:
    229 	movb	$0x42, %ah
    230 	int	$0x13
    231 	jc	read_fail
    232 	popa
    233 	ret
    234 read_fail:
    235 	cmpb	$ERROR_TIMEOUT, %ah
    236 	jz	read_again
    237 	movw	$str_read_error, %si
    238 	call	message
    239 	jmp	panic
    240 
    241 /*
    242  * For debugging purpose
    243  */
    244 put_char:
    245 	pusha
    246 	movb	$0x0e, %ah
    247 	movw	$0x0001, %bx
    248 	int	$0x10
    249 	popa
    250 	ret
    251 
    252 #include <message.S>
    253 
    254 edd_packet:
    255 edd_len:	.word	16
    256 edd_nsecs:	.word	0		/* Number of sectors to transfer */
    257 edd_offset:	.word	0
    258 edd_segment:	.word	0
    259 edd_lba:	.quad	0
    260 
    261 wait_count:	.byte	6
    262 boot_drive:	.byte	0
    263 
    264 str_banner:	.ascii	"\r\nNetBSD/i386 cd9660 Primary Bootstrap"
    265 str_crlf:	.asciz	"\r\n"
    266 str_press_key:	.asciz	"\r\nPress any key to boot from CD"
    267 str_dot:	.asciz	"."
    268 str_read_error:	.asciz	"Can't read CD"
    269 str_no_pvd:	.asciz	"Can't find Primary Volume Descriptor"
    270 str_no_loader:	.asciz	"Can't find /boot"
    271 str_loader:	.asciz	"BOOT.;1"
    272 
    273 /* Used to calculate free bytes */
    274 free_space = end - .
    275 
    276 	. = start + BLOCK_SIZE
    277 end:
    278