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 ((EFI_D_INFO
, "PixelBlueGreenRedReserved8BitPerColor\n"));
34 Info
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
36 Info
->PixelsPerScanLine
= Info
->HorizontalResolution
;
42 QemuVideoCompleteModeData (
43 IN QEMU_VIDEO_PRIVATE_DATA
*Private
,
44 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*Mode
47 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
48 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*FrameBufDesc
;
49 QEMU_VIDEO_MODE_DATA
*ModeData
;
51 ModeData
= &Private
->ModeData
[Mode
->Mode
];
53 QemuVideoCompleteModeInfo (ModeData
, Info
);
55 Private
->PciIo
->GetBarAttributes (
57 Private
->FrameBufferVramBarIndex
,
59 (VOID
**) &FrameBufDesc
62 Mode
->FrameBufferBase
= FrameBufDesc
->AddrRangeMin
;
63 Mode
->FrameBufferSize
= Info
->HorizontalResolution
* Info
->VerticalResolution
;
64 Mode
->FrameBufferSize
= Mode
->FrameBufferSize
* ((ModeData
->ColorDepth
+ 7) / 8);
65 Mode
->FrameBufferSize
= EFI_PAGES_TO_SIZE (
66 EFI_SIZE_TO_PAGES (Mode
->FrameBufferSize
)
68 DEBUG ((EFI_D_INFO
, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
69 Mode
->FrameBufferBase
, (UINT64
)Mode
->FrameBufferSize
));
71 FreePool (FrameBufDesc
);
76 // Graphics Output Protocol Member Functions
80 QemuVideoGraphicsOutputQueryMode (
81 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
83 OUT UINTN
*SizeOfInfo
,
84 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
90 Graphics Output protocol interface to query video mode
93 This - Protocol instance pointer.
94 ModeNumber - The mode number to return information on.
95 Info - Caller allocated buffer that returns information about ModeNumber.
96 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
99 EFI_SUCCESS - Mode information returned.
100 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
101 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
102 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
103 EFI_INVALID_PARAMETER - One of the input args was NULL.
107 QEMU_VIDEO_PRIVATE_DATA
*Private
;
108 QEMU_VIDEO_MODE_DATA
*ModeData
;
110 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
112 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
113 return EFI_INVALID_PARAMETER
;
116 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
118 return EFI_OUT_OF_RESOURCES
;
121 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
123 ModeData
= &Private
->ModeData
[ModeNumber
];
124 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
125 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
126 QemuVideoCompleteModeInfo (ModeData
, *Info
);
133 QemuVideoGraphicsOutputSetMode (
134 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
141 Graphics Output protocol interface to set video mode
144 This - Protocol instance pointer.
145 ModeNumber - The mode number to be set.
148 EFI_SUCCESS - Graphics mode was changed.
149 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
150 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
154 QEMU_VIDEO_PRIVATE_DATA
*Private
;
155 QEMU_VIDEO_MODE_DATA
*ModeData
;
156 RETURN_STATUS Status
;
157 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black
;
159 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
161 if (ModeNumber
>= This
->Mode
->MaxMode
) {
162 return EFI_UNSUPPORTED
;
165 ModeData
= &Private
->ModeData
[ModeNumber
];
167 switch (Private
->Variant
) {
168 case QEMU_VIDEO_CIRRUS_5430
:
169 case QEMU_VIDEO_CIRRUS_5446
:
170 InitializeCirrusGraphicsMode (Private
, &QemuVideoCirrusModes
[ModeData
->InternalModeIndex
]);
172 case QEMU_VIDEO_BOCHS_MMIO
:
173 case QEMU_VIDEO_BOCHS
:
174 InitializeBochsGraphicsMode (Private
, &QemuVideoBochsModes
[ModeData
->InternalModeIndex
]);
178 return EFI_DEVICE_ERROR
;
181 This
->Mode
->Mode
= ModeNumber
;
182 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
183 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
184 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
186 QemuVideoCompleteModeData (Private
, This
->Mode
);
189 // Re-initialize the frame buffer configure when mode changes.
191 Status
= FrameBufferBltConfigure (
192 (VOID
*) (UINTN
) This
->Mode
->FrameBufferBase
,
194 Private
->FrameBufferBltConfigure
,
195 &Private
->FrameBufferBltConfigureSize
197 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
199 // Frame buffer configure may be larger in new mode.
201 if (Private
->FrameBufferBltConfigure
!= NULL
) {
202 FreePool (Private
->FrameBufferBltConfigure
);
204 Private
->FrameBufferBltConfigure
=
205 AllocatePool (Private
->FrameBufferBltConfigureSize
);
206 ASSERT (Private
->FrameBufferBltConfigure
!= NULL
);
209 // Create the configuration for FrameBufferBltLib
211 Status
= FrameBufferBltConfigure (
212 (VOID
*) (UINTN
) This
->Mode
->FrameBufferBase
,
214 Private
->FrameBufferBltConfigure
,
215 &Private
->FrameBufferBltConfigureSize
218 ASSERT (Status
== RETURN_SUCCESS
);
221 // Per UEFI Spec, need to clear the visible portions of the output display to black.
223 ZeroMem (&Black
, sizeof (Black
));
224 Status
= FrameBufferBlt (
225 Private
->FrameBufferBltConfigure
,
230 This
->Mode
->Info
->HorizontalResolution
, This
->Mode
->Info
->VerticalResolution
,
233 ASSERT_RETURN_ERROR (Status
);
240 QemuVideoGraphicsOutputBlt (
241 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
242 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
243 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
246 IN UINTN DestinationX
,
247 IN UINTN DestinationY
,
256 Graphics Output protocol instance to block transfer for CirrusLogic device
260 This - Pointer to Graphics Output protocol instance
261 BltBuffer - The data to transfer to screen
262 BltOperation - The operation to perform
263 SourceX - The X coordinate of the source for BltOperation
264 SourceY - The Y coordinate of the source for BltOperation
265 DestinationX - The X coordinate of the destination for BltOperation
266 DestinationY - The Y coordinate of the destination for BltOperation
267 Width - The width of a rectangle in the blt rectangle in pixels
268 Height - The height of a rectangle in the blt rectangle in pixels
269 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
270 If a Delta of 0 is used, the entire BltBuffer will be operated on.
271 If a subrectangle of the BltBuffer is used, then Delta represents
272 the number of bytes in a row of the BltBuffer.
276 EFI_INVALID_PARAMETER - Invalid parameter passed in
277 EFI_SUCCESS - Blt operation success
283 QEMU_VIDEO_PRIVATE_DATA
*Private
;
285 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
287 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
288 // We would not want a timer based event (Cursor, ...) to come in while we are
289 // doing this operation.
291 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
293 switch (BltOperation
) {
294 case EfiBltVideoToBltBuffer
:
295 case EfiBltBufferToVideo
:
296 case EfiBltVideoFill
:
297 case EfiBltVideoToVideo
:
298 Status
= FrameBufferBlt (
299 Private
->FrameBufferBltConfigure
,
313 Status
= EFI_INVALID_PARAMETER
;
317 gBS
->RestoreTPL (OriginalTPL
);
323 QemuVideoGraphicsOutputConstructor (
324 QEMU_VIDEO_PRIVATE_DATA
*Private
328 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
331 GraphicsOutput
= &Private
->GraphicsOutput
;
332 GraphicsOutput
->QueryMode
= QemuVideoGraphicsOutputQueryMode
;
333 GraphicsOutput
->SetMode
= QemuVideoGraphicsOutputSetMode
;
334 GraphicsOutput
->Blt
= QemuVideoGraphicsOutputBlt
;
337 // Initialize the private data
339 Status
= gBS
->AllocatePool (
341 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
342 (VOID
**) &Private
->GraphicsOutput
.Mode
344 if (EFI_ERROR (Status
)) {
348 Status
= gBS
->AllocatePool (
350 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
351 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
353 if (EFI_ERROR (Status
)) {
356 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) Private
->MaxMode
;
357 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
358 Private
->FrameBufferBltConfigure
= NULL
;
359 Private
->FrameBufferBltConfigureSize
= 0;
362 // Initialize the hardware
364 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, 0);
365 if (EFI_ERROR (Status
)) {
371 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
372 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
378 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
381 FreePool (Private
->GraphicsOutput
.Mode
);
382 Private
->GraphicsOutput
.Mode
= NULL
;
388 QemuVideoGraphicsOutputDestructor (
389 QEMU_VIDEO_PRIVATE_DATA
*Private
403 if (Private
->FrameBufferBltConfigure
!= NULL
) {
404 FreePool (Private
->FrameBufferBltConfigure
);
407 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
408 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
409 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
411 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);