mbr.s revision 134431
147471Srnordier# 247471Srnordier# Copyright (c) 1999 Robert Nordier 347471Srnordier# All rights reserved. 447471Srnordier# 547471Srnordier# Redistribution and use in source and binary forms are freely 647471Srnordier# permitted provided that the above copyright notice and this 747471Srnordier# paragraph and the following disclaimer are duplicated in all 847471Srnordier# such forms. 947471Srnordier# 1047471Srnordier# This software is provided "AS IS" and without any express or 1147471Srnordier# implied warranties, including, without limitation, the implied 1247471Srnordier# warranties of merchantability and fitness for a particular 1347471Srnordier# purpose. 1447471Srnordier# 1547471Srnordier 1650477Speter# $FreeBSD: head/sys/boot/i386/mbr/mbr.s 134431 2004-08-28 08:39:35Z yar $ 1747471Srnordier 1862146Sjhb# A 512 byte MBR boot manager that simply boots the active partition. 1947471Srnordier 2047471Srnordier .set LOAD,0x7c00 # Load address 2147471Srnordier .set EXEC,0x600 # Execution address 2247471Srnordier .set PT_OFF,0x1be # Partition table 2347471Srnordier .set MAGIC,0xaa55 # Magic: bootable 24134431Syar .set FL_PACKET,0x80 # Flag: try EDD 2547471Srnordier 2662176Sjhb .set NHRDRV,0x475 # Number of hard drives 2747471Srnordier 2847471Srnordier .globl start # Entry point 2960822Sjhb .code16 3047471Srnordier 3162146Sjhb# 3262146Sjhb# Setup the segment registers for flat addressing and setup the stack. 3362146Sjhb# 3447471Srnordierstart: cld # String ops inc 3560822Sjhb xorw %ax,%ax # Zero 3660822Sjhb movw %ax,%es # Address 3760822Sjhb movw %ax,%ds # data 3860822Sjhb movw %ax,%ss # Set up 3960822Sjhb movw $LOAD,%sp # stack 4062146Sjhb# 4162146Sjhb# Relocate ourself to a lower address so that we are out of the way when 4262146Sjhb# we load in the bootstrap from the partition to boot. 4362146Sjhb# 4460822Sjhb movw $main-EXEC+LOAD,%si # Source 4560822Sjhb movw $main,%di # Destination 4660822Sjhb movw $0x200-(main-start),%cx # Byte count 4747471Srnordier rep # Relocate 4847471Srnordier movsb # code 4962146Sjhb# 5062146Sjhb# Jump to the relocated code. 5162146Sjhb# 5260822Sjhb jmp main-LOAD+EXEC # To relocated code 5362146Sjhb# 5462146Sjhb# Scan the partition table looking for an active entry. Note that %ch is 5562146Sjhb# zero from the repeated string instruction above. We save the offset of 5662146Sjhb# the active partition in %si and scan the entire table to ensure that only 5762146Sjhb# one partition is marked active. 5862146Sjhb# 5960822Sjhbmain: xorw %si,%si # No active partition 6060822Sjhb movw $partbl,%bx # Partition table 6148033Srnordier movb $0x4,%cl # Number of entries 6260822Sjhbmain.1: cmpb %ch,(%bx) # Null entry? 6347471Srnordier je main.2 # Yes 6448033Srnordier jg err_pt # If 0x1..0x7f 6560822Sjhb testw %si,%si # Active already found? 6647471Srnordier jnz err_pt # Yes 6760822Sjhb movw %bx,%si # Point to active 6847471Srnordiermain.2: addb $0x10,%bl # Till 6947471Srnordier loop main.1 # done 7060822Sjhb testw %si,%si # Active found? 7147471Srnordier jnz main.3 # Yes 7247471Srnordier int $0x18 # BIOS: Diskless boot 7362146Sjhb# 7462146Sjhb# Ok, we've found a possible active partition. Check to see that the drive 7562176Sjhb# is a valid hard drive number. 7662146Sjhb# 7747471Srnordiermain.3: cmpb $0x80,%dl # Drive valid? 7847471Srnordier jb main.4 # No 7962176Sjhb movb NHRDRV,%dh # Calculate the highest 8062176Sjhb addb $0x80,%dh # drive number available 8162176Sjhb cmpb %dh,%dl # Within range? 8247471Srnordier jb main.5 # Yes 8362176Sjhbmain.4: movb (%si),%dl # Load drive 8462146Sjhb# 8562146Sjhb# Ok, now that we have a valid drive and partition entry, load the CHS from 8662146Sjhb# the partition entry and read the sector from the disk. 8762146Sjhb# 8862176Sjhbmain.5: movw %sp,%di # Save stack pointer 8962176Sjhb movb 0x1(%si),%dh # Load head 9060822Sjhb movw 0x2(%si),%cx # Load cylinder:sector 9160822Sjhb movw $LOAD,%bx # Transfer buffer 92134431Syar testb $FL_PACKET,flags # Try EDD? 93134431Syar jz main.7 # No. 9462176Sjhb pushw %cx # Save %cx 9562176Sjhb pushw %bx # Save %bx 9662176Sjhb movw $0x55aa,%bx # Magic 9762176Sjhb movb $0x41,%ah # BIOS: EDD extensions 9862176Sjhb int $0x13 # present? 9962176Sjhb jc main.6 # No. 10062176Sjhb cmpw $0xaa55,%bx # Magic ok? 10162176Sjhb jne main.6 # No. 10262176Sjhb testb $0x1,%cl # Packet mode present? 10362176Sjhb jz main.6 # No. 10462176Sjhb popw %bx # Restore %bx 10562176Sjhb pushl $0x0 # Set the LBA 10662176Sjhb pushl 0x8(%si) # address 10762176Sjhb pushw %es # Set the address of 10862176Sjhb pushw %bx # the transfer buffer 10962176Sjhb pushw $0x1 # Read 1 sector 11062176Sjhb pushw $0x10 # Packet length 11162176Sjhb movw %sp,%si # Packer pointer 11262176Sjhb movw $0x4200,%ax # BIOS: LBA Read from disk 11362176Sjhb jmp main.8 # Skip the CHS setup 11462176Sjhbmain.6: popw %bx # Restore %bx 11562176Sjhb popw %cx # Restore %cx 11662176Sjhbmain.7: movw $0x201,%ax # BIOS: Read from disk 11762176Sjhbmain.8: int $0x13 # Call the BIOS 11862176Sjhb movw %di,%sp # Restore stack 11947471Srnordier jc err_rd # If error 12062146Sjhb# 12162146Sjhb# Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it 12262146Sjhb# is present, execute the bootstrap we just loaded. 12362146Sjhb# 12460822Sjhb cmpw $MAGIC,0x1fe(%bx) # Bootable? 12547471Srnordier jne err_os # No 12660822Sjhb jmp *%bx # Invoke bootstrap 12762146Sjhb# 12862146Sjhb# Various error message entry points. 12962146Sjhb# 13060822Sjhberr_pt: movw $msg_pt,%si # "Invalid partition 13147471Srnordier jmp putstr # table" 13247471Srnordier 13360822Sjhberr_rd: movw $msg_rd,%si # "Error loading 13447471Srnordier jmp putstr # operating system" 13547471Srnordier 13660822Sjhberr_os: movw $msg_os,%si # "Missing operating 13747471Srnordier jmp putstr # system" 13862146Sjhb# 13962146Sjhb# Output an ASCIZ string to the console via the BIOS. 14062146Sjhb# 14160822Sjhbputstr.0: movw $0x7,%bx # Page:attribute 14247471Srnordier movb $0xe,%ah # BIOS: Display 14347471Srnordier int $0x10 # character 14447471Srnordierputstr: lodsb # Get character 14547471Srnordier testb %al,%al # End of string? 14647471Srnordier jnz putstr.0 # No 14747471Srnordierputstr.1: jmp putstr.1 # Await reset 14847471Srnordier 14947471Srnordiermsg_pt: .asciz "Invalid partition table" 15047471Srnordiermsg_rd: .asciz "Error loading operating system" 15147471Srnordiermsg_os: .asciz "Missing operating system" 15247471Srnordier 153134431Syar .org PT_OFF-1,0x90 154134431Syarflags: .byte FLAGS # Flags 15547471Srnordier 15647471Srnordierpartbl: .fill 0x10,0x4,0x0 # Partition table 15747471Srnordier .word MAGIC # Magic number 158