On 12/07/2014 16:45, Vladimir 'φ-coder/phcoder' Serbinenko wrote: > On 28.10.2014 21:32, Kris Moore wrote: >> Got another patch for review today. >> >> This patch adds support for FreeBSD's new VT console driver when booting >> in EFI mode on FreeBSD 10.1 and later. >> >> Please let me know any comments, or things that need addressed to get >> this merged in. >> >> Thanks! >> >> -- Kris Moore PC-BSD Software iXsystems >> >> >> patch-grub-fb >> >> >> From a9c20c1640cdea0ba902095cb18760f5ebe98875 Mon Sep 17 00:00:00 2001 >> From: Kris Moore <k...@pcbsd.org> >> 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 <grub/efi/efi.h> >> #define NETBSD_DEFAULT_VIDEO_MODE "800x600" >> +#define FREEBSD_DEFAULT_VIDEO_MODE "800x600" >> #else >> #define NETBSD_DEFAULT_VIDEO_MODE "text" >> #include <grub/i386/pc/vbe.h> >> @@ -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; > Please, don't add redundant fields to structs. All this info can be > inferred from available fields in FreeBSD code. As a bonus it will work > with other gfx drivers. > Another point: is this driver usable on non-EFI? It's of particular > interest on coreboot where changing video mode currently requires reflash. > > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel
Attached is a cleaned up version of the patch which doesn't add to any existing structs now. Let me know if this is closer to what you had in mind. I don't think this driver is usable on non-EFI FreeBSD yet. They have a new VT console driver, but I'm not sure their loader does video mode passthrough outside of EFI. I'm sure it will in the future, probably sometime in 11.X. -- Kris Moore PC-BSD Software iXsystems
From 997363ec7698f34d74769960c4e76cf8b369052e Mon Sep 17 00:00:00 2001 From: Kris Moore <k...@pcbsd.org> Date: Tue, 30 Dec 2014 14:34:58 -0500 Subject: [PATCH] Add the patch for FreeBSD UEFI booting / framebuffer passthrough, add fixes to ACPI environment variables while here --- ChangeLog | 9 +++ grub-core/loader/i386/bsd.c | 134 +++++++++++++++++++++++++++++++++++ include/grub/i386/bsd.h | 1 + include/grub/i386/freebsd_bootinfo.h | 33 +++++++++ 4 files changed, 177 insertions(+) create mode 100644 include/grub/i386/freebsd_bootinfo.h diff --git ChangeLog ChangeLog index c38917b..b717a2d 100644 --- ChangeLog +++ ChangeLog @@ -1,3 +1,12 @@ +2014-12-30 Kris Moore <k...@pcbsd.org> + * grub-core/loader/i386/bsd.c: Set FreeBSD specific ACPI hints when booting + in EFI mode + * grub-core/loader/i386/bsd.c: Add default FreeBSD EFI video mode, and + structure to pass information into EFI booted kernel + * 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 + 2014-12-09 Andrei Borzenkov <arvidj...@gmail.com> * grub-core/term/serial.c (grub_cmd_serial): Fix --rtscts diff --git grub-core/loader/i386/bsd.c grub-core/loader/i386/bsd.c index 8f691e0..9d51cff 100644 --- grub-core/loader/i386/bsd.c +++ grub-core/loader/i386/bsd.c @@ -42,12 +42,14 @@ GRUB_MOD_LICENSE ("GPLv3+"); #include <grub/video.h> +#include <grub/acpi.h> #ifdef GRUB_MACHINE_PCBIOS #include <grub/machine/biosnum.h> #endif #ifdef GRUB_MACHINE_EFI #include <grub/efi/efi.h> #define NETBSD_DEFAULT_VIDEO_MODE "800x600" +#define FREEBSD_DEFAULT_VIDEO_MODE "800x600" #else #define NETBSD_DEFAULT_VIDEO_MODE "text" #include <grub/i386/pc/vbe.h> @@ -584,6 +586,72 @@ 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.pitch / mode_info.bytes_per_pixel; + + efifb.fb_addr = (grub_addr_t) framebuffer; + efifb.fb_size = ALIGN_UP (mode_info.pitch * efifb.fb_height, 65536); + + if ( mode_info.blue_field_pos == 16 ) { + efifb.fb_mask_red = 0x000000ff; + efifb.fb_mask_green = 0x0000ff00; + efifb.fb_mask_blue = 0x00ff0000; + } + + if ( mode_info.blue_field_pos == 0 ) { + efifb.fb_mask_red = 0x00ff0000; + efifb.fb_mask_green = 0x0000ff00; + efifb.fb_mask_blue = 0x000000ff; + } + + efifb.fb_mask_reserved = 0xff000000; + + 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) { @@ -602,6 +670,55 @@ grub_freebsd_boot (void) bi.boot_device = freebsd_biosdev; +#ifdef GRUB_MACHINE_EFI + /* When booting in EFI mode, we need to export some additional kernel ACPI hints */ + struct grub_acpi_rsdp_v10 *v1; + struct grub_acpi_rsdp_v20 *v2; + v1 = grub_acpi_get_rsdpv1 (); + v2 = grub_acpi_get_rsdpv2 (); + if (v2 && v2->length > 40) + v2 = 0; + + int revision; + char acpiBuf[24]; + + if (v1) + { + revision = v1->revision; + if ( revision == 0 ) + revision = 1; + grub_snprintf (acpiBuf, sizeof (acpiBuf), "%d", revision); + grub_env_set("kFreeBSD.hint.acpi.0.revision", acpiBuf); + + grub_snprintf (acpiBuf, sizeof (acpiBuf), "%s", v1->oemid); + grub_env_set("kFreeBSD.hint.acpi.0.oem", acpiBuf); + + grub_snprintf (acpiBuf, sizeof (acpiBuf), "0x%016x", v1->rsdt_addr); + grub_env_set("kFreeBSD.hint.acpi.0.rsdt", acpiBuf); + + grub_snprintf (acpiBuf, sizeof (acpiBuf), "0x%016llx", (unsigned long long)v1); + grub_env_set("kFreeBSD.hint.acpi.0.rsdp", acpiBuf); + } + + if (v2) + { + revision = v2->rsdpv1.revision; + if ( revision == 0 ) + revision = 1; + + grub_snprintf (acpiBuf, sizeof (acpiBuf), "%d", revision); + grub_env_set("kFreeBSD.hint.acpi.0.revision", acpiBuf); + + grub_snprintf (acpiBuf, sizeof (acpiBuf), "0x%016llx", (unsigned long long)v2->xsdt_addr); + grub_env_set("kFreeBSD.hint.acpi.0.xsdt", acpiBuf); + + grub_snprintf (acpiBuf, sizeof (acpiBuf), "%d", v2->length); + grub_env_set("kFreeBSD.hint.acpi.0.xsdt_length", acpiBuf); + } + + +#endif + p_size = 0; FOR_SORTED_ENV (var) if ((grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var->name[sizeof("kFreeBSD.") - 1])) @@ -687,6 +804,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 +837,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 +1684,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 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 <grub/i386/netbsd_reboot.h> #include <grub/i386/openbsd_reboot.h> #include <grub/i386/freebsd_linker.h> +#include <grub/i386/freebsd_bootinfo.h> #include <grub/i386/netbsd_bootinfo.h> #include <grub/i386/openbsd_bootarg.h> 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 <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> + +#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; +}; -- 2.2.1
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel