Ticket #4028: new_haiku_gpt_mbr.diff

File new_haiku_gpt_mbr.diff, 27.8 KB (added by meianoite, 9 years ago)

in patch form

  • build/jam/AnybootImage

     
    3333}
    3434
    3535local baseMBR = base_mbr.bin ;
    36 local mbrSource = [ FDirName $(HAIKU_TOP) src bin writembr mbr.S ] ;
     36local mbrSource = [ FDirName $(HAIKU_TOP) src bin writembr hybrid_mbr.S ] ;
    3737BuildAnybootMBR $(baseMBR) : $(mbrSource) ;
    3838MakeLocate $(baseMBR) : $(HAIKU_OUTPUT_DIR) ;
    3939MakeLocate $(HAIKU_ANYBOOT) : $(HAIKU_ANYBOOT_DIR) ;
  • src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp

     
    3939
    4040// compiled form of hybrid FreeBSD pmbr and mbr loader done by André Braga
    4141static const uint8 kBootCode[] = {
    42     0xfc, 0xe8, 0x05, 0x01, 0xbc, 0x00, 0x0e, 0xbe, 0x15, 0x7c, 0xbf, 0x15,
    43     0x06, 0xb9, 0xeb, 0x01, 0xf3, 0xa4, 0xe9, 0x00, 0x8a, 0xe8, 0xfc, 0x00,
    44     0xbb, 0x00, 0x0e, 0xbe, 0xb0, 0x07, 0xb9, 0x01, 0x00, 0xe8, 0x03, 0x01,
    45     0x66, 0x81, 0x3e, 0x00, 0x0e, 0x45, 0x46, 0x49, 0x20, 0x75, 0x5c, 0x66,
    46     0x81, 0x3e, 0x04, 0x0e, 0x50, 0x41, 0x52, 0x54, 0x75, 0x51, 0xbe, 0x48,
    47     0x0e, 0xbb, 0x00, 0x10, 0xb9, 0x01, 0x00, 0xe8, 0xe1, 0x00, 0x89, 0xde,
    48     0xbf, 0xa0, 0x07, 0xb1, 0x10, 0xf3, 0xa6, 0x75, 0x1b, 0x89, 0xdf, 0x8d,
    49     0x75, 0x20, 0xbb, 0xc0, 0x07, 0x8e, 0xc3, 0x31, 0xdb, 0x56, 0x8a, 0x0e,
    50     0x9f, 0x07, 0xe8, 0xc2, 0x00, 0x31, 0xc0, 0x8e, 0xc0, 0xe9, 0x94, 0x75,
    51     0x66, 0xff, 0x0e, 0x50, 0x0e, 0x74, 0x18, 0xa1, 0x54, 0x0e, 0x01, 0xc3,
    52     0x81, 0xfb, 0x00, 0x12, 0x72, 0xc8, 0x66, 0xff, 0x06, 0x48, 0x0e, 0x66,
    53     0x83, 0x16, 0x4c, 0x0e, 0x00, 0xeb, 0xaf, 0xe8, 0x7b, 0x00, 0xbc, 0x00,
    54     0x7c, 0x31, 0xf6, 0xbb, 0xbe, 0x07, 0xb1, 0x04, 0x38, 0x2f, 0x74, 0x0c,
    55     0x0f, 0x8f, 0xa2, 0x00, 0x85, 0xf6, 0x0f, 0x85, 0x9c, 0x00, 0x89, 0xde,
    56     0x80, 0xc3, 0x10, 0xe2, 0xeb, 0x85, 0xf6, 0x75, 0x02, 0xcd, 0x18, 0xe8,
    57     0x5e, 0x00, 0x89, 0xe7, 0x8a, 0x74, 0x01, 0x8b, 0x4c, 0x02, 0xbb, 0x00,
    58     0x7c, 0xf6, 0x06, 0x9e, 0x07, 0x80, 0x74, 0x2d, 0x51, 0x53, 0xbb, 0xaa,
    59     0x55, 0xb4, 0x41, 0xcd, 0x13, 0x72, 0x20, 0x81, 0xfb, 0x55, 0xaa, 0x75,
    60     0x1a, 0xf6, 0xc1, 0x01, 0x74, 0x15, 0x5b, 0x66, 0x6a, 0x00, 0x66, 0xff,
    61     0x74, 0x08, 0x06, 0x53, 0x6a, 0x01, 0x6a, 0x10, 0x89, 0xe6, 0xb8, 0x00,
    62     0x42, 0xeb, 0x05, 0x5b, 0x59, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x89, 0xfc,
    63     0x72, 0x49, 0x81, 0xbf, 0xfe, 0x01, 0x55, 0xaa, 0x75, 0x46, 0xe9, 0x5c,
    64     0xff, 0x31, 0xc9, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xc3,
    65     0x80, 0xfa, 0x80, 0x72, 0x0b, 0x8a, 0x36, 0x75, 0x04, 0x80, 0xc6, 0x80,
    66     0x38, 0xf2, 0x72, 0x02, 0xb2, 0x80, 0xc3, 0x66, 0xff, 0x74, 0x04, 0x66,
    67     0xff, 0x34, 0x06, 0x53, 0x51, 0x6a, 0x10, 0x89, 0xe6, 0xb8, 0x00, 0x42,
    68     0xcd, 0x13, 0x83, 0xc4, 0x10, 0x0f, 0x82, 0x4a, 0xff, 0xc3, 0xbe, 0x60,
    69     0x07, 0xeb, 0x11, 0xbe, 0x74, 0x07, 0xeb, 0x0c, 0xbe, 0x7d, 0x07, 0xeb,
    70     0x07, 0xbb, 0x07, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac, 0x84, 0xc0, 0x75,
    71     0xf4, 0xf4, 0xeb, 0xfd, 0x42, 0x61, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74,
    72     0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x00,
    73     0x49, 0x4f, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x4d, 0x69, 0x73,
    74     0x73, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20,
    75     0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x00, 0xff,
    76     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0x31, 0x53, 0x46, 0x42,
     42    0xfa, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0xf8, 0x0d,
     43    0xfd, 0xbe, 0x00, 0x7c, 0x8d, 0x7c, 0xff, 0xb9, 0xff, 0x75, 0xf3, 0xaa,
     44    0xfc, 0xb9, 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x23, 0x06, 0x00, 0x00, 0xfb,
     45    0xb6, 0x00, 0xbb, 0xaa, 0x55, 0xb4, 0x41, 0xcd, 0x13, 0x72, 0x0b, 0x81,
     46    0xfb, 0x55, 0xaa, 0x75, 0x05, 0xf6, 0xc1, 0x01, 0x75, 0x05, 0xb6, 0x01,
     47    0xe9, 0x92, 0x00, 0xbb, 0x00, 0x0e, 0xbe, 0xf8, 0x0d, 0xc6, 0x04, 0x01,
     48    0xe8, 0xe8, 0x00, 0x66, 0x81, 0x3e, 0x00, 0x0e, 0x45, 0x46, 0x49, 0x20,
     49    0x75, 0x7b, 0x66, 0x81, 0x3e, 0x04, 0x0e, 0x50, 0x41, 0x52, 0x54, 0x75,
     50    0x70, 0xbe, 0x48, 0x0e, 0xbb, 0x00, 0x10, 0xe8, 0xc9, 0x00, 0x89, 0xde,
     51    0xbf, 0xa0, 0x07, 0xb1, 0x10, 0xf3, 0xa6, 0x75, 0x3d, 0x89, 0xdf, 0x8d,
     52    0x75, 0x20, 0xbb, 0xc0, 0x07, 0x8e, 0xc3, 0x31, 0xdb, 0x56, 0xe8, 0xae,
     53    0x00, 0x5e, 0x66, 0x8b, 0x45, 0x28, 0x66, 0x3b, 0x04, 0x75, 0x0d, 0x66,
     54    0x8b, 0x45, 0x2c, 0x66, 0x3b, 0x44, 0x04, 0x75, 0x03, 0xe9, 0x8e, 0x00,
     55    0x66, 0xff, 0x04, 0x66, 0x83, 0x54, 0x04, 0x00, 0x8c, 0xc0, 0x83, 0xc0,
     56    0x20, 0x3d, 0x00, 0x90, 0x73, 0x7c, 0x8e, 0xc0, 0xeb, 0xcf, 0x66, 0xff,
     57    0x0e, 0x50, 0x0e, 0x74, 0x18, 0xa1, 0x54, 0x0e, 0x01, 0xc3, 0x81, 0xfb,
     58    0x00, 0x12, 0x72, 0xa6, 0x66, 0xff, 0x06, 0x48, 0x0e, 0x66, 0x83, 0x16,
     59    0x4c, 0x0e, 0x00, 0xeb, 0x90, 0x31, 0xc0, 0x8e, 0xc0, 0xbc, 0x00, 0x7c,
     60    0x31, 0xf6, 0xbb, 0xbe, 0x07, 0xb9, 0x04, 0x00, 0x38, 0x2f, 0x74, 0x08,
     61    0x7f, 0x74, 0x85, 0xf6, 0x75, 0x70, 0x89, 0xde, 0x80, 0xc3, 0x10, 0xe2,
     62    0xef, 0x85, 0xf6, 0x75, 0x02, 0xcd, 0x18, 0x89, 0xe3, 0x56, 0x80, 0xfe,
     63    0x01, 0x74, 0x12, 0x83, 0xc6, 0x08, 0xbf, 0xf8, 0x0d, 0x66, 0xa5, 0x87,
     64    0xfe, 0x83, 0xee, 0x04, 0xe8, 0x24, 0x00, 0xeb, 0x0c, 0x8a, 0x74, 0x01,
     65    0x8b, 0x4c, 0x02, 0xb0, 0x02, 0xb4, 0x02, 0xcd, 0x13, 0x72, 0x43, 0x5e,
     66    0x88, 0x14, 0x81, 0xbf, 0xfe, 0x01, 0x55, 0xaa, 0x75, 0x40, 0x31, 0xc0,
     67    0x8e, 0xc0, 0xea, 0x00, 0x7c, 0x00, 0x00, 0x66, 0xff, 0x74, 0x04, 0x66,
     68    0xff, 0x34, 0x06, 0x53, 0x6a, 0x01, 0x6a, 0x10, 0x89, 0xe6, 0xb8, 0x00,
     69    0x42, 0xcd, 0x13, 0x83, 0xc4, 0x10, 0x72, 0x16, 0xc3, 0xbb, 0x07, 0x00,
     70    0xb4, 0x0e, 0xcd, 0x10, 0xac, 0x84, 0xc0, 0x75, 0xf4, 0xc3, 0xbe, 0x74,
     71    0x07, 0xe8, 0xf4, 0xff, 0xeb, 0x0e, 0xbe, 0x85, 0x07, 0xe8, 0xec, 0xff,
     72    0xeb, 0x06, 0xbe, 0x91, 0x07, 0xe8, 0xe4, 0xff, 0xfa, 0xf4, 0xeb, 0xfc,
     73    0x42, 0x61, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x2e, 0x20, 0x54, 0x61,
     74    0x62, 0x6c, 0x65, 0x21, 0x00, 0x52, 0x65, 0x61, 0x64, 0x20, 0x45, 0x72,
     75    0x72, 0x6f, 0x72, 0x21, 0x00, 0x4e, 0x6f, 0x20, 0x53, 0x79, 0x73, 0x20,
     76    0x4c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x21, 0x00, 0x31, 0x53, 0x46, 0x42,
    7777    0xa3, 0x3b, 0xf1, 0x10, 0x80, 0x2a, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x21
    7878};
    7979
  • src/bin/writembr/mbr.S

     
    1 /*
    2 ** Copyright (c) 1999 Robert Nordier
    3 ** All rights reserved.
    4 **
    5 ** Redistribution and use in source and binary forms are freely
    6 ** permitted provided that the above copyright notice and this
    7 ** paragraph and the following disclaimer are duplicated in all
    8 ** such forms.
    9 **
    10 ** This software is provided "AS IS" and without any express or
    11 ** implied warranties, including, without limitation, the implied
    12 ** warranties of merchantability and fitness for a particular
    13 ** purpose.
    14 /*
    15 
    16 /* A 512 byte MBR boot manager that simply boots the active partition. */
    17 
    18         .set LOAD, 0x7c00               // Load address
    19         .set EXEC, 0x600                // Execution address
    20         .set PT_OFF, 0x1be              // Partition table
    21         .set MAGIC, 0xaa55              // Magic: bootable
    22 
    23         .set NUM_HARD_DRIVES, 0x475     // Number of hard drives
    24 
    25         .globl start                    // Entry point
    26         .code16
    27 
    28 /*
    29  * Setup the segment registers for flat addressing and setup the stack.
    30  */
    31 start:  cld                             // String ops inc
    32         xorw %ax, %ax                   // Zero
    33         movw %ax, %es                   // Address
    34         movw %ax, %ds                   // data
    35         movw %ax, %ss                   // Set up stack
    36         movw $LOAD, %sp                 //
    37 /*
    38  * Relocate ourself to a lower address so that we are out of the way when
    39  * we load in the bootstrap from the partition to boot.
    40  */
    41         movw $main-EXEC+LOAD, %si       // Source
    42         movw $main, %di                 // Destination
    43         movw $0x200-(main-start), %cx   // Byte count
    44         rep                             // Relocate code
    45         movsb                           //
    46 /*
    47  * Jump to the relocated code.
    48  */
    49         jmp main-LOAD+EXEC              // Jump to relocated code
    50 
    51 /*
    52  * Scan the partition table looking for an active entry.  Note that %ch is
    53  * zero from the repeated string instruction above.  We save the offset of
    54  * the active partition in %si and scan the entire table to ensure that only
    55  * one partition is marked active.
    56  */
    57 
    58 main:   xorw %si, %si                   // No active partition
    59         movw $partition_table, %bx      // Partition table
    60         movb $0x4, %cl                  // Number of entries
    61 main.1: cmpb %ch, (%bx)                 // Null entry?
    62         je main.2                       // Yes
    63         jg err_partition_table          // If 0x1..0x7f
    64         testw %si, %si                  // Active already found?
    65         jnz err_partition_table         // Yes
    66         movw %bx, %si                   // Point to active
    67 main.2: addb $0x10, %bl                 // Till
    68         loop main.1                     //  done
    69         testw %si, %si                  // Active found?
    70         jnz main.3                      // Yes
    71         int $0x18                       // BIOS: Diskless boot
    72 /*
    73  * Ok, we've found a possible active partition.  Check to see that the drive
    74  * is a valid hard drive number.
    75  */
    76 main.3: cmpb $0x80, %dl                 // Drive valid?
    77         jb main.4                       // No
    78         movb NUM_HARD_DRIVES, %dh       // Calculate the highest
    79         addb $0x80, %dh                 //   drive number available
    80         cmpb %dh, %dl                   // Within range?
    81         jb main.5                       // Yes
    82 main.4: movb (%si), %dl                 // Load drive
    83 /*
    84  * Ok, now that we have a valid drive and partition entry, load the CHS from
    85  * the partition entry and read the sector from the disk.
    86  */
    87 main.5: movw %sp, %di                   // Save stack pointer
    88         movb 0x1(%si), %dh              // Load head
    89         movw 0x2(%si), %cx              // Load cylinder:sector
    90         movw $LOAD, %bx                 // Transfer buffer
    91         cmpb $0xff, %dh                 // Might we need to use LBA?
    92         jnz main.7                      // No.
    93         cmpw $0xffff, %cx               // Do we need to use LBA?
    94         jnz main.7                      // No.
    95         pushw %cx                       // Save %cx
    96         pushw %bx                       // Save %bx
    97         movw $0x55aa, %bx               // Reversed Magic
    98         movb $0x41, %ah                 // BIOS:    EDD extensions present?
    99         int $0x13                       //
    100         jc main.6                       // No.
    101         cmpw $MAGIC, %bx                // Magic ok?
    102         jne main.6                      // No.
    103         testb $0x1, %cl                 // Packet mode present?
    104         jz main.6                       // No.
    105         popw %bx                        // Restore %bx
    106         pushl $0x0                      // Set the LBA
    107         pushl 0x8(%si)                  //  address
    108         pushw %es                       // Set the address of
    109         pushw %bx                       //  the transfer buffer
    110         pushw $0x1                      // Read 1 sector
    111         pushw $0x10                     // Packet length
    112         movw %sp, %si                   // Packet pointer
    113         movw $0x4200, %ax               // BIOS:    LBA Read from disk
    114         jmp main.8                      // Skip the CHS setup
    115 main.6: popw %bx                        // Restore %bx
    116         popw %cx                        // Restore %cx
    117 main.7: movw $0x201, %ax                // BIOS: Read from disk
    118 main.8: int $0x13                       // Call the BIOS
    119         movw %di,%sp                    // Restore stack
    120         jc err_loading_os               // If error
    121 /*
    122  * Now that we've loaded the bootstrap, check for the magic 0xaa55 signature.
    123  * If it is present, execute the bootstrap we just loaded.
    124  */
    125         cmpw $MAGIC, 0x1fe(%bx)         // Bootable?
    126         jne err_missing_os              // No
    127         jmp *%bx                        // Invoke bootstrap
    128 /*
    129  * Various error message entry points.
    130  */
    131 err_partition_table:
    132         movw $msg_partition_table, %si  // "Invalid partition table"
    133         jmp putString                   //
    134 
    135 err_loading_os:
    136         movw $msg_loading_os, %si       // "Error loading operating system"
    137         jmp putString                   //
    138 
    139 err_missing_os:
    140         movw $msg_missing_os, %si       // "Missing operating system"
    141         jmp putString                   //
    142 /*
    143  * Output an ASCIZ string to the console via the BIOS.
    144  */
    145 putString.0:
    146         movw $0x7, %bx                  // Page:attribute
    147         movb $0xe, %ah                  // BIOS: Display character
    148         int $0x10                       //
    149 putString:
    150         lodsb                           // Get character
    151         testb %al,%al                   // End of string?
    152         jnz putString.0                 // No
    153 putString.1:
    154         jmp putString.1                 // Await reset
    155 
    156 msg_partition_table:    .asciz "Invalid partition table"
    157 msg_loading_os:         .asciz "Error loading operating system"
    158 msg_missing_os:         .asciz "Missing operating system"
    159 
    160         .org PT_OFF
    161 
    162 partition_table:
    163         .fill 0x10,0x4,0x0              // Partition table
    164         .word MAGIC                     // Magic number
  • src/bin/writembr/hybrid_mbr.S

     
     1#
     2# Partly from:
     3# $FreeBSD: src/sys/boot/i386/pmbr/pmbr.s,v 1.2 2007/11/26 21:29:59 jhb Exp $
     4#
     5# Copyright (c) 2007 Yahoo!, Inc.
     6# All rights reserved.
     7# Written by: John Baldwin <jhb@FreeBSD.org>
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12# 1. Redistributions of source code must retain the above copyright
     13#    notice, this list of conditions and the following disclaimer.
     14# 2. Redistributions in binary form must reproduce the above copyright
     15#    notice, this list of conditions and the following disclaimer in the
     16#    documentation and/or other materials provided with the distribution.
     17# 3. Neither the name of the author nor the names of any co-contributors
     18#    may be used to endorse or promote products derived from this software
     19#    without specific prior written permission.
     20#
     21# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     22# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     25# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31# SUCH DAMAGE.
     32#
     33
     34#
     35# Partly from:
     36# $FreeBSD: src/sys/boot/i386/mbr/mbr.s,v 1.7 2004/08/28 08:39:35 yar Exp $
     37#
     38# Copyright (c) 1999 Robert Nordier
     39# All rights reserved.
     40#
     41# Redistribution and use in source and binary forms are freely
     42# permitted provided that the above copyright notice and this
     43# paragraph and the following disclaimer are duplicated in all
     44# such forms.
     45#
     46# This software is provided "AS IS" and without any express or
     47# implied warranties, including, without limitation, the implied
     48# warranties of merchantability and fitness for a particular
     49# purpose.
     50#
     51
     52#
     53# "Hybridisation" and modifications for booting Haiku by Andre' Braga
     54# (me@andrebraga.com), with valuable input from Jean-Loïc Charroud
     55# (jcharroud@free.fr). The modifications contained herein are released into
     56# the Public Domain.
     57#
     58
     59#
     60#       A 432 bytes MBR IPL (Initial Program Loader) that looks for the UUID of
     61# a Haiku Boot GUID partition and boots it, falling back to MBR partitions if
     62# said UUID isn't found or if the (primary) GPT is corrupted or non-existent.
     63#       Its usefulness is in being a versatile, "universal" IPL that supports
     64# both partitioning styles, allowing it to be used transparently and even
     65# facilitating the conversion between partitioning styles, should the need
     66# for more partitions or volumes over 2TiB arise (for instance when cloning
     67# an older disk to a newer, more capacious one).
     68#       It also paves the way for Haiku to create and support booting from
     69# multiple volumes larger than 2TiB, which we're in the very privileged
     70# position of enjoying efficiently in the near future due to BFS. Another use
     71# case is taking a disk from a Intel EFI machine, plugging it on a BIOS
     72# machine and boot just fine; and vice-versa.
     73#       As mentioned, if there are valid partitions defined in the MBR, and the
     74# primary GPT becomes corrupt, it can fall back to loading the MBR partition
     75# with the active flag set, if one is defined.
     76#       Currently there's no provision for falling back to the GPT copy that
     77# lives in the end of the disk, due to the 512 bytes constraint; supporting
     78# this is unlikely given that the code is packed tight. An alternative would be
     79# disabling support for booting from MBR using BIOS calls other than Int13h
     80# function 42h, "Extended Read From Disk" (i.e., LBA mode). It's unlikely that
     81# any machine that Haiku supports won't have this BIOS function, but having an
     82# "universal" IPL should be quite useful to, say, people using Haiku to
     83# rewrite a corrupt MBR on another disk using the excellent DiskProbe.
     84#       The number of sectors loaded depends on the boot style. Booting from a
     85# MBR partition assumes that the Partition Boot Record is one sector long,
     86# whereas booting from a GPT partition assumes a partition exclusive for a
     87# system loader and will either copy its entirety into memory starting from
     88# address 0x7c00, or will copy up to circa 545KiB, whichever is smaller. Thus,
     89# it remains compatible with the FreeBSD gptloader and should work for loading
     90# Bootman from an exclusive Haiku boot manager partition as well.
     91#       It should be easy to adjust the UUID signature as needed. It lives at
     92# offset 0x1a0 (416), leaving plenty of space before the 32-bit disk signature
     93# at offset 0x1b8 (440), so compatibility with Microsoft Windows and other OSs
     94# is maintained.
     95#
     96
     97.ifndef VALIDATE_DRV
     98                .set VALIDATE_DRV,0
     99.endif
     100                .set LOAD,0x7c00                # Load address
     101                .set EXEC,0x600                 # Execution address
     102                .set MAGIC,0xaa55               # Magic: bootable
     103                .set HANDSHAKE,0x55aa           # Int13h EDD handshake
     104                .set SECSIZE,0x200              # Size of a single disk sector
     105
     106                .set UUID,0x1a0                 # Boot partition UUID offset
     107                .set DISKSIG,0x1b8              # Disk signature offset
     108                .set PT_OFF,0x1be               # Partition table offset
     109
     110                .set GPTSTACK,EXEC+SECSIZE*4-8  # Stack address
     111                .set LBABUF,GPTSTACK            # LBA address pointer buffer,
     112                                                #  8 bytes long, after stack
     113
     114                .set GPT_ADDR,LBABUF+8          # GPT header address
     115                .set GPT_SIG,0                  # Signature offset from LBA 1
     116                .set GPT_SIG_0,0x20494645       # "EFI ", bswapped
     117                .set GPT_SIG_1,0x54524150       # "PART", bswapped
     118                .set GPT_MYLBA,24               # Offs of curr header copy addr
     119                .set GPT_PART_LBA,72            # Offs of partitions start LBA
     120                .set GPT_NPART,80               # Offs to number of partitions
     121                .set GPT_PART_SIZE,84           # Offs to size of partition
     122                .set PART_ADDR,GPT_ADDR+SECSIZE # GPT partition array addr.
     123                .set PART_TYPE,0
     124                .set PART_START_LBA,32          # Offs to 1st LBA on part entry
     125                .set PART_END_LBA,40            # Offs to last LBA
     126
     127                .set NHRDRV,0x475               # Number of hard drives
     128
     129                .globl start                    # Entry point
     130                .code16
     131
     132#
     133# Setup the segment registers for flat addressing and setup the stack.
     134#
     135start:          cli                     # Clear interrupts before relocation
     136
     137                xorw %ax,%ax            # Zero
     138                movw %ax,%es            # Address
     139                movw %ax,%ds            #  data
     140
     141                movw %ax,%ss            # Set up
     142                movw $GPTSTACK,%sp      #  stack
     143
     144                std                     # String ops set to decrement
     145                movw $LOAD,%si          # We'll clear working memory starting
     146                leaw -1(%si),%di        #  from $LOAD-1 and stopping at EXEC.
     147                movw $(LOAD-EXEC-1),%cx #  In the end we have %si pointing
     148                rep stosb               #  at LOAD and %di at EXEC.
     149
     150
     151#
     152# Relocate ourself to a lower address so that we have more room to load
     153# other sectors.
     154#
     155reloc:          cld                     # String ops set to increment
     156                movw $SECSIZE,%cx       # Now we walk forward and relocate.
     157                rep movsb               #  Tricky, but works great!
     158
     159#
     160# Jump to the relocated code.
     161#
     162                jmp $0,$main                # Absolute address (far) jump
     163
     164#
     165# Will land here; we're now at %cs = 0x0000 and %ip a little above 0x0600
     166#
     167main:           sti                         # Re-enable interrupts
     168
     169.if VALIDATE_DRV
     170#
     171# Validate drive number in %dl. Certain BIOSes might not like it.
     172#
     173validate_drv:   cmpb $0x80,%dl              # Drive valid? (>= 0x80)
     174                jb validate_drv.1           # No
     175                movb NHRDRV,%dh             # Calculate the highest
     176                addb $0x80,%dh              #  drive number available
     177                cmpb %dh,%dl                # Within range?
     178                jb test_extensions          # Yes, proceed
     179validate_drv.1: movb $0x80,%dl              # Else, assume drive 0x80
     180.endif
     181
     182#
     183# Test if BIOS supports Int13h extensions. If so, will try GPT scheme first.
     184# Else, sets flag (%dh = 1) and goes straight to MBR code.
     185# (%dl still contains the drive number from BIOS bootstrap)
     186#
     187test_extensions:
     188                movb $0,%dh                 # We'll test for EDD extensions.
     189                                            #  LBA read (Int13,42) uses only
     190                                            #  %dl to get drive number and if
     191                                            #  we must fall back to CHS read
     192                                            #  (Int13,02), %dh receives head
     193                                            #  number, so it's clear to use
     194                                            #  %dh to hold a "use CHS" flag
     195
     196                movw $HANDSHAKE,%bx         # EDD extensions magic number
     197                movb $0x41,%ah              # BIOS: EDD extensions
     198                int $0x13                   #  present?
     199                jc set_chs                  # No, fall back to CHS read
     200
     201test_magic:     cmpw $MAGIC,%bx             # Magic ok?
     202                jne set_chs                 # No, fall back to CHS read
     203
     204test_packet:    testb $0x1,%cl              # Packet mode present?
     205                jnz load_gpt_hdr            # Yes!
     206
     207set_chs:        movb $1,%dh                 # read_chs overwrites this, and
     208                                            #  Int13,42 only uses %dl, so
     209                                            #  it's clear to use %dh as flag
     210                jmp try_mbr
     211
     212
     213#
     214# If we reached here, drive is valid, LBA reads are available, will try GPT.
     215# Load the primary GPT header from LBA 1 and verify signature.
     216#
     217load_gpt_hdr:   movw $GPT_ADDR,%bx
     218                movw $LBABUF,%si        # Will load LBA sector 1 from disk
     219                movb $1,(%si)           #  (64-bit value! Memory was zeroed so
     220                                        #  it's OK to write only the LSB)
     221                call read
     222                cmpl $GPT_SIG_0,GPT_ADDR+GPT_SIG
     223                jnz try_mbr             # If invalid GPT header
     224                cmpl $GPT_SIG_1,GPT_ADDR+GPT_SIG+4
     225                jnz try_mbr             # Fluke :( Try MBR now
     226
     227#
     228# GPT is valid. Load a partition table sector from disk and look for a
     229# partition matching the UUID found in boot_uuid.
     230#
     231load_part:      movw $GPT_ADDR+GPT_PART_LBA,%si
     232                movw $PART_ADDR,%bx
     233                call read
     234scan:           movw %bx,%si            # Compare partition UUID
     235                movw $boot_uuid,%di     #  with Haiku boot UUID
     236                movb $0x10,%cl          #  (16 bytes)
     237                repe cmpsb
     238                jnz next_part           # Didn't match, next partition
     239
     240#
     241# We found a partition. Load it into RAM starting at 0x7c00.
     242#
     243                movw %bx,%di                    # Save partition pointer in %di
     244                leaw PART_START_LBA(%di),%si
     245                movw $LOAD/16,%bx
     246                movw %bx,%es
     247                xorw %bx,%bx
     248load_bootcode:  push %si                        # Save %si
     249                call read
     250                pop %si                         # Restore
     251                movl PART_END_LBA(%di),%eax     # See if this was the last LBA
     252                cmpl (%si),%eax
     253                jnz next_boot_lba
     254                movl PART_END_LBA+4(%di),%eax
     255                cmpl 4(%si),%eax
     256                jnz next_boot_lba
     257                jmp start_loader                # Jump to boot code
     258
     259next_boot_lba:  incl (%si)                      # Next LBA
     260                adcl $0,4(%si)
     261                mov %es,%ax                     # Adjust segment for next
     262                addw $SECSIZE/16,%ax            #  sector
     263                cmp $0x9000,%ax                 # Don't load past 0x90000,
     264                jae start_loader                #  545k should be enough for
     265                mov %ax,%es                     #  any boot code. :)
     266                jmp load_bootcode
     267
     268#
     269# Move to the next partition. If we walk off the end of the sector, load
     270# the next sector.
     271#
     272next_part:      decl GPT_ADDR+GPT_NPART         # Was this the last partition?
     273                jz try_mbr                      # UUID boot signature not found
     274                movw GPT_ADDR+GPT_PART_SIZE,%ax
     275                addw %ax,%bx                    # Next partition
     276                cmpw $PART_ADDR+0x200,%bx       # Still in sector?
     277                jb scan
     278                incl GPT_ADDR+GPT_PART_LBA      # Next sector
     279                adcl $0,GPT_ADDR+GPT_PART_LBA+4
     280                jmp load_part
     281
     282#
     283# If loading boot sectors from a GPT partition fails, try booting a MBR part.
     284# Reset stack/segment. Could have been tainted by the GPT loading code.
     285#
     286try_mbr:        xorw %ax,%ax                # Zero
     287                movw %ax,%es                #  extra segment
     288                movw $LOAD,%sp              # Reset stack
     289
     290                xorw %si,%si                # Will point to active partition
     291                movw $partbl,%bx            # Point to partition table start
     292                movw $0x4,%cx               # Tested entries counter (4 total)
     293read_mbr_entry: cmpb %ch,(%bx)              # Null entry? (%ch just zeroed)
     294                je next_mbr_entry           # Yes
     295                jg err_part_table           # If 0x1..0x7f
     296                testw %si,%si               # Active already found?
     297                jnz err_part_table          # Yes
     298                movw %bx,%si                # Point to active
     299next_mbr_entry: addb $0x10,%bl              # Till
     300                loop read_mbr_entry         #  done
     301                testw %si,%si               # Active found?
     302                jnz read_bootsect           # Yes, read OS loader
     303try_diskless:   int $0x18                   # Else, BIOS: Diskless boot
     304
     305
     306#
     307# Ok, now that we have a valid drive and partition entry, load either CHS
     308# or LBA from the partition entry and read the boot sector from the partition.
     309#
     310read_bootsect:  movw %sp,%bx                # Write addr. (%sp points to LOAD)
     311                pushw %si                   # Points at active part. entry;
     312                                            #  save, else 'read' will trash it
     313
     314test_flag:      cmpb $1,%dh                 # Test flag set by set_chs above
     315                jz read_chs                 # CHS read if set
     316
     317read_lba:       addw $0x8,%si               # Start LBA of partition, 32-bit
     318                movw $LBABUF,%di            # So far either QWORD 1 or 0, so
     319                movsl                       #  top significant bytes are all 0
     320                xchg %di,%si                #  Copy to buffer and swap pointers
     321                subw $0x4,%si               # Adjust back to start of buffer
     322                call read
     323                jmp finished_read           # Skip the CHS setup
     324
     325read_chs:       movb 0x1(%si),%dh           # Load head
     326                movw 0x2(%si),%cx           # Load cylinder:sector
     327                movb $2,%al                 # Read two sectors
     328                movb $2,%ah                 # BIOS: Read sectors from disk
     329                int $0x13                   # Call the BIOS
     330
     331finished_read:  jc err_reading              # If error
     332
     333
     334#
     335# Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it
     336# is present, execute the bootstrap we just loaded.
     337#
     338                popw %si                    # Restore %si (active part entry)
     339                movb %dl,(%si)              # Patch part record with drive num
     340                cmpw $MAGIC,0x1fe(%bx)      # Bootable?
     341                jne err_noboot              # No, error out.
     342                                            #  Else, start loader
     343
     344start_loader:   xorw %ax,%ax
     345                movw %ax,%es                # Reset %es to zero
     346                jmp $0,$LOAD                # Jump to boot code
     347
     348
     349################################################################################
     350
     351# Auxiliary functions
     352
     353
     354#
     355# Load a sector (64-bit LBA at %si) from disk %dl into %es:%bx by creating
     356# a EDD packet on the stack and passing it to the BIOS. Trashes %ax and %si.
     357#
     358read:           pushl 0x4(%si)              # Set the LBA
     359                pushl 0x0(%si)              #  address
     360                pushw %es                   # Set the address of
     361                pushw %bx                   #  the transfer buffer
     362                pushw $0x1                  # Read 1 sector
     363                pushw $0x10                 # Packet length
     364                movw %sp,%si                # Packet pointer
     365                movw $0x4200,%ax            # BIOS: LBA Read from disk
     366                int $0x13                   # Call the BIOS
     367                add $0x10,%sp               # Restore stack
     368                jc err_reading              # If error
     369                ret
     370
     371
     372#
     373# Output an ASCIZ string pointed at by %si to the console via the BIOS.
     374#
     375putstr.0:       movw $0x7,%bx               # Page:attribute
     376                movb $0xe,%ah               # BIOS: Display
     377                int $0x10                   #  character
     378putstr:         lodsb                       # Get character
     379                testb %al,%al               # End of string?
     380                jnz putstr.0                # No
     381                ret
     382
     383
     384#
     385# Various error message entry points.
     386#
     387err_part_table: movw $msg_badtable,%si      # "Bad Part. Table!"
     388                call putstr
     389                jmp halt
     390
     391
     392err_reading:    movw $msg_ioerror,%si       # "Read Error!"
     393                call putstr
     394                jmp halt
     395
     396
     397err_noboot:     movw $msg_noloader,%si      # "No Sys Loader!"
     398                call putstr
     399#               jmp halt                    # ("halt" is right here)
     400
     401
     402halt:           cli
     403                hlt
     404                jmp halt
     405
     406
     407###############################################################################
     408
     409# Data section
     410
     411
     412# Error messages
     413
     414.if VALIDATE_DRV
     415# Messages must be shortened so the code fits 440 bytes
     416msg_badtable:   .asciz "BadPTbl!"
     417msg_ioerror:    .asciz "IOErr!"
     418msg_noloader:   .asciz "NoSysLdr!"
     419.else
     420msg_badtable:   .asciz "Bad Part. Table!"
     421msg_ioerror:    .asciz "Read Error!"
     422msg_noloader:   .asciz "No Sys Loader!"
     423.endif
     424
     425
     426# Boot partition UUID signature
     427
     428                .org UUID,0x0               # Zero-pad up to UUID offset
     429
     430boot_uuid:      .long 0x42465331            # 'BFS1' (formally, UUID time-low)
     431                .word 0x3ba3                # UUID time-mid
     432                .word 0x10f1                # UUID time-high & version (v1)
     433                .byte 0x80                  # UUID DCE 1.1 variant
     434                .byte 0x2a                  # '*' (formally, UUID clock-seq-low)
     435                .byte 0x48                  # 'H'
     436                .byte 0x61                  # 'a'
     437                .byte 0x69                  # 'i'
     438                .byte 0x6b                  # 'k'
     439                .byte 0x75                  # 'u'
     440                .byte 0x21                  # '!'
     441
     442# Disk signature
     443
     444                .org DISKSIG,0x0            # Zero-pad up to signature offset
     445
     446sig:            .long 0                     # OS Disk Signature
     447                .word 0                     # "Unknown" in PMBR
     448
     449
     450# Partition table
     451
     452                .org PT_OFF,0x0             # Won't pad, just documenting
     453
     454partbl:         .fill 0x10,0x4,0x0          # Partition table
     455                .word MAGIC                 # Magic number