176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	Copyright (C) 2000, Entity Cyber, Inc.
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	Authors: Gary Byers (gb@thinguin.org)
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		 Marty Connor (mdc@thinguin.org)
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	This software may be used and distributed according to the terms
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	of the GNU Public License (GPL), incorporated herein by reference.
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	Description:
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	This is just a little bit of code and data that can get prepended
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	to a ROM image in order to allow bootloaders to load the result
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	as if it were a Linux kernel image.
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	A real Linux kernel image consists of a one-sector boot loader
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	(to load the image from a floppy disk), followed a few sectors
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	of setup code, followed by the kernel code itself.  There's
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	a table in the first sector (starting at offset 497) that indicates
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	how many sectors of setup code follow the first sector and which
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	contains some other parameters that aren't interesting in this
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	case.
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	When a bootloader loads the sectors that comprise a kernel image,
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	it doesn't execute the code in the first sector (since that code
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	would try to load the image from a floppy disk.)  The code in the
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	first sector below doesn't expect to get executed (and prints an
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	error message if it ever -is- executed.)
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	We don't require much in the way of setup code.  Historically, the
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	Linux kernel required at least 4 sectors of setup code.
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	Therefore, at least 4 sectors must be present even though we don't
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	use them.
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3776d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL_ANY )
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define	SETUPSECS 4		/* Minimal nr of setup-sectors */
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PREFIXSIZE ((SETUPSECS+1)*512)
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PREFIXPGH (PREFIXSIZE / 16 )
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define	BOOTSEG  0x07C0		/* original address of boot-sector */
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define	INITSEG  0x9000		/* we move boot here - out of the way */
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define	SETUPSEG 0x9020		/* setup starts here */
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define SYSSEG   0x1000		/* system loaded at 0x10000 (65536). */
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.text
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.code16
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.arch i386
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.org	0
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.section ".prefix", "ax", @progbits
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	This is a minimal boot sector.	If anyone tries to execute it (e.g., if
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	a .lilo file is dd'ed to a floppy), print an error message.
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbootsector:
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jmp	$BOOTSEG, $1f	/* reload cs:ip to match relocation addr */
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x2000, %di		/*  0x2000 is arbitrary value >= length
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    of bootsect + room for stack */
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$BOOTSEG, %ax
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%ax,%ds
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%ax,%es
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cli
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%ax, %ss		/* put stack at BOOTSEG:0x2000. */
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%di,%sp
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	sti
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$why_end-why, %cx
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$why, %si
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x0007, %bx		/* page 0, attribute 7 (normal) */
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	$0x0e, %ah		/* write char, tty mode */
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanprloop:
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	lodsb
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int	$0x10
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	loop	prloop
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfreeze: jmp	freeze
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanwhy:	.ascii	"This image cannot be loaded from a floppy disk.\r\n"
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanwhy_end:
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	The following header is documented in the Linux source code at
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	Documentation/i386/boot.txt
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.org	497
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansetup_sects:
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	SETUPSECS
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanroot_flags:
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansyssize:
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	-PREFIXPGH
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.ascii	"ADDL"
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	syssize
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	16
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.previous
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanram_size:
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvid_mode:
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanroot_dev:
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanboot_flag:
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0xAA55
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanjump:
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Manually specify a two-byte jmp instruction here rather
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * than leaving it up to the assembler. */
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0xeb
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	setup_code - header
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanheader:
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	'H', 'd', 'r', 'S'
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanversion:
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0x0207 /* 2.07 */
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanrealmode_swtch:
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstart_sys:
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmankernel_version:
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantype_of_loader:
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanloadflags:
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansetup_move_size:
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmancode32_start:
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanramdisk_image:
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanramdisk_size:
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbootsect_kludge:
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanheap_end_ptr:
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpad1:
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmancmd_line_ptr:
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmaninitrd_addr_max:
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * been known to require this field.  Set the value to 2 GB.  This
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * value is also used by the Linux kernel. */
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0x7fffffff
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmankernel_alignment:
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanrelocatable_kernel:
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpad2:
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0, 0, 0
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmancmdline_size:
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanhardware_subarch:
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanhardware_subarch_data:
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0, 0, 0, 0, 0, 0, 0, 0
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	We don't need to do too much setup.
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	This code gets loaded at SETUPSEG:0.  It wants to start
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	executing the image that's loaded at SYSSEG:0 and
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	whose entry point is SYSSEG:0.
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansetup_code:
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* We expect to be contiguous in memory once loaded.  The Linux image
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * boot process requires that setup code is loaded separately from
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * "non-real code".  Since we don't need any information that's left
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * in the prefix, it doesn't matter: we just have to ensure that
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * %cs:0000 is where the start of the image *would* be.
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 */
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ljmp	$(SYSSEG-(PREFIXSIZE/16)), $run_gpxe
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.org	PREFIXSIZE
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	We're now at the beginning of the kernel proper.
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanrun_gpxe:
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Set up stack just below 0x7c00 */
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorw	%ax, %ax
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%ax, %ss
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x7c00, %sp
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Install gPXE */
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	install
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Set up real-mode stack */
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%bx, %ss
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$_estack16, %sp
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Jump to .text16 segment */
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	%ax
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	$1f
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	lret
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.section ".text16", "awx", @progbits
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushl	$main
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	%cs
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	prot_call
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popl	%ecx /* discard */
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Uninstall gPXE */
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	uninstall
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Boot next device */
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int $0x18
217