Home | History | Annotate | Download | only in prefix
      1 FILE_LICENCE ( GPL2_OR_LATER )
      2 
      3 #define BOOT_SEG	0x07c0
      4 #define EXEC_SEG	0x0100
      5 #define STACK_SEG 	0x0200
      6 #define STACK_SIZE	0x2000
      7 
      8 	.text
      9 	.arch i386
     10 	.section ".prefix", "awx", @progbits
     11 	.code16
     12 
     13 /*
     14  * Find active partition
     15  *
     16  * Parameters:
     17  *   %dl	: BIOS drive number
     18  *   %bp	: Active partition handler routine
     19  */
     20 find_active_partition:
     21 	/* Set up stack at STACK_SEG:STACK_SIZE */
     22 	movw	$STACK_SEG, %ax
     23 	movw	%ax, %ss
     24 	movw	$STACK_SIZE, %sp
     25 
     26 	/* Relocate self to EXEC_SEG */
     27 	pushw	$BOOT_SEG
     28 	popw	%ds
     29 	pushw	$EXEC_SEG
     30 	popw	%es
     31 	xorw	%si, %si
     32 	xorw	%di, %di
     33 	movw	$0x200, %cx
     34 	rep movsb
     35 	ljmp	$EXEC_SEG, $1f
     36 1:	pushw	%ds
     37 	popw	%es
     38 	pushw	%cs
     39 	popw	%ds
     40 
     41 	/* Check for LBA extensions */
     42 	movb	$0x41, %ah
     43 	movw	$0x55aa, %bx
     44 	stc
     45 	int	$0x13
     46 	jc	1f
     47 	cmpw	$0xaa55, %bx
     48 	jne	1f
     49 	movw	$read_lba, read_sectors
     50 1:
     51 	/* Read and process root partition table */
     52 	xorb	%dh, %dh
     53 	movw	$0x0001, %cx
     54 	xorl	%esi, %esi
     55 	xorl	%edi, %edi
     56 	call	process_table
     57 
     58 	/* Print failure message */
     59 	movw	$10f, %si
     60 	jmp	boot_error
     61 10:	.asciz	"Could not locate active partition\r\n"
     62 
     63 /*
     64  * Print failure message and boot next device
     65  *
     66  * Parameters:
     67  *   %si	: Failure string
     68  */
     69 boot_error:
     70 	cld
     71 	movw	$0x0007, %bx
     72 	movb	$0x0e, %ah
     73 1:	lodsb
     74 	testb	%al, %al
     75 	je	99f
     76 	int	$0x10
     77 	jmp	1b
     78 99:	/* Boot next device */
     79 	int	$0x18
     80 
     81 /*
     82  * Process partition table
     83  *
     84  * Parameters:
     85  *   %dl	: BIOS drive number
     86  *   %dh	: Head
     87  *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
     88  *   %ch	: Low eight bits of cylinder
     89  *   %esi:%edi	: LBA address
     90  *   %bp	: Active partition handler routine
     91  *
     92  * Returns:
     93  *   CF set on error
     94  */
     95 process_table:
     96 	pushal
     97 	call	read_boot_sector
     98 	jc	99f
     99 	movw	$446, %bx
    100 1:	call	process_partition
    101 	addw	$16, %bx
    102 	cmpw	$510, %bx
    103 	jne	1b
    104 99:	popal
    105 	ret
    106 
    107 /*
    108  * Process partition
    109  *
    110  * Parameters:
    111  *   %dl	: BIOS drive number
    112  *   %dh	: Head
    113  *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
    114  *   %ch	: Low eight bits of cylinder
    115  *   %esi:%edi	: LBA address
    116  *   %bx	: Offset within partition table
    117  *   %bp	: Active partition handler routine
    118  */
    119 process_partition:
    120 	pushal
    121 	/* Load C/H/S values from partition entry */
    122 	movb	%es:1(%bx), %dh
    123 	movw	%es:2(%bx), %cx
    124 	/* Update LBA address from partition entry */
    125 	addl	%es:8(%bx), %edi
    126 	adcl	$0, %esi
    127 	/* Check active flag */
    128 	testb	$0x80, %es:(%bx)
    129 	jz	1f
    130 	call	read_boot_sector
    131 	jc	99f
    132 	jmp	*%bp
    133 1:	/* Check for extended partition */
    134 	movb	%es:4(%bx), %al
    135 	cmpb	$0x05, %al
    136 	je	2f
    137 	cmpb	$0x0f, %al
    138 	je	2f
    139 	cmpb	$0x85, %al
    140 	jne	99f
    141 2:	call	process_table
    142 99:	popal
    143 	/* Reload original partition table */
    144 	call	read_boot_sector
    145 	ret
    146 
    147 /*
    148  * Read single sector to %es:0000 and verify 0x55aa signature
    149  *
    150  * Parameters:
    151  *   %dl	: BIOS drive number
    152  *   %dh	: Head
    153  *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
    154  *   %ch	: Low eight bits of cylinder
    155  *   %esi:%edi	: LBA address
    156  *
    157  * Returns:
    158  *   CF set on error
    159  */
    160 read_boot_sector:
    161 	pushw	%ax
    162 	movw	$1, %ax
    163 	call	*read_sectors
    164 	jc	99f
    165 	cmpw	$0xaa55, %es:(510)
    166 	je	99f
    167 	stc
    168 99:	popw	%ax
    169 	ret
    170 
    171 /*
    172  * Read sectors to %es:0000
    173  *
    174  * Parameters:
    175  *   %dl	: BIOS drive number
    176  *   %dh	: Head
    177  *   %cl	: Sector (bits 0-5), high two bits of cylinder (bits 6-7)
    178  *   %ch	: Low eight bits of cylinder
    179  *   %esi:%edi	: LBA address
    180  *   %ax	: Number of sectors (max 127)
    181  *
    182  * Returns:
    183  *   CF set on error
    184  */
    185 read_sectors:	.word	read_chs
    186 
    187 read_chs:
    188 	/* Read sectors using C/H/S address */
    189 	pushal
    190 	xorw	%bx, %bx
    191 	movb	$0x02, %ah
    192 	stc
    193 	int	$0x13
    194 	sti
    195 	popal
    196 	ret
    197 
    198 read_lba:
    199 	/* Read sectors using LBA address */
    200 	pushal
    201 	movw	%ax, (lba_desc + 2)
    202 	pushw	%es
    203 	popw	(lba_desc + 6)
    204 	movl	%edi, (lba_desc + 8)
    205 	movl	%esi, (lba_desc + 12)
    206 	movw	$lba_desc, %si
    207 	movb	$0x42, %ah
    208 	int	$0x13
    209 	popal
    210 	ret
    211 
    212 lba_desc:
    213 	.byte	0x10
    214 	.byte	0
    215 	.word	1
    216 	.word	0x0000
    217 	.word	0x0000
    218 	.long	0, 0
    219