From a9c20c1640cdea0ba902095cb18760f5ebe98875 Mon Sep 17 00:00:00 2001 From: Kris Moore Date: Tue, 28 Oct 2014 15:59:59 -0400 Subject: [PATCH 1/2] Add support for passing EFI framebuffer information to FreeBSD kernel on FreeBSD 10.1 and later. --- grub-core/loader/i386/bsd.c | 75 ++++++++++++++++++++++++++++++++++++ grub-core/video/efi_gop.c | 14 +++++++ include/grub/i386/bsd.h | 1 + include/grub/i386/freebsd_bootinfo.h | 33 ++++++++++++++++ include/grub/video.h | 18 +++++++++ 5 files changed, 141 insertions(+) create mode 100644 include/grub/i386/freebsd_bootinfo.h diff --git grub-core/loader/i386/bsd.c grub-core/loader/i386/bsd.c index 8f691e0..c685552 100644 --- grub-core/loader/i386/bsd.c +++ grub-core/loader/i386/bsd.c @@ -48,6 +48,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #ifdef GRUB_MACHINE_EFI #include #define NETBSD_DEFAULT_VIDEO_MODE "800x600" +#define FREEBSD_DEFAULT_VIDEO_MODE "800x600" #else #define NETBSD_DEFAULT_VIDEO_MODE "text" #include @@ -584,6 +585,63 @@ freebsd_get_zfs (void) grub_free (uuid); } +#ifdef GRUB_MACHINE_EFI + +static grub_err_t +grub_freebsd_setup_video (void) +{ + struct grub_video_mode_info mode_info; + void *framebuffer; + const char *modevar; + struct grub_freebsd_btinfo_framebuf efifb; + grub_err_t err; + grub_video_driver_id_t driv_id; + + modevar = grub_env_get ("gfxpayload"); + + /* Now all graphical modes are acceptable. + May change in future if we have modes without framebuffer. */ + if (modevar && *modevar != 0) + { + char *tmp; + tmp = grub_xasprintf ("%s;" FREEBSD_DEFAULT_VIDEO_MODE, modevar); + if (! tmp) + return grub_errno; + err = grub_video_set_mode (tmp, 0, 0); + grub_free (tmp); + } + else + err = grub_video_set_mode (FREEBSD_DEFAULT_VIDEO_MODE, 0, 0); + + if (err) + return err; + + driv_id = grub_video_get_driver_id (); + if (driv_id == GRUB_VIDEO_DRIVER_NONE) + return GRUB_ERR_NONE; + + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); + + if (err) + return err; + + efifb.fb_width = mode_info.width; + efifb.fb_height = mode_info.height; + efifb.fb_stride = mode_info.stride; + + efifb.fb_addr = (grub_addr_t) framebuffer; + efifb.fb_size = ALIGN_UP (mode_info.pitch * efifb.fb_height, 65536); + + efifb.fb_mask_red = mode_info.red_mask; + efifb.fb_mask_green = mode_info.green_mask; + efifb.fb_mask_blue = mode_info.blue_mask; + efifb.fb_mask_reserved = mode_info.reserved_mask; + + err = grub_bsd_add_meta ( FREEBSD_MODINFO_METADATA | FREEBSD_BTINFO_FRAMEBUF, &efifb, sizeof (efifb)); + return err; +} +#endif + static grub_err_t grub_freebsd_boot (void) { @@ -687,6 +745,10 @@ grub_freebsd_boot (void) *(grub_uint32_t *) p_tag = bootflags; break; + case FREEBSD_MODINFO_METADATA | FREEBSD_BTINFO_FRAMEBUF: + grub_memcpy (p_tag, tag->data, tag->len); + break; + case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ENVP: if (is_64bit) *(grub_uint64_t *) p_tag = bi.environment; @@ -716,7 +778,10 @@ grub_freebsd_boot (void) bi.kern_end = kern_end; +#ifndef GRUB_MACHINE_EFI + /* Don't set text mode on EFI boot */ grub_video_set_mode ("text", 0, 0); +#endif if (is_64bit) { @@ -1560,6 +1625,16 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) FREEBSD_MODINFOMD_KERNEND, &data, len); if (err) return err; + +#ifdef GRUB_MACHINE_EFI + err = grub_freebsd_setup_video (); + if (err) + { + grub_print_error (); + grub_puts_ (N_("Booting in EFI blind mode")); + grub_errno = GRUB_ERR_NONE; + } +#endif } grub_bsd_get_device (&freebsd_biosdev, &unit, &slice, &part); freebsd_zfsguid = 0; diff --git grub-core/video/efi_gop.c grub-core/video/efi_gop.c index 7f9d1c2..cfe0119 100644 --- grub-core/video/efi_gop.c +++ grub-core/video/efi_gop.c @@ -180,6 +180,8 @@ grub_video_gop_fill_real_mode_info (unsigned mode, out->mode_type = GRUB_VIDEO_MODE_TYPE_RGB; out->bpp = grub_video_gop_get_bpp (in); out->bytes_per_pixel = out->bpp >> 3; + out->stride = in->pixels_per_scanline; + out->pixel_format = in->pixel_format; if (!out->bpp) return grub_error (GRUB_ERR_IO, "unsupported video mode"); out->pitch = in->pixels_per_scanline * out->bytes_per_pixel; @@ -195,6 +197,10 @@ grub_video_gop_fill_real_mode_info (unsigned mode, out->blue_field_pos = 16; out->reserved_mask_size = 8; out->reserved_field_pos = 24; + out->red_mask = 0x000000ff; + out->green_mask = 0x0000ff00; + out->blue_mask = 0x00ff0000; + out->reserved_mask = 0xff000000; break; case GRUB_EFI_GOT_BGRA8: @@ -206,6 +212,10 @@ grub_video_gop_fill_real_mode_info (unsigned mode, out->blue_field_pos = 0; out->reserved_mask_size = 8; out->reserved_field_pos = 24; + out->red_mask = 0x00ff0000; + out->green_mask = 0x0000ff00; + out->blue_mask = 0x000000ff; + out->reserved_mask = 0xff000000; break; case GRUB_EFI_GOT_BITMASK: @@ -217,6 +227,10 @@ grub_video_gop_fill_real_mode_info (unsigned mode, &out->blue_field_pos); grub_video_gop_get_bitmask (in->pixel_bitmask.a, &out->reserved_mask_size, &out->reserved_field_pos); + out->red_mask = in->pixel_bitmask.r; + out->green_mask = in->pixel_bitmask.g; + out->blue_mask = in->pixel_bitmask.b; + out->reserved_mask = in->pixel_bitmask.a; break; default: diff --git include/grub/i386/bsd.h include/grub/i386/bsd.h index 524d47a..b7bb545 100644 --- include/grub/i386/bsd.h +++ include/grub/i386/bsd.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff --git include/grub/i386/freebsd_bootinfo.h include/grub/i386/freebsd_bootinfo.h new file mode 100644 index 0000000..17e5997 --- /dev/null +++ include/grub/i386/freebsd_bootinfo.h @@ -0,0 +1,33 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#include + +#define FREEBSD_BTINFO_FRAMEBUF 0x1005 + +struct grub_freebsd_btinfo_framebuf { + grub_uint64_t fb_addr; + grub_uint64_t fb_size; + grub_int32_t fb_height; + grub_int32_t fb_width; + grub_int32_t fb_stride; + grub_uint32_t fb_mask_red; + grub_uint32_t fb_mask_green; + grub_uint32_t fb_mask_blue; + grub_uint32_t fb_mask_reserved; +}; diff --git include/grub/video.h include/grub/video.h index 52c3fd7..e980fb1 100644 --- include/grub/video.h +++ include/grub/video.h @@ -141,6 +141,12 @@ struct grub_video_mode_info /* Pitch of one scanline. How many bytes there are for scanline. */ unsigned int pitch; + /* Pixels per scanline */ + unsigned int stride; + + /* Native pixel format */ + unsigned int pixel_format; + /* In index color mode, number of colors. In RGB mode this is 256. */ unsigned int number_of_colors; @@ -156,21 +162,33 @@ struct grub_video_mode_info /* What is location of red color bits. In Index Color mode, this is 0. */ unsigned int red_field_pos; + /* Native red mask */ + unsigned int red_mask; + /* How many bits are reserved for green color. */ unsigned int green_mask_size; /* What is location of green color bits. In Index Color mode, this is 0. */ unsigned int green_field_pos; + /* Native green mask */ + unsigned int green_mask; + /* How many bits are reserved for blue color. */ unsigned int blue_mask_size; /* What is location of blue color bits. In Index Color mode, this is 0. */ unsigned int blue_field_pos; + /* Native blue mask */ + unsigned int blue_mask; + /* How many bits are reserved in color. */ unsigned int reserved_mask_size; + /* Native reserved mask */ + unsigned int reserved_mask; + /* What is location of reserved color bits. In Index Color mode, this is 0. */ unsigned int reserved_field_pos; -- 2.1.2 From 68a48b4a3597b67110ad3c7fcc05f6f0e1e40b05 Mon Sep 17 00:00:00 2001 From: Kris Moore Date: Tue, 28 Oct 2014 16:21:51 -0400 Subject: [PATCH 2/2] Update changelog with details about the FreeBSD EFI framebuffer passthrough --- ChangeLog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git ChangeLog ChangeLog index 190d19d..0988971 100644 --- ChangeLog +++ ChangeLog @@ -1,3 +1,12 @@ +2014-10-28 Kris Moore + * grub-core/loader/i386/bsd.c: Add default FreeBSD EFI video mode, and + structure to pass information into EFI booted kernel + * grub-core/video/efi_gop.c: Expose some additional GOP mode information + * include/grub/i386/bsd.h: Include new freebsd_bootinfo.h + * include/grub/i386/freebsd_bootinfo.h: Add grub_freebsd_btinfo_framebuf + structure for FreeBSD EFI framebuffer passthrough + * include/grub/video.h: Add the additional exposed GOP values + 2014-10-14 Andrei Borzenkov * grub-core/loader/arm/linux.c: Use full initializer for initrd_ctx to -- 2.1.2