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