|
|
1.1 root 1: /******************************************************************************
2: * Copyright (c) 2004, 2008 IBM Corporation
3: * All rights reserved.
4: * This program and the accompanying materials
5: * are made available under the terms of the BSD License
6: * which accompanies this distribution, and is available at
7: * http://www.opensource.org/licenses/bsd-license.php
8: *
9: * Contributors:
10: * IBM Corporation - initial implementation
11: *****************************************************************************/
12:
13: #include <stdio.h>
14: #include <stdlib.h>
15: #include <string.h>
16:
17: #include <stdint.h>
18: #include <cpu.h>
19:
20: #include "debug.h"
21:
22: #include <x86emu/x86emu.h>
23: #include <x86emu/regs.h>
24: #include <x86emu/prim_ops.h> // for push_word
25:
26: #include "biosemu.h"
27: #include "io.h"
28: #include "mem.h"
29: #include "interrupt.h"
30: #include "device.h"
31:
32: static X86EMU_memFuncs my_mem_funcs = {
33: my_rdb, my_rdw, my_rdl,
34: my_wrb, my_wrw, my_wrl
35: };
36:
37: static X86EMU_pioFuncs my_pio_funcs = {
38: my_inb, my_inw, my_inl,
39: my_outb, my_outw, my_outl
40: };
41:
42: // pointer to VBEInfoBuffer, set by vbe_prepare
43: uint8_t *vbe_info_buffer = 0;
44: // virtual BIOS Memory
45: uint8_t *biosmem;
46: uint32_t biosmem_size;
47:
48: // these structs are for input from and output to OF
49: typedef struct {
50: uint8_t display_type; // 0=NONE, 1= analog, 2=digital
51: uint16_t screen_width;
52: uint16_t screen_height;
53: uint16_t screen_linebytes; // bytes per line in framebuffer, may be more than screen_width
54: uint8_t color_depth; // color depth in bpp
55: uint32_t framebuffer_address;
56: uint8_t edid_block_zero[128];
57: } __attribute__ ((__packed__)) screen_info_t;
58:
59: typedef struct {
60: uint8_t signature[4];
61: uint16_t size_reserved;
62: uint8_t monitor_number;
63: uint16_t max_screen_width;
64: uint8_t color_depth;
65: } __attribute__ ((__packed__)) screen_info_input_t;
66:
67: // these structs only store a subset of the VBE defined fields
68: // only those needed.
69: typedef struct {
70: char signature[4];
71: uint16_t version;
72: uint8_t *oem_string_ptr;
73: uint32_t capabilities;
74: uint16_t video_mode_list[256]; // lets hope we never have more than 256 video modes...
75: uint16_t total_memory;
76: } vbe_info_t;
77:
78: typedef struct {
79: uint16_t video_mode;
80: uint8_t mode_info_block[256];
81: uint16_t attributes;
82: uint16_t linebytes;
83: uint16_t x_resolution;
84: uint16_t y_resolution;
85: uint8_t x_charsize;
86: uint8_t y_charsize;
87: uint8_t bits_per_pixel;
88: uint8_t memory_model;
89: uint32_t framebuffer_address;
90: } vbe_mode_info_t;
91:
92: typedef struct {
93: uint8_t port_number; // i.e. monitor number
94: uint8_t edid_transfer_time;
95: uint8_t ddc_level;
96: uint8_t edid_block_zero[128];
97: } vbe_ddc_info_t;
98:
99: static inline uint8_t
100: vbe_prepare()
101: {
102: vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area
103: //clear buffer
104: memset(vbe_info_buffer, 0, 512);
105: //set VbeSignature to "VBE2" to indicate VBE 2.0+ request
106: vbe_info_buffer[0] = 'V';
107: vbe_info_buffer[0] = 'B';
108: vbe_info_buffer[0] = 'E';
109: vbe_info_buffer[0] = '2';
110: // ES:DI store pointer to buffer in virtual mem see vbe_info_buffer above...
111: M.x86.R_EDI = 0x0;
112: M.x86.R_ES = VBE_SEGMENT;
113:
114: return 0; // successfull init
115: }
116:
117: // VBE Function 00h
118: uint8_t
119: vbe_info(vbe_info_t * info)
120: {
121: vbe_prepare();
122: // call VBE function 00h (Info Function)
123: M.x86.R_EAX = 0x4f00;
124:
125: // enable trace
126: CHECK_DBG(DEBUG_TRACE_X86EMU) {
127: X86EMU_trace_on();
128: }
129: // run VESA Interrupt
130: runInt10();
131:
132: if (M.x86.R_AL != 0x4f) {
133: DEBUG_PRINTF_VBE("%s: VBE Info Function NOT supported! AL=%x\n",
134: __FUNCTION__, M.x86.R_AL);
135: return -1;
136: }
137:
138: if (M.x86.R_AH != 0x0) {
139: DEBUG_PRINTF_VBE
140: ("%s: VBE Info Function Return Code NOT OK! AH=%x\n",
141: __FUNCTION__, M.x86.R_AH);
142: return M.x86.R_AH;
143: }
144: //printf("VBE Info Dump:");
145: //dump(vbe_info_buffer, 64);
146:
147: //offset 0: signature
148: info->signature[0] = vbe_info_buffer[0];
149: info->signature[1] = vbe_info_buffer[1];
150: info->signature[2] = vbe_info_buffer[2];
151: info->signature[3] = vbe_info_buffer[3];
152:
153: // offset 4: 16bit le containing VbeVersion
154: info->version = in16le(vbe_info_buffer + 4);
155:
156: // offset 6: 32bit le containg segment:offset of OEM String in virtual Mem.
157: info->oem_string_ptr =
158: biosmem + ((in16le(vbe_info_buffer + 8) << 4) +
159: in16le(vbe_info_buffer + 6));
160:
161: // offset 10: 32bit le capabilities
162: info->capabilities = in32le(vbe_info_buffer + 10);
163:
164: // offset 14: 32 bit le containing segment:offset of supported video mode table
165: uint16_t *video_mode_ptr;
166: video_mode_ptr =
167: (uint16_t *) (biosmem +
168: ((in16le(vbe_info_buffer + 16) << 4) +
169: in16le(vbe_info_buffer + 14)));
170: uint32_t i = 0;
171: do {
172: info->video_mode_list[i] = in16le(video_mode_ptr + i);
173: i++;
174: }
175: while ((i <
176: (sizeof(info->video_mode_list) /
177: sizeof(info->video_mode_list[0])))
178: && (info->video_mode_list[i - 1] != 0xFFFF));
179:
180: //offset 18: 16bit le total memory in 64KB blocks
181: info->total_memory = in16le(vbe_info_buffer + 18);
182:
183: return 0;
184: }
185:
186: // VBE Function 01h
187: uint8_t
188: vbe_get_mode_info(vbe_mode_info_t * mode_info)
189: {
190: vbe_prepare();
191: // call VBE function 01h (Return VBE Mode Info Function)
192: M.x86.R_EAX = 0x4f01;
193: M.x86.R_CX = mode_info->video_mode;
194:
195: // enable trace
196: CHECK_DBG(DEBUG_TRACE_X86EMU) {
197: X86EMU_trace_on();
198: }
199: // run VESA Interrupt
200: runInt10();
201:
202: if (M.x86.R_AL != 0x4f) {
203: DEBUG_PRINTF_VBE
204: ("%s: VBE Return Mode Info Function NOT supported! AL=%x\n",
205: __FUNCTION__, M.x86.R_AL);
206: return -1;
207: }
208:
209: if (M.x86.R_AH != 0x0) {
210: DEBUG_PRINTF_VBE
211: ("%s: VBE Return Mode Info (mode: %04x) Function Return Code NOT OK! AH=%02x\n",
212: __FUNCTION__, mode_info->video_mode, M.x86.R_AH);
213: return M.x86.R_AH;
214: }
215: //pointer to mode_info_block is in ES:DI
216: memcpy(mode_info->mode_info_block,
217: biosmem + ((M.x86.R_ES << 4) + M.x86.R_DI),
218: sizeof(mode_info->mode_info_block));
219:
220: //printf("Mode Info Dump:");
221: //dump(mode_info_block, 64);
222:
223: // offset 0: 16bit le mode attributes
224: mode_info->attributes = in16le(mode_info->mode_info_block);
225:
226: // offset 16: 16bit le bytes per scan line
227: mode_info->linebytes = in16le(mode_info->mode_info_block + 16);
228:
229: // offset 18: 16bit le x resolution
230: mode_info->x_resolution = in16le(mode_info->mode_info_block + 18);
231:
232: // offset 20: 16bit le y resolution
233: mode_info->y_resolution = in16le(mode_info->mode_info_block + 20);
234:
235: // offset 22: 8bit le x charsize
236: mode_info->x_charsize = *(mode_info->mode_info_block + 22);
237:
238: // offset 23: 8bit le y charsize
239: mode_info->y_charsize = *(mode_info->mode_info_block + 23);
240:
241: // offset 25: 8bit le bits per pixel
242: mode_info->bits_per_pixel = *(mode_info->mode_info_block + 25);
243:
244: // offset 27: 8bit le memory model
245: mode_info->memory_model = *(mode_info->mode_info_block + 27);
246:
247: // offset 40: 32bit le containg offset of frame buffer memory ptr
248: mode_info->framebuffer_address =
249: in32le(mode_info->mode_info_block + 40);
250:
251: return 0;
252: }
253:
254: // VBE Function 02h
255: uint8_t
256: vbe_set_mode(vbe_mode_info_t * mode_info)
257: {
258: vbe_prepare();
259: // call VBE function 02h (Set VBE Mode Function)
260: M.x86.R_EAX = 0x4f02;
261: M.x86.R_BX = mode_info->video_mode;
262: M.x86.R_BX |= 0x4000; // set bit 14 to request linear framebuffer mode
263: M.x86.R_BX &= 0x7FFF; // clear bit 15 to request clearing of framebuffer
264:
265: DEBUG_PRINTF_VBE("%s: setting mode: 0x%04x\n", __FUNCTION__,
266: M.x86.R_BX);
267:
268: // enable trace
269: CHECK_DBG(DEBUG_TRACE_X86EMU) {
270: X86EMU_trace_on();
271: }
272: // run VESA Interrupt
273: runInt10();
274:
275: if (M.x86.R_AL != 0x4f) {
276: DEBUG_PRINTF_VBE
277: ("%s: VBE Set Mode Function NOT supported! AL=%x\n",
278: __FUNCTION__, M.x86.R_AL);
279: return -1;
280: }
281:
282: if (M.x86.R_AH != 0x0) {
283: DEBUG_PRINTF_VBE
284: ("%s: mode: %x VBE Set Mode Function Return Code NOT OK! AH=%x\n",
285: __FUNCTION__, mode_info->video_mode, M.x86.R_AH);
286: return M.x86.R_AH;
287: }
288: return 0;
289: }
290:
291: //VBE Function 08h
292: uint8_t
293: vbe_set_palette_format(uint8_t format)
294: {
295: vbe_prepare();
296: // call VBE function 09h (Set/Get Palette Data Function)
297: M.x86.R_EAX = 0x4f08;
298: M.x86.R_BL = 0x00; // set format
299: M.x86.R_BH = format;
300:
301: DEBUG_PRINTF_VBE("%s: setting palette format: %d\n", __FUNCTION__,
302: format);
303:
304: // enable trace
305: CHECK_DBG(DEBUG_TRACE_X86EMU) {
306: X86EMU_trace_on();
307: }
308: // run VESA Interrupt
309: runInt10();
310:
311: if (M.x86.R_AL != 0x4f) {
312: DEBUG_PRINTF_VBE
313: ("%s: VBE Set Palette Format Function NOT supported! AL=%x\n",
314: __FUNCTION__, M.x86.R_AL);
315: return -1;
316: }
317:
318: if (M.x86.R_AH != 0x0) {
319: DEBUG_PRINTF_VBE
320: ("%s: VBE Set Palette Format Function Return Code NOT OK! AH=%x\n",
321: __FUNCTION__, M.x86.R_AH);
322: return M.x86.R_AH;
323: }
324: return 0;
325: }
326:
327: // VBE Function 09h
328: uint8_t
329: vbe_set_color(uint16_t color_number, uint32_t color_value)
330: {
331: vbe_prepare();
332: // call VBE function 09h (Set/Get Palette Data Function)
333: M.x86.R_EAX = 0x4f09;
334: M.x86.R_BL = 0x00; // set color
335: M.x86.R_CX = 0x01; // set only one entry
336: M.x86.R_DX = color_number;
337: // ES:DI is address where color_value is stored, we store it at 2000:0000
338: M.x86.R_ES = 0x2000;
339: M.x86.R_DI = 0x0;
340:
341: // store color value at ES:DI
342: out32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, color_value);
343:
344: DEBUG_PRINTF_VBE("%s: setting color #%x: 0x%04x\n", __FUNCTION__,
345: color_number, color_value);
346:
347: // enable trace
348: CHECK_DBG(DEBUG_TRACE_X86EMU) {
349: X86EMU_trace_on();
350: }
351: // run VESA Interrupt
352: runInt10();
353:
354: if (M.x86.R_AL != 0x4f) {
355: DEBUG_PRINTF_VBE
356: ("%s: VBE Set Palette Function NOT supported! AL=%x\n",
357: __FUNCTION__, M.x86.R_AL);
358: return -1;
359: }
360:
361: if (M.x86.R_AH != 0x0) {
362: DEBUG_PRINTF_VBE
363: ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n",
364: __FUNCTION__, M.x86.R_AH);
365: return M.x86.R_AH;
366: }
367: return 0;
368: }
369:
370: uint8_t
371: vbe_get_color(uint16_t color_number, uint32_t * color_value)
372: {
373: vbe_prepare();
374: // call VBE function 09h (Set/Get Palette Data Function)
375: M.x86.R_EAX = 0x4f09;
376: M.x86.R_BL = 0x00; // get color
377: M.x86.R_CX = 0x01; // get only one entry
378: M.x86.R_DX = color_number;
379: // ES:DI is address where color_value is stored, we store it at 2000:0000
380: M.x86.R_ES = 0x2000;
381: M.x86.R_DI = 0x0;
382:
383: // enable trace
384: CHECK_DBG(DEBUG_TRACE_X86EMU) {
385: X86EMU_trace_on();
386: }
387: // run VESA Interrupt
388: runInt10();
389:
390: if (M.x86.R_AL != 0x4f) {
391: DEBUG_PRINTF_VBE
392: ("%s: VBE Set Palette Function NOT supported! AL=%x\n",
393: __FUNCTION__, M.x86.R_AL);
394: return -1;
395: }
396:
397: if (M.x86.R_AH != 0x0) {
398: DEBUG_PRINTF_VBE
399: ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n",
400: __FUNCTION__, M.x86.R_AH);
401: return M.x86.R_AH;
402: }
403: // read color value from ES:DI
404: *color_value = in32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI);
405:
406: DEBUG_PRINTF_VBE("%s: getting color #%x --> 0x%04x\n", __FUNCTION__,
407: color_number, *color_value);
408:
409: return 0;
410: }
411:
412: // VBE Function 15h
413: uint8_t
414: vbe_get_ddc_info(vbe_ddc_info_t * ddc_info)
415: {
416: vbe_prepare();
417: // call VBE function 15h (DDC Info Function)
418: M.x86.R_EAX = 0x4f15;
419: M.x86.R_BL = 0x00; // get DDC Info
420: M.x86.R_CX = ddc_info->port_number;
421: M.x86.R_ES = 0x0;
422: M.x86.R_DI = 0x0;
423:
424: // enable trace
425: CHECK_DBG(DEBUG_TRACE_X86EMU) {
426: X86EMU_trace_on();
427: }
428: // run VESA Interrupt
429: runInt10();
430:
431: if (M.x86.R_AL != 0x4f) {
432: DEBUG_PRINTF_VBE
433: ("%s: VBE Get DDC Info Function NOT supported! AL=%x\n",
434: __FUNCTION__, M.x86.R_AL);
435: return -1;
436: }
437:
438: if (M.x86.R_AH != 0x0) {
439: DEBUG_PRINTF_VBE
440: ("%s: port: %x VBE Get DDC Info Function Return Code NOT OK! AH=%x\n",
441: __FUNCTION__, ddc_info->port_number, M.x86.R_AH);
442: return M.x86.R_AH;
443: }
444: // BH = approx. time in seconds to transfer one EDID block
445: ddc_info->edid_transfer_time = M.x86.R_BH;
446: // BL = DDC Level
447: ddc_info->ddc_level = M.x86.R_BL;
448:
449: vbe_prepare();
450: // call VBE function 15h (DDC Info Function)
451: M.x86.R_EAX = 0x4f15;
452: M.x86.R_BL = 0x01; // read EDID
453: M.x86.R_CX = ddc_info->port_number;
454: M.x86.R_DX = 0x0; // block number
455: // ES:DI is address where EDID is stored, we store it at 2000:0000
456: M.x86.R_ES = 0x2000;
457: M.x86.R_DI = 0x0;
458:
459: // enable trace
460: CHECK_DBG(DEBUG_TRACE_X86EMU) {
461: X86EMU_trace_on();
462: }
463: // run VESA Interrupt
464: runInt10();
465:
466: if (M.x86.R_AL != 0x4f) {
467: DEBUG_PRINTF_VBE
468: ("%s: VBE Read EDID Function NOT supported! AL=%x\n",
469: __FUNCTION__, M.x86.R_AL);
470: return -1;
471: }
472:
473: if (M.x86.R_AH != 0x0) {
474: DEBUG_PRINTF_VBE
475: ("%s: port: %x VBE Read EDID Function Return Code NOT OK! AH=%x\n",
476: __FUNCTION__, ddc_info->port_number, M.x86.R_AH);
477: return M.x86.R_AH;
478: }
479:
480: memcpy(ddc_info->edid_block_zero,
481: biosmem + (M.x86.R_ES << 4) + M.x86.R_DI,
482: sizeof(ddc_info->edid_block_zero));
483:
484: return 0;
485: }
486:
487: uint32_t
488: vbe_get_info(uint8_t argc, char ** argv)
489: {
490: uint8_t rval;
1.1.1.2 ! root 491: static const uint8_t valid_edid_sig[] = {
! 492: 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
! 493: };
1.1 root 494: uint32_t i;
1.1.1.2 ! root 495:
1.1 root 496: if (argc < 4) {
497: printf
498: ("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n",
499: argv[0]);
500: int i = 0;
501: for (i = 0; i < argc; i++) {
502: printf("argv[%d]: %s\n", i, argv[i]);
503: }
504: return -1;
505: }
506: // get a copy of input struct...
507: screen_info_input_t input =
508: *((screen_info_input_t *) strtoul((char *) argv[4], 0, 16));
509: // output is pointer to the address passed as argv[4]
510: screen_info_t *output =
511: (screen_info_t *) strtoul((char *) argv[4], 0, 16);
512: // zero output
513: memset(output, 0, sizeof(screen_info_t));
514:
515: // argv[1] is address of virtual BIOS mem...
516: // argv[2] is the size
517: biosmem = (uint8_t *) strtoul(argv[1], 0, 16);
518: biosmem_size = strtoul(argv[2], 0, 16);;
519: if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
520: printf("Error: Not enough virtual memory: %x, required: %x!\n",
521: biosmem_size, MIN_REQUIRED_VMEM_SIZE);
522: return -1;
523: }
524: // argv[3] is the device to open and use...
525: if (dev_init((char *) argv[3]) != 0) {
526: printf("Error initializing device!\n");
527: return -1;
528: }
529: //setup interrupt handler
530: X86EMU_intrFuncs intrFuncs[256];
531: for (i = 0; i < 256; i++)
532: intrFuncs[i] = handleInterrupt;
533: X86EMU_setupIntrFuncs(intrFuncs);
534: X86EMU_setupPioFuncs(&my_pio_funcs);
535: X86EMU_setupMemFuncs(&my_mem_funcs);
536:
537: // set mem_base
538: M.mem_base = (long) biosmem;
539: M.mem_size = biosmem_size;
540: DEBUG_PRINTF_VBE("membase set: %08x, size: %08x\n", (int) M.mem_base,
541: (int) M.mem_size);
542:
543: vbe_info_t info;
544: rval = vbe_info(&info);
545: if (rval != 0)
546: return rval;
547:
548: DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature);
549: DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version);
550: DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr);
551: DEBUG_PRINTF_VBE("Capabilities:\n");
552: DEBUG_PRINTF_VBE("\tDAC: %s\n",
553: (info.capabilities & 0x1) ==
554: 0 ? "fixed 6bit" : "switchable 6/8bit");
555: DEBUG_PRINTF_VBE("\tVGA: %s\n",
556: (info.capabilities & 0x2) ==
557: 0 ? "compatible" : "not compatible");
558: DEBUG_PRINTF_VBE("\tRAMDAC: %s\n",
559: (info.capabilities & 0x4) ==
560: 0 ? "normal" : "use blank bit in Function 09h");
561:
562: // argv[4] may be a pointer with enough space to return screen_info_t
563: // as input, it must contain a screen_info_input_t with the following content:
564: // byte[0:3] = "DDC\0" (zero-terminated signature header)
565: // byte[4:5] = reserved space for the return struct... just in case we ever change
566: // the struct and dont have reserved enough memory (and let's hope the struct
567: // never gets larger than 64KB)
568: // byte[6] = monitor port number for DDC requests ("only" one byte... so lets hope we never have more than 255 monitors...
569: // byte[7:8] = max. screen width (OF may want to limit this)
570: // byte[9] = required color depth in bpp
571: if (strncmp((char *) input.signature, "DDC", 4) != 0) {
572: printf
573: ("%s: Invalid input signature! expected: %s, is: %s\n",
574: __FUNCTION__, "DDC", input.signature);
575: return -1;
576: }
577: if (input.size_reserved != sizeof(screen_info_t)) {
578: printf
579: ("%s: Size of return struct is wrong, required: %d, available: %d\n",
580: __FUNCTION__, (int) sizeof(screen_info_t),
581: input.size_reserved);
582: return -1;
583: }
584:
585: vbe_ddc_info_t ddc_info;
586: ddc_info.port_number = input.monitor_number;
587: vbe_get_ddc_info(&ddc_info);
588:
589: #if 0
590: DEBUG_PRINTF_VBE("DDC: edid_tranfer_time: %d\n",
591: ddc_info.edid_transfer_time);
592: DEBUG_PRINTF_VBE("DDC: ddc_level: %x\n", ddc_info.ddc_level);
593: DEBUG_PRINTF_VBE("DDC: EDID: \n");
594: CHECK_DBG(DEBUG_VBE) {
595: dump(ddc_info.edid_block_zero,
596: sizeof(ddc_info.edid_block_zero));
597: }
598: #endif
1.1.1.2 ! root 599: if (memcmp(ddc_info.edid_block_zero, valid_edid_sig, 8) != 0) {
1.1 root 600: // invalid EDID signature... probably no monitor
601: output->display_type = 0x0;
602: return 0;
603: } else if ((ddc_info.edid_block_zero[20] & 0x80) != 0) {
604: // digital display
605: output->display_type = 2;
606: } else {
607: // analog
608: output->display_type = 1;
609: }
610: DEBUG_PRINTF_VBE("DDC: found display type %d\n", output->display_type);
611: memcpy(output->edid_block_zero, ddc_info.edid_block_zero,
612: sizeof(ddc_info.edid_block_zero));
613: i = 0;
614: vbe_mode_info_t mode_info;
615: vbe_mode_info_t best_mode_info;
616: // initialize best_mode to 0
617: memset(&best_mode_info, 0, sizeof(best_mode_info));
618: while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) {
619: //DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode);
620: vbe_get_mode_info(&mode_info);
621: #if 0
622: DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n",
623: mode_info.video_mode,
624: (mode_info.attributes & 0x1) ==
625: 0 ? "not supported" : "supported");
626: DEBUG_PRINTF_VBE("\tTTY: %s\n",
627: (mode_info.attributes & 0x4) ==
628: 0 ? "no" : "yes");
629: DEBUG_PRINTF_VBE("\tMode: %s %s\n",
630: (mode_info.attributes & 0x8) ==
631: 0 ? "monochrome" : "color",
632: (mode_info.attributes & 0x10) ==
633: 0 ? "text" : "graphics");
634: DEBUG_PRINTF_VBE("\tVGA: %s\n",
635: (mode_info.attributes & 0x20) ==
636: 0 ? "compatible" : "not compatible");
637: DEBUG_PRINTF_VBE("\tWindowed Mode: %s\n",
638: (mode_info.attributes & 0x40) ==
639: 0 ? "yes" : "no");
640: DEBUG_PRINTF_VBE("\tFramebuffer: %s\n",
641: (mode_info.attributes & 0x80) ==
642: 0 ? "no" : "yes");
643: DEBUG_PRINTF_VBE("\tResolution: %dx%d\n",
644: mode_info.x_resolution,
645: mode_info.y_resolution);
646: DEBUG_PRINTF_VBE("\tChar Size: %dx%d\n",
647: mode_info.x_charsize, mode_info.y_charsize);
648: DEBUG_PRINTF_VBE("\tColor Depth: %dbpp\n",
649: mode_info.bits_per_pixel);
650: DEBUG_PRINTF_VBE("\tMemory Model: 0x%x\n",
651: mode_info.memory_model);
652: DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n",
653: mode_info.framebuffer_address);
654: #endif
655: if ((mode_info.bits_per_pixel == input.color_depth)
656: && (mode_info.x_resolution <= input.max_screen_width)
657: && ((mode_info.attributes & 0x80) != 0) // framebuffer mode
658: && ((mode_info.attributes & 0x10) != 0) // graphics
659: && ((mode_info.attributes & 0x8) != 0) // color
660: && (mode_info.x_resolution > best_mode_info.x_resolution)) // better than previous best_mode
661: {
662: // yiiiihaah... we found a new best mode
663: memcpy(&best_mode_info, &mode_info, sizeof(mode_info));
664: }
665: i++;
666: }
667:
668: if (best_mode_info.video_mode != 0) {
669: DEBUG_PRINTF_VBE
670: ("Best Video Mode found: 0x%x, %dx%d, %dbpp, framebuffer_address: 0x%x\n",
671: best_mode_info.video_mode,
672: best_mode_info.x_resolution,
673: best_mode_info.y_resolution,
674: best_mode_info.bits_per_pixel,
675: best_mode_info.framebuffer_address);
676:
677: //printf("Mode Info Dump:");
678: //dump(best_mode_info.mode_info_block, 64);
679:
680: // set the video mode
681: vbe_set_mode(&best_mode_info);
682:
683: if ((info.capabilities & 0x1) != 0) {
684: // switch to 8 bit palette format
685: vbe_set_palette_format(8);
686: }
687: // setup a palette:
688: // - first 216 colors are mixed colors for each component in 6 steps
689: // (6*6*6=216)
690: // - then 10 shades of the three primary colors
691: // - then 10 shades of grey
692: // -------
693: // = 256 colors
694: //
695: // - finally black is color 0 and white color FF (because SLOF expects it
696: // this way...)
697: // this resembles the palette that the kernel/X Server seems to expect...
698:
699: uint8_t mixed_color_values[6] =
700: { 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 };
701: uint8_t primary_color_values[10] =
702: { 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F,
703: 0x27
704: };
705: uint8_t mc_size = sizeof(mixed_color_values);
706: uint8_t prim_size = sizeof(primary_color_values);
707:
708: uint8_t curr_color_index;
709: uint32_t curr_color;
710:
711: uint8_t r, g, b;
712: // 216 mixed colors
713: for (r = 0; r < mc_size; r++) {
714: for (g = 0; g < mc_size; g++) {
715: for (b = 0; b < mc_size; b++) {
716: curr_color_index =
717: (r * mc_size * mc_size) +
718: (g * mc_size) + b;
719: curr_color = 0;
720: curr_color |= ((uint32_t) mixed_color_values[r]) << 16; //red value
721: curr_color |= ((uint32_t) mixed_color_values[g]) << 8; //green value
722: curr_color |= (uint32_t) mixed_color_values[b]; //blue value
723: vbe_set_color(curr_color_index,
724: curr_color);
725: }
726: }
727: }
728:
729: // 10 shades of each primary color
730: // red
731: for (r = 0; r < prim_size; r++) {
732: curr_color_index = mc_size * mc_size * mc_size + r;
733: curr_color = ((uint32_t) primary_color_values[r]) << 16;
734: vbe_set_color(curr_color_index, curr_color);
735: }
736: //green
737: for (g = 0; g < prim_size; g++) {
738: curr_color_index =
739: mc_size * mc_size * mc_size + prim_size + g;
740: curr_color = ((uint32_t) primary_color_values[g]) << 8;
741: vbe_set_color(curr_color_index, curr_color);
742: }
743: //blue
744: for (b = 0; b < prim_size; b++) {
745: curr_color_index =
746: mc_size * mc_size * mc_size + prim_size * 2 + b;
747: curr_color = (uint32_t) primary_color_values[b];
748: vbe_set_color(curr_color_index, curr_color);
749: }
750: // 10 shades of grey
751: for (i = 0; i < prim_size; i++) {
752: curr_color_index =
753: mc_size * mc_size * mc_size + prim_size * 3 + i;
754: curr_color = 0;
755: curr_color |= ((uint32_t) primary_color_values[i]) << 16; //red
756: curr_color |= ((uint32_t) primary_color_values[i]) << 8; //green
757: curr_color |= ((uint32_t) primary_color_values[i]); //blue
758: vbe_set_color(curr_color_index, curr_color);
759: }
760:
761: // SLOF is using color 0x0 (black) and 0xFF (white) to draw to the screen...
762: vbe_set_color(0x00, 0x00000000);
763: vbe_set_color(0xFF, 0x00FFFFFF);
764:
765: output->screen_width = best_mode_info.x_resolution;
766: output->screen_height = best_mode_info.y_resolution;
767: output->screen_linebytes = best_mode_info.linebytes;
768: output->color_depth = best_mode_info.bits_per_pixel;
769: output->framebuffer_address =
770: best_mode_info.framebuffer_address;
771: } else {
772: printf("%s: No suitable video mode found!\n", __FUNCTION__);
773: //unset display_type...
774: output->display_type = 0;
775: }
776: return 0;
777: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.