loader.efi: reworked framebuffer setup

Pass gfx_state to efi_find_framebuffer(), so we can pick between
GOP and UGA in efi_find_framebuffer(), also we can then
set up struct gen_fb in gfx_state from efifb and isolate efi fb data
processing into framebuffer.c.

This change does allow us to clean up efi_cons_init() and reduce
BS->LocateProtocol() calls.

A little downside is that we now need to translate gen_fb back to
efifb in bootinfo.c (for passing to kernel), and we need to add few
-I options to CFLAGS.
This commit is contained in:
Toomas Soome 2021-01-11 21:54:23 +00:00
parent 85d028223b
commit 50180d2b52
6 changed files with 89 additions and 62 deletions

View File

@ -50,6 +50,7 @@ CFLAGS+= -fPIC -mno-red-zone
CFLAGS+= -I${EFIINC}
CFLAGS+= -I${EFIINCMD}
CFLAGS.efi_console.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite
CFLAGS.efi_console.c+= -I${.CURDIR}/../loader
CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
.if ${MK_LOADER_ZFS} != "no"
CFLAGS+= -I${ZFSSRC}

View File

@ -34,10 +34,10 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <machine/metadata.h>
#include <gfx_fb.h>
#include <framebuffer.h>
#include "bootstrap.h"
extern EFI_GUID gop_guid;
extern int efi_find_framebuffer(struct efi_fb *efifb);
static EFI_GUID simple_input_ex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
static SIMPLE_INPUT_INTERFACE *conin;
@ -884,52 +884,29 @@ cons_update_mode(bool use_gfx_mode)
const teken_attr_t *a;
teken_attr_t attr;
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT *gop = NULL;
struct efi_fb efifb;
char env[10], *ptr;
if (use_gfx_mode == true) {
gfx_state.tg_fb_type = FB_GOP;
if (gfx_state.tg_private == NULL) {
(void) BS->LocateProtocol(&gop_guid, NULL,
(void **)&gop);
gfx_state.tg_private = gop;
} else {
gop = gfx_state.tg_private;
}
/*
* Despite the use_gfx_mode, we want to make sure we call
* efi_find_framebuffer(). This will populate the fb data,
* which will be passed to kernel.
*/
if (efi_find_framebuffer(&gfx_state) == 0 && use_gfx_mode) {
int roff, goff, boff;
/*
* We have FB but no GOP - it must be UGA.
*/
if (gop == NULL)
gfx_state.tg_fb_type = FB_UGA;
roff = ffs(gfx_state.tg_fb.fb_mask_red) - 1;
goff = ffs(gfx_state.tg_fb.fb_mask_green) - 1;
boff = ffs(gfx_state.tg_fb.fb_mask_blue) - 1;
if (efi_find_framebuffer(&efifb) == 0) {
int roff, goff, boff;
gfx_state.tg_fb.fb_addr = efifb.fb_addr;
gfx_state.tg_fb.fb_size = efifb.fb_size;
gfx_state.tg_fb.fb_height = efifb.fb_height;
gfx_state.tg_fb.fb_width = efifb.fb_width;
gfx_state.tg_fb.fb_stride = efifb.fb_stride;
gfx_state.tg_fb.fb_mask_red = efifb.fb_mask_red;
gfx_state.tg_fb.fb_mask_green = efifb.fb_mask_green;
gfx_state.tg_fb.fb_mask_blue = efifb.fb_mask_blue;
gfx_state.tg_fb.fb_mask_reserved =
efifb.fb_mask_reserved;
roff = ffs(efifb.fb_mask_red) - 1;
goff = ffs(efifb.fb_mask_green) - 1;
boff = ffs(efifb.fb_mask_blue) - 1;
(void) generate_cons_palette(cmap, COLOR_FORMAT_RGB,
efifb.fb_mask_red >> roff, roff,
efifb.fb_mask_green >> goff, goff,
efifb.fb_mask_blue >> boff, boff);
gfx_state.tg_fb.fb_bpp = fls(
efifb.fb_mask_red | efifb.fb_mask_green |
efifb.fb_mask_blue | efifb.fb_mask_reserved);
}
(void) generate_cons_palette(cmap, COLOR_FORMAT_RGB,
gfx_state.tg_fb.fb_mask_red >> roff, roff,
gfx_state.tg_fb.fb_mask_green >> goff, goff,
gfx_state.tg_fb.fb_mask_blue >> boff, boff);
} else {
/*
* Either text mode was asked by user or we failed to
* find frame buffer.
*/
gfx_state.tg_fb_type = FB_TEXT;
}

View File

@ -35,6 +35,10 @@ CFLAGS+= -DEFI_ZFS_BOOT
HAVE_ZFS= yes
.endif
CFLAGS.bootinfo.c += -I$(SRCTOP)/sys/teken
CFLAGS.bootinfo.c += -I${SRCTOP}/contrib/pnglite
CFLAGS.framebuffer.c += -I$(SRCTOP)/sys/teken
CFLAGS.framebuffer.c += -I${SRCTOP}/contrib/pnglite
CFLAGS.gfx_fb.c += -I$(SRCTOP)/sys/teken
CFLAGS.gfx_fb.c += -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
CFLAGS.gfx_fb.c += -I${SRCTOP}/contrib/pnglite

View File

@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#include <machine/specialreg.h>
#endif
#include "framebuffer.h"
#include "gfx_fb.h"
#if defined(LOADER_FDT_SUPPORT)
#include <fdt_platform.h>
@ -300,19 +300,26 @@ bi_load_efi_data(struct preloaded_file *kfp)
#if defined(__amd64__) || defined(__aarch64__)
struct efi_fb efifb;
if (efi_find_framebuffer(&efifb) == 0) {
printf("EFI framebuffer information:\n");
printf("addr, size 0x%jx, 0x%jx\n", efifb.fb_addr,
efifb.fb_size);
printf("dimensions %d x %d\n", efifb.fb_width,
efifb.fb_height);
printf("stride %d\n", efifb.fb_stride);
printf("masks 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue,
efifb.fb_mask_reserved);
efifb.fb_addr = gfx_state.tg_fb.fb_addr;
efifb.fb_size = gfx_state.tg_fb.fb_size;
efifb.fb_height = gfx_state.tg_fb.fb_height;
efifb.fb_width = gfx_state.tg_fb.fb_width;
efifb.fb_stride = gfx_state.tg_fb.fb_stride;
efifb.fb_mask_red = gfx_state.tg_fb.fb_mask_red;
efifb.fb_mask_green = gfx_state.tg_fb.fb_mask_green;
efifb.fb_mask_blue = gfx_state.tg_fb.fb_mask_blue;
efifb.fb_mask_reserved = gfx_state.tg_fb.fb_mask_reserved;
printf("EFI framebuffer information:\n");
printf("addr, size 0x%jx, 0x%jx\n", efifb.fb_addr, efifb.fb_size);
printf("dimensions %d x %d\n", efifb.fb_width, efifb.fb_height);
printf("stride %d\n", efifb.fb_stride);
printf("masks 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue,
efifb.fb_mask_reserved);
if (efifb.fb_addr != 0)
file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb);
}
#endif
do_vmap = true;

View File

@ -464,21 +464,57 @@ efifb_from_uga(struct efi_fb *efifb, EFI_UGA_DRAW_PROTOCOL *uga)
}
int
efi_find_framebuffer(struct efi_fb *efifb)
efi_find_framebuffer(teken_gfx_t *gfx_state)
{
struct efi_fb efifb;
EFI_GRAPHICS_OUTPUT *gop;
EFI_UGA_DRAW_PROTOCOL *uga;
EFI_STATUS status;
int rv;
gfx_state->tg_fb_type = FB_TEXT;
status = BS->LocateProtocol(&gop_guid, NULL, (VOID **)&gop);
if (status == EFI_SUCCESS)
return (efifb_from_gop(efifb, gop->Mode, gop->Mode->Info));
if (status == EFI_SUCCESS) {
gfx_state->tg_fb_type = FB_GOP;
gfx_state->tg_private = gop;
} else {
status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
if (status == EFI_SUCCESS) {
gfx_state->tg_fb_type = FB_UGA;
gfx_state->tg_private = uga;
} else {
return (1);
}
}
status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
if (status == EFI_SUCCESS)
return (efifb_from_uga(efifb, uga));
switch (gfx_state->tg_fb_type) {
case FB_GOP:
rv = efifb_from_gop(&efifb, gop->Mode, gop->Mode->Info);
break;
return (1);
case FB_UGA:
rv = efifb_from_uga(&efifb, uga);
break;
default:
return (1);
}
gfx_state->tg_fb.fb_addr = efifb.fb_addr;
gfx_state->tg_fb.fb_size = efifb.fb_size;
gfx_state->tg_fb.fb_height = efifb.fb_height;
gfx_state->tg_fb.fb_width = efifb.fb_width;
gfx_state->tg_fb.fb_stride = efifb.fb_stride;
gfx_state->tg_fb.fb_mask_red = efifb.fb_mask_red;
gfx_state->tg_fb.fb_mask_green = efifb.fb_mask_green;
gfx_state->tg_fb.fb_mask_blue = efifb.fb_mask_blue;
gfx_state->tg_fb.fb_mask_reserved = efifb.fb_mask_reserved;
gfx_state->tg_fb.fb_bpp = fls(efifb.fb_mask_red | efifb.fb_mask_green |
efifb.fb_mask_blue | efifb.fb_mask_reserved);
return (0);
}
static void

View File

@ -28,9 +28,11 @@
* $FreeBSD$
*/
#include <gfx_fb.h>
#ifndef _EFIFB_H_
#define _EFIFB_H_
int efi_find_framebuffer(struct efi_fb *efifb);
int efi_find_framebuffer(teken_gfx_t *gfx_state);
#endif /* _EFIFB_H_ */