Ticket #3441: MBRcode.diff

File MBRcode.diff, 22.6 KB (added by starsseed, 13 years ago)

the source (should build fine now!)

  • build/jam/AnybootImage

     
    1414
    1515actions BuildAnybootMBR1 {
    1616    $(RM) $(1)
    17     $(TARGET_CC) $(MBR_SOURCE) -o $(1) -nostdlib -Xlinker --oformat=binary -Xlinker -S -Xlinker -N -Xlinker "-e start" -Xlinker "-Ttext=0x600"
     17    $(HAIKU_YASM) -f bin $(MBR_SOURCE) -O5 -o $(1)
    1818}
    1919
    2020rule BuildAnybootImage anybootImage : mbrPart : isoPart : imageFile {
  • src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp

     
    3737#endif
    3838
    3939
    40 // compiled form of hybrid FreeBSD pmbr and mbr loader done by André Braga
     40// compiled mbr boot loader code
    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,
    77     0xa3, 0x3b, 0xf1, 0x10, 0x80, 0x2a, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x21
     42    // compiled form of //haiku/trunk/src/bin/writembr/mbr.S
     43    // yasm -f bin -O5 -o mbrcode.bin mbr.S -dMBR_CODE_ONLY=1
     44    // bin2h <mbrcode.bin 12
     45    0xfa, 0xfc, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0x00,
     46    0x7c, 0xbf, 0x00, 0x08, 0xb9, 0x18, 0x00, 0xf3, 0xaa, 0xbe, 0x00, 0x7c,
     47    0x89, 0x36, 0x0c, 0x08, 0xc6, 0x06, 0x08, 0x08, 0x10, 0xc6, 0x06, 0x0a,
     48    0x08, 0x01, 0xbf, 0x00, 0x06, 0xb5, 0x01, 0xf3, 0xa5, 0xea, 0x32, 0x06,
     49    0x00, 0x00, 0xfb, 0xbe, 0xbe, 0x07, 0xb0, 0x04, 0x80, 0x3c, 0x80, 0x74,
     50    0x09, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xeb, 0x6d, 0x89, 0x36,
     51    0x04, 0x08, 0x66, 0x8b, 0x44, 0x08, 0x66, 0xa3, 0x10, 0x08, 0x66, 0x85,
     52    0xc0, 0x74, 0x27, 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x72, 0x1e,
     53    0xbe, 0x08, 0x08, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x15, 0x81, 0x3e, 0xfe,
     54    0x7d, 0x55, 0xaa, 0x75, 0x42, 0xbe, 0xfb, 0x06, 0xe8, 0x52, 0x00, 0x8b,
     55    0x36, 0x04, 0x08, 0xe9, 0x82, 0x75, 0x8b, 0x36, 0x04, 0x08, 0x8a, 0x74,
     56    0x01, 0x8b, 0x4c, 0x02, 0x88, 0xc8, 0x24, 0x3f, 0x84, 0xc0, 0x74, 0x23,
     57    0x3c, 0x3f, 0x75, 0x14, 0x89, 0xc8, 0xc0, 0xec, 0x06, 0x3d, 0xff, 0x03,
     58    0x75, 0x0a, 0x80, 0xfe, 0xff, 0x75, 0x05, 0x80, 0xfe, 0xfe, 0x74, 0x0b,
     59    0xbb, 0x00, 0x7c, 0xb0, 0x01, 0xb4, 0x02, 0xcd, 0x13, 0x73, 0xb6, 0xbe,
     60    0xdf, 0x06, 0xe8, 0x10, 0x00, 0xe8, 0x08, 0x00, 0xbe, 0xd5, 0x06, 0xe8,
     61    0x07, 0x00, 0xcd, 0x18, 0xb4, 0x00, 0xcd, 0x16, 0xc3, 0x31, 0xdb, 0xac,
     62    0xb4, 0x0e, 0xcd, 0x10, 0x08, 0xc0, 0x75, 0xf7, 0xc3, 0x52, 0x4f, 0x4d,
     63    0x20, 0x42, 0x41, 0x53, 0x49, 0x43, 0x00, 0x4e, 0x6f, 0x20, 0x62, 0x6f,
     64    0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76,
     65    0x65, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x0d, 0x0a, 0x00, 0x4c,
     66    0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
     67    0x6d, 0x0a, 0x0d, 0x00
    7868};
    7969
    8070
  • 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 /*
     1; Copyright 2011, Jean-Loïc Charroud, jcharroud@free.fr
     2; Distributed under the terms of the MIT License or LGPL v3
     3;
     4; Haiku (C) Copyright Haiku 2011
     5; MBR Boot code
     6;
     7; assemble the Master boot record with:
     8;   yasm -f bin -O5 -o mbr.bin mbr.S
     9;
     10; assemble the MBR's code (does not contain the partiton table
     11; nor the MAGIC code) with:
     12;   yasm -f bin -O5 -o mbrcode.bin mbr.S -dMBR_CODE_ONLY=1
    1513
    16 /* A 512 byte MBR boot manager that simply boots the active partition. */
    1714
    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
     15;%define    DEBUG           1
     16;%define    MBR_CODE_ONLY   1
    2217
    23         .set NUM_HARD_DRIVES, 0x475     // Number of hard drives
    2418
    25         .globl start                    // Entry point
    26         .code16
     19;CONST
     20    %assign DISKSIG         440             ; Disk signature offset
     21    %assign PT_OFF          0x1be           ; Partition table offset
     22    %assign MAGIC_OFF       0x1fe           ; Magic offset
     23    %assign MAGIC           0xaa55          ; Magic bootable signature
     24    %assign SECSIZE         0x200           ; Size of a single disk sector
     25    %assign FLG_ACTIVE      0x80            ; active partition flag
     26    %assign SECTOR_COUNT    0x01            ; Number of record to load from
     27                                            ; the ctive partition
    2728
    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
     29    %assign LOAD            0x7c00          ; Load address
     30    %assign EXEC            0x600           ; Execution address
     31    %assign HEAP            EXEC+SECSIZE    ; Execution address
    5032
    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  */
     33;BIOS calls
     34    %assign BIOS_VIDEO_SERVICES         0x10; ah - function
     35    %assign BIOS_DISK_SERVICES          0x13
     36    %assign BIOS_KEYBOARD_SERVICES      0X16
     37    %assign BIOS_BASIC                  0X18
     38    %assign BIOS_REBOOT                 0X19
    5739
    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                   //
     40    ;BIOS calls parameters
     41        ; video services
     42            %assign WRITE_CHAR          0x0e; al - char
     43                                            ; bh - page?
    13444
    135 err_loading_os:
    136         movw $msg_loading_os, %si       // "Error loading operating system"
    137         jmp putString                   //
     45        ; disk services
     46            %assign READ_DISK_SECTORS   0x02; dl    - drive
     47                                            ; es:bx - buffer
     48                                            ; dh    - head
     49                                            ; ch7:0 - track7:0
     50                                            ; cl7:6 - track9:8
     51                                            ;   5:0 - sector
     52                                            ; al    - sector count
     53                                            ; -> al - sectors read
     54            %assign READ_DRV_PARAMETERS 0x08; dl - drive
     55                                            ; -> cl - max cylinder 9:8
     56                                            ;       - sectors per track
     57                                            ;    ch - max cylinder 7:0
     58                                            ;    dh - max head
     59                                            ;    dl - number of drives (?)
     60            %assign CHK_DISK_EXTENTIONS 0x41; bx - 0x55aa
     61                                            ; dl - drive
     62                                            ; -> success: carry clear
     63                                            ;    ah - extension version
     64                                            ;    bx - 0xaa55
     65                                            ;    cx - support bit mask
     66                                            ;       1 - Device Access using the
     67                                            ;           packet structure
     68                                            ;       2 - Drive Locking and
     69                                            ;           Ejecting
     70                                            ;       4 - Enhanced Disk Drive
     71                                            ;           Support (EDD)
     72                                            ; -> error: carry set
     73            %assign EXTENDED_READ       0x42; dl - drive
     74                                            ; ds:si - address packet
     75                                            ; -> success: carry clear
     76                                            ; -> error: carry set
    13877
    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
     78            %assign FIXED_DSK_SUPPORT   0x1 ; flag indicating fixed disk
     79                                            ; extension command subset
    15580
    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"
     81        ; keyboard services
     82            %assign READ_CHAR           0x00; -> al - ASCII char
    15983
    160         .org PT_OFF
     84;MACRO
     85    ; nicer way to get the size of a structure
     86    %define sizeof(s)   s %+ _size
    16187
    162 partition_table:
    163         .fill 0x10,0x4,0x0              // Partition table
    164         .word MAGIC                     // Magic number
     88    ; using a structure in a another structure definition
     89    %macro  nstruc  1-2     1
     90        resb    sizeof(%1) * %2
     91    %endmacro
     92
     93    ; nicer way to access GlobalVariables
     94    %macro  declare_var 1
     95        %define %1  HEAP + GlobalVariables. %+ %1
     96    %endmacro
     97
     98    %macro  puts    1
     99        mov     si,     %1
     100        call    _puts
     101    %endmacro
     102
     103    %macro  error   1
     104        mov     si, %1
     105        jmp     _error
     106    %endmacro
     107
     108;TYPEDEFS
     109    ; 64 bit value
     110    struc   quadword
     111        .lower          resd    1
     112        .upper          resd    1
     113    endstruc
     114
     115    struc   CHS_addr
     116        .head           resb    1
     117        .sector         resb    1
     118        .cylindre       resb    1
     119    endstruc
     120
     121    struc   PartitionEntry
     122        .status         resb    1
     123        .CHS_first      nstruc  CHS_addr
     124        .type           resb    1
     125        .CHS_last       nstruc  CHS_addr
     126        .LBA_start      resd    1
     127        .LBA_size       resd    1
     128    endstruc
     129       
     130    ; address packet as required by the EXTENDED_READ BIOS call
     131    struc   AddressPacket
     132        .packet_size    resb    1
     133        .reserved       resb    1
     134        .block_count    resw    1
     135        .buffer         resd    1
     136        .sector         nstruc  quadword
     137        ;.long_buffer   nstruc  quadword
     138        ;   We don't need the 64 bit buffer pointer. The 32 bit .buffer is more
     139        ;   than sufficient.
     140    endstruc
     141
     142    ; Structure containing the variables that don't need pre-initialization.
     143    ; this structure will be allocated onto our "heap".
     144    struc   GlobalVariables
     145        .boot_drive_id              resd    1
     146        .boot_partition             resd    1
     147        .address_packet             nstruc  AddressPacket
     148    endstruc
     149
     150;alias for easy access to our global variables
     151    declare_var boot_drive_id
     152    declare_var boot_partition
     153    declare_var address_packet
     154
     155;/////////////////////////////////////////////////////////////////////////
     156;// A 512 byte MBR boot manager that simply boots the active partition. //
     157;/////////////////////////////////////////////////////////////////////////
     158; 16 bit code
     159SECTION .text
     160BITS 16
     161ORG EXEC                        ; MBR is loaded at 0x7c00 but relocated at 0x600
     162start:                          ; we run the LOADed code
     163        cli                     ; disable interrupts
     164        cld                     ; clear direction flag (for string operations)
     165    init:
     166        xor     ax,     ax      ; Zero
     167        mov     es,     ax      ; Set up extra segment
     168        mov     ds,     ax      ; Set up data segment
     169        mov     ss,     ax      ; Set up stack segment
     170        mov     sp,     LOAD    ; Set up stack pointer
     171
     172        ;init our heap allocated variables with zeros
     173        mov     di,     HEAP    ;start adress
     174        mov     cx,     sizeof(GlobalVariables) ;size
     175        rep                     ; while(cx--)
     176            stosb               ;   es[di++]:=al;
     177
     178    ; Relocate ourself to a lower address so that we are out of the way
     179    ; when we load in the bootstrap from the partition to boot.
     180    reloc:
     181        mov     si,     LOAD    ; Source
     182        ; init AddressPacket.buffer now since LOAD is in 'si'
     183        mov [address_packet+AddressPacket.buffer],si
     184        mov byte[address_packet+AddressPacket.packet_size],sizeof(AddressPacket)
     185        mov byte[address_packet+AddressPacket.block_count],SECTOR_COUNT
     186
     187        mov     di,     EXEC    ; Destination
     188        mov     ch,     1       ; count cx:=256 (cl cleared by precedent rep call)
     189        rep                     ; while(cx--)
     190            movsw               ;   es[di++]:=ds[si++]
     191                                ; //di and si are incremented by sizeof(word)
     192        jmp word 0x0000:continue; FAR jump to the relocated "continue" (some
     193                                ; BIOSes initialise CS to 0x07c0 so we must set
     194                                ; CS correctly)
     195
     196continue:                       ; Now we run EXEC_based relocated code
     197        sti                     ; enable interrupts
     198        %ifdef DEBUG
     199        puts    kMsgStart
     200        %endif
     201
     202search_active_partition:
     203        mov     si,EXEC+PT_OFF              ; point to first table entry
     204        mov     al,04                       ; there are 4 table entries
     205    .loop:                                  ; SEARCH FOR AN ACTIVE ENTRY
     206        cmp     byte[si],FLG_ACTIVE         ; is this the active entry?
     207        je      found_active                ; yes
     208        add     si, sizeof(PartitionEntry)  ; next PartitionEntry
     209        dec     al                          ; decrease remaining entry count
     210        jnz     .loop                       ; loop if entry count > 0
     211        jmp     no_bootable_active_partition; last partition reached
     212
     213found_active:                               ; active partition (pointed by si)
     214        mov     [boot_partition],si         ; Save active partition pointer
     215
     216    .get_read_sector:                       ; initialise address_packet:
     217        mov eax,[si + PartitionEntry.LBA_start]
     218        mov [address_packet+AddressPacket.sector],eax
     219
     220        ; if LBA_adress equals 0 then it's not a valid PBR (it is the MBR)
     221        ; this can append when we only have a CHS adress in the partition entry
     222        test    eax,        eax             ;if ( LBA_adress == 0 )
     223        jz      no_disk_extentions          ;then no_disk_extentions()
     224
     225check_disk_extensions:
     226        ; Note: this test may be unnecessary since EXTENDED_READ also
     227        ; set the carry flag when extended calls are not supported
     228        %ifdef DEBUG
     229        puts    kMsgCheckEx
     230        %endif
     231
     232        mov     ah, CHK_DISK_EXTENTIONS     ; set command
     233        mov     bx, 0x55aa                  ; set parameter : hton(MAGIC)
     234        ; dl has not changed yet, still contains the drive ID
     235        int     BIOS_DISK_SERVICES          ; if( do_command() <> OK )
     236        jc      no_disk_extentions          ; then use simple read operation
     237                                            ; else use extended read
     238disk_extentions:
     239        %ifdef DEBUG
     240        puts    kMsgRead_Ex
     241        %endif
     242
     243        ; load first bloc active partition
     244        ; dl has not changed yet, still contains the drive ID
     245        mov     si, address_packet          ; set command parameters
     246        mov     ah, EXTENDED_READ           ; set command
     247    .read_PBR:
     248        int     BIOS_DISK_SERVICES          ; if ( do_command() <> OK )
     249        jc      no_disk_extentions          ; then try CHS_read();
     250
     251check_for_bootable_partition:
     252        cmp     word[LOAD+MAGIC_OFF],MAGIC  ; if ( ! volume.isBootable() )
     253        jne     no_bootable_active_partition; then error();
     254
     255jump_PBR:
     256        %ifdef DEBUG
     257        puts    kMsgBootPBR
     258        call    _pause
     259        %else
     260        puts    kMsgStart
     261        %endif
     262
     263        ; jump to 0x7c00 with :
     264        ;   - CS=0
     265        ;   - DL=drive number
     266        ;   - DS:SI=pointer to the selected partition table
     267        ;           entry (required by some PBR)
     268
     269        ; dl has not changed yet, still contains the drive ID
     270        mov     si,     [boot_partition]
     271        jmp     LOAD                        ; jump into partition boot loader
     272
     273no_disk_extentions:
     274        %ifdef DEBUG
     275        puts    kMsgNoExtentions
     276        %endif
     277
     278        mov     si,     [boot_partition]    ; Restore active partition pointer
     279
     280        ;load CHS PBR sector info
     281        mov     dh,     [si+1]              ; dh 7:0 = head 7:0   (0 - 255)
     282        mov     cx,     [si+2]              ; cl 5:0 = sector 7:0 (1 - 63)
     283                                            ; cl 7:6 = cylinder 9:8 (0 - 1023)
     284                                            ; ch 7:0 = cylinder 7:0
     285    .check_Sector:
     286        mov     al,     cl
     287        and     al,     0x3F                ; extract sector
     288        test    al,     al;                 ; if (sector==0)
     289        jz      no_bootable_active_partition; then error("invalid sector");
     290        cmp     al,     0x3F                ; if(  (Sector == 63)
     291        jne     .CHS_valid                  ;
     292    .check_Cylinder:
     293        mov     ax,     cx
     294        shr     ah,     6
     295        cmp     ax,     0x03FF              ;   and  (Cylinder == 1023)
     296        jne     .CHS_valid
     297    .check_Head:
     298        cmp     dh,     0xFF                ;   and  ( (Head == 255)
     299        jne     .CHS_valid
     300        cmp     dh,     0xFE                ;       or (Head == 254) )  )
     301        je      no_bootable_active_partition; then error("invalid CHS_adress");
     302
     303    .CHS_valid:
     304        ; dl has not changed yet, still contains the drive ID
     305        mov     bx,     LOAD                ; set buffer
     306        mov     al,     SECTOR_COUNT        ; set Size
     307        mov     ah,     READ_DISK_SECTORS   ; set read command
     308        int     BIOS_DISK_SERVICES          ; if ( do_command() == OK )
     309        jnc     check_for_bootable_partition; then resume(normal boot sequence)
     310                                            ; else continue;
     311
     312no_bootable_active_partition:
     313        mov     si, kMsgNoBootable
     314        ;jmp _error                         ; _error is the next line !
     315
     316_error:
     317    ; display a non-empty null-terminated string on the screen,
     318    ; wait for a key pressed and go back to the bios
     319    ; IN :
     320    ;   - si = address of string to display
     321    ; OUT :
     322    ; DIRTY :
     323    ;   - ax
     324    ;   - si
     325        call    _puts
     326        call    _pause
     327        puts    kMsgROMBASIC
     328        int     BIOS_BASIC                  ; BIOS_BASIC give the control back
     329                                            ; to the BIOS. Doing so, let some
     330                                            ; BIOSes try to boot an alternate
     331                                            ; device (PXE/CD/HDD : see your
     332                                            ; BIOS' boot device order )
     333_pause:
     334    ; wait for a key pressed
     335    ; IN :
     336    ; OUT :
     337    ; DIRTY :
     338    ;   - ax
     339        mov     ah,     READ_CHAR
     340        int     BIOS_KEYBOARD_SERVICES
     341        ret
     342
     343_puts:
     344    ; display a non-empty null-terminated string on the screen
     345    ; IN :
     346    ;   - si = address of string to display
     347    ; OUT :
     348    ; DIRTY :
     349    ;   - ax
     350    ;   - bx
     351    ;   - si
     352        xor     bx,     bx                  ; bx:=0
     353    .loop:                                  ; do {
     354        lodsb                               ;   al=[si++];
     355        mov     ah,     WRITE_CHAR          ;   
     356        int     BIOS_VIDEO_SERVICES         ;   WRITE_CHAR(al)
     357        or      al, al                      ; } while (al<>0);
     358        jnz     .loop
     359        ret
     360
     361data:
     362        kMsgROMBASIC    db  'ROM BASIC',0
     363        kMsgNoBootable  db  'No bootable active volume',13,10,0
     364        kMsgStart       db  'Loading system',10,13,0
     365
     366    %ifdef DEBUG
     367        kMsgBootPBR     db  'JMP PBR',13,10,0
     368        kMsgRead_Ex     db  'Read_ex block',13,10,0
     369        kMsgCheckEx     db  'CheckEx',13,10,0
     370        kMsgNoExtentions db 'Read block',13,10,0
     371        kMsgReloc       db  'reloc MBR',13,10,0
     372    %endif
     373
     374; check whether the code is small enough to fit in the boot code area
     375end:
     376        ;use nasm instead of yasm to check  the code size
     377        ;%if end - start > DISKSIG
     378        ;   %error "Code exceeds master boot code area!"
     379        ;%endif
     380
     381%ifdef MBR_CODE_ONLY
     382    ;just build the code.
     383    ;Do not generate the datas
     384%else
     385        ;use nasm instead of yasm => use %rep instead of times
     386        ;%rep start + DISKSIG - end
     387        ;   db  0                   ;fill the rest of the code area
     388        ;%endrep
     389        times start + DISKSIG - end db 0
     390        kMbrDiskID  dd  0           ;Disk signature
     391        dw 0                        ;reserved
     392        PartitionTable times PartitionEntry_size * 4 db 0
     393DiskSignature:
     394        ;use nasm instead of yasm to check  the MAGIC offset
     395        ;%if DiskSignature - start <> MAGIC_OFF
     396        ;   %error "incorrect Disk Signature offset"
     397        ;%endif
     398        kMbrSignature   db  0x55, 0xAA
     399%endif