:: commit 229bc85481d47e6991ad9cbf49ac900f54aa27e4

Mintsuki <mintsuki@protonmail.com> — 2026-02-16 12:36

parents: 1f9a418511

drivers/gop: Ensure SetMode is called at least once per GOP handle

diff --git a/common/drivers/gop.c b/common/drivers/gop.c
index a66e6ffe..59fa374c 100644
--- a/common/drivers/gop.c
+++ b/common/drivers/gop.c
@@ -126,7 +126,8 @@ bool gop_force_16 = false;
 
 static bool try_mode(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
                      size_t mode, uint64_t width, uint64_t height, int bpp,
-                     struct fb_info *fbs, size_t fbs_count) {
+                     struct fb_info *fbs, size_t fbs_count,
+                     bool *setmode_called) {
     EFI_STATUS status;
 
     if (!mode_to_fb_info(ret, gop, mode)) {
@@ -157,7 +158,7 @@ static bool try_mode(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
 
     printv("gop: Found matching mode %X, attempting to set...\n", (uint64_t)mode);
 
-    if (mode == gop->Mode->Mode) {
+    if (mode == gop->Mode->Mode && *setmode_called) {
         printv("gop: Mode was already set, perfect!\n");
     } else {
         status = gop->SetMode(gop, mode);
@@ -166,6 +167,8 @@ static bool try_mode(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
             printv("gop: Failed to set video mode %X, moving on...\n", (uint64_t)mode);
             return false;
         }
+
+        *setmode_called = true;
     }
 
     // Recalculate pitch from gop->Mode->Info, as some firmware (e.g. Apple
@@ -207,6 +210,7 @@ static struct fb_info *get_mode_list(size_t *count, EFI_GRAPHICS_OUTPUT_PROTOCOL
 
 #define MAX_PRESET_MODES 128
 no_unwind static int preset_modes[MAX_PRESET_MODES];
+no_unwind static bool setmode_called[MAX_PRESET_MODES];
 no_unwind static bool preset_modes_initialised = false;
 
 void init_gop(struct fb_info **ret, size_t *_fbs_count,
@@ -214,6 +218,7 @@ void init_gop(struct fb_info **ret, size_t *_fbs_count,
     if (preset_modes_initialised == false) {
         for (size_t i = 0; i < MAX_PRESET_MODES; i++) {
             preset_modes[i] = -1;
+            setmode_called[i] = false;
         }
         preset_modes_initialised = true;
     }
@@ -286,6 +291,7 @@ void init_gop(struct fb_info **ret, size_t *_fbs_count,
             if (status) {
                 continue;
             }
+            setmode_called[i] = true;
             status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
                                     &mode_info_size, &mode_info);
         }
@@ -313,7 +319,7 @@ void init_gop(struct fb_info **ret, size_t *_fbs_count,
 
 retry:
         for (size_t j = 0; j < modes_count; j++) {
-            if (try_mode(fb, gop, j, _target_width, _target_height, _target_bpp, *ret, fbs_count)) {
+            if (try_mode(fb, gop, j, _target_width, _target_height, _target_bpp, *ret, fbs_count, &setmode_called[i])) {
                 goto success;
             }
         }
@@ -340,7 +346,7 @@ fallback:
         if (current_fallback == 1) {
             current_fallback++;
 
-            if (try_mode(fb, gop, preset_modes[i], 0, 0, 0, *ret, fbs_count)) {
+            if (try_mode(fb, gop, preset_modes[i], 0, 0, 0, *ret, fbs_count, &setmode_called[i])) {
                 goto success;
             }
         }
tab: 248 wrap: offon