618
edits
[unchecked revision] | [unchecked revision] |
mNo edit summary |
|||
(12 intermediate revisions by 9 users not shown) | |||
Line 1:
This is the new standard for UEFI that superseded [[VESA]] (BIOS) and UGA (EFI 1.0).
==
It has
NOTE: UEFI uses
=== Detecting GOP ===
As with other UEFI protocols, you have to locate a structure with the function pointers first using the protocol's GUID.
<
EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
Line 15:
if(EFI_ERROR(status))
PrintLn(L"Unable to locate GOP");
</syntaxhighlight>
GOP is the default protocol, so you should be able to locate it on all UEFI firmware. It can probably only fail if you're on an old EFI (pre-UEFI) machine, like an Itanium-based computer or a Mac released before 2009.
If your kernel uses GRUB, you need to insert a module called "all_video" before loading the kernel to add UEFI GOP compatibility. Not doing so will display a message saying "WARNING: no console will be available to OS".
=== Get the Current Mode ===▼
In order to get the mode code for the current video mode, you must set the mode first to circumvent some buggy UEFI firmware. This is done using the QueryMode function, and then gop->Mode->Mode will contain the code (this is a perfect example how badly designed UEFI is. Look: gop->Mode is a struct, while gop->Mode->Mode is a UINTN). See the QueryMode example below.▼
insmod all_video
menuentry "Example OS" {
=== Query Available Video Modes ===▼
multiboot2 /boot/kernel.bin
boot
▲<source lang="c">
}
</syntaxhighlight>
▲=== Get the Current Mode ===
▲In order to get the mode code for the current video mode, you must set the mode
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN SizeOfInfo, numModes, nativeMode;
Line 32 ⟶ 40:
if(EFI_ERROR(status)) {
PrintLn(L"Unable to get native mode");
} else {
nativeMode = gop->Mode->Mode;▼
numModes = gop->Mode->MaxMode;▼
}
</syntaxhighlight>
▲ nativeMode = gop->Mode->Mode;
▲ numModes = gop->Mode->MaxMode;
▲=== Query Available Video Modes ===
Similarly to VESA, there's no standard mode codes, rather you have a function to query the available modes. Now you know how many modes there are (numModes above), and which one is currently set (nativeMode). You can iterate on the modes and query the information structure for each:
<
for (i = 0; i < numModes; i++) {
status = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo, &info);
Line 49 ⟶ 59:
);
}
</syntaxhighlight>
=== Set Video Mode and Get the Framebuffer ===
This is pretty easy. The mode argument is between 0 and numModes.
<
status = uefi_call_wrapper(gop->SetMode, 2, gop, mode);
if(EFI_ERROR(status)) {
PrintLn(L"Unable to set mode %03d", mode);
} else {
// get framebuffer▼
gop->Mode->FrameBufferBase,▼
gop->Mode->FrameBufferSize,▼
gop->Mode->Info->HorizontalResolution,▼
gop->Mode->Info->VerticalResolution,▼
gop->Mode->Info->PixelsPerScanLine▼
);▼
}
</syntaxhighlight>
▲ // get framebuffer
To get the same value as scanline in VESA (also
▲ PrintLn(L"Framebuffer address %x size %d, width %d height %d pixelperline %d",
<syntaxhighlight lang="c">
▲ gop->Mode->FrameBufferBase,
▲ gop->Mode->FrameBufferSize,
▲ gop->Mode->Info->HorizontalResolution,
▲ gop->Mode->Info->VerticalResolution,
▲ gop->Mode->Info->PixelsPerScanLine
▲ );
▲To get the same value as scanline in VESA (also called commonly pitch in many graphics libraries), you have to multiply PixelsPerScanLine by the number of bytes per pixel. That can be detected by examining the gop->Mode->Info->PixelFormat field. For example with 32 bit packed pixel formats,
▲<source lang="c">
pitch = 4 * gop->Mode->Info->PixelsPerScanLine;
</syntaxhighlight>
=== Plotting Pixels ===
{{Main|Drawing In Protected Mode}}
Now you can use the returned framebuffer exactly the same way as you would with VESA, there's absolutely no difference.
To calculate the offset for an (X,Y) coordinate on screen, do pitch*Y+pixelbytes*X. For example for 32 bit true-color (where pixelbytes is 4):
<
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;
}
</syntaxhighlight>
For drawing characters, you can use the same method described in [[VGA Fonts]].
=== Don't Read From Video Memory ===
Reading from the video memory is slooow! Use [[Double Buffering|double buffering]] instead.
Line 95 ⟶ 105:
* GOP at [https://en.wikipedia.org/wiki/Graphics_Output_Protocol Wikipedia]
* UEFI Graphic Features at [https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#Graphics_features Wikipedia]
* [https://
* [https://www.intel.com/content/dam/doc/guide/uefi-driver-graphics-controller-guide.pdf Intel documentation on GOP]
[[Category:UEFI]]
[[Category:Video]]
|