libpayload: Cache copy of `cb_framebuffer` struct
Our AArch64 code supports dynamic framebuffer allocation which makes it necessary to change the framebuffer information during runtime. Having a pointer inside `libsysinfo` made a mess of it as the pointer would either refer to the original struct inside the coreboot table or to a new struct inside payload space. The latter would be unaffected by a relocation of the payload. Instead of the pointer, we'll always keep a copy of the whole struct, which can be altered on demand without affecting the coreboot table. To align the `video/graphics` driver with the console driver, we also replace `fbaddr` with a macro `FB` that calls phys_to_virt(). Change-Id: I3edc09cdb502a71516c1ee71457c1f8dcd01c119 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/c/coreboot/+/43578 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
be842cb72d
commit
5e0db58533
|
@ -625,14 +625,10 @@ static void mmu_extract_ranges(struct memrange *cb_ranges,
|
||||||
static void mmu_add_fb_range(struct mmu_ranges *mmu_ranges)
|
static void mmu_add_fb_range(struct mmu_ranges *mmu_ranges)
|
||||||
{
|
{
|
||||||
struct mmu_memrange *fb_range;
|
struct mmu_memrange *fb_range;
|
||||||
static struct cb_framebuffer modified_fb;
|
struct cb_framebuffer *framebuffer = &lib_sysinfo.framebuffer;
|
||||||
struct cb_framebuffer *framebuffer = lib_sysinfo.framebuffer;
|
|
||||||
uint32_t fb_size;
|
uint32_t fb_size;
|
||||||
|
|
||||||
/* Check whether framebuffer is needed */
|
/* Check whether framebuffer is needed */
|
||||||
if (framebuffer == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fb_size = framebuffer->bytes_per_line * framebuffer->y_resolution;
|
fb_size = framebuffer->bytes_per_line * framebuffer->y_resolution;
|
||||||
if (!fb_size)
|
if (!fb_size)
|
||||||
return;
|
return;
|
||||||
|
@ -652,16 +648,7 @@ static void mmu_add_fb_range(struct mmu_ranges *mmu_ranges)
|
||||||
if (fb_range == NULL)
|
if (fb_range == NULL)
|
||||||
mmu_error();
|
mmu_error();
|
||||||
|
|
||||||
/*
|
framebuffer->physical_address = fb_range->base;
|
||||||
* Set framebuffer address. However, one needs to use a freshly
|
|
||||||
* allocated framebuffer structure because the one in the coreboot
|
|
||||||
* table is part of a checksum calculation. Therefore, one cannot
|
|
||||||
* modify a field without recomputing the necessary checksum
|
|
||||||
* calcuation.
|
|
||||||
*/
|
|
||||||
modified_fb = *framebuffer;
|
|
||||||
modified_fb.physical_address = fb_range->base;
|
|
||||||
lib_sysinfo.framebuffer = &modified_fb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -60,7 +60,7 @@ static const u32 vga_colors[] = {
|
||||||
(0xFF << 16) | (0xFF << 8) | 0xFF,
|
(0xFF << 16) | (0xFF << 8) | 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cb_framebuffer fbinfo;
|
static struct cb_framebuffer fbinfo;
|
||||||
static unsigned short *chars;
|
static unsigned short *chars;
|
||||||
|
|
||||||
/* Shorthand for up-to-date virtual framebuffer address */
|
/* Shorthand for up-to-date virtual framebuffer address */
|
||||||
|
@ -223,13 +223,10 @@ static void corebootfb_set_cursor(unsigned int x, unsigned int y)
|
||||||
|
|
||||||
static int corebootfb_init(void)
|
static int corebootfb_init(void)
|
||||||
{
|
{
|
||||||
if (lib_sysinfo.framebuffer == NULL)
|
if (!lib_sysinfo.framebuffer.physical_address)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
fbinfo = *lib_sysinfo.framebuffer;
|
fbinfo = lib_sysinfo.framebuffer;
|
||||||
|
|
||||||
if (fbinfo.physical_address == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
font_init(fbinfo.x_resolution);
|
font_init(fbinfo.x_resolution);
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,10 @@ static struct rect screen;
|
||||||
* Framebuffer is assumed to assign a higher coordinate (larger x, y) to
|
* Framebuffer is assumed to assign a higher coordinate (larger x, y) to
|
||||||
* a higher address
|
* a higher address
|
||||||
*/
|
*/
|
||||||
static struct cb_framebuffer *fbinfo;
|
static const struct cb_framebuffer *fbinfo;
|
||||||
static uint8_t *fbaddr;
|
|
||||||
|
/* Shorthand for up-to-date virtual framebuffer address */
|
||||||
|
#define FB ((unsigned char *)phys_to_virt(fbinfo->physical_address))
|
||||||
|
|
||||||
#define LOG(x...) printf("CBGFX: " x)
|
#define LOG(x...) printf("CBGFX: " x)
|
||||||
#define PIVOT_H_MASK (PIVOT_H_LEFT|PIVOT_H_CENTER|PIVOT_H_RIGHT)
|
#define PIVOT_H_MASK (PIVOT_H_LEFT|PIVOT_H_CENTER|PIVOT_H_RIGHT)
|
||||||
|
@ -296,7 +298,7 @@ static inline void set_pixel(struct vector *coord, uint32_t color)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * const pixel = fbaddr + rcoord.y * bpl + rcoord.x * bpp / 8;
|
uint8_t * const pixel = FB + rcoord.y * bpl + rcoord.x * bpp / 8;
|
||||||
for (i = 0; i < bpp / 8; i++)
|
for (i = 0; i < bpp / 8; i++)
|
||||||
pixel[i] = (color >> (i * 8));
|
pixel[i] = (color >> (i * 8));
|
||||||
}
|
}
|
||||||
|
@ -310,12 +312,9 @@ static int cbgfx_init(void)
|
||||||
if (initialized)
|
if (initialized)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fbinfo = lib_sysinfo.framebuffer;
|
fbinfo = &lib_sysinfo.framebuffer;
|
||||||
if (!fbinfo)
|
|
||||||
return CBGFX_ERROR_FRAMEBUFFER_INFO;
|
|
||||||
|
|
||||||
fbaddr = phys_to_virt((uint8_t *)(uintptr_t)(fbinfo->physical_address));
|
if (!fbinfo->physical_address)
|
||||||
if (!fbaddr)
|
|
||||||
return CBGFX_ERROR_FRAMEBUFFER_ADDR;
|
return CBGFX_ERROR_FRAMEBUFFER_ADDR;
|
||||||
|
|
||||||
switch (fbinfo->orientation) {
|
switch (fbinfo->orientation) {
|
||||||
|
@ -627,7 +626,7 @@ int clear_screen(const struct rgb_color *rgb)
|
||||||
* We assume that for 32bpp the high byte gets ignored anyway. */
|
* We assume that for 32bpp the high byte gets ignored anyway. */
|
||||||
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
|
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
|
||||||
(((color >> 16) & 0xff) == (color & 0xff)))) {
|
(((color >> 16) & 0xff) == (color & 0xff)))) {
|
||||||
memset(fbaddr, color & 0xff, fbinfo->y_resolution * bpl);
|
memset(FB, color & 0xff, fbinfo->y_resolution * bpl);
|
||||||
} else {
|
} else {
|
||||||
for (p.y = 0; p.y < screen.size.height; p.y++)
|
for (p.y = 0; p.y < screen.size.height; p.y++)
|
||||||
for (p.x = 0; p.x < screen.size.width; p.x++)
|
for (p.x = 0; p.x < screen.size.width; p.x++)
|
||||||
|
|
|
@ -81,7 +81,7 @@ struct sysinfo_t {
|
||||||
|
|
||||||
char *cb_version;
|
char *cb_version;
|
||||||
|
|
||||||
struct cb_framebuffer *framebuffer;
|
struct cb_framebuffer framebuffer;
|
||||||
|
|
||||||
int num_gpios;
|
int num_gpios;
|
||||||
struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
|
struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
|
||||||
|
|
|
@ -186,8 +186,7 @@ static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
|
||||||
#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
|
#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
|
||||||
static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
|
static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
|
||||||
{
|
{
|
||||||
/* ptr points to a coreboot table entry and is already virtual */
|
info->framebuffer = *(struct cb_framebuffer *)ptr;
|
||||||
info->framebuffer = ptr;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue