wok-next diff etherboot/stuff/patches/etherboot-prefix.u @ rev 20661

Unification of the patch system
author Aleksej Bobylev <al.bobylev@gmail.com>
date Thu May 10 21:12:00 2018 +0300 (2018-05-10)
parents etherboot/stuff/etherboot-prefix.u@4a87a0aa0476
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/etherboot/stuff/patches/etherboot-prefix.u	Thu May 10 21:12:00 2018 +0300
     1.3 @@ -0,0 +1,859 @@
     1.4 +--- etherboot-5.4.3/src/arch/i386/prefix/liloprefix.S
     1.5 ++++ etherboot-5.4.3/src/arch/i386/prefix/liloprefix.S
     1.6 +@@ -1,92 +1,377 @@
     1.7 +-/*
     1.8 +-	Copyright (C) 2000, Entity Cyber, Inc.
     1.9 +-
    1.10 +-	Authors: Gary Byers (gb@thinguin.org)
    1.11 +-		 Marty Connor (mdc@thinguin.org)
    1.12 +-
    1.13 +-	This software may be used and distributed according to the terms
    1.14 +-	of the GNU Public License (GPL), incorporated herein by reference.
    1.15 +-
    1.16 +-	Description:	
    1.17 +-
    1.18 +-	This is just a little bit of code and data that can get prepended
    1.19 +-	to an Etherboot ROM image in order to allow LILO to load the
    1.20 +-	result as if it were a Linux kernel image.
    1.21 +-
    1.22 +-	A real Linux kernel image consists of a one-sector boot loader
    1.23 +-	(to load the image from a floppy disk), followed a few sectors
    1.24 +-	of setup code, followed by the kernel code itself.  There's
    1.25 +-	a table in the first sector (starting at offset 497) that indicates
    1.26 +-	how many sectors of setup code follow the first sector and which
    1.27 +-	contains some other parameters that aren't interesting in this
    1.28 +-	case.
    1.29 +-
    1.30 +-	When LILO loads the sectors that comprise a kernel image, it doesn't
    1.31 +-	execute the code in the first sector (since that code would try to
    1.32 +-	load the image from a floppy disk.)  The code in the first sector
    1.33 +-	below doesn't expect to get executed (and prints an error message
    1.34 +-	if it ever -is- executed.)  LILO's only interested in knowing the
    1.35 +-	number of setup sectors advertised in the table (at offset 497 in
    1.36 +-	the first sector.)
    1.37 +-
    1.38 +-	Etherboot doesn't require much in the way of setup code.
    1.39 +-	Historically, the Linux kernel required at least 4 sectors of
    1.40 +-	setup code.  Current versions of LILO look at the byte at
    1.41 +-	offset 497 in the first sector to indicate how many sectors
    1.42 +-	of setup code are contained in the image.
    1.43 +-
    1.44 +-*/
    1.45 ++/* SYS_SIZE is the number of clicks (16 bytes) to be loaded.  For Etherboot
    1.46 ++ * purposes, we need to load everything but the boot sector itself, i.e. 32
    1.47 ++ * clicks less than the size of the entire (verbatim) image.  The image size
    1.48 ++ * is practically limited only by the available base memory size.
    1.49 ++ */
    1.50 ++.globl	SYSSIZE
    1.51 ++.equ	SYSSIZE, _verbatim_size_pgh - 32
    1.52 ++
    1.53 ++/*	floppyload.S Copyright (C) 1991, 1992 Linus Torvalds
    1.54 ++ *	modified by Drew Eckhardt
    1.55 ++ *	modified by Bruce Evans (bde)
    1.56 ++ *
    1.57 ++ * floppyprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
    1.58 ++ *
    1.59 ++ * It then loads the system at SYSSEG<<4, using BIOS interrupts.
    1.60 ++ *
    1.61 ++ * The loader has been made as simple as possible, and continuous read errors
    1.62 ++ * will result in a unbreakable loop. Reboot by hand. It loads pretty fast by
    1.63 ++ * getting whole tracks at a time whenever possible.
    1.64 ++ */
    1.65 + 
    1.66 + #define	SETUPSECS 4		/* Minimal nr of setup-sectors */
    1.67 + #define PREFIXSIZE ((SETUPSECS+1)*512)
    1.68 + #define PREFIXPGH (PREFIXSIZE / 16 )
    1.69 +-#define	BOOTSEG  0x07C0		/* original address of boot-sector */
    1.70 + #define	INITSEG  0x9000		/* we move boot here - out of the way */
    1.71 + #define	SETUPSEG 0x9020		/* setup starts here */
    1.72 +-#define SYSSEG   0x1000		/* system loaded at 0x10000 (65536). */
    1.73 + 
    1.74 +-	.text
    1.75 +-	.code16
    1.76 +-	.arch i386
    1.77 +-	.org	0
    1.78 +-	.section ".prefix", "ax", @progbits
    1.79 + 	.globl	_prefix
    1.80 + _prefix:
    1.81 ++.equ	BOOTSEG, 0x07C0			/* original address of boot-sector */
    1.82 + 
    1.83 +-/* 
    1.84 +-	This is a minimal boot sector.	If anyone tries to execute it (e.g., if
    1.85 +-	a .lilo file is dd'ed to a floppy), print an error message. 
    1.86 +-*/
    1.87 ++.equ	SYSSEG, 0x1000			/* system loaded at SYSSEG<<4 */
    1.88 ++
    1.89 ++	.org	0
    1.90 ++	.arch i386
    1.91 ++	.text
    1.92 ++	.section ".prefix", "ax", @progbits
    1.93 ++	.code16
    1.94 ++
    1.95 ++	call	here
    1.96 ++here:
    1.97 ++	pop	%ax
    1.98 ++	cmpw	$0x103, %ax		/* COM entry point is cs:0x100 */
    1.99 ++	jne	bootsector
   1.100 ++
   1.101 ++/* We need a real mode stack that won't be stomped on by Etherboot
   1.102 ++   which starts at 0x20000. Choose something that's sufficiently high,
   1.103 ++   but not in DOC territory. Note that we couldn't do this in a real
   1.104 ++   .com program since stack variables are in the same segment as the
   1.105 ++   code and data, but this isn't really a .com program, it just looks
   1.106 ++   like one to make DOS load it into memory. It still has the 64kB
   1.107 ++   limitation of .com files though. */
   1.108 ++#define STACK_SEG	0x7000
   1.109 ++#define STACK_SIZE	0x4000
   1.110 ++	/* Set up temporary stack */ 
   1.111 ++	movw	$STACK_SEG, %ax
   1.112 ++	movw	%ax, %ss
   1.113 ++	movw	$STACK_SIZE, %sp
   1.114 ++
   1.115 ++	/* Calculate segment address of image start */
   1.116 ++	pushw	%cs
   1.117 ++	popw	%ax
   1.118 ++	addw	$(0x100/16), %ax
   1.119 ++	jmp	go_setup_code
   1.120 + 
   1.121 +-bootsector: 
   1.122 +-	jmp	$BOOTSEG, $go - _prefix	/* reload cs:ip to match relocation addr */
   1.123 ++bootsector:
   1.124 ++	jmp	$BOOTSEG, $go		/* reload cs:ip to match relocation addr */
   1.125 + go: 
   1.126 +-	movw	$0x2000, %di		/*  0x2000 is arbitrary value >= length
   1.127 +-					    of bootsect + room for stack */
   1.128 ++	movw	$0x2000-12, %di		/* 0x2000 is arbitrary value >= length */
   1.129 ++					/* of bootsect + room for stack + 12 for */
   1.130 ++					/* saved disk parm block */
   1.131 + 
   1.132 + 	movw	$BOOTSEG, %ax
   1.133 + 	movw	%ax,%ds
   1.134 + 	movw	%ax,%es
   1.135 +-
   1.136 +-	cli
   1.137 +-	movw	%ax, %ss		/* put stack at BOOTSEG:0x2000. */
   1.138 ++	movw	%ax,%ss			/* put stack at initial position */
   1.139 + 	movw	%di,%sp
   1.140 +-	sti
   1.141 + 
   1.142 +-	movw	$why_end-why, %cx
   1.143 +-	movw	$why - _prefix, %si
   1.144 ++/* Many BIOS's default disk parameter tables will not recognize multi-sector
   1.145 ++ * reads beyond the maximum sector number specified in the default diskette
   1.146 ++ * parameter tables - this may mean 7 sectors in some cases.
   1.147 ++ *
   1.148 ++ * Since single sector reads are slow and out of the question, we must take care
   1.149 ++ * of this by creating new parameter tables (for the first disk) in RAM.  We
   1.150 ++ * will set the maximum sector count to 36 - the most we will encounter on an
   1.151 ++ * ED 2.88.  High doesn't hurt.	Low does.
   1.152 ++ *
   1.153 ++ * Segments are as follows: ds=es=ss=cs - BOOTSEG
   1.154 ++ */
   1.155 ++
   1.156 ++	xorw	%cx,%cx
   1.157 ++	movw	%cx,%es			/* access segment 0 */
   1.158 ++	movw	$0x78, %bx		/* 0:bx is parameter table address */
   1.159 ++	pushw	%ds			/* save ds */
   1.160 ++/* 0:bx is parameter table address */
   1.161 ++	ldsw	%es:(%bx),%si		/* loads ds and si */
   1.162 ++
   1.163 ++	movw	%ax,%es			/* ax is BOOTSECT (loaded above) */
   1.164 ++	movb	$6, %cl			/* copy 12 bytes */
   1.165 ++	cld
   1.166 ++	pushw	%di			/* keep a copy for later */
   1.167 ++	rep
   1.168 ++	movsw				/* ds:si is source, es:di is dest */
   1.169 ++	popw	%di
   1.170 ++
   1.171 ++	movb	$36,%es:4(%di)
   1.172 ++
   1.173 ++	movw	%cx,%ds			/* access segment 0 */
   1.174 ++	xchgw	%di,(%bx)
   1.175 ++	movw	%es,%si
   1.176 ++	xchgw	%si,2(%bx)
   1.177 ++	popw	%ds			/* restore ds */
   1.178 ++	movw	%di, dpoff		/* save old parameters */
   1.179 ++	movw	%si, dpseg		/* to restore just before finishing */
   1.180 ++	pushw	%ds
   1.181 ++	popw	%es			/* reload es */
   1.182 ++
   1.183 ++/* Note that es is already set up.  Also cx is 0 from rep movsw above. */
   1.184 ++
   1.185 ++	xorb	%ah,%ah			/* reset FDC */
   1.186 ++	xorb	%dl,%dl
   1.187 ++	int	$0x13
   1.188 ++
   1.189 ++/* Get disk drive parameters, specifically number of sectors/track.
   1.190 ++ *
   1.191 ++ * It seems that there is no BIOS call to get the number of sectors.  Guess
   1.192 ++ * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
   1.193 ++ * 15 if sector 15 can be read.	Otherwise guess 9.
   1.194 ++ */
   1.195 + 
   1.196 +-	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
   1.197 +-	movb	$0x0e, %ah		/* write char, tty mode */
   1.198 +-prloop: 
   1.199 ++	movw	$disksizes, %si		/* table of sizes to try */
   1.200 ++
   1.201 ++probe_loop: 
   1.202 + 	lodsb
   1.203 ++	orb	%al, %al
   1.204 ++	je	got_sectors		/* if all else fails, try 9 */
   1.205 ++	cbtw				/* extend to word */
   1.206 ++	movw	%ax, sectors
   1.207 ++	xchgw	%cx,%ax			/* cx = track and sector */
   1.208 ++	xorw	%dx,%dx			/* drive 0, head 0 */
   1.209 ++	movw	$0x0200, %bx		/* address after boot sector */
   1.210 ++					/*   (512 bytes from origin, es = cs) */
   1.211 ++	movw	$0x0201, %ax		/* service 2, 1 sector */
   1.212 ++	int	$0x13
   1.213 ++	jc	probe_loop		/* try next value */
   1.214 ++
   1.215 ++got_sectors: 
   1.216 ++	movw	$msg1end-msg1, %cx
   1.217 ++	movw	$msg1, %si
   1.218 ++	call	print_str
   1.219 ++
   1.220 ++/* ok, we've written the Loading... message, now we want to load the system */
   1.221 ++
   1.222 ++	pushw	%es			/* = ds */
   1.223 ++	movw	$SYSSEG, %ax
   1.224 ++	movw	%ax,%es			/* segment of SYSSEG<<4 */
   1.225 ++	pushw	%es
   1.226 ++	call	read_it
   1.227 ++
   1.228 ++/* This turns off the floppy drive motor, so that we enter the kernel in a
   1.229 ++ * known state, and don't have to worry about it later.
   1.230 ++ */
   1.231 ++	movw	$0x3f2, %dx
   1.232 ++	xorb	%al,%al
   1.233 ++	outb	%al,%dx
   1.234 ++
   1.235 ++	call	print_nl
   1.236 ++	pop	%es			/* = SYSSEG */
   1.237 ++	pop	%es			/* balance push/pop es */
   1.238 ++sigok: 
   1.239 ++
   1.240 ++/* Restore original disk parameters */
   1.241 ++	movw	$0x78, %bx
   1.242 ++	movw	dpoff, %di
   1.243 ++	movw	dpseg, %si
   1.244 ++	xorw	%ax,%ax
   1.245 ++	movw	%ax,%ds
   1.246 ++	movw	%di,(%bx)
   1.247 ++	movw	%si,2(%bx)
   1.248 ++
   1.249 ++/* after that (everything loaded), we call to the .ROM file loaded. */
   1.250 ++
   1.251 ++	movw	$SYSSEG, %ax
   1.252 ++	jmp	go_setup_code
   1.253 ++
   1.254 ++/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
   1.255 ++ * boundaries are crossed. We try to load it as fast as possible, loading whole
   1.256 ++ * tracks whenever we can.
   1.257 ++ *
   1.258 ++ * in:	es - starting address segment (normally SYSSEG)
   1.259 ++ */
   1.260 ++read_it: 
   1.261 ++	movw	$0,sread		/* read whole image incl boot sector */
   1.262 ++	movw	%es,%ax
   1.263 ++	testw	$0x0fff, %ax
   1.264 ++die:	jne	die			/* es must be at 64kB boundary */
   1.265 ++	xorw	%bx,%bx			/* bx is starting address within segment */
   1.266 ++rp_read: 
   1.267 ++	movw	%es,%ax
   1.268 ++	movw	%bx,%dx
   1.269 ++	movb	$4, %cl
   1.270 ++	shrw	%cl,%dx			/* bx is always divisible by 16 */
   1.271 ++	addw	%dx,%ax
   1.272 ++	cmpw	$SYSSEG+SYSSIZE, %ax	/* have we loaded all yet? */
   1.273 ++	jb	ok1_read
   1.274 ++	ret
   1.275 ++ok1_read: 
   1.276 ++	movw	sectors, %ax
   1.277 ++	subw	sread, %ax
   1.278 ++	movw	%ax,%cx
   1.279 ++	shlw	$9, %cx			/* 80186 opcode */
   1.280 ++	addw	%bx,%cx
   1.281 ++	jnc	ok2_read
   1.282 ++	je	ok2_read
   1.283 ++	xorw	%ax,%ax
   1.284 ++	subw	%bx,%ax
   1.285 ++	shrw	$9, %ax			/* 80186 opcode */
   1.286 ++ok2_read: 
   1.287 ++	call	read_track
   1.288 ++	movw	%ax,%cx
   1.289 ++	addw	sread, %ax
   1.290 ++	cmpw	sectors, %ax
   1.291 ++	jne	ok3_read
   1.292 ++	movw	$1, %ax
   1.293 ++	subw	head, %ax
   1.294 ++	jne	ok4_read
   1.295 ++	incw	track
   1.296 ++ok4_read: 
   1.297 ++	movw	%ax, head
   1.298 ++	xorw	%ax,%ax
   1.299 ++ok3_read: 
   1.300 ++	movw	%ax, sread
   1.301 ++	shlw	$9, %cx			/* 80186 opcode */
   1.302 ++	addw	%cx,%bx
   1.303 ++	jnc	rp_read
   1.304 ++	movw	%es,%ax
   1.305 ++	addb	$0x10, %ah
   1.306 ++	movw	%ax,%es
   1.307 ++	xorw	%bx,%bx
   1.308 ++	jmp	rp_read
   1.309 ++
   1.310 ++read_track: 
   1.311 ++	pusha				/* 80186 opcode */
   1.312 ++	pushw	%ax
   1.313 ++	pushw	%bx
   1.314 ++	pushw	%bp			/* just in case the BIOS is buggy */
   1.315 ++	movb	$0x2e, %al		/* 0x2e = . */
   1.316 ++	call	print_char
   1.317 ++	popw	%bp
   1.318 ++	popw	%bx
   1.319 ++	popw	%ax
   1.320 ++
   1.321 ++	movw	sread, %cx
   1.322 ++	incw	%cx
   1.323 ++	movb	track, %ch
   1.324 ++	movw	$0x0100, %dx
   1.325 ++	andb	head, %dh
   1.326 ++	movb	$2, %ah
   1.327 ++
   1.328 ++	pushw	%dx			/* save for error dump */
   1.329 ++	pushw	%cx
   1.330 ++	pushw	%bx
   1.331 ++	pushw	%ax
   1.332 ++
   1.333 ++	int	$0x13
   1.334 ++	jc	bad_rt
   1.335 ++	addw	$8, %sp
   1.336 ++	popa				/* 80186 opcode */
   1.337 ++	ret
   1.338 ++
   1.339 ++bad_rt: pushw	%ax			/* save error code */
   1.340 ++	call	print_all		/* ah = error, al = read */
   1.341 ++
   1.342 ++	xorb	%ah,%ah
   1.343 ++	xorb	%dl,%dl
   1.344 ++	int	$0x13
   1.345 ++
   1.346 ++	addw	$10, %sp
   1.347 ++	popa				/* 80186 opcode */
   1.348 ++	jmp	read_track
   1.349 ++
   1.350 ++/* print_all is for debugging purposes.	It will print out all of the registers.
   1.351 ++ * The assumption is that this is called from a routine, with a stack frame like
   1.352 ++ *	dx
   1.353 ++ *	cx
   1.354 ++ *	bx
   1.355 ++ *	ax
   1.356 ++ *	error
   1.357 ++ *	ret <- sp
   1.358 ++ */
   1.359 ++
   1.360 ++print_all: 
   1.361 ++	call	print_nl		/* nl for readability */
   1.362 ++					/* print_nl update ah and bx */
   1.363 ++	movw	$5, %cx			/* error code + 4 registers */
   1.364 ++	movw	%sp,%bp
   1.365 ++
   1.366 ++print_loop: 
   1.367 ++	pushw	%cx			/* save count left */
   1.368 ++
   1.369 ++	cmpb	$5, %cl
   1.370 ++	jae	no_reg			/* see if register name is needed */
   1.371 ++
   1.372 ++	movb	$0x5+0x41-1, %al
   1.373 ++	subb	%cl,%al
   1.374 ++	int	$0x10
   1.375 ++
   1.376 ++	movb	$0x58, %al		/* 'X' */
   1.377 ++	int	$0x10
   1.378 ++
   1.379 ++	movb	$0x3A, %al		/* ':' */
   1.380 ++	int	$0x10
   1.381 ++
   1.382 ++no_reg: 
   1.383 ++	addw	$2, %bp			/* next register */
   1.384 ++	call	print_hex		/* print it */
   1.385 ++	movb	$0x20, %al		/* print a space */
   1.386 + 	int	$0x10
   1.387 ++	popw	%cx
   1.388 ++	loop	print_loop
   1.389 ++					/* nl for readability */
   1.390 ++print_nl: 
   1.391 ++	movb	$0xd, %al		/* CR */
   1.392 ++	call	print_char
   1.393 ++	movb	$0xa, %al		/* LF */
   1.394 ++	jmp	print_char
   1.395 ++
   1.396 ++
   1.397 ++print_str: 
   1.398 ++prloop: 
   1.399 ++	lodsb
   1.400 ++	call	print_char
   1.401 + 	loop	prloop
   1.402 +-freeze: jmp	freeze
   1.403 ++	ret
   1.404 ++
   1.405 ++/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
   1.406 ++
   1.407 ++print_hex: 
   1.408 ++	movw	(%bp),%dx		/* load word into dx */
   1.409 ++	movb	$4, %cl
   1.410 ++	call	print_2digits
   1.411 ++print_2digits: 
   1.412 ++	call	print_digit
   1.413 ++/* fall through */
   1.414 ++print_digit: 
   1.415 ++	rol	%cl,%dx			/* rotate to use lowest 4 bits */
   1.416 ++	movb	$0x0f, %al		/* mask for nybble */
   1.417 ++	andb	%dl,%al
   1.418 ++	addb	$0x90, %al		/* convert al to ascii hex */
   1.419 ++	daa				/* (four instructions) */
   1.420 ++	adcb	$0x40, %al
   1.421 ++	daa
   1.422 ++print_char:
   1.423 ++	movb	$0x0e, %ah		/* write char, tty mode */
   1.424 ++	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
   1.425 ++	int	$0x10
   1.426 ++	ret
   1.427 ++
   1.428 ++sread:	.word 0				/* sectors read of current track */
   1.429 ++head:	.word 0				/* current head */
   1.430 ++track:	.word 0				/* current track */
   1.431 ++
   1.432 ++sectors: 
   1.433 ++	.word 0
   1.434 ++
   1.435 ++dpseg:	.word 0
   1.436 ++dpoff:	.word 0
   1.437 + 
   1.438 +-why:	.ascii	"This image cannot be loaded from a floppy disk.\r\n"
   1.439 +-why_end: 
   1.440 ++disksizes: 
   1.441 ++	.byte 36,18,15,9,0
   1.442 + 
   1.443 ++msg1: 
   1.444 ++	.ascii "Loading ROM image"
   1.445 ++msg1end: 
   1.446 + 
   1.447 + 	.org	497
   1.448 + setup_sects: 
   1.449 +@@ -117,15 +402,22 @@
   1.450 + 	whose entry point is SYSSEG:0.
   1.451 + */
   1.452 + setup_code: 
   1.453 +-	pushl	$0		/* No parameters to preserve for exit path */
   1.454 +-	pushw	$0		/* Use prefix exit path mechanism */
   1.455 ++	movw	$(SYSSEG-(PREFIXSIZE/16)), %ax
   1.456 + 	/* Etherboot expects to be contiguous in memory once loaded.
   1.457 + 	 * LILO doesn't do this, but since we don't need any
   1.458 + 	 * information that's left in the prefix, it doesn't matter:
   1.459 + 	 * we just have to ensure that %cs:0000 is where the start of
   1.460 + 	 * the Etherboot image *would* be.
   1.461 + 	 */
   1.462 +-	ljmp	$(SYSSEG-(PREFIXSIZE/16)), $_start
   1.463 ++go_setup_code: 
   1.464 ++	xorw	%cx, %cx
   1.465 ++	pushw	%cx
   1.466 ++	pushw	%cx		/* No parameters to preserve for exit path */
   1.467 ++	pushw	%cx		/* Use prefix exit path mechanism */
   1.468 ++	pushw	%ax
   1.469 ++	pushw	$_start
   1.470 ++	/* Calculated lcall to _start with %cs:0000 = image start */
   1.471 ++	lret
   1.472 + 
   1.473 + 	.section ".text16", "ax", @progbits
   1.474 + 	.globl	prefix_exit
   1.475 +
   1.476 +--- etherboot-5.4.3/src/arch/i386/prefix/bImageprefix.S
   1.477 ++++ etherboot-5.4.3/src/arch/i386/prefix/bImageprefix.S
   1.478 +@@ -82,6 +82,14 @@
   1.479 + #define SIG1	0xAA55
   1.480 + #define SIG2	0x5A5A
   1.481 + 
   1.482 ++/* SYS_SIZE is the number of clicks (16 bytes) to be loaded.  For Etherboot
   1.483 ++ * purposes, we need to load everything but the boot sector itself, i.e. 32
   1.484 ++ * clicks less than the size of the entire (verbatim) image.  The image size
   1.485 ++ * is practically limited only by the available base memory size.
   1.486 ++ */
   1.487 ++.globl	SYSSIZE
   1.488 ++.equ	SYSSIZE, _verbatim_size_pgh - 32
   1.489 ++
   1.490 + 	.text
   1.491 + 	.code16
   1.492 + 	.arch i386
   1.493 +@@ -90,40 +98,349 @@
   1.494 + 	.globl	_prefix
   1.495 + _prefix:
   1.496 + 
   1.497 +-/* 
   1.498 +-	This is a minimal boot sector.	If anyone tries to execute it (e.g., if
   1.499 +-	a .lilo file is dd'ed to a floppy), print an error message. 
   1.500 +-*/
   1.501 ++	call	here
   1.502 ++here:
   1.503 ++	pop	%ax
   1.504 ++	cmpw	$0x103, %ax		/* COM entry point is cs:0x100 */
   1.505 ++	jne	bootsector
   1.506 ++
   1.507 ++/* We need a real mode stack that won't be stomped on by Etherboot
   1.508 ++   which starts at 0x20000. Choose something that's sufficiently high,
   1.509 ++   but not in DOC territory. Note that we couldn't do this in a real
   1.510 ++   .com program since stack variables are in the same segment as the
   1.511 ++   code and data, but this isn't really a .com program, it just looks
   1.512 ++   like one to make DOS load it into memory. It still has the 64kB
   1.513 ++   limitation of .com files though. */
   1.514 ++#define STACK_SEG	0x7000
   1.515 ++#define STACK_SIZE	0x4000
   1.516 ++	/* Set up temporary stack */ 
   1.517 ++	movw	$STACK_SEG, %ax
   1.518 ++	movw	%ax, %ss
   1.519 ++	movw	$STACK_SIZE, %sp
   1.520 ++
   1.521 ++	/* Calculate segment address of image start */
   1.522 ++	pushw	%cs
   1.523 ++	popw	%ax
   1.524 ++	addw	$(0x100/16), %ax
   1.525 ++	jmp	go_setup_code
   1.526 + 
   1.527 +-bootsector: 
   1.528 +-	jmp	$BOOTSEG, $go - _prefix	/* reload cs:ip to match relocation addr */
   1.529 ++bootsector:
   1.530 ++	jmp	$BOOTSEG, $go		/* reload cs:ip to match relocation addr */
   1.531 + go: 
   1.532 +-	movw	$0x2000, %di		/*  0x2000 is arbitrary value >= length
   1.533 +-					    of bootsect + room for stack */
   1.534 ++	movw	$0x2000-12, %di		/* 0x2000 is arbitrary value >= length */
   1.535 ++					/* of bootsect + room for stack + 12 for */
   1.536 ++					/* saved disk parm block */
   1.537 + 
   1.538 + 	movw	$BOOTSEG, %ax
   1.539 + 	movw	%ax,%ds
   1.540 + 	movw	%ax,%es
   1.541 +-
   1.542 +-	cli
   1.543 +-	movw	%ax, %ss		/* put stack at BOOTSEG:0x2000. */
   1.544 ++	movw	%ax,%ss			/* put stack at initial position */
   1.545 + 	movw	%di,%sp
   1.546 +-	sti
   1.547 + 
   1.548 +-	movw	$why_end-why, %cx
   1.549 +-	movw	$why - _prefix, %si
   1.550 ++/* Many BIOS's default disk parameter tables will not recognize multi-sector
   1.551 ++ * reads beyond the maximum sector number specified in the default diskette
   1.552 ++ * parameter tables - this may mean 7 sectors in some cases.
   1.553 ++ *
   1.554 ++ * Since single sector reads are slow and out of the question, we must take care
   1.555 ++ * of this by creating new parameter tables (for the first disk) in RAM.  We
   1.556 ++ * will set the maximum sector count to 36 - the most we will encounter on an
   1.557 ++ * ED 2.88.  High doesn't hurt.	Low does.
   1.558 ++ *
   1.559 ++ * Segments are as follows: ds=es=ss=cs - BOOTSEG
   1.560 ++ */
   1.561 ++
   1.562 ++	xorw	%cx,%cx
   1.563 ++	movw	%cx,%es			/* access segment 0 */
   1.564 ++	movw	$0x78, %bx		/* 0:bx is parameter table address */
   1.565 ++	pushw	%ds			/* save ds */
   1.566 ++/* 0:bx is parameter table address */
   1.567 ++	ldsw	%es:(%bx),%si		/* loads ds and si */
   1.568 ++
   1.569 ++	movw	%ax,%es			/* ax is BOOTSECT (loaded above) */
   1.570 ++	movb	$6, %cl			/* copy 12 bytes */
   1.571 ++	cld
   1.572 ++	pushw	%di			/* keep a copy for later */
   1.573 ++	rep
   1.574 ++	movsw				/* ds:si is source, es:di is dest */
   1.575 ++	popw	%di
   1.576 + 
   1.577 +-	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
   1.578 +-	movb	$0x0e, %ah		/* write char, tty mode */
   1.579 +-prloop: 
   1.580 ++	movb	$36,%es:4(%di)
   1.581 ++
   1.582 ++	movw	%cx,%ds			/* access segment 0 */
   1.583 ++	xchgw	%di,(%bx)
   1.584 ++	movw	%es,%si
   1.585 ++	xchgw	%si,2(%bx)
   1.586 ++	popw	%ds			/* restore ds */
   1.587 ++	movw	%di, dpoff		/* save old parameters */
   1.588 ++	movw	%si, dpseg		/* to restore just before finishing */
   1.589 ++	pushw	%ds
   1.590 ++	popw	%es			/* reload es */
   1.591 ++
   1.592 ++/* Note that es is already set up.  Also cx is 0 from rep movsw above. */
   1.593 ++
   1.594 ++	xorb	%ah,%ah			/* reset FDC */
   1.595 ++	xorb	%dl,%dl
   1.596 ++	int	$0x13
   1.597 ++
   1.598 ++/* Get disk drive parameters, specifically number of sectors/track.
   1.599 ++ *
   1.600 ++ * It seems that there is no BIOS call to get the number of sectors.  Guess
   1.601 ++ * 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
   1.602 ++ * 15 if sector 15 can be read.	Otherwise guess 9.
   1.603 ++ */
   1.604 ++
   1.605 ++	movw	$disksizes, %si		/* table of sizes to try */
   1.606 ++
   1.607 ++probe_loop: 
   1.608 + 	lodsb
   1.609 ++	orb	%al, %al
   1.610 ++	je	got_sectors		/* if all else fails, try 9 */
   1.611 ++	cbtw				/* extend to word */
   1.612 ++	movw	%ax, sectors
   1.613 ++	xchgw	%cx,%ax			/* cx = track and sector */
   1.614 ++	xorw	%dx,%dx			/* drive 0, head 0 */
   1.615 ++	movw	$0x0200, %bx		/* address after boot sector */
   1.616 ++					/*   (512 bytes from origin, es = cs) */
   1.617 ++	movw	$0x0201, %ax		/* service 2, 1 sector */
   1.618 ++	int	$0x13
   1.619 ++	jc	probe_loop		/* try next value */
   1.620 ++
   1.621 ++got_sectors: 
   1.622 ++	movw	$msg1end-msg1, %cx
   1.623 ++	movw	$msg1, %si
   1.624 ++	call	print_str
   1.625 ++
   1.626 ++/* ok, we've written the Loading... message, now we want to load the system */
   1.627 ++
   1.628 ++	pushw	%es			/* = ds */
   1.629 ++	movw	$SYSSEG, %ax
   1.630 ++	movw	%ax,%es			/* segment of SYSSEG<<4 */
   1.631 ++	pushw	%es
   1.632 ++	call	read_it
   1.633 ++
   1.634 ++/* This turns off the floppy drive motor, so that we enter the kernel in a
   1.635 ++ * known state, and don't have to worry about it later.
   1.636 ++ */
   1.637 ++	movw	$0x3f2, %dx
   1.638 ++	xorb	%al,%al
   1.639 ++	outb	%al,%dx
   1.640 ++
   1.641 ++	call	print_nl
   1.642 ++	pop	%es			/* = SYSSEG */
   1.643 ++	pop	%es			/* balance push/pop es */
   1.644 ++sigok: 
   1.645 ++
   1.646 ++/* Restore original disk parameters */
   1.647 ++	movw	$0x78, %bx
   1.648 ++	movw	dpoff, %di
   1.649 ++	movw	dpseg, %si
   1.650 ++	xorw	%ax,%ax
   1.651 ++	movw	%ax,%ds
   1.652 ++	movw	%di,(%bx)
   1.653 ++	movw	%si,2(%bx)
   1.654 ++
   1.655 ++/* after that (everything loaded), we call to the .ROM file loaded. */
   1.656 ++
   1.657 ++	movw	$SYSSEG, %ax
   1.658 ++go_setup_code: 
   1.659 ++	xorw	%cx, %cx
   1.660 ++	pushw	%cx
   1.661 ++	pushw	%cx		/* No parameters to preserve for exit path */
   1.662 ++	pushw	%cx		/* Use prefix exit path mechanism */
   1.663 ++	pushw	%ax
   1.664 ++	pushw	$_start
   1.665 ++	/* Calculated lcall to _start with %cs:0000 = image start */
   1.666 ++	lret
   1.667 ++
   1.668 ++/* This routine loads the system at address SYSSEG<<4, making sure no 64kB
   1.669 ++ * boundaries are crossed. We try to load it as fast as possible, loading whole
   1.670 ++ * tracks whenever we can.
   1.671 ++ *
   1.672 ++ * in:	es - starting address segment (normally SYSSEG)
   1.673 ++ */
   1.674 ++read_it: 
   1.675 ++	movw	$0,sread		/* read whole image incl boot sector */
   1.676 ++	movw	%es,%ax
   1.677 ++	testw	$0x0fff, %ax
   1.678 ++die:	jne	die			/* es must be at 64kB boundary */
   1.679 ++	xorw	%bx,%bx			/* bx is starting address within segment */
   1.680 ++rp_read: 
   1.681 ++	movw	%es,%ax
   1.682 ++	movw	%bx,%dx
   1.683 ++	movb	$4, %cl
   1.684 ++	shrw	%cl,%dx			/* bx is always divisible by 16 */
   1.685 ++	addw	%dx,%ax
   1.686 ++	cmpw	$SYSSEG+SYSSIZE, %ax	/* have we loaded all yet? */
   1.687 ++	jb	ok1_read
   1.688 ++	ret
   1.689 ++ok1_read: 
   1.690 ++	movw	sectors, %ax
   1.691 ++	subw	sread, %ax
   1.692 ++	movw	%ax,%cx
   1.693 ++	shlw	$9, %cx			/* 80186 opcode */
   1.694 ++	addw	%bx,%cx
   1.695 ++	jnc	ok2_read
   1.696 ++	je	ok2_read
   1.697 ++	xorw	%ax,%ax
   1.698 ++	subw	%bx,%ax
   1.699 ++	shrw	$9, %ax			/* 80186 opcode */
   1.700 ++ok2_read: 
   1.701 ++	call	read_track
   1.702 ++	movw	%ax,%cx
   1.703 ++	addw	sread, %ax
   1.704 ++	cmpw	sectors, %ax
   1.705 ++	jne	ok3_read
   1.706 ++	movw	$1, %ax
   1.707 ++	subw	head, %ax
   1.708 ++	jne	ok4_read
   1.709 ++	incw	track
   1.710 ++ok4_read: 
   1.711 ++	movw	%ax, head
   1.712 ++	xorw	%ax,%ax
   1.713 ++ok3_read: 
   1.714 ++	movw	%ax, sread
   1.715 ++	shlw	$9, %cx			/* 80186 opcode */
   1.716 ++	addw	%cx,%bx
   1.717 ++	jnc	rp_read
   1.718 ++	movw	%es,%ax
   1.719 ++	addb	$0x10, %ah
   1.720 ++	movw	%ax,%es
   1.721 ++	xorw	%bx,%bx
   1.722 ++	jmp	rp_read
   1.723 ++
   1.724 ++read_track: 
   1.725 ++	pusha				/* 80186 opcode */
   1.726 ++	pushw	%ax
   1.727 ++	pushw	%bx
   1.728 ++	pushw	%bp			/* just in case the BIOS is buggy */
   1.729 ++	movb	$0x2e, %al		/* 0x2e = . */
   1.730 ++	call	print_char
   1.731 ++	popw	%bp
   1.732 ++	popw	%bx
   1.733 ++	popw	%ax
   1.734 ++
   1.735 ++	movw	sread, %cx
   1.736 ++	incw	%cx
   1.737 ++	movb	track, %ch
   1.738 ++	movw	$0x0100, %dx
   1.739 ++	andb	head, %dh
   1.740 ++	movb	$2, %ah
   1.741 ++
   1.742 ++	pushw	%dx			/* save for error dump */
   1.743 ++	pushw	%cx
   1.744 ++	pushw	%bx
   1.745 ++	pushw	%ax
   1.746 ++
   1.747 ++	int	$0x13
   1.748 ++	jc	bad_rt
   1.749 ++	addw	$8, %sp
   1.750 ++	popa				/* 80186 opcode */
   1.751 ++	ret
   1.752 ++
   1.753 ++bad_rt: pushw	%ax			/* save error code */
   1.754 ++	call	print_all		/* ah = error, al = read */
   1.755 ++
   1.756 ++	xorb	%ah,%ah
   1.757 ++	xorb	%dl,%dl
   1.758 ++	int	$0x13
   1.759 ++
   1.760 ++	addw	$10, %sp
   1.761 ++	popa				/* 80186 opcode */
   1.762 ++	jmp	read_track
   1.763 ++
   1.764 ++/* print_all is for debugging purposes.	It will print out all of the registers.
   1.765 ++ * The assumption is that this is called from a routine, with a stack frame like
   1.766 ++ *	dx
   1.767 ++ *	cx
   1.768 ++ *	bx
   1.769 ++ *	ax
   1.770 ++ *	error
   1.771 ++ *	ret <- sp
   1.772 ++ */
   1.773 ++
   1.774 ++print_all: 
   1.775 ++	call	print_nl		/* nl for readability */
   1.776 ++					/* print_nl update ah and bx */
   1.777 ++	movw	$5, %cx			/* error code + 4 registers */
   1.778 ++	movw	%sp,%bp
   1.779 ++
   1.780 ++print_loop: 
   1.781 ++	pushw	%cx			/* save count left */
   1.782 ++
   1.783 ++	cmpb	$5, %cl
   1.784 ++	jae	no_reg			/* see if register name is needed */
   1.785 ++
   1.786 ++	movb	$0x5+0x41-1, %al
   1.787 ++	subb	%cl,%al
   1.788 + 	int	$0x10
   1.789 ++
   1.790 ++	movb	$0x58, %al		/* 'X' */
   1.791 ++	int	$0x10
   1.792 ++
   1.793 ++	movb	$0x3A, %al		/* ':' */
   1.794 ++	int	$0x10
   1.795 ++
   1.796 ++no_reg: 
   1.797 ++	addw	$2, %bp			/* next register */
   1.798 ++	call	print_hex		/* print it */
   1.799 ++	movb	$0x20, %al		/* print a space */
   1.800 ++	int	$0x10
   1.801 ++	popw	%cx
   1.802 ++	loop	print_loop
   1.803 ++					/* nl for readability */
   1.804 ++print_nl: 
   1.805 ++	movb	$0xd, %al		/* CR */
   1.806 ++	call	print_char
   1.807 ++	movb	$0xa, %al		/* LF */
   1.808 ++	jmp	print_char
   1.809 ++
   1.810 ++
   1.811 ++print_str: 
   1.812 ++prloop: 
   1.813 ++	lodsb
   1.814 ++	call	print_char
   1.815 + 	loop	prloop
   1.816 +-freeze: jmp	freeze
   1.817 ++	ret
   1.818 + 
   1.819 +-why:	.ascii	"This image cannot be loaded from a floppy disk.\r\n"
   1.820 +-why_end: 
   1.821 ++/* print_hex prints the word pointed to by ss:bp in hexadecimal. */
   1.822 ++
   1.823 ++print_hex: 
   1.824 ++	movw	(%bp),%dx		/* load word into dx */
   1.825 ++	movb	$4, %cl
   1.826 ++	call	print_2digits
   1.827 ++print_2digits: 
   1.828 ++	call	print_digit
   1.829 ++/* fall through */
   1.830 ++print_digit: 
   1.831 ++	rol	%cl,%dx			/* rotate to use lowest 4 bits */
   1.832 ++	movb	$0x0f, %al		/* mask for nybble */
   1.833 ++	andb	%dl,%al
   1.834 ++	addb	$0x90, %al		/* convert al to ascii hex */
   1.835 ++	daa				/* (four instructions) */
   1.836 ++	adcb	$0x40, %al
   1.837 ++	daa
   1.838 ++print_char:
   1.839 ++	movb	$0x0e, %ah		/* write char, tty mode */
   1.840 ++	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
   1.841 ++	int	$0x10
   1.842 ++	ret
   1.843 + 
   1.844 ++sread:	.word 0				/* sectors read of current track */
   1.845 ++head:	.word 0				/* current head */
   1.846 ++track:	.word 0				/* current track */
   1.847 ++
   1.848 ++sectors: 
   1.849 ++	.word 0
   1.850 ++
   1.851 ++dpseg:	.word 0
   1.852 ++dpoff:	.word 0
   1.853 ++
   1.854 ++disksizes: 
   1.855 ++	.byte 36,18,15,9,0
   1.856 ++
   1.857 ++msg1: 
   1.858 ++	.ascii "Loading ROM image"
   1.859 ++msg1end: 
   1.860 + 
   1.861 + 	.org	497
   1.862 + setup_sects: