gop: Change way preset resolution is set when fallbacking
diff --git a/stage23/drivers/gop.c b/stage23/drivers/gop.c
index a68266d5..6ed3a53d 100644
--- a/stage23/drivers/gop.c
+++ b/stage23/drivers/gop.c
@@ -33,6 +33,87 @@ static void linear_mask_to_mask_shift(
// Most of this code taken from https://wiki.osdev.org/GOP
+static bool try_mode(struct fb_info *ret, size_t mode, int width, int height, int bpp) {
+ EFI_STATUS status;
+
+ EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
+
+ uefi_call_wrapper(gBS->LocateProtocol, 3, &gop_guid, NULL, (void **)&gop);
+
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
+ UINTN mode_info_size;
+
+ status = uefi_call_wrapper(gop->QueryMode, 4,
+ gop, mode, &mode_info_size, &mode_info);
+
+ if (status)
+ return false;
+
+ switch (mode_info->PixelFormat) {
+ case PixelBlueGreenRedReserved8BitPerColor:
+ ret->framebuffer_bpp = 32;
+ ret->red_mask_size = 8;
+ ret->red_mask_shift = 16;
+ ret->green_mask_size = 8;
+ ret->green_mask_shift = 8;
+ ret->blue_mask_size = 8;
+ ret->blue_mask_shift = 0;
+ break;
+ case PixelRedGreenBlueReserved8BitPerColor:
+ ret->framebuffer_bpp = 32;
+ ret->red_mask_size = 8;
+ ret->red_mask_shift = 0;
+ ret->green_mask_size = 8;
+ ret->green_mask_shift = 8;
+ ret->blue_mask_size = 8;
+ ret->blue_mask_shift = 16;
+ break;
+ case PixelBitMask:
+ ret->framebuffer_bpp = linear_masks_to_bpp(
+ mode_info->PixelInformation.RedMask,
+ mode_info->PixelInformation.GreenMask,
+ mode_info->PixelInformation.BlueMask,
+ mode_info->PixelInformation.ReservedMask);
+ linear_mask_to_mask_shift(&ret->red_mask_size,
+ &ret->red_mask_shift,
+ mode_info->PixelInformation.RedMask);
+ linear_mask_to_mask_shift(&ret->green_mask_size,
+ &ret->green_mask_shift,
+ mode_info->PixelInformation.GreenMask);
+ linear_mask_to_mask_shift(&ret->blue_mask_size,
+ &ret->blue_mask_shift,
+ mode_info->PixelInformation.BlueMask);
+ break;
+ default:
+ panic("gop: Invalid PixelFormat");
+ }
+
+ if (width != 0 && height != 0 && bpp != 0) {
+ if ((int)mode_info->HorizontalResolution != width
+ || (int)mode_info->VerticalResolution != height
+ || (int)ret->framebuffer_bpp != bpp)
+ return false;
+ }
+
+ print("gop: Found matching mode %x, attempting to set...\n", mode);
+
+ status = uefi_call_wrapper(gop->SetMode, 2, gop, mode);
+
+ if (status) {
+ print("gop: Failed to set video mode %x, moving on...\n", mode);
+ return false;
+ }
+
+ ret->memory_model = 0x06;
+ ret->framebuffer_addr = gop->Mode->FrameBufferBase;
+ ret->framebuffer_pitch = gop->Mode->Info->PixelsPerScanLine * 4;
+ ret->framebuffer_width = gop->Mode->Info->HorizontalResolution;
+ ret->framebuffer_height = gop->Mode->Info->VerticalResolution;
+
+ return true;
+}
+
bool init_gop(struct fb_info *ret,
uint16_t target_width, uint16_t target_height, uint16_t target_bpp) {
EFI_STATUS status;
@@ -57,24 +138,15 @@ bool init_gop(struct fb_info *ret,
panic("gop: Initialisation failed");
}
+ size_t preset_mode = gop->Mode->Mode;
+
struct resolution fallback_resolutions[] = {
- { 0, 0, 0 }, // Overwritten by preset resolution
+ { 0, 0, 0 }, // Overridden by preset mode
{ 1024, 768, 32 },
{ 800, 600, 32 },
{ 640, 480, 32 }
};
- uefi_call_wrapper(gop->QueryMode, 4,
- gop, gop->Mode->Mode, &mode_info_size, &mode_info);
-
- fallback_resolutions[0].width = mode_info->HorizontalResolution;
- fallback_resolutions[0].height = mode_info->VerticalResolution;
- fallback_resolutions[0].bpp = linear_masks_to_bpp(
- mode_info->PixelInformation.RedMask,
- mode_info->PixelInformation.GreenMask,
- mode_info->PixelInformation.BlueMask,
- mode_info->PixelInformation.ReservedMask);
-
UINTN modes_count = gop->Mode->MaxMode;
size_t current_fallback = 0;
@@ -103,75 +175,18 @@ bool init_gop(struct fb_info *ret,
retry:
for (size_t i = 0; i < modes_count; i++) {
- status = uefi_call_wrapper(gop->QueryMode, 4,
- gop, i, &mode_info_size, &mode_info);
-
- if (status)
- continue;
-
- switch (mode_info->PixelFormat) {
- case PixelBlueGreenRedReserved8BitPerColor:
- ret->framebuffer_bpp = 32;
- ret->red_mask_size = 8;
- ret->red_mask_shift = 16;
- ret->green_mask_size = 8;
- ret->green_mask_shift = 8;
- ret->blue_mask_size = 8;
- ret->blue_mask_shift = 0;
- break;
- case PixelRedGreenBlueReserved8BitPerColor:
- ret->framebuffer_bpp = 32;
- ret->red_mask_size = 8;
- ret->red_mask_shift = 0;
- ret->green_mask_size = 8;
- ret->green_mask_shift = 8;
- ret->blue_mask_size = 8;
- ret->blue_mask_shift = 16;
- break;
- case PixelBitMask:
- ret->framebuffer_bpp = linear_masks_to_bpp(
- mode_info->PixelInformation.RedMask,
- mode_info->PixelInformation.GreenMask,
- mode_info->PixelInformation.BlueMask,
- mode_info->PixelInformation.ReservedMask);
- linear_mask_to_mask_shift(&ret->red_mask_size,
- &ret->red_mask_shift,
- mode_info->PixelInformation.RedMask);
- linear_mask_to_mask_shift(&ret->green_mask_size,
- &ret->green_mask_shift,
- mode_info->PixelInformation.GreenMask);
- linear_mask_to_mask_shift(&ret->blue_mask_size,
- &ret->blue_mask_shift,
- mode_info->PixelInformation.BlueMask);
- break;
- default:
- panic("gop: Invalid PixelFormat");
- }
-
- if (mode_info->HorizontalResolution != target_width
- || mode_info->VerticalResolution != target_height
- || ret->framebuffer_bpp != target_bpp)
- continue;
-
- print("gop: Found matching mode %x, attempting to set...\n", i);
-
- status = uefi_call_wrapper(gop->SetMode, 2, gop, i);
-
- if (status) {
- print("gop: Failed to set video mode %x, moving on...\n", i);
- continue;
- }
+ if (try_mode(ret, i, target_width, target_height, target_bpp))
+ return true;
+ }
- ret->memory_model = 0x06;
- ret->framebuffer_addr = gop->Mode->FrameBufferBase;
- ret->framebuffer_pitch = gop->Mode->Info->PixelsPerScanLine * 4;
- ret->framebuffer_width = gop->Mode->Info->HorizontalResolution;
- ret->framebuffer_height = gop->Mode->Info->VerticalResolution;
+fallback:
+ if (current_fallback == 0) {
+ if (try_mode(ret, preset_mode, 0, 0, 0))
+ return true;
- return true;
+ current_fallback++;
}
-fallback:
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
target_width = fallback_resolutions[current_fallback].width;
target_height = fallback_resolutions[current_fallback].height;
