diff options
Diffstat (limited to 'util/x86emu/yabel/vbe.c')
-rw-r--r-- | util/x86emu/yabel/vbe.c | 779 |
1 files changed, 779 insertions, 0 deletions
diff --git a/util/x86emu/yabel/vbe.c b/util/x86emu/yabel/vbe.c new file mode 100644 index 0000000000..a2c9f82655 --- /dev/null +++ b/util/x86emu/yabel/vbe.c @@ -0,0 +1,779 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * Copyright (c) 2009 Pattrick Hueper <phueper@hueper.net> + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <string.h> +#include <types.h> +#ifndef CONFIG_COREBOOT_V2 +#include <cpu.h> +#endif + +#include "debug.h" + +#include <x86emu/x86emu.h> +#include <x86emu/regs.h> +#ifdef CONFIG_COREBOOT_V2 +#include "../x86emu/prim_ops.h" +#else +#include <x86emu/prim_ops.h> // for push_word +#endif + +#include "biosemu.h" +#include "io.h" +#include "mem.h" +#include "interrupt.h" +#include "device.h" + +static X86EMU_memFuncs my_mem_funcs = { + my_rdb, my_rdw, my_rdl, + my_wrb, my_wrw, my_wrl +}; + +static X86EMU_pioFuncs my_pio_funcs = { + my_inb, my_inw, my_inl, + my_outb, my_outw, my_outl +}; + +// pointer to VBEInfoBuffer, set by vbe_prepare +u8 *vbe_info_buffer = 0; +// virtual BIOS Memory +u8 *biosmem; +u32 biosmem_size; + +// these structs are for input from and output to OF +typedef struct { + u8 display_type; // 0=NONE, 1= analog, 2=digital + u16 screen_width; + u16 screen_height; + u16 screen_linebytes; // bytes per line in framebuffer, may be more than screen_width + u8 color_depth; // color depth in bpp + u32 framebuffer_address; + u8 edid_block_zero[128]; +} __attribute__ ((__packed__)) screen_info_t; + +typedef struct { + u8 signature[4]; + u16 size_reserved; + u8 monitor_number; + u16 max_screen_width; + u8 color_depth; +} __attribute__ ((__packed__)) screen_info_input_t; + +// these structs only store a subset of the VBE defined fields +// only those needed. +typedef struct { + char signature[4]; + u16 version; + u8 *oem_string_ptr; + u32 capabilities; + u16 video_mode_list[256]; // lets hope we never have more than 256 video modes... + u16 total_memory; +} vbe_info_t; + +typedef struct { + u16 video_mode; + u8 mode_info_block[256]; + u16 attributes; + u16 linebytes; + u16 x_resolution; + u16 y_resolution; + u8 x_charsize; + u8 y_charsize; + u8 bits_per_pixel; + u8 memory_model; + u32 framebuffer_address; +} vbe_mode_info_t; + +typedef struct { + u8 port_number; // i.e. monitor number + u8 edid_transfer_time; + u8 ddc_level; + u8 edid_block_zero[128]; +} vbe_ddc_info_t; + +static inline u8 +vbe_prepare() +{ + vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area + //clear buffer + memset(vbe_info_buffer, 0, 512); + //set VbeSignature to "VBE2" to indicate VBE 2.0+ request + vbe_info_buffer[0] = 'V'; + vbe_info_buffer[0] = 'B'; + vbe_info_buffer[0] = 'E'; + vbe_info_buffer[0] = '2'; + // ES:DI store pointer to buffer in virtual mem see vbe_info_buffer above... + M.x86.R_EDI = 0x0; + M.x86.R_ES = VBE_SEGMENT; + + return 0; // successfull init +} + +// VBE Function 00h +u8 +vbe_info(vbe_info_t * info) +{ + vbe_prepare(); + // call VBE function 00h (Info Function) + M.x86.R_EAX = 0x4f00; + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE("%s: VBE Info Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: VBE Info Function Return Code NOT OK! AH=%x\n", + __func__, M.x86.R_AH); + return M.x86.R_AH; + } + //printf("VBE Info Dump:"); + //dump(vbe_info_buffer, 64); + + //offset 0: signature + info->signature[0] = vbe_info_buffer[0]; + info->signature[1] = vbe_info_buffer[1]; + info->signature[2] = vbe_info_buffer[2]; + info->signature[3] = vbe_info_buffer[3]; + + // offset 4: 16bit le containing VbeVersion + info->version = in16le(vbe_info_buffer + 4); + + // offset 6: 32bit le containg segment:offset of OEM String in virtual Mem. + info->oem_string_ptr = + biosmem + ((in16le(vbe_info_buffer + 8) << 4) + + in16le(vbe_info_buffer + 6)); + + // offset 10: 32bit le capabilities + info->capabilities = in32le(vbe_info_buffer + 10); + + // offset 14: 32 bit le containing segment:offset of supported video mode table + u16 *video_mode_ptr; + video_mode_ptr = + (u16 *) (biosmem + + ((in16le(vbe_info_buffer + 16) << 4) + + in16le(vbe_info_buffer + 14))); + u32 i = 0; + do { + info->video_mode_list[i] = in16le(video_mode_ptr + i); + i++; + } + while ((i < + (sizeof(info->video_mode_list) / + sizeof(info->video_mode_list[0]))) + && (info->video_mode_list[i - 1] != 0xFFFF)); + + //offset 18: 16bit le total memory in 64KB blocks + info->total_memory = in16le(vbe_info_buffer + 18); + + return 0; +} + +// VBE Function 01h +u8 +vbe_get_mode_info(vbe_mode_info_t * mode_info) +{ + vbe_prepare(); + // call VBE function 01h (Return VBE Mode Info Function) + M.x86.R_EAX = 0x4f01; + M.x86.R_CX = mode_info->video_mode; + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Return Mode Info Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: VBE Return Mode Info (mode: %04x) Function Return Code NOT OK! AH=%02x\n", + __func__, mode_info->video_mode, M.x86.R_AH); + return M.x86.R_AH; + } + //pointer to mode_info_block is in ES:DI + memcpy(mode_info->mode_info_block, + biosmem + ((M.x86.R_ES << 4) + M.x86.R_DI), + sizeof(mode_info->mode_info_block)); + + //printf("Mode Info Dump:"); + //dump(mode_info_block, 64); + + // offset 0: 16bit le mode attributes + mode_info->attributes = in16le(mode_info->mode_info_block); + + // offset 16: 16bit le bytes per scan line + mode_info->linebytes = in16le(mode_info->mode_info_block + 16); + + // offset 18: 16bit le x resolution + mode_info->x_resolution = in16le(mode_info->mode_info_block + 18); + + // offset 20: 16bit le y resolution + mode_info->y_resolution = in16le(mode_info->mode_info_block + 20); + + // offset 22: 8bit le x charsize + mode_info->x_charsize = *(mode_info->mode_info_block + 22); + + // offset 23: 8bit le y charsize + mode_info->y_charsize = *(mode_info->mode_info_block + 23); + + // offset 25: 8bit le bits per pixel + mode_info->bits_per_pixel = *(mode_info->mode_info_block + 25); + + // offset 27: 8bit le memory model + mode_info->memory_model = *(mode_info->mode_info_block + 27); + + // offset 40: 32bit le containg offset of frame buffer memory ptr + mode_info->framebuffer_address = + in32le(mode_info->mode_info_block + 40); + + return 0; +} + +// VBE Function 02h +u8 +vbe_set_mode(vbe_mode_info_t * mode_info) +{ + vbe_prepare(); + // call VBE function 02h (Set VBE Mode Function) + M.x86.R_EAX = 0x4f02; + M.x86.R_BX = mode_info->video_mode; + M.x86.R_BX |= 0x4000; // set bit 14 to request linear framebuffer mode + M.x86.R_BX &= 0x7FFF; // clear bit 15 to request clearing of framebuffer + + DEBUG_PRINTF_VBE("%s: setting mode: 0x%04x\n", __func__, + M.x86.R_BX); + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Mode Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: mode: %x VBE Set Mode Function Return Code NOT OK! AH=%x\n", + __func__, mode_info->video_mode, M.x86.R_AH); + return M.x86.R_AH; + } + return 0; +} + +//VBE Function 08h +u8 +vbe_set_palette_format(u8 format) +{ + vbe_prepare(); + // call VBE function 09h (Set/Get Palette Data Function) + M.x86.R_EAX = 0x4f08; + M.x86.R_BL = 0x00; // set format + M.x86.R_BH = format; + + DEBUG_PRINTF_VBE("%s: setting palette format: %d\n", __func__, + format); + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Palette Format Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Palette Format Function Return Code NOT OK! AH=%x\n", + __func__, M.x86.R_AH); + return M.x86.R_AH; + } + return 0; +} + +// VBE Function 09h +u8 +vbe_set_color(u16 color_number, u32 color_value) +{ + vbe_prepare(); + // call VBE function 09h (Set/Get Palette Data Function) + M.x86.R_EAX = 0x4f09; + M.x86.R_BL = 0x00; // set color + M.x86.R_CX = 0x01; // set only one entry + M.x86.R_DX = color_number; + // ES:DI is address where color_value is stored, we store it at 2000:0000 + M.x86.R_ES = 0x2000; + M.x86.R_DI = 0x0; + + // store color value at ES:DI + out32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, color_value); + + DEBUG_PRINTF_VBE("%s: setting color #%x: 0x%04x\n", __func__, + color_number, color_value); + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Palette Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n", + __func__, M.x86.R_AH); + return M.x86.R_AH; + } + return 0; +} + +u8 +vbe_get_color(u16 color_number, u32 * color_value) +{ + vbe_prepare(); + // call VBE function 09h (Set/Get Palette Data Function) + M.x86.R_EAX = 0x4f09; + M.x86.R_BL = 0x00; // get color + M.x86.R_CX = 0x01; // get only one entry + M.x86.R_DX = color_number; + // ES:DI is address where color_value is stored, we store it at 2000:0000 + M.x86.R_ES = 0x2000; + M.x86.R_DI = 0x0; + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Palette Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n", + __func__, M.x86.R_AH); + return M.x86.R_AH; + } + // read color value from ES:DI + *color_value = in32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI); + + DEBUG_PRINTF_VBE("%s: getting color #%x --> 0x%04x\n", __func__, + color_number, *color_value); + + return 0; +} + +// VBE Function 15h +u8 +vbe_get_ddc_info(vbe_ddc_info_t * ddc_info) +{ + vbe_prepare(); + // call VBE function 15h (DDC Info Function) + M.x86.R_EAX = 0x4f15; + M.x86.R_BL = 0x00; // get DDC Info + M.x86.R_CX = ddc_info->port_number; + M.x86.R_ES = 0x0; + M.x86.R_DI = 0x0; + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Get DDC Info Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: port: %x VBE Get DDC Info Function Return Code NOT OK! AH=%x\n", + __func__, ddc_info->port_number, M.x86.R_AH); + return M.x86.R_AH; + } + // BH = approx. time in seconds to transfer one EDID block + ddc_info->edid_transfer_time = M.x86.R_BH; + // BL = DDC Level + ddc_info->ddc_level = M.x86.R_BL; + + vbe_prepare(); + // call VBE function 15h (DDC Info Function) + M.x86.R_EAX = 0x4f15; + M.x86.R_BL = 0x01; // read EDID + M.x86.R_CX = ddc_info->port_number; + M.x86.R_DX = 0x0; // block number + // ES:DI is address where EDID is stored, we store it at 2000:0000 + M.x86.R_ES = 0x2000; + M.x86.R_DI = 0x0; + + // enable trace + CHECK_DBG(DEBUG_TRACE_X86EMU) { + X86EMU_trace_on(); + } + // run VESA Interrupt + runInt10(); + + if (M.x86.R_AL != 0x4f) { + DEBUG_PRINTF_VBE + ("%s: VBE Read EDID Function NOT supported! AL=%x\n", + __func__, M.x86.R_AL); + return -1; + } + + if (M.x86.R_AH != 0x0) { + DEBUG_PRINTF_VBE + ("%s: port: %x VBE Read EDID Function Return Code NOT OK! AH=%x\n", + __func__, ddc_info->port_number, M.x86.R_AH); + return M.x86.R_AH; + } + + memcpy(ddc_info->edid_block_zero, + biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, + sizeof(ddc_info->edid_block_zero)); + + return 0; +} + +u32 +vbe_get_info(u8 argc, char ** argv) +{ + u8 rval; + u32 i; + if (argc < 4) { + printf + ("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n", + argv[0]); + int i = 0; + for (i = 0; i < argc; i++) { + printf("argv[%d]: %s\n", i, argv[i]); + } + return -1; + } + // get a copy of input struct... + screen_info_input_t input = + *((screen_info_input_t *) strtoul((char *) argv[4], 0, 16)); + // output is pointer to the address passed as argv[4] + screen_info_t *output = + (screen_info_t *) strtoul((char *) argv[4], 0, 16); + // zero output + memset(output, 0, sizeof(screen_info_t)); + + // argv[1] is address of virtual BIOS mem... + // argv[2] is the size + biosmem = (u8 *) strtoul(argv[1], 0, 16); + biosmem_size = strtoul(argv[2], 0, 16);; + if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) { + printf("Error: Not enough virtual memory: %x, required: %x!\n", + biosmem_size, MIN_REQUIRED_VMEM_SIZE); + return -1; + } + // argv[3] is the device to open and use... + if (dev_init((char *) argv[3]) != 0) { + printf("Error initializing device!\n"); + return -1; + } + //setup interrupt handler + X86EMU_intrFuncs intrFuncs[256]; + for (i = 0; i < 256; i++) + intrFuncs[i] = handleInterrupt; + X86EMU_setupIntrFuncs(intrFuncs); + X86EMU_setupPioFuncs(&my_pio_funcs); + X86EMU_setupMemFuncs(&my_mem_funcs); + + // set mem_base + M.mem_base = (long) biosmem; + M.mem_size = biosmem_size; + DEBUG_PRINTF_VBE("membase set: %08x, size: %08x\n", (int) M.mem_base, + (int) M.mem_size); + + vbe_info_t info; + rval = vbe_info(&info); + if (rval != 0) + return rval; + + DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature); + DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version); + DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr); + DEBUG_PRINTF_VBE("Capabilities:\n"); + DEBUG_PRINTF_VBE("\tDAC: %s\n", + (info.capabilities & 0x1) == + 0 ? "fixed 6bit" : "switchable 6/8bit"); + DEBUG_PRINTF_VBE("\tVGA: %s\n", + (info.capabilities & 0x2) == + 0 ? "compatible" : "not compatible"); + DEBUG_PRINTF_VBE("\tRAMDAC: %s\n", + (info.capabilities & 0x4) == + 0 ? "normal" : "use blank bit in Function 09h"); + + // argv[4] may be a pointer with enough space to return screen_info_t + // as input, it must contain a screen_info_input_t with the following content: + // byte[0:3] = "DDC\0" (zero-terminated signature header) + // byte[4:5] = reserved space for the return struct... just in case we ever change + // the struct and dont have reserved enough memory (and let's hope the struct + // never gets larger than 64KB) + // byte[6] = monitor port number for DDC requests ("only" one byte... so lets hope we never have more than 255 monitors... + // byte[7:8] = max. screen width (OF may want to limit this) + // byte[9] = required color depth in bpp + if (strncmp((char *) input.signature, "DDC", 4) != 0) { + printf + ("%s: Invalid input signature! expected: %s, is: %s\n", + __func__, "DDC", input.signature); + return -1; + } + if (input.size_reserved != sizeof(screen_info_t)) { + printf + ("%s: Size of return struct is wrong, required: %d, available: %d\n", + __func__, (int) sizeof(screen_info_t), + input.size_reserved); + return -1; + } + + vbe_ddc_info_t ddc_info; + ddc_info.port_number = input.monitor_number; + vbe_get_ddc_info(&ddc_info); + +#if 0 + DEBUG_PRINTF_VBE("DDC: edid_tranfer_time: %d\n", + ddc_info.edid_transfer_time); + DEBUG_PRINTF_VBE("DDC: ddc_level: %x\n", ddc_info.ddc_level); + DEBUG_PRINTF_VBE("DDC: EDID: \n"); + CHECK_DBG(DEBUG_VBE) { + dump(ddc_info.edid_block_zero, + sizeof(ddc_info.edid_block_zero)); + } +#endif + if (*((u64 *) ddc_info.edid_block_zero) != + (u64) 0x00FFFFFFFFFFFF00) { + // invalid EDID signature... probably no monitor + + output->display_type = 0x0; + return 0; + } else if ((ddc_info.edid_block_zero[20] & 0x80) != 0) { + // digital display + output->display_type = 2; + } else { + // analog + output->display_type = 1; + } + DEBUG_PRINTF_VBE("DDC: found display type %d\n", output->display_type); + memcpy(output->edid_block_zero, ddc_info.edid_block_zero, + sizeof(ddc_info.edid_block_zero)); + i = 0; + vbe_mode_info_t mode_info; + vbe_mode_info_t best_mode_info; + // initialize best_mode to 0 + memset(&best_mode_info, 0, sizeof(best_mode_info)); + while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) { + //DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode); + vbe_get_mode_info(&mode_info); +#if 0 + DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n", + mode_info.video_mode, + (mode_info.attributes & 0x1) == + 0 ? "not supported" : "supported"); + DEBUG_PRINTF_VBE("\tTTY: %s\n", + (mode_info.attributes & 0x4) == + 0 ? "no" : "yes"); + DEBUG_PRINTF_VBE("\tMode: %s %s\n", + (mode_info.attributes & 0x8) == + 0 ? "monochrome" : "color", + (mode_info.attributes & 0x10) == + 0 ? "text" : "graphics"); + DEBUG_PRINTF_VBE("\tVGA: %s\n", + (mode_info.attributes & 0x20) == + 0 ? "compatible" : "not compatible"); + DEBUG_PRINTF_VBE("\tWindowed Mode: %s\n", + (mode_info.attributes & 0x40) == + 0 ? "yes" : "no"); + DEBUG_PRINTF_VBE("\tFramebuffer: %s\n", + (mode_info.attributes & 0x80) == + 0 ? "no" : "yes"); + DEBUG_PRINTF_VBE("\tResolution: %dx%d\n", + mode_info.x_resolution, + mode_info.y_resolution); + DEBUG_PRINTF_VBE("\tChar Size: %dx%d\n", + mode_info.x_charsize, mode_info.y_charsize); + DEBUG_PRINTF_VBE("\tColor Depth: %dbpp\n", + mode_info.bits_per_pixel); + DEBUG_PRINTF_VBE("\tMemory Model: 0x%x\n", + mode_info.memory_model); + DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n", + mode_info.framebuffer_address); +#endif + if ((mode_info.bits_per_pixel == input.color_depth) + && (mode_info.x_resolution <= input.max_screen_width) + && ((mode_info.attributes & 0x80) != 0) // framebuffer mode + && ((mode_info.attributes & 0x10) != 0) // graphics + && ((mode_info.attributes & 0x8) != 0) // color + && (mode_info.x_resolution > best_mode_info.x_resolution)) // better than previous best_mode + { + // yiiiihaah... we found a new best mode + memcpy(&best_mode_info, &mode_info, sizeof(mode_info)); + } + i++; + } + + if (best_mode_info.video_mode != 0) { + DEBUG_PRINTF_VBE + ("Best Video Mode found: 0x%x, %dx%d, %dbpp, framebuffer_address: 0x%x\n", + best_mode_info.video_mode, + best_mode_info.x_resolution, + best_mode_info.y_resolution, + best_mode_info.bits_per_pixel, + best_mode_info.framebuffer_address); + + //printf("Mode Info Dump:"); + //dump(best_mode_info.mode_info_block, 64); + + // set the video mode + vbe_set_mode(&best_mode_info); + + if ((info.capabilities & 0x1) != 0) { + // switch to 8 bit palette format + vbe_set_palette_format(8); + } + // setup a palette: + // - first 216 colors are mixed colors for each component in 6 steps + // (6*6*6=216) + // - then 10 shades of the three primary colors + // - then 10 shades of grey + // ------- + // = 256 colors + // + // - finally black is color 0 and white color FF (because SLOF expects it + // this way...) + // this resembles the palette that the kernel/X Server seems to expect... + + u8 mixed_color_values[6] = + { 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 }; + u8 primary_color_values[10] = + { 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F, + 0x27 + }; + u8 mc_size = sizeof(mixed_color_values); + u8 prim_size = sizeof(primary_color_values); + + u8 curr_color_index; + u32 curr_color; + + u8 r, g, b; + // 216 mixed colors + for (r = 0; r < mc_size; r++) { + for (g = 0; g < mc_size; g++) { + for (b = 0; b < mc_size; b++) { + curr_color_index = + (r * mc_size * mc_size) + + (g * mc_size) + b; + curr_color = 0; + curr_color |= ((u32) mixed_color_values[r]) << 16; //red value + curr_color |= ((u32) mixed_color_values[g]) << 8; //green value + curr_color |= (u32) mixed_color_values[b]; //blue value + vbe_set_color(curr_color_index, + curr_color); + } + } + } + + // 10 shades of each primary color + // red + for (r = 0; r < prim_size; r++) { + curr_color_index = mc_size * mc_size * mc_size + r; + curr_color = ((u32) primary_color_values[r]) << 16; + vbe_set_color(curr_color_index, curr_color); + } + //green + for (g = 0; g < prim_size; g++) { + curr_color_index = + mc_size * mc_size * mc_size + prim_size + g; + curr_color = ((u32) primary_color_values[g]) << 8; + vbe_set_color(curr_color_index, curr_color); + } + //blue + for (b = 0; b < prim_size; b++) { + curr_color_index = + mc_size * mc_size * mc_size + prim_size * 2 + b; + curr_color = (u32) primary_color_values[b]; + vbe_set_color(curr_color_index, curr_color); + } + // 10 shades of grey + for (i = 0; i < prim_size; i++) { + curr_color_index = + mc_size * mc_size * mc_size + prim_size * 3 + i; + curr_color = 0; + curr_color |= ((u32) primary_color_values[i]) << 16; //red + curr_color |= ((u32) primary_color_values[i]) << 8; //green + curr_color |= ((u32) primary_color_values[i]); //blue + vbe_set_color(curr_color_index, curr_color); + } + + // SLOF is using color 0x0 (black) and 0xFF (white) to draw to the screen... + vbe_set_color(0x00, 0x00000000); + vbe_set_color(0xFF, 0x00FFFFFF); + + output->screen_width = best_mode_info.x_resolution; + output->screen_height = best_mode_info.y_resolution; + output->screen_linebytes = best_mode_info.linebytes; + output->color_depth = best_mode_info.bits_per_pixel; + output->framebuffer_address = + best_mode_info.framebuffer_address; + } else { + printf("%s: No suitable video mode found!\n", __func__); + //unset display_type... + output->display_type = 0; + } + return 0; +} |