[patch] [RFT] 360k/720k diskette booting and bootcode optimizations

Chris Noe (stiker@northlink.com)
Thu, 25 Nov 1999 13:08:54 -0500 (EST)


Thanks to this patch courtesy of Andrzej Krzysztofowicz
<ankry@green.mif.pg.gda.pl>, we now have the ability to boot from 360k
(must be a tiny kernel though..) and 720k diskettes with the simple
loader.

Please give this patch a thorough run through (using make [bz]disk) with
older BIOS' and obscure disk sizes.

Chris Noe
(stiker@northlink.com)

diff -u --recursive linux-2.3.29/README linux/README
--- linux-2.3.29/README Wed Nov 24 23:32:11 1999
+++ linux/README Wed Nov 24 23:31:56 1999
@@ -197,10 +197,7 @@

For some, this is on a floppy disk, in which case you can "cp
/usr/src/linux/arch/i386/boot/zImage /dev/fd0" to make a bootable
- floppy. Please note that you can not boot a kernel by
- directly dumping it to a 720k double-density 3.5" floppy. In this
- case, it is highly recommended that you install LILO on your
- double-density boot floppy or switch to high-density floppies.
+ floppy.

If you boot Linux from the hard drive, chances are you use LILO which
uses the kernel image as specified in the file /etc/lilo.conf. The
diff -u --recursive linux-2.3.29/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- linux-2.3.29/arch/i386/boot/bootsect.S Wed Nov 24 23:32:11 1999
+++ linux/arch/i386/boot/bootsect.S Wed Nov 24 23:32:55 1999
@@ -116,48 +116,12 @@
movw %di, %fs:(%bx)
movw %es, %fs:2(%bx)

-# Load the setup-sectors directly after the bootblock.
-# Note that 'es' is already set up.
-# Also, cx = 0 from rep movsw above.
-
-load_setup:
- xorb %ah, %ah # reset FDC
- xorb %dl, %dl
- int $0x13
- xorw %dx, %dx # drive 0, head 0
- movb $0x02, %cl # sector 2, track 0
- movw $0x0200, %bx # address = 512, in INITSEG
- movb $0x02, %ah # service 2, "read sector(s)"
- movb setup_sects, %al # (assume all on head 0, track 0)
- int $0x13 # read it
- jnc ok_load_setup # ok - continue
-
- pushw %ax # dump error code
- call print_nl
- movw %sp, %bp
- call print_hex
- popw %ax
- jmp load_setup
-
-ok_load_setup:
# Get disk drive parameters, specifically nr of sectors/track.

-#if 0
-
-# bde - the Phoenix BIOS manual says function 0x08 only works for fixed
-# disks. It doesn't work for one of my BIOS's (1987 Award). It was
-# fatal not to check the error code.
-
- xorb %dl, %dl
- movb $0x08, %ah # AH=8 is get drive parameters
- int $0x13
- xorb %ch, %ch
-
-#else
-
# It seems that there is no BIOS call to get the number of sectors.
# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
# can be read, 15 if sector 15 can be read. Otherwise guess 9.
+# Note that %cx = 0 from rep movsw above.

movw $disksizes, %si # table of sizes to try
probe_loop:
@@ -166,30 +130,59 @@
movw %ax, sectors
cmpw $disksizes+4, %si
jae got_sectors # if all else fails, try 9
-
- xchgw %cx, %ax # cx = track and sector
+
+ xchgw %cx, %ax # %cx = track and sector
xorw %dx, %dx # drive 0, head 0
- xorb %bl, %bl
- movb setup_sects, %bh
- incb %bh
- shlb %bh # address after setup (es = cs)
+ movw $0x0200, %bx # address = 512, in INITSEG (%es = %cs)
movw $0x0201, %ax # service 2, 1 sector
int $0x13
jc probe_loop # try next value
-#endif

got_sectors:
- movw $INITSEG, %ax
- movw %ax, %es # set up es
movb $0x03, %ah # read cursor pos
xorb %bh, %bh
int $0x10
movw $9, %cx
- movw $0x0007, %bx # page 0, attribute 7 (normal)
- movw $msg1, %bp
- movw $0x1301, %ax # write string, move cursor
+ movb $0x07, %bl # page 0, attribute 7 (normal)
+ # %bh is set above; int10 do not
+ # modify it
+ movw $msg1, %bp
+ movw $0x1301, %ax # write string, move cursor
int $0x10 # tell the user we're loading..
- movw $SYSSEG, %ax # ok, we've written the message, now
+
+# Load the setup-sectors directly after the mooved bootblock (at 0x90200).
+# We should know the drive geometry to do it, as setup may excede first
+# cylinder (for 9-sector 360K and 720K floppies).
+
+# Note that %es is already set up to $INITSEG.
+
+ movw $0x0001, %ax # set sread (sector-to-read) to 1 as
+ movw $sread, %si # the boot sector has already been read)
+ movw %ax, (%si)
+
+ xorw %ax, %ax # reset FDC
+ xorb %dl, %dl
+ int $0x13
+ movw $0x0200, %bx # address = 512, in INITSEG
+next_step:
+ movb setup_sects, %al #
+ movw sectors, %cx #
+ subw (%si), %cx # (%si) = sread
+ cmpb %cl, %al
+ jbe no_cyl_crossing
+ movw sectors, %ax
+ subw (%si), %ax # (%si) = sread
+no_cyl_crossing:
+ call read_track
+ pushw %ax # save it
+ call set_next # set %bx properly; it uses ax,cx,dx
+ popw %ax # restore
+ subb %al, setup_sects # rest - for next step
+ jnz next_step
+
+# es is still set to INITSEG
+
+ movw $SYSSEG, %ax # now
movw %ax, %es # we want to load system (at 0x10000)
call read_it
call kill_motor
@@ -200,26 +193,30 @@
# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
# depending on the number of sectors we pretend to know we have.

- movw %cs:root_dev, %ax
+# Segments are as follows: %ds=%ss=%cs - INITSEG,
+# %es - segment containing end of kernel code
+# %fs = 0, %gs is unused.
+
+ movw root_dev, %ax
orw %ax, %ax
jne root_defined
-
- movw %cs:sectors, %bx
+
+ movw sectors, %bx
movw $0x0208, %ax # /dev/ps0 - 1.2Mb
cmpw $15, %bx
je root_defined
-
+
movb $0x1c, %al # /dev/PS0 - 1.44Mb
- cmpw $18, %bx
+ cmp $18, %bx
je root_defined
-
+
movb $0x20, %al # /dev/fd0H2880 - 2.88Mb
cmpw $36, %bx
je root_defined
-
+
movb $0, %al # /dev/fd0 - autodetect
root_defined:
- movw %ax, %cs:root_dev
+ movw %ax, root_dev

# After that (everything loaded), we jump to the setup-routine
# loaded directly after the bootblock:
@@ -230,16 +227,15 @@
# no 64kB boundaries are crossed. We try to load it as fast as
# possible, loading whole tracks whenever we can.

-# es = starting address segment (normally 0x1000)
+# %es = starting address segment (normally 0x1000)
+
+# These variables are addressed via %si register as it gives shorter code.

sread: .word 0 # sectors read of current track
head: .word 0 # current head
track: .word 0 # current track

read_it:
- movb setup_sects, %al
- incb %al
- movb %al, sread
movw %es, %ax
testw $0x0fff, %ax
die: jne die # es must be at 64kB boundary
@@ -252,6 +248,9 @@
#else
movw %es, %ax
subw $SYSSEG, %ax
+ movw %bx, %cx
+ shr $4, %cx
+ add %cx, %ax # check also offset
#endif
cmpw syssize, %ax # have we loaded all yet?
jbe ok1_read
@@ -260,12 +259,12 @@

ok1_read:
movw sectors, %ax
- subw sread, %ax
+ subw (%si), %ax # (%si) = sread
movw %ax, %cx
shlw $9, %cx
addw %bx, %cx
jnc ok2_read
-
+
je ok2_read

xorw %ax, %ax
@@ -273,56 +272,61 @@
shrw $9, %ax
ok2_read:
call read_track
- movw %ax, %cx
- addw sread, %ax
- cmpw sectors, %ax
- jne ok3_read
-
- movw $1, %ax
- subw head, %ax
- jne ok4_read
-
- incw track
-ok4_read:
- movw %ax, head
- xorw %ax, %ax
-ok3_read:
- movw %ax, sread
- shlw $9, %cx
- addw %cx, %bx
- jnc rp_read
-
- movw %es, %ax
- addb $0x10, %ah
- movw %ax, %es
- xorw %bx, %bx
+ call set_next
jmp rp_read

read_track:
pusha
pusha
- movw $0xe2e, %ax # loading... message 2e = .
+ movw $0xe2e, %ax # loading... message 2e = .
movw $7, %bx
int $0x10
popa
- movw track, %dx
- movw sread, %cx
+
+# Accessing head, track, sread via %si gives shorter code.
+
+ movw 4(%si), %dx # 4(%si) = track
+ movw (%si), %cx # (%si) = sread
incw %cx
movb %dl, %ch
- movw head, %dx
+ movw 2(%si), %dx # 2(%si) = head
movb %dl, %dh
andw $0x0100, %dx
movb $2, %ah
- pushw %dx # save for error dump
+ pushw %dx # save for error dump
pushw %cx
pushw %bx
pushw %ax
int $0x13
jc bad_rt
-
+
addw $8, %sp
popa
ret
+
+set_next:
+ movw %ax, %cx
+ addw (%si), %ax # (%si) = sread
+ cmp sectors, %ax
+ jne ok3_set
+ movw $0x0001, %ax
+ xorw %ax, 2(%si) # change head
+ jne ok4_set
+ incw 4(%si) # next track
+ok4_set:
+ xorw %ax, %ax
+ok3_set:
+ movw %ax, (%si) # set sread
+ shlw $9, %cx
+ addw %cx, %bx
+ jnc set_next_fin
+ movw %es, %ax
+ addb $0x10, %ah
+ movw %ax, %es
+ xorw %bx, %bx
+set_next_fin:
+ ret
+

bad_rt:
pushw %ax # save error code

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/