2 Graphics Output Protocol functions for the QEMU video controller.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
14 QemuVideoCompleteModeInfo (
15 IN QEMU_VIDEO_MODE_DATA
*ModeData
,
16 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
20 if (ModeData
->ColorDepth
== 8) {
21 Info
->PixelFormat
= PixelBitMask
;
22 Info
->PixelInformation
.RedMask
= PIXEL_RED_MASK
;
23 Info
->PixelInformation
.GreenMask
= PIXEL_GREEN_MASK
;
24 Info
->PixelInformation
.BlueMask
= PIXEL_BLUE_MASK
;
25 Info
->PixelInformation
.ReservedMask
= 0;
26 } else if (ModeData
->ColorDepth
== 24) {
27 Info
->PixelFormat
= PixelBitMask
;
28 Info
->PixelInformation
.RedMask
= PIXEL24_RED_MASK
;
29 Info
->PixelInformation
.GreenMask
= PIXEL24_GREEN_MASK
;
30 Info
->PixelInformation
.BlueMask
= PIXEL24_BLUE_MASK
;
31 Info
->PixelInformation
.ReservedMask
= 0;
32 } else if (ModeData
->ColorDepth
== 32) {
33 DEBUG ((DEBUG_INFO
, "PixelBlueGreenRedReserved8BitPerColor\n"));
34 Info
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
35 Info
->PixelInformation
.RedMask
= 0;
36 Info
->PixelInformation
.GreenMask
= 0;
37 Info
->PixelInformation
.BlueMask
= 0;
38 Info
->PixelInformation
.ReservedMask
= 0;
40 DEBUG ((DEBUG_ERROR
, "%a: Invalid ColorDepth %u", __FUNCTION__
, ModeData
->ColorDepth
));
44 Info
->PixelsPerScanLine
= Info
->HorizontalResolution
;
49 QemuVideoCompleteModeData (
50 IN QEMU_VIDEO_PRIVATE_DATA
*Private
,
51 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*Mode
54 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
55 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*FrameBufDesc
;
56 QEMU_VIDEO_MODE_DATA
*ModeData
;
58 ModeData
= &Private
->ModeData
[Mode
->Mode
];
60 QemuVideoCompleteModeInfo (ModeData
, Info
);
62 Private
->PciIo
->GetBarAttributes (
64 Private
->FrameBufferVramBarIndex
,
66 (VOID
**)&FrameBufDesc
69 Mode
->FrameBufferBase
= FrameBufDesc
->AddrRangeMin
;
70 Mode
->FrameBufferSize
= Info
->HorizontalResolution
* Info
->VerticalResolution
;
71 Mode
->FrameBufferSize
= Mode
->FrameBufferSize
* ((ModeData
->ColorDepth
+ 7) / 8);
72 Mode
->FrameBufferSize
= EFI_PAGES_TO_SIZE (
73 EFI_SIZE_TO_PAGES (Mode
->FrameBufferSize
)
77 "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
78 Mode
->FrameBufferBase
,
79 (UINT64
)Mode
->FrameBufferSize
82 FreePool (FrameBufDesc
);
87 // Graphics Output Protocol Member Functions
91 QemuVideoGraphicsOutputQueryMode (
92 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
94 OUT UINTN
*SizeOfInfo
,
95 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
102 Graphics Output protocol interface to query video mode
105 This - Protocol instance pointer.
106 ModeNumber - The mode number to return information on.
107 Info - Caller allocated buffer that returns information about ModeNumber.
108 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
111 EFI_SUCCESS - Mode information returned.
112 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
113 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
114 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
115 EFI_INVALID_PARAMETER - One of the input args was NULL.
119 QEMU_VIDEO_PRIVATE_DATA
*Private
;
120 QEMU_VIDEO_MODE_DATA
*ModeData
;
122 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
124 if ((Info
== NULL
) || (SizeOfInfo
== NULL
) || (ModeNumber
>= This
->Mode
->MaxMode
)) {
125 return EFI_INVALID_PARAMETER
;
128 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
130 return EFI_OUT_OF_RESOURCES
;
133 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
135 ModeData
= &Private
->ModeData
[ModeNumber
];
136 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
137 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
138 QemuVideoCompleteModeInfo (ModeData
, *Info
);
145 QemuVideoGraphicsOutputSetMode (
146 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
154 Graphics Output protocol interface to set video mode
157 This - Protocol instance pointer.
158 ModeNumber - The mode number to be set.
161 EFI_SUCCESS - Graphics mode was changed.
162 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
163 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
167 QEMU_VIDEO_PRIVATE_DATA
*Private
;
168 QEMU_VIDEO_MODE_DATA
*ModeData
;
169 RETURN_STATUS Status
;
170 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black
;
172 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
174 if (ModeNumber
>= This
->Mode
->MaxMode
) {
175 return EFI_UNSUPPORTED
;
178 ModeData
= &Private
->ModeData
[ModeNumber
];
180 switch (Private
->Variant
) {
181 case QEMU_VIDEO_CIRRUS_5430
:
182 case QEMU_VIDEO_CIRRUS_5446
:
183 InitializeCirrusGraphicsMode (Private
, &QemuVideoCirrusModes
[ModeData
->InternalModeIndex
]);
185 case QEMU_VIDEO_BOCHS_MMIO
:
186 case QEMU_VIDEO_BOCHS
:
187 InitializeBochsGraphicsMode (Private
, ModeData
);
191 return EFI_DEVICE_ERROR
;
194 This
->Mode
->Mode
= ModeNumber
;
195 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
196 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
197 This
->Mode
->SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
199 QemuVideoCompleteModeData (Private
, This
->Mode
);
202 // Re-initialize the frame buffer configure when mode changes.
204 Status
= FrameBufferBltConfigure (
205 (VOID
*)(UINTN
)This
->Mode
->FrameBufferBase
,
207 Private
->FrameBufferBltConfigure
,
208 &Private
->FrameBufferBltConfigureSize
210 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
212 // Frame buffer configure may be larger in new mode.
214 if (Private
->FrameBufferBltConfigure
!= NULL
) {
215 FreePool (Private
->FrameBufferBltConfigure
);
218 Private
->FrameBufferBltConfigure
=
219 AllocatePool (Private
->FrameBufferBltConfigureSize
);
220 ASSERT (Private
->FrameBufferBltConfigure
!= NULL
);
223 // Create the configuration for FrameBufferBltLib
225 Status
= FrameBufferBltConfigure (
226 (VOID
*)(UINTN
)This
->Mode
->FrameBufferBase
,
228 Private
->FrameBufferBltConfigure
,
229 &Private
->FrameBufferBltConfigureSize
233 ASSERT (Status
== RETURN_SUCCESS
);
236 // Per UEFI Spec, need to clear the visible portions of the output display to black.
238 ZeroMem (&Black
, sizeof (Black
));
239 Status
= FrameBufferBlt (
240 Private
->FrameBufferBltConfigure
,
247 This
->Mode
->Info
->HorizontalResolution
,
248 This
->Mode
->Info
->VerticalResolution
,
251 ASSERT_RETURN_ERROR (Status
);
258 QemuVideoGraphicsOutputBlt (
259 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
260 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer OPTIONAL
,
261 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
264 IN UINTN DestinationX
,
265 IN UINTN DestinationY
,
275 Graphics Output protocol instance to block transfer for CirrusLogic device
279 This - Pointer to Graphics Output protocol instance
280 BltBuffer - The data to transfer to screen
281 BltOperation - The operation to perform
282 SourceX - The X coordinate of the source for BltOperation
283 SourceY - The Y coordinate of the source for BltOperation
284 DestinationX - The X coordinate of the destination for BltOperation
285 DestinationY - The Y coordinate of the destination for BltOperation
286 Width - The width of a rectangle in the blt rectangle in pixels
287 Height - The height of a rectangle in the blt rectangle in pixels
288 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
289 If a Delta of 0 is used, the entire BltBuffer will be operated on.
290 If a subrectangle of the BltBuffer is used, then Delta represents
291 the number of bytes in a row of the BltBuffer.
295 EFI_INVALID_PARAMETER - Invalid parameter passed in
296 EFI_SUCCESS - Blt operation success
302 QEMU_VIDEO_PRIVATE_DATA
*Private
;
304 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
306 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
307 // We would not want a timer based event (Cursor, ...) to come in while we are
308 // doing this operation.
310 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
312 switch (BltOperation
) {
313 case EfiBltVideoToBltBuffer
:
314 case EfiBltBufferToVideo
:
315 case EfiBltVideoFill
:
316 case EfiBltVideoToVideo
:
317 Status
= FrameBufferBlt (
318 Private
->FrameBufferBltConfigure
,
332 Status
= EFI_INVALID_PARAMETER
;
336 gBS
->RestoreTPL (OriginalTPL
);
342 QemuVideoGraphicsOutputConstructor (
343 QEMU_VIDEO_PRIVATE_DATA
*Private
347 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
349 GraphicsOutput
= &Private
->GraphicsOutput
;
350 GraphicsOutput
->QueryMode
= QemuVideoGraphicsOutputQueryMode
;
351 GraphicsOutput
->SetMode
= QemuVideoGraphicsOutputSetMode
;
352 GraphicsOutput
->Blt
= QemuVideoGraphicsOutputBlt
;
355 // Initialize the private data
357 Status
= gBS
->AllocatePool (
359 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
360 (VOID
**)&Private
->GraphicsOutput
.Mode
362 if (EFI_ERROR (Status
)) {
366 Status
= gBS
->AllocatePool (
368 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
369 (VOID
**)&Private
->GraphicsOutput
.Mode
->Info
371 if (EFI_ERROR (Status
)) {
375 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
)Private
->MaxMode
;
376 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
377 Private
->FrameBufferBltConfigure
= NULL
;
378 Private
->FrameBufferBltConfigureSize
= 0;
381 // Initialize the hardware
383 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, 0);
384 if (EFI_ERROR (Status
)) {
390 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
391 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
397 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
400 FreePool (Private
->GraphicsOutput
.Mode
);
401 Private
->GraphicsOutput
.Mode
= NULL
;
407 QemuVideoGraphicsOutputDestructor (
408 QEMU_VIDEO_PRIVATE_DATA
*Private
423 if (Private
->FrameBufferBltConfigure
!= NULL
) {
424 FreePool (Private
->FrameBufferBltConfigure
);
427 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
428 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
429 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
432 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);