bootsect.c and DD floppies

Andrzej Krzysztofowicz (ankry@green.mif.pg.gda.pl)
Tue, 2 Nov 1999 15:14:43 +0100 (CET)


Hi,
I enclose the patch for 2.3.2[45] bootsect.S which:
- enables loading each kernel from a 9-sector formatted floppy (360K/720K)
independently on setup size (original bootsect loads it if
size of setup <= 4kB; with this patch included setup may grow even to
100kB...)
- makes it more compact for future purposes (32bit syssize ?) - now it
leaves 19/27 spare bytes for zImage/bzImage.

Modifications base on assumption that BIOS calls int10/int13 does not
modify registers that they should not (cs,ds; bx for int10/function 03)
and include:

a) removed not necessary segment prefixes (%cx:...),
b) uses same code for loading setup that is used later for loading compressed
kernel (slightly modified comparing to original),
c) loading setup moved after geometry detection (necessary for loading setup
from more than a single track)
d) accessing reading position (sread/head/track) using %si register -
it gives shorter code (1-2 bytes per statement)

I've tested it loading 2.0.23/24 [b]zImage from 360K and 1.44M floppies
on different machines (AMI, Award, Phoenix BIOSes). However, it may still
need more testing with other BIOSes/hardware...

Plase, mail me your opinion if it is worth to be included (maybe only some
parts of it) in the 2.3 tree in the future ?

The patch is also available at:
ftp://rudy.mif.pg.gda.pl/pub/People/ankry/linux-patches/2.3/

Regards
Andrzej

************************************************************************
diff -u --recursive 2.3.25-1/README linux/README
--- 2.3.25-1/README Thu Jul 1 19:54:08 1999
+++ linux/README Fri Oct 29 22:29:21 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 2.3.25-1/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- 2.3.25-1/arch/i386/boot/bootsect.S Sat Oct 30 00:48:47 1999
+++ linux/arch/i386/boot/bootsect.S Fri Oct 29 22:04:40 1999
@@ -116,30 +116,6 @@
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
@@ -158,6 +134,7 @@
# 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 +143,60 @@
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 +207,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 +241,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
@@ -251,6 +261,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
@@ -259,12 +272,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
@@ -272,56 +285,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
************************************************************************

-- 
=======================================================================
  Andrzej M. Krzysztofowicz               ankry@mif.pg.gda.pl
  tel.  (0-58) 347 14 61
Wydz.Fizyki Technicznej i Matematyki Stosowanej Politechniki Gdanskiej

- 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/