TianoCore EDK2 master
Loading...
Searching...
No Matches
QemuRamfb.c
Go to the documentation of this file.
1
12
13#include <Library/BaseLib.h>
15#include <Library/DebugLib.h>
21
22#include <Guid/QemuRamfb.h>
23
24#define RAMFB_FORMAT 0x34325258 /* DRM_FORMAT_XRGB8888 */
25#define RAMFB_BPP 4
26
27#pragma pack (1)
28typedef struct RAMFB_CONFIG {
29 UINT64 Address;
30 UINT32 FourCC;
31 UINT32 Flags;
32 UINT32 Width;
33 UINT32 Height;
34 UINT32 Stride;
36#pragma pack ()
37
38STATIC EFI_HANDLE mRamfbHandle;
39STATIC EFI_HANDLE mGopHandle;
40STATIC FRAME_BUFFER_CONFIGURE *mQemuRamfbFrameBufferBltConfigure;
41STATIC UINTN mQemuRamfbFrameBufferBltConfigureSize;
42STATIC FIRMWARE_CONFIG_ITEM mRamfbFwCfgItem;
43
44STATIC EFI_GRAPHICS_OUTPUT_MODE_INFORMATION mQemuRamfbModeInfo[] = {
45 {
46 0, // Version
47 640, // HorizontalResolution
48 480, // VerticalResolution
49 },{
50 0, // Version
51 800, // HorizontalResolution
52 600, // VerticalResolution
53 },{
54 0, // Version
55 1024, // HorizontalResolution
56 768, // VerticalResolution
57 }
58};
59
61 ARRAY_SIZE (mQemuRamfbModeInfo), // MaxMode
62 0, // Mode
63 mQemuRamfbModeInfo, // Info
64 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo
65};
66
69EFIAPI
70QemuRamfbGraphicsOutputQueryMode (
72 IN UINT32 ModeNumber,
73 OUT UINTN *SizeOfInfo,
75 )
76{
78
79 if ((Info == NULL) || (SizeOfInfo == NULL) ||
80 (ModeNumber >= mQemuRamfbMode.MaxMode))
81 {
82 return EFI_INVALID_PARAMETER;
83 }
84
85 ModeInfo = &mQemuRamfbModeInfo[ModeNumber];
86
87 *Info = AllocateCopyPool (
89 ModeInfo
90 );
91 if (*Info == NULL) {
92 return EFI_OUT_OF_RESOURCES;
93 }
94
95 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
96
97 return EFI_SUCCESS;
98}
99
100STATIC
102EFIAPI
103QemuRamfbGraphicsOutputSetMode (
105 IN UINT32 ModeNumber
106 )
107{
109 RAMFB_CONFIG Config;
111 RETURN_STATUS Status;
112
113 if (ModeNumber >= mQemuRamfbMode.MaxMode) {
114 return EFI_UNSUPPORTED;
115 }
116
117 ModeInfo = &mQemuRamfbModeInfo[ModeNumber];
118
119 DEBUG ((
120 DEBUG_INFO,
121 "Ramfb: SetMode %u (%ux%u)\n",
122 ModeNumber,
123 ModeInfo->HorizontalResolution,
124 ModeInfo->VerticalResolution
125 ));
126
127 Config.Address = SwapBytes64 (mQemuRamfbMode.FrameBufferBase);
128 Config.FourCC = SwapBytes32 (RAMFB_FORMAT);
129 Config.Flags = SwapBytes32 (0);
130 Config.Width = SwapBytes32 (ModeInfo->HorizontalResolution);
131 Config.Height = SwapBytes32 (ModeInfo->VerticalResolution);
132 Config.Stride = SwapBytes32 (ModeInfo->HorizontalResolution * RAMFB_BPP);
133
134 Status = FrameBufferBltConfigure (
135 (VOID *)(UINTN)mQemuRamfbMode.FrameBufferBase,
136 ModeInfo,
137 mQemuRamfbFrameBufferBltConfigure,
138 &mQemuRamfbFrameBufferBltConfigureSize
139 );
140
141 if (Status == RETURN_BUFFER_TOO_SMALL) {
142 if (mQemuRamfbFrameBufferBltConfigure != NULL) {
143 FreePool (mQemuRamfbFrameBufferBltConfigure);
144 }
145
146 mQemuRamfbFrameBufferBltConfigure =
147 AllocatePool (mQemuRamfbFrameBufferBltConfigureSize);
148 if (mQemuRamfbFrameBufferBltConfigure == NULL) {
149 mQemuRamfbFrameBufferBltConfigureSize = 0;
150 return EFI_OUT_OF_RESOURCES;
151 }
152
153 Status = FrameBufferBltConfigure (
154 (VOID *)(UINTN)mQemuRamfbMode.FrameBufferBase,
155 ModeInfo,
156 mQemuRamfbFrameBufferBltConfigure,
157 &mQemuRamfbFrameBufferBltConfigureSize
158 );
159 }
160
161 if (RETURN_ERROR (Status)) {
162 ASSERT (Status == RETURN_UNSUPPORTED);
163 return Status;
164 }
165
166 mQemuRamfbMode.Mode = ModeNumber;
167 mQemuRamfbMode.Info = ModeInfo;
168
169 QemuFwCfgSelectItem (mRamfbFwCfgItem);
170 QemuFwCfgWriteBytes (sizeof (Config), &Config);
171
172 //
173 // clear screen
174 //
175 ZeroMem (&Black, sizeof (Black));
176 Status = FrameBufferBlt (
177 mQemuRamfbFrameBufferBltConfigure,
178 &Black,
180 0, // SourceX -- ignored
181 0, // SourceY -- ignored
182 0, // DestinationX
183 0, // DestinationY
184 ModeInfo->HorizontalResolution, // Width
185 ModeInfo->VerticalResolution, // Height
186 0 // Delta -- ignored
187 );
188 if (RETURN_ERROR (Status)) {
189 DEBUG ((
190 DEBUG_WARN,
191 "%a: clearing the screen failed: %r\n",
192 __func__,
193 Status
194 ));
195 }
196
197 return EFI_SUCCESS;
198}
199
200STATIC
202EFIAPI
203QemuRamfbGraphicsOutputBlt (
205 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
207 IN UINTN SourceX,
208 IN UINTN SourceY,
209 IN UINTN DestinationX,
210 IN UINTN DestinationY,
211 IN UINTN Width,
212 IN UINTN Height,
213 IN UINTN Delta
214 )
215{
216 return FrameBufferBlt (
217 mQemuRamfbFrameBufferBltConfigure,
218 BltBuffer,
219 BltOperation,
220 SourceX,
221 SourceY,
222 DestinationX,
223 DestinationY,
224 Width,
225 Height,
226 Delta
227 );
228}
229
230STATIC EFI_GRAPHICS_OUTPUT_PROTOCOL mQemuRamfbGraphicsOutput = {
231 QemuRamfbGraphicsOutputQueryMode,
232 QemuRamfbGraphicsOutputSetMode,
233 QemuRamfbGraphicsOutputBlt,
234 &mQemuRamfbMode,
235};
236
238EFIAPI
239InitializeQemuRamfb (
240 IN EFI_HANDLE ImageHandle,
241 IN EFI_SYSTEM_TABLE *SystemTable
242 )
243{
244 EFI_DEVICE_PATH_PROTOCOL *RamfbDevicePath;
245 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
246 VOID *DevicePath;
247 VENDOR_DEVICE_PATH VendorDeviceNode;
248 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
249 EFI_STATUS Status;
251 UINTN FbSize, MaxFbSize, Pages;
252 UINTN FwCfgSize;
253 UINTN Index;
254
255 if (!QemuFwCfgIsAvailable ()) {
256 DEBUG ((DEBUG_INFO, "Ramfb: no FwCfg\n"));
257 return EFI_NOT_FOUND;
258 }
259
260 Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize);
261 if (EFI_ERROR (Status)) {
262 return EFI_NOT_FOUND;
263 }
264
265 if (FwCfgSize != sizeof (RAMFB_CONFIG)) {
266 DEBUG ((
267 DEBUG_ERROR,
268 "Ramfb: FwCfg size mismatch (expected %lu, got %lu)\n",
269 (UINT64)sizeof (RAMFB_CONFIG),
270 (UINT64)FwCfgSize
271 ));
272 return EFI_PROTOCOL_ERROR;
273 }
274
275 MaxFbSize = 0;
276 for (Index = 0; Index < ARRAY_SIZE (mQemuRamfbModeInfo); Index++) {
277 mQemuRamfbModeInfo[Index].PixelsPerScanLine =
278 mQemuRamfbModeInfo[Index].HorizontalResolution;
279 mQemuRamfbModeInfo[Index].PixelFormat =
281 FbSize = RAMFB_BPP *
282 mQemuRamfbModeInfo[Index].HorizontalResolution *
283 mQemuRamfbModeInfo[Index].VerticalResolution;
284 if (MaxFbSize < FbSize) {
285 MaxFbSize = FbSize;
286 }
287
288 DEBUG ((
289 DEBUG_INFO,
290 "Ramfb: Mode %lu: %ux%u, %lu kB\n",
291 (UINT64)Index,
292 mQemuRamfbModeInfo[Index].HorizontalResolution,
293 mQemuRamfbModeInfo[Index].VerticalResolution,
294 (UINT64)(FbSize / 1024)
295 ));
296 }
297
298 Pages = EFI_SIZE_TO_PAGES (MaxFbSize);
299 MaxFbSize = EFI_PAGES_TO_SIZE (Pages);
301 if (FbBase == 0) {
302 DEBUG ((DEBUG_ERROR, "Ramfb: memory allocation failed\n"));
303 return EFI_OUT_OF_RESOURCES;
304 }
305
306 DEBUG ((
307 DEBUG_INFO,
308 "Ramfb: Framebuffer at 0x%lx, %lu kB, %lu pages\n",
309 (UINT64)FbBase,
310 (UINT64)(MaxFbSize / 1024),
311 (UINT64)Pages
312 ));
313 mQemuRamfbMode.FrameBufferSize = MaxFbSize;
314 mQemuRamfbMode.FrameBufferBase = FbBase;
315
316 //
317 // 800 x 600
318 //
319 QemuRamfbGraphicsOutputSetMode (&mQemuRamfbGraphicsOutput, 1);
320
321 //
322 // ramfb vendor devpath
323 //
324 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
325 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
326 CopyGuid (&VendorDeviceNode.Guid, &gQemuRamfbGuid);
328 &VendorDeviceNode.Header,
329 sizeof (VENDOR_DEVICE_PATH)
330 );
331
332 RamfbDevicePath = AppendDevicePathNode (
333 NULL,
334 (EFI_DEVICE_PATH_PROTOCOL *)&VendorDeviceNode
335 );
336 if (RamfbDevicePath == NULL) {
337 Status = EFI_OUT_OF_RESOURCES;
338 goto FreeFramebuffer;
339 }
340
341 Status = gBS->InstallMultipleProtocolInterfaces (
342 &mRamfbHandle,
343 &gEfiDevicePathProtocolGuid,
344 RamfbDevicePath,
345 NULL
346 );
347 if (EFI_ERROR (Status)) {
348 DEBUG ((
349 DEBUG_ERROR,
350 "Ramfb: install Ramfb Vendor DevicePath failed: %r\n",
351 Status
352 ));
353 goto FreeRamfbDevicePath;
354 }
355
356 //
357 // gop devpath + protocol
358 //
359 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
360 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
361 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (
362 1, // DeviceIdScheme
363 0, // HeadId
364 0, // NonVgaOutput
365 1, // BiosCanDetect
366 0, // VendorInfo
367 ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type
368 0, // Port
369 0 // Index
370 );
372 &AcpiDeviceNode.Header,
373 sizeof (ACPI_ADR_DEVICE_PATH)
374 );
375
376 GopDevicePath = AppendDevicePathNode (
377 RamfbDevicePath,
378 (EFI_DEVICE_PATH_PROTOCOL *)&AcpiDeviceNode
379 );
380 if (GopDevicePath == NULL) {
381 Status = EFI_OUT_OF_RESOURCES;
382 goto FreeRamfbHandle;
383 }
384
385 Status = gBS->InstallMultipleProtocolInterfaces (
386 &mGopHandle,
387 &gEfiDevicePathProtocolGuid,
388 GopDevicePath,
389 &gEfiGraphicsOutputProtocolGuid,
390 &mQemuRamfbGraphicsOutput,
391 NULL
392 );
393 if (EFI_ERROR (Status)) {
394 DEBUG ((
395 DEBUG_ERROR,
396 "Ramfb: install GOP DevicePath failed: %r\n",
397 Status
398 ));
399 goto FreeGopDevicePath;
400 }
401
402 Status = gBS->OpenProtocol (
403 mRamfbHandle,
404 &gEfiDevicePathProtocolGuid,
405 &DevicePath,
407 mGopHandle,
408 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
409 );
410 if (EFI_ERROR (Status)) {
411 DEBUG ((DEBUG_ERROR, "Ramfb: OpenProtocol failed: %r\n", Status));
412 goto FreeGopHandle;
413 }
414
415 return EFI_SUCCESS;
416
417FreeGopHandle:
418 gBS->UninstallMultipleProtocolInterfaces (
419 mGopHandle,
420 &gEfiDevicePathProtocolGuid,
421 GopDevicePath,
422 &gEfiGraphicsOutputProtocolGuid,
423 &mQemuRamfbGraphicsOutput,
424 NULL
425 );
426FreeGopDevicePath:
427 FreePool (GopDevicePath);
428FreeRamfbHandle:
429 gBS->UninstallMultipleProtocolInterfaces (
430 mRamfbHandle,
431 &gEfiDevicePathProtocolGuid,
432 RamfbDevicePath,
433 NULL
434 );
435FreeRamfbDevicePath:
436 FreePool (RamfbDevicePath);
437FreeFramebuffer:
438 FreePages ((VOID *)(UINTN)mQemuRamfbMode.FrameBufferBase, Pages);
439 return Status;
440}
UINT64 UINTN
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define HW_VENDOR_DP
Definition: DevicePath.h:133
#define ACPI_DEVICE_PATH
Definition: DevicePath.h:190
#define ACPI_ADR_DP
Definition: DevicePath.h:264
UINT16 EFIAPI SetDevicePathNodeLength(IN OUT VOID *Node, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
VOID EFIAPI FreePages(IN VOID *Buffer, IN UINTN Pages)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateReservedPages(IN UINTN Pages)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
RETURN_STATUS EFIAPI FrameBufferBlt(IN FRAME_BUFFER_CONFIGURE *Configure, IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta)
RETURN_STATUS EFIAPI FrameBufferBltConfigure(IN VOID *FrameBuffer, IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *FrameBufferInfo, IN OUT FRAME_BUFFER_CONFIGURE *Configure, IN OUT UINTN *ConfigureSize)
#define NULL
Definition: Base.h:319
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define STATIC
Definition: Base.h:264
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_GRAPHICS_OUTPUT_BLT_OPERATION
@ EfiBltVideoFill
@ PixelBlueGreenRedReserved8BitPerColor
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI QemuFwCfgWriteBytes(IN UINTN Size, IN VOID *Buffer)
Definition: QemuFwCfgLib.c:101
RETURN_STATUS EFIAPI QemuFwCfgFindFile(IN CONST CHAR8 *Name, OUT FIRMWARE_CONFIG_ITEM *Item, OUT UINTN *Size)
Definition: QemuFwCfgLib.c:250
VOID EFIAPI QemuFwCfgSelectItem(IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem)
Definition: QemuFwCfgLib.c:33
BOOLEAN EFIAPI QemuFwCfgIsAvailable(VOID)
Definition: QemuFwCfgDxe.c:44
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat
EFI_PHYSICAL_ADDRESS FrameBufferBase
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * Info