source: bootcd/isolinux/syslinux-6.03/mbr/mbr.S

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/* -----------------------------------------------------------------------
2 *
3 *   Copyright 2007-2009 H. Peter Anvin - All Rights Reserved
4 *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
5 *
6 *   Permission is hereby granted, free of charge, to any person
7 *   obtaining a copy of this software and associated documentation
8 *   files (the "Software"), to deal in the Software without
9 *   restriction, including without limitation the rights to use,
10 *   copy, modify, merge, publish, distribute, sublicense, and/or
11 *   sell copies of the Software, and to permit persons to whom
12 *   the Software is furnished to do so, subject to the following
13 *   conditions:
14 *
15 *   The above copyright notice and this permission notice shall
16 *   be included in all copies or substantial portions of the Software.
17 *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 *   OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * ----------------------------------------------------------------------- */
28
29#include "adjust.h"
30
31        .code16
32        .text
33
34        .globl  bootsec
35stack           = 0x7c00
36driveno         = (stack-6)
37sectors         = (stack-8)
38secpercyl       = (stack-12)
39
40BIOS_kbdflags   = 0x417
41BIOS_page       = 0x462
42
43        /* gas/ld has issues with doing this as absolute addresses... */
44        .section ".bootsec", "a", @nobits
45        .globl  bootsec
46bootsec:
47        .space  512
48
49        .text
50        .globl  _start
51_start:
52        .byte   0x33, 0xc0      /* xorw %ax, %ax */
53        cli
54        movw    %ax, %ds
55        movw    %ax, %ss
56        movw    $stack, %sp
57        movw    %sp, %si
58        pushw   %es             /* es:di -> $PnP header */
59        pushw   %di
60        movw    %ax, %es
61        sti
62        cld
63
64        /* Copy down to 0:0x600 */
65        movw    $_start, %di
66        movw    $(512/2), %cx
67        rep; movsw
68
69        ljmpw   $0, $next
70next:
71
72        ADJUST_DRIVE
73        pushw   %dx             /* dl -> drive number */
74
75        /* Check to see if we have EBIOS */
76        pushw   %dx             /* drive number */
77        movb    $0x41, %ah      /* %al == 0 already */
78        movw    $0x55aa, %bx
79        xorw    %cx, %cx
80        xorb    %dh, %dh
81        stc
82        int     $0x13
83        jc      1f
84        cmpw    $0xaa55, %bx
85        jne     1f
86        shrw    %cx             /* Bit 0 = fixed disk subset */
87        jnc     1f
88
89        /* We have EBIOS; patch in the following code at
90           read_sector_cbios: movb $0x42, %ah ;  jmp read_common */
91        movl    $0xeb42b4+((read_common-read_sector_cbios-4) << 24), \
92                (read_sector_cbios)
93
941:
95        popw    %dx
96
97        /* Get (C)HS geometry */
98        movb    $0x08, %ah
99        int     $0x13
100        andw    $0x3f, %cx      /* Sector count */
101        pushw   %cx             /* Save sectors on the stack */
102        movzbw  %dh, %ax        /* dh = max head */
103        incw    %ax             /* From 0-based max to count */
104        mulw    %cx             /* Heads*sectors -> sectors per cylinder */
105
106        /* Save sectors/cylinder on the stack */
107        pushw   %dx             /* High word */
108        pushw   %ax             /* Low word */
109
110        xorl    %eax, %eax      /* Base */
111        cdq                     /* Root (%edx <- 0) */
112        call    scan_partition_table
113
114        /* If we get here, we have no OS */
115missing_os:
116        call    error
117        .ascii  "Missing operating system.\r\n"
118
119/*
120 * read_sector: read a single sector pointed to by %eax to 0x7c00.
121 * CF is set on error.  All registers saved.
122 */
123read_sector:
124        pushal
125        xorl    %edx, %edx
126        movw    $bootsec, %bx
127        pushl   %edx    /* MSW of LBA */
128        pushl   %eax    /* LSW of LBA */
129        pushw   %es     /* Buffer segment */
130        pushw   %bx     /* Buffer offset */
131        pushw   $1      /* Sector count */
132        pushw   $16     /* Size of packet */
133        movw    %sp, %si
134
135        /* This chunk is skipped if we have ebios */
136        /* Do not clobber %eax before this chunk! */
137        /* This also relies on %bx and %edx as set up above. */
138read_sector_cbios:
139        divl    (secpercyl)
140        shlb    $6, %ah
141        movb    %ah, %cl
142        movb    %al, %ch
143        xchgw   %dx, %ax
144        divb    (sectors)
145        movb    %al, %dh
146        orb     %ah, %cl
147        incw    %cx     /* Sectors are 1-based */
148        movw    $0x0201, %ax
149
150read_common:
151        movb    (driveno), %dl
152        int     $0x13
153        leaw    16(%si), %sp    /* Drop DAPA */
154        popal
155        ret
156
157/*
158 * read_partition_table:
159 *      Read a partition table (pointed to by %eax), and copy
160 *      the partition table into the ptab buffer.
161 *
162 *      Clobbers %si, %di, and %cx, other registers preserved.
163 *      %cx = 0 on exit.
164 *
165 *      On error, CF is set and ptab is overwritten with junk.
166 */
167ptab    = _start+446
168
169read_partition_table:
170        call    read_sector
171        movw    $bootsec+446, %si
172        movw    $ptab, %di
173        movw    $(16*4/2), %cx
174        rep ; movsw
175        ret
176
177/*
178 * scan_partition_table:
179 *      Scan a partition table currently loaded in the partition table
180 *      area.  Preserve all registers.
181 *
182 *      On entry:
183 *        %eax - base (location of this partition table)
184 *        %edx - root (offset from MBR, or 0 for MBR)
185 *
186 *      These get pushed into stack slots:
187 *        28(%bp) - %eax - base
188 *        20(%bp) - %edx - root
189 */
190
191scan_partition_table:
192        pushal
193        movw    %sp, %bp
194
195        /* Search for active partitions */
196        movw    $ptab, %bx
197        movw    $4, %cx
198        xorw    %ax, %ax
199        push    %bx
200        push    %cx
2015:
202        testb   $0x80, (%bx)
203        jz      6f
204        incw    %ax
205        movw    %bx, %si
2066:
207        addw    $16, %bx
208        loopw   5b
209
210        decw    %ax             /* Number of active partitions found */
211        jz      boot
212        jns     too_many_active
213
214        /* No active partitions found, look for extended partitions */
215        popw    %cx             /* %cx <- 4    */
216        popw    %bx             /* %bx <- ptab */
2177:
218        movb    4(%bx), %al
219        cmpb    $0x0f, %al      /* 0x0f = Win9x extended */
220        je      8f
221        andb    $~0x80, %al     /* 0x85 = Linux extended */
222        cmpb    $0x05, %al      /* 0x05 = MS-DOS extended */
223        jne     9f
224
225        /* It is an extended partition.  Read the extended partition and
226           try to scan it.  If the scan returns, re-load the current
227           partition table and resume scan. */
2288:
229        movl    8(%bx), %eax            /* Partition table offset */
230        movl    20(%bp), %edx           /* "Root" */
231        addl    %edx, %eax              /* Compute location of new ptab */
232        andl    %edx, %edx              /* Is this the MBR? */
233        jnz     10f
234        movl    %eax, %edx              /* Offset -> root if this was MBR */
23510:
236        call    read_partition_table
237        jc      11f
238        call    scan_partition_table
23911:
240        /* This returned, so we need to reload the current partition table */
241        movl    28(%bp), %eax           /* "Base" */
242        call    read_partition_table
243
244        /* fall through */
2459:
246        /* Not an extended partition */
247        addw    $16, %bx
248        loopw   7b
249
250        /* Nothing found, return */
251        popal
252        ret
253
254too_many_active:
255        call    error
256        .ascii  "Multiple active partitions.\r\n"
257
258/*
259 * boot: invoke the actual bootstrap. (%si) points to the partition
260 *       table entry, and 28(%bp) has the partition table base.
261 */
262boot:
263        movl    8(%si), %eax
264        addl    28(%bp), %eax
265        movl    %eax, 8(%si)    /* Adjust in-memory partition table entry */
266        call    read_sector
267        jc      disk_error
268
269        /* Check if the read sector is a XFS superblock */
270        cmpl    $0x42534658, (bootsec) /* "XFSB" */
271        jne     no_xfs
272
273        /* We put the Syslinux boot sector at offset 0x800 (4 sectors), so we
274         * need to adjust %eax (%eax + 4) to read the right sector into 0x7C00.
275         */
276        addl    $0x800 >> 0x09, %eax /* plus 4 sectors */
277        call    read_sector
278        jc      disk_error
279
280no_xfs:
281        cmpw    $0xaa55, (bootsec+510)
282        jne     missing_os              /* Not a valid boot sector */
283        movw    $driveno, %sp   /* driveno == bootsec-6 */
284        popw    %dx             /* dl -> drive number */
285        popw    %di             /* es:di -> $PnP vector */
286        popw    %es
287        cli
288        jmpw    *%sp            /* %sp == bootsec */
289
290disk_error:
291        call    error
292        .ascii  "Operating system load error.\r\n"
293
294/*
295 * Print error messages.  This is invoked with "call", with the
296 * error message at the return address.
297 */
298error:
299        popw    %si
3002:
301        lodsb
302        movb    $0x0e, %ah
303        movb    (BIOS_page), %bh
304        movb    $0x07, %bl
305        int     $0x10           /* May destroy %bp */
306        cmpb    $10, %al        /* Newline? */
307        jne     2b
308
309        int     $0x18           /* Boot failure */
310die:
311        hlt
312        jmp     die
Note: See TracBrowser for help on using the repository browser.