Improve error reporting for strange length combinations reported by
[people/xl0/gpxe-arm.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
24         /* Relocate self to EXEC_SEG */
25         pushw   $BOOT_SEG
26         popw    %ds
27         pushw   $EXEC_SEG
28         popw    %es
29         xorw    %si, %si
30         xorw    %di, %di
31         movw    $0x200, %cx
32         rep movsb
33         ljmp    $EXEC_SEG, $1f
34 1:      pushw   %ds
35         popw    %es
36         pushw   %cs
37         popw    %ds
38
39         /* Check for LBA extensions */
40         movb    $0x41, %ah
41         movw    $0x55aa, %bx
42         stc
43         int     $0x13
44         jc      1f
45         cmpw    $0xaa55, %bx
46         jne     1f
47         movw    $read_lba, read_sectors
48 1:      
49         /* Read and process root partition table */
50         xorb    %dh, %dh
51         movw    $0x0001, %cx
52         xorl    %esi, %esi
53         xorl    %edi, %edi
54         call    process_table
55
56         /* Print failure message */
57         movw    $10f, %si
58         jmp     boot_error
59 10:     .asciz  "Could not locate active partition\r\n"
60
61 /*
62  * Print failure message and boot next device
63  *
64  * Parameters:
65  *   %si        : Failure string
66  */
67 boot_error:
68         cld
69         movw    $0x0007, %bx
70         movb    $0x0e, %ah
71 1:      lodsb
72         testb   %al, %al
73         je      99f
74         int     $0x10
75         jmp     1b
76 99:     /* Boot next device */
77         int     $0x18
78
79 /*
80  * Process partition table
81  *
82  * Parameters:
83  *   %dl        : BIOS drive number
84  *   %dh        : Head
85  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
86  *   %ch        : Low eight bits of cylinder
87  *   %esi:%edi  : LBA address
88  *   %bp        : Active partition handler routine
89  *
90  * Returns:
91  *   CF set on error
92  */
93 process_table:
94         pushal
95         call    read_boot_sector
96         jc      99f
97         movw    $446, %bx
98 1:      call    process_partition
99         addw    $16, %bx
100         cmpw    $510, %bx
101         jne     1b
102 99:     popal
103         ret
104
105 /*
106  * Process partition
107  *
108  * Parameters:
109  *   %dl        : BIOS drive number
110  *   %dh        : Head
111  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
112  *   %ch        : Low eight bits of cylinder
113  *   %esi:%edi  : LBA address
114  *   %bx        : Offset within partition table
115  *   %bp        : Active partition handler routine
116  */
117 process_partition:
118         pushal
119         /* Load C/H/S values from partition entry */
120         movb    %es:1(%bx), %dh
121         movw    %es:2(%bx), %cx
122         /* Update LBA address from partition entry */
123         addl    %es:8(%bx), %edi
124         adcl    $0, %esi
125         /* Check active flag */
126         testb   $0x80, %es:(%bx)
127         jz      1f
128         call    read_boot_sector
129         jc      99f
130         jmp     *%bp
131 1:      /* Check for extended partition */
132         movb    %es:4(%bx), %al
133         cmpb    $0x05, %al
134         je      2f
135         cmpb    $0x0f, %al
136         je      2f
137         cmpb    $0x85, %al
138         jne     99f
139 2:      call    process_table
140 99:     popal
141         /* Reload original partition table */
142         call    read_boot_sector
143         ret
144
145 /*
146  * Read single sector to %es:0000 and verify 0x55aa signature
147  *
148  * Parameters:
149  *   %dl        : BIOS drive number
150  *   %dh        : Head
151  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
152  *   %ch        : Low eight bits of cylinder
153  *   %esi:%edi  : LBA address
154  *
155  * Returns:
156  *   CF set on error
157  */
158 read_boot_sector:
159         pushw   %ax
160         movw    $1, %ax
161         call    *read_sectors
162         jc      99f
163         cmpw    $0xaa55, %es:(510)
164         je      99f
165         stc     
166 99:     popw    %ax
167         ret
168         
169 /*
170  * Read sectors to %es:0000
171  *
172  * Parameters:
173  *   %dl        : BIOS drive number
174  *   %dh        : Head
175  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
176  *   %ch        : Low eight bits of cylinder
177  *   %esi:%edi  : LBA address
178  *   %ax        : Number of sectors (max 127)
179  *
180  * Returns:
181  *   CF set on error
182  */
183 read_sectors:   .word   read_chs
184
185 read_chs:
186         /* Read sectors using C/H/S address */
187         pushal
188         xorw    %bx, %bx
189         movb    $0x02, %ah
190         stc
191         int     $0x13
192         sti
193         popal
194         ret
195
196 read_lba:
197         /* Read sectors using LBA address */
198         pushal
199         movw    %ax, (lba_desc + 2)
200         pushw   %es
201         popw    (lba_desc + 6)
202         movl    %edi, (lba_desc + 8)
203         movl    %esi, (lba_desc + 12)
204         movw    $lba_desc, %si
205         movb    $0x42, %ah
206         int     $0x13
207         popal
208         ret
209
210 lba_desc:
211         .byte   0x10
212         .byte   0
213         .word   1
214         .word   0x0000
215         .word   0x0000
216         .long   0, 0