source: mainline/kernel/arch/ia32/src/boot/vesa_real.inc

Last change on this file was 36aec61e, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Verify fallback VESA mode before attempting to set it

The mode must be listed in the list of supported modes and it
must have the correct attributes (e.g., supported, having linear
frame buffer).

  • Property mode set to 100644
File size: 7.7 KB
Line 
1#ifdef CONFIG_FB
2
3#include <macros.h>
4
5#define VESA_INFO_SIZE 1024
6
7#define VESA_MODE_ATTRIBUTES_OFFSET 0
8#define VESA_MODE_LIST_PTR_OFFSET 14
9#define VESA_MODE_SCANLINE_OFFSET 16
10#define VESA_MODE_WIDTH_OFFSET 18
11#define VESA_MODE_HEIGHT_OFFSET 20
12#define VESA_MODE_BPP_OFFSET 25
13#define VESA_MODE_RED_MASK_OFFSET 31
14#define VESA_MODE_RED_POS_OFFSET 32
15#define VESA_MODE_GREEN_MASK_OFFSET 33
16#define VESA_MODE_GREEN_POS_OFFSET 34
17#define VESA_MODE_BLUE_MASK_OFFSET 35
18#define VESA_MODE_BLUE_POS_OFFSET 36
19#define VESA_MODE_PHADDR_OFFSET 40
20
21#define VESA_END_OF_MODES 0xffff
22
23#define VESA_OK 0x004f
24
25#define VESA_GET_INFO 0x4f00
26#define VESA_GET_MODE_INFO 0x4f01
27#define VESA_SET_MODE 0x4f02
28#define VESA_SET_PALETTE 0x4f09
29
30.code32
31vesa_init:
32 lidtl vesa_idtr
33
34 mov $GDT_SELECTOR(VESA_INIT_DATA_DES), %bx
35
36 mov %bx, %es
37 mov %bx, %fs
38 mov %bx, %gs
39 mov %bx, %ds
40 mov %bx, %ss
41
42 jmp $GDT_SELECTOR(VESA_INIT_CODE_DES), $vesa_init_real - vesa_init
43
44vesa_idtr:
45 .word 0x3ff
46 .long 0
47
48.code16
49vesa_init_real:
50 mov %cr0, %eax
51 and $~CR0_PE, %eax
52 mov %eax, %cr0
53
54 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
55
56vesa_init_real2:
57 mov $VESA_INIT_SEGMENT, %bx
58
59 mov %bx, %es
60 mov %bx, %fs
61 mov %bx, %gs
62 mov %bx, %ds
63 mov %bx, %ss
64
65 movl %esp, %eax
66 movl $0x0000fffc, %esp
67 movl $0x0000fffc, %ebp
68 pushl %eax
69
70 /* Parse default mode string */
71
72 mov $default_mode - vesa_init, %di
73 xor %eax, %eax
74 xor %ebx, %ebx
75
76 mov $8, %ecx
77 parse_width:
78 mov (%di), %al
79
80 /* Check for digit */
81
82 cmp $'0', %al
83 jb parse_width_done
84
85 cmp $'9', %al
86 ja parse_width_done
87
88 sub $'0', %al
89
90 /* Multiply default_width by 10 and add digit */
91
92 mov default_width - vesa_init, %bx
93 lea (%ebx, %ebx, 4), %ebx
94 shl $1, %ebx
95 add %ax, %bx
96 mov %bx, default_width - vesa_init
97
98 inc %di
99 loop parse_width
100 parse_width_done:
101
102 mov (%di), %al
103 cmp $0, %al
104 jz parse_done
105 inc %di
106
107 mov $8, %ecx
108 parse_height:
109 mov (%di), %al
110
111 /* Check for digit */
112
113 cmp $'0', %al
114 jb parse_height_done
115
116 cmp $'9', %al
117 ja parse_height_done
118
119 sub $'0', %al
120
121 /* Multiply default_height by 10 and add digit */
122
123 mov default_height - vesa_init, %bx
124 lea (%ebx, %ebx, 4), %ebx
125 shl $1, %ebx
126 add %ax, %bx
127 mov %bx, default_height - vesa_init
128
129 inc %di
130 loop parse_height
131 parse_height_done:
132
133 mov (%di), %al
134 cmp $0, %al
135 jz parse_done
136 inc %di
137
138 mov $4, %ecx
139 parse_bpp:
140 mov (%di), %al
141
142 /* Check for digit */
143
144 cmp $'0', %al
145 jb parse_bpp_done
146
147 cmp $'9', %al
148 ja parse_bpp_done
149
150 sub $'0', %al
151
152 /* Multiply default_bpp by 10 and add digit */
153
154 mov default_bpp - vesa_init, %bx
155 lea (%ebx, %ebx, 4), %ebx
156 shl $1, %ebx
157 add %ax, %bx
158 mov %bx, default_bpp - vesa_init
159
160 inc %di
161 loop parse_bpp
162 parse_bpp_done:
163
164 parse_done:
165
166 mov $VESA_GET_INFO, %ax
167 mov $e_vesa_init - vesa_init, %di
168 push %di
169 /* Write the "VBE2" signature into the info structure in order
170 * to get proper mode information. The presence of "VBE2"
171 * indicates two things:
172 *
173 * - VBE controller information structure is expected to be
174 * 512 bytes long instead of 256 bytes.
175 * - The BIOS should report VBE 3.0 information (potentially
176 * including non-standard modes in the mode list).
177 */
178 movl $0x32454256, (%di)
179 int $0x10
180
181 pop %di
182 cmp $VESA_OK, %ax
183 jnz no_mode
184
185 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
186 mov %si, %gs
187 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
188
189 add $VESA_INFO_SIZE, %di
190
191 next_mode:
192 /* Try next mode */
193
194 mov %gs:(%si), %cx
195 cmp $VESA_END_OF_MODES, %cx
196 je no_mode
197
198 inc %si
199 inc %si
200 push %cx
201 push %di
202 push %si
203 mov $VESA_GET_MODE_INFO, %ax
204 int $0x10
205
206 pop %si
207 pop %di
208 pop %cx
209 cmp $VESA_OK, %ax
210 jne no_mode
211
212 /*
213 * Check for proper attributes (supported,
214 * color, graphics, linear framebuffer).
215 */
216
217 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
218 and $0x99, %ax
219 cmp $0x99, %ax
220 jne next_mode
221
222 /* Check for proper resolution */
223
224 mov default_width - vesa_init, %ax
225 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
226 jne next_mode
227
228 mov default_height - vesa_init, %ax
229 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
230 jne next_mode
231
232 /* Check for proper bpp */
233
234 mov default_bpp - vesa_init, %al
235 cmp VESA_MODE_BPP_OFFSET(%di), %al
236 je set_mode
237
238 mov $24, %al
239 cmp default_bpp - vesa_init, %al
240 jne next_mode
241
242 /* For 24 bpp modes accept also 32 bit bpp */
243
244 mov $32, %al
245 cmp VESA_MODE_BPP_OFFSET(%di), %al
246 jne next_mode
247
248 set_mode:
249 mov %cx, %bx
250 or $0xc000, %bx
251 push %di
252 mov $VESA_SET_MODE, %ax
253 int $0x10
254
255 pop %di
256 cmp $VESA_OK, %ax
257 jnz no_mode
258
259 /* Set 3:2:3 VGA palette */
260
261 mov VESA_MODE_BPP_OFFSET(%di), %al
262 cmp $8, %al
263 jnz vga_not_set
264
265 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
266 push %di
267 mov $vga323 - vesa_init, %di
268 mov $0x100, %ecx
269
270 /* Test if VGA compatible registers are present */
271 bt $5, %ax
272 jnc vga_compat
273
274 /* Use VESA routine to set the palette */
275
276 mov $VESA_SET_PALETTE, %ax
277 xor %bl, %bl
278 xor %dx, %dx
279 int $0x10
280
281 cmp $0x00, %ah
282 je vga_not_compat
283
284 vga_compat:
285
286 /* Use VGA registers to set the palette */
287
288 movw $0x3c6, %dx /* set palette mask */
289 movb $0xff, %al
290 outb %al, %dx
291
292 movw $0x3c8, %dx /* first index to set */
293 xor %al, %al
294 outb %al, %dx
295
296 movw $0x3c9, %dx /* data port */
297
298 vga_loop:
299 movb %es:2(%di), %al
300 outb %al, %dx
301
302 movb %es:1(%di), %al
303 outb %al, %dx
304
305 movb %es:(%di), %al
306 outb %al, %dx
307
308 addw $4, %di
309 loop vga_loop
310
311 vga_not_compat:
312
313 pop %di
314
315 vga_not_set:
316
317 /*
318 * Store mode parameters:
319 * eax = bpp[16] scanline[16]
320 * ebx = width[16] height[16]
321 * edx = red_mask[8] red_pos[8] green_mask[8] green_pos[8]
322 * esi = blue_mask[8] blue_pos[8]
323 * edi = linear frame buffer
324 */
325
326 mov VESA_MODE_BPP_OFFSET(%di), %al
327 xor %ah, %ah
328 shl $16, %eax
329 mov VESA_MODE_SCANLINE_OFFSET(%di), %ax
330
331 mov VESA_MODE_WIDTH_OFFSET(%di), %bx
332 shl $16, %ebx
333 mov VESA_MODE_HEIGHT_OFFSET(%di), %bx
334
335 mov VESA_MODE_BLUE_MASK_OFFSET(%di), %dl
336 shl $8, %edx
337 mov VESA_MODE_BLUE_POS_OFFSET(%di), %dl
338 mov %edx, %esi
339
340 mov VESA_MODE_RED_MASK_OFFSET(%di), %dl
341 shl $8, %edx
342 mov VESA_MODE_RED_POS_OFFSET(%di), %dl
343
344 shl $8, %edx
345 mov VESA_MODE_GREEN_MASK_OFFSET(%di), %dl
346 shl $8, %edx
347 mov VESA_MODE_GREEN_POS_OFFSET(%di), %dl
348
349 mov VESA_MODE_PHADDR_OFFSET(%di), %edi
350
351 vesa_leave_real:
352
353 mov %cr0, %ecx
354 or $CR0_PE, %ecx
355 mov %ecx, %cr0
356
357 jmp vesa_leave_real2
358
359 vesa_leave_real2:
360
361 ljmpl $GDT_SELECTOR(KTEXT32_DES), $(vesa_init_protected - vesa_init + VESA_INIT_SEGMENT << 4)
362
363 no_mode:
364
365 /* No prefered mode found */
366 push %di
367 mov $e_vesa_init - vesa_init, %di
368 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
369 mov %si, %gs
370 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
371 pop %di
372
373 /* Check if list of supported modes contains fallback mode */
374 find_fallback_mode:
375
376 mov %gs:(%si), %cx
377
378 cmp $0x111, %cx
379 je fallback_mode_listed
380
381 cmp $VESA_END_OF_MODES, %cx
382 je text_mode
383
384 inc %si
385 inc %si
386 jmp find_fallback_mode /* 16-bit relative jump */
387
388 fallback_mode_listed:
389 /* Make sure fallback mode is really supported */
390 mov $0x111, %cx
391 push %di
392 push %cx
393 mov $VESA_GET_MODE_INFO, %ax
394 int $0x10
395
396 pop %cx
397 pop %di
398 cmp $VESA_OK, %ax
399 jnz text_mode
400
401 /* Verify mode attributes */
402 and $0x99, %ax
403 cmp $0x99, %ax
404 jne text_mode
405
406 jmp set_mode /* 16-bit relative jump */
407
408 text_mode:
409
410 /* Reset to EGA text mode (because of problems with VESA) */
411
412 mov $0x0003, %ax
413 int $0x10
414
415 xor %eax, %eax
416 xor %ebx, %ebx
417 xor %edx, %edx
418 xor %edi, %edi
419
420 jz vesa_leave_real /* force relative jump */
421
422vga323:
423#include "vga323.pal"
424
425default_width:
426 .word 0
427
428default_height:
429 .word 0
430
431default_bpp:
432 .byte 0
433
434default_mode:
435 .ascii STRING(CONFIG_BFB_MODE)
436 .ascii "-"
437 .asciz STRING(CONFIG_BFB_BPP)
438 .fill 24
439
440#include "vesa_ret.inc"
441
442.align 4
443e_vesa_init:
444#endif
Note: See TracBrowser for help on using the repository browser.