]>
Commit | Line | Data |
---|---|---|
995b3017 GH |
1 | /* |
2 | * early boot framebuffer in guest ram | |
3 | * configured using fw_cfg | |
4 | * | |
5 | * Copyright Red Hat, Inc. 2017 | |
6 | * | |
7 | * Author: | |
8 | * Gerd Hoffmann <kraxel@redhat.com> | |
9 | * | |
10 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
11 | * See the COPYING file in the top-level directory. | |
12 | */ | |
71e8a915 | 13 | |
995b3017 GH |
14 | #include "qemu/osdep.h" |
15 | #include "qapi/error.h" | |
16 | #include "hw/loader.h" | |
17 | #include "hw/display/ramfb.h" | |
18 | #include "ui/console.h" | |
71e8a915 | 19 | #include "sysemu/reset.h" |
995b3017 GH |
20 | |
21 | struct QEMU_PACKED RAMFBCfg { | |
22 | uint64_t addr; | |
23 | uint32_t fourcc; | |
24 | uint32_t flags; | |
25 | uint32_t width; | |
26 | uint32_t height; | |
27 | uint32_t stride; | |
28 | }; | |
29 | ||
30 | struct RAMFBState { | |
31 | DisplaySurface *ds; | |
32 | uint32_t width, height; | |
33 | struct RAMFBCfg cfg; | |
34 | }; | |
35 | ||
d57f252a HQ |
36 | static void ramfb_unmap_display_surface(pixman_image_t *image, void *unused) |
37 | { | |
38 | void *data = pixman_image_get_data(image); | |
39 | uint32_t size = pixman_image_get_stride(image) * | |
40 | pixman_image_get_height(image); | |
41 | cpu_physical_memory_unmap(data, size, 0, 0); | |
42 | } | |
43 | ||
44 | static DisplaySurface *ramfb_create_display_surface(int width, int height, | |
45 | pixman_format_code_t format, | |
46 | int linesize, uint64_t addr) | |
47 | { | |
48 | DisplaySurface *surface; | |
49 | hwaddr size; | |
50 | void *data; | |
51 | ||
52 | if (linesize == 0) { | |
53 | linesize = width * PIXMAN_FORMAT_BPP(format) / 8; | |
54 | } | |
55 | ||
56 | size = (hwaddr)linesize * height; | |
85eb7c18 | 57 | data = cpu_physical_memory_map(addr, &size, false); |
d57f252a HQ |
58 | if (size != (hwaddr)linesize * height) { |
59 | cpu_physical_memory_unmap(data, size, 0, 0); | |
60 | return NULL; | |
61 | } | |
62 | ||
63 | surface = qemu_create_displaysurface_from(width, height, | |
64 | format, linesize, data); | |
65 | pixman_image_set_destroy_function(surface->image, | |
66 | ramfb_unmap_display_surface, NULL); | |
67 | ||
68 | return surface; | |
69 | } | |
70 | ||
995b3017 GH |
71 | static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len) |
72 | { | |
73 | RAMFBState *s = dev; | |
19aaee2a GH |
74 | DisplaySurface *surface; |
75 | uint32_t fourcc, format, width, height; | |
d57f252a | 76 | hwaddr stride, addr; |
995b3017 | 77 | |
19aaee2a GH |
78 | width = be32_to_cpu(s->cfg.width); |
79 | height = be32_to_cpu(s->cfg.height); | |
80 | stride = be32_to_cpu(s->cfg.stride); | |
81 | fourcc = be32_to_cpu(s->cfg.fourcc); | |
82 | addr = be64_to_cpu(s->cfg.addr); | |
83 | format = qemu_drm_format_to_pixman(fourcc); | |
84 | ||
85 | surface = ramfb_create_display_surface(width, height, | |
86 | format, stride, addr); | |
87 | if (!surface) { | |
88 | return; | |
89 | } | |
995b3017 | 90 | |
19aaee2a GH |
91 | s->width = width; |
92 | s->height = height; | |
93 | s->ds = surface; | |
995b3017 GH |
94 | } |
95 | ||
96 | void ramfb_display_update(QemuConsole *con, RAMFBState *s) | |
97 | { | |
98 | if (!s->width || !s->height) { | |
99 | return; | |
100 | } | |
101 | ||
102 | if (s->ds) { | |
103 | dpy_gfx_replace_surface(con, s->ds); | |
104 | s->ds = NULL; | |
105 | } | |
106 | ||
107 | /* simple full screen update */ | |
108 | dpy_gfx_update_full(con); | |
109 | } | |
110 | ||
2fc979cb | 111 | RAMFBState *ramfb_setup(Error **errp) |
995b3017 GH |
112 | { |
113 | FWCfgState *fw_cfg = fw_cfg_find(); | |
114 | RAMFBState *s; | |
115 | ||
116 | if (!fw_cfg || !fw_cfg->dma_enabled) { | |
117 | error_setg(errp, "ramfb device requires fw_cfg with DMA"); | |
118 | return NULL; | |
119 | } | |
120 | ||
121 | s = g_new0(RAMFBState, 1); | |
122 | ||
9f5d9c19 | 123 | rom_add_vga("vgabios-ramfb.bin"); |
995b3017 GH |
124 | fw_cfg_add_file_callback(fw_cfg, "etc/ramfb", |
125 | NULL, ramfb_fw_cfg_write, s, | |
126 | &s->cfg, sizeof(s->cfg), false); | |
127 | return s; | |
128 | } |