Hi Gerd, Thanks for taking a look at the patch.
On Fri, 6 May 2022 12:39:52 +0200 Gerd Hoffmann <kra...@redhat.com> wrote: > Hi, > > > On some buggy EFI firmwares, GRUB is started with the console resolution > > set to the maximum but the output console EFI object has the mode set as > > 0, which is the minimum supported mode of 80x25 characters. This causes > > strange behavior at the GRUB shell where output can fill the screen, but > > the prompt is at line 80 in the middle of the screen. > > This behavior might not be ideal, but it's clearly within the specs and > not buggy. What firmware do you talk about btw? I have only a cursory understanding of the spec and fairly new to EFI. Could you elaborate on which spec(s) and where this behavior is described? Trying to make sense of your assertion, my inexperienced reading of some relevant (but perhaps not all relevant) portions of the spec lead me to conclude that this behavior may not violate the spec because the spec isn't very clear on this. For instance, looking at the UEFI 2.9 version of the spec in section 12.4 on page 454 in table 12-4 "EFI Cursor Location/Advance Rules" there is reference to "bottom of the display". What is the display? Does being in a particular "mode" of cols x rows dimensions encompass all the pixels of the physical screen? If it doesn't, is the display all the pixels or just the ones being used for the columns x rows character output of a particular mode? Suppose that the display is just the pixels used by the particular mode, then this firmware violates the spec by allowing LF characters to advance the cursor past the end of the "display" and allow writing of GRUB generated output there. On the other hand, if the "display" is all pixels on the screen and the text mode may be a sub-rectangle of that, then OutputString allows writing outside of the columns x rows of a given mode, ie for the purposes of the cursor advance rules the firmware is considering the whole screen as the display but SetCursorPosition() is limited to a top-left section of the screen. So what would be the point of having that behavior? Just to limit SetCursorPosition() to a subset of the screen? May be you can enlighten me on the wisdom of the spec here (are there some types of hardware displays where this is useful?). Another place the spec isn't clear is in section 2.4 at the end of page 450, it says "If the output device is not in a valid text mode at the time of the EFI_BOOT_SERVICES.HandleProtocol() call, the device is to indicate that its CurrentMode is –1". But nowhere in the spec is "CurrentMode" defined and a search of the PDF shows that as the only instance of that string. If I were a betting person, I'd put my money on "CurrentMode" being the "Mode" member of the struct defined above, or ConsoleOut->Mode->Mode. It seems to me this is a bug/ambiguity in the spec. Looking at the last paragraph on 450 and assuming my guess above as to the meaning of "CurrentMode", which I could be wrong about, I considered that the paragraph could be used to justify this behavior. However, ConsoleOut->Mode->Mode == 0, not -1. So the console should be in 80x25 mode (which is kinda is). Its not clear to me that this is relevant either because GRUB only ever calls EFI_BOOT_SERVICES.HandleProtocol() on ia64 (not my architecture). So how does GRUB know whether ConsoleOut is in a valid mode or not? Do we need to call HandleProtocol() on the ConsoleOutHandle to trigger this? I would think not since ConOut is support to already be a handle to this interface. To be more verbose as to the issue I'm seeing, the computer boots to GRUB with the display resolution at native, 1920x1080, but only uses what appears to be the top left 800x600 pixels for the 80x25 text mode _initially_. So running "lsmod", for instance, uses the full height of the screen when outputing text and the screen starts scrolling at the bottom of the screen. But when it finished the GRUB shell prompt is about midway down from the top and typing overwrites some of lsmod output. Then further output gets mangled with the previous output. Going to a grub menu interface clears the screen, so I end up having to exit the shell and re-enter it to get a non-mangled display. A video of this would be worth million words. If I set the mode to some other mode and then back to mode 0, which is the mode its claims to start up in, then there appears to be a screen resolution change to 640x480 with accompanying giant font with the screen centered now instead of in the top left corner of the display. I've yet to figure out a way to get the display back into the weird, spec-compliant, mode that it starts out in. So if this is some desirable mode, why can't I get back in to it? And why does it only happen for default boot entries? In my case, my firmware behavior seems like a clear bug, I have a hard time believing that HP firmware devs would chose this behavior. Whether it violates the spec or not is a separate issue (there can be bugs that do not violate the spec). I've only seen this undesirable behavior only manifest when booting a default boot entry. When I choose via the firmware boot selection screen an EFI app to run and run the same GRUB EFI app that exhibits the issue when run from default boot selection, this does not manifest. I get the same behavior for the EDK2 EFI shell app when it is used as the default boot app. Whether its called a bug or spec-compliant mis-feature, the important point is that this is undesirable behavior for GRUB users. I considered that this may have to do with ConsoleOut and StandardError being in different modes. It seems like this might be caused by StandardError being in the maximum mode and ConsoleOut being in the minimum mode, but it turns out that EFI_BOOT_SERVICES.StdErr is NULL. This seems to violate the descriptions of StandardErrorHandle and StdErr in section 4.3, page 95. Changing the mode of ConsoleOut and not StandardError does nothing but improve the display out. I'm also curious if anyone has seen issues with the largest area text mode mode. Is there a problem with doing that this patch intends? Ultimately, I think it would be nice to have a key sequence that raises and lowers the mode so that if the largest mode is not usable for some reason, the user has a blind way out. I've created another patch to add a command called efitextmode, which is very similar to the EFI Shell's "mode" command. But that doesn't solve the issue just mentioned. The firmware I'm looking at is from Hewlett-Packard for a Zbook G2 15. > > + /* Set text-mode resolution to maximum supported */ > > + o = grub_efi_system_table->con_out; > > + for (i=0, columns_max=0, rows_max=0, mode_max=0; i < o->mode->max_mode; > > i++) > > + if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, o->mode->mode, > > + &columns, &rows) > > + && (columns_max * rows_max) < (columns * rows)) > > + mode_max = i; > > + > > + efi_call_2 (o->set_mode, o, mode_max); > > This is buggy. It find the last entry in the mode list. Which works by > pure luck because that happens to be the entry you want have in case the > list is sorted. Yep, thanks, there's a reason that coding while driving is illegal in many localities. Glenn _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel