FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

#include <librm.h>

#define BZI_LOAD_HIGH_ADDR 0x100000

	.text
	.arch i386
	.code16
	.section ".prefix", "ax", @progbits
	.globl	_lkrn_start
_lkrn_start:

/*****************************************************************************
 *
 * Kernel header
 *
 * We place our prefix (i.e. our .prefix and .text16.early sections)
 * within the bzImage real-mode portion which gets loaded at
 * 1000:0000, and our payload (i.e. everything else) within the
 * bzImage protected-mode portion which gets loaded at 0x100000
 * upwards.
 *
 */

	.org	0x1f1
setup_sects:
	.byte	-1 /* Allow for initial "boot sector" */
	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
	.ascii	"ADHL"
	.long	setup_sects
	.long	512
	.long	0
	.previous
root_flags:
	.word	0
syssize:
	.long	0
	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
	.ascii	"ADPL"
	.long	syssize
	.long	16
	.long	0
	.previous
ram_size:
	.word	0
vid_mode:
	.word	0
root_dev:
	.word	0
boot_flag:
	.word	0xaa55
jump:
	/* Manually specify a two-byte jmp instruction here rather
	 * than leaving it up to the assembler.
	 */
	.byte	0xeb, ( setup - header )
header:
	.byte	'H', 'd', 'r', 'S'
version:
	.word	0x0207 /* 2.07 */
realmode_swtch:
	.long	0
start_sys:
	.word	0
kernel_version:
	.word	version_string - 0x200
type_of_loader:
	.byte	0
loadflags:
	.byte	0x01 /* LOADED_HIGH */
setup_move_size:
	.word	0
code32_start:
	.long	0
ramdisk_image:
	.long	0
ramdisk_size:
	.long	0
bootsect_kludge:
	.long	0
heap_end_ptr:
	.word	0
ext_loader_ver:
	.byte	0
ext_loader_type:
	.byte	0
cmd_line_ptr:
	.long	0
initrd_addr_max:
	.long	0xffffffff
kernel_alignment:
	.long	0
relocatable_kernel:
	.byte	0
min_alignment:
	.byte	0
xloadflags:
	.word	0
cmdline_size:
	.long	0x7ff
hardware_subarch:
	.long	0
hardware_subarch_data:
	.byte	0, 0, 0, 0, 0, 0, 0, 0

version_string:
	.asciz	VERSION

/*****************************************************************************
 *
 * Setup code
 *
 */

setup:
	/* Fix up code segment */
	pushw	%ds
	pushw	$1f
	lret
1:
	/* Set up stack just below 0x7c00 and clear direction flag */
	xorw	%ax, %ax
	movw	%ax, %ss
	movw	$0x7c00, %sp
	cld

	/* Retrieve command-line pointer */
	movl	cmd_line_ptr, %edx
	testl	%edx, %edx
	jz	no_cmd_line

	/* Set up %es:%di to point to command line */
	movl	%edx, %edi
	andl	$0xf, %edi
	rorl	$4, %edx
	movw	%dx, %es

	/* Find length of command line */
	pushw	%di
	movw	$0xffff, %cx
	repnz scasb
	notw	%cx
	popw	%si

	/* Make space for command line on stack */
	movw	%sp, %di
	subw	%cx, %di
	andw	$~0xf, %di
	movw	%di, %sp

	/* Copy command line to stack */
	pushw	%ds
	pushw	%es
	popw	%ds
	pushw	%ss
	popw	%es
	rep movsb
	popw	%ds

	/* Store new command-line pointer */
	movzwl	%sp, %edx
no_cmd_line:

	/* Calculate maximum relocation address */
	movl	ramdisk_image, %ebp
	testl	%ebp, %ebp
	jnz	1f
	orl	$0xffffffff, %ebp /* Allow arbitrary relocation if no initrd */
1:
	/* Install iPXE */
	call	alloc_basemem
	xorl	%esi, %esi
	xorl	%edi, %edi
	call	install_prealloc

	/* Set up real-mode stack */
	movw	%bx, %ss
	movw	$_estack16, %sp

	/* Jump to .text16 segment */
	pushw	%ax
	pushw	$1f
	lret
	.section ".text16", "awx", @progbits
1:
	/* Retrieve initrd pointer and size */
	movl	ramdisk_image, %ebp
	movl	ramdisk_size, %ecx

	/* Set up %ds for access to .data16 */
	movw	%bx, %ds

	/* Store command-line pointer */
	movl	%edx, cmdline_phys

	/* Store initrd pointer and size */
	movl	%ebp, initrd_phys
	movl	%ecx, initrd_len

	/* Run iPXE */
	virtcall main

	/* Uninstall iPXE */
	call	uninstall

	/* Boot next device */
	int $0x18

/*****************************************************************************
 *
 * Open payload (called by libprefix)
 *
 * Parameters:
 *   %ds:0000 : Prefix
 *   %esi : Buffer for copy of image source (or zero if no buffer available)
 *   %ecx : Expected offset within buffer of first payload block
 * Returns:
 *   %esi : Valid image source address (buffered or unbuffered)
 *   %ecx : Actual offset within buffer of first payload block
 *   CF set on error
 */

	.section ".text16.early", "awx", @progbits
	.globl	open_payload
open_payload:

	/* Our payload will always end up at BZI_LOAD_HIGH_ADDR */
	movl	$BZI_LOAD_HIGH_ADDR, %esi
	xorl	%ecx, %ecx
	lret

	/* Payload must be aligned to a whole number of setup sectors */
	.globl	_payload_align
	.equ	_payload_align, 512
