176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER )
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define BOOT_SEG	0x07c0
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EXEC_SEG	0x0100
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define STACK_SEG 	0x0200
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define STACK_SIZE	0x2000
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.text
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.arch i386
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.section ".prefix", "awx", @progbits
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.code16
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Find active partition
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parameters:
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dl	: BIOS drive number
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %bp	: Active partition handler routine
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanfind_active_partition:
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Set up stack at STACK_SEG:STACK_SIZE */
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$STACK_SEG, %ax
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%ax, %ss
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$STACK_SIZE, %sp
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Relocate self to EXEC_SEG */
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	$BOOT_SEG
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popw	%ds
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	$EXEC_SEG
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popw	%es
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorw	%si, %si
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorw	%di, %di
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x200, %cx
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	rep movsb
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ljmp	$EXEC_SEG, $1f
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:	pushw	%ds
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popw	%es
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	%cs
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popw	%ds
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Check for LBA extensions */
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	$0x41, %ah
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x55aa, %bx
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	stc
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int	$0x13
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jc	1f
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cmpw	$0xaa55, %bx
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jne	1f
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$read_lba, read_sectors
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Read and process root partition table */
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorb	%dh, %dh
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x0001, %cx
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorl	%esi, %esi
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorl	%edi, %edi
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	process_table
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Print failure message */
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$10f, %si
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jmp	boot_error
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman10:	.asciz	"Could not locate active partition\r\n"
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Print failure message and boot next device
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parameters:
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %si	: Failure string
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanboot_error:
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cld
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$0x0007, %bx
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	$0x0e, %ah
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:	lodsb
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	testb	%al, %al
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	je	99f
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int	$0x10
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jmp	1b
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman99:	/* Boot next device */
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int	$0x18
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Process partition table
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parameters:
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dl	: BIOS drive number
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dh	: Head
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %ch	: Low eight bits of cylinder
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %esi:%edi	: LBA address
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %bp	: Active partition handler routine
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns:
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   CF set on error
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanprocess_table:
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushal
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	read_boot_sector
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jc	99f
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$446, %bx
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:	call	process_partition
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	addw	$16, %bx
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cmpw	$510, %bx
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jne	1b
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman99:	popal
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ret
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Process partition
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parameters:
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dl	: BIOS drive number
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dh	: Head
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %ch	: Low eight bits of cylinder
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %esi:%edi	: LBA address
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %bx	: Offset within partition table
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %bp	: Active partition handler routine
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanprocess_partition:
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushal
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Load C/H/S values from partition entry */
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	%es:1(%bx), %dh
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%es:2(%bx), %cx
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Update LBA address from partition entry */
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	addl	%es:8(%bx), %edi
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	adcl	$0, %esi
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Check active flag */
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	testb	$0x80, %es:(%bx)
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jz	1f
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	read_boot_sector
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jc	99f
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jmp	*%bp
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman1:	/* Check for extended partition */
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	%es:4(%bx), %al
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cmpb	$0x05, %al
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	je	2f
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cmpb	$0x0f, %al
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	je	2f
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cmpb	$0x85, %al
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jne	99f
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman2:	call	process_table
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman99:	popal
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Reload original partition table */
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	read_boot_sector
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ret
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Read single sector to %es:0000 and verify 0x55aa signature
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parameters:
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dl	: BIOS drive number
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dh	: Head
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %ch	: Low eight bits of cylinder
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %esi:%edi	: LBA address
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns:
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   CF set on error
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanread_boot_sector:
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	%ax
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$1, %ax
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	call	*read_sectors
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	jc	99f
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	cmpw	$0xaa55, %es:(510)
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	je	99f
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	stc
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman99:	popw	%ax
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ret
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Read sectors to %es:0000
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parameters:
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dl	: BIOS drive number
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %dh	: Head
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %ch	: Low eight bits of cylinder
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %esi:%edi	: LBA address
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   %ax	: Number of sectors (max 127)
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns:
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   CF set on error
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanread_sectors:	.word	read_chs
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanread_chs:
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Read sectors using C/H/S address */
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushal
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	xorw	%bx, %bx
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	$0x02, %ah
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	stc
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int	$0x13
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	sti
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popal
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ret
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanread_lba:
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Read sectors using LBA address */
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushal
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	%ax, (lba_desc + 2)
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	pushw	%es
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popw	(lba_desc + 6)
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movl	%edi, (lba_desc + 8)
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movl	%esi, (lba_desc + 12)
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movw	$lba_desc, %si
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	movb	$0x42, %ah
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int	$0x13
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	popal
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ret
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanlba_desc:
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0x10
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.byte	0
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	1
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0x0000
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.word	0x0000
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.long	0, 0
219