wok diff ipxe/stuff/lkrnprefix.S @ rev 15368

Up ipxe (1.0.0-20130925)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Oct 14 13:38:36 2013 +0000 (2013-10-14)
parents
children 4ae7c7dde4e2
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipxe/stuff/lkrnprefix.S	Mon Oct 14 13:38:36 2013 +0000
     1.3 @@ -0,0 +1,644 @@
     1.4 +/*
     1.5 +	Copyright (C) 2000, Entity Cyber, Inc.
     1.6 +
     1.7 +	Authors: Gary Byers (gb@thinguin.org)
     1.8 +		 Marty Connor (mdc@thinguin.org)
     1.9 +
    1.10 +	This software may be used and distributed according to the terms
    1.11 +	of the GNU Public License (GPL), incorporated herein by reference.
    1.12 +
    1.13 +	Description:	
    1.14 +
    1.15 +	This is just a little bit of code and data that can get prepended
    1.16 +	to a ROM image in order to allow bootloaders to load the result
    1.17 +	as if it were a Linux kernel image.
    1.18 +
    1.19 +	A real Linux kernel image consists of a one-sector boot loader
    1.20 +	(to load the image from a floppy disk), followed a few sectors
    1.21 +	of setup code, followed by the kernel code itself.  There's
    1.22 +	a table in the first sector (starting at offset 497) that indicates
    1.23 +	how many sectors of setup code follow the first sector and which
    1.24 +	contains some other parameters that aren't interesting in this
    1.25 +	case.
    1.26 +
    1.27 +	When a bootloader loads the sectors that comprise a kernel image,
    1.28 +	it doesn't execute the code in the first sector (since that code
    1.29 +	would try to load the image from a floppy disk.)  The code in the
    1.30 +	first sector below doesn't expect to get executed (and prints an
    1.31 +	error message if it ever -is- executed.)
    1.32 +
    1.33 +	We don't require much in the way of setup code.  Historically, the
    1.34 +	Linux kernel required at least 4 sectors of setup code.
    1.35 +	Therefore, at least 4 sectors must be present even though we don't
    1.36 +	use them.
    1.37 +
    1.38 +*/
    1.39 +
    1.40 +FILE_LICENCE ( GPL_ANY )
    1.41 +
    1.42 +#define	SETUPSECS 4		/* Minimal nr of setup-sectors */
    1.43 +#define PREFIXSIZE ((SETUPSECS+1)*512)
    1.44 +#define PREFIXPGH (PREFIXSIZE / 16 )
    1.45 +#define	BOOTSEG  0x07C0		/* original address of boot-sector */
    1.46 +#define	INITSEG  0x9000		/* we move boot here - out of the way */
    1.47 +#define	SETUPSEG 0x9020		/* setup starts here */
    1.48 +#define SYSSEG   0x1000		/* system loaded at 0x10000 (65536). */
    1.49 +
    1.50 +	.text
    1.51 +	.code16
    1.52 +	.arch i386
    1.53 +	.org	0
    1.54 +	.section ".prefix", "ax", @progbits
    1.55 +	.globl	_lkrn_start
    1.56 +_lkrn_start:
    1.57 +
    1.58 +bootsector: 
    1.59 +_start:
    1.60 +
    1.61 +/* some extra features */
    1.62 +#define EXE_SUPPORT		real mode dos .exe file support
    1.63 +
    1.64 +#define EXEADRS(x)	(x+0xE0)
    1.65 +
    1.66 +/* some contraints to reduce the size */
    1.67 +//#define FLOPPY_1440K_ONLY	1.44M floppies support only
    1.68 +
    1.69 +#ifdef EXE_SUPPORT
    1.70 +/* Initial temporary stack size */
    1.71 +#define EXE_STACK_SIZE 0x400
    1.72 +
    1.73 +/* Temporary decompression area (avoid DOS high memory area) */
    1.74 +#define EXE_DECOMPRESS_ADDRESS 0x110000
    1.75 +
    1.76 +/* Fields within the Program Segment Prefix */
    1.77 +#define PSP_CMDLINE_LEN 0x80
    1.78 +#define PSP_CMDLINE_START 0x81
    1.79 +
    1.80 +#define HEADER_SIZE	0x20
    1.81 +
    1.82 +signature:
    1.83 +	decw	%bp			// Magic number: MZ
    1.84 +	popw	%dx
    1.85 +	jmp	start			// Bytes on last page of file
    1.86 +blocks:
    1.87 +	.word	0			// Pages in file
    1.88 +	.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
    1.89 +	.ascii	"ADDW"
    1.90 +	.long	blocks
    1.91 +	.long	512
    1.92 +	.long	0
    1.93 +	.previous
    1.94 +	.word	0			// Relocations
    1.95 +	.word	( HEADER_SIZE / 16 )	// Size of header in paragraphs
    1.96 +	.word	( EXE_STACK_SIZE / 16 )	// Minimum extra paragraphs needed
    1.97 +	.word	( EXE_STACK_SIZE / 16 )	// Maximum extra paragraphs needed
    1.98 +init_ss:
    1.99 +	.word	-( ( _exe_start - signature ) / 16 )	// Initial (relative) SS value
   1.100 +	.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
   1.101 +	.ascii	"ADDW"
   1.102 +	.long	init_ss
   1.103 +	.long	16
   1.104 +	.long	0
   1.105 +	.previous
   1.106 +	.word	EXE_STACK_SIZE		// Initial SP value
   1.107 +	.word	0			// Checksum
   1.108 +	.word	_exe_start		// Initial IP value
   1.109 +	/* Initial code segment (relative to start of executable) */
   1.110 +	//.word	-( ( _exe_start - signature ) / 16 )	// Initial (relative) CS value
   1.111 +	.word	-( HEADER_SIZE / 16 )	// Initial (relative) CS value
   1.112 +//	.word	0x001C			// File address of relocation table
   1.113 +//	.word	0,0,0			// Overlay number
   1.114 +
   1.115 +start:
   1.116 +	pushw	%dx
   1.117 +	xorw	%dx, %dx
   1.118 +#endif
   1.119 +	cld				# assume nothing
   1.120 +stacktop	= 0x9E00		# in 0x8000 .. 0xA000
   1.121 +zeroed		= 12			# zeroed registers
   1.122 +	movw	$stacktop-12-zeroed, %di	# stacktop is an arbitrary value >=
   1.123 +					# length of bootsect + length of
   1.124 +					# setup + room for stack;
   1.125 +					# 12 is disk parm size.
   1.126 +	pushw	$INITSEG
   1.127 +	popw	%ss			# %ss contain INITSEG
   1.128 +	movw	%di, %sp		# put stack at INITSEG:stacktop-...
   1.129 +
   1.130 +# Many BIOS's default disk parameter tables will not recognize
   1.131 +# multi-sector reads beyond the maximum sector number specified
   1.132 +# in the default diskette parameter tables - this may mean 7
   1.133 +# sectors in some cases.
   1.134 +#
   1.135 +# Since single sector reads are slow and out of the question,
   1.136 +# we must take care of this by creating new parameter tables
   1.137 +# (for the first disk) in RAM.  We can set the maximum sector
   1.138 +# count to 36 - the most we will encounter on an ED 2.88.  
   1.139 +#
   1.140 +# High doesn't hurt.  Low does.  Let's use the max: 63
   1.141 +
   1.142 +	pushw	%ss
   1.143 +	popw	%es			# %es = %ss = INITSEG
   1.144 +	xorw	%ax, %ax		# %ax = 0
   1.145 +	movw	$zeroed/2, %cx		# clear gdt + offset, %ds, limits
   1.146 +	rep				# don't worry about cld
   1.147 +	stosw				# already done above
   1.148 +	popw	%bx			# offset = 0
   1.149 +	popw	%ds			# %ds = 0
   1.150 +	popw	%fs			# %fs = 0
   1.151 +
   1.152 +	movb	setup_sects+0x7C00, %al	# read bootsector + setup (%ds = 0)
   1.153 +	incw	%ax
   1.154 +
   1.155 +	ldsw	0x78(%bx), %si		# %ds:%bx+0x78 is parameter table address
   1.156 +	pushw	%es
   1.157 +	pushw	%di
   1.158 +	movb	$6, %cl			# copy 12 bytes
   1.159 +	rep				# don't worry about cld
   1.160 +	movsw				# already done above
   1.161 +	pushw	%ss
   1.162 +	popw	%ds			# now %ds = %es = %ss = INITSEG
   1.163 +	popl	%fs:0x78(%bx)		# update parameter table address
   1.164 +	movb	$63, 0x4-12(%di)	# patch sector count, %di = stacktop
   1.165 +	cli
   1.166 +
   1.167 +	xchg	%ax, %di		# sector count
   1.168 +	popw	%ax			# limits = 0
   1.169 +	incw	%cx			# cylinder 0, sector 1, clear Z
   1.170 +	call	read_first_sectors	# read setup
   1.171 +
   1.172 +# This routine loads the system at address LOADSEG, making sure
   1.173 +# no 64kB boundaries are crossed. We try to load it as fast as
   1.174 +# possible, loading whole tracks whenever we can.
   1.175 +
   1.176 +	popw	%bx			# clear %bx
   1.177 +	movw	syssize, %di
   1.178 +	addw	$(512/16)-1, %di
   1.179 +	shrw	$9-4, %di
   1.180 +	movw	$SYSSEG, %cx
   1.181 +	call	read_sectorsCX
   1.182 +
   1.183 +# This procedure turns off the floppy drive motor, so
   1.184 +# that we enter the kernel in a known state, and
   1.185 +# don't have to worry about it later.
   1.186 +
   1.187 +kill_motor:
   1.188 +	xchgw	%ax, %di		# reset FDC (%di < 128)
   1.189 +	int	$0x13
   1.190 +
   1.191 +# After that (everything loaded), we jump to the setup-routine
   1.192 +# loaded directly after the bootblock:
   1.193 +# Segments are as follows: %ds = %ss = INITSEG
   1.194 +
   1.195 +	ljmp	$SETUPSEG, $0
   1.196 +
   1.197 +#ifdef EXE_SUPPORT
   1.198 +dosexit:
   1.199 +	movw	$0x4c00, %ax
   1.200 +	int	$0x21
   1.201 +
   1.202 +_exe_start:
   1.203 +	pushw	$dosexit
   1.204 +	movw	$EXEADRS(need386), %si
   1.205 +	pushfw			// save flags
   1.206 +		// bits  15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
   1.207 +		// flags  0 NT  IOPL OF DF IF TF SF ZF  0 AF  0 PF  1 CF
   1.208 +	movb	$0x10, %ah	// DF = IF = TF = 0
   1.209 +	pushw	%ax
   1.210 +	popfw			// < 286 : flags[12..15] are forced 1
   1.211 +	pushfw			// = 286 : flags[12..15] are forced 0
   1.212 +	popw	%cx		// > 286 : only flags[15] is forced 0
   1.213 +	popfw			// restore flags
   1.214 +	addb	%ah, %ch	// test F0 and 00 cases
   1.215 +	cmpb	%ah, %ch
   1.216 +	jbe	puts		// C=8086/80186, Z=80286
   1.217 +//	smsww	%ax
   1.218 +//	andb	$1, %al
   1.219 +//	jne	puts
   1.220 +
   1.221 +	/* Terminate command line with a NUL */
   1.222 +	movzbw	PSP_CMDLINE_LEN, %si
   1.223 +	movb	$0, PSP_CMDLINE_START(%si)
   1.224 +	cmpb	$'?', PSP_CMDLINE_START-1(%si)
   1.225 +	je	help
   1.226 +	pushw	%si
   1.227 +
   1.228 +	/* Install iPXE.  Use a fixed temporary decompression area to
   1.229 +	 * avoid trashing the DOS high memory area.
   1.230 +	 */
   1.231 +	call	alloc_basemem
   1.232 +	movl	$EXE_DECOMPRESS_ADDRESS, %edi
   1.233 +	stc
   1.234 +	sbbl	%ebp, %ebp		/* Allow arbitrary relocation */
   1.235 +	xorl	%esi, %esi
   1.236 +	call	install_prealloc
   1.237 +
   1.238 +	xorl	%ebp, %ebp
   1.239 +	xorl	%ecx, %ecx
   1.240 +
   1.241 +	/* Calculate command line physical address */
   1.242 +	xorl	%edx, %edx
   1.243 +	movw	%ds, %dx
   1.244 +	shll	$4, %edx
   1.245 +	popw	%si
   1.246 +	orw	%si, %si
   1.247 +	jne	gotarg
   1.248 +	movw	$EXEADRS(default_config), %bp
   1.249 +	addl	%edx, %ebp
   1.250 +	movw	$0xA00-default_config, %cx
   1.251 +gotarg:
   1.252 +	addl	$PSP_CMDLINE_START, %edx
   1.253 +	
   1.254 +	jmp	start_ipxe
   1.255 +
   1.256 +help:
   1.257 +	movw	$EXEADRS(helpmsg), %si
   1.258 +puts:
   1.259 +	lodsb
   1.260 +	orb	%al, %al
   1.261 +	je	exit
   1.262 +	call	putc
   1.263 +	jmp	puts
   1.264 +#endif
   1.265 +
   1.266 +putcdot:
   1.267 +	movb	$0x2E, %al
   1.268 +putc:
   1.269 +	movb	$0xE, %ah
   1.270 +	movw	$7, %bx
   1.271 +	int	$0x10
   1.272 +exit:
   1.273 +	ret
   1.274 +
   1.275 +
   1.276 +# read_sectors reads %di sectors into %es:0 buffer.
   1.277 +# %es:0 is updated to the next memory location.
   1.278 +# First, sectors are read sector by sector until
   1.279 +# sector per track count is known. Then they are
   1.280 +# read track by track.
   1.281 +# Assume no error on first track.
   1.282 +
   1.283 +#ifdef FLOPPY_1440K_ONLY
   1.284 +#define FLOPPY_HEADS		2	/* 2 heads */
   1.285 +#define FLOPPY_SECTORS		18	/* 18 sectors */
   1.286 +#else
   1.287 +#define FLOPPY_HEADS		2	/* 2 heads minimum */
   1.288 +#define FLOPPY_SECTORS		9	/* 9 sectors minimum */
   1.289 +#endif
   1.290 +
   1.291 +check_limits:
   1.292 +#ifndef FLOPPY_1440K_ONLY
   1.293 +	popw	%dx
   1.294 +#ifdef FLOPPY_SECTORS
   1.295 +	cmpb	$FLOPPY_SECTORS+1, %cl	# minimum sector count
   1.296 +	jb	check_head
   1.297 +#endif
   1.298 +        cmpb    %al, %cl		# max sector known ?
   1.299 +        ja	next_head		#   no -> store it
   1.300 +check_head:
   1.301 +#ifdef FLOPPY_HEADS
   1.302 +	cmpb	$FLOPPY_HEADS, %dh	# 2 heads minimum
   1.303 +	jb	check_cylinder
   1.304 +#endif
   1.305 +        cmpb    %ah, %dh		# max head known ?
   1.306 +        ja	next_cylinder		#   no -> store it
   1.307 +check_cylinder:
   1.308 +#endif
   1.309 +	pushaw
   1.310 +#ifndef FLOPPY_1440K_ONLY
   1.311 +	cbw				# %ah = 0
   1.312 +#endif
   1.313 +        int     $0x13			# reset controler
   1.314 +	popaw
   1.315 +	movb	$1, %al			# sector by sector...
   1.316 +read_sectorslp:
   1.317 +	pushw	%dx			# some bios break dx...
   1.318 +#ifndef FLOPPY_1440K_ONLY
   1.319 +        pushw   %ax			# limits
   1.320 +	subb	%cl, %al		# sectors remaining in track
   1.321 +	ja	tolastsect
   1.322 +	movb	$1, %al			# 1 sector mini
   1.323 +tolastsect:
   1.324 +#else
   1.325 +	mov	$FLOPPY_SECTORS+1, %al
   1.326 +	subb	%cl, %al		# sectors remaining in track
   1.327 +#endif
   1.328 +	cbw
   1.329 +	cmpw	%di, %ax
   1.330 +	jb	more1trk
   1.331 +	movw	%di, %ax		# sectors to read
   1.332 +more1trk:
   1.333 +	pushw	%ax			# save context
   1.334 +	movb	$2, %ah			# cmd: read chs
   1.335 +        int     $0x13
   1.336 +#ifndef FLOPPY_1440K_ONLY
   1.337 +	popw	%dx			# save %ax
   1.338 +        popw    %ax			# limits
   1.339 +#else
   1.340 +	popw	%ax			# restore context
   1.341 +	popw	%dx
   1.342 +#endif
   1.343 +	jc	check_limits
   1.344 +#ifndef FLOPPY_1440K_ONLY
   1.345 +	xchgw	%ax, %bp
   1.346 +	addw	%dx,%cx			# next sector
   1.347 +	movw	%cx, %gs
   1.348 +	movw	%es, %cx
   1.349 +	pushw	%dx
   1.350 +	shlw	$5, %dx
   1.351 +	addw	%dx, %cx
   1.352 +	popw	%dx
   1.353 +	subw	%dx,%di			# update sector counter
   1.354 +	popw	%dx
   1.355 +read_sectorsCX:
   1.356 +	movw	%cx, %es		# next location
   1.357 +	jz	putcdot
   1.358 +#else
   1.359 +	addw	%ax,%cx			# next sector
   1.360 +	movw	%cx, %gs
   1.361 +	movw	%es, %cx
   1.362 +	pushw	%ax
   1.363 +	shlw	$5, %ax
   1.364 +	addw	%ax, %cx
   1.365 +	popw	%ax
   1.366 +	subw	%ax,%di			# update sector counter
   1.367 +read_sectorsCX:
   1.368 +	movw	%cx, %es		# next location
   1.369 +	jz	putcdot
   1.370 +#endif
   1.371 +read_sectors:
   1.372 +	movw	%gs, %cx
   1.373 +#ifndef FLOPPY_1440K_ONLY
   1.374 +#   al is last sector+1
   1.375 +#   ah is last cylinder+1
   1.376 +	xchgw	%ax, %bp
   1.377 +#endif
   1.378 +#ifndef FLOPPY_1440K_ONLY
   1.379 +        cmpb    %al,%cl			# reach sector limit ?
   1.380 +        jne     bdendlp
   1.381 +next_head:
   1.382 +        movb    %cl,%al
   1.383 +#else
   1.384 +        cmpb    $FLOPPY_SECTORS+1,%cl	# reach sector limit ?
   1.385 +        jne     bdendlp
   1.386 +#endif
   1.387 +        incb    %dh			# next head
   1.388 +        movb    $1,%cl			# first sector
   1.389 +#ifndef FLOPPY_1440K_ONLY
   1.390 +        cmpb    %ah, %dh		# reach head limit ?
   1.391 +        jne     bdendlp
   1.392 +next_cylinder:
   1.393 +        movb    %dh,%ah
   1.394 +#else
   1.395 +        cmpb    %cl,%dh			# reach head limit ?
   1.396 +        je	bdendlp
   1.397 +#endif
   1.398 +# NOTE : support 256 cylinders max
   1.399 +        incb    %ch			# next cylinder
   1.400 +read_first_sectors:
   1.401 +        movb    $0,%dh			# first head
   1.402 +bdendlp:
   1.403 +        jmp	read_sectorslp
   1.404 +
   1.405 +#ifdef EXE_SUPPORT
   1.406 +need386:
   1.407 +	.ascii	"No 386+."
   1.408 +	.byte	13,10
   1.409 +	.byte	0
   1.410 +helpmsg:
   1.411 +	.ascii	"No help available."
   1.412 +	.byte	13,10
   1.413 +	.byte	0
   1.414 +#endif
   1.415 +
   1.416 +/*
   1.417 +	The following header is documented in the Linux source code at
   1.418 +	Documentation/x86/boot.txt
   1.419 +*/
   1.420 +	.org	497
   1.421 +setup_sects: 
   1.422 +	.byte	SETUPSECS
   1.423 +root_flags: 
   1.424 +	.word	0
   1.425 +syssize: 
   1.426 +	.long	-PREFIXPGH
   1.427 +
   1.428 +	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
   1.429 +	.ascii	"ADDL"
   1.430 +	.long	syssize
   1.431 +	.long	16
   1.432 +	.long	0
   1.433 +	.previous
   1.434 +	
   1.435 +ram_size: 
   1.436 +	.word	0
   1.437 +vid_mode: 
   1.438 +	.word	0
   1.439 +root_dev: 
   1.440 +	.word	0
   1.441 +boot_flag: 
   1.442 +	.word	0xAA55
   1.443 +jump:
   1.444 +	/* Manually specify a two-byte jmp instruction here rather
   1.445 +	 * than leaving it up to the assembler. */
   1.446 +	.byte	0xeb
   1.447 +	.byte	setup_code - header
   1.448 +header:
   1.449 +	.byte	'H', 'd', 'r', 'S'
   1.450 +version:
   1.451 +	.word	0x0207 /* 2.07 */
   1.452 +realmode_swtch:
   1.453 +	.long	0
   1.454 +start_sys:
   1.455 +	.word	0
   1.456 +kernel_version:
   1.457 +	.word	0
   1.458 +type_of_loader:
   1.459 +	.byte	0
   1.460 +loadflags:
   1.461 +	.byte	0
   1.462 +setup_move_size:
   1.463 +	.word	0
   1.464 +code32_start:
   1.465 +	.long	SYSSEG*16
   1.466 +ramdisk_image:
   1.467 +	.long	0
   1.468 +ramdisk_size:
   1.469 +	.long	0
   1.470 +bootsect_kludge:
   1.471 +	.long	0
   1.472 +heap_end_ptr:
   1.473 +	.word	0
   1.474 +pad1:
   1.475 +	.word	0
   1.476 +cmd_line_ptr:
   1.477 +	.long	0
   1.478 +initrd_addr_max:
   1.479 +	/* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have
   1.480 +	 * been known to require this field.  Set the value to 2 GB.  This
   1.481 +	 * value is also used by the Linux kernel. */
   1.482 +	.long	0x7fffffff
   1.483 +kernel_alignment:
   1.484 +	.long	0
   1.485 +relocatable_kernel:
   1.486 +	.byte	0
   1.487 +pad2:
   1.488 +	.byte	0, 0, 0
   1.489 +cmdline_size:
   1.490 +	.long	0x7ff
   1.491 +hardware_subarch:
   1.492 +	.long	0
   1.493 +hardware_subarch_data:
   1.494 +	.byte	0, 0, 0, 0, 0, 0, 0, 0
   1.495 +
   1.496 +/*
   1.497 +	We don't need to do too much setup.
   1.498 +
   1.499 +	This code gets loaded at SETUPSEG:0.  It wants to start
   1.500 +	executing the image that's loaded at SYSSEG:0 and
   1.501 +	whose entry point is SYSSEG:0.
   1.502 +*/
   1.503 +setup_code:
   1.504 +	movl	ramdisk_image, %eax
   1.505 +	orl	%eax, %eax
   1.506 +	jnz	setup_done
   1.507 +
   1.508 +	movw	$default_config, %di
   1.509 +	movw	$-1, %bx
   1.510 +
   1.511 +	movw	$9, %cx
   1.512 +1:
   1.513 +	pushw	%ax
   1.514 +	loop	1b
   1.515 +	pushw	$0x9310
   1.516 +	pushw	%ax
   1.517 +	pushw	%bx
   1.518 +	pushw	%ax
   1.519 +	pushw	$0x9300+(INITSEG>>12)
   1.520 +	pushw	%di
   1.521 +	pushw	%bx
   1.522 +	movb	$8, %cl
   1.523 +1:
   1.524 +	pushw	%ax
   1.525 +	loop	1b
   1.526 +1:
   1.527 +	incw	%bx
   1.528 +	cmpb	%al, (%bx,%di)
   1.529 +	jne	1b
   1.530 +	movw	%bx, ramdisk_size
   1.531 +	movb	$0x10, ramdisk_image+2
   1.532 +
   1.533 +	pushw	%ss
   1.534 +	popw	%es
   1.535 +	movw	%sp, %si
   1.536 +	movb	$0x87, %ah
   1.537 +	movw	$(run_ipxe-default_config)/2+1, %cx
   1.538 +	int	$0x15
   1.539 +
   1.540 +setup_done:
   1.541 +	/* We expect to be contiguous in memory once loaded.  The Linux image
   1.542 +	 * boot process requires that setup code is loaded separately from
   1.543 +	 * "non-real code".  Since we don't need any information that's left
   1.544 +	 * in the prefix, it doesn't matter: we just have to ensure that
   1.545 +	 * %cs:0000 is where the start of the image *would* be.
   1.546 +	 */
   1.547 +	ljmp	$(SYSSEG-(PREFIXSIZE/16)), $run_ipxe
   1.548 +
   1.549 +default_config:
   1.550 +
   1.551 +	.org	PREFIXSIZE
   1.552 +/*
   1.553 +	We're now at the beginning of the kernel proper.
   1.554 + */
   1.555 +run_ipxe:
   1.556 +	/* Set up stack just below 0x7c00 and clear direction flag */
   1.557 +	xorw	%ax, %ax
   1.558 +	movw	%ax, %ss
   1.559 +	movw	$0x7c00, %sp
   1.560 +	cld
   1.561 +
   1.562 +	/* Retrieve command-line pointer */
   1.563 +	movl	%ds:cmd_line_ptr, %edx
   1.564 +	testl	%edx, %edx
   1.565 +	jz	no_cmd_line
   1.566 +
   1.567 +	/* Set up %es:%di to point to command line */
   1.568 +	movl	%edx, %edi
   1.569 +	andl	$0xf, %edi
   1.570 +	rorl	$4, %edx
   1.571 +	movw	%dx, %es
   1.572 +
   1.573 +	/* Find length of command line */
   1.574 +	pushw	%di
   1.575 +	movw	$0xffff, %cx
   1.576 +	repnz scasb
   1.577 +	notw	%cx
   1.578 +	popw	%si
   1.579 +
   1.580 +	/* Make space for command line on stack */
   1.581 +	movw	%sp, %di
   1.582 +	subw	%cx, %di
   1.583 +	andw	$~0xf, %di
   1.584 +	movw	%di, %sp
   1.585 +
   1.586 +	/* Copy command line to stack */
   1.587 +	pushw	%ds
   1.588 +	pushw	%es
   1.589 +	popw	%ds
   1.590 +	pushw	%ss
   1.591 +	popw	%es
   1.592 +	rep movsb
   1.593 +	popw	%ds
   1.594 +
   1.595 +	/* Store new command-line pointer */
   1.596 +	movzwl	%sp, %edx
   1.597 +no_cmd_line:
   1.598 +
   1.599 +	/* Calculate maximum relocation address */
   1.600 +	movl	ramdisk_image, %ebp
   1.601 +	testl	%ebp, %ebp
   1.602 +	jnz	1f
   1.603 +	decl	%ebp		/* Allow arbitrary relocation if no initrd */
   1.604 +1:
   1.605 +
   1.606 +	/* Install iPXE */
   1.607 +	call	alloc_basemem
   1.608 +	xorl	%esi, %esi
   1.609 +	xorl	%edi, %edi
   1.610 +	call	install_prealloc
   1.611 +
   1.612 +	/* Retrieve initrd pointer and size */
   1.613 +	movl	ramdisk_image, %ebp
   1.614 +	movl	ramdisk_size, %ecx
   1.615 +
   1.616 +start_ipxe:
   1.617 +	/* Set up real-mode stack */
   1.618 +	movw	%bx, %ss
   1.619 +	movw	$_estack16, %sp
   1.620 +
   1.621 +	/* Jump to .text16 segment */
   1.622 +	pushw	%ax
   1.623 +	pushw	$1f
   1.624 +	lret
   1.625 +	.section ".text16", "awx", @progbits
   1.626 +1:
   1.627 +	/* Set up %ds for access to .data16 */
   1.628 +	movw	%bx, %ds
   1.629 +
   1.630 +	/* Store command-line pointer */
   1.631 +	movl	%edx, cmdline_phys
   1.632 +
   1.633 +	/* Store initrd pointer and size */
   1.634 +	movl	%ebp, initrd_phys
   1.635 +	movl	%ecx, initrd_len
   1.636 +
   1.637 +	/* Run iPXE */
   1.638 +	pushl	$main
   1.639 +	pushw	%cs
   1.640 +	call	prot_call
   1.641 +	popl	%ecx /* discard */
   1.642 +
   1.643 +	/* Uninstall iPXE */
   1.644 +	call	uninstall
   1.645 +
   1.646 +	/* Boot next device */
   1.647 +	int $0x18