mirror of
https://github.com/qemu/qemu.git
synced 2025-08-10 12:46:22 +00:00

Currently the ramfb device loads the vgabios-ramfb.bin unconditionally, but only the x86 need the vgabios-ramfb.bin, this can cause that when use the release package on arm64 it can't find the vgabios-ramfb.bin. Because only seabios will use the vgabios-ramfb.bin, load the rom logic is x86-specific. For other !x86 platforms, the edk2 ships an EFI driver for ramfb, so they don't need to load the romfile. So add a new property use-legacy-x86-rom in both ramfb and vfio_pci device, because the vfio display also use the ramfb_setup() to load the vgabios-ramfb.bin file. After have this property, the machine type can set the compatibility to not load the vgabios-ramfb.bin if the arch doesn't need it. For now the default value is true but it will be turned off by default in subsequent patch when compats get properly handled. Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Shaoqin Huang <shahuang@redhat.com> Message-ID: <20250717100941.2230408-2-shahuang@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
158 lines
4.0 KiB
C
158 lines
4.0 KiB
C
/*
|
|
* early boot framebuffer in guest ram
|
|
* configured using fw_cfg
|
|
*
|
|
* Copyright Red Hat, Inc. 2017
|
|
*
|
|
* Author:
|
|
* Gerd Hoffmann <kraxel@redhat.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "hw/loader.h"
|
|
#include "hw/display/ramfb.h"
|
|
#include "hw/display/bochs-vbe.h" /* for limits */
|
|
#include "ui/console.h"
|
|
#include "system/reset.h"
|
|
|
|
struct QEMU_PACKED RAMFBCfg {
|
|
uint64_t addr;
|
|
uint32_t fourcc;
|
|
uint32_t flags;
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t stride;
|
|
};
|
|
|
|
typedef struct RAMFBCfg RAMFBCfg;
|
|
|
|
struct RAMFBState {
|
|
DisplaySurface *ds;
|
|
uint32_t width, height;
|
|
struct RAMFBCfg cfg;
|
|
};
|
|
|
|
static void ramfb_unmap_display_surface(pixman_image_t *image, void *unused)
|
|
{
|
|
void *data = pixman_image_get_data(image);
|
|
uint32_t size = pixman_image_get_stride(image) *
|
|
pixman_image_get_height(image);
|
|
cpu_physical_memory_unmap(data, size, 0, 0);
|
|
}
|
|
|
|
static DisplaySurface *ramfb_create_display_surface(int width, int height,
|
|
pixman_format_code_t format,
|
|
hwaddr stride, hwaddr addr)
|
|
{
|
|
DisplaySurface *surface;
|
|
hwaddr size, mapsize, linesize;
|
|
void *data;
|
|
|
|
if (width < 16 || width > VBE_DISPI_MAX_XRES ||
|
|
height < 16 || height > VBE_DISPI_MAX_YRES ||
|
|
format == 0 /* unknown format */)
|
|
return NULL;
|
|
|
|
linesize = width * PIXMAN_FORMAT_BPP(format) / 8;
|
|
if (stride == 0) {
|
|
stride = linesize;
|
|
}
|
|
|
|
mapsize = size = stride * (height - 1) + linesize;
|
|
data = cpu_physical_memory_map(addr, &mapsize, false);
|
|
if (size != mapsize) {
|
|
cpu_physical_memory_unmap(data, mapsize, 0, 0);
|
|
return NULL;
|
|
}
|
|
|
|
surface = qemu_create_displaysurface_from(width, height,
|
|
format, stride, data);
|
|
pixman_image_set_destroy_function(surface->image,
|
|
ramfb_unmap_display_surface, NULL);
|
|
|
|
return surface;
|
|
}
|
|
|
|
static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len)
|
|
{
|
|
RAMFBState *s = dev;
|
|
DisplaySurface *surface;
|
|
uint32_t fourcc, format, width, height;
|
|
hwaddr stride, addr;
|
|
|
|
width = be32_to_cpu(s->cfg.width);
|
|
height = be32_to_cpu(s->cfg.height);
|
|
stride = be32_to_cpu(s->cfg.stride);
|
|
fourcc = be32_to_cpu(s->cfg.fourcc);
|
|
addr = be64_to_cpu(s->cfg.addr);
|
|
format = qemu_drm_format_to_pixman(fourcc);
|
|
|
|
surface = ramfb_create_display_surface(width, height,
|
|
format, stride, addr);
|
|
if (!surface) {
|
|
return;
|
|
}
|
|
|
|
s->width = width;
|
|
s->height = height;
|
|
qemu_free_displaysurface(s->ds);
|
|
s->ds = surface;
|
|
}
|
|
|
|
void ramfb_display_update(QemuConsole *con, RAMFBState *s)
|
|
{
|
|
if (!s->width || !s->height) {
|
|
return;
|
|
}
|
|
|
|
if (s->ds) {
|
|
dpy_gfx_replace_surface(con, s->ds);
|
|
s->ds = NULL;
|
|
}
|
|
|
|
/* simple full screen update */
|
|
dpy_gfx_update_full(con);
|
|
}
|
|
|
|
static int ramfb_post_load(void *opaque, int version_id)
|
|
{
|
|
ramfb_fw_cfg_write(opaque, 0, 0);
|
|
return 0;
|
|
}
|
|
|
|
const VMStateDescription ramfb_vmstate = {
|
|
.name = "ramfb",
|
|
.version_id = 1,
|
|
.minimum_version_id = 1,
|
|
.post_load = ramfb_post_load,
|
|
.fields = (const VMStateField[]) {
|
|
VMSTATE_BUFFER_UNSAFE(cfg, RAMFBState, 0, sizeof(RAMFBCfg)),
|
|
VMSTATE_END_OF_LIST()
|
|
}
|
|
};
|
|
|
|
RAMFBState *ramfb_setup(bool romfile, Error **errp)
|
|
{
|
|
FWCfgState *fw_cfg = fw_cfg_find();
|
|
RAMFBState *s;
|
|
|
|
if (!fw_cfg || !fw_cfg->dma_enabled) {
|
|
error_setg(errp, "ramfb device requires fw_cfg with DMA");
|
|
return NULL;
|
|
}
|
|
|
|
s = g_new0(RAMFBState, 1);
|
|
|
|
if (romfile) {
|
|
rom_add_vga("vgabios-ramfb.bin");
|
|
}
|
|
fw_cfg_add_file_callback(fw_cfg, "etc/ramfb",
|
|
NULL, ramfb_fw_cfg_write, s,
|
|
&s->cfg, sizeof(s->cfg), false);
|
|
return s;
|
|
}
|