[patch] 2.3.41: 360/720k bootsect booting support..
Chris Noe
stiker en northlink.com
Dom Ene 30 23:23:25 CST 2000
AK's boocode updated to 2.3.41, sprinkled with a few more little
optimizations. Not compile tested though, so beware.
This should go straight into 2.5 if anyone besides nkbj tests it :)
<hint hint>
Chris Noe
(stiker en northlink.com)
diff -u --recursive linux-2.3.41/README linux/README
--- linux-2.3.41/README Sun Jan 9 01:15:48 2000
+++ linux/README Sun Jan 30 21:36:44 2000
@@ -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.41/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- linux-2.3.41/arch/i386/boot/bootsect.S Sun Jan 30 21:41:45 2000
+++ linux/arch/i386/boot/bootsect.S Sun Jan 30 21:38:55 2000
@@ -5,8 +5,12 @@
* modified by Bruce Evans (bde)
* modified by Chris Noe (May 1999) (as86 -> gas)
*
- * bootsect is loaded at 0x7c00 by the bios-startup routines, and moves
- * itself out of the way to address 0x90000, and jumps there.
+ * 360k/720k disk support: Andrzej Krzysztofowicz <ankry en green.mif.pg.gda.pl>
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
*
* bde - should not jump blindly, there may be systems with only 512K low
* memory. Use int 0x12 to get the top of memory, etc.
@@ -56,14 +60,12 @@
.global _start
_start:
-#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
- int $0x3
-#endif
+# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there.
movw $BOOTSEG, %ax
- movw %ax, %ds
+ movw %ax, %ds # %ds = BOOTSEG
movw $INITSEG, %ax
- movw %ax, %es
+ movw %ax, %es # %ax = %es = INITSEG
movw $256, %cx
subw %si, %si
subw %di, %di
@@ -82,7 +84,7 @@
# length of bootsect + length of
# setup + room for stack;
# 12 is disk parm size.
- movw %ax, %ds # ax and es already contain INITSEG
+ movw %ax, %ds # %ax and %es already contain INITSEG
movw %ax, %ss
movw %di, %sp # put stack at INITSEG:0x4000-12.
@@ -98,66 +100,29 @@
#
# High doesn't hurt. Low does.
#
-# Segments are as follows: ds = es = ss = cs - INITSEG, fs = 0,
-# and gs is unused.
+# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
+# and %gs is unused.
- movw %cx, %fs # set fs to 0
- movw $0x78, %bx # fs:bx is parameter table address
+ movw %cx, %fs # %fs = 0
+ movw $0x78, %bx # %fs:%bx is parameter table address
pushw %ds
- ldsw %fs:(%bx), %si # ds:si is source
+ ldsw %fs:(%bx), %si # %ds:%si is source
movb $6, %cl # copy 12 bytes
- cld
- pushw %di # di = 0x4000-12.
- rep
- movsw
+ pushw %di # %di = 0x4000-12.
+ rep # don't worry about cld
+ movsw # already done above
popw %di
popw %ds
movb $36, 0x4(%di) # patch sector count
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,31 +131,56 @@
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 doesn't
+ # 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
- movw %ax, %es # we want to load system (at 0x10000)
+
+# Load the setup-sectors directly after the moved bootblock (at 0x90200).
+# We should know the drive geometry to do it, as setup may exceed first
+# cylinder (for 9-sector 360K and 720K floppies).
+
+ 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
+
+ pushw $SYSSEG
+ popw %es # %es = SYSSEG
call read_it
call kill_motor
call print_nl
@@ -200,72 +190,74 @@
# 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: %cs = %ds = %ss = INITSEG,
+# %es = SYSSEG, %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
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:
ljmp $SETUPSEG, $0
-# This routine loads the system at address 0x10000, making sure
-# 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)
+# 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
+# This routine loads the system at address SYSSEG, making sure
+# no 64kB boundaries are crossed. We try to load it as fast as
+# possible, loading whole tracks whenever we can.
+
read_it:
- movb setup_sects, %al
- incb %al
- movb %al, sread
- movw %es, %ax
+ movw %es, %ax # %es = SYSSEG when called
testw $0x0fff, %ax
-die: jne die # es must be at 64kB boundary
-
- xorw %bx, %bx # bx is starting address within segment
+die: jne die # %es must be at 64kB boundary
+ xorw %bx, %bx # %bx is starting address within segment
rp_read:
-#ifdef __BIG_KERNEL__
- bootsect_kludge = 0x220 # 0x200 (size of bootsector) + 0x20 (offset
- lcall bootsect_kludge # of bootsect_kludge in setup.S)
+#ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge
+ bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the
+ lcall bootsect_kludge # bootsector + bootsect_kludge offset
#else
- movw %es, %ax
+ movw %es, %ax
subw $SYSSEG, %ax
+ movw %bx, %cx
+ shr $4, %cx
+ add %cx, %ax # check offset
#endif
- cmpw syssize, %ax # have we loaded all yet?
+ cmpw syssize, %ax # have we loaded everything yet?
jbe ok1_read
ret
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,60 +265,64 @@
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 # print "." (0x2e) for each track read
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
- call print_all # ah = error, al = read
+ call print_all # %ah = error, %al = read
xorb %ah, %ah
xorb %dl, %dl
int $0x13
@@ -350,8 +346,8 @@
movw $5, %cx # error code + 4 registers
movw %sp, %bp
print_loop:
- pushw %cx # save count left
- call print_nl # nl for readability
+ pushw %cx # save count remaining
+ call print_nl # <-- for readability
cmpb $5, %cl
jae no_reg # see if register name is needed
@@ -377,16 +373,16 @@
ret
# print_hex is for debugging purposes, and prints the word
-# pointed to by ss:bp in hexadecimal.
+# pointed to by %ss:%bp in hexadecimal.
print_hex:
movw $4, %cx # 4 hex digits
- movw (%bp), %dx # load word into dx
+ movw (%bp), %dx # load word into %dx
print_digit:
rolw $4, %dx # rotate to use low 4 bits
- movw $0xe0f, %ax # ah = request
- andb %dl, %al # al = mask for nybble
- addb $0x90, %al # convert al to ascii hex
+ movw $0xe0f, %ax # %ah = request
+ andb %dl, %al # %al = mask for nybble
+ addb $0x90, %al # convert %al to ascii hex
daa # in only four instructions!
adc $0x40, %al
daa
@@ -397,6 +393,7 @@
# This procedure turns off the floppy drive motor, so
# that we enter the kernel in a known state, and
# don't have to worry about it later.
+# NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
kill_motor:
movw $0x3f2, %dx
@@ -409,7 +406,7 @@
msg1: .byte 13, 10
.ascii "Loading"
-# XXX: This is a *very* snug fit.
+# XXX: This is a fairly snug fit.
.org 497
setup_sects: .byte SETUPSECS
diff -u --recursive linux-2.3.41/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- linux-2.3.41/arch/i386/boot/setup.S Thu Jan 6 18:58:02 2000
+++ linux/arch/i386/boot/setup.S Sun Jan 30 21:52:13 2000
@@ -210,8 +210,8 @@
# Move rest of setup code/data to here
movw $2048, %di # four sectors loaded by LILO
subw %si, %si
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %es
+ pushw %cs
+ popw %es # aka SETUPSEG
movw $SYSSEG, %ax
movw %ax, %ds
rep
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo en vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
Más información sobre la lista de distribución Ayuda