Blame | Last modification | View Log | Download | RSS feed
This patch makes the currently initialized graphics framebuffer parameters (address, width, height, pixel format) available
to user-space QNX8 programs through the _CS_GRAPHICS configuration strings when booting a x86-compatible BSP from UEFI.
In <BSP-x86>/src/hardware/startup/boards/x86/main.c
Just before the call to:
// Collect information on all free RAM in the system with
// the EFI service routine GetMemoryMap
init_raminfo_uefi();
Insert this self-contained code:
{ // inject information about the current linear framebuffer used by the UEFI setup program -- BEGIN
typedef struct efi_gop_mode_info_s {
uint32_t version; // version of this data structure. Typically zero for the current UEFI standard revision.
uint32_t horizontal_res; // size of the video screen in pixels in the X dimension
uint32_t vertical_res; // size of the video screen in pixels in the Y dimension
int pixel_format; // physical format of the pixel (0 = RGBx 8-bit, 1 = BGRx 8-bit, 2 = bitmask, 3 = no framebuffer for this mode)
struct {
uint32_t red_mask; // a bit being set means this bit is used for the red color
uint32_t green_mask; // a bit being set means this bit is used for the green color
uint32_t blue_mask; // a bit being set means this bit is used for the blue color
uint32_t reserved_mask; // a bit being set means this bit is not used by any of the red, green and blue colors
} pixel_info; // only valid if pixel_format is 2 (bitmask)
uint32_t pixels_per_scanline; // defines the number of pixel elements per video memory line
} efi_gop_mode_info_t;
typedef struct efi_gop_mode_s {
uint32_t max_mode; // number of modes supported by QueryMode() and SetMode()
uint32_t current_mode; // current Mode of the graphics device (0 to max_mode-1)
efi_gop_mode_info_t *info; // pointer to read-only efi_gop_mode_info_t data
_Uintn info_size; // size of info structure in bytes
uint64_t framebuffer_base; // base address of graphics linear frame buffer, where offset zero represents the upper left pixel of the display
_Uintn framebuffer_size; // amount of frame buffer needed to support the active mode as defined by PixelsPerScanLine x VerticalResolution x PixelElementSize
} efi_gop_mode_t;
typedef struct efi_gop_s {
EFI_STATUS (*QueryMode) (void *this_gop, uint32_t mode_number, _Uintn *info_size, efi_gop_mode_info_t **info);
EFI_STATUS (*SetMode) (void *this_gop, uint32_t mode_number);
EFI_STATUS (*Blt) (void *this_gop, void *blit_buffer, int blit_op, _Uintn src_x, _Uintn src_y, _Uintn dst_x, _Uintn dst_y, _Uintn w, _Uintn h, _Uintn delta);
efi_gop_mode_t *mode; // pointer to efi_gop_mode_t data
} efi_gop_t;
efi_gop_t *gop = NULL;
EFI_GUID gop_guid = { 0x9042a9de, 0x23dc, 0x4a38, { 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } }; // EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
if (efi_system_table->BootServices->LocateProtocol (&gop_guid, NULL, (void **) &gop) == 0) // obtain a pointer to the UEFI GOP API
{
_Uintn info_size;
efi_gop_mode_info_t *info;
EFI_STATUS status = gop->QueryMode (gop, (gop->mode == NULL ? 0 : gop->mode->current_mode), &info_size, &info); // obtain information about the current graphic mode
if (status == EFI_NOT_STARTED) // graphic output not started yet ?
{
gop->SetMode (gop, 0); // initialize display with the first available mode if the UEFI program didn't do it already
status = gop->QueryMode (gop, (gop->mode == NULL ? 0 : gop->mode->current_mode), &info_size, &info); // obtain information about the current graphic mode again
}
if ((status == 0) && (gop->mode != NULL) && (gop->mode->info != NULL) && (gop->mode->info->version == 0) && (gop->mode->info->pixel_format < 3)) // valid graphic mode info obtained ?
{
static char framebuffer_confstr[64] = ""; // keep allocations on the heap
char *pixfmt_string = "none";
if (gop->mode->info->pixel_format == 0) pixfmt_string = "RGBx"; // only support 32-bit modes at the moment
else if (gop->mode->info->pixel_format == 1) pixfmt_string = "BGRx"; // only support 32-bit modes at the moment
ksprintf (framebuffer_confstr, "0x%L %d %d %d %s", gop->mode->framebuffer_base, gop->mode->framebuffer_size, gop->mode->info->horizontal_res, gop->mode->info->vertical_res, pixfmt_string);
add_typed_string (_CS_GRAPHICS, framebuffer_confstr); // save this configuration in the _CS_GRAPHICS configuration string
kprintf ("framebuffer at 0x%L size %d res %dx%d format %s\n", gop->mode->framebuffer_base, gop->mode->framebuffer_size, gop->mode->info->horizontal_res, gop->mode->info->vertical_res, pixfmt_string);
}
else
{
static const char uefi_lfb_error2[] = "unable to get linear framebuffer default graphic mode information from EFI\n";
kprintf (uefi_lfb_error2); // print error on kernel standard error
uefi_print_str ((char *) uefi_lfb_error2); // and also on the EFI console
}
}
else
{
static const char uefi_lfb_error1[] = "unable to locate UEFI Graphic Output Protocol (no display?)\n";
kprintf (uefi_lfb_error1); // print error on kernel standard error
uefi_print_str ((char *) uefi_lfb_error1); // and also on the EFI console
}
} // inject information about the current linear framebuffer used by the UEFI setup program -- END
Rebuild your BSP and use the _CS_GRAPHICS value from user-space to fire up a working UEFI console driver.
--
Pierre-Marie Baty <pm@pmbaty.com>