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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1558d85 was d242cb6, checked in by Martin Decky <martin@…>, 12 years ago

make sure we configure two distinct segment descriptors and set the read bit on the code segment before switching back to real-mode for VESA/VBE
this fixes execution on the latest (3.9.1) Linux KVM with real-mode x86 code emulation that is particularly picky about the code segment permission bits

  • Property mode set to 100644
File size: 7.3 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 0x4f
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 $~1, %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, %al
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, %al
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, %al
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 $1, %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
367 mov $0x111, %cx
368 push %di
369 push %cx
370 mov $VESA_GET_MODE_INFO, %ax
371 int $0x10
372
373 pop %cx
374 pop %di
375 cmp $VESA_OK, %al
376 jnz text_mode
377 jz set_mode /* force relative jump */
378
379 text_mode:
380
381 /* Reset to EGA text mode (because of problems with VESA) */
382
383 mov $0x0003, %ax
384 int $0x10
385
386 xor %eax, %eax
387 xor %ebx, %ebx
388 xor %edx, %edx
389 xor %edi, %edi
390
391 jz vesa_leave_real /* force relative jump */
392
393vga323:
394#include "vga323.pal"
395
396default_width:
397 .word 0
398
399default_height:
400 .word 0
401
402default_bpp:
403 .byte 0
404
405default_mode:
406 .ascii STRING(CONFIG_BFB_MODE)
407 .ascii "-"
408 .asciz STRING(CONFIG_BFB_BPP)
409 .fill 24
410
411#include "vesa_ret.inc"
412
413.align 4
414e_vesa_init:
415#endif
Note: See TracBrowser for help on using the repository browser.