mbr: enable packet mode by default
[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 */