Applied patch by Jean-Loïc Charroud that reworks the anyboot MBR to fix boot

problems on various systems. Resolves #3441. Thanks!

+alpha3



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42104 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
anevilyak 2011-06-11 19:14:49 +00:00
parent 6e70e32dec
commit 4bcb62ee96
4 changed files with 416 additions and 190 deletions

View File

@ -14,7 +14,7 @@ rule BuildAnybootMBR binary : source {
actions BuildAnybootMBR1 {
$(RM) $(1)
$(TARGET_CC) $(MBR_SOURCE) -o $(1) -nostdlib -Xlinker --oformat=binary -Xlinker -S -Xlinker -N -Xlinker "-e start" -Xlinker "-Ttext=0x600"
$(HAIKU_YASM) -f bin $(MBR_SOURCE) -O5 -o $(1)
}
rule BuildAnybootImage anybootImage : mbrPart : isoPart : imageFile {

View File

@ -37,44 +37,34 @@ using std::nothrow;
#endif
// compiled form of hybrid FreeBSD pmbr and mbr loader done by André Braga
// compiled mbr boot loader code
static const uint8 kBootCode[] = {
0xfc, 0xe8, 0x05, 0x01, 0xbc, 0x00, 0x0e, 0xbe, 0x15, 0x7c, 0xbf, 0x15,
0x06, 0xb9, 0xeb, 0x01, 0xf3, 0xa4, 0xe9, 0x00, 0x8a, 0xe8, 0xfc, 0x00,
0xbb, 0x00, 0x0e, 0xbe, 0xb0, 0x07, 0xb9, 0x01, 0x00, 0xe8, 0x03, 0x01,
0x66, 0x81, 0x3e, 0x00, 0x0e, 0x45, 0x46, 0x49, 0x20, 0x75, 0x5c, 0x66,
0x81, 0x3e, 0x04, 0x0e, 0x50, 0x41, 0x52, 0x54, 0x75, 0x51, 0xbe, 0x48,
0x0e, 0xbb, 0x00, 0x10, 0xb9, 0x01, 0x00, 0xe8, 0xe1, 0x00, 0x89, 0xde,
0xbf, 0xa0, 0x07, 0xb1, 0x10, 0xf3, 0xa6, 0x75, 0x1b, 0x89, 0xdf, 0x8d,
0x75, 0x20, 0xbb, 0xc0, 0x07, 0x8e, 0xc3, 0x31, 0xdb, 0x56, 0x8a, 0x0e,
0x9f, 0x07, 0xe8, 0xc2, 0x00, 0x31, 0xc0, 0x8e, 0xc0, 0xe9, 0x94, 0x75,
0x66, 0xff, 0x0e, 0x50, 0x0e, 0x74, 0x18, 0xa1, 0x54, 0x0e, 0x01, 0xc3,
0x81, 0xfb, 0x00, 0x12, 0x72, 0xc8, 0x66, 0xff, 0x06, 0x48, 0x0e, 0x66,
0x83, 0x16, 0x4c, 0x0e, 0x00, 0xeb, 0xaf, 0xe8, 0x7b, 0x00, 0xbc, 0x00,
0x7c, 0x31, 0xf6, 0xbb, 0xbe, 0x07, 0xb1, 0x04, 0x38, 0x2f, 0x74, 0x0c,
0x0f, 0x8f, 0xa2, 0x00, 0x85, 0xf6, 0x0f, 0x85, 0x9c, 0x00, 0x89, 0xde,
0x80, 0xc3, 0x10, 0xe2, 0xeb, 0x85, 0xf6, 0x75, 0x02, 0xcd, 0x18, 0xe8,
0x5e, 0x00, 0x89, 0xe7, 0x8a, 0x74, 0x01, 0x8b, 0x4c, 0x02, 0xbb, 0x00,
0x7c, 0xf6, 0x06, 0x9e, 0x07, 0x80, 0x74, 0x2d, 0x51, 0x53, 0xbb, 0xaa,
0x55, 0xb4, 0x41, 0xcd, 0x13, 0x72, 0x20, 0x81, 0xfb, 0x55, 0xaa, 0x75,
0x1a, 0xf6, 0xc1, 0x01, 0x74, 0x15, 0x5b, 0x66, 0x6a, 0x00, 0x66, 0xff,
0x74, 0x08, 0x06, 0x53, 0x6a, 0x01, 0x6a, 0x10, 0x89, 0xe6, 0xb8, 0x00,
0x42, 0xeb, 0x05, 0x5b, 0x59, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x89, 0xfc,
0x72, 0x49, 0x81, 0xbf, 0xfe, 0x01, 0x55, 0xaa, 0x75, 0x46, 0xe9, 0x5c,
0xff, 0x31, 0xc9, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xc3,
0x80, 0xfa, 0x80, 0x72, 0x0b, 0x8a, 0x36, 0x75, 0x04, 0x80, 0xc6, 0x80,
0x38, 0xf2, 0x72, 0x02, 0xb2, 0x80, 0xc3, 0x66, 0xff, 0x74, 0x04, 0x66,
0xff, 0x34, 0x06, 0x53, 0x51, 0x6a, 0x10, 0x89, 0xe6, 0xb8, 0x00, 0x42,
0xcd, 0x13, 0x83, 0xc4, 0x10, 0x0f, 0x82, 0x4a, 0xff, 0xc3, 0xbe, 0x60,
0x07, 0xeb, 0x11, 0xbe, 0x74, 0x07, 0xeb, 0x0c, 0xbe, 0x7d, 0x07, 0xeb,
0x07, 0xbb, 0x07, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xac, 0x84, 0xc0, 0x75,
0xf4, 0xf4, 0xeb, 0xfd, 0x42, 0x61, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x00,
0x49, 0x4f, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x4d, 0x69, 0x73,
0x73, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20,
0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0x31, 0x53, 0x46, 0x42,
0xa3, 0x3b, 0xf1, 0x10, 0x80, 0x2a, 0x48, 0x61, 0x69, 0x6b, 0x75, 0x21
// compiled form of //haiku/trunk/src/bin/writembr/mbr.S
// yasm -f bin -O5 -o mbrcode.bin mbr.S -dMBR_CODE_ONLY=1
// bin2h <mbrcode.bin 12
0xfa, 0xfc, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0x00,
0x7c, 0xbf, 0x00, 0x08, 0xb9, 0x18, 0x00, 0xf3, 0xaa, 0xbe, 0x00, 0x7c,
0x89, 0x36, 0x0c, 0x08, 0xc6, 0x06, 0x08, 0x08, 0x10, 0xc6, 0x06, 0x0a,
0x08, 0x01, 0xbf, 0x00, 0x06, 0xb5, 0x01, 0xf3, 0xa5, 0xea, 0x32, 0x06,
0x00, 0x00, 0xfb, 0xbe, 0xbe, 0x07, 0xb0, 0x04, 0x80, 0x3c, 0x80, 0x74,
0x09, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xeb, 0x6d, 0x89, 0x36,
0x04, 0x08, 0x66, 0x8b, 0x44, 0x08, 0x66, 0xa3, 0x10, 0x08, 0x66, 0x85,
0xc0, 0x74, 0x27, 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0xcd, 0x13, 0x72, 0x1e,
0xbe, 0x08, 0x08, 0xb4, 0x42, 0xcd, 0x13, 0x72, 0x15, 0x81, 0x3e, 0xfe,
0x7d, 0x55, 0xaa, 0x75, 0x42, 0xbe, 0xfb, 0x06, 0xe8, 0x52, 0x00, 0x8b,
0x36, 0x04, 0x08, 0xe9, 0x82, 0x75, 0x8b, 0x36, 0x04, 0x08, 0x8a, 0x74,
0x01, 0x8b, 0x4c, 0x02, 0x88, 0xc8, 0x24, 0x3f, 0x84, 0xc0, 0x74, 0x23,
0x3c, 0x3f, 0x75, 0x14, 0x89, 0xc8, 0xc0, 0xec, 0x06, 0x3d, 0xff, 0x03,
0x75, 0x0a, 0x80, 0xfe, 0xff, 0x75, 0x05, 0x80, 0xfe, 0xfe, 0x74, 0x0b,
0xbb, 0x00, 0x7c, 0xb0, 0x01, 0xb4, 0x02, 0xcd, 0x13, 0x73, 0xb6, 0xbe,
0xdf, 0x06, 0xe8, 0x10, 0x00, 0xe8, 0x08, 0x00, 0xbe, 0xd5, 0x06, 0xe8,
0x07, 0x00, 0xcd, 0x18, 0xb4, 0x00, 0xcd, 0x16, 0xc3, 0x31, 0xdb, 0xac,
0xb4, 0x0e, 0xcd, 0x10, 0x08, 0xc0, 0x75, 0xf7, 0xc3, 0x52, 0x4f, 0x4d,
0x20, 0x42, 0x41, 0x53, 0x49, 0x43, 0x00, 0x4e, 0x6f, 0x20, 0x62, 0x6f,
0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76,
0x65, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x0d, 0x0a, 0x00, 0x4c,
0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
0x6d, 0x0a, 0x0d, 0x00
};

View File

@ -1051,6 +1051,7 @@ AboutView::_CreateCreditsView()
"Andre Braga\n"
"Michael Bulash\n"
"Bruce Cameron\n"
"Jean-Loïc Charroud\n"
"Greg Crain\n"
"Michael Davidson\n"
"David Dengg\n"

View File

@ -1,164 +1,399 @@
/*
** Copyright (c) 1999 Robert Nordier
** All rights reserved.
**
** Redistribution and use in source and binary forms are freely
** permitted provided that the above copyright notice and this
** paragraph and the following disclaimer are duplicated in all
** such forms.
**
** This software is provided "AS IS" and without any express or
** implied warranties, including, without limitation, the implied
** warranties of merchantability and fitness for a particular
** purpose.
/*
; Copyright 2011, Jean-Loïc Charroud, jcharroud@free.fr
; Distributed under the terms of the MIT License or LGPL v3
;
; Haiku (C) Copyright Haiku 2011
; MBR Boot code
;
; assemble the Master boot record with:
; yasm -f bin -O5 -o mbr.bin mbr.S
;
; assemble the MBR's code (does not contain the partiton table
; nor the MAGIC code) with:
; yasm -f bin -O5 -o mbrcode.bin mbr.S -dMBR_CODE_ONLY=1
/* A 512 byte MBR boot manager that simply boots the active partition. */
.set LOAD, 0x7c00 // Load address
.set EXEC, 0x600 // Execution address
.set PT_OFF, 0x1be // Partition table
.set MAGIC, 0xaa55 // Magic: bootable
;%define DEBUG 1
;%define MBR_CODE_ONLY 1
.set NUM_HARD_DRIVES, 0x475 // Number of hard drives
.globl start // Entry point
.code16
;CONST
%assign DISKSIG 440 ; Disk signature offset
%assign PT_OFF 0x1be ; Partition table offset
%assign MAGIC_OFF 0x1fe ; Magic offset
%assign MAGIC 0xaa55 ; Magic bootable signature
%assign SECSIZE 0x200 ; Size of a single disk sector
%assign FLG_ACTIVE 0x80 ; active partition flag
%assign SECTOR_COUNT 0x01 ; Number of record to load from
; the ctive partition
/*
* Setup the segment registers for flat addressing and setup the stack.
*/
start: cld // String ops inc
xorw %ax, %ax // Zero
movw %ax, %es // Address
movw %ax, %ds // data
movw %ax, %ss // Set up stack
movw $LOAD, %sp //
/*
* Relocate ourself to a lower address so that we are out of the way when
* we load in the bootstrap from the partition to boot.
*/
movw $main-EXEC+LOAD, %si // Source
movw $main, %di // Destination
movw $0x200-(main-start), %cx // Byte count
rep // Relocate code
movsb //
/*
* Jump to the relocated code.
*/
jmp main-LOAD+EXEC // Jump to relocated code
%assign LOAD 0x7c00 ; Load address
%assign EXEC 0x600 ; Execution address
%assign HEAP EXEC+SECSIZE ; Execution address
/*
* Scan the partition table looking for an active entry. Note that %ch is
* zero from the repeated string instruction above. We save the offset of
* the active partition in %si and scan the entire table to ensure that only
* one partition is marked active.
*/
;BIOS calls
%assign BIOS_VIDEO_SERVICES 0x10; ah - function
%assign BIOS_DISK_SERVICES 0x13
%assign BIOS_KEYBOARD_SERVICES 0X16
%assign BIOS_BASIC 0X18
%assign BIOS_REBOOT 0X19
main: xorw %si, %si // No active partition
movw $partition_table, %bx // Partition table
movb $0x4, %cl // Number of entries
main.1: cmpb %ch, (%bx) // Null entry?
je main.2 // Yes
jg err_partition_table // If 0x1..0x7f
testw %si, %si // Active already found?
jnz err_partition_table // Yes
movw %bx, %si // Point to active
main.2: addb $0x10, %bl // Till
loop main.1 // done
testw %si, %si // Active found?
jnz main.3 // Yes
int $0x18 // BIOS: Diskless boot
/*
* Ok, we've found a possible active partition. Check to see that the drive
* is a valid hard drive number.
*/
main.3: cmpb $0x80, %dl // Drive valid?
jb main.4 // No
movb NUM_HARD_DRIVES, %dh // Calculate the highest
addb $0x80, %dh // drive number available
cmpb %dh, %dl // Within range?
jb main.5 // Yes
main.4: movb (%si), %dl // Load drive
/*
* Ok, now that we have a valid drive and partition entry, load the CHS from
* the partition entry and read the sector from the disk.
*/
main.5: movw %sp, %di // Save stack pointer
movb 0x1(%si), %dh // Load head
movw 0x2(%si), %cx // Load cylinder:sector
movw $LOAD, %bx // Transfer buffer
cmpb $0xff, %dh // Might we need to use LBA?
jnz main.7 // No.
cmpw $0xffff, %cx // Do we need to use LBA?
jnz main.7 // No.
pushw %cx // Save %cx
pushw %bx // Save %bx
movw $0x55aa, %bx // Reversed Magic
movb $0x41, %ah // BIOS: EDD extensions present?
int $0x13 //
jc main.6 // No.
cmpw $MAGIC, %bx // Magic ok?
jne main.6 // No.
testb $0x1, %cl // Packet mode present?
jz main.6 // No.
popw %bx // Restore %bx
pushl $0x0 // Set the LBA
pushl 0x8(%si) // address
pushw %es // Set the address of
pushw %bx // the transfer buffer
pushw $0x1 // Read 1 sector
pushw $0x10 // Packet length
movw %sp, %si // Packet pointer
movw $0x4200, %ax // BIOS: LBA Read from disk
jmp main.8 // Skip the CHS setup
main.6: popw %bx // Restore %bx
popw %cx // Restore %cx
main.7: movw $0x201, %ax // BIOS: Read from disk
main.8: int $0x13 // Call the BIOS
movw %di,%sp // Restore stack
jc err_loading_os // If error
/*
* Now that we've loaded the bootstrap, check for the magic 0xaa55 signature.
* If it is present, execute the bootstrap we just loaded.
*/
cmpw $MAGIC, 0x1fe(%bx) // Bootable?
jne err_missing_os // No
jmp *%bx // Invoke bootstrap
/*
* Various error message entry points.
*/
err_partition_table:
movw $msg_partition_table, %si // "Invalid partition table"
jmp putString //
;BIOS calls parameters
; video services
%assign WRITE_CHAR 0x0e; al - char
; bh - page?
err_loading_os:
movw $msg_loading_os, %si // "Error loading operating system"
jmp putString //
; disk services
%assign READ_DISK_SECTORS 0x02; dl - drive
; es:bx - buffer
; dh - head
; ch7:0 - track7:0
; cl7:6 - track9:8
; 5:0 - sector
; al - sector count
; -> al - sectors read
%assign READ_DRV_PARAMETERS 0x08; dl - drive
; -> cl - max cylinder 9:8
; - sectors per track
; ch - max cylinder 7:0
; dh - max head
; dl - number of drives (?)
%assign CHK_DISK_EXTENTIONS 0x41; bx - 0x55aa
; dl - drive
; -> success: carry clear
; ah - extension version
; bx - 0xaa55
; cx - support bit mask
; 1 - Device Access using the
; packet structure
; 2 - Drive Locking and
; Ejecting
; 4 - Enhanced Disk Drive
; Support (EDD)
; -> error: carry set
%assign EXTENDED_READ 0x42; dl - drive
; ds:si - address packet
; -> success: carry clear
; -> error: carry set
err_missing_os:
movw $msg_missing_os, %si // "Missing operating system"
jmp putString //
/*
* Output an ASCIZ string to the console via the BIOS.
*/
putString.0:
movw $0x7, %bx // Page:attribute
movb $0xe, %ah // BIOS: Display character
int $0x10 //
putString:
lodsb // Get character
testb %al,%al // End of string?
jnz putString.0 // No
putString.1:
jmp putString.1 // Await reset
%assign FIXED_DSK_SUPPORT 0x1 ; flag indicating fixed disk
; extension command subset
msg_partition_table: .asciz "Invalid partition table"
msg_loading_os: .asciz "Error loading operating system"
msg_missing_os: .asciz "Missing operating system"
; keyboard services
%assign READ_CHAR 0x00; -> al - ASCII char
.org PT_OFF
;MACRO
; nicer way to get the size of a structure
%define sizeof(s) s %+ _size
partition_table:
.fill 0x10,0x4,0x0 // Partition table
.word MAGIC // Magic number
; using a structure in a another structure definition
%macro nstruc 1-2 1
resb sizeof(%1) * %2
%endmacro
; nicer way to access GlobalVariables
%macro declare_var 1
%define %1 HEAP + GlobalVariables. %+ %1
%endmacro
%macro puts 1
mov si, %1
call _puts
%endmacro
%macro error 1
mov si, %1
jmp _error
%endmacro
;TYPEDEFS
; 64 bit value
struc quadword
.lower resd 1
.upper resd 1
endstruc
struc CHS_addr
.head resb 1
.sector resb 1
.cylindre resb 1
endstruc
struc PartitionEntry
.status resb 1
.CHS_first nstruc CHS_addr
.type resb 1
.CHS_last nstruc CHS_addr
.LBA_start resd 1
.LBA_size resd 1
endstruc
; address packet as required by the EXTENDED_READ BIOS call
struc AddressPacket
.packet_size resb 1
.reserved resb 1
.block_count resw 1
.buffer resd 1
.sector nstruc quadword
;.long_buffer nstruc quadword
; We don't need the 64 bit buffer pointer. The 32 bit .buffer is more
; than sufficient.
endstruc
; Structure containing the variables that don't need pre-initialization.
; this structure will be allocated onto our "heap".
struc GlobalVariables
.boot_drive_id resd 1
.boot_partition resd 1
.address_packet nstruc AddressPacket
endstruc
;alias for easy access to our global variables
declare_var boot_drive_id
declare_var boot_partition
declare_var address_packet
;/////////////////////////////////////////////////////////////////////////
;// A 512 byte MBR boot manager that simply boots the active partition. //
;/////////////////////////////////////////////////////////////////////////
; 16 bit code
SECTION .text
BITS 16
ORG EXEC ; MBR is loaded at 0x7c00 but relocated at 0x600
start: ; we run the LOADed code
cli ; disable interrupts
cld ; clear direction flag (for string operations)
init:
xor ax, ax ; Zero
mov es, ax ; Set up extra segment
mov ds, ax ; Set up data segment
mov ss, ax ; Set up stack segment
mov sp, LOAD ; Set up stack pointer
;init our heap allocated variables with zeros
mov di, HEAP ;start adress
mov cx, sizeof(GlobalVariables) ;size
rep ; while(cx--)
stosb ; es[di++]:=al;
; Relocate ourself to a lower address so that we are out of the way
; when we load in the bootstrap from the partition to boot.
reloc:
mov si, LOAD ; Source
; init AddressPacket.buffer now since LOAD is in 'si'
mov [address_packet+AddressPacket.buffer],si
mov byte[address_packet+AddressPacket.packet_size],sizeof(AddressPacket)
mov byte[address_packet+AddressPacket.block_count],SECTOR_COUNT
mov di, EXEC ; Destination
mov ch, 1 ; count cx:=256 (cl cleared by precedent rep call)
rep ; while(cx--)
movsw ; es[di++]:=ds[si++]
; //di and si are incremented by sizeof(word)
jmp word 0x0000:continue; FAR jump to the relocated "continue" (some
; BIOSes initialise CS to 0x07c0 so we must set
; CS correctly)
continue: ; Now we run EXEC_based relocated code
sti ; enable interrupts
%ifdef DEBUG
puts kMsgStart
%endif
search_active_partition:
mov si,EXEC+PT_OFF ; point to first table entry
mov al,04 ; there are 4 table entries
.loop: ; SEARCH FOR AN ACTIVE ENTRY
cmp byte[si],FLG_ACTIVE ; is this the active entry?
je found_active ; yes
add si, sizeof(PartitionEntry) ; next PartitionEntry
dec al ; decrease remaining entry count
jnz .loop ; loop if entry count > 0
jmp no_bootable_active_partition; last partition reached
found_active: ; active partition (pointed by si)
mov [boot_partition],si ; Save active partition pointer
.get_read_sector: ; initialise address_packet:
mov eax,[si + PartitionEntry.LBA_start]
mov [address_packet+AddressPacket.sector],eax
; if LBA_adress equals 0 then it's not a valid PBR (it is the MBR)
; this can append when we only have a CHS adress in the partition entry
test eax, eax ;if ( LBA_adress == 0 )
jz no_disk_extentions ;then no_disk_extentions()
check_disk_extensions:
; Note: this test may be unnecessary since EXTENDED_READ also
; set the carry flag when extended calls are not supported
%ifdef DEBUG
puts kMsgCheckEx
%endif
mov ah, CHK_DISK_EXTENTIONS ; set command
mov bx, 0x55aa ; set parameter : hton(MAGIC)
; dl has not changed yet, still contains the drive ID
int BIOS_DISK_SERVICES ; if( do_command() <> OK )
jc no_disk_extentions ; then use simple read operation
; else use extended read
disk_extentions:
%ifdef DEBUG
puts kMsgRead_Ex
%endif
; load first bloc active partition
; dl has not changed yet, still contains the drive ID
mov si, address_packet ; set command parameters
mov ah, EXTENDED_READ ; set command
.read_PBR:
int BIOS_DISK_SERVICES ; if ( do_command() <> OK )
jc no_disk_extentions ; then try CHS_read();
check_for_bootable_partition:
cmp word[LOAD+MAGIC_OFF],MAGIC ; if ( ! volume.isBootable() )
jne no_bootable_active_partition; then error();
jump_PBR:
%ifdef DEBUG
puts kMsgBootPBR
call _pause
%else
puts kMsgStart
%endif
; jump to 0x7c00 with :
; - CS=0
; - DL=drive number
; - DS:SI=pointer to the selected partition table
; entry (required by some PBR)
; dl has not changed yet, still contains the drive ID
mov si, [boot_partition]
jmp LOAD ; jump into partition boot loader
no_disk_extentions:
%ifdef DEBUG
puts kMsgNoExtentions
%endif
mov si, [boot_partition] ; Restore active partition pointer
;load CHS PBR sector info
mov dh, [si+1] ; dh 7:0 = head 7:0 (0 - 255)
mov cx, [si+2] ; cl 5:0 = sector 7:0 (1 - 63)
; cl 7:6 = cylinder 9:8 (0 - 1023)
; ch 7:0 = cylinder 7:0
.check_Sector:
mov al, cl
and al, 0x3F ; extract sector
test al, al; ; if (sector==0)
jz no_bootable_active_partition; then error("invalid sector");
cmp al, 0x3F ; if( (Sector == 63)
jne .CHS_valid ;
.check_Cylinder:
mov ax, cx
shr ah, 6
cmp ax, 0x03FF ; and (Cylinder == 1023)
jne .CHS_valid
.check_Head:
cmp dh, 0xFF ; and ( (Head == 255)
jne .CHS_valid
cmp dh, 0xFE ; or (Head == 254) ) )
je no_bootable_active_partition; then error("invalid CHS_adress");
.CHS_valid:
; dl has not changed yet, still contains the drive ID
mov bx, LOAD ; set buffer
mov al, SECTOR_COUNT ; set Size
mov ah, READ_DISK_SECTORS ; set read command
int BIOS_DISK_SERVICES ; if ( do_command() == OK )
jnc check_for_bootable_partition; then resume(normal boot sequence)
; else continue;
no_bootable_active_partition:
mov si, kMsgNoBootable
;jmp _error ; _error is the next line !
_error:
; display a non-empty null-terminated string on the screen,
; wait for a key pressed and go back to the bios
; IN :
; - si = address of string to display
; OUT :
; DIRTY :
; - ax
; - si
call _puts
call _pause
puts kMsgROMBASIC
int BIOS_BASIC ; BIOS_BASIC give the control back
; to the BIOS. Doing so, let some
; BIOSes try to boot an alternate
; device (PXE/CD/HDD : see your
; BIOS' boot device order )
_pause:
; wait for a key pressed
; IN :
; OUT :
; DIRTY :
; - ax
mov ah, READ_CHAR
int BIOS_KEYBOARD_SERVICES
ret
_puts:
; display a non-empty null-terminated string on the screen
; IN :
; - si = address of string to display
; OUT :
; DIRTY :
; - ax
; - bx
; - si
xor bx, bx ; bx:=0
.loop: ; do {
lodsb ; al=[si++];
mov ah, WRITE_CHAR ;
int BIOS_VIDEO_SERVICES ; WRITE_CHAR(al)
or al, al ; } while (al<>0);
jnz .loop
ret
data:
kMsgROMBASIC db 'ROM BASIC',0
kMsgNoBootable db 'No bootable active volume',13,10,0
kMsgStart db 'Loading system',10,13,0
%ifdef DEBUG
kMsgBootPBR db 'JMP PBR',13,10,0
kMsgRead_Ex db 'Read_ex block',13,10,0
kMsgCheckEx db 'CheckEx',13,10,0
kMsgNoExtentions db 'Read block',13,10,0
kMsgReloc db 'reloc MBR',13,10,0
%endif
; check whether the code is small enough to fit in the boot code area
end:
;use nasm instead of yasm to check the code size
;%if end - start > DISKSIG
; %error "Code exceeds master boot code area!"
;%endif
%ifdef MBR_CODE_ONLY
;just build the code.
;Do not generate the datas
%else
;use nasm instead of yasm => use %rep instead of times
;%rep start + DISKSIG - end
; db 0 ;fill the rest of the code area
;%endrep
times start + DISKSIG - end db 0
kMbrDiskID dd 0 ;Disk signature
dw 0 ;reserved
PartitionTable times PartitionEntry_size * 4 db 0
DiskSignature:
;use nasm instead of yasm to check the MAGIC offset
;%if DiskSignature - start <> MAGIC_OFF
; %error "incorrect Disk Signature offset"
;%endif
kMbrSignature db 0x55, 0xAA
%endif