#include "console.h"
#include "util.h"
+#define SYSTEM_FONT_WIDTH 8
+#define SYSTEM_FONT_HEIGHT 19
+
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
return err;
}
+static UINT64 text_area_from_font_size(void) {
+ EFI_STATUS err;
+ UINT64 text_area;
+ UINTN rows, columns;
+
+ err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &columns, &rows);
+ if (EFI_ERROR(err)) {
+ columns = 80;
+ rows = 25;
+ }
+
+ text_area = SYSTEM_FONT_WIDTH * SYSTEM_FONT_HEIGHT * (UINT64)rows * (UINT64)columns;
+
+ return text_area;
+}
+
static EFI_STATUS mode_auto(UINTN *mode) {
- /* Mode number 2 is first non standard mode, which is provided by
- * the device manufacturer, so it should be a good mode.
+ const UINT32 HORIZONTAL_MAX_OK = 1920;
+ const UINT32 VERTICAL_MAX_OK = 1080;
+ const UINT64 VIEWPORT_RATIO = 10;
+ UINT64 screen_area, text_area;
+ EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_STATUS err;
+ BOOLEAN keep = FALSE;
+
+ err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
+ if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) {
+ Info = GraphicsOutput->Mode->Info;
+
+ /* Start verifying if we are in a resolution larger than Full HD
+ * (1920x1080). If we're not, assume we're in a good mode and do not
+ * try to change it. */
+ if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK && Info->VerticalResolution <= VERTICAL_MAX_OK)
+ keep = TRUE;
+ /* For larger resolutions, calculate the ratio of the total screen
+ * area to the text viewport area. If it's less than 10 times bigger,
+ * then assume the text is readable and keep the text mode. */
+ else {
+ screen_area = (UINT64)Info->HorizontalResolution * (UINT64)Info->VerticalResolution;
+ text_area = text_area_from_font_size();
+
+ if (text_area != 0 && screen_area/text_area < VIEWPORT_RATIO)
+ keep = TRUE;
+ }
+ }
+
+ if (keep) {
+ /* Just clear the screen instead of changing the mode and return. */
+ *mode = ST->ConOut->Mode->Mode;
+ uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+ return EFI_SUCCESS;
+ }
+
+ /* If we reached here, then we have a high resolution screen and the text
+ * viewport is less than 10% the screen area, so the firmware developer
+ * screwed up. Try to switch to a better mode. Mode number 2 is first non
+ * standard mode, which is provided by the device manufacturer, so it should
+ * be a good mode.
* Note: MaxMode is the number of modes, not the last mode. */
if (ST->ConOut->Mode->MaxMode > 2)
*mode = 2;