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