Page 2 of 2

Re: EFI GOP lying about screen resolution?

Posted: Thu Mar 14, 2024 2:45 am
by linuxyne
zaval wrote: To linuxine. You overcomplicated all heavily.
I try to cover as much ground as possible.
zaval wrote: There is no "text" mode in UEFI.
UEFI hasn't deprecated/outlawed text-mode. In fact, the spec requires all output
devices to implement 80x25 text-mode, at least.

STOP explicitly says it is meant for controlling "text-based ConsoleOut device".

GOP says:
"A unique Graphics Output protocol must represent each video frame buffer in
the system that is driven out to one or more video output devices."

The spec does not mandate that the ConOut be based on a frame-buffer, or
have its framebuffer be the same as, the GOP provided framebuffer.

Hence, it should be okay for the firmware to expose the VGA text-mode as ConOut,
or to utilize a ConOut framebuffer different in size than that setup by GOP.
In both of these cases, either ConsoleControlProtocol.SetMode, or GOP.SetMode,
or LocateProtocol for GOP, or some other out-of-band indication is required, in
order to inform the firmware that its client wants to switch away from the
ConOut.

I think CCP must have been introduced specifically for this purpose: switching
between text-mode and graphics-mode.

Intel's Dxe graphics-driver [1] from the now-deprecated EDK1 further
distinguishes between "text-based STO" and "video/GOP/UGA based STO".
Such a differentiation seems reasonable given the spec. They rely on
ConsoleControlProtocol to switch their screens b/w text and graphics mode.

VMware [2] also implements and utilizes ConsoleControlProtocol in order to
switch their virtual screens b/w text and graphics mode.

zaval wrote: The spec doesn't require from loaders to worry about STOP and GOP coexistence. If there are no bugs, they coexist normally.
Given that Windows has no troubles with its bootup screens on this laptop, do we
think it assumes that STOP and GOP coexist? If it did, it would have run into
the same problem as belliash and limine did.

STOP isn't necessarily pixel-addressible, while GOP is. They cannot be assumed
to coexist on a single output device.
---

Does the firmware on this laptop implement the ConsoleControlProtocol? If so,
it can be instructed to switch the screen b/w graphics and text mode. Although
this is non-std, it seems that many loaders including grub, rEFInd, systemd-boot
do check for CCP, and behave accordingly.

Nevertheless, drawing the fonts ourselves after an explicit GOP.SetMode
shouldn't be too hard.

---
Edit: edk2 has "Graphics Console Driver" [3], that consumes GOP and produces
an STOP. But this is specifically implemented as such; it does not rely on the
assumption that GOP and STOP coexist on the same output device.

Its source is at [4].

----
Edit2: limine thinks that Gop.QueryMode can return EFI_NOT_STARTED.
But the UEFI 2.10 (latest at this time) spec shows only
EFI_SUCCESS, EFI_DEVICE_ERROR, or EFI_INVALID_PARAMETER
as return values for Gop.QueryMode. The limine loader itself isn't
following the spec!

belliash's comment about requiring EFI_NOT_STARTED is based on
what?

Does the spec mandate that a mode must be "active" on the display to
be able to query it? I think not.
----


[1] https://android.googlesource.com/device ... hics.c#416
[2] https://communities.vmware.com/t5/VMwar ... d-p/864677
[3] https://github.com/tianocore-docs/edk2- ... drivers.md
[4] https://github.com/tianocore/edk2/tree/ ... ConsoleDxe

Re: EFI GOP lying about screen resolution?

Posted: Thu Mar 14, 2024 5:23 pm
by zaval
linuxyne wrote:
zaval wrote: There is no "text" mode in UEFI.
UEFI hasn't deprecated/outlawed text-mode. In fact, the spec requires all output
devices to implement 80x25 text-mode, at least.

STOP explicitly says it is meant for controlling "text-based ConsoleOut device".

GOP says:
"A unique Graphics Output protocol must represent each video frame buffer in
the system that is driven out to one or more video output devices."

The spec does not mandate that the ConOut be based on a frame-buffer, or
have its framebuffer be the same as, the GOP provided framebuffer.

Hence, it should be okay for the firmware to expose the VGA text-mode as ConOut,
or to utilize a ConOut framebuffer different in size than that setup by GOP.
In both of these cases, either ConsoleControlProtocol.SetMode, or GOP.SetMode,
or LocateProtocol for GOP, or some other out-of-band indication is required, in
order to inform the firmware that its client wants to switch away from the
ConOut.
But those words are descriptions what the protocols are in essence, it's not refering to assumed hardware internals. For UEFI, there is no VGA text mode and graphical mode of some hardware. The protocol you are constantly referring to (CCP) doesn't even exist in the spec (>2.xx). STOP and GOP are abstractions. the 1st represents an 2D array of characters, the latter 2D array of pixels on a linear buffer. No further assumptions on the internal organization. No VGA stuff. STOP's SetMode sets matrix width/height in characters, GOP's one is more low level and operates on pixel resolution. If you use a STOP
instance and GOP instance on the same output device, the mode in effect would be that set by the last call to GOP.SetMode for pixels and by STOP.SetMode for characters. ConOut is mutiinstance, it sends STOP based output to many devices, including GOP capable display system and text only serial (terminal) connection.

GOP and STOP coexist in the straight sense, that fw allows you to both print text (via ConOut e.g.) to a monitor and paint/draw your stuff to the same monitor at the same time. there is never any prohibition (nor preparation) on doing so. except maybe self censoring. :D

The belliash case is a fw bug. it really lies about what exactly resolution the FB is in. What is the cause of this, only the bug introducers know, but it's not sure, even they do.
I think CCP must have been introduced specifically for this purpose: switching
between text-mode and graphics-mode.
Forget this outdated or non-standard invention, it only makes further confusions.
This is what I wanted to disagree with: again there is no such a "switching" in UEFI. You can you use both. All you need is to get a corresponding protocol instance. ConOut is particularly not very useful because of being noisy - it broadcasts its output to all suitable out devices, trashing cuteness on the screen, so I for example specifically search a STOP instance on a serial interface to send there trace print, leaving the display for the Boot Screen.

The only switches in UEFI are between modes, for both text and pixel resolutions. The former is being done via STOP.SetMode the latter via GOP.SetMode.
zaval wrote: The spec doesn't require from loaders to worry about STOP and GOP coexistence. If there are no bugs, they coexist normally.
Given that Windows has no troubles with its bootup screens on this laptop, do we
think it assumes that STOP and GOP coexist? If it did, it would have run into
the same problem as belliash and limine did.
As I've said, Windows loader most probably, knowing the oddities of implementations, explicitly requests available resolutions (GOP ones) and sets what it likes. This is what I suggested to belliash as well. Or even using some BIOS compatibility magic.

It's not the 1st time when Windows loader works when your one doesn't no matter, how hard it followed the spec. We discussed recently a similar bug with that Device Path Protocol-less handle for one of 2 GOP instances. On my HP Probook 4530s, this thing doesn't want to draw, while reporting success on Blt() calls. Windows's loader does draw successfully. After picking the other, DPP containing handle and using its GOP instance, the drawing appears on the screen. For the former, it appears only after the loader exits to firmware back! :lol: And btw, both GOP instances report the same FB base! So, it's a bug. Just like here.
STOP isn't necessarily pixel-addressible, while GOP is. They cannot be assumed
to coexist on a single output device.
They can be assumed to coexist. And ConOut variable is the proof. It is an embodiment of their coexistence on your main monitor. That's why you can use STOP printing and GOP painting to your display in parallel. Note, this simultaneous usage works in a vast majority of cases, so isn't it a practical proof that it is supposed to be so, if the spec formulations aren't clear enough for you? STOP isn't pixel addressable at all. It's characted based, but it doesn't expose any VGA-isms to you, it's just an abstract 2D matrix of characters. The only "control" is the already mention setting different text resolutions. ah and fooling around with colors. Apparently STOP is made atop of GOP. At least from the logical perspective.
Edit: edk2 has "Graphics Console Driver" [3], that consumes GOP and produces
an STOP. But this is specifically implemented as such; it does not rely on the
assumption that GOP and STOP coexist on the same output device.
It's rather a proof of my above conclusions on their relations. This "specificalty" is a logical consequence.
Modern hardware doesn't use VGA, but rather some flat linear pixel buffers, so you first implement GOP,
and then produce STOP, that consumes GOP.

Re: EFI GOP lying about screen resolution?

Posted: Thu Mar 14, 2024 7:29 pm
by eekee
zaval wrote:It's not the 1st time when Windows loader works when your one doesn't no matter, how hard it followed the spec. We discussed recently a similar bug with that Device Path Protocol-less handle for one of 2 GOP instances. On my HP Probook 4530s, this thing doesn't want to draw, while reporting success on Blt() calls. Windows's loader does draw successfully. After picking the other, DPP containing handle and using its GOP instance, the drawing appears on the screen. For the former, it appears only after the loader exits to firmware back! :lol: And btw, both GOP instances report the same FB base! So, it's a bug. Just like here.
This looks like buffered io needing the io channel to be flushed before you see results. I don't do UEFI so I have no idea if there is a flush call.

Re: EFI GOP lying about screen resolution?

Posted: Fri Mar 15, 2024 5:22 pm
by linuxyne
Thank you @zaval.

I understood that STOP-over-GOP is how the vast majority of the firmware
(including the one on this laptop) choose to implement STOP, perhaps
because the implementation is readily available with edk2. This is the way
STOP and GOP coexist on the same output device. But this coexistence
binds together the modes of ConOut and GOP. This binding seems to
be broken on this laptop.

A workaround to try:
Since xtldr wants 80x25 mode on ConOut, whose corresponding mode on GOP is
640x480, xtldr can explicitly and unconditionally execute GOP.SetMode to select
640x480, and then explicitly and unconditionally execute ConOut.SetMode to
select 80x25.

Another workaround to try:
An alternative is to execute ConOut.SetMode (128x40), which is the resolution
in characters for a frame-buffer of 1024x768 pixels. Hopefully, this forces the
display resolution to change from the current 640x480 to 1024x768 to match
with the GOP's current mode.

Yet another workaround to try is to go along with the default GOP and STOP
modes chosen by the firmware (provided that the binding is intact right from
the get go).

As a last resort, rely completely on GOP and do our own font rendering.

Re: EFI GOP lying about screen resolution?

Posted: Fri Mar 15, 2024 6:10 pm
by eekee
640x480 is wrong for 80x25, it doesn't fit neatly at all. Given 8x16 pixel characters, you get 30 lines in that mode. If you really want 25 lines, your lines will be 19 pixels high, with 5 pixels left over at the top or bottom. Perhaps good UEFI implementations insert padding between lines, but it's not hard to imagine a poor implementation just making a mess or refusing to work. The alternative for 25 lines is to ask for 640x400 or 720x400, but these modes don't have square pixels.

Re: EFI GOP lying about screen resolution?

Posted: Fri Mar 15, 2024 8:23 pm
by Octocontrabass
UEFI specifies 8x19 characters, not 8x16.

Re: EFI GOP lying about screen resolution?

Posted: Sun Mar 17, 2024 1:42 am
by belliash
linuxyne wrote:A workaround to try:
Since xtldr wants 80x25 mode on ConOut, whose corresponding mode on GOP is
640x480, xtldr can explicitly and unconditionally execute GOP.SetMode to select
640x480, and then explicitly and unconditionally execute ConOut.SetMode to
select 80x25.
In this specific case, 80x25 is set by default, while GOP reports 1024x768 and forcing 80x25 text mode has no real effect.
I have chosen another workaround. I will let user choose screen resolution, like other bootloaders does, and set it before invoking kernel.
On the other side, if user does not specify custom mode, I will still do it. This time I will simply reset current mode, by temporarily switching to lowest supported screen resolution and then immediately switching back to native (default) mode.

Re: EFI GOP lying about screen resolution?

Posted: Mon May 27, 2024 3:43 pm
by 0Nera
My Limine also behaves on UEFI. From the bootloader I get a screen resolution lower than the GOP setting.
I can't change the screen resolution via GOP because Limine disables boot services after initialization

Re: EFI GOP lying about screen resolution?

Posted: Mon May 27, 2024 11:22 pm
by belliash
I think Limine allows you to choose screen resolution, you just need to add some parameter to its configuration file.

Re: EFI GOP lying about screen resolution?

Posted: Tue May 28, 2024 12:40 pm
by 0Nera
belliash wrote:I think Limine allows you to choose screen resolution, you just need to add some parameter to its configuration file.
I have added several resolutions including the resolution of the monitor itself. But I still get 3840x2160 from the loader, but this is the wrong resolution.

Here is a list of permissions that are supported by the current configuration (I got it from the loader):
[0] 3840x2160 BPP 32 MEM_MODES 1
[1] 640x480 BPP 32 MEM_MODES 1
[2] 800x600 BPP 32 MEM_MODES 1
[3] 1024x768 BPP 32 MEM_MODES 1
[4] 1280x720 BPP 32 MEM_MODES 1
[5] 1280x800 BPP 32 MEM_MODES 1
[6] 1280x1024 BPP 32 MEM_MODES 1
[7] 1366x768 BPP 32 MEM_MODES 1
[8] 1440x900 BPP 32 MEM_MODES 1
[9] 1400x1050 BPP 32 MEM_MODES 1
[10] 1600x1200 BPP 32 MEM_MODES 1
[11] 1680x1050 BPP 32 MEM_MODES 1
[12] 1920x1200 BPP 32 MEM_MODES 1
[13] 2048x1536 BPP 32 MEM_MODES 1