Control: tag -1 - patch Hi,
Thanks for the proposed patch but as discussed elsewhere it seemed too risky to force 32 bpp on everyone, so I went for what looked like the least risky (adding bochs.ko and cirrus.ko, manually and for the time being). Ben Hutchings <b...@decadent.org.uk> (2023-05-14): > I think the problem is this GRUB has native drivers for Bochs and > Cirrus that reprogram the framebuffer bit depth, and the kernel is then > confused about what the bit depth is supposed to be. With QXL, GRUB > doesn't have a native driver so it doesn't reconfigure the framebuffer. I've spent some time trying to reproduce these issues under UEFI but without Secure Boot, and I failed. So I've moved to learning how to sign a Linux kernel (certutil, pesign, mokutil, etc.), and I've added some debugging information in various places. Under Secure Boot, with the default QEMU driver (std aka. bochs), initialization happens via: drivers/firmware/efi/libstub/x86-stub.c and its setup_graphics() that grabs the screen info part of boot params and starts by zero-ing it: si = &boot_params->screen_info; memset(si, 0, sizeof(*si)); before trying efi_setup_gop() and setup_uga() in turn; the former being current, the latter being the old standard. Moving on to: drivers/firmware/efi/libstub/gop.c we see that its efi_setup_gop() calls setup_gop(), which in turn calls find_gop(). That last one gets hold of a suitable GOP pointer: https://uefi.org/specs/UEFI/2.10/12_Protocols_Console_Support.html#graphics-output-protocol The rest of setup_gop() then uses information contained within that structure to derive all relevant information, filling the screen_info structure. That structure is then trusted by efifb, which can do nothing else but fail miserably… The si (screen_info) is set starting here: https://elixir.bootlin.com/linux/v6.1.27/source/drivers/firmware/efi/libstub/gop.c#L534 Adding some debug, here's what I get with GRUB set to 800x600x24: info->version: 0 info->horizontal_resolution: 1024 info->vertical_resolution: 768 info->pixel_format: 1 info->pixel_information.red_mask: 0 info->pixel_information.green_mask: 0 info->pixel_information.blue_mask: 0 info->pixel_information.reserved_mask: 0 info->pixels_per_scan_line: 1024 Let's see: - Of course width, height, and pixels_per_scan_line are incorrect. - pixel_format 1 means PIXEL_BGR_RESERVED_8BIT_PER_COLOR aka PixelBlueGreenRedReserved8BitPerColor in the spec, which means: A pixel is 32-bits and byte zero represents blue, byte one represents green, byte two represents red, and byte three is reserved. This is the definition for the physical frame buffer. The byte values for the red, green, and blue components represent the color intensity. This color intensity value range from a minimum intensity of 0 to maximum intensity of 255. - And masks are all 0. So for this particular GRUB configuration to work, I've verified that fixing all those fields was leading to a correct display via efifb (having dropped bochs.ko to stick to efifb): info->horizontal_resolution = 800; info->vertical_resolution = 600; info->pixels_per_scan_line = 800; info->pixel_format = PIXEL_BIT_MASK; info->pixel_information.red_mask = 0x00ff0000; info->pixel_information.green_mask = 0x0000ff00; info->pixel_information.blue_mask = 0x000000ff; info->pixel_information.reserved_mask = 0x00000000; Setting PIXEL_BIT_MASK means masks become relevant, and bits set in those are added to determine the actual color depth, instead of an hardcoded 32, giving me (and efifb) 24. And even: efifb: mode is 800x600x24, linelength=2400, pages=1 efifb: scrolling: redraw efifb: Truecolor: size=0:8:8:8, shift=0:16:8:0 instead of the dreaded: efifb: mode is 1024x768x32, linelength=4096, pages=1 efifb: scrolling: redraw efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0 Now, where to go from here? It seems pretty clear to me at this point that the Linux kernel only relies on information that was obtained via that GOP pointer, and does its best afterward. The way the function call works seems pretty similar to what happens in GRUB, so I'd think that the problem is likely *not* in the kernel, but rather: - GRUB fails to set mode information properly. - OVMF drops the ball and return some default information. > Unfortunately, with Secure Boot we have to use a monolithic GRUB build > so I can't easily exclude video_bochs and video_cirrus to see if that > improves matters. Applying my new pesign skills on GRUB is the next step, but I have to spend some time on another topic before Bookworm… It it possible that trying to build a debug-enabled OVMF package might yield interesting results, since AFAIUI that's the one implementing the back and forth… If that's indeed the case, it should be easy to see what's written by GRUB vs. what's read by Linux? Cheers, -- Cyril Brulebois (k...@debian.org) <https://debamax.com/> D-I release manager -- Release team member -- Freelance Consultant
signature.asc
Description: PGP signature