1FILE_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 */ 20find_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 361: 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 501: 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 6110: .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 */ 69boot_error: 70 cld 71 movw $0x0007, %bx 72 movb $0x0e, %ah 731: lodsb 74 testb %al, %al 75 je 99f 76 int $0x10 77 jmp 1b 7899: /* 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 */ 95process_table: 96 pushal 97 call read_boot_sector 98 jc 99f 99 movw $446, %bx 1001: call process_partition 101 addw $16, %bx 102 cmpw $510, %bx 103 jne 1b 10499: 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 */ 119process_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 1331: /* 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 1412: call process_table 14299: 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 */ 160read_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 16899: 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 */ 185read_sectors: .word read_chs 186 187read_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 198read_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 212lba_desc: 213 .byte 0x10 214 .byte 0 215 .word 1 216 .word 0x0000 217 .word 0x0000 218 .long 0, 0 219