Added master boot record capable of locating active partition
[people/sha0/gpxe.git] / src / arch / i386 / prefix / bootpart.S
1 #define BOOT_SEG        0x07c0
2 #define EXEC_SEG        0x0100
3 #define STACK_SEG       0x0200
4 #define STACK_SIZE      0x2000
5         
6         .text
7         .arch i386
8         .section ".prefix", "awx", @progbits
9         .code16
10
11 /*
12  * Find active partition
13  *
14  * Parameters:
15  *   %dl        : BIOS drive number
16  *   %bp        : Active partition handler routine
17  */
18 find_active_partition:
19         /* Set up stack at STACK_SEG:STACK_SIZE */
20         movw    $STACK_SEG, %ax
21         movw    %ax, %ss
22         movw    $STACK_SIZE, %sp
23         /* Relocate self to EXEC_SEG */
24         pushw   $BOOT_SEG
25         popw    %ds
26         pushw   $EXEC_SEG
27         popw    %es
28         xorw    %si, %si
29         xorw    %di, %di
30         movw    $0x200, %cx
31         rep movsb
32         ljmp    $EXEC_SEG, $1f
33 1:      pushw   %ds
34         popw    %es
35         pushw   %cs
36         popw    %ds
37         /* Read and process root partition table */
38         xorb    %dh, %dh
39         movw    $0x0001, %cx
40         xorl    %esi, %esi
41         xorl    %edi, %edi
42         call    process_table
43         /* Print failure message */
44         movw    $10f, %si
45         movw    $(20f-10f), %cx
46 1:      movw    $0x0007, %bx
47         movb    $0x0e, %ah
48         lodsb
49         int     $0x10
50         loop    1b
51         /* Boot next device */
52         int     $0x18
53 10:     .ascii  "Could not locate active partition\r\n"
54 20:     
55
56 /*
57  * Process partition table
58  *
59  * Parameters:
60  *   %dl        : BIOS drive number
61  *   %dh        : Head
62  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
63  *   %ch        : Low eight bits of cylinder
64  *   %esi:%edi  : LBA address
65  *   %bp        : Active partition handler routine
66  *
67  * Returns:
68  *   CF set on error
69  */
70 process_table:
71                                 xchgw   %bx,%bx
72         pushal
73         movw    $446, %bx
74 1:      call    read_sector
75         jc      99f
76         call    process_partition
77         addw    $16, %bx
78         cmpw    $510, %bx
79         jne     1b
80 99:     popal
81         ret
82
83 /*
84  * Process partition
85  *
86  * Parameters:
87  *   %dl        : BIOS drive number
88  *   %dh        : Head
89  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
90  *   %ch        : Low eight bits of cylinder
91  *   %esi:%edi  : LBA address
92  *   %bx        : Offset within partition table
93  *   %bp        : Active partition handler routine
94  */
95 process_partition:
96         pushal
97         /* Load C/H/S values from partition entry */
98         movb    %es:1(%bx), %dh
99         movw    %es:2(%bx), %cx
100         /* Update LBA address from partition entry */
101         addl    %es:8(%bx), %edi
102         adcl    $0, %esi
103         /* Check active flag */
104         testb   $0x80, %es:(%bx)
105         jz      1f
106         call    read_sector
107         jc      99f
108         jmp     *%bp
109 1:      /* Check for extended partition */
110         movb    %es:4(%bx), %al
111         cmpb    $0x05, %al
112         je      2f
113         cmpb    $0x0f, %al
114         je      2f
115         cmpb    $0x85, %al
116         jne     99f
117 2:      call    process_table
118 99:     popal
119         ret
120
121 /*
122  * Read single sector to 0000:7c00 and verify 0x55aa signature
123  *
124  * Parameters:
125  *   %dl        : BIOS drive number
126  *   %dh        : Head
127  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
128  *   %ch        : Low eight bits of cylinder
129  *   %esi:%edi  : LBA address
130  *
131  * Returns:
132  *   CF set on error
133  */
134 read_sector:
135         pushal
136         /* Check for LBA extensions */
137         call    check_lba
138         jnc     read_lba
139 read_chs:
140         /* Read sector using C/H/S address */
141         movw    $0x0201, %ax
142         xorw    %bx, %bx
143         stc
144         int     $0x13
145         sti
146         jmp     99f
147 read_lba:
148         /* Read sector using LBA address */
149         movb    $0x42, %ah
150         movl    %esi, (lba_desc + 12)
151         movl    %edi, (lba_desc + 8)
152         movw    $lba_desc, %si
153         int     $0x13
154 99:     /* Check for 55aa signature */
155         jc      99f
156         cmpw    $0xaa55, %es:(510)
157         je      99f
158         stc
159 99:     popal
160         ret
161
162 lba_desc:
163         .byte   0x10
164         .byte   0
165         .word   1
166         .word   0x0000
167         .word   0x07c0
168         .long   0, 0
169
170 /*
171  * Check for LBA extensions
172  *      
173  * Parameters:
174  *   %dl        : BIOS drive number
175  *
176  * Returns:
177  *   CF clear if LBA extensions supported
178  */
179 check_lba:
180         pushal
181         movb    $0x41, %ah
182         movw    $0x55aa, %bx
183         stc
184         int     $0x13
185         jc      99f
186         cmpw    $0xaa55, %bx
187         je      99f
188         stc
189 99:     popal
190         ret