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:
parent
6e70e32dec
commit
4bcb62ee96
@ -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 {
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user