diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2018-03-23 21:02:46 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2018-03-23 21:02:46 +0000 |
commit | 05e8899d7d2c779b90a10d1304b493afb95fb18e (patch) | |
tree | fbdb745731e8b688ea6c87492e975cc217e7bac6 /stand | |
parent | 8dbc390581f7bf64c0a99007a1d68c147ab87581 (diff) | |
download | src-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.conf | 3 | ||||
-rw-r--r-- | stand/efi/loader/framebuffer.c | 96 |
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; } |