//VBE Function 08h static 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 02h static 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; }
static void vga_init(device_t dev) { printk(BIOS_INFO, "Starting Graphics Initialization\n"); struct cbfs_file *file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "mbi.bin"); void *mbi = NULL; unsigned int mbi_len = 0; if (file) { if (ntohl(file->type) != CBFS_TYPE_MBI) { printk(BIOS_INFO, "CBFS: MBI binary is of type %x instead of" "type %x\n", file->type, CBFS_TYPE_MBI); } else { mbi = (void *) CBFS_SUBHEADER(file); mbi_len = ntohl(file->len); } } else { printk(BIOS_INFO, "Could not find MBI.\n"); } if (mbi && mbi_len) { /* The GDT or coreboot table is going to live here. But * a long time after we relocated the GNVS, so this is * not troublesome. */ *(u32 *)0x500 = (u32)mbi; *(u32 *)0x504 = (u32)mbi_len; outb(0xeb, 0xb2); } pci_dev_init(dev); printk(BIOS_INFO, "Graphics Initialization Complete\n"); /* Enable TV-Out */ #if CONFIG_PCI_OPTION_ROM_RUN_YABEL #define PIPE_A_CRT (1 << 0) #define PIPE_A_LFP (1 << 1) #define PIPE_A_TV (1 << 3) #define PIPE_B_CRT (1 << 8) #define PIPE_B_TV (1 << 10) printk(BIOS_DEBUG, "Enabling TV-Out\n"); void runInt10(void); X86_AX = 0x5f64; X86_BX = 0x0001; // Set Display Device, force execution X86_CX = PIPE_A_CRT | PIPE_A_TV; // M.x86.R_CX = PIPE_B_TV; runInt10(); switch (X86_AX) { case 0x005f: printk(BIOS_DEBUG, "... failed.\n"); break; case 0x015f: printk(BIOS_DEBUG, "... ok.\n"); break; default: printk(BIOS_DEBUG, "... not supported.\n"); break; } #endif }
void vbe_textmode_console(void) { /* Wait, just a little bit more, pleeeease ;-) */ delay(2); M.x86.R_EAX = 0x0003; runInt10(); }
static void vga_init(device_t dev) { printk(BIOS_INFO, "Starting Graphics Initialization\n"); size_t mbi_len; void *mbi = cbfs_boot_map_with_leak("mbi.bin", CBFS_TYPE_MBI, &mbi_len); if (mbi && mbi_len) { /* The GDT or coreboot table is going to live here. But * a long time after we relocated the GNVS, so this is * not troublesome. */ *(u32 *)0x500 = (u32)mbi; *(u32 *)0x504 = (u32)mbi_len; outb(0xeb, 0xb2); } pci_dev_init(dev); printk(BIOS_INFO, "Graphics Initialization Complete\n"); /* Enable TV-Out */ #if CONFIG_PCI_OPTION_ROM_RUN_YABEL #define PIPE_A_CRT (1 << 0) #define PIPE_A_LFP (1 << 1) #define PIPE_A_TV (1 << 3) #define PIPE_B_CRT (1 << 8) #define PIPE_B_TV (1 << 10) printk(BIOS_DEBUG, "Enabling TV-Out\n"); void runInt10(void); X86_AX = 0x5f64; X86_BX = 0x0001; // Set Display Device, force execution X86_CX = PIPE_A_CRT | PIPE_A_TV; // M.x86.R_CX = PIPE_B_TV; runInt10(); switch (X86_AX) { case 0x005f: printk(BIOS_DEBUG, "... failed.\n"); break; case 0x015f: printk(BIOS_DEBUG, "... ok.\n"); break; default: printk(BIOS_DEBUG, "... not supported.\n"); break; } #endif }
static 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 01h static 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)); mode_info_valid = 1; //printf("Mode Info Dump:"); //dump(mode_info_block, 64); return 0; }
// VBE Function 00h static 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 containing 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 15h static 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; }