2 Graphics Output Protocol functions for the QEMU video controller.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <IndustryStandard/VmwareSvga.h>
21 QemuVideoCompleteModeInfo (
22 IN QEMU_VIDEO_MODE_DATA
*ModeData
,
23 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
27 if (ModeData
->ColorDepth
== 8) {
28 Info
->PixelFormat
= PixelBitMask
;
29 Info
->PixelInformation
.RedMask
= PIXEL_RED_MASK
;
30 Info
->PixelInformation
.GreenMask
= PIXEL_GREEN_MASK
;
31 Info
->PixelInformation
.BlueMask
= PIXEL_BLUE_MASK
;
32 Info
->PixelInformation
.ReservedMask
= 0;
33 } else if (ModeData
->ColorDepth
== 24) {
34 Info
->PixelFormat
= PixelBitMask
;
35 Info
->PixelInformation
.RedMask
= PIXEL24_RED_MASK
;
36 Info
->PixelInformation
.GreenMask
= PIXEL24_GREEN_MASK
;
37 Info
->PixelInformation
.BlueMask
= PIXEL24_BLUE_MASK
;
38 Info
->PixelInformation
.ReservedMask
= 0;
39 } else if (ModeData
->ColorDepth
== 32) {
40 DEBUG ((EFI_D_INFO
, "PixelBlueGreenRedReserved8BitPerColor\n"));
41 Info
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
43 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 (
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
)
75 DEBUG ((EFI_D_INFO
, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
76 Mode
->FrameBufferBase
, (UINT64
)Mode
->FrameBufferSize
));
78 FreePool (FrameBufDesc
);
84 QemuVideoVmwareSvgaCompleteModeData (
85 IN QEMU_VIDEO_PRIVATE_DATA
*Private
,
86 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*Mode
90 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
91 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*FrameBufDesc
;
92 UINT32 BytesPerLine
, FbOffset
, BytesPerPixel
;
95 CopyMem (Info
, &Private
->VmwareSvgaModeInfo
[Mode
->Mode
], sizeof (*Info
));
96 BytesPerPixel
= Private
->ModeData
[Mode
->Mode
].ColorDepth
/ 8;
97 BytesPerLine
= Info
->PixelsPerScanLine
* BytesPerPixel
;
99 FbOffset
= VmwareSvgaRead (Private
, VmwareSvgaRegFbOffset
);
101 Status
= Private
->PciIo
->GetBarAttributes (
105 (VOID
**) &FrameBufDesc
107 if (EFI_ERROR (Status
)) {
108 return EFI_DEVICE_ERROR
;
111 Mode
->FrameBufferBase
= FrameBufDesc
->AddrRangeMin
+ FbOffset
;
112 Mode
->FrameBufferSize
= BytesPerLine
* Info
->VerticalResolution
;
113 Mode
->FrameBufferSize
= EFI_PAGES_TO_SIZE (
114 EFI_SIZE_TO_PAGES (Mode
->FrameBufferSize
)
117 FreePool (FrameBufDesc
);
123 // Graphics Output Protocol Member Functions
127 QemuVideoGraphicsOutputQueryMode (
128 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
129 IN UINT32 ModeNumber
,
130 OUT UINTN
*SizeOfInfo
,
131 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
137 Graphics Output protocol interface to query video mode
140 This - Protocol instance pointer.
141 ModeNumber - The mode number to return information on.
142 Info - Caller allocated buffer that returns information about ModeNumber.
143 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
146 EFI_SUCCESS - Mode information returned.
147 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
148 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
149 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
150 EFI_INVALID_PARAMETER - One of the input args was NULL.
154 QEMU_VIDEO_PRIVATE_DATA
*Private
;
155 QEMU_VIDEO_MODE_DATA
*ModeData
;
157 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
159 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
160 return EFI_INVALID_PARAMETER
;
163 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
165 return EFI_OUT_OF_RESOURCES
;
168 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
170 if (Private
->Variant
== QEMU_VIDEO_VMWARE_SVGA
) {
171 CopyMem (*Info
, &Private
->VmwareSvgaModeInfo
[ModeNumber
], sizeof (**Info
));
173 ModeData
= &Private
->ModeData
[ModeNumber
];
174 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
175 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
176 QemuVideoCompleteModeInfo (ModeData
, *Info
);
184 QemuVideoGraphicsOutputSetMode (
185 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
192 Graphics Output protocol interface to set video mode
195 This - Protocol instance pointer.
196 ModeNumber - The mode number to be set.
199 EFI_SUCCESS - Graphics mode was changed.
200 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
201 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
205 QEMU_VIDEO_PRIVATE_DATA
*Private
;
206 QEMU_VIDEO_MODE_DATA
*ModeData
;
207 RETURN_STATUS Status
;
208 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black
;
210 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
212 if (ModeNumber
>= This
->Mode
->MaxMode
) {
213 return EFI_UNSUPPORTED
;
216 ModeData
= &Private
->ModeData
[ModeNumber
];
218 switch (Private
->Variant
) {
219 case QEMU_VIDEO_CIRRUS_5430
:
220 case QEMU_VIDEO_CIRRUS_5446
:
221 InitializeCirrusGraphicsMode (Private
, &QemuVideoCirrusModes
[ModeData
->InternalModeIndex
]);
223 case QEMU_VIDEO_BOCHS_MMIO
:
224 case QEMU_VIDEO_BOCHS
:
225 InitializeBochsGraphicsMode (Private
, &QemuVideoBochsModes
[ModeData
->InternalModeIndex
]);
227 case QEMU_VIDEO_VMWARE_SVGA
:
228 InitializeVmwareSvgaGraphicsMode (
230 &QemuVideoBochsModes
[ModeData
->InternalModeIndex
]
235 return EFI_DEVICE_ERROR
;
238 This
->Mode
->Mode
= ModeNumber
;
239 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
240 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
241 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
243 if (Private
->Variant
== QEMU_VIDEO_VMWARE_SVGA
) {
244 QemuVideoVmwareSvgaCompleteModeData (Private
, This
->Mode
);
246 QemuVideoCompleteModeData (Private
, This
->Mode
);
250 // Re-initialize the frame buffer configure when mode changes.
252 Status
= FrameBufferBltConfigure (
253 (VOID
*) (UINTN
) This
->Mode
->FrameBufferBase
,
255 Private
->FrameBufferBltConfigure
,
256 &Private
->FrameBufferBltConfigureSize
258 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
260 // Frame buffer configure may be larger in new mode.
262 if (Private
->FrameBufferBltConfigure
!= NULL
) {
263 FreePool (Private
->FrameBufferBltConfigure
);
265 Private
->FrameBufferBltConfigure
=
266 AllocatePool (Private
->FrameBufferBltConfigureSize
);
267 ASSERT (Private
->FrameBufferBltConfigure
!= NULL
);
270 // Create the configuration for FrameBufferBltLib
272 Status
= FrameBufferBltConfigure (
273 (VOID
*) (UINTN
) This
->Mode
->FrameBufferBase
,
275 Private
->FrameBufferBltConfigure
,
276 &Private
->FrameBufferBltConfigureSize
279 ASSERT (Status
== RETURN_SUCCESS
);
282 // Per UEFI Spec, need to clear the visible portions of the output display to black.
284 ZeroMem (&Black
, sizeof (Black
));
285 Status
= FrameBufferBlt (
286 Private
->FrameBufferBltConfigure
,
291 This
->Mode
->Info
->HorizontalResolution
, This
->Mode
->Info
->VerticalResolution
,
294 ASSERT_RETURN_ERROR (Status
);
301 QemuVideoGraphicsOutputBlt (
302 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
303 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
304 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
307 IN UINTN DestinationX
,
308 IN UINTN DestinationY
,
317 Graphics Output protocol instance to block transfer for CirrusLogic device
321 This - Pointer to Graphics Output protocol instance
322 BltBuffer - The data to transfer to screen
323 BltOperation - The operation to perform
324 SourceX - The X coordinate of the source for BltOperation
325 SourceY - The Y coordinate of the source for BltOperation
326 DestinationX - The X coordinate of the destination for BltOperation
327 DestinationY - The Y coordinate of the destination for BltOperation
328 Width - The width of a rectangle in the blt rectangle in pixels
329 Height - The height of a rectangle in the blt rectangle in pixels
330 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
331 If a Delta of 0 is used, the entire BltBuffer will be operated on.
332 If a subrectangle of the BltBuffer is used, then Delta represents
333 the number of bytes in a row of the BltBuffer.
337 EFI_INVALID_PARAMETER - Invalid parameter passed in
338 EFI_SUCCESS - Blt operation success
344 QEMU_VIDEO_PRIVATE_DATA
*Private
;
346 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
348 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
349 // We would not want a timer based event (Cursor, ...) to come in while we are
350 // doing this operation.
352 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
354 switch (BltOperation
) {
355 case EfiBltVideoToBltBuffer
:
356 case EfiBltBufferToVideo
:
357 case EfiBltVideoFill
:
358 case EfiBltVideoToVideo
:
359 Status
= FrameBufferBlt (
360 Private
->FrameBufferBltConfigure
,
374 Status
= EFI_INVALID_PARAMETER
;
378 gBS
->RestoreTPL (OriginalTPL
);
384 QemuVideoGraphicsOutputConstructor (
385 QEMU_VIDEO_PRIVATE_DATA
*Private
389 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
392 GraphicsOutput
= &Private
->GraphicsOutput
;
393 GraphicsOutput
->QueryMode
= QemuVideoGraphicsOutputQueryMode
;
394 GraphicsOutput
->SetMode
= QemuVideoGraphicsOutputSetMode
;
395 GraphicsOutput
->Blt
= QemuVideoGraphicsOutputBlt
;
398 // Initialize the private data
400 Status
= gBS
->AllocatePool (
402 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
403 (VOID
**) &Private
->GraphicsOutput
.Mode
405 if (EFI_ERROR (Status
)) {
409 Status
= gBS
->AllocatePool (
411 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
412 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
414 if (EFI_ERROR (Status
)) {
417 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) Private
->MaxMode
;
418 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
419 Private
->FrameBufferBltConfigure
= NULL
;
420 Private
->FrameBufferBltConfigureSize
= 0;
423 // Initialize the hardware
425 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, 0);
426 if (EFI_ERROR (Status
)) {
432 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
433 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
439 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
442 FreePool (Private
->GraphicsOutput
.Mode
);
443 Private
->GraphicsOutput
.Mode
= NULL
;
449 QemuVideoGraphicsOutputDestructor (
450 QEMU_VIDEO_PRIVATE_DATA
*Private
464 if (Private
->FrameBufferBltConfigure
!= NULL
) {
465 FreePool (Private
->FrameBufferBltConfigure
);
468 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
469 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
470 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
472 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);