1f7eb23eeSEd Maste# 2f7eb23eeSEd Maste# Copyright (c) 1999 Robert Nordier 3f7eb23eeSEd Maste# All rights reserved. 4f7eb23eeSEd Maste# 5f7eb23eeSEd Maste# Redistribution and use in source and binary forms are freely 6f7eb23eeSEd Maste# permitted provided that the above copyright notice and this 7f7eb23eeSEd Maste# paragraph and the following disclaimer are duplicated in all 8f7eb23eeSEd Maste# such forms. 9f7eb23eeSEd Maste# 10f7eb23eeSEd Maste# This software is provided "AS IS" and without any express or 11f7eb23eeSEd Maste# implied warranties, including, without limitation, the implied 12f7eb23eeSEd Maste# warranties of merchantability and fitness for a particular 13f7eb23eeSEd Maste# purpose. 14f7eb23eeSEd Maste# 15f7eb23eeSEd Maste 16f7eb23eeSEd Maste# $FreeBSD$ 17f7eb23eeSEd Maste 18f7eb23eeSEd Maste# A 512 byte MBR boot manager that simply boots the active partition. 19f7eb23eeSEd Maste 20f7eb23eeSEd Maste .set LOAD,0x7c00 # Load address 21f7eb23eeSEd Maste .set EXEC,0x600 # Execution address 22f7eb23eeSEd Maste .set PT_OFF,0x1be # Partition table 23f7eb23eeSEd Maste .set MAGIC,0xaa55 # Magic: bootable 24f7eb23eeSEd Maste .set FL_PACKET,0x80 # Flag: try EDD 25f7eb23eeSEd Maste 26f7eb23eeSEd Maste .set NHRDRV,0x475 # Number of hard drives 27f7eb23eeSEd Maste 28f7eb23eeSEd Maste .globl start # Entry point 29f7eb23eeSEd Maste .code16 30f7eb23eeSEd Maste 31f7eb23eeSEd Maste# 32f7eb23eeSEd Maste# Setup the segment registers for flat addressing and setup the stack. 33f7eb23eeSEd Maste# 34f7eb23eeSEd Mastestart: cld # String ops inc 35f7eb23eeSEd Maste xorw %ax,%ax # Zero 36f7eb23eeSEd Maste movw %ax,%es # Address 37f7eb23eeSEd Maste movw %ax,%ds # data 38f7eb23eeSEd Maste movw %ax,%ss # Set up 39f7eb23eeSEd Maste movw $LOAD,%sp # stack 40f7eb23eeSEd Maste# 41f7eb23eeSEd Maste# Relocate ourself to a lower address so that we are out of the way when 42f7eb23eeSEd Maste# we load in the bootstrap from the partition to boot. 43f7eb23eeSEd Maste# 44f7eb23eeSEd Maste movw $main-EXEC+LOAD,%si # Source 45f7eb23eeSEd Maste movw $main,%di # Destination 46f7eb23eeSEd Maste movw $0x200-(main-start),%cx # Byte count 47f7eb23eeSEd Maste rep # Relocate 48f7eb23eeSEd Maste movsb # code 49f7eb23eeSEd Maste# 50f7eb23eeSEd Maste# Jump to the relocated code. 51f7eb23eeSEd Maste# 52f7eb23eeSEd Maste jmp main-LOAD+EXEC # To relocated code 53f7eb23eeSEd Maste# 54f7eb23eeSEd Maste# Scan the partition table looking for an active entry. Note that %ch is 55f7eb23eeSEd Maste# zero from the repeated string instruction above. We save the offset of 56f7eb23eeSEd Maste# the active partition in %si and scan the entire table to ensure that only 57f7eb23eeSEd Maste# one partition is marked active. 58f7eb23eeSEd Maste# 59f7eb23eeSEd Mastemain: xorw %si,%si # No active partition 60f7eb23eeSEd Maste movw $partbl,%bx # Partition table 61f7eb23eeSEd Maste movb $0x4,%cl # Number of entries 62f7eb23eeSEd Mastemain.1: cmpb %ch,(%bx) # Null entry? 63f7eb23eeSEd Maste je main.2 # Yes 64f7eb23eeSEd Maste jg err_pt # If 0x1..0x7f 65f7eb23eeSEd Maste testw %si,%si # Active already found? 66f7eb23eeSEd Maste jnz err_pt # Yes 67f7eb23eeSEd Maste movw %bx,%si # Point to active 68f7eb23eeSEd Mastemain.2: addb $0x10,%bl # Till 69f7eb23eeSEd Maste loop main.1 # done 70f7eb23eeSEd Maste testw %si,%si # Active found? 71f7eb23eeSEd Maste jnz main.3 # Yes 72f7eb23eeSEd Maste int $0x18 # BIOS: Diskless boot 73f7eb23eeSEd Maste# 74f7eb23eeSEd Maste# Ok, we've found a possible active partition. Check to see that the drive 75f7eb23eeSEd Maste# is a valid hard drive number. 76f7eb23eeSEd Maste# 77f7eb23eeSEd Mastemain.3: cmpb $0x80,%dl # Drive valid? 78f7eb23eeSEd Maste jb main.4 # No 79f7eb23eeSEd Maste movb NHRDRV,%dh # Calculate the highest 80f7eb23eeSEd Maste addb $0x80,%dh # drive number available 81f7eb23eeSEd Maste cmpb %dh,%dl # Within range? 82f7eb23eeSEd Maste jb main.5 # Yes 83f7eb23eeSEd Mastemain.4: movb (%si),%dl # Load drive 84f7eb23eeSEd Maste# 85f7eb23eeSEd Maste# Ok, now that we have a valid drive and partition entry, load the CHS from 86f7eb23eeSEd Maste# the partition entry and read the sector from the disk. 87f7eb23eeSEd Maste# 88f7eb23eeSEd Mastemain.5: movw %sp,%di # Save stack pointer 89f7eb23eeSEd Maste movb 0x1(%si),%dh # Load head 90f7eb23eeSEd Maste movw 0x2(%si),%cx # Load cylinder:sector 91f7eb23eeSEd Maste movw $LOAD,%bx # Transfer buffer 92f7eb23eeSEd Maste testb $FL_PACKET,flags # Try EDD? 93f7eb23eeSEd Maste jz main.7 # No. 94f7eb23eeSEd Maste pushw %cx # Save %cx 95f7eb23eeSEd Maste pushw %bx # Save %bx 96f7eb23eeSEd Maste movw $0x55aa,%bx # Magic 97f7eb23eeSEd Maste movb $0x41,%ah # BIOS: EDD extensions 98f7eb23eeSEd Maste int $0x13 # present? 99f7eb23eeSEd Maste jc main.6 # No. 100f7eb23eeSEd Maste cmpw $0xaa55,%bx # Magic ok? 101f7eb23eeSEd Maste jne main.6 # No. 102f7eb23eeSEd Maste testb $0x1,%cl # Packet mode present? 103f7eb23eeSEd Maste jz main.6 # No. 104f7eb23eeSEd Maste popw %bx # Restore %bx 105f7eb23eeSEd Maste pushl $0x0 # Set the LBA 106f7eb23eeSEd Maste pushl 0x8(%si) # address 107f7eb23eeSEd Maste pushw %es # Set the address of 108f7eb23eeSEd Maste pushw %bx # the transfer buffer 109f7eb23eeSEd Maste pushw $0x1 # Read 1 sector 110f7eb23eeSEd Maste pushw $0x10 # Packet length 111f7eb23eeSEd Maste movw %sp,%si # Packer pointer 112f7eb23eeSEd Maste movw $0x4200,%ax # BIOS: LBA Read from disk 113f7eb23eeSEd Maste jmp main.8 # Skip the CHS setup 114f7eb23eeSEd Mastemain.6: popw %bx # Restore %bx 115f7eb23eeSEd Maste popw %cx # Restore %cx 116f7eb23eeSEd Mastemain.7: movw $0x201,%ax # BIOS: Read from disk 117f7eb23eeSEd Mastemain.8: int $0x13 # Call the BIOS 118f7eb23eeSEd Maste movw %di,%sp # Restore stack 119f7eb23eeSEd Maste jc err_rd # If error 120f7eb23eeSEd Maste# 121f7eb23eeSEd Maste# Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it 122f7eb23eeSEd Maste# is present, execute the bootstrap we just loaded. 123f7eb23eeSEd Maste# 124f7eb23eeSEd Maste cmpw $MAGIC,0x1fe(%bx) # Bootable? 125f7eb23eeSEd Maste jne err_os # No 126f7eb23eeSEd Maste jmp *%bx # Invoke bootstrap 127f7eb23eeSEd Maste# 128f7eb23eeSEd Maste# Various error message entry points. 129f7eb23eeSEd Maste# 130f7eb23eeSEd Masteerr_pt: movw $msg_pt,%si # "Invalid partition 131f7eb23eeSEd Maste jmp putstr # table" 132f7eb23eeSEd Maste 133f7eb23eeSEd Masteerr_rd: movw $msg_rd,%si # "Error loading 134f7eb23eeSEd Maste jmp putstr # operating system" 135f7eb23eeSEd Maste 136f7eb23eeSEd Masteerr_os: movw $msg_os,%si # "Missing operating 137f7eb23eeSEd Maste jmp putstr # system" 138f7eb23eeSEd Maste# 139f7eb23eeSEd Maste# Output an ASCIZ string to the console via the BIOS. 140f7eb23eeSEd Maste# 141f7eb23eeSEd Masteputstr.0: movw $0x7,%bx # Page:attribute 142f7eb23eeSEd Maste movb $0xe,%ah # BIOS: Display 143f7eb23eeSEd Maste int $0x10 # character 144f7eb23eeSEd Masteputstr: lodsb # Get character 145f7eb23eeSEd Maste testb %al,%al # End of string? 146f7eb23eeSEd Maste jnz putstr.0 # No 147f7eb23eeSEd Masteputstr.1: jmp putstr.1 # Await reset 148f7eb23eeSEd Maste 149f7eb23eeSEd Mastemsg_pt: .asciz "Invalid partition table" 150f7eb23eeSEd Mastemsg_rd: .asciz "Error loading operating system" 151f7eb23eeSEd Mastemsg_os: .asciz "Missing operating system" 152f7eb23eeSEd Maste 153f7eb23eeSEd Maste .org PT_OFF-1,0x90 154f7eb23eeSEd Masteflags: .byte FLAGS # Flags 155f7eb23eeSEd Maste 156f7eb23eeSEd Mastepartbl: .fill 0x10,0x4,0x0 # Partition table 157f7eb23eeSEd Maste .word MAGIC # Magic number 158