Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Mar 2018 21:02:46 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r331464 - in head/stand: defaults efi/loader
Message-ID:  <201803232102.w2NL2kNN042501@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Fri Mar 23 21:02:46 2018
New Revision: 331464
URL: https://svnweb.freebsd.org/changeset/base/331464

Log:
  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

Modified:
  head/stand/defaults/loader.conf
  head/stand/efi/loader/framebuffer.c

Modified: head/stand/defaults/loader.conf
==============================================================================
--- head/stand/defaults/loader.conf	Fri Mar 23 20:56:18 2018	(r331463)
+++ head/stand/defaults/loader.conf	Fri Mar 23 21:02:46 2018	(r331464)
@@ -75,6 +75,9 @@ acpi_video_load="NO"		# Load the ACPI video extension 
 #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

Modified: head/stand/efi/loader/framebuffer.c
==============================================================================
--- head/stand/efi/loader/framebuffer.c	Fri Mar 23 20:56:18 2018	(r331463)
+++ head/stand/efi/loader/framebuffer.c	Fri Mar 23 21:02:46 2018	(r331464)
@@ -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_PROTOCO
 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 verbos
 	}
 }
 
+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;
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803232102.w2NL2kNN042501>