Writing to the screen without BIOS

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Writing to the screen without BIOS

Post by bzt »

PavelCheckov wrote:So, that code would work in GOP even thought it was meant for VESA? And truecolor?
Just use Scalable Screen Font. With your current skills and understanding I would recommend to pick an easy to use library instead of writing your own.

From the wiki:
The SSFN package comes with a single ANSI C/C++ header file, which has two renderers. The header contains everything, no shared library nor static linking needed. They are compatible with both VESA and GOP framebuffers.
An example code where SSFN is printed on GOP framebuffer without the library can be found here (note: it does not depend on POSIX-UEFI, you can use it with EDK2 as well as with GNU-EFI).
An example using the SSFN single header library and GOP is here. In both case you need the function

Code: Select all

printString
Cheers,
bzt
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Writing to the screen without BIOS

Post by kzinti »

bzt wrote:With your current skills and understanding I would recommend to pick an easy to use library instead of writing your own.
I completely disagree with that statement. I think OP should learn to walk before learning to run. The OP clearly doesn't understand what is going on and my advice to him would be to learn how the simple text drawing code works before trying to tackle something bigger like scalable fonts, library or not.

If one doesn't understand framebuffers and how to draw characters on it, it will be a serious hurdle down the road and this step should not be skipped. Beside, I am not sure how one would manage to integrate a scalable font library with his existing framebuffer if he doesn't understand how the later works. This would be trading a small problem for a bigger one.
PavelCheckov wrote:So, that code would work in GOP even thought it was meant for VESA? And truecolor?
Take the time to understand what a framebuffer is and how the pixel colours are encoded. Once you have done so, the answer to your question will be obvious. (Yes: a framebuffer works the same way no matter which API / system you used to retrieve its address and parameters like width, height, pitch (aka stride) and pixel format.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Writing to the screen without BIOS

Post by bzt »

kzinti wrote:
bzt wrote:With your current skills and understanding I would recommend to pick an easy to use library instead of writing your own.
I completely disagree with that statement. I think OP should learn to walk before learning to run.
I don't understand why you disagree, because that's exactly what I've said. Using a ready-to-use library = walk, writing everything from scratch = run.
kzinti wrote:The OP clearly doesn't understand what is going on and my advice to him would be to learn how the simple text drawing code works before trying to tackle something bigger like scalable fonts, library or not.
Don't let the name fool you. SSFN comes with two renderers, I've recommended the simpler one, ssfn_putc, which only works with unscaled bitmap fonts, and was specifically designed for OS kernel consoles.
kzinti wrote:If one doesn't understand framebuffers and how to draw characters on it, it will be a serious hurdle down the road and this step should not be skipped.
Agreed. But he could start with a simple to use library to get a Hello world on screen, and learn the things under the hood later as he progresses. Not being able to write debug messages on screen is very hard.

Cheers,
bzt
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Writing to the screen without BIOS

Post by kzinti »

bzt wrote:I don't understand why you disagree, because that's exactly what I've said. Using a ready-to-use library = walk, writing everything from scratch = run.
Do not twist my words to fit your narrative. You perfectly understood what I meant to say.
bzt wrote:Agreed. But he could start with a simple to use library to get a Hello world on screen, and learn the things under the hood later as he progresses. Not being able to write debug messages on screen is very hard.
There are better ways to get debug messages out of your app for debugging purposes.

Since he is working on a UEFI bootloader, one can simply use the OutputString() function from the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. This will write text to the screen *and* the serial port. Under QEMU, the serial port can easily be redirected to the host's terminal with "-serial stdio" or "-serial mon:stdio".

Using a debugger is probably even a better idea, but can be a bit more complicated to setup for someone with little experience.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Writing to the screen without BIOS

Post by bzt »

kzinti wrote:Do not twist my words to fit your narrative.
??? This makes absolutely no sense. I haven't twisted anything. Please read my posts carefully. If you have problems understanding English sentences, let me know and I'll rephrase.
kzinti wrote:Since he is working on a UEFI bootloader, one can simply use the OutputString() function from the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
That protocol doesn't guaranteed to work after GOP gets initialized, and it does not work on some firmware (TianoCore included). That's the very reason why you need your own GOP-compatible font renderer in the first place. Yeah, I agree it would be better and it should just work, but in reality it does not.

Cheers,
bzt
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Writing to the screen without BIOS

Post by nexos »

bzt wrote:Yeah, I agree it would be better and it should just work, but in reality it does not.
That would not be possible. After you have called the GOP, the framebuffer is yours not UEFI's. UEFI can't just make poor assumptions about the screen state. Instead, it lets you take control after using GOP.
Commercial standards aren't designed to be easy to use. If somebody is looking for easy, then they need to become a web developer. Developing an OS is hard, and OS developers should be willing to be accept this, not use timesaving libraries, when one day soon, the complexity they hide will bight them in the leg. This is a reason why I recommend learning Assembly before C. The understanding of C Assembly gives you is very important. But one day, Assembly will bight you when writing in C.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
davmac314
Member
Member
Posts: 121
Joined: Mon Jul 05, 2021 6:57 pm

Re: Writing to the screen without BIOS

Post by davmac314 »

bzt wrote:
kzinti wrote:Do not twist my words to fit your narrative.
??? This makes absolutely no sense. I haven't twisted anything. Please read my posts carefully. If you have problems understanding English sentences, let me know and I'll rephrase.
Right here:
bzt wrote:I don't understand why you disagree, because that's exactly what I've said. Using a ready-to-use library = walk, writing everything from scratch = run.
Clearly kzinti was not equating "using a ready-to-use library" to "walk" like you are.

For what it's worth, and kzinti can confirm or correct if they choose, but I interpreted "walk" as "take the time to learn and understand what needs to happen at a lower level" (which is slower to get a result, hence "walk"). I thought it was pretty clear from context.
vvaltchev
Member
Member
Posts: 274
Joined: Fri May 11, 2018 6:51 am

Re: Writing to the screen without BIOS

Post by vvaltchev »

nexos wrote:After you have called the GOP, the framebuffer is yours not UEFI's. UEFI can't just make poor assumptions about the screen state. Instead, it lets you take control after using GOP.
In my UEFI bootloader, I'm using the GOP to change screen's resolution and after that I clear the screen and write text using the basic UEFI console utilities and it works everywhere: on all of my UEFI machines and on VMs with OVMF.

Can you clarify what do you mean by "calling the GOP" ? Does the UEFI spec explicitly states that we should not try to write text after changing the resolution?

Let me explain my use case: I wanna have a small and simple bootloader and I don't wanna draw on the framebuffer by myself, but I need to change the screen resolution because on some modern laptops with retina displays like my Dell XPS 13", the native resolution is simply too big and the text using firmware's default font is way too small. So, in order to the bootloader to be humanly usable, it's necessary to switch to a smaller resolution like 800x600. It would be very sad discovering that my case is not officially supported by the spec. That would practically mean requiring almost every bootloader to draw on the screen because the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL is not usable in all the cases.
Tilck, a Tiny Linux-Compatible Kernel: https://github.com/vvaltchev/tilck
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Writing to the screen without BIOS

Post by nexos »

@vvaltchev - that makes sense. I didn't read that anywhere, the spec doesn't state anything about EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL after setting GOP mode. By "calling GOP" I meant "setting GOP mode", I could have worded that better. It just made sense that OVMF wouldn't support EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL after setting GOP mode, based on what bzt said. I haven't witnessed either case yet, honestly.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
vvaltchev
Member
Member
Posts: 274
Joined: Fri May 11, 2018 6:51 am

Re: Writing to the screen without BIOS

Post by vvaltchev »

nexos wrote:@vvaltchev - that makes sense. I didn't read that anywhere, the spec doesn't state anything about EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL after setting GOP mode. By "calling GOP" I meant "setting GOP mode", I could have worded that better. It just made sense that OVMF wouldn't support EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL after setting GOP mode, based on what bzt said. I haven't witnessed either case yet, honestly.
Ah, OK. Thanks for the clarification :-)
Tilck, a Tiny Linux-Compatible Kernel: https://github.com/vvaltchev/tilck
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Writing to the screen without BIOS

Post by kzinti »

Using the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL after changing the screen resolution with the GOP seems to work just fine for me as well. I see no reason why it wouldn't. There is no concept of taking ownership or locking the framebuffer/hardware in the spec that relates to GOP operations.

Even if EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL stops rendering to the screen for a given machine, the serial port should continue to work. One can use still use OutputString() to help you debug your framebuffer code. You can even locate the SerialIo protocol directly and use that to output text if you want. The idea that you cannot output any useful debug information because you are working on GOP code is not true. There are alternatives, especially with UEFI. As stated previously, using a debugger is always an option.

EDIT: I just verified this with Tianocore "ovmf-x86_64-pure-efi.fd" under QEMU. Not sure which version of the firmware I have, but it's a relatively recent one. I can use OutputString() after changing the screen resolution with the GOP and it works just fine.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Writing to the screen without BIOS

Post by bzt »

kzinti wrote:Using the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL after changing the screen resolution with the GOP seems to work just fine for me as well.
And it doesn't for me. Some reported it doesn't work on their real machine either. A workaround for me under TianoCore was to call simple text's Reset() after GOP SetMode() to update the simple text's internal state otherwise OutputString() stops working properly. But on real machines this is highly video card specific, as it is the video card's driver that implements GOP and the console.
kzinti wrote:Even if EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL stops rendering to the screen for a given machine, the serial port should continue to work.
The serial will work, but the problem is, if you change the GOP resolution but do not update the simple text's internal state, you will get not only bad number of coloumns and rows that messes up the display, but also out of bounds memory writes with OutputString() causing random crashes in certain scenarios.

As I've said, not all implementations are affected, but the the default console in latest TianoCore definitely still has this bug. (Note how this implementation uses it's internal "Mode" property instead of checking the actual GOP Mode in line 933 - 950. The value of MaxColumn and MaxRow can be easily totally wrong.)

Cheers,
bzt
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Writing to the screen without BIOS

Post by nexos »

Then reset the console. It's literally one (OK, maybe two) lines of code. Or, maybe just use GOP and draw your own fonts. That's my plan, as I want to have a consistent looking font across all machines.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Writing to the screen without BIOS

Post by bzt »

nexos wrote:maybe just use GOP and draw your own fonts.
Yeah, that's what I do, that's what my bootloader's tutorial kernel does and that's exactly what I've recommended to the OP.

Furthermore you cannot use simple text for true UNICODE. It just looks like that it supports the BMP, but when you actually try to print mixed English, non-English Latin and CJK scripts you'll realize that just doesn't work (and forget about everything above BMP, excluded from the UEFI spec).
That's why I've recommended the SSFN library instead as it is fully UNICODE compatible, supports UTF-8 too and works with GOP. Like in this simple example:
Image

Even though printString is just ca. 30 SLoC, writing a font renderer like that is a bumpy ride at least to say, definitely not for beginners.

Cheers,
bzt
User avatar
PavelChekov
Member
Member
Posts: 113
Joined: Mon Sep 21, 2020 9:51 am
Location: Aboard the Enterprise

Re: Writing to the screen without BIOS

Post by PavelChekov »

The GOP and Writing to the Linear Framebuffer articles contradict. I don't know whether to use:

Code: Select all

static void putpixel(unsigned char* screen, int x,int y, int color) {
    unsigned where = x*pixelwidth + y*pitch;
    screen[where] = color & 255;              // BLUE
    screen[where + 1] = (color >> 8) & 255;   // GREEN
    screen[where + 2] = (color >> 16) & 255;  // RED
}
(The latter)

-or-

Code: Select all

static inline void PlotPixel_32bpp(int x, int y, uint32_t pixel)
{
   *((uint32_t*)(gop->Mode->FrameBufferBase + 4 * gop->Mode->Info->PixelsPerScanLine * y + 4 * x)) = pixel;
}
(The former)
USS Enterprise NCC-1701,
The Final Frontier,
Space,
The Universe

Live Long And Prosper

Slava Ukraini!
Слава Україні!
Post Reply