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