From 839b333ad80db4f39a97b7aedc927147794e576b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 21 Apr 2013 13:02:10 +0200 Subject: [PATCH 332/364] Support coreboot framebuffer. * grub-core/video/i386/coreboot/cbfb.c: New file. --- ChangeLog | 6 ++ grub-core/Makefile.core.def | 6 ++ grub-core/commands/i386/coreboot/cbls.c | 16 ++- grub-core/video/i386/coreboot/cbfb.c | 180 ++++++++++++++++++++++++++++++++ include/grub/i386/coreboot/lbio.h | 36 +++++-- 5 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 grub-core/video/i386/coreboot/cbfb.c diff --git a/ChangeLog b/ChangeLog index 2a4264c..6be583e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-04-21 Vladimir Serbinenko + + Support coreboot framebuffer. + + * grub-core/video/i386/coreboot/cbfb.c: New file. + 2013-04-20 Vladimir Serbinenko * grub-core/kern/mm.c (grub_mm_init_region): Fix condition for diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1f04afb..7269609 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1797,6 +1797,12 @@ module = { }; module = { + name = coreboot_fb; + common = video/i386/coreboot/cbfb.c; + enable = i386_coreboot; +}; + +module = { name = sdl; emu = video/emu/sdl.c; enable = emu; diff --git a/grub-core/commands/i386/coreboot/cbls.c b/grub-core/commands/i386/coreboot/cbls.c index 151f9e8..a3542f3 100644 --- a/grub-core/commands/i386/coreboot/cbls.c +++ b/grub-core/commands/i386/coreboot/cbls.c @@ -50,7 +50,7 @@ static const char *descs[] = { [0xd] = "assembler", [0xf] = "serial", [GRUB_LINUXBIOS_MEMBER_CONSOLE] = "console", - [0x12] = "framebuffer", + [GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER] = "framebuffer", [0x13] = "GPIO", [0x15] = "VDAT", [GRUB_LINUXBIOS_MEMBER_TIMESTAMPS] = "timestamps (`coreboot_boottime' to list)", @@ -77,6 +77,20 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, switch (table_item->tag) { + case GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER: + { + struct grub_linuxbios_table_framebuffer *fb; + fb = (struct grub_linuxbios_table_framebuffer *) (table_item + 1); + + grub_printf (": %dx%dx%d pitch=%d lfb=0x%llx %d/%d/%d/%d %d/%d/%d/%d", + fb->width, fb->height, + fb->bpp, fb->pitch, fb->lfb, + fb->red_mask_size, fb->green_mask_size, + fb->blue_mask_size, fb->reserved_mask_size, + fb->red_field_pos, fb->green_field_pos, + fb->blue_field_pos, fb->reserved_field_pos); + break; + } case GRUB_LINUXBIOS_MEMBER_MAINBOARD: { struct grub_linuxbios_mainboard *mb; diff --git a/grub-core/video/i386/coreboot/cbfb.c b/grub-core/video/i386/coreboot/cbfb.c new file mode 100644 index 0000000..000efdb --- /dev/null +++ b/grub-core/video/i386/coreboot/cbfb.c @@ -0,0 +1,180 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static struct grub_linuxbios_table_framebuffer *cbfb; + +static struct +{ + struct grub_video_mode_info mode_info; + grub_uint8_t *ptr; +} framebuffer; + +static grub_err_t +grub_video_cbfb_init (void) +{ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_cbfb_fill_mode_info (struct grub_video_mode_info *out) +{ + grub_memset (out, 0, sizeof (*out)); + + out->width = cbfb->width; + out->height = cbfb->height; + out->pitch = cbfb->pitch; + + out->red_field_pos = cbfb->red_field_pos; + out->red_mask_size = cbfb->red_mask_size; + out->green_field_pos = cbfb->green_field_pos; + out->green_mask_size = cbfb->green_mask_size; + out->blue_field_pos = cbfb->blue_field_pos; + out->blue_mask_size = cbfb->blue_mask_size; + out->reserved_field_pos = cbfb->reserved_field_pos; + out->reserved_mask_size = cbfb->reserved_mask_size; + + out->mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + out->bpp = cbfb->bpp; + out->bytes_per_pixel = (cbfb->bpp + 7) / 8; + out->number_of_colors = 256; + + out->blit_format = grub_video_get_blit_format (out); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_cbfb_setup (unsigned int width, unsigned int height, + unsigned int mode_type __attribute__ ((unused)), + unsigned int mode_mask __attribute__ ((unused))) +{ + grub_err_t err; + + if (!cbfb) + return grub_error (GRUB_ERR_IO, "Couldn't find display device."); + + if (!((width == cbfb->width && height == cbfb->height) + || (width == 0 && height == 0))) + return grub_error (GRUB_ERR_IO, "can't set mode %dx%d", width, height); + + err = grub_video_cbfb_fill_mode_info (&framebuffer.mode_info); + if (err) + { + grub_dprintf ("video", "CBFB: couldn't fill mode info\n"); + return err; + } + + framebuffer.ptr = (void *) (grub_addr_t) cbfb->lfb; + + grub_dprintf ("video", "CBFB: initialising FB @ %p %dx%dx%d\n", + framebuffer.ptr, framebuffer.mode_info.width, + framebuffer.mode_info.height, framebuffer.mode_info.bpp); + + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, NULL, NULL); + if (err) + return err; + + grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + + return err; +} + +static grub_err_t +grub_video_cbfb_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); + *framebuf = (char *) framebuffer.ptr; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + +static struct grub_video_adapter grub_video_cbfb_adapter = + { + .name = "Coreboot video driver", + + .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE_DIRTY, + + .init = grub_video_cbfb_init, + .fini = grub_video_fb_fini, + .setup = grub_video_cbfb_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_cbfb_get_info_and_fini, + .set_palette = grub_video_fb_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_fb_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data __attribute__ ((unused))) +{ + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER) + return 0; + cbfb = (struct grub_linuxbios_table_framebuffer *) (table_item + 1); + return 1; +} + +GRUB_MOD_INIT(coreboot_fb) +{ + grub_linuxbios_table_iterate (iterate_linuxbios_table, 0); + + if (cbfb) + grub_video_register (&grub_video_cbfb_adapter); +} + +GRUB_MOD_FINI(coreboot_fb) +{ + if (cbfb) + grub_video_unregister (&grub_video_cbfb_adapter); +} diff --git a/include/grub/i386/coreboot/lbio.h b/include/grub/i386/coreboot/lbio.h index b4150f4..9a93046 100644 --- a/include/grub/i386/coreboot/lbio.h +++ b/include/grub/i386/coreboot/lbio.h @@ -54,18 +54,40 @@ struct grub_linuxbios_mainboard struct grub_linuxbios_table_item { -#define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00 -#define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01 -#define GRUB_LINUXBIOS_MEMBER_MAINBOARD 0x03 -#define GRUB_LINUXBIOS_MEMBER_CONSOLE 0x10 -#define GRUB_LINUXBIOS_MEMBER_LINK 0x11 -#define GRUB_LINUXBIOS_MEMBER_TIMESTAMPS 0x16 -#define GRUB_LINUXBIOS_MEMBER_CBMEMC 0x17 grub_uint32_t tag; grub_uint32_t size; }; typedef struct grub_linuxbios_table_item *grub_linuxbios_table_item_t; +enum + { + GRUB_LINUXBIOS_MEMBER_UNUSED = 0x00, + GRUB_LINUXBIOS_MEMBER_MEMORY = 0x01, + GRUB_LINUXBIOS_MEMBER_MAINBOARD = 0x03, + GRUB_LINUXBIOS_MEMBER_CONSOLE = 0x10, + GRUB_LINUXBIOS_MEMBER_LINK = 0x11, + GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER = 0x12, + GRUB_LINUXBIOS_MEMBER_TIMESTAMPS = 0x16, + GRUB_LINUXBIOS_MEMBER_CBMEMC = 0x17 + }; + +struct grub_linuxbios_table_framebuffer { + grub_uint64_t lfb; + grub_uint32_t width; + grub_uint32_t height; + grub_uint32_t pitch; + grub_uint8_t bpp; + + grub_uint8_t red_field_pos; + grub_uint8_t red_mask_size; + grub_uint8_t green_field_pos; + grub_uint8_t green_mask_size; + grub_uint8_t blue_field_pos; + grub_uint8_t blue_mask_size; + grub_uint8_t reserved_field_pos; + grub_uint8_t reserved_mask_size; +}; + struct grub_linuxbios_mem_region { grub_uint64_t addr; -- 1.8.1.4