xref: /dragonfly/stand/boot/pc32/mbr/mbr.S (revision 479ab7f0492f2a51b48e8537e4f1dc686fc6014b)
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 */
37start:              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 */
62main:               xorw %si,%si                             # No active partition
63                    movw $partbl,%bx               # Partition table
64                    movb $0x4,%cl                            # Number of entries
65main.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
71main.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 */
80main.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
86main.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 */
91main.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
121main.6:             popw %bx                       # Restore %bx
122                    popw %cx                       # Restore %cx
123main.7:             movw $0x201,%ax                          # BIOS: Read from disk
124main.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 */
137err_pt:   movw $msg_pt,%si               # "Invalid partition
138                    jmp putstr                               #  table"
139
140err_rd:   movw $msg_rd,%si               # "Error loading
141                    jmp putstr                               #  operating system"
142
143err_os:   movw $msg_os,%si               # "Missing operating
144                    jmp putstr                               #  system"
145/*
146 * Output an ASCIZ string to the console via the BIOS.
147 */
148putstr.0: movw $0x7,%bx                            # Page:attribute
149                    movb $0xe,%ah                            # BIOS: Display
150                    int $0x10                      #  character
151putstr:   lodsb                                    # Get character
152                    testb %al,%al                            # End of string?
153                    jnz putstr.0                             # No
154putstr.1: jmp putstr.1                             # Await reset
155
156msg_pt:   .asciz "Invalid partition table"
157msg_rd:   .asciz "Error loading operating system"
158msg_os:   .asciz "Missing operating system"
159
160                    .org PT_OFF
161
162partbl:   .fill 0x10,0x4,0x0             # Partition table
163                    .word MAGIC                              # Magic number
164