aboutsummaryrefslogtreecommitdiff
path: root/stand
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2018-03-23 21:02:46 +0000
committerKyle Evans <kevans@FreeBSD.org>2018-03-23 21:02:46 +0000
commit05e8899d7d2c779b90a10d1304b493afb95fb18e (patch)
treefbdb745731e8b688ea6c87492e975cc217e7bac6 /stand
parent8dbc390581f7bf64c0a99007a1d68c147ab87581 (diff)
downloadsrc-05e8899d7d2c779b90a10d1304b493afb95fb18e.tar.gz
src-05e8899d7d2c779b90a10d1304b493afb95fb18e.zip
efi loader: Respect efi_max_resolution in loader.conf(5)
Default the max resolution to 1080p, we'll accept Width x Height specifications along with the following presets: - 480p - 720p - 1080p - 2160p or 4k - 5k PR: 224825 Differential Revision: https://reviews.freebsd.org/D14801
Notes
Notes: svn path=/head/; revision=331464
Diffstat (limited to 'stand')
-rw-r--r--stand/defaults/loader.conf3
-rw-r--r--stand/efi/loader/framebuffer.c96
2 files changed, 97 insertions, 2 deletions
diff --git a/stand/defaults/loader.conf b/stand/defaults/loader.conf
index d7908bff182e..a3b179b68178 100644
--- a/stand/defaults/loader.conf
+++ b/stand/defaults/loader.conf
@@ -75,6 +75,9 @@ acpi_video_load="NO" # Load the ACPI video extension driver
#geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root
bootenv_autolist="YES" # Auto populate the list of ZFS Boot Environments
#beastie_disable="NO" # Turn the beastie boot menu on and off
+efi_max_resolution="1080p" # Set the max resolution for EFI loader to use:
+ # 480p, 720p, 1080p, 2160p/4k, 5k, or specify
+ # WidthxHeight (e.g. 1920x1080)
#kernels="kernel kernel.old" # Kernels to display in the boot menu
#loader_logo="orbbw" # Desired logo: orbbw, orb, fbsdbw, beastiebw, beastie, none
#comconsole_speed="9600" # Set the current serial console speed
diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c
index 7b3d46ca90e3..9f95f92a5682 100644
--- a/stand/efi/loader/framebuffer.c
+++ b/stand/efi/loader/framebuffer.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <sys/endian.h>
+#include <sys/param.h>
#include <stand.h>
#include <efi.h>
@@ -45,6 +46,40 @@ static EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
static EFI_GUID pciio_guid = EFI_PCI_IO_PROTOCOL_GUID;
static EFI_GUID uga_guid = EFI_UGA_DRAW_PROTOCOL_GUID;
+static struct named_resolution {
+ const char *name;
+ const char *alias;
+ unsigned int width;
+ unsigned int height;
+} resolutions[] = {
+ {
+ .name = "480p",
+ .width = 640,
+ .height = 480,
+ },
+ {
+ .name = "720p",
+ .width = 1280,
+ .height = 720,
+ },
+ {
+ .name = "1080p",
+ .width = 1920,
+ .height = 1080,
+ },
+ {
+ .name = "2160p",
+ .alias = "4k",
+ .width = 3840,
+ .height = 2160,
+ },
+ {
+ .name = "5k",
+ .width = 5120,
+ .height = 2880,
+ }
+};
+
static u_int
efifb_color_depth(struct efi_fb *efifb)
{
@@ -462,6 +497,57 @@ print_efifb(int mode, struct efi_fb *efifb, int verbose)
}
}
+static bool
+efi_resolution_compare(struct named_resolution *res, const char *cmp)
+{
+
+ if (strcasecmp(res->name, cmp) == 0)
+ return (true);
+ if (res->alias != NULL && strcasecmp(res->alias, cmp) == 0)
+ return (true);
+ return (false);
+}
+
+
+static void
+efi_get_max_resolution(int *width, int *height)
+{
+ struct named_resolution *res;
+ char *maxres;
+ char *height_start, *width_start;
+ int idx;
+
+ *width = *height = 0;
+ maxres = getenv("efi_max_resolution");
+ /* No max_resolution set? Bail out; choose highest resolution */
+ if (maxres == NULL)
+ return;
+ /* See if it matches one of our known resolutions */
+ for (idx = 0; idx < nitems(resolutions); ++idx) {
+ res = &resolutions[idx];
+ if (efi_resolution_compare(res, maxres)) {
+ *width = res->width;
+ *height = res->height;
+ return;
+ }
+ }
+ /* Not a known resolution, try to parse it; make a copy we can modify */
+ maxres = strdup(maxres);
+ if (maxres == NULL)
+ return;
+ height_start = strchr(maxres, 'x');
+ if (height_start == NULL) {
+ free(maxres);
+ return;
+ }
+ width_start = maxres;
+ *height_start++ = 0;
+ /* Errors from this will effectively mean "no max" */
+ *width = (int)strtol(width_start, NULL, 0);
+ *height = (int)strtol(height_start, NULL, 0);
+ free(maxres);
+}
+
static int
gop_autoresize(EFI_GRAPHICS_OUTPUT *gop)
{
@@ -470,16 +556,22 @@ gop_autoresize(EFI_GRAPHICS_OUTPUT *gop)
EFI_STATUS status;
UINTN infosz;
UINT32 best_mode, currdim, maxdim, mode;
+ int height, max_height, max_width, width;
best_mode = maxdim = 0;
+ efi_get_max_resolution(&max_width, &max_height);
for (mode = 0; mode < gop->Mode->MaxMode; mode++) {
status = gop->QueryMode(gop, mode, &infosz, &info);
if (EFI_ERROR(status))
continue;
efifb_from_gop(&efifb, gop->Mode, info);
- currdim = info->HorizontalResolution * info->VerticalResolution;
- /* XXX TODO: Allow tunable or something for max resolution */
+ width = info->HorizontalResolution;
+ height = info->VerticalResolution;
+ currdim = width * height;
if (currdim > maxdim) {
+ if ((max_width != 0 && width > max_width) ||
+ (max_height != 0 && height > max_height))
+ continue;
maxdim = currdim;
best_mode = mode;
}