2 * Copyright (c) 1999 Robert Nordier
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
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
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 $
21 * A 512 byte MBR boot manager that simply boots the active partition.
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 */
29 .set NHRDRV,0x475 /* Number of hard drives */
31 .globl start /* Entry point */
35 * Setup the segment registers for flat addressing and setup the stack.
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 */
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.
47 movw $main-EXEC+LOAD,%si /* Source */
48 movw $main,%di /* Destination */
49 movw $0x200-(main-start),%cx /* Byte count */
53 * Jump to the relocated code.
55 jmp main-LOAD+EXEC /* To relocated code */
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.
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? */
67 jg err_pt /* If 0x1..0x7f */
68 testw %si,%si /* Active already found? */
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? */
75 int $0x18 /* BIOS: Diskless boot */
77 * Ok, we've found a possible active partition. Check to see that the drive
78 * is a valid hard drive number.
80 main.3: cmpb $0x80,%dl /* Drive valid? */
82 movb NHRDRV,%dh /* Calculate the highest */
83 addb $0x80,%dh /* drive number available */
84 cmpb %dh,%dl /* Within range? */
86 main.4: movb (%si),%dl /* Load drive */
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.
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 cmpb $0xff,%dh /* Might we need to use LBA? */
97 cmpw $0xffff,%cx /* Do we need to use LBA? */
99 pushw %cx /* Save %cx */
100 pushw %bx /* Save %bx */
101 movw $0x55aa,%bx /* Magic */
102 movb $0x41,%ah /* BIOS: EDD extensions */
103 int $0x13 /* present? */
105 cmpw $0xaa55,%bx /* Magic ok? */
107 testb $0x1,%cl /* Packet mode present? */
109 popw %bx /* Restore %bx */
110 pushl $0x0 /* Set the LBA */
111 pushl 0x8(%si) /* address */
112 pushw %es /* Set the address of */
113 pushw %bx /* the transfer buffer */
114 pushw $0x1 /* Read 1 sector */
115 pushw $0x10 /* Packet length */
116 movw %sp,%si /* Packer pointer */
117 movw $0x4200,%ax /* BIOS: LBA Read from disk */
118 jmp main.8 /* Skip the CHS setup */
119 main.6: popw %bx /* Restore %bx */
120 popw %cx /* Restore %cx */
121 main.7: movw $0x201,%ax /* BIOS: Read from disk */
122 main.8: int $0x13 /* Call the BIOS */
123 movw %di,%sp /* Restore stack */
124 jc err_rd /* If error */
126 * Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it
127 * is present, execute the bootstrap we just loaded.
129 cmpw $MAGIC,0x1fe(%bx) /* Bootable? */
131 jmp *%bx /* Invoke bootstrap */
133 * Various error message entry points.
135 err_pt: movw $msg_pt,%si /* "Invalid partition */
136 jmp putstr /* table" */
138 err_rd: movw $msg_rd,%si /* "Error loading */
139 jmp putstr /* operating system" */
141 err_os: movw $msg_os,%si /* "Missing operating */
142 jmp putstr /* system" */
144 * Output an ASCIZ string to the console via the BIOS.
146 putstr.0: movw $0x7,%bx /* Page:attribute */
147 movb $0xe,%ah /* BIOS: Display */
148 int $0x10 /* character */
149 putstr: lodsb /* Get character */
150 testb %al,%al /* End of string? */
151 jnz putstr.0 /* No */
152 putstr.1: jmp putstr.1 /* Await reset */
154 msg_pt: .asciz "Invalid partition table"
155 msg_rd: .asciz "Error loading operating system"
156 msg_os: .asciz "Missing operating system"
160 partbl: .fill 0x10,0x4,0x0 /* Partition table */
161 .word MAGIC /* Magic number */