Blame SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch

d1e1c8
From 55163bc82c5179adb109c3d8b982c2689d68b4c9 Mon Sep 17 00:00:00 2001
d1e1c8
From: Ivan Hu <ivan.hu@canonical.com>
d1e1c8
Date: Fri, 10 May 2019 17:50:12 +0800
d1e1c8
Subject: [PATCH 39/62] MokManager: console mode modification for hi-dpi screen
d1e1c8
 devices
d1e1c8
d1e1c8
There are lots of hi-dpi laptops nowadays, as doing mok enrollment, the font
d1e1c8
is too small to see.
d1e1c8
https://bugs.launchpad.net/ubuntu/+source/shim/+bug/1822043
d1e1c8
d1e1c8
This patch checks if the resolution is larger than Full HD (1920x1080) and
d1e1c8
current console output columns and rows is in a good mode. Then swith the
d1e1c8
console output to a better mode.
d1e1c8
d1e1c8
Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
d1e1c8
Upstream-commit-id: cf05af6d899
d1e1c8
---
d1e1c8
 MokManager.c      |   2 +
d1e1c8
 lib/console.c     | 161 +++++++++++++++++++++++++++++++++++++++++++++-
d1e1c8
 include/console.h |   2 +
d1e1c8
 3 files changed, 164 insertions(+), 1 deletion(-)
d1e1c8
d1e1c8
diff --git a/MokManager.c b/MokManager.c
d1e1c8
index 30192c16789..78da9fd95ee 100644
d1e1c8
--- a/MokManager.c
d1e1c8
+++ b/MokManager.c
d1e1c8
@@ -2560,6 +2560,8 @@ EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * systab)
d1e1c8
 
d1e1c8
 	setup_rand();
d1e1c8
 
d1e1c8
+	console_mode_handle();
d1e1c8
+
d1e1c8
 	efi_status = check_mok_request(image_handle);
d1e1c8
 
d1e1c8
 	console_fini();
d1e1c8
diff --git a/lib/console.c b/lib/console.c
d1e1c8
index 3aee41cd276..c92d27f3c86 100644
d1e1c8
--- a/lib/console.c
d1e1c8
+++ b/lib/console.c
d1e1c8
@@ -409,7 +409,166 @@ console_notify(CHAR16 *string)
d1e1c8
 	console_alertbox(str_arr);
d1e1c8
 }
d1e1c8
 
d1e1c8
-#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
d1e1c8
+void
d1e1c8
+console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode)
d1e1c8
+{
d1e1c8
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
d1e1c8
+
d1e1c8
+	if (!SavedMode) {
d1e1c8
+		console_print(L"Invalid parameter: SavedMode\n");
d1e1c8
+		return;
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	CopyMem(SavedMode, co->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE));
d1e1c8
+	co->EnableCursor(co, FALSE);
d1e1c8
+	co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
d1e1c8
+}
d1e1c8
+
d1e1c8
+void
d1e1c8
+console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode)
d1e1c8
+{
d1e1c8
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
d1e1c8
+
d1e1c8
+	co->EnableCursor(co, SavedMode->CursorVisible);
d1e1c8
+	co->SetCursorPosition(co, SavedMode->CursorColumn,
d1e1c8
+				SavedMode->CursorRow);
d1e1c8
+	co->SetAttribute(co, SavedMode->Attribute);
d1e1c8
+}
d1e1c8
+
d1e1c8
+int
d1e1c8
+console_countdown(CHAR16* title, const CHAR16* message, int timeout)
d1e1c8
+{
d1e1c8
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
d1e1c8
+	SIMPLE_INPUT_INTERFACE *ci = ST->ConIn;
d1e1c8
+	SIMPLE_TEXT_OUTPUT_MODE SavedMode;
d1e1c8
+	EFI_INPUT_KEY key;
d1e1c8
+	EFI_STATUS efi_status;
d1e1c8
+	UINTN cols, rows;
d1e1c8
+	CHAR16 *titles[2];
d1e1c8
+	int wait = 10000000;
d1e1c8
+
d1e1c8
+	console_save_and_set_mode(&SavedMode);
d1e1c8
+
d1e1c8
+	titles[0] = title;
d1e1c8
+	titles[1] = NULL;
d1e1c8
+
d1e1c8
+	console_print_box_at(titles, -1, 0, 0, -1, -1, 1, 1);
d1e1c8
+
d1e1c8
+	co->QueryMode(co, co->Mode->Mode, &cols, &rows);
d1e1c8
+
d1e1c8
+	console_print_at((cols - StrLen(message)) / 2, rows / 2, message);
d1e1c8
+	while (1) {
d1e1c8
+		if (timeout > 1)
d1e1c8
+			console_print_at(2, rows - 3,
d1e1c8
+					 L"Booting in %d seconds  ",
d1e1c8
+					 timeout);
d1e1c8
+		else if (timeout)
d1e1c8
+			console_print_at(2, rows - 3,
d1e1c8
+					 L"Booting in %d second   ",
d1e1c8
+					 timeout);
d1e1c8
+
d1e1c8
+		efi_status = WaitForSingleEvent(ci->WaitForKey, wait);
d1e1c8
+		if (efi_status != EFI_TIMEOUT) {
d1e1c8
+			/* Clear the key in the queue */
d1e1c8
+			ci->ReadKeyStroke(ci, &key);
d1e1c8
+			break;
d1e1c8
+		}
d1e1c8
+
d1e1c8
+		timeout--;
d1e1c8
+		if (!timeout)
d1e1c8
+			break;
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	console_restore_mode(&SavedMode);
d1e1c8
+
d1e1c8
+	return timeout;
d1e1c8
+}
d1e1c8
+
d1e1c8
+#define HORIZONTAL_MAX_OK 1920
d1e1c8
+#define VERTICAL_MAX_OK 1080
d1e1c8
+#define COLUMNS_MAX_OK 200
d1e1c8
+#define ROWS_MAX_OK 100
d1e1c8
+
d1e1c8
+void
d1e1c8
+console_mode_handle(VOID)
d1e1c8
+{
d1e1c8
+	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
d1e1c8
+	EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
d1e1c8
+	EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
d1e1c8
+	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
d1e1c8
+
d1e1c8
+	UINTN mode_set;
d1e1c8
+	UINTN rows = 0, columns = 0;
d1e1c8
+	EFI_STATUS efi_status = EFI_SUCCESS;
d1e1c8
+
d1e1c8
+	efi_status = gBS->LocateProtocol(&gop_guid, NULL, (void **)&gop);
d1e1c8
+	if (EFI_ERROR(efi_status)) {
d1e1c8
+		console_error(L"Locate graphic output protocol fail", efi_status);
d1e1c8
+		return;
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	Info = gop->Mode->Info;
d1e1c8
+
d1e1c8
+	/*
d1e1c8
+	 * Start verifying if we are in a resolution larger than Full HD
d1e1c8
+	 * (1920x1080). If we're not, assume we're in a good mode and do not
d1e1c8
+	 * try to change it.
d1e1c8
+	 */
d1e1c8
+	if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK &&
d1e1c8
+	    Info->VerticalResolution <= VERTICAL_MAX_OK) {
d1e1c8
+		/* keep original mode and return */
d1e1c8
+		return;
d1e1c8
+	}
d1e1c8
+
d1e1c8
+        efi_status = co->QueryMode(co, co->Mode->Mode, &columns, &rows);
d1e1c8
+	if (EFI_ERROR(efi_status)) {
d1e1c8
+		console_error(L"Console query mode fail", efi_status);
d1e1c8
+		return;
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	/*
d1e1c8
+	 * Verify current console output to check if the character columns and
d1e1c8
+	 * rows in a good mode.
d1e1c8
+	 */
d1e1c8
+	if (columns <= COLUMNS_MAX_OK && rows <= ROWS_MAX_OK) {
d1e1c8
+		/* keep original mode and return */
d1e1c8
+		return;
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	if (!console_text_mode)
d1e1c8
+		setup_console(1);
d1e1c8
+
d1e1c8
+	co->Reset(co, TRUE);
d1e1c8
+
d1e1c8
+	/*
d1e1c8
+	 * If we reached here, then we have a high resolution screen and the
d1e1c8
+	 * text too small. Try to switch to a better mode. Mode number 2 is
d1e1c8
+	 * first non standard mode, which is provided by the device
d1e1c8
+	 * manufacturer, so it should be a good mode.
d1e1c8
+	 */
d1e1c8
+	if (co->Mode->MaxMode > 2)
d1e1c8
+		mode_set = 2;
d1e1c8
+	else
d1e1c8
+		mode_set = 0;
d1e1c8
+
d1e1c8
+	efi_status = co->SetMode(co, mode_set);
d1e1c8
+	if (EFI_ERROR(efi_status) && mode_set != 0) {
d1e1c8
+		/*
d1e1c8
+		 * Set to 0 mode which is required that all output devices
d1e1c8
+		 * support at least 80x25 text mode.
d1e1c8
+		 */
d1e1c8
+		mode_set = 0;
d1e1c8
+		efi_status = co->SetMode(co, mode_set);
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	co->ClearScreen(co);
d1e1c8
+
d1e1c8
+	if (EFI_ERROR(efi_status)) {
d1e1c8
+		console_error(L"Console set mode fail", efi_status);
d1e1c8
+	}
d1e1c8
+
d1e1c8
+	return;
d1e1c8
+}
d1e1c8
 
d1e1c8
 /* Copy of gnu-efi-3.0 with the added secure boot strings */
d1e1c8
 static struct {
d1e1c8
diff --git a/include/console.h b/include/console.h
d1e1c8
index deb4fa3db23..9f259c71b72 100644
d1e1c8
--- a/include/console.h
d1e1c8
+++ b/include/console.h
d1e1c8
@@ -34,6 +34,8 @@ void
d1e1c8
 console_notify(CHAR16 *string);
d1e1c8
 void
d1e1c8
 console_reset(void);
d1e1c8
+void
d1e1c8
+console_mode_handle(void);
d1e1c8
 #define NOSEL 0x7fffffff
d1e1c8
 
d1e1c8
 typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL   EFI_CONSOLE_CONTROL_PROTOCOL;
d1e1c8
-- 
d1e1c8
2.26.2
d1e1c8