Commit 72574bb3 authored by H. Peter Anvin's avatar H. Peter Anvin Committed by Linus Torvalds

[PATCH] bootsect removal

This is the "boot sector removal" patch for i386 updated for Linux
2.5.63-bk7.  The only change against the 2.5.59 version is that the
FDOPTS Makefile variable, which lets one create a floppy image with
arbitrary kernel options, has been merged from the x86-64 version, and
the comments have been updated.

The patch removes the in-kernel boot sector, which these days rarely
work correctly (it only supports up to 1 MB kernels, and only work on
legacy floppies -- not on IDE or USB devices, nor on any kind of
emulated devices like El Torito), replaces it with a placeholder stub,
and sets up the Makefile targets to create floppies or floppy images
using SYSLINUX.  The FDOPTS Makefile variable can be used to set
kernel command line options (thanks to a suggestion by Andi Kleen.)

Note that the same change has already been applied to the x86-64
architecture.  The last hunk of the patch corrects a comment in that
architecture.
parent 7deaf3b8
...@@ -92,7 +92,8 @@ AFLAGS += $(mflags-y) ...@@ -92,7 +92,8 @@ AFLAGS += $(mflags-y)
boot := arch/i386/boot boot := arch/i386/boot
.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install .PHONY: zImage bzImage compressed zlilo bzlilo \
zdisk bzdisk fdimage fdimage144 fdimage288 install
all: bzImage all: bzImage
...@@ -110,8 +111,8 @@ zlilo bzlilo: vmlinux ...@@ -110,8 +111,8 @@ zlilo bzlilo: vmlinux
zdisk bzdisk: vmlinux zdisk bzdisk: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
install: vmlinux install fdimage fdimage144 fdimage288: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
archclean: archclean:
$(Q)$(MAKE) $(clean)=arch/i386/boot $(Q)$(MAKE) $(clean)=arch/i386/boot
...@@ -122,5 +123,8 @@ define archhelp ...@@ -122,5 +123,8 @@ define archhelp
echo ' (your) ~/bin/installkernel or' echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or' echo ' (distribution) /sbin/installkernel or'
echo ' install to $$(INSTALL_PATH) and run lilo' echo ' install to $$(INSTALL_PATH) and run lilo'
echo ' bzdisk - Create a boot floppy in /dev/fd0'
echo ' fdimage - Create a boot floppy image'
endef endef
CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
...@@ -62,8 +62,36 @@ $(obj)/compressed/vmlinux: FORCE ...@@ -62,8 +62,36 @@ $(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \ $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
IMAGE_OFFSET=$(IMAGE_OFFSET) $@ IMAGE_OFFSET=$(IMAGE_OFFSET) $@
zdisk: $(BOOTIMAGE) # Set this if you want to pass append arguments to the zdisk/fdimage kernel
dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0 FDARGS =
$(obj)/mtools.conf: $(obj)/mtools.conf.in
sed -e 's|@OBJ@|$(obj)|g' < $< > $@
# This requires write access to /dev/fd0
zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
MTOOLSRC=$(src)/mtools.conf mformat a: ; sync
syslinux /dev/fd0 ; sync
echo 'default linux $(FDARGS)' | \
MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
# These require being root or having syslinux 2.02 or higher installed
fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
MTOOLSRC=$(src)/mtools.conf mformat v: ; sync
syslinux $(obj)/fdimage ; sync
echo 'default linux $(FDARGS)' | \
MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg
MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync
fdimage288: $(BOOTIMAGE) $(src)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
MTOOLSRC=$(src)/mtools.conf mformat w: ; sync
syslinux $(obj)/fdimage ; sync
echo 'default linux $(FDARGS)' | \
MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg
MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync
zlilo: $(BOOTIMAGE) zlilo: $(BOOTIMAGE)
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
......
...@@ -4,29 +4,13 @@ ...@@ -4,29 +4,13 @@
* modified by Drew Eckhardt * modified by Drew Eckhardt
* modified by Bruce Evans (bde) * modified by Bruce Evans (bde)
* modified by Chris Noe (May 1999) (as86 -> gas) * modified by Chris Noe (May 1999) (as86 -> gas)
* * gutted by H. Peter Anvin (Jan 2003)
* 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 * 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 must be multiplied by 16 to obtain their respective linear
* addresses. To avoid confusion, linear addresses are written using leading * addresses. To avoid confusion, linear addresses are written using leading
* hex while segment addresses are written as segment:offset. * 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.
*
* It then loads 'setup' directly after itself (0x90200), and the system
* at 0x10000, using BIOS interrupts.
*
* NOTE! currently system is at most (8*65536-4096) bytes long. This should
* be no problem, even in the future. I want to keep it simple. This 508 kB
* kernel size should be enough, especially as this doesn't contain the
* buffer cache as in minix (and especially now that the kernel is
* compressed :-)
*
* The loader has been made as simple as possible, and continuous
* read errors will result in a unbreakable loop. Reboot by hand. It
* loads pretty fast by getting whole tracks at a time whenever possible.
*/ */
#include <asm/boot.h> #include <asm/boot.h>
...@@ -59,359 +43,51 @@ SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ ...@@ -59,359 +43,51 @@ SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
.global _start .global _start
_start: _start:
# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there. # Normalize the start address
jmpl $BOOTSEG, $start2
movw $BOOTSEG, %ax
movw %ax, %ds # %ds = BOOTSEG
movw $INITSEG, %ax
movw %ax, %es # %ax = %es = INITSEG
movw $256, %cx
subw %si, %si
subw %di, %di
cld
rep
movsw
ljmp $INITSEG, $go
# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
# wouldn't have to worry about this if we checked the top of memory. Also
# my BIOS can be configured to put the wini drive tables in high memory
# instead of in the vector table. The old stack might have clobbered the
# drive table.
go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >= start2:
# length of bootsect + length of movw %cs, %ax
# setup + room for stack; movw %ax, %ds
# 12 is disk parm size. movw %ax, %es
movw %ax, %ds # %ax and %es already contain INITSEG
movw %ax, %ss movw %ax, %ss
movw %di, %sp # put stack at INITSEG:0x4000-12. movw $0x7c00, %sp
sti
# Many BIOS's default disk parameter tables will not recognize cld
# multi-sector reads beyond the maximum sector number specified
# in the default diskette parameter tables - this may mean 7
# sectors in some cases.
#
# Since single sector reads are slow and out of the question,
# we must take care of this by creating new parameter tables
# (for the first disk) in RAM. We will set the maximum sector
# count to 36 - the most we will encounter on an ED 2.88.
#
# High doesn't hurt. Low does.
#
# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
# and %gs is unused.
movw %cx, %fs # %fs = 0
movw $0x78, %bx # %fs:%bx is parameter table address
pushw %ds
ldsw %fs:(%bx), %si # %ds:%si is source
movb $6, %cl # copy 12 bytes
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)
# Get disk drive parameters, specifically number of sectors/track.
# It seems that there is no BIOS call to get the number of sectors. movw $bugger_off_msg, %si
# 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 msg_loop:
probe_loop:
lodsb lodsb
cbtw # extend to word andb %al, %al
movw %ax, sectors jz die
cmpw $disksizes+4, %si movb $0xe, %ah
jae got_sectors # If all else fails, try 9
xchgw %cx, %ax # %cx = track and sector
xorw %dx, %dx # drive 0, head 0
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:
movb $0x03, %ah # read cursor pos
xorb %bh, %bh
int $0x10
movw $9, %cx
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..
# 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)
call kill_motor # reset FDC
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
# After that we check which root-device to use. If the device is
# defined (!= 0), nothing is done and the given device is used.
# 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
# After that (everything loaded), we jump to the setup-routine
# loaded directly after the bootblock:
ljmp $SETUPSEG, $0
# 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:
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
rp_read:
#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 everything yet?
jbe ok1_read
ret
ok1_read:
movw sectors, %ax
subw (%si), %ax # (%si) = sread
movw %ax, %cx
shlw $9, %cx
addw %bx, %cx
jnc ok2_read
je ok2_read
xorw %ax, %ax
subw %bx, %ax
shrw $9, %ax
ok2_read:
call read_track
call set_next
jmp rp_read
read_track:
pusha
pusha
movw $0xe2e, %ax # loading... message 2e = .
movw $7, %bx movw $7, %bx
int $0x10 int $0x10
popa jmp msg_loop
# 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 2(%si), %dx # 2(%si) = head
movb %dl, %dh
andw $0x0100, %dx
movb $2, %ah
pushw %dx # save for error dump
pushw %cx
pushw %bx
pushw %ax
int $0x13
jc bad_rt
addw $8, %sp
popa
ret
set_next: die:
movw %ax, %cx # Allow the user to press a key, then reboot
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 xorw %ax, %ax
ok3_set: int $0x16
movw %ax, (%si) # set sread int $0x19
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
xorb %ah, %ah
xorb %dl, %dl
int $0x13
addw $10, %sp
popa
jmp read_track
# print_all is for debugging purposes.
#
# it will print out all of the registers. The assumption is that this is
# called from a routine, with a stack frame like
#
# %dx
# %cx
# %bx
# %ax
# (error)
# ret <- %sp
print_all:
movw $5, %cx # error code + 4 registers
movw %sp, %bp
print_loop:
pushw %cx # save count remaining
call print_nl # <-- for readability
cmpb $5, %cl
jae no_reg # see if register name is needed
movw $0xe05 + 'A' - 1, %ax
subb %cl, %al
int $0x10
movb $'X', %al
int $0x10
movb $':', %al
int $0x10
no_reg:
addw $2, %bp # next register
call print_hex # print it
popw %cx
loop print_loop
ret
print_nl: # int 0x19 should never return. In case it does anyway,
movw $0xe0d, %ax # CR # invoke the BIOS reset code...
int $0x10 ljmp $0xf000,$0xfff0
movb $0xa, %al # LF
int $0x10
ret
# print_hex is for debugging purposes, and prints the word
# pointed to by %ss:%bp in hexadecimal.
print_hex: bugger_off_msg:
movw $4, %cx # 4 hex digits .ascii "Direct booting from floppy is no longer supported.\r\n"
movw (%bp), %dx # load word into %dx .ascii "Please use a boot loader program instead.\r\n"
print_digit: .ascii "\n"
rolw $4, %dx # rotate to use low 4 bits .ascii "Remove disk and press any key to reboot . . .\r\n"
movw $0xe0f, %ax # %ah = request .byte 0
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
loop print_digit
ret
# 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:
#if 1
xorw %ax, %ax # reset FDC
xorb %dl, %dl
int $0x13
#else
movw $0x3f2, %dx
xorb %al, %al
outb %al, %dx
#endif
ret
sectors: .word 0
disksizes: .byte 36, 21, 18, 15, 9
msg1: .byte 13, 10
.ascii "Loading"
# XXX: This is a fairly snug fit. # Kernel attributes; used by setup
.org 497 .org 497
setup_sects: .byte SETUPSECTS setup_sects: .byte SETUPSECTS
root_flags: .word ROOT_RDONLY root_flags: .word ROOT_RDONLY
syssize: .word SYSSIZE syssize: .word SYSSIZE
......
#
# mtools configuration file for "make (b)zdisk"
#
# Actual floppy drive
drive a:
file="/dev/fd0"
# 1.44 MB floppy disk image
drive v:
file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
# 2.88 MB floppy disk image (mostly for virtual uses)
drive w:
file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
...@@ -150,13 +150,10 @@ int main(int argc, char ** argv) ...@@ -150,13 +150,10 @@ int main(int argc, char ** argv)
sz = sb.st_size; sz = sb.st_size;
fprintf (stderr, "System is %d kB\n", sz/1024); fprintf (stderr, "System is %d kB\n", sz/1024);
sys_size = (sz + 15) / 16; sys_size = (sz + 15) / 16;
/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */ /* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE)) if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
die("System is too big. Try using %smodules.", die("System is too big. Try using %smodules.",
is_big_kernel ? "" : "bzImage or "); is_big_kernel ? "" : "bzImage or ");
if (sys_size > 0xefff)
fprintf(stderr,"warning: kernel is too big for standalone boot "
"from floppy\n");
while (sz > 0) { while (sz > 0) {
int l, n; int l, n;
......
...@@ -73,7 +73,7 @@ zdisk: $(BOOTIMAGE) $(obj)/mtools.conf ...@@ -73,7 +73,7 @@ zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
# These require being root or having syslinux run setuid # These require being root or having syslinux 2.02 or higher installed
fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf
dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
MTOOLSRC=$(src)/mtools.conf mformat v: ; sync MTOOLSRC=$(src)/mtools.conf mformat v: ; sync
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment