From c1efb9038402af268a0a25957ac236d047b21f22 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Wed, 12 Oct 2011 14:30:59 -0700 Subject: [PATCH] refactor vesa mode setting code and bootsplash code - adds possibility to set a vesa mode without showing a bootsplash - make bootsplash / mode setting code available in real mode. Change-Id: I0045c9d75757657f4ce531889593102ea1e39ce5 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/256 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones --- src/Kconfig | 46 +++++---- src/arch/x86/boot/coreboot_table.c | 2 +- src/devices/oprom/include/vbe.h | 8 +- src/devices/oprom/x86.c | 103 +++++++++++++++++++-- src/devices/oprom/x86.h | 1 + src/devices/oprom/x86_asm.S | 5 + src/devices/oprom/yabel/compat/functions.c | 2 +- src/devices/oprom/yabel/device.c | 2 + src/devices/oprom/yabel/vbe.c | 9 +- src/lib/fallback_boot.c | 2 +- 10 files changed, 145 insertions(+), 35 deletions(-) diff --git a/src/Kconfig b/src/Kconfig index e9ceed5e1..525d452f4 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -516,40 +516,31 @@ config MBI_FILE endmenu -menu "Bootsplash" - depends on PCI_OPTION_ROM_RUN_YABEL +menu "Display" + depends on PCI_OPTION_ROM_RUN_YABEL || PCI_OPTION_ROM_RUN_REALMODE -config BOOTSPLASH - prompt "Show graphical bootsplash" +config FRAMEBUFFER_SET_VESA_MODE + prompt "Set VESA framebuffer mode" bool - depends on PCI_OPTION_ROM_RUN_YABEL + depends on PCI_OPTION_ROM_RUN_YABEL || PCI_OPTION_ROM_RUN_REALMODE help - This option shows a graphical bootsplash screen. The grapics are - loaded from the CBFS file bootsplash.jpg. - -config BOOTSPLASH_FILE - string "Bootsplash path and filename" - depends on BOOTSPLASH - default "bootsplash.jpg" - help - The path and filename of the file to use as graphical bootsplash - screen. The file format has to be jpg. + Set VESA framebuffer mode (needed for bootsplash) # TODO: Turn this into a "choice". config FRAMEBUFFER_VESA_MODE prompt "VESA framebuffer video mode" hex default 0x117 - depends on BOOTSPLASH + depends on FRAMEBUFFER_SET_VESA_MODE help - This option sets the resolution used for the coreboot framebuffer and - bootsplash screen. Set to 0x117 for 1024x768x16. A diligent soul will + This option sets the resolution used for the coreboot framebuffer (and + bootsplash screen). Set to 0x117 for 1024x768x16. A diligent soul will some day make this a "choice". -config COREBOOT_KEEP_FRAMEBUFFER +config FRAMEBUFFER_KEEP_VESA_MODE prompt "Keep VESA framebuffer" bool - depends on BOOTSPLASH + depends on PCI_OPTION_ROM_RUN_YABEL || PCI_OPTION_ROM_RUN_REALMODE help This option keeps the framebuffer mode set after coreboot finishes execution. If this option is enabled, coreboot will pass a @@ -557,6 +548,21 @@ config COREBOOT_KEEP_FRAMEBUFFER framebuffer driver. If this option is disabled, coreboot will switch back to text mode before handing control to a payload. +config BOOTSPLASH + prompt "Show graphical bootsplash" + bool + depends on FRAMEBUFFER_SET_VESA_MODE + help + This option shows a graphical bootsplash screen. The grapics are + loaded from the CBFS file bootsplash.jpg. + +config BOOTSPLASH_FILE + string "Bootsplash path and filename" + depends on BOOTSPLASH + default "bootsplash.jpg" + help + The path and filename of the file to use as graphical bootsplash + screen. The file format has to be jpg. endmenu menu "Debugging" diff --git a/src/arch/x86/boot/coreboot_table.c b/src/arch/x86/boot/coreboot_table.c index db3a8a9b5..d53a23a9e 100644 --- a/src/arch/x86/boot/coreboot_table.c +++ b/src/arch/x86/boot/coreboot_table.c @@ -148,7 +148,7 @@ static void lb_console(struct lb_header *header) static void lb_framebuffer(struct lb_header *header) { -#if CONFIG_BOOTSPLASH && CONFIG_COREBOOT_KEEP_FRAMEBUFFER +#if CONFIG_FRAMEBUFFER_KEEP_VESA_MODE void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); struct lb_framebuffer *framebuffer; diff --git a/src/devices/oprom/include/vbe.h b/src/devices/oprom/include/vbe.h index b87b0d550..f857b67af 100644 --- a/src/devices/oprom/include/vbe.h +++ b/src/devices/oprom/include/vbe.h @@ -104,9 +104,11 @@ typedef struct { struct lb_framebuffer; -void vbe_set_graphics(void); // yabel only - -void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); +void vbe_set_graphics(void); void vbe_textmode_console(void); +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); +#define VESA_GET_INFO 0x4f00 +#define VESA_GET_MODE_INFO 0x4f01 +#define VESA_SET_MODE 0x4f02 diff --git a/src/devices/oprom/x86.c b/src/devices/oprom/x86.c index 9a6ce4102..22fc2c5da 100644 --- a/src/devices/oprom/x86.c +++ b/src/devices/oprom/x86.c @@ -25,14 +25,19 @@ #include #include #include - +#include +#include #include "x86.h" +#include "vbe.h" +#include "../../src/lib/jpeg.h" void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx, - u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_call; + u32 esi, u32 edi) __attribute__((regparm(0))) = + (void *)&__realmode_call; void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx, - u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_interrupt; + u32 esi, u32 edi) __attribute__((regparm(0))) = + (void *)&__realmode_interrupt; static void setup_bda(void) { @@ -107,9 +112,9 @@ static void setup_interrupt_handlers(void) if(!intXX_handler[i]) { /* Now set the default functions that are actually - * needed to initialize the option roms. This is very - * slick, as it allows us to implement mainboard specific - * interrupt handlers, such as the int15 + * needed to initialize the option roms. This is + * very slick, as it allows us to implement mainboard + * specific interrupt handlers, such as the int15. */ switch (i) { case 0x10: @@ -178,6 +183,88 @@ static void setup_realmode_idt(void) write_idt_stub((void *)0xffe6e, 0x1a); } +#if CONFIG_FRAMEBUFFER_SET_VESA_MODE +static u8 vbe_get_mode_info(vbe_mode_info_t * mode_info) +{ + char *buffer = (char *)&__buffer; + u16 buffer_seg = (((unsigned long)buffer) >> 4) & 0xff00; + u16 buffer_adr = ((unsigned long)buffer) & 0xffff; + realmode_interrupt(0x10, VESA_GET_MODE_INFO, 0x0000, + mode_info->video_mode, 0x0000, buffer_seg, buffer_adr); + memcpy(mode_info, buffer, sizeof(vbe_mode_info_t)); + return 0; +} + +static u8 vbe_set_mode(vbe_mode_info_t * mode_info) +{ + // request linear framebuffer mode + mode_info->video_mode |= (1 << 14); + // request clearing of framebuffer + mode_info->video_mode &= ~(1 << 15); + realmode_interrupt(0x10, VESA_SET_MODE, mode_info->video_mode, + 0x0000, 0x0000, 0x0000, 0x0000); + return 0; +} + +vbe_mode_info_t mode_info; + +/* These two functions could probably even be generic between + * yabel and x86 native. TBD later. + */ +void vbe_set_graphics(void) +{ + mode_info.video_mode = (1 << 14) | CONFIG_FRAMEBUFFER_VESA_MODE; + vbe_get_mode_info(&mode_info); + unsigned char *framebuffer = + (unsigned char *) le32_to_cpu(mode_info.vesa.phys_base_ptr); + printk(BIOS_DEBUG, "framebuffer: %p\n", framebuffer); + printk(BIOS_DEBUG, "framebuffer: %x\n", mode_info.vesa.phys_base_ptr); + vbe_set_mode(&mode_info); +#if CONFIG_BOOTSPLASH + struct jpeg_decdata *decdata; + decdata = malloc(sizeof(*decdata)); + unsigned char *jpeg = cbfs_find_file("bootsplash.jpg", + CBFS_TYPE_BOOTSPLASH); + if (!jpeg) { + return; + } + int ret = 0; + ret = jpeg_decode(jpeg, framebuffer, 1024, 768, 16, decdata); +#endif +} + +void vbe_textmode_console(void) +{ + delay(2); + realmode_interrupt(0x10, 0x0003, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000); +} + +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer) +{ + framebuffer->physical_address = + le32_to_cpu(mode_info.vesa.phys_base_ptr); + + framebuffer->x_resolution = le16_to_cpu(mode_info.vesa.x_resolution); + framebuffer->y_resolution = le16_to_cpu(mode_info.vesa.y_resolution); + framebuffer->bytes_per_line = + le16_to_cpu(mode_info.vesa.bytes_per_scanline); + framebuffer->bits_per_pixel = mode_info.vesa.bits_per_pixel; + + framebuffer->red_mask_pos = mode_info.vesa.red_mask_pos; + framebuffer->red_mask_size = mode_info.vesa.red_mask_size; + + framebuffer->green_mask_pos = mode_info.vesa.green_mask_pos; + framebuffer->green_mask_size = mode_info.vesa.green_mask_size; + + framebuffer->blue_mask_pos = mode_info.vesa.blue_mask_pos; + framebuffer->blue_mask_size = mode_info.vesa.blue_mask_size; + + framebuffer->reserved_mask_pos = mode_info.vesa.reserved_mask_pos; + framebuffer->reserved_mask_size = mode_info.vesa.reserved_mask_size; +} +#endif + void run_bios(struct device *dev, unsigned long addr) { u32 num_dev = (dev->bus->secondary << 8) | dev->path.pci.devfn; @@ -203,6 +290,10 @@ void run_bios(struct device *dev, unsigned long addr) /* Option ROM entry point is at OPROM start + 3 */ realmode_call(addr + 0x0003, num_dev, 0xffff, 0x0000, 0xffff, 0x0, 0x0); printk(BIOS_DEBUG, "... Option ROM returned.\n"); + +#if CONFIG_FRAMEBUFFER_SET_VESA_MODE + vbe_set_graphics(); +#endif } #if CONFIG_GEODE_VSA diff --git a/src/devices/oprom/x86.h b/src/devices/oprom/x86.h index 0bc24122e..40c5778de 100644 --- a/src/devices/oprom/x86.h +++ b/src/devices/oprom/x86.h @@ -30,6 +30,7 @@ void x86_exception(struct eregs *info); extern unsigned char __idt_handler, __idt_handler_size; extern unsigned char __realmode_code, __realmode_code_size; extern unsigned char __realmode_call, __realmode_interrupt; +extern unsigned char __buffer; extern void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx, u32 esi, u32 edi) __attribute__((regparm(0))); diff --git a/src/devices/oprom/x86_asm.S b/src/devices/oprom/x86_asm.S index d5b5e1859..57c533891 100644 --- a/src/devices/oprom/x86_asm.S +++ b/src/devices/oprom/x86_asm.S @@ -66,6 +66,11 @@ __registers = RELOCATED(.) .long 0 /* 16 - ESI */ .long 0 /* 20 - EDI */ +/* 256 byte buffer, used by int10 */ + .globl __buffer +__buffer = RELOCATED(.) + .skip 256 + .code32 .globl __realmode_call __realmode_call = RELOCATED(.) diff --git a/src/devices/oprom/yabel/compat/functions.c b/src/devices/oprom/yabel/compat/functions.c index db37fbc6f..542c81f31 100644 --- a/src/devices/oprom/yabel/compat/functions.c +++ b/src/devices/oprom/yabel/compat/functions.c @@ -38,7 +38,7 @@ void run_bios(struct device * dev, unsigned long addr) biosemu(vmem, VMEM_SIZE, dev, addr); -#if CONFIG_BOOTSPLASH +#if CONFIG_FRAMEBUFFER_SET_VESA_MODE vbe_set_graphics(); #endif } diff --git a/src/devices/oprom/yabel/device.c b/src/devices/oprom/yabel/device.c index 82595945a..b09f50e4a 100644 --- a/src/devices/oprom/yabel/device.c +++ b/src/devices/oprom/yabel/device.c @@ -364,6 +364,7 @@ biosemu_dev_check_exprom(unsigned long rom_base_addr) pci_ds.device_id = in16le(&pci_ds.device_id); pci_ds.img_length = in16le(&pci_ds.img_length); pci_ds.pci_ds_length = in16le(&pci_ds.pci_ds_length); +#ifdef DO_THIS_TEST_TWICE if (pci_ds.vendor_id != bios_device.pci_vendor_id) { printf ("Image has invalid Vendor ID: %04x, expected: %04x\n", @@ -376,6 +377,7 @@ biosemu_dev_check_exprom(unsigned long rom_base_addr) pci_ds.device_id, bios_device.pci_device_id); break; } +#endif DEBUG_PRINTF("Image Length: %d\n", pci_ds.img_length * 512); DEBUG_PRINTF("Image Code Type: %d\n", pci_ds.code_type); if (pci_ds.code_type == 0) { diff --git a/src/devices/oprom/yabel/vbe.c b/src/devices/oprom/yabel/vbe.c index 27bf5e62b..b1d6984d7 100644 --- a/src/devices/oprom/yabel/vbe.c +++ b/src/devices/oprom/yabel/vbe.c @@ -13,7 +13,7 @@ #include #include -#if CONFIG_BOOTSPLASH +#if CONFIG_FRAMEBUFFER_SET_VESA_MODE #include #endif @@ -64,7 +64,7 @@ vbe_prepare(void) return 0; // successfull init } -#if CONFIG_BOOTSPLASH +#if CONFIG_FRAMEBUFFER_SET_VESA_MODE // VBE Function 00h static u8 vbe_info(vbe_info_t * info) @@ -704,10 +704,12 @@ void vbe_set_graphics(void) mode_info.video_mode = (1 << 14) | CONFIG_FRAMEBUFFER_VESA_MODE; vbe_get_mode_info(&mode_info); + vbe_set_mode(&mode_info); + +#if CONFIG_BOOTSPLASH unsigned char *framebuffer = (unsigned char *) le32_to_cpu(mode_info.vesa.phys_base_ptr); DEBUG_PRINTF_VBE("FRAMEBUFFER: 0x%p\n", framebuffer); - vbe_set_mode(&mode_info); struct jpeg_decdata *decdata; decdata = malloc(sizeof(*decdata)); @@ -728,6 +730,7 @@ void vbe_set_graphics(void) DEBUG_PRINTF_VBE("Decompressing boot splash screen...\n"); ret = jpeg_decode(jpeg, framebuffer, 1024, 768, 16, decdata); DEBUG_PRINTF_VBE("returns %x\n", ret); +#endif } void fill_lb_framebuffer(struct lb_framebuffer *framebuffer) diff --git a/src/lib/fallback_boot.c b/src/lib/fallback_boot.c index a8fe37712..b5ec6c303 100644 --- a/src/lib/fallback_boot.c +++ b/src/lib/fallback_boot.c @@ -28,7 +28,7 @@ void set_boot_successful(void) void boot_successful(void) { -#if CONFIG_BOOTSPLASH && !CONFIG_COREBOOT_KEEP_FRAMEBUFFER +#if CONFIG_FRAMEBUFFER_SET_VESA_MODE && !CONFIG_FRAMEBUFFER_KEEP_VESA_MODE void vbe_textmode_console(void); vbe_textmode_console(); -- 2.25.1