:: commit 0f703612815792078f93f96bacd6feab8210aecf

mintsuki <mintsuki@protonmail.com> — 2022-11-14 06:29

parents: 2200f373ac

gop: Use ConOut to obtain GOP whenever possible

diff --git a/common/drivers/edid.c b/common/drivers/edid.c
index 5fcb05a3..3ee60ea7 100644
--- a/common/drivers/edid.c
+++ b/common/drivers/edid.c
@@ -1,5 +1,6 @@
 #include <stdint.h>
 #include <stddef.h>
+#include <drivers/gop.h>
 #include <drivers/edid.h>
 #include <mm/pmm.h>
 #include <lib/misc.h>
@@ -50,32 +51,18 @@ success:
 #include <efi.h>
 
 struct edid_info_struct *get_edid_info(void) {
+    if (!gop_ready) {
+        goto fail;
+    }
+
     struct edid_info_struct *buf = ext_mem_alloc(sizeof(struct edid_info_struct));
 
     EFI_STATUS status;
 
-    EFI_HANDLE tmp_handles[1];
-
-    EFI_HANDLE *handles = tmp_handles;
-    UINTN handles_size = sizeof(EFI_HANDLE);
-    EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
-
-    status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
-
-    if (status != EFI_SUCCESS && status != EFI_BUFFER_TOO_SMALL)
-        goto fail_n;
-
-    handles = ext_mem_alloc(handles_size);
-
-    status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
-
-    if (status)
-        goto fail;
-
     EFI_EDID_ACTIVE_PROTOCOL *edid = NULL;
     EFI_GUID edid_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID;
 
-    status = gBS->HandleProtocol(handles[0], &edid_guid, (void **)&edid);
+    status = gBS->HandleProtocol(gop_handle, &edid_guid, (void **)&edid);
 
     if (status)
         goto fail;
@@ -90,13 +77,10 @@ struct edid_info_struct *get_edid_info(void) {
             goto success;
 
 fail:
-    pmm_free(handles, handles_size);
-fail_n:
     printv("edid: Could not fetch EDID data.\n");
     return NULL;
 
 success:
-    pmm_free(handles, handles_size);
     printv("edid: Success.\n");
     return buf;
 }
diff --git a/common/drivers/gop.c b/common/drivers/gop.c
index 7267d4ec..4f6a8e67 100644
--- a/common/drivers/gop.c
+++ b/common/drivers/gop.c
@@ -37,7 +37,7 @@ static void linear_mask_to_mask_shift(
 
 // Most of this code taken from https://wiki.osdev.org/GOP
 
-static bool mode_to_fb_info(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, struct fb_info *ret, size_t mode) {
+static bool mode_to_fb_info(struct fb_info *ret, size_t mode) {
     EFI_STATUS status;
 
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
@@ -98,11 +98,10 @@ static bool mode_to_fb_info(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, struct fb_info *r
 
 bool gop_force_16 = false;
 
-static bool try_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
-                     struct fb_info *ret, size_t mode, uint64_t width, uint64_t height, int bpp) {
+static bool try_mode(struct fb_info *ret, size_t mode, uint64_t width, uint64_t height, int bpp) {
     EFI_STATUS status;
 
-    if (!mode_to_fb_info(gop, ret, mode)) {
+    if (!mode_to_fb_info(ret, mode)) {
         return false;
     }
 
@@ -146,36 +145,8 @@ static bool try_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
 }
 
 struct fb_info *gop_get_mode_list(size_t *count) {
-    EFI_STATUS status;
-
-    EFI_HANDLE tmp_handles[1];
-
-    EFI_HANDLE *handles = tmp_handles;
-    UINTN handles_size = sizeof(EFI_HANDLE);
-    EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
-
-    status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
-
-    if (status != EFI_SUCCESS && status != EFI_BUFFER_TOO_SMALL) {
-        return false;
-    }
-
-    handles = ext_mem_alloc(handles_size);
-
-    status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
-    if (status != EFI_SUCCESS) {
-        pmm_free(handles, handles_size);
-        return false;
-    }
-
-    EFI_HANDLE gop_handle = handles[0];
-    pmm_free(handles, handles_size);
-
-    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
-
-    status = gBS->HandleProtocol(gop_handle, &gop_guid, (void **)&gop);
-    if (status != EFI_SUCCESS) {
-        return false;
+    if (!gop_ready) {
+        return NULL;
     }
 
     UINTN modes_count = gop->Mode->MaxMode;
@@ -184,7 +155,7 @@ struct fb_info *gop_get_mode_list(size_t *count) {
 
     size_t actual_count = 0;
     for (size_t i = 0; i < modes_count; i++) {
-        if (mode_to_fb_info(gop, &ret[actual_count], i)) {
+        if (mode_to_fb_info(&ret[actual_count], i)) {
             actual_count++;
         }
     }
@@ -204,8 +175,14 @@ struct fb_info *gop_get_mode_list(size_t *count) {
 static no_unwind size_t preset_mode = INVALID_PRESET_MODE;
 static no_unwind EFI_GRAPHICS_OUTPUT_MODE_INFORMATION preset_mode_info;
 
+bool gop_ready = false;
+EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
+EFI_HANDLE gop_handle;
+
 bool init_gop(struct fb_info *ret,
               uint64_t target_width, uint64_t target_height, uint16_t target_bpp) {
+    gop_ready = false;
+
     ret->default_res = false;
 
     EFI_STATUS status;
@@ -216,6 +193,19 @@ bool init_gop(struct fb_info *ret,
     UINTN handles_size = sizeof(EFI_HANDLE);
     EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
 
+    bool using_conout = true;
+
+    status = gBS->HandleProtocol(gST->ConsoleOutHandle, &gop_guid, (void **)&gop);
+    if (status == EFI_SUCCESS) {
+        print("gop: ConOut provides GOP. Using that...\n");
+        gop_handle = gST->ConsoleOutHandle;
+        goto conout_gop;
+    }
+
+no_conout:
+    {
+    using_conout = false;
+
     status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
 
     if (status != EFI_SUCCESS && status != EFI_BUFFER_TOO_SMALL) {
@@ -230,15 +220,17 @@ bool init_gop(struct fb_info *ret,
         return false;
     }
 
-    EFI_HANDLE gop_handle = handles[0];
+    gop_handle = handles[0];
     pmm_free(handles, handles_size);
 
-    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
-
     status = gBS->HandleProtocol(gop_handle, &gop_guid, (void **)&gop);
     if (status != EFI_SUCCESS) {
         return false;
     }
+    }
+
+conout_gop:;
+    gop_ready = true;
 
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
     UINTN mode_info_size;
@@ -292,7 +284,7 @@ bool init_gop(struct fb_info *ret,
 
 retry:
     for (size_t i = 0; i < modes_count; i++) {
-        if (try_mode(gop, ret, i, target_width, target_height, target_bpp)) {
+        if (try_mode(ret, i, target_width, target_height, target_bpp)) {
             gop_force_16 = false;
             return true;
         }
@@ -323,7 +315,7 @@ fallback:
     if (current_fallback == 1) {
         current_fallback++;
 
-        if (try_mode(gop, ret, preset_mode, 0, 0, 0)) {
+        if (try_mode(ret, preset_mode, 0, 0, 0)) {
             gop_force_16 = false;
             return true;
         }
@@ -339,6 +331,9 @@ fallback:
     }
 
     gop_force_16 = false;
+    if (using_conout) {
+        goto no_conout;
+    }
     return false;
 }
 
diff --git a/common/drivers/gop.h b/common/drivers/gop.h
index 3b8afe53..32440be4 100644
--- a/common/drivers/gop.h
+++ b/common/drivers/gop.h
@@ -16,6 +16,10 @@ struct fb_info *gop_get_mode_list(size_t *count);
 
 extern bool gop_force_16;
 
+extern bool gop_ready;
+extern EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
+extern EFI_HANDLE gop_handle;
+
 #endif
 
 #endif
tab: 248 wrap: offon