wok rev 4504

linux: add floppy boot support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Nov 22 12:46:40 2009 +0100 (2009-11-22)
parents fd85055f79db
children 4b16c8ec84b1
files linux/receipt linux/stuff/bootloader.sh linux/stuff/linux-header-2.6.30.6.u
line diff
     1.1 --- a/linux/receipt	Sun Nov 22 12:40:18 2009 +0100
     1.2 +++ b/linux/receipt	Sun Nov 22 12:46:40 2009 +0100
     1.3 @@ -29,6 +29,7 @@
     1.4  	mkdir slitaz
     1.5  	echo "$WGET_URL" > slitaz/url
     1.6  	cp ../stuff/gztazmod.sh ../stuff/list_modules.sh slitaz
     1.7 +	cp ../stuff/bootloader.sh slitaz
     1.8  	# Misc patches from pascal
     1.9  	while read patch_file; do
    1.10  		echo "$patch_file" >> slitaz/patches
    1.11 @@ -49,6 +50,7 @@
    1.12  aufs2-base.patch
    1.13  aufs2-kbuild.patch
    1.14  aufs2-standalone.patch
    1.15 +$PACKAGE-header-$VERSION.u
    1.16  EOT
    1.17  	make mrproper
    1.18  	cp ../stuff/$PACKAGE-$VERSION-slitaz.config .config
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/linux/stuff/bootloader.sh	Sun Nov 22 12:46:40 2009 +0100
     2.3 @@ -0,0 +1,155 @@
     2.4 +#!/bin/sh
     2.5 +#
     2.6 +# This script creates a floppy image set from a linux bzImage and can merge
     2.7 +# a cmdline and/or one or more initramfs.
     2.8 +# The total size can not exceed 15M because INT 15H function 87H limitations.
     2.9 +#
    2.10 +# (C) 2009 Pascal Bellard - GNU General Public License v3.
    2.11 +
    2.12 +usage()
    2.13 +{
    2.14 +cat <<EOT
    2.15 +Usage: $0 bzImage [--prefix image_prefix] [--cmdline 'args']
    2.16 +       [--format 1440|1680|1720|2880 ] [--initrd initrdfile]...
    2.17 +
    2.18 +Example:
    2.19 +$0 /boot/vmlinuz-2.6.30.6 --cmdline 'rw lang=fr_FR kmap=fr-latin1 laptop autologin' --initrd /boot/rootfs.gz --initrd ./myconfig.gz
    2.20 +EOT
    2.21 +exit 1
    2.22 +}
    2.23 +
    2.24 +KERNEL=""
    2.25 +INITRD=""
    2.26 +CMDLINE=""
    2.27 +PREFIX="floppy"
    2.28 +FORMAT="1440"
    2.29 +while [ -n "$1" ]; do
    2.30 +	case "$1" in
    2.31 +	--cmdline) CMDLINE="$2"; shift;;
    2.32 +	--initrd)  INITRD="$INITRD $2"; shift;;
    2.33 +	--prefix)  PREFIX="$2"; shift;;
    2.34 +	--format)  FORMAT="$2"; shift;;
    2.35 +	*) KERNEL="$1";;
    2.36 +	esac
    2.37 +	shift
    2.38 +done
    2.39 +[ -n "$KERNEL" -a -f "$KERNEL" ] || usage
    2.40 +
    2.41 +# write a 32 bits data
    2.42 +# usage: storelong offset data32 file
    2.43 +storelong()
    2.44 +{
    2.45 +	printf "00000  %02X %02X %02X %02X \n" \
    2.46 +		$(( $2 & 255 )) $(( ($2>>8) & 255 )) \
    2.47 +		$(( ($2>>16) & 255 )) $(( ($2>>24) & 255 )) | \
    2.48 +	hexdump -R | dd bs=1 conv=notrunc of=$3 seek=$(( $1 )) 2> /dev/null
    2.49 +}
    2.50 +
    2.51 +# read a 32 bits data
    2.52 +# usage: getlong offset file
    2.53 +getlong()
    2.54 +{
    2.55 +	dd if=$2 bs=1 skip=$(( $1 )) count=4 2> /dev/null | \
    2.56 +		hexdump -e '"" 1/4 "%d" "\n"'
    2.57 +}
    2.58 +
    2.59 +floppyset()
    2.60 +{
    2.61 +	# bzImage offsets
    2.62 +	SetupSzOfs=497
    2.63 +	SyssizeOfs=500
    2.64 +	CodeAdrOfs=0x214
    2.65 +	RamfsAdrOfs=0x218
    2.66 +	RamfsLenOfs=0x21C
    2.67 +	ArgPtrOfs=0x228
    2.68 +
    2.69 +	# boot+setup address
    2.70 +	SetupBase=0x90000
    2.71 +
    2.72 +	stacktop=0x9E00
    2.73 +
    2.74 +	bs=/tmp/bs$$
    2.75 +
    2.76 +	# Get and patch boot sector
    2.77 +	dd if=$KERNEL bs=512 count=1 of=$bs 2> /dev/null
    2.78 +	uudecode <<EOT | dd of=$bs conv=notrunc 2> /dev/null
    2.79 +begin-base64 644 -
    2.80 +v/Sd/GgAkAcxyQYXify7eACO2cU3sQbzpY7ZiSeMRwKg8X2YQAYfxkX4P/qX
    2.81 +mEEw9jHb6FcBvgACgEwRgMdEJACcA3QO6GYBvigCORxyLkeLHFboQQFfizXo
    2.82 +UgGwIOg+AbAIzRBOmM0WPAh0BZiJBEZGOzV08OgmATwKdd+5GABqAOL8ieaw
    2.83 +D7/0Af5NHLEFtJOJRBywAYlEFJmJVBCJVBhmMdtD0+NLZgMdZtPraAAQB7+A
    2.84 +ACn7nHMCAd9TVjHb6NQAXrkAgLSH/kQczRVbnXfcoRoCSL8cArEJOEQccrAx
    2.85 +wM0T6gAAIJCwRijIvrkB6L0AXesjgPkTcgQ4wXdogP4CcgQ45ndpgP1Qc3Ng
    2.86 +BlJRU5a0AlC5BgBRsQTBxQSwDyHoBJAnFEAn6HMA4u6wIM0QWeK0mM0TYTH2
    2.87 +rZGtkq1QKMh3ArABmDn4cgKJ+FBStALNE1qVXlhynCn3AfHB5gkB8zjBdSaI
    2.88 +yP7GsQE45nUciPS2AP7FPBN1EoD9UHINtQBgvrwB6CUAmM0WYaMEAFJRZo8G
    2.89 +AAAJ/3WeFgewLrQOuwcAzRA8DXUOsArr8bAN6Oz/rAjAdfjDWDoASW5zZXJ0
    2.90 +IG5leHQgZmxvcHB5IGFuZCBwcmVzcyBhbnkga2V5IHRvIGNvbnRpbnVlLgcN
    2.91 +AA==
    2.92 +====
    2.93 +EOT
    2.94 +
    2.95 +	# Get setup
    2.96 +	setupsz=$(getlong $SetupSzOfs $bs)
    2.97 +	setupszb=$(( $setupsz & 255 ))
    2.98 +	dd if=$KERNEL bs=512 skip=1 count=$setupszb 2> /dev/null >> $bs
    2.99 +
   2.100 +	# Store cmdline after setup
   2.101 +	if [ -n "$CMDLINE" ]; then
   2.102 +		echo -n "$CMDLINE" | dd bs=512 count=1 conv=sync 2> /dev/null >> $bs
   2.103 +		storelong ArgPtrOfs $(( $SetupBase + $stacktop )) $bs
   2.104 +	fi
   2.105 +
   2.106 +	# Compute initramfs size
   2.107 +	initrdlen=0
   2.108 +	padding=0
   2.109 +	for i in $( echo $INITRD | sed 's/,/ /' ); do
   2.110 +		[ -s "$i" ] || continue
   2.111 +		initrdlen=$(( $initrdlen + $padding ))
   2.112 +		padding=$(stat -c %s $i)
   2.113 +		initrdlen=$(( $initrdlen + $padding ))
   2.114 +		padding=$(( 4096 - ($padding & 4095) ))
   2.115 +		[ $padding -eq 4096 ] && padding=0
   2.116 +	done
   2.117 +	Ksize=$(( $(getlong $SyssizeOfs $bs)*16 ))
   2.118 +	Kpad=$(( (($Ksize+4095)/4096)*4096 - Ksize ))
   2.119 +	if [ $initrdlen -ne 0 ]; then
   2.120 +		Kbase=$(getlong $CodeAdrOfs $bs)
   2.121 +		storelong $RamfsAdrOfs \
   2.122 +			$(( (0x1000000 - $initrdlen) & 0xFFFF0000 )) $bs
   2.123 +		storelong $RamfsLenOfs $initrdlen $bs
   2.124 +	fi
   2.125 +
   2.126 +	# Output boot sector + setup + cmdline
   2.127 +	dd if=$bs 2> /dev/null
   2.128 +
   2.129 +	# Output kernel code
   2.130 +	dd if=$KERNEL bs=512 skip=$(( $setupszb + 1 )) 2> /dev/null
   2.131 +
   2.132 +	# Pad to next sector
   2.133 +	Kpad=$(( 512 - ($(stat -c %s $KERNEL) & 511) ))
   2.134 +	[ $Kpad -eq 512 ] || dd if=/dev/zero bs=1 count=$Kpad 2> /dev/null
   2.135 +
   2.136 +	# Output initramfs
   2.137 +	padding=0
   2.138 +	for i in $( echo $INITRD | sed 's/,/ /' ); do
   2.139 +		[ -s "$i" ] || continue
   2.140 +		[ $padding -ne 0 ] && dd if=/dev/zero bs=1 count=$padding
   2.141 +		dd if=$i 2> /dev/null
   2.142 +		padding=$(( 4096 - ($(stat -c %s $i) & 4095) ))
   2.143 +		[ $padding -eq 4096 ] && padding=0
   2.144 +	done
   2.145 +
   2.146 +	# Cleanup
   2.147 +	rm -f $bs
   2.148 +}
   2.149 +
   2.150 +floppyset | split -b ${FORMAT}k /dev/stdin floppy$$
   2.151 +i=1
   2.152 +ls floppy$$* | while read file ; do
   2.153 +	output=$PREFIX.$(printf "%03d" $i)
   2.154 +	cat $file /dev/zero | dd bs=1k count=$FORMAT conv=sync of=$output 2> /dev/null
   2.155 +	echo $output
   2.156 +	rm -f $file
   2.157 +	i=$(( $i + 1 ))
   2.158 +done
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/linux/stuff/linux-header-2.6.30.6.u	Sun Nov 22 12:46:40 2009 +0100
     3.3 @@ -0,0 +1,445 @@
     3.4 +--- linux-2.6.30.6/arch/x86/boot/header.S
     3.5 ++++ linux-2.6.30.6/arch/x86/boot/header.S
     3.6 +@@ -6,7 +6,7 @@
     3.7 +  *	Based on bootsect.S and setup.S
     3.8 +  *	modified by more people than can be counted
     3.9 +  *
    3.10 +- *	Rewritten as a common file by H. Peter Anvin (Apr 2007)
    3.11 ++ *	Rewritten Pascal Bellard (Nov 2009)
    3.12 +  *
    3.13 +  * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
    3.14 +  * addresses must be multiplied by 16 to obtain their respective linear
    3.15 +@@ -26,6 +26,8 @@
    3.16 + 
    3.17 + BOOTSEG		= 0x07C0		/* original address of boot-sector */
    3.18 + SYSSEG		= 0x1000		/* historical load address >> 4 */
    3.19 ++INITSEG		= 0x9000		/* boot address >> 4 */
    3.20 ++SETUPSEG	= 0x9020		/* setup address >> 4 */
    3.21 + 
    3.22 + #ifndef SVGA_MODE
    3.23 + #define SVGA_MODE ASK_VGA
    3.24 +@@ -39,53 +41,392 @@
    3.25 + #define ROOT_RDONLY 1
    3.26 + #endif
    3.27 + 
    3.28 ++#define SHOW_REGS	show int13 status & parameters
    3.29 ++#define EDIT_CMDLINE	add kernel command line support
    3.30 ++
    3.31 + 	.code16
    3.32 + 	.section ".bstext", "ax"
    3.33 + 
    3.34 + 	.global bootsect_start
    3.35 + bootsect_start:
    3.36 ++stacktop	= 0x9E00		# in 0x8000 .. 0xA000
    3.37 ++					# with 512 bytes for cmdline
    3.38 ++	movw	$stacktop-12, %di	# stacktop is an arbitrary value >=
    3.39 ++					# length of bootsect + length of
    3.40 ++					# setup + room for stack;
    3.41 ++					# 12 is disk parm size.
    3.42 ++					# gdt will heat 48 more bytes.
    3.43 ++curcx	=	0
    3.44 ++curdx	=	curcx+2
    3.45 ++	cld				# assume nothing
    3.46 ++#ifndef FLOPPY_1440K_ONLY
    3.47 ++limits	=	4
    3.48 ++#endif
    3.49 + 
    3.50 +-	# Normalize the start address
    3.51 +-	ljmp	$BOOTSEG, $start2
    3.52 ++	pushw	$INITSEG
    3.53 ++	popw	%es			# %es = INITSEG
    3.54 ++	xorw	%cx, %cx		# %cx = 0
    3.55 + 
    3.56 +-start2:
    3.57 +-	movw	%cs, %ax
    3.58 +-	movw	%ax, %ds
    3.59 +-	movw	%ax, %es
    3.60 +-	movw	%ax, %ss
    3.61 +-	xorw	%sp, %sp
    3.62 +-	sti
    3.63 +-	cld
    3.64 ++	pushw	%es
    3.65 ++	popw	%ss			# %ss and %es already contain INITSEG
    3.66 ++	movw	%di, %sp		# put stack at INITSEG:stacktop-12.
    3.67 + 
    3.68 +-	movw	$bugger_off_msg, %si
    3.69 ++# Many BIOS's default disk parameter tables will not recognize
    3.70 ++# multi-sector reads beyond the maximum sector number specified
    3.71 ++# in the default diskette parameter tables - this may mean 7
    3.72 ++# sectors in some cases.
    3.73 ++#
    3.74 ++# Since single sector reads are slow and out of the question,
    3.75 ++# we must take care of this by creating new parameter tables
    3.76 ++# (for the first disk) in RAM.  We can set the maximum sector
    3.77 ++# count to 36 - the most we will encounter on an ED 2.88.  
    3.78 ++#
    3.79 ++# High doesn't hurt.  Low does.  Let's use the max: 63
    3.80 ++#
    3.81 ++# Segments are as follows: %es = %ss = INITSEG,
    3.82 ++# %fs and %gs are unused.
    3.83 + 
    3.84 +-msg_loop:
    3.85 +-	lodsb
    3.86 +-	andb	%al, %al
    3.87 +-	jz	bs_die
    3.88 +-	movb	$0xe, %ah
    3.89 +-	movw	$7, %bx
    3.90 ++	movw	$0x78, %bx		# %ds:%bx is parameter table address
    3.91 ++	movw	%cx, %ds		# %ds = 0
    3.92 ++	ldsw	(%bx), %si		# %ds:%si is source
    3.93 ++	movb	$6, %cl			# copy 12 bytes
    3.94 ++	rep				# don't worry about cld
    3.95 ++	movsw				# already done above
    3.96 ++	movw	%cx, %ds		# %ds = 0
    3.97 ++	movw	%sp, (%bx)		# %sp = stacktop-12
    3.98 ++	movw	%es, 2(%bx)
    3.99 ++
   3.100 ++	movb	setup_sects+0x7C00, %al	# read bootsector + setup (%ds = 0)
   3.101 ++	cbw
   3.102 ++	incw	%ax
   3.103 ++
   3.104 ++	pushw	%es
   3.105 ++	popw	%ds			# now %ds = %es = %ss = INITSEG
   3.106 ++	movb	$63, 0x4-12(%di)	# patch sector count, %di = stacktop
   3.107 ++
   3.108 ++	cli
   3.109 ++
   3.110 ++	xchg	%ax, %di		# sector count
   3.111 ++	cbw				# limits = 0
   3.112 ++	incw	%cx			# cylinder 0, sector 1
   3.113 ++	xorb	%dh, %dh		# head 0, current drive
   3.114 ++	xorw	%bx, %bx
   3.115 ++	call	read_first_sectors	# read setup
   3.116 ++
   3.117 ++#define version_offset		0xE
   3.118 ++#define loadflags_offset	0x11
   3.119 ++#define heap_end_ptr_offset	0x24
   3.120 ++
   3.121 ++	movw	$_start,%si
   3.122 ++	orb	$0x80, loadflags_offset(%si)
   3.123 ++	movw	$stacktop-0x200, heap_end_ptr_offset(%si)
   3.124 ++
   3.125 ++	addw	version_offset(%si),%si	# starting protocol 2.00, Kernel 1.3.73
   3.126 ++	call	puts			# show which kernel we are loading
   3.127 ++
   3.128 ++#ifdef	EDIT_CMDLINE
   3.129 ++# The cmdline can be entered and modifed on hot key.
   3.130 ++# Only characters before the cursor are passed to the kernel.
   3.131 ++	movw	$cmd_line_ptr, %si
   3.132 ++	cmpw	%bx,(%si)		# %bx = 7
   3.133 ++	jb	nocmdline
   3.134 ++	incw	%di			# read 1 sector
   3.135 ++	movw	(%si), %bx
   3.136 ++	pushw	%si
   3.137 ++	call	read_sectors
   3.138 ++	popw	%di
   3.139 ++	movw	(%di), %si
   3.140 ++	call	puts
   3.141 ++cmdlp:
   3.142 ++	movb	$32, %al		# clear end of line
   3.143 ++	call	putc			#  with Space
   3.144 ++	movb	$8, %al			#   and BackSpace
   3.145 + 	int	$0x10
   3.146 +-	jmp	msg_loop
   3.147 ++	decw	%si
   3.148 ++cmdget:
   3.149 ++	cbw				# %ah = 0, get keyboard character
   3.150 ++	int	$0x16
   3.151 ++	cmpb	$8, %al			# BackSpace ?
   3.152 ++	je	cmdbs
   3.153 ++	cbw
   3.154 ++	movw	%ax, (%si)		# store end of string too
   3.155 ++	incw	%si
   3.156 ++	incw	%si
   3.157 ++cmdbs:
   3.158 ++	cmpw	(%di), %si		# lower limit is checked
   3.159 ++	je	cmdget			#   but upper limit not
   3.160 ++	call	putc
   3.161 ++	cmpb	$10, %al		# Enter ?
   3.162 ++	jne	cmdlp
   3.163 ++endcmdline:
   3.164 ++	
   3.165 ++nocmdline:
   3.166 ++#endif
   3.167 + 
   3.168 +-bs_die:
   3.169 +-	# Allow the user to press a key, then reboot
   3.170 +-	xorw	%ax, %ax
   3.171 ++# This routine loads the system at address SYSSEG, making sure
   3.172 ++# no 64kB boundaries are crossed. We try to load it as fast as
   3.173 ++# possible, loading whole tracks whenever we can.
   3.174 ++
   3.175 ++	movw	$24, %cx		# allocate 48 bytes in stack
   3.176 ++init_gdt:
   3.177 ++	push	$0			#   initialized with 0
   3.178 ++	loop	init_gdt
   3.179 ++	movw	%sp, %si		# for bootsect_gdt
   3.180 ++	movb	$0x0F, %al		# destination = 0x100000
   3.181 ++	movw	$syssize, %di
   3.182 ++#define type_of_loader_offset	0x1C	/* type_of_loader - syssize */
   3.183 ++	decb	type_of_loader_offset(%di)	# loader type = 0xFF
   3.184 ++	movb	$5, %cl
   3.185 ++initrdlp:
   3.186 ++	movb	$0x93,%ah
   3.187 ++	movw	%ax, 28(%si)		# bootsect_dst_base+2
   3.188 ++	movb	$(SYSSEG/4096), %al	# source = SYSSEG
   3.189 ++	movw	%ax, 20(%si)		# bootsect_src_base+2
   3.190 ++	cwd
   3.191 ++	movw	%dx, 16(%si)		# bootsect_src = 64Kb
   3.192 ++	movw	%dx, 24(%si)		# bootsect_dst = 64Kb
   3.193 ++	xorl	%ebx, %ebx
   3.194 ++	incw	%bx
   3.195 ++	shlw	%cl,%bx
   3.196 ++	decw	%bx
   3.197 ++	addl	(%di),%ebx
   3.198 ++	shrl	%cl, %ebx
   3.199 ++syslp:
   3.200 ++	pushw	$SYSSEG
   3.201 ++	popw	%es
   3.202 ++	movw	$128,%di		# 64Kb
   3.203 ++	subw	%di, %bx		# max 32M > int 15 limit
   3.204 ++	pushf
   3.205 ++	jnc	not_last
   3.206 ++	addw	%bx, %di
   3.207 ++not_last:
   3.208 ++	pushw	%bx
   3.209 ++	pushw	%si
   3.210 ++	xorw	%bx, %bx
   3.211 ++	call	read_sectors
   3.212 ++	popw	%si
   3.213 ++	movw	$0x8000, %cx		# full 64K
   3.214 ++	movb	$0x87, %ah
   3.215 ++	incb	28(%si)			# bootsect_dst_base+2
   3.216 ++	int	$0x15			# max 16M
   3.217 ++	popw	%bx
   3.218 ++	popf
   3.219 ++	ja	syslp
   3.220 ++	movw	ramdisk_image+2,%ax
   3.221 ++	decw	%ax
   3.222 ++	movw	$ramdisk_size,%di
   3.223 ++	movb	$9, %cl
   3.224 ++	cmpb	%al,28(%si)
   3.225 ++	jb	initrdlp
   3.226 ++
   3.227 ++# This procedure turns off the floppy drive motor, so
   3.228 ++# that we enter the kernel in a known state, and
   3.229 ++# don't have to worry about it later.
   3.230 ++
   3.231 ++kill_motor:
   3.232 ++	xorw	%ax, %ax		# reset FDC
   3.233 ++	int	$0x13
   3.234 ++
   3.235 ++# After that (everything loaded), we jump to the setup-routine
   3.236 ++# loaded directly after the bootblock:
   3.237 ++# Segments are as follows: %ds = %ss = INITSEG
   3.238 ++
   3.239 ++	ljmp	$SETUPSEG, $0
   3.240 ++
   3.241 ++# read_sectors reads %di sectors into %es:0 buffer.
   3.242 ++# %es:0 is updated to the next memory location.
   3.243 ++# First, sectors are read sector by sector until
   3.244 ++# sector per track count is known. Then they are
   3.245 ++# read track by track.
   3.246 ++# Assume no error on first track.
   3.247 ++
   3.248 ++#define FLOPPY_CYLINDERS	80	/* 80 cylinders minimum */
   3.249 ++#define FLOPPY_HEADS		2	/* 2 heads minimum */
   3.250 ++#define FLOPPY_SECTORS		18	/* 18 sectors minimum */
   3.251 ++
   3.252 ++#ifdef SHOW_REGS
   3.253 ++print_loop:
   3.254 ++	movb	$0x6 + 'A' - 1, %al
   3.255 ++	subb	%cl, %al
   3.256 ++	movw	$regs, %si		# caller %si is saved
   3.257 ++	call	putcs			# putc(%al) + puts(%si)
   3.258 ++# it will print out all of the registers.
   3.259 ++	popw	%bp			# load word into %bp
   3.260 ++	jmp	print_all		# print %bp (status)
   3.261 ++#endif
   3.262 ++check_limits:
   3.263 ++#ifndef FLOPPY_1440K_ONLY
   3.264 ++	cmpb	$FLOPPY_SECTORS+1, %cl	# 18 sectors minimum
   3.265 ++	jb	check_head
   3.266 ++        cmpb    %al, %cl		# max sector known ?
   3.267 ++        ja	next_head		#   no -> store it
   3.268 ++check_head:
   3.269 ++	cmpb	$FLOPPY_HEADS, %dh	# 2 heads minimum
   3.270 ++	jb	check_cylinder
   3.271 ++        cmpb    %ah, %dh		# max head known ?
   3.272 ++        ja	next_cylinder		#   no -> store it
   3.273 ++check_cylinder:
   3.274 ++	cmpb	$FLOPPY_CYLINDERS, %ch	# 80 cylinders minimum
   3.275 ++	jae	next_floppy
   3.276 ++#endif
   3.277 ++	pushaw
   3.278 ++#ifdef SHOW_REGS
   3.279 ++	pushw	%es			# print %es (named EX)
   3.280 ++	pushw	%dx			# print %dx
   3.281 ++	pushw	%cx			# print %cx
   3.282 ++	pushw	%bx			# print %bx
   3.283 ++#ifndef FLOPPY_1440K_ONLY
   3.284 ++	xchgw	%ax, %si
   3.285 ++#endif
   3.286 ++	movb	$2,%ah
   3.287 ++	pushw	%ax			# print %ax
   3.288 ++	movw	$6,%cx
   3.289 ++print_all:
   3.290 ++	pushw	%cx			# save count remaining
   3.291 ++	movb	$4, %cl			# 4 hex digits
   3.292 ++print_digit:
   3.293 ++	rolw	$4, %bp			# rotate to use low 4 bits
   3.294 ++	movb	$0x0f, %al
   3.295 ++	andw	%bp, %ax		# %al = mask for nybble
   3.296 ++	addb	$0x90, %al		# convert %al to ascii hex
   3.297 ++	daa				# in only four instructions!
   3.298 ++	adcb	$0x40, %al
   3.299 ++	daa
   3.300 ++	call	putc			# set %ah and %bx
   3.301 ++	loop	print_digit
   3.302 ++	movb	$0x20, %al		# SPACE
   3.303 ++	int	$0x10
   3.304 ++	popw	%cx
   3.305 ++	loop	print_loop
   3.306 ++#endif
   3.307 ++	cbw				# %ah = 0
   3.308 ++        int     $0x13			# reset controler
   3.309 ++	popaw
   3.310 ++read_sectorslp:
   3.311 ++	xorw	%si, %si
   3.312 ++	lodsw
   3.313 ++	xchgw	%ax,%cx			# restore disk state
   3.314 ++	lodsw
   3.315 ++	xchgw	%ax,%dx
   3.316 ++#ifndef FLOPPY_1440K_ONLY
   3.317 ++#   al is last sector+1
   3.318 ++#   ah is last cylinder+1
   3.319 ++	lodsw
   3.320 ++#endif
   3.321 ++#ifndef FLOPPY_1440K_ONLY
   3.322 ++        pushw   %ax			# limits
   3.323 ++	subb	%cl, %al		# sectors remaining in track
   3.324 ++	ja	tolastsect
   3.325 ++	movb	$1, %al			# 1 sector mini
   3.326 ++tolastsect:
   3.327 ++#else
   3.328 ++	mov	$FLOPPY_SECTORS+1, %al
   3.329 ++	subb	%cl, %al		# sectors remaining in track
   3.330 ++#endif
   3.331 ++	cbw
   3.332 ++	cmpw	%di, %ax
   3.333 ++	jb	more1trk
   3.334 ++	movw	%di, %ax		# sectors to read
   3.335 ++more1trk:
   3.336 ++	pushw	%ax			# save context
   3.337 ++	pushw	%dx			# some bios break dx...
   3.338 ++	movb	$2, %ah			# cmd: read chs
   3.339 ++        int     $0x13
   3.340 ++	popw	%dx
   3.341 ++	xchgw	%ax, %bp		# status
   3.342 ++#ifndef FLOPPY_1440K_ONLY
   3.343 ++	popw	%si			# save %ax
   3.344 ++        popw    %ax			# limits
   3.345 ++#else
   3.346 ++	popw	%ax			# restore context
   3.347 ++#endif
   3.348 ++	jc	check_limits
   3.349 ++#ifndef FLOPPY_1440K_ONLY
   3.350 ++	subw	%si,%di			# update sector counter
   3.351 ++	addw	%si,%cx			# next sector
   3.352 ++	shlw	$9,%si
   3.353 ++	addw	%si,%bx			# next location
   3.354 ++#else
   3.355 ++	subw	%ax,%di			# update sector counter
   3.356 ++	addw	%ax,%cx			# next sector
   3.357 ++	addw	%ax,%ax
   3.358 ++	addb	%al,%bh			# next location
   3.359 ++#endif
   3.360 ++#ifndef FLOPPY_1440K_ONLY
   3.361 ++        cmpb    %al,%cl			# reach sector limit ?
   3.362 ++        jne     bdendlp
   3.363 ++next_head:
   3.364 ++        movb    %cl,%al
   3.365 ++#else
   3.366 ++        cmpb    $FLOPPY_SECTORS+1,%cl	# reach sector limit ?
   3.367 ++        jne     bdendlp
   3.368 ++#endif
   3.369 ++        incb    %dh			# next head
   3.370 ++        movb    $1,%cl			# first sector
   3.371 ++#ifndef FLOPPY_1440K_ONLY
   3.372 ++        cmpb    %ah, %dh		# reach head limit ?
   3.373 ++        jne     bdendlp
   3.374 ++next_cylinder:
   3.375 ++        movb    %dh,%ah
   3.376 ++#else
   3.377 ++        cmpb    %cl,%dh			# reach head limit ?
   3.378 ++        je	bdendlp
   3.379 ++#endif
   3.380 ++        movb    $0,%dh			# first head
   3.381 ++# NOTE : support 256 cylinders max
   3.382 ++        incb    %ch			# next cylinder
   3.383 ++#ifndef FLOPPY_1440K_ONLY
   3.384 ++	cmpb	$FLOPPY_SECTORS+1,%al	# 1.44M floppy ?
   3.385 ++        jne	bdendlp
   3.386 ++#endif
   3.387 ++        cmpb    $FLOPPY_CYLINDERS,%ch	# reach cylinder limit ?
   3.388 ++        jb	bdendlp
   3.389 ++next_floppy:
   3.390 ++	movb	$0,%ch			# first cylinder
   3.391 ++	pushaw
   3.392 ++	movw	$swap_floppy,%si
   3.393 ++	call	puts
   3.394 ++	cbw				# %ah = 0, get keyboard character
   3.395 + 	int	$0x16
   3.396 +-	int	$0x19
   3.397 ++	popaw
   3.398 ++bdendlp:
   3.399 ++read_first_sectors:
   3.400 ++#ifndef FLOPPY_1440K_ONLY
   3.401 ++	movw	%ax, limits
   3.402 ++#endif
   3.403 ++	pushw	%dx
   3.404 ++	pushw	%cx
   3.405 ++	popl	curcx			# save disk state
   3.406 ++read_sectors:
   3.407 ++	orw	%di,%di
   3.408 ++        jne	read_sectorslp
   3.409 ++	pushw	%ss
   3.410 ++	popw	%es			# restore es
   3.411 ++	movb	$0x2e, %al 		# loading... message 2e = .
   3.412 ++putc:
   3.413 ++	movb	$0xe, %ah
   3.414 ++	movw	$7, %bx			#   one dot each 64k
   3.415 ++ 	int	$0x10
   3.416 ++	cmp	$0xd, %al		# CR ?
   3.417 ++	jne	return
   3.418 ++	movb	$0xa, %al		# LF
   3.419 ++	jmp	putc
   3.420 + 
   3.421 +-	# int 0x19 should never return.  In case it does anyway,
   3.422 +-	# invoke the BIOS reset code...
   3.423 +-	ljmp	$0xf000,$0xfff0
   3.424 ++puts:
   3.425 ++	movb	$0xd, %al		# CR
   3.426 ++putcs:
   3.427 ++	call	putc
   3.428 ++	lodsb
   3.429 ++	orb	%al,%al			# end of string is \0
   3.430 ++	jnz	putcs
   3.431 ++return:
   3.432 ++	ret
   3.433 + 
   3.434 +-	.section ".bsdata", "a"
   3.435 +-bugger_off_msg:
   3.436 +-	.ascii	"Direct booting from floppy is no longer supported.\r\n"
   3.437 +-	.ascii	"Please use a boot loader program instead.\r\n"
   3.438 +-	.ascii	"\n"
   3.439 +-	.ascii	"Remove disk and press any key to reboot . . .\r\n"
   3.440 +-	.byte	0
   3.441 ++regs:	.asciz	"X:"
   3.442 + 
   3.443 ++swap_floppy:
   3.444 ++	.ascii	"Insert next floppy and press any key to continue."
   3.445 ++	.byte	7,13,0
   3.446 + 
   3.447 + 	# Kernel attributes; used by setup.  This is part 1 of the
   3.448 + 	# header, from the old boot sector.