wok diff linux/stuff/linux-header-2.6.30.6.u @ rev 4504

linux: add floppy boot support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Nov 22 12:46:40 2009 +0100 (2009-11-22)
parents
children b5013b460117
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/linux/stuff/linux-header-2.6.30.6.u	Sun Nov 22 12:46:40 2009 +0100
     1.3 @@ -0,0 +1,445 @@
     1.4 +--- linux-2.6.30.6/arch/x86/boot/header.S
     1.5 ++++ linux-2.6.30.6/arch/x86/boot/header.S
     1.6 +@@ -6,7 +6,7 @@
     1.7 +  *	Based on bootsect.S and setup.S
     1.8 +  *	modified by more people than can be counted
     1.9 +  *
    1.10 +- *	Rewritten as a common file by H. Peter Anvin (Apr 2007)
    1.11 ++ *	Rewritten Pascal Bellard (Nov 2009)
    1.12 +  *
    1.13 +  * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
    1.14 +  * addresses must be multiplied by 16 to obtain their respective linear
    1.15 +@@ -26,6 +26,8 @@
    1.16 + 
    1.17 + BOOTSEG		= 0x07C0		/* original address of boot-sector */
    1.18 + SYSSEG		= 0x1000		/* historical load address >> 4 */
    1.19 ++INITSEG		= 0x9000		/* boot address >> 4 */
    1.20 ++SETUPSEG	= 0x9020		/* setup address >> 4 */
    1.21 + 
    1.22 + #ifndef SVGA_MODE
    1.23 + #define SVGA_MODE ASK_VGA
    1.24 +@@ -39,53 +41,392 @@
    1.25 + #define ROOT_RDONLY 1
    1.26 + #endif
    1.27 + 
    1.28 ++#define SHOW_REGS	show int13 status & parameters
    1.29 ++#define EDIT_CMDLINE	add kernel command line support
    1.30 ++
    1.31 + 	.code16
    1.32 + 	.section ".bstext", "ax"
    1.33 + 
    1.34 + 	.global bootsect_start
    1.35 + bootsect_start:
    1.36 ++stacktop	= 0x9E00		# in 0x8000 .. 0xA000
    1.37 ++					# with 512 bytes for cmdline
    1.38 ++	movw	$stacktop-12, %di	# stacktop is an arbitrary value >=
    1.39 ++					# length of bootsect + length of
    1.40 ++					# setup + room for stack;
    1.41 ++					# 12 is disk parm size.
    1.42 ++					# gdt will heat 48 more bytes.
    1.43 ++curcx	=	0
    1.44 ++curdx	=	curcx+2
    1.45 ++	cld				# assume nothing
    1.46 ++#ifndef FLOPPY_1440K_ONLY
    1.47 ++limits	=	4
    1.48 ++#endif
    1.49 + 
    1.50 +-	# Normalize the start address
    1.51 +-	ljmp	$BOOTSEG, $start2
    1.52 ++	pushw	$INITSEG
    1.53 ++	popw	%es			# %es = INITSEG
    1.54 ++	xorw	%cx, %cx		# %cx = 0
    1.55 + 
    1.56 +-start2:
    1.57 +-	movw	%cs, %ax
    1.58 +-	movw	%ax, %ds
    1.59 +-	movw	%ax, %es
    1.60 +-	movw	%ax, %ss
    1.61 +-	xorw	%sp, %sp
    1.62 +-	sti
    1.63 +-	cld
    1.64 ++	pushw	%es
    1.65 ++	popw	%ss			# %ss and %es already contain INITSEG
    1.66 ++	movw	%di, %sp		# put stack at INITSEG:stacktop-12.
    1.67 + 
    1.68 +-	movw	$bugger_off_msg, %si
    1.69 ++# Many BIOS's default disk parameter tables will not recognize
    1.70 ++# multi-sector reads beyond the maximum sector number specified
    1.71 ++# in the default diskette parameter tables - this may mean 7
    1.72 ++# sectors in some cases.
    1.73 ++#
    1.74 ++# Since single sector reads are slow and out of the question,
    1.75 ++# we must take care of this by creating new parameter tables
    1.76 ++# (for the first disk) in RAM.  We can set the maximum sector
    1.77 ++# count to 36 - the most we will encounter on an ED 2.88.  
    1.78 ++#
    1.79 ++# High doesn't hurt.  Low does.  Let's use the max: 63
    1.80 ++#
    1.81 ++# Segments are as follows: %es = %ss = INITSEG,
    1.82 ++# %fs and %gs are unused.
    1.83 + 
    1.84 +-msg_loop:
    1.85 +-	lodsb
    1.86 +-	andb	%al, %al
    1.87 +-	jz	bs_die
    1.88 +-	movb	$0xe, %ah
    1.89 +-	movw	$7, %bx
    1.90 ++	movw	$0x78, %bx		# %ds:%bx is parameter table address
    1.91 ++	movw	%cx, %ds		# %ds = 0
    1.92 ++	ldsw	(%bx), %si		# %ds:%si is source
    1.93 ++	movb	$6, %cl			# copy 12 bytes
    1.94 ++	rep				# don't worry about cld
    1.95 ++	movsw				# already done above
    1.96 ++	movw	%cx, %ds		# %ds = 0
    1.97 ++	movw	%sp, (%bx)		# %sp = stacktop-12
    1.98 ++	movw	%es, 2(%bx)
    1.99 ++
   1.100 ++	movb	setup_sects+0x7C00, %al	# read bootsector + setup (%ds = 0)
   1.101 ++	cbw
   1.102 ++	incw	%ax
   1.103 ++
   1.104 ++	pushw	%es
   1.105 ++	popw	%ds			# now %ds = %es = %ss = INITSEG
   1.106 ++	movb	$63, 0x4-12(%di)	# patch sector count, %di = stacktop
   1.107 ++
   1.108 ++	cli
   1.109 ++
   1.110 ++	xchg	%ax, %di		# sector count
   1.111 ++	cbw				# limits = 0
   1.112 ++	incw	%cx			# cylinder 0, sector 1
   1.113 ++	xorb	%dh, %dh		# head 0, current drive
   1.114 ++	xorw	%bx, %bx
   1.115 ++	call	read_first_sectors	# read setup
   1.116 ++
   1.117 ++#define version_offset		0xE
   1.118 ++#define loadflags_offset	0x11
   1.119 ++#define heap_end_ptr_offset	0x24
   1.120 ++
   1.121 ++	movw	$_start,%si
   1.122 ++	orb	$0x80, loadflags_offset(%si)
   1.123 ++	movw	$stacktop-0x200, heap_end_ptr_offset(%si)
   1.124 ++
   1.125 ++	addw	version_offset(%si),%si	# starting protocol 2.00, Kernel 1.3.73
   1.126 ++	call	puts			# show which kernel we are loading
   1.127 ++
   1.128 ++#ifdef	EDIT_CMDLINE
   1.129 ++# The cmdline can be entered and modifed on hot key.
   1.130 ++# Only characters before the cursor are passed to the kernel.
   1.131 ++	movw	$cmd_line_ptr, %si
   1.132 ++	cmpw	%bx,(%si)		# %bx = 7
   1.133 ++	jb	nocmdline
   1.134 ++	incw	%di			# read 1 sector
   1.135 ++	movw	(%si), %bx
   1.136 ++	pushw	%si
   1.137 ++	call	read_sectors
   1.138 ++	popw	%di
   1.139 ++	movw	(%di), %si
   1.140 ++	call	puts
   1.141 ++cmdlp:
   1.142 ++	movb	$32, %al		# clear end of line
   1.143 ++	call	putc			#  with Space
   1.144 ++	movb	$8, %al			#   and BackSpace
   1.145 + 	int	$0x10
   1.146 +-	jmp	msg_loop
   1.147 ++	decw	%si
   1.148 ++cmdget:
   1.149 ++	cbw				# %ah = 0, get keyboard character
   1.150 ++	int	$0x16
   1.151 ++	cmpb	$8, %al			# BackSpace ?
   1.152 ++	je	cmdbs
   1.153 ++	cbw
   1.154 ++	movw	%ax, (%si)		# store end of string too
   1.155 ++	incw	%si
   1.156 ++	incw	%si
   1.157 ++cmdbs:
   1.158 ++	cmpw	(%di), %si		# lower limit is checked
   1.159 ++	je	cmdget			#   but upper limit not
   1.160 ++	call	putc
   1.161 ++	cmpb	$10, %al		# Enter ?
   1.162 ++	jne	cmdlp
   1.163 ++endcmdline:
   1.164 ++	
   1.165 ++nocmdline:
   1.166 ++#endif
   1.167 + 
   1.168 +-bs_die:
   1.169 +-	# Allow the user to press a key, then reboot
   1.170 +-	xorw	%ax, %ax
   1.171 ++# This routine loads the system at address SYSSEG, making sure
   1.172 ++# no 64kB boundaries are crossed. We try to load it as fast as
   1.173 ++# possible, loading whole tracks whenever we can.
   1.174 ++
   1.175 ++	movw	$24, %cx		# allocate 48 bytes in stack
   1.176 ++init_gdt:
   1.177 ++	push	$0			#   initialized with 0
   1.178 ++	loop	init_gdt
   1.179 ++	movw	%sp, %si		# for bootsect_gdt
   1.180 ++	movb	$0x0F, %al		# destination = 0x100000
   1.181 ++	movw	$syssize, %di
   1.182 ++#define type_of_loader_offset	0x1C	/* type_of_loader - syssize */
   1.183 ++	decb	type_of_loader_offset(%di)	# loader type = 0xFF
   1.184 ++	movb	$5, %cl
   1.185 ++initrdlp:
   1.186 ++	movb	$0x93,%ah
   1.187 ++	movw	%ax, 28(%si)		# bootsect_dst_base+2
   1.188 ++	movb	$(SYSSEG/4096), %al	# source = SYSSEG
   1.189 ++	movw	%ax, 20(%si)		# bootsect_src_base+2
   1.190 ++	cwd
   1.191 ++	movw	%dx, 16(%si)		# bootsect_src = 64Kb
   1.192 ++	movw	%dx, 24(%si)		# bootsect_dst = 64Kb
   1.193 ++	xorl	%ebx, %ebx
   1.194 ++	incw	%bx
   1.195 ++	shlw	%cl,%bx
   1.196 ++	decw	%bx
   1.197 ++	addl	(%di),%ebx
   1.198 ++	shrl	%cl, %ebx
   1.199 ++syslp:
   1.200 ++	pushw	$SYSSEG
   1.201 ++	popw	%es
   1.202 ++	movw	$128,%di		# 64Kb
   1.203 ++	subw	%di, %bx		# max 32M > int 15 limit
   1.204 ++	pushf
   1.205 ++	jnc	not_last
   1.206 ++	addw	%bx, %di
   1.207 ++not_last:
   1.208 ++	pushw	%bx
   1.209 ++	pushw	%si
   1.210 ++	xorw	%bx, %bx
   1.211 ++	call	read_sectors
   1.212 ++	popw	%si
   1.213 ++	movw	$0x8000, %cx		# full 64K
   1.214 ++	movb	$0x87, %ah
   1.215 ++	incb	28(%si)			# bootsect_dst_base+2
   1.216 ++	int	$0x15			# max 16M
   1.217 ++	popw	%bx
   1.218 ++	popf
   1.219 ++	ja	syslp
   1.220 ++	movw	ramdisk_image+2,%ax
   1.221 ++	decw	%ax
   1.222 ++	movw	$ramdisk_size,%di
   1.223 ++	movb	$9, %cl
   1.224 ++	cmpb	%al,28(%si)
   1.225 ++	jb	initrdlp
   1.226 ++
   1.227 ++# This procedure turns off the floppy drive motor, so
   1.228 ++# that we enter the kernel in a known state, and
   1.229 ++# don't have to worry about it later.
   1.230 ++
   1.231 ++kill_motor:
   1.232 ++	xorw	%ax, %ax		# reset FDC
   1.233 ++	int	$0x13
   1.234 ++
   1.235 ++# After that (everything loaded), we jump to the setup-routine
   1.236 ++# loaded directly after the bootblock:
   1.237 ++# Segments are as follows: %ds = %ss = INITSEG
   1.238 ++
   1.239 ++	ljmp	$SETUPSEG, $0
   1.240 ++
   1.241 ++# read_sectors reads %di sectors into %es:0 buffer.
   1.242 ++# %es:0 is updated to the next memory location.
   1.243 ++# First, sectors are read sector by sector until
   1.244 ++# sector per track count is known. Then they are
   1.245 ++# read track by track.
   1.246 ++# Assume no error on first track.
   1.247 ++
   1.248 ++#define FLOPPY_CYLINDERS	80	/* 80 cylinders minimum */
   1.249 ++#define FLOPPY_HEADS		2	/* 2 heads minimum */
   1.250 ++#define FLOPPY_SECTORS		18	/* 18 sectors minimum */
   1.251 ++
   1.252 ++#ifdef SHOW_REGS
   1.253 ++print_loop:
   1.254 ++	movb	$0x6 + 'A' - 1, %al
   1.255 ++	subb	%cl, %al
   1.256 ++	movw	$regs, %si		# caller %si is saved
   1.257 ++	call	putcs			# putc(%al) + puts(%si)
   1.258 ++# it will print out all of the registers.
   1.259 ++	popw	%bp			# load word into %bp
   1.260 ++	jmp	print_all		# print %bp (status)
   1.261 ++#endif
   1.262 ++check_limits:
   1.263 ++#ifndef FLOPPY_1440K_ONLY
   1.264 ++	cmpb	$FLOPPY_SECTORS+1, %cl	# 18 sectors minimum
   1.265 ++	jb	check_head
   1.266 ++        cmpb    %al, %cl		# max sector known ?
   1.267 ++        ja	next_head		#   no -> store it
   1.268 ++check_head:
   1.269 ++	cmpb	$FLOPPY_HEADS, %dh	# 2 heads minimum
   1.270 ++	jb	check_cylinder
   1.271 ++        cmpb    %ah, %dh		# max head known ?
   1.272 ++        ja	next_cylinder		#   no -> store it
   1.273 ++check_cylinder:
   1.274 ++	cmpb	$FLOPPY_CYLINDERS, %ch	# 80 cylinders minimum
   1.275 ++	jae	next_floppy
   1.276 ++#endif
   1.277 ++	pushaw
   1.278 ++#ifdef SHOW_REGS
   1.279 ++	pushw	%es			# print %es (named EX)
   1.280 ++	pushw	%dx			# print %dx
   1.281 ++	pushw	%cx			# print %cx
   1.282 ++	pushw	%bx			# print %bx
   1.283 ++#ifndef FLOPPY_1440K_ONLY
   1.284 ++	xchgw	%ax, %si
   1.285 ++#endif
   1.286 ++	movb	$2,%ah
   1.287 ++	pushw	%ax			# print %ax
   1.288 ++	movw	$6,%cx
   1.289 ++print_all:
   1.290 ++	pushw	%cx			# save count remaining
   1.291 ++	movb	$4, %cl			# 4 hex digits
   1.292 ++print_digit:
   1.293 ++	rolw	$4, %bp			# rotate to use low 4 bits
   1.294 ++	movb	$0x0f, %al
   1.295 ++	andw	%bp, %ax		# %al = mask for nybble
   1.296 ++	addb	$0x90, %al		# convert %al to ascii hex
   1.297 ++	daa				# in only four instructions!
   1.298 ++	adcb	$0x40, %al
   1.299 ++	daa
   1.300 ++	call	putc			# set %ah and %bx
   1.301 ++	loop	print_digit
   1.302 ++	movb	$0x20, %al		# SPACE
   1.303 ++	int	$0x10
   1.304 ++	popw	%cx
   1.305 ++	loop	print_loop
   1.306 ++#endif
   1.307 ++	cbw				# %ah = 0
   1.308 ++        int     $0x13			# reset controler
   1.309 ++	popaw
   1.310 ++read_sectorslp:
   1.311 ++	xorw	%si, %si
   1.312 ++	lodsw
   1.313 ++	xchgw	%ax,%cx			# restore disk state
   1.314 ++	lodsw
   1.315 ++	xchgw	%ax,%dx
   1.316 ++#ifndef FLOPPY_1440K_ONLY
   1.317 ++#   al is last sector+1
   1.318 ++#   ah is last cylinder+1
   1.319 ++	lodsw
   1.320 ++#endif
   1.321 ++#ifndef FLOPPY_1440K_ONLY
   1.322 ++        pushw   %ax			# limits
   1.323 ++	subb	%cl, %al		# sectors remaining in track
   1.324 ++	ja	tolastsect
   1.325 ++	movb	$1, %al			# 1 sector mini
   1.326 ++tolastsect:
   1.327 ++#else
   1.328 ++	mov	$FLOPPY_SECTORS+1, %al
   1.329 ++	subb	%cl, %al		# sectors remaining in track
   1.330 ++#endif
   1.331 ++	cbw
   1.332 ++	cmpw	%di, %ax
   1.333 ++	jb	more1trk
   1.334 ++	movw	%di, %ax		# sectors to read
   1.335 ++more1trk:
   1.336 ++	pushw	%ax			# save context
   1.337 ++	pushw	%dx			# some bios break dx...
   1.338 ++	movb	$2, %ah			# cmd: read chs
   1.339 ++        int     $0x13
   1.340 ++	popw	%dx
   1.341 ++	xchgw	%ax, %bp		# status
   1.342 ++#ifndef FLOPPY_1440K_ONLY
   1.343 ++	popw	%si			# save %ax
   1.344 ++        popw    %ax			# limits
   1.345 ++#else
   1.346 ++	popw	%ax			# restore context
   1.347 ++#endif
   1.348 ++	jc	check_limits
   1.349 ++#ifndef FLOPPY_1440K_ONLY
   1.350 ++	subw	%si,%di			# update sector counter
   1.351 ++	addw	%si,%cx			# next sector
   1.352 ++	shlw	$9,%si
   1.353 ++	addw	%si,%bx			# next location
   1.354 ++#else
   1.355 ++	subw	%ax,%di			# update sector counter
   1.356 ++	addw	%ax,%cx			# next sector
   1.357 ++	addw	%ax,%ax
   1.358 ++	addb	%al,%bh			# next location
   1.359 ++#endif
   1.360 ++#ifndef FLOPPY_1440K_ONLY
   1.361 ++        cmpb    %al,%cl			# reach sector limit ?
   1.362 ++        jne     bdendlp
   1.363 ++next_head:
   1.364 ++        movb    %cl,%al
   1.365 ++#else
   1.366 ++        cmpb    $FLOPPY_SECTORS+1,%cl	# reach sector limit ?
   1.367 ++        jne     bdendlp
   1.368 ++#endif
   1.369 ++        incb    %dh			# next head
   1.370 ++        movb    $1,%cl			# first sector
   1.371 ++#ifndef FLOPPY_1440K_ONLY
   1.372 ++        cmpb    %ah, %dh		# reach head limit ?
   1.373 ++        jne     bdendlp
   1.374 ++next_cylinder:
   1.375 ++        movb    %dh,%ah
   1.376 ++#else
   1.377 ++        cmpb    %cl,%dh			# reach head limit ?
   1.378 ++        je	bdendlp
   1.379 ++#endif
   1.380 ++        movb    $0,%dh			# first head
   1.381 ++# NOTE : support 256 cylinders max
   1.382 ++        incb    %ch			# next cylinder
   1.383 ++#ifndef FLOPPY_1440K_ONLY
   1.384 ++	cmpb	$FLOPPY_SECTORS+1,%al	# 1.44M floppy ?
   1.385 ++        jne	bdendlp
   1.386 ++#endif
   1.387 ++        cmpb    $FLOPPY_CYLINDERS,%ch	# reach cylinder limit ?
   1.388 ++        jb	bdendlp
   1.389 ++next_floppy:
   1.390 ++	movb	$0,%ch			# first cylinder
   1.391 ++	pushaw
   1.392 ++	movw	$swap_floppy,%si
   1.393 ++	call	puts
   1.394 ++	cbw				# %ah = 0, get keyboard character
   1.395 + 	int	$0x16
   1.396 +-	int	$0x19
   1.397 ++	popaw
   1.398 ++bdendlp:
   1.399 ++read_first_sectors:
   1.400 ++#ifndef FLOPPY_1440K_ONLY
   1.401 ++	movw	%ax, limits
   1.402 ++#endif
   1.403 ++	pushw	%dx
   1.404 ++	pushw	%cx
   1.405 ++	popl	curcx			# save disk state
   1.406 ++read_sectors:
   1.407 ++	orw	%di,%di
   1.408 ++        jne	read_sectorslp
   1.409 ++	pushw	%ss
   1.410 ++	popw	%es			# restore es
   1.411 ++	movb	$0x2e, %al 		# loading... message 2e = .
   1.412 ++putc:
   1.413 ++	movb	$0xe, %ah
   1.414 ++	movw	$7, %bx			#   one dot each 64k
   1.415 ++ 	int	$0x10
   1.416 ++	cmp	$0xd, %al		# CR ?
   1.417 ++	jne	return
   1.418 ++	movb	$0xa, %al		# LF
   1.419 ++	jmp	putc
   1.420 + 
   1.421 +-	# int 0x19 should never return.  In case it does anyway,
   1.422 +-	# invoke the BIOS reset code...
   1.423 +-	ljmp	$0xf000,$0xfff0
   1.424 ++puts:
   1.425 ++	movb	$0xd, %al		# CR
   1.426 ++putcs:
   1.427 ++	call	putc
   1.428 ++	lodsb
   1.429 ++	orb	%al,%al			# end of string is \0
   1.430 ++	jnz	putcs
   1.431 ++return:
   1.432 ++	ret
   1.433 + 
   1.434 +-	.section ".bsdata", "a"
   1.435 +-bugger_off_msg:
   1.436 +-	.ascii	"Direct booting from floppy is no longer supported.\r\n"
   1.437 +-	.ascii	"Please use a boot loader program instead.\r\n"
   1.438 +-	.ascii	"\n"
   1.439 +-	.ascii	"Remove disk and press any key to reboot . . .\r\n"
   1.440 +-	.byte	0
   1.441 ++regs:	.asciz	"X:"
   1.442 + 
   1.443 ++swap_floppy:
   1.444 ++	.ascii	"Insert next floppy and press any key to continue."
   1.445 ++	.byte	7,13,0
   1.446 + 
   1.447 + 	# Kernel attributes; used by setup.  This is part 1 of the
   1.448 + 	# header, from the old boot sector.