Ticket #3441: MBRcode.diff
File MBRcode.diff, 22.6 KB (added by , 13 years ago) |
---|
-
build/jam/AnybootImage
14 14 15 15 actions BuildAnybootMBR1 { 16 16 $(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) 18 18 } 19 19 20 20 rule BuildAnybootImage anybootImage : mbrPart : isoPart : imageFile { -
src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp
37 37 #endif 38 38 39 39 40 // compiled form of hybrid FreeBSD pmbr and mbr loader done by André Braga40 // compiled mbr boot loader code 41 41 static 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 78 68 }; 79 69 80 70 -
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 15 13 16 /* A 512 byte MBR boot manager that simply boots the active partition. */17 14 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 22 17 23 .set NUM_HARD_DRIVES, 0x475 // Number of hard drives24 18 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 27 28 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 50 32 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 57 39 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? 134 44 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 138 77 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 155 80 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 159 83 160 .org PT_OFF 84 ;MACRO 85 ; nicer way to get the size of a structure 86 %define sizeof(s) s %+ _size 161 87 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 159 SECTION .text 160 BITS 16 161 ORG EXEC ; MBR is loaded at 0x7c00 but relocated at 0x600 162 start: ; 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 196 continue: ; Now we run EXEC_based relocated code 197 sti ; enable interrupts 198 %ifdef DEBUG 199 puts kMsgStart 200 %endif 201 202 search_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 213 found_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 225 check_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 238 disk_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 251 check_for_bootable_partition: 252 cmp word[LOAD+MAGIC_OFF],MAGIC ; if ( ! volume.isBootable() ) 253 jne no_bootable_active_partition; then error(); 254 255 jump_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 273 no_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 312 no_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 361 data: 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 375 end: 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 393 DiskSignature: 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