patch-2.4.10 linux/arch/i386/boot/bootsect.S
Next file: linux/arch/i386/boot/compressed/Makefile
Previous file: linux/arch/cris/kernel/ptrace.c
Back to the patch index
Back to the overall index
- Lines: 444
- Date:
Fri Sep 14 14:04:08 2001
- Orig file:
v2.4.9/linux/arch/i386/boot/bootsect.S
- Orig date:
Mon Jan 29 16:19:41 2001
diff -u --recursive --new-file v2.4.9/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
@@ -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@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.
@@ -43,7 +47,7 @@
#ifndef RAMDISK
#define RAMDISK 0
-#endif
+#endif
#ifndef ROOT_RDONLY
#define ROOT_RDONLY 1
@@ -55,14 +59,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
@@ -81,7 +83,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.
@@ -97,52 +99,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
- pushw %di # di = 0x4000-12.
- rep # don't need cld -> done on line 66
- 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 number of sectors/track.
# 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:
@@ -151,30 +130,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
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
@@ -184,23 +189,26 @@
# 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.
+# 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 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, root_dev
@@ -210,46 +218,45 @@
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
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
@@ -257,60 +264,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 # 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
- call print_all # ah = error, al = read
+ pushw %ax # save error code
+ call print_all # %ah = error, %al = read
xorb %ah, %ah
xorb %dl, %dl
int $0x13
@@ -331,13 +342,13 @@
# ret <- %sp
print_all:
- movw $5, %cx # error code + 4 registers
+ 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
+ jae no_reg # see if register name is needed
movw $0xe05 + 'A' - 1, %ax
subb %cl, %al
@@ -347,31 +358,31 @@
movb $':', %al
int $0x10
no_reg:
- addw $2, %bp # next register
- call print_hex # print it
+ addw $2, %bp # next register
+ call print_hex # print it
popw %cx
loop print_loop
ret
print_nl:
- movw $0xe0d, %ax # CR
+ movw $0xe0d, %ax # CR
int $0x10
- movb $0xa, %al # LF
+ movb $0xa, %al # LF
int $0x10
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 $4, %cx # 4 hex digits
+ 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
- daa # in only four instructions!
+ 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
+ daa # in only four instructions!
adc $0x40, %al
daa
int $0x10
@@ -381,6 +392,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
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)