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.
20 QemuVideoCompleteModeInfo (
21 IN QEMU_VIDEO_MODE_DATA
*ModeData
,
22 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
26 if (ModeData
->ColorDepth
== 8) {
27 Info
->PixelFormat
= PixelBitMask
;
28 Info
->PixelInformation
.RedMask
= PIXEL_RED_MASK
;
29 Info
->PixelInformation
.GreenMask
= PIXEL_GREEN_MASK
;
30 Info
->PixelInformation
.BlueMask
= PIXEL_BLUE_MASK
;
31 Info
->PixelInformation
.ReservedMask
= 0;
32 } else if (ModeData
->ColorDepth
== 24) {
33 Info
->PixelFormat
= PixelBitMask
;
34 Info
->PixelInformation
.RedMask
= PIXEL24_RED_MASK
;
35 Info
->PixelInformation
.GreenMask
= PIXEL24_GREEN_MASK
;
36 Info
->PixelInformation
.BlueMask
= PIXEL24_BLUE_MASK
;
37 Info
->PixelInformation
.ReservedMask
= 0;
38 } else if (ModeData
->ColorDepth
== 32) {
39 DEBUG ((EFI_D_INFO
, "PixelBlueGreenRedReserved8BitPerColor\n"));
40 Info
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
42 Info
->PixelsPerScanLine
= Info
->HorizontalResolution
;
48 QemuVideoCompleteModeData (
49 IN QEMU_VIDEO_PRIVATE_DATA
*Private
,
50 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*Mode
53 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
54 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*FrameBufDesc
;
55 QEMU_VIDEO_MODE_DATA
*ModeData
;
57 ModeData
= &Private
->ModeData
[Mode
->Mode
];
59 QemuVideoCompleteModeInfo (ModeData
, Info
);
61 Private
->PciIo
->GetBarAttributes (
63 Private
->FrameBufferVramBarIndex
,
65 (VOID
**) &FrameBufDesc
68 Mode
->FrameBufferBase
= FrameBufDesc
->AddrRangeMin
;
69 Mode
->FrameBufferSize
= Info
->HorizontalResolution
* Info
->VerticalResolution
;
70 Mode
->FrameBufferSize
= Mode
->FrameBufferSize
* ((ModeData
->ColorDepth
+ 7) / 8);
71 Mode
->FrameBufferSize
= EFI_PAGES_TO_SIZE (
72 EFI_SIZE_TO_PAGES (Mode
->FrameBufferSize
)
74 DEBUG ((EFI_D_INFO
, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
75 Mode
->FrameBufferBase
, (UINT64
)Mode
->FrameBufferSize
));
77 FreePool (FrameBufDesc
);
82 // Graphics Output Protocol Member Functions
86 QemuVideoGraphicsOutputQueryMode (
87 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
89 OUT UINTN
*SizeOfInfo
,
90 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
96 Graphics Output protocol interface to query video mode
99 This - Protocol instance pointer.
100 ModeNumber - The mode number to return information on.
101 Info - Caller allocated buffer that returns information about ModeNumber.
102 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
105 EFI_SUCCESS - Mode information returned.
106 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
107 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
108 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
109 EFI_INVALID_PARAMETER - One of the input args was NULL.
113 QEMU_VIDEO_PRIVATE_DATA
*Private
;
114 QEMU_VIDEO_MODE_DATA
*ModeData
;
116 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
118 if (Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
119 return EFI_INVALID_PARAMETER
;
122 *Info
= AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
));
124 return EFI_OUT_OF_RESOURCES
;
127 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
129 ModeData
= &Private
->ModeData
[ModeNumber
];
130 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
131 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
132 QemuVideoCompleteModeInfo (ModeData
, *Info
);
139 QemuVideoGraphicsOutputSetMode (
140 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
147 Graphics Output protocol interface to set video mode
150 This - Protocol instance pointer.
151 ModeNumber - The mode number to be set.
154 EFI_SUCCESS - Graphics mode was changed.
155 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
156 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
160 QEMU_VIDEO_PRIVATE_DATA
*Private
;
161 QEMU_VIDEO_MODE_DATA
*ModeData
;
162 RETURN_STATUS Status
;
163 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black
;
165 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
167 if (ModeNumber
>= This
->Mode
->MaxMode
) {
168 return EFI_UNSUPPORTED
;
171 ModeData
= &Private
->ModeData
[ModeNumber
];
173 switch (Private
->Variant
) {
174 case QEMU_VIDEO_CIRRUS_5430
:
175 case QEMU_VIDEO_CIRRUS_5446
:
176 InitializeCirrusGraphicsMode (Private
, &QemuVideoCirrusModes
[ModeData
->InternalModeIndex
]);
178 case QEMU_VIDEO_BOCHS_MMIO
:
179 case QEMU_VIDEO_BOCHS
:
180 InitializeBochsGraphicsMode (Private
, &QemuVideoBochsModes
[ModeData
->InternalModeIndex
]);
184 return EFI_DEVICE_ERROR
;
187 This
->Mode
->Mode
= ModeNumber
;
188 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
189 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
190 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
192 QemuVideoCompleteModeData (Private
, This
->Mode
);
195 // Re-initialize the frame buffer configure when mode changes.
197 Status
= FrameBufferBltConfigure (
198 (VOID
*) (UINTN
) This
->Mode
->FrameBufferBase
,
200 Private
->FrameBufferBltConfigure
,
201 &Private
->FrameBufferBltConfigureSize
203 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
205 // Frame buffer configure may be larger in new mode.
207 if (Private
->FrameBufferBltConfigure
!= NULL
) {
208 FreePool (Private
->FrameBufferBltConfigure
);
210 Private
->FrameBufferBltConfigure
=
211 AllocatePool (Private
->FrameBufferBltConfigureSize
);
212 ASSERT (Private
->FrameBufferBltConfigure
!= NULL
);
215 // Create the configuration for FrameBufferBltLib
217 Status
= FrameBufferBltConfigure (
218 (VOID
*) (UINTN
) This
->Mode
->FrameBufferBase
,
220 Private
->FrameBufferBltConfigure
,
221 &Private
->FrameBufferBltConfigureSize
224 ASSERT (Status
== RETURN_SUCCESS
);
227 // Per UEFI Spec, need to clear the visible portions of the output display to black.
229 ZeroMem (&Black
, sizeof (Black
));
230 Status
= FrameBufferBlt (
231 Private
->FrameBufferBltConfigure
,
236 This
->Mode
->Info
->HorizontalResolution
, This
->Mode
->Info
->VerticalResolution
,
239 ASSERT_RETURN_ERROR (Status
);
246 QemuVideoGraphicsOutputBlt (
247 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
248 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
249 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
252 IN UINTN DestinationX
,
253 IN UINTN DestinationY
,
262 Graphics Output protocol instance to block transfer for CirrusLogic device
266 This - Pointer to Graphics Output protocol instance
267 BltBuffer - The data to transfer to screen
268 BltOperation - The operation to perform
269 SourceX - The X coordinate of the source for BltOperation
270 SourceY - The Y coordinate of the source for BltOperation
271 DestinationX - The X coordinate of the destination for BltOperation
272 DestinationY - The Y coordinate of the destination for BltOperation
273 Width - The width of a rectangle in the blt rectangle in pixels
274 Height - The height of a rectangle in the blt rectangle in pixels
275 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
276 If a Delta of 0 is used, the entire BltBuffer will be operated on.
277 If a subrectangle of the BltBuffer is used, then Delta represents
278 the number of bytes in a row of the BltBuffer.
282 EFI_INVALID_PARAMETER - Invalid parameter passed in
283 EFI_SUCCESS - Blt operation success
289 QEMU_VIDEO_PRIVATE_DATA
*Private
;
291 Private
= QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This
);
293 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
294 // We would not want a timer based event (Cursor, ...) to come in while we are
295 // doing this operation.
297 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
299 switch (BltOperation
) {
300 case EfiBltVideoToBltBuffer
:
301 case EfiBltBufferToVideo
:
302 case EfiBltVideoFill
:
303 case EfiBltVideoToVideo
:
304 Status
= FrameBufferBlt (
305 Private
->FrameBufferBltConfigure
,
319 Status
= EFI_INVALID_PARAMETER
;
323 gBS
->RestoreTPL (OriginalTPL
);
329 QemuVideoGraphicsOutputConstructor (
330 QEMU_VIDEO_PRIVATE_DATA
*Private
334 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
337 GraphicsOutput
= &Private
->GraphicsOutput
;
338 GraphicsOutput
->QueryMode
= QemuVideoGraphicsOutputQueryMode
;
339 GraphicsOutput
->SetMode
= QemuVideoGraphicsOutputSetMode
;
340 GraphicsOutput
->Blt
= QemuVideoGraphicsOutputBlt
;
343 // Initialize the private data
345 Status
= gBS
->AllocatePool (
347 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
348 (VOID
**) &Private
->GraphicsOutput
.Mode
350 if (EFI_ERROR (Status
)) {
354 Status
= gBS
->AllocatePool (
356 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
357 (VOID
**) &Private
->GraphicsOutput
.Mode
->Info
359 if (EFI_ERROR (Status
)) {
362 Private
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) Private
->MaxMode
;
363 Private
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
364 Private
->FrameBufferBltConfigure
= NULL
;
365 Private
->FrameBufferBltConfigureSize
= 0;
368 // Initialize the hardware
370 Status
= GraphicsOutput
->SetMode (GraphicsOutput
, 0);
371 if (EFI_ERROR (Status
)) {
377 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].HorizontalResolution
,
378 Private
->ModeData
[Private
->GraphicsOutput
.Mode
->Mode
].VerticalResolution
384 FreePool (Private
->GraphicsOutput
.Mode
->Info
);
387 FreePool (Private
->GraphicsOutput
.Mode
);
388 Private
->GraphicsOutput
.Mode
= NULL
;
394 QemuVideoGraphicsOutputDestructor (
395 QEMU_VIDEO_PRIVATE_DATA
*Private
409 if (Private
->FrameBufferBltConfigure
!= NULL
) {
410 FreePool (Private
->FrameBufferBltConfigure
);
413 if (Private
->GraphicsOutput
.Mode
!= NULL
) {
414 if (Private
->GraphicsOutput
.Mode
->Info
!= NULL
) {
415 gBS
->FreePool (Private
->GraphicsOutput
.Mode
->Info
);
417 gBS
->FreePool (Private
->GraphicsOutput
.Mode
);