Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / prefix / bootpart.S
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S b/qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S
new file mode 100644 (file)
index 0000000..968da1a
--- /dev/null
@@ -0,0 +1,218 @@
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#define BOOT_SEG       0x07c0
+#define EXEC_SEG       0x0100
+#define STACK_SEG      0x0200
+#define STACK_SIZE     0x2000
+       
+       .text
+       .arch i386
+       .section ".prefix", "awx", @progbits
+       .code16
+
+/*
+ * Find active partition
+ *
+ * Parameters:
+ *   %dl       : BIOS drive number
+ *   %bp       : Active partition handler routine
+ */
+find_active_partition:
+       /* Set up stack at STACK_SEG:STACK_SIZE */
+       movw    $STACK_SEG, %ax
+       movw    %ax, %ss
+       movw    $STACK_SIZE, %sp
+
+       /* Relocate self to EXEC_SEG */
+       pushw   $BOOT_SEG
+       popw    %ds
+       pushw   $EXEC_SEG
+       popw    %es
+       xorw    %si, %si
+       xorw    %di, %di
+       movw    $0x200, %cx
+       rep movsb
+       ljmp    $EXEC_SEG, $1f
+1:     pushw   %ds
+       popw    %es
+       pushw   %cs
+       popw    %ds
+
+       /* Check for LBA extensions */
+       movb    $0x41, %ah
+       movw    $0x55aa, %bx
+       stc
+       int     $0x13
+       jc      1f
+       cmpw    $0xaa55, %bx
+       jne     1f
+       movw    $read_lba, read_sectors
+1:     
+       /* Read and process root partition table */
+       xorb    %dh, %dh
+       movw    $0x0001, %cx
+       xorl    %esi, %esi
+       xorl    %edi, %edi
+       call    process_table
+
+       /* Print failure message */
+       movw    $10f, %si
+       jmp     boot_error
+10:    .asciz  "Could not locate active partition\r\n"
+
+/*
+ * Print failure message and boot next device
+ *
+ * Parameters:
+ *   %si       : Failure string
+ */
+boot_error:
+       cld
+       movw    $0x0007, %bx
+       movb    $0x0e, %ah
+1:     lodsb
+       testb   %al, %al
+       je      99f
+       int     $0x10
+       jmp     1b
+99:    /* Boot next device */
+       int     $0x18
+
+/*
+ * Process partition table
+ *
+ * Parameters:
+ *   %dl       : BIOS drive number
+ *   %dh       : Head
+ *   %cl       : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ *   %ch       : Low eight bits of cylinder
+ *   %esi:%edi : LBA address
+ *   %bp       : Active partition handler routine
+ *
+ * Returns:
+ *   CF set on error
+ */
+process_table:
+       pushal
+       call    read_boot_sector
+       jc      99f
+       movw    $446, %bx
+1:     call    process_partition
+       addw    $16, %bx
+       cmpw    $510, %bx
+       jne     1b
+99:    popal
+       ret
+
+/*
+ * Process partition
+ *
+ * Parameters:
+ *   %dl       : BIOS drive number
+ *   %dh       : Head
+ *   %cl       : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ *   %ch       : Low eight bits of cylinder
+ *   %esi:%edi : LBA address
+ *   %bx       : Offset within partition table
+ *   %bp       : Active partition handler routine
+ */
+process_partition:
+       pushal
+       /* Load C/H/S values from partition entry */
+       movb    %es:1(%bx), %dh
+       movw    %es:2(%bx), %cx
+       /* Update LBA address from partition entry */
+       addl    %es:8(%bx), %edi
+       adcl    $0, %esi
+       /* Check active flag */
+       testb   $0x80, %es:(%bx)
+       jz      1f
+       call    read_boot_sector
+       jc      99f
+       jmp     *%bp
+1:     /* Check for extended partition */
+       movb    %es:4(%bx), %al
+       cmpb    $0x05, %al
+       je      2f
+       cmpb    $0x0f, %al
+       je      2f
+       cmpb    $0x85, %al
+       jne     99f
+2:     call    process_table
+99:    popal
+       /* Reload original partition table */
+       call    read_boot_sector
+       ret
+
+/*
+ * Read single sector to %es:0000 and verify 0x55aa signature
+ *
+ * Parameters:
+ *   %dl       : BIOS drive number
+ *   %dh       : Head
+ *   %cl       : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ *   %ch       : Low eight bits of cylinder
+ *   %esi:%edi : LBA address
+ *
+ * Returns:
+ *   CF set on error
+ */
+read_boot_sector:
+       pushw   %ax
+       movw    $1, %ax
+       call    *read_sectors
+       jc      99f
+       cmpw    $0xaa55, %es:(510)
+       je      99f
+       stc     
+99:    popw    %ax
+       ret
+       
+/*
+ * Read sectors to %es:0000
+ *
+ * Parameters:
+ *   %dl       : BIOS drive number
+ *   %dh       : Head
+ *   %cl       : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
+ *   %ch       : Low eight bits of cylinder
+ *   %esi:%edi : LBA address
+ *   %ax       : Number of sectors (max 127)
+ *
+ * Returns:
+ *   CF set on error
+ */
+read_sectors:  .word   read_chs
+
+read_chs:
+       /* Read sectors using C/H/S address */
+       pushal
+       xorw    %bx, %bx
+       movb    $0x02, %ah
+       stc
+       int     $0x13
+       sti
+       popal
+       ret
+
+read_lba:
+       /* Read sectors using LBA address */
+       pushal
+       movw    %ax, (lba_desc + 2)
+       pushw   %es
+       popw    (lba_desc + 6)
+       movl    %edi, (lba_desc + 8)
+       movl    %esi, (lba_desc + 12)
+       movw    $lba_desc, %si
+       movb    $0x42, %ah
+       int     $0x13
+       popal
+       ret
+
+lba_desc:
+       .byte   0x10
+       .byte   0
+       .word   1
+       .word   0x0000
+       .word   0x0000
+       .long   0, 0