support for booting from hd partition
authormarty_connor <marty_connor>
Wed, 31 Aug 2005 12:30:26 +0000 (12:30 +0000)
committermarty_connor <marty_connor>
Wed, 31 Aug 2005 12:30:26 +0000 (12:30 +0000)
src/arch/i386/prefix/hdprefix.S [new file with mode: 0644]

diff --git a/src/arch/i386/prefix/hdprefix.S b/src/arch/i386/prefix/hdprefix.S
new file mode 100644 (file)
index 0000000..38e62bc
--- /dev/null
@@ -0,0 +1,296 @@
+/****************************************************************\
+
+hdprefix.S Copyright (C) 2005 Per Dalgas Jakobsen
+
+This code has been inspired/derived by the OSLoader by Vladislav Aleksandrov.
+http://www.programmersheaven.com/zone5/cat469/40546.htm.
+
+This software may be used and distributed according to the terms
+of the GNU Public License (GPL), incorporated herein by reference.
+
+hdprefix.S is loaded at 0x0000:0x7c00 by the bios-startup routines.
+
+Actions performed by hdprefix:
+1) Load the MBR to LOADSEG:0
+2) Check which partition is active (or try first partition if none active)
+3) Check wether LBA is supported.
+3a) LBA
+3a1) Load PAYLOAD_SECTS sectors from chosen partition to LOADSEG:0
+3b) CHS (standard)
+3b1) Load PAYLOAD_SECTS sectors from chosen partition to LOADSEG:0
+4) Check loaded bootsector for BOOTMAGIC code.
+5) Jump to payload LOADSEG:ENTRYPOINT.
+
+Output with failure points (!#):
+---
+Loading (!1)partition #
+Std. BIOS(!2) | Ext. BIOS(!3)
+Booting...(!4)
+(!5)
+---
+
+!1: Failed to load MBR with Int13,ah=2.
+!2: Failed to load bootrecord+payload with Int13,ah=2.
+!3: Failed to load bootrecord+payload with Int13,ah=42.
+!4: Invalid BOOTMAGIC in loaded bootrecord.
+!5: Jumping to payload.
+
+\*****************************************************************/
+.equ   BOOTSEG,        0x07c0
+.equ   LOADSEG,        0x1000
+.equ   ENTRYPOINT,     _start
+
+.equ   BOOTMAGIC,      0x0aa55
+
+.equ   partition_table,        0x1be
+.equ   partition_rec_size,     0x10
+
+.equ   boot_ind,       0       /* 80h=active */
+.equ   start_head,     1
+.equ   start_sector,   2       /* bits 0-5 */
+.equ   start_cyl,      3       /* bits 8,9 in bits 6,7 of sector */
+.equ   os_ind,         4       /* os indicator */
+.equ   end_head,       5
+.equ   end_sector,     6       /* bits 0-5 */
+.equ   end_track,      7       /* bits 8,9 in bits 6,7 of sector */
+.equ   nsect,          8       /* sectors preceding partition */
+.equ   lenght,         0x0c    /* length of partition in sectors */
+
+/-------------------------------------------------------------
+
+       .arch i386
+       .text
+       .section ".prefix", "ax", @progbits
+       .code16
+        
+bootstart:
+       jmp     $BOOTSEG,$_go           /* reload cs:ip */
+
+
+/****************************************************************/
+/* support routines.                                           */
+/*--------------------------------------------------------------*/
+_failed:
+       movw    $BOOTSEG,%ax
+       movw    %ax,%ds
+       movw    $_failed_msg_end-_failed_msg,%cx
+       movw    $_failed_msg,%si
+       call    _print_str
+
+       /* stop execution - should probably have option to auto-reboot after delay. */
+_failed_loop:
+       jmp     _failed_loop
+
+/*--------------------------------------------------------------*/
+_print_str:
+       /* cx = count, ds:si = string. */
+       movw    $0x0007,%bx
+       movb    $0x0e,%ah
+_print_loop:
+       lodsb
+       int     $0x10
+       loop    _print_loop
+       ret
+
+/*--------------------------------------------------------------*/                     
+_print_char:
+       /* al = char. */
+       movw    $0x0007,%bx
+       movb    $0x0e,%ah
+       int     $0x10
+       ret
+
+/*--------------------------------------------------------------*/
+_print_nl:
+       /* - */
+       movb    $0x0d,%al
+       call    _print_char
+       movb    $0x0a,%al
+       call    _print_char
+       ret
+
+/*--------------------------------------------------------------*/
+_print_hex:
+       /* dx = value */
+       movb    $0x0e,%ah       /* write char, tty mode */
+       movw    $0x0007,%bx     /* page 0, attribute 7 (normal) */
+       call    _print_digit
+       call    _print_digit
+       call    _print_digit
+       /* fall through */
+_print_digit:
+       rolw    $4,%dx          /* rotate so that lowest 4 bits are used */
+       movb    $0x0f,%al       /* mask for nibble */
+       andb    %dl,%al
+       addb    $0x90,%al       /* convert al to ascii hex (four instructions) */
+       daa
+       adcb    $0x40,%al
+       daa
+       int     $0x10
+       ret
+
+/****************************************************************/
+
+
+_go:
+       cli
+       movw    $BOOTSEG,%ax
+       movw    %ax,%ds
+       movw    %ax,%ss
+       movw    $0x2000,%sp     /* good large stack. */
+       sti
+       cld
+       movw    $LOADSEG,%ax
+       movw    %ax,%es
+
+       movw    $_load_msg_end-_load_msg,%cx
+       movw    $_load_msg,%si
+       call    _print_str
+
+/*--- load MBR so we can use its partition table. ---*/
+       xorw    %bx,%bx
+       movw    $0x0001,%cx     /* chs: 0,0,1 */
+       movb    %bh,%dh         /* - */
+       movb    $0x80,%dl
+       movw    $0x0201,%ax     /* read one sector (MBR) */
+       int     $0x13
+       jc      _failed
+
+/*--- find the active partition ---*/
+       movw    $_part_msg_end-_part_msg,%cx
+       movw    $_part_msg,%si
+       call    _print_str
+
+       movw    $partition_table,%di
+       movw    $4,%cx
+_partition_loop:
+       cmpb    $0x80,%es:(%di)         /* active? */
+       je      _partition_found
+       addw    $partition_rec_size,%di
+       loop    _partition_loop
+
+       /*- no partitions marked active - use 1. partition. */
+       movw    $partition_table,%di
+       movw    $4,%cx
+
+_partition_found:
+       movb    $'5',%al                        /* convert to ascii */
+       subb    %cl,%al
+       call    _print_char
+       call    _print_nl
+
+/*--- check for lba support ---*/
+       movw    $0x55aa,%bx
+       movb    $0x80,%dl
+       movb    $0x41,%ah
+       int     $0x13
+       jc      __bios
+       cmpw    $0x0aa55,%bx
+       jnz     __bios
+       testb   $1,%cl
+       jz      __bios
+
+/*--- use lba bios calls to read sectors ---*/
+_lba:
+       movw    $_extbios_msg_end-_extbios_msg,%cx
+       movw    $_extbios_msg,%si
+       call    _print_str
+
+       movw    %es:nsect(%di),%ax
+       movw    %ax,_bios_lba_low
+       movw    %es:nsect+2(%di),%ax
+       movw    %ax,_bios_lba_high
+       movb    $0x80,%dl
+       movw    $_disk_address_packet,%si
+       movw    $0x4200,%ax     /* read */
+       int     $0x13
+       jc      _failed
+       jmp     __loaded
+
+/*--- use standard bios calls to read sectors ---*/
+__bios:
+       movw    $_stdbios_msg_end-_stdbios_msg,%cx
+       movw    $_stdbios_msg,%si
+       call    _print_str
+
+       movw    _disk_address_packet+2(,1),%ax  /* only low byte is used. */
+       xorw    %bx,%bx
+       movw    %es:start_sector(%di),%cx
+       movb    %es:start_head(%di),%dh
+       movb    $0x80,%dl
+       movb    $0x02,%ah
+       int     $0x13
+       jc      _failed
+
+__loaded:
+       movw    $_boot_msg_end-_boot_msg,%cx
+       movw    $_boot_msg,%si
+       call    _print_str
+
+       /* check if it has a valid bootrecord. */
+       cmpw    $BOOTMAGIC,%es:510(,1)
+       jne     _failed
+       call    _print_nl
+
+       /* call the payload. */
+       pushl   $0              /* No parameters to preserve for exit path */
+       pushw   $0              /* Use prefix exit path mechanism */
+       jmp     $LOADSEG,$ENTRYPOINT
+
+       .section ".text16", "ax", @progbits
+       .globl  prefix_exit
+prefix_exit:
+       int     $0x19           /* should try to boot machine */
+       .globl  prefix_exit_end
+prefix_exit_end:
+       .previous
+        
+
+/*--------------------------------------------------------------*/
+
+_load_msg:     .ascii  "Loading "
+_load_msg_end:
+_part_msg:     .ascii  "partition "
+_part_msg_end:
+_boot_msg:     .ascii  "Booting..."
+_boot_msg_end:
+_stdbios_msg:  .ascii  "Std. BIOS\r\n"
+_stdbios_msg_end:
+_extbios_msg:  .ascii  "Ext. BIOS\r\n"
+_extbios_msg_end:
+_failed_msg:   .ascii  "FAILED!!!\r\n"
+_failed_msg_end:
+
+
+/*--------------------------------------------------------------*/
+
+_disk_address_packet:
+               .byte   0x10            /* size of the packet */
+               .byte   0               /* reserved */
+               .word   _verbatim_size_sct      /* number of sectors to read */
+               .word   0x0000          /* offset */
+               .word   LOADSEG         /* segment of buffer */
+_bios_lba_low: .word   0
+_bios_lba_high:        .word   0
+               .word   0
+               .word   0
+
+       .rept 32
+               .byte   0
+       .endr
+
+
+/*--- Partition table ------------------------------------------*/
+
+       .org 446, 0
+       .rept 64
+               .byte   0
+       .endr
+
+
+/*--- Magic code -----------------------------------------------*/
+       .org 510, 0
+               .word BOOTMAGIC
+
+/*** END ********************************************************/