]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/boot/i386/mbr/mbr.s
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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$
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                 .set FL_PACKET,0x80             # Flag: try EDD
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                 testb $FL_PACKET,flags          # Try EDD?
93                 jz main.7                       # No.
94                 pushw %cx                       # Save %cx
95                 pushw %bx                       # Save %bx
96                 movw $0x55aa,%bx                # Magic
97                 movb $0x41,%ah                  # BIOS: EDD extensions
98                 int $0x13                       #  present?
99                 jc main.6                       # No.
100                 cmpw $0xaa55,%bx                # Magic ok?
101                 jne main.6                      # No.
102                 testb $0x1,%cl                  # Packet mode present?
103                 jz main.6                       # No.
104                 popw %bx                        # Restore %bx
105                 pushl $0x0                      # Set the LBA
106                 pushl 0x8(%si)                  #  address
107                 pushw %es                       # Set the address of
108                 pushw %bx                       #  the transfer buffer
109                 pushw $0x1                      # Read 1 sector
110                 pushw $0x10                     # Packet length
111                 movw %sp,%si                    # Packer pointer
112                 movw $0x4200,%ax                # BIOS: LBA Read from disk
113                 jmp main.8                      # Skip the CHS setup
114 main.6:         popw %bx                        # Restore %bx
115                 popw %cx                        # Restore %cx
116 main.7:         movw $0x201,%ax                 # BIOS: Read from disk
117 main.8:         int $0x13                       # Call the BIOS
118                 movw %di,%sp                    # Restore stack
119                 jc err_rd                       # If error
120 #
121 # Now that we've loaded the bootstrap, check for the 0xaa55 signature.  If it
122 # is present, execute the bootstrap we just loaded.
123 #
124                 cmpw $MAGIC,0x1fe(%bx)          # Bootable?
125                 jne err_os                      # No
126                 jmp *%bx                        # Invoke bootstrap
127 #
128 # Various error message entry points.
129 #
130 err_pt:         movw $msg_pt,%si                # "Invalid partition
131                 jmp putstr                      #  table"
132
133 err_rd:         movw $msg_rd,%si                # "Error loading
134                 jmp putstr                      #  operating system"
135
136 err_os:         movw $msg_os,%si                # "Missing operating
137                 jmp putstr                      #  system"
138 #
139 # Output an ASCIZ string to the console via the BIOS.
140
141 putstr.0:       movw $0x7,%bx                   # Page:attribute
142                 movb $0xe,%ah                   # BIOS: Display
143                 int $0x10                       #  character
144 putstr:         lodsb                           # Get character
145                 testb %al,%al                   # End of string?
146                 jnz putstr.0                    # No
147 putstr.1:       jmp putstr.1                    # Await reset
148
149 msg_pt:         .asciz "Invalid partition table"
150 msg_rd:         .asciz "Error loading operating system"
151 msg_os:         .asciz "Missing operating system"
152
153                 .org PT_OFF-1,0x90
154 flags:          .byte FLAGS                     # Flags
155
156 partbl:         .fill 0x10,0x4,0x0              # Partition table
157                 .word MAGIC                     # Magic number