Page 1 of 1

Printing a message when the graphics driver fails to start

Posted: Fri Jun 15, 2018 4:19 am
by glauxosdever
Hi,


Some days ago, I decided to return to OS development. Until now, I experimented with booting from a HDD, booting from network (PXE) and booting from CD using El Torito, which I'm currently continuing. I'm planning to start from a monolithic kernel, which I'll turn into a microkernel later during development, after the interfaces between the kernel and the device drivers have been refined.

But now to the question. The bootloader can print warning/error messages using the firmware. Then, it loads the kernel and the firmware stops being functional. The kernel may not need to print anything, or it may print after the graphics driver has been started. But it may also need to warn that something failed before the graphics driver was started (in this case a log buffer would do the trick and it would be flushed after the graphics driver started, this is AFAIK something that Brendan suggests). But what if the graphics driver cannot be started for some reason? How should the kernel warn about it?

This is what I've thought about until now:
  • Have a BAL that can be used from the kernel using callback functions. The BAL reverts to real/v86 mode and uses the BIOS to print. But this doesn't work for UEFI, which stops being functional after calling ExitBootServices().
  • Use a "basic graphics driver" in the BAL that doesn't do any advanced things (like 3D acceleration, shaders and such) and only prints messages to the display in known video modes. But what if I decide that the kernel should be configurable to use other means (e.g. serial, USB drives, network, etc) to report messages? Would I turn the BAL into a monolithic kernel?
  • Ignore the display and use the second most-preferred means of reporting messages (see previous point). But what if for some reason everything fails (e.g. no serial present, no USB drives attached, unknown network card present, etc)? Of course when everything fails, the system is unusable, but knowing why it's unusable is preferable to not knowing why it's unusable.
Is there any other possibility that I've not thought about?

Thanks in advance! :-)


Regards,
glauxosdever

Re: Printing a message when the graphics driver fails to sta

Posted: Fri Jun 15, 2018 6:23 am
by iansjack
What about just switching to text mode?

Re: Printing a message when the graphics driver fails to sta

Posted: Fri Jun 15, 2018 7:16 am
by glauxosdever
Hi,


Thank you for your reply. :-)

I'm actually planning to use text mode by default (for BIOS, not sure if it exists in UEFI). So I could put printing code in the BAL (or, currently, in the kernel, although I'm not planning on having a text-mode interface for any native display driver). But, then again, what if messages should be over serial or something, should the BAL need to handle that too, and also other things? It would become too complicated.

Thank you in advance! :-)


Regards,
glauxosdever

Re: Printing a message when the graphics driver fails to sta

Posted: Fri Jun 15, 2018 9:08 am
by Brendan
glauxosdever wrote:The bootloader can print warning/error messages using the firmware. Then, it loads the kernel and the firmware stops being functional. The kernel may not need to print anything, or it may print after the graphics driver has been started. But it may also need to warn that something failed before the graphics driver was started (in this case a log buffer would do the trick and it would be flushed after the graphics driver started, this is AFAIK something that Brendan suggests). But what if the graphics driver cannot be started for some reason? How should the kernel warn about it?
I think you're missing a piece in the middle:
  • Early boot code uses firmware to display error messages; then
  • Early boot code (or kernel initialisation?) sets up some temporary "raw framebuffer" video support code
  • Later boot code does a huge number of things (which can all potentially report errors); but during this stage the "raw framebuffer" code can display the error messages
  • Even later; a video driver is started (and you have some kind of "frame buffer hand-off"); and from this point on the video driver can be used to display error messages
Note that with some careful design there are still ways to reduce the chance of unreportable failure. For example, you can split the "raw framebuffer" code into an initialisation phase that prepares things for the selected video mode (e.g. allocates double buffers, pre-renders a frame in the buffer, etc) before the video mode is switched (so that any errors that occur during this initialisation can be reported), and then do a "switch video modes and immediately be able to use it" thing after it's been safely prepared. Of course you'd also have some kind of cancellation in case you fail to set that video mode that you prepared for; and this could be in a retry loop (e.g. if you fail to set the selected video mode, cancel the prepared stuff, mark the video mode as borked so it can't be reselected, then select a new video mode and prepare for that; and keep doing that until either something worked or there's no video modes left to try).


Cheers,

Brendan

Re: Printing a message when the graphics driver fails to sta

Posted: Fri Jun 15, 2018 11:19 am
by glauxosdever
Hi,


I initially excluded "raw framebuffer", partly because I expected some native video driver to set up a good video mode (instead of covering the initial lack of drivers with a framebuffer), partly because on some old computers VESA/VBE may not be supported (and I'd need additional code for VGA instead) and partly because having boot code handle all of the complexity needed for setting up a good video mode that native drivers could instead handle themselves would turn the bootloader into a massive component.

But maybe having a framebuffer is better than having a "native" VGA driver ("native" is inside quotes because I don't consider a VGA driver native for an e.g. Intel GPU, but not having a framebuffer would make it more apparent that a native driver is needed and it would motivate me better to write one). Maybe if VESA/VBE is unsupported, it's fine not to support that computer (or fallback to VGA). Maybe it's fine to have the boot code query EDID and check which modes can be safely set. And for UEFI, where text mode doesn't exist AFAIK, I'd still need to set up a framebuffer. So I'll probably go with setting up a framebuffer and support drawing to it using callback functions to the BAL.

Thank you everyone! :-)


Regards,
glauxosdever

Re: Printing a message when the graphics driver fails to sta

Posted: Fri Jun 15, 2018 12:02 pm
by Brendan
Hi,
glauxosdever wrote:I initially excluded "raw framebuffer", partly because I expected some native video driver to set up a good video mode (instead of covering the initial lack of drivers with a framebuffer), partly because on some old computers VESA/VBE may not be supported (and I'd need additional code for VGA instead) and partly because having boot code handle all of the complexity needed for setting up a good video mode that native drivers could instead handle themselves would turn the bootloader into a massive component.

But maybe having a framebuffer is better than having a "native" VGA driver ("native" is inside quotes because I don't consider a VGA driver native for an e.g. Intel GPU, but not having a framebuffer would make it more apparent that a native driver is needed and it would motivate me better to write one). Maybe if VESA/VBE is unsupported, it's fine not to support that computer (or fallback to VGA).
For "no VBE" (assuming BIOS) I fall back to the older "int 0x10" BIOS function; but I only support graphics modes that have a linear frame buffer which excludes everything except 300*200 with 256 colours. For "no UGA and no GOP" (assuming UEFI) and for "no VGA or better video card" (for BIOS) I treat it as a headless system (different beeps so you have some idea of how far it got, serial port output, ...).

For "no EDID" (including none explicitly included and configured by the user to be used as a work-around) I restrict it to VESA's Safe Mode Timing (which is mostly just the 640*480 timing used by VGA anyway); so the best you can hope for in that case is 640*480 with 16 million colours.
glauxosdever wrote:Maybe it's fine to have the boot code query EDID and check which modes can be safely set.
For this; I get the EDID and do some relatively insane shenanigans to try to make ensure I only set the best and most likely to be supported video modes; but VBE doesn't give you timings and it's impossible to provide guarantees (e.g. VBE might say there's a "640 * 480 with 16 million colours" video mode, but you can't know if it's 60 Hz, 90 Hz, 120 Hz, and even then you can't know if it's a relatively standard timing for that refresh rate or something entirely bizarre).

In theory; for UEFI (UGA and GOP) the firmware is supposed to make sure that only video modes that the monitor supports are mentioned, so in theory you don't need to check. However, without parsing the EDID there's no way to figure out things like (e.g.) if a video mode matches the monitor's preferred resolution (and more complex stuff, like which colour space the monitor uses); and if you have the code (for BIOS) anyway then there's little harm in treating UEFI the same as BIOS.
glauxosdever wrote:And for UEFI, where text mode doesn't exist AFAIK, I'd still need to set up a framebuffer. So I'll probably go with setting up a framebuffer and support drawing to it using callback functions to the BAL.
The other thing that might be worth mentioning is that (unlike VBE) UEFI is able to support multiple monitors. During boot it'd be nice to setup a raw frame buffer for however monitors are present, and display the same thing on all monitors throughout boot (and be able to handle multiple monitors after boot when there isn't any native video driver).


Cheers,

Brendan

Re: Printing a message when the graphics driver fails to sta

Posted: Fri Jun 15, 2018 2:13 pm
by glauxosdever
Hi,


I read that querying EDID is rather complex. Don't get me wrong, I want to eventually do it, but only after implementing some kernel internals and some basic drivers. I don't think perfecting the boot code before having started developing the kernel makes much sense. It's all about the order I'd like to implement features.

So would it make sense to initially implement some VGA fallback that can also be used after querying EDID is implemented, in cases where EDID isn't supported and VESA/VBE isn't supported either (in cases you use "mode 13")? I'd use "mode 12" though, as it's more suitable for printing text (it has more rows and columns and the number of colours is not important).

Thank you in advance! :-)


Regards,
glauxosdever