Miscellaneous efficiency improvements, and extend read_sectors to
[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_sector
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         movw    $(20f-10f), %cx
59 1:      movw    $0x0007, %bx
60         movb    $0x0e, %ah
61         lodsb
62         int     $0x10
63         loop    1b
64
65         /* Boot next device */
66         int     $0x18
67 10:     .ascii  "Could not locate active partition\r\n"
68 20:     
69
70 /*
71  * Process partition table
72  *
73  * Parameters:
74  *   %dl        : BIOS drive number
75  *   %dh        : Head
76  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
77  *   %ch        : Low eight bits of cylinder
78  *   %esi:%edi  : LBA address
79  *   %bp        : Active partition handler routine
80  *
81  * Returns:
82  *   CF set on error
83  */
84 process_table:
85         pushal
86         call    read_boot_sector
87         jc      99f
88         movw    $446, %bx
89 1:      call    process_partition
90         addw    $16, %bx
91         cmpw    $510, %bx
92         jne     1b
93 99:     popal
94         ret
95
96 /*
97  * Process partition
98  *
99  * Parameters:
100  *   %dl        : BIOS drive number
101  *   %dh        : Head
102  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
103  *   %ch        : Low eight bits of cylinder
104  *   %esi:%edi  : LBA address
105  *   %bx        : Offset within partition table
106  *   %bp        : Active partition handler routine
107  */
108 process_partition:
109         pushal
110         /* Load C/H/S values from partition entry */
111         movb    %es:1(%bx), %dh
112         movw    %es:2(%bx), %cx
113         /* Update LBA address from partition entry */
114         addl    %es:8(%bx), %edi
115         adcl    $0, %esi
116         /* Check active flag */
117         testb   $0x80, %es:(%bx)
118         jz      1f
119         call    read_boot_sector
120         jc      99f
121         jmp     *%bp
122 1:      /* Check for extended partition */
123         movb    %es:4(%bx), %al
124         cmpb    $0x05, %al
125         je      2f
126         cmpb    $0x0f, %al
127         je      2f
128         cmpb    $0x85, %al
129         jne     99f
130 2:      call    process_table
131 99:     popal
132         /* Reload original partition table */
133         call    read_boot_sector
134         ret
135
136 /*
137  * Read single sector to %es:0000 and verify 0x55aa signature
138  *
139  * Parameters:
140  *   %dl        : BIOS drive number
141  *   %dh        : Head
142  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
143  *   %ch        : Low eight bits of cylinder
144  *   %esi:%edi  : LBA address
145  *
146  * Returns:
147  *   CF set on error
148  */
149 read_boot_sector:
150         pushw   %ax
151         movw    $1, %ax
152         call    *read_sector
153         jc      99f
154         cmpw    $0xaa55, %es:(510)
155         je      99f
156         stc     
157 99:     popw    %ax
158         ret
159         
160 /*
161  * Read single sector to %es:0000 and verify 0x55aa signature
162  *
163  * Parameters:
164  *   %dl        : BIOS drive number
165  *   %dh        : Head
166  *   %cl        : Sector (bits 0-5), high two bits of cylinder (bits 6-7)
167  *   %ch        : Low eight bits of cylinder
168  *   %esi:%edi  : LBA address
169  *   %ax        : Number of sectors (max 127)
170  *
171  * Returns:
172  *   CF set on error
173  */
174 read_sector:    .word   read_chs
175
176 read_chs:
177         /* Read sectors using C/H/S address */
178         pushal
179         xorw    %bx, %bx
180         movb    $0x02, %ah
181         stc
182         int     $0x13
183         sti
184         popal
185         ret
186
187 read_lba:
188         /* Read sectors using LBA address */
189         pushal
190         movw    %ax, (lba_desc + 2)
191         pushw   %es
192         popw    (lba_desc + 6)
193         movl    %edi, (lba_desc + 8)
194         movl    %esi, (lba_desc + 12)
195         movw    $lba_desc, %si
196         movb    $0x42, %ah
197         int     $0x13
198         popal
199         ret
200
201 lba_desc:
202         .byte   0x10
203         .byte   0
204         .word   1
205         .word   0x0000
206         .word   0x0000
207         .long   0, 0