]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Gop.c
359e9217d3d143fbbe90c6a742cd15b9e74cd73b
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Gop.c
1 /** @file
2 Graphics Output Protocol functions for the QEMU video controller.
3
4 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5
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
10
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.
13
14 **/
15
16 #include "Qemu.h"
17
18 STATIC
19 VOID
20 QemuVideoCompleteModeInfo (
21 IN QEMU_VIDEO_MODE_DATA *ModeData,
22 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
23 )
24 {
25 Info->Version = 0;
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;
41 }
42 Info->PixelsPerScanLine = Info->HorizontalResolution;
43 }
44
45
46 STATIC
47 EFI_STATUS
48 QemuVideoCompleteModeData (
49 IN QEMU_VIDEO_PRIVATE_DATA *Private,
50 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
51 )
52 {
53 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
54 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
55 QEMU_VIDEO_MODE_DATA *ModeData;
56
57 ModeData = &Private->ModeData[Mode->Mode];
58 Info = Mode->Info;
59 QemuVideoCompleteModeInfo (ModeData, Info);
60
61 Private->PciIo->GetBarAttributes (
62 Private->PciIo,
63 0,
64 NULL,
65 (VOID**) &FrameBufDesc
66 );
67
68 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
69 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
70 Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
71 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
72 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));
73
74 FreePool (FrameBufDesc);
75 return EFI_SUCCESS;
76 }
77
78
79 //
80 // Graphics Output Protocol Member Functions
81 //
82 EFI_STATUS
83 EFIAPI
84 QemuVideoGraphicsOutputQueryMode (
85 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
86 IN UINT32 ModeNumber,
87 OUT UINTN *SizeOfInfo,
88 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
89 )
90 /*++
91
92 Routine Description:
93
94 Graphics Output protocol interface to query video mode
95
96 Arguments:
97 This - Protocol instance pointer.
98 ModeNumber - The mode number to return information on.
99 Info - Caller allocated buffer that returns information about ModeNumber.
100 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
101
102 Returns:
103 EFI_SUCCESS - Mode information returned.
104 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
105 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
106 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
107 EFI_INVALID_PARAMETER - One of the input args was NULL.
108
109 --*/
110 {
111 QEMU_VIDEO_PRIVATE_DATA *Private;
112 QEMU_VIDEO_MODE_DATA *ModeData;
113
114 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
115
116 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
117 return EFI_INVALID_PARAMETER;
118 }
119
120 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
121 if (*Info == NULL) {
122 return EFI_OUT_OF_RESOURCES;
123 }
124
125 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
126
127 ModeData = &Private->ModeData[ModeNumber];
128 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
129 (*Info)->VerticalResolution = ModeData->VerticalResolution;
130 QemuVideoCompleteModeInfo (ModeData, *Info);
131
132 return EFI_SUCCESS;
133 }
134
135 EFI_STATUS
136 EFIAPI
137 QemuVideoGraphicsOutputSetMode (
138 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
139 IN UINT32 ModeNumber
140 )
141 /*++
142
143 Routine Description:
144
145 Graphics Output protocol interface to set video mode
146
147 Arguments:
148 This - Protocol instance pointer.
149 ModeNumber - The mode number to be set.
150
151 Returns:
152 EFI_SUCCESS - Graphics mode was changed.
153 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
154 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
155
156 --*/
157 {
158 QEMU_VIDEO_PRIVATE_DATA *Private;
159 QEMU_VIDEO_MODE_DATA *ModeData;
160 RETURN_STATUS Status;
161
162 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
163
164 if (ModeNumber >= This->Mode->MaxMode) {
165 return EFI_UNSUPPORTED;
166 }
167
168 ModeData = &Private->ModeData[ModeNumber];
169
170 switch (Private->Variant) {
171 case QEMU_VIDEO_CIRRUS_5430:
172 case QEMU_VIDEO_CIRRUS_5446:
173 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
174 break;
175 case QEMU_VIDEO_BOCHS_MMIO:
176 case QEMU_VIDEO_BOCHS:
177 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
178 break;
179 default:
180 ASSERT (FALSE);
181 return EFI_DEVICE_ERROR;
182 }
183
184 This->Mode->Mode = ModeNumber;
185 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
186 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
187 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
188
189 QemuVideoCompleteModeData (Private, This->Mode);
190
191 //
192 // Re-initialize the frame buffer configure when mode changes.
193 //
194 Status = FrameBufferBltConfigure (
195 (VOID*) (UINTN) This->Mode->FrameBufferBase,
196 This->Mode->Info,
197 Private->FrameBufferBltConfigure,
198 &Private->FrameBufferBltConfigureSize
199 );
200 if (Status == RETURN_BUFFER_TOO_SMALL) {
201 //
202 // Frame buffer configure may be larger in new mode.
203 //
204 if (Private->FrameBufferBltConfigure != NULL) {
205 FreePool (Private->FrameBufferBltConfigure);
206 }
207 Private->FrameBufferBltConfigure =
208 AllocatePool (Private->FrameBufferBltConfigureSize);
209 ASSERT (Private->FrameBufferBltConfigure != NULL);
210
211 //
212 // Create the configuration for FrameBufferBltLib
213 //
214 Status = FrameBufferBltConfigure (
215 (VOID*) (UINTN) This->Mode->FrameBufferBase,
216 This->Mode->Info,
217 Private->FrameBufferBltConfigure,
218 &Private->FrameBufferBltConfigureSize
219 );
220 }
221 ASSERT (Status == RETURN_SUCCESS);
222
223 return EFI_SUCCESS;
224 }
225
226 EFI_STATUS
227 EFIAPI
228 QemuVideoGraphicsOutputBlt (
229 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
230 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
231 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
232 IN UINTN SourceX,
233 IN UINTN SourceY,
234 IN UINTN DestinationX,
235 IN UINTN DestinationY,
236 IN UINTN Width,
237 IN UINTN Height,
238 IN UINTN Delta
239 )
240 /*++
241
242 Routine Description:
243
244 Graphics Output protocol instance to block transfer for CirrusLogic device
245
246 Arguments:
247
248 This - Pointer to Graphics Output protocol instance
249 BltBuffer - The data to transfer to screen
250 BltOperation - The operation to perform
251 SourceX - The X coordinate of the source for BltOperation
252 SourceY - The Y coordinate of the source for BltOperation
253 DestinationX - The X coordinate of the destination for BltOperation
254 DestinationY - The Y coordinate of the destination for BltOperation
255 Width - The width of a rectangle in the blt rectangle in pixels
256 Height - The height of a rectangle in the blt rectangle in pixels
257 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
258 If a Delta of 0 is used, the entire BltBuffer will be operated on.
259 If a subrectangle of the BltBuffer is used, then Delta represents
260 the number of bytes in a row of the BltBuffer.
261
262 Returns:
263
264 EFI_INVALID_PARAMETER - Invalid parameter passed in
265 EFI_SUCCESS - Blt operation success
266
267 --*/
268 {
269 EFI_STATUS Status;
270 EFI_TPL OriginalTPL;
271 QEMU_VIDEO_PRIVATE_DATA *Private;
272
273 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
274 //
275 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
276 // We would not want a timer based event (Cursor, ...) to come in while we are
277 // doing this operation.
278 //
279 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
280
281 switch (BltOperation) {
282 case EfiBltVideoToBltBuffer:
283 case EfiBltBufferToVideo:
284 case EfiBltVideoFill:
285 case EfiBltVideoToVideo:
286 Status = FrameBufferBlt (
287 Private->FrameBufferBltConfigure,
288 BltBuffer,
289 BltOperation,
290 SourceX,
291 SourceY,
292 DestinationX,
293 DestinationY,
294 Width,
295 Height,
296 Delta
297 );
298 break;
299
300 default:
301 Status = EFI_INVALID_PARAMETER;
302 ASSERT (FALSE);
303 }
304
305 gBS->RestoreTPL (OriginalTPL);
306
307 return Status;
308 }
309
310 EFI_STATUS
311 QemuVideoGraphicsOutputConstructor (
312 QEMU_VIDEO_PRIVATE_DATA *Private
313 )
314 {
315 EFI_STATUS Status;
316 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
317
318
319 GraphicsOutput = &Private->GraphicsOutput;
320 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
321 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
322 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
323
324 //
325 // Initialize the private data
326 //
327 Status = gBS->AllocatePool (
328 EfiBootServicesData,
329 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
330 (VOID **) &Private->GraphicsOutput.Mode
331 );
332 if (EFI_ERROR (Status)) {
333 return Status;
334 }
335
336 Status = gBS->AllocatePool (
337 EfiBootServicesData,
338 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
339 (VOID **) &Private->GraphicsOutput.Mode->Info
340 );
341 if (EFI_ERROR (Status)) {
342 goto FreeMode;
343 }
344 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
345 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
346 Private->FrameBufferBltConfigure = NULL;
347 Private->FrameBufferBltConfigureSize = 0;
348
349 //
350 // Initialize the hardware
351 //
352 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
353 if (EFI_ERROR (Status)) {
354 goto FreeInfo;
355 }
356
357 DrawLogo (
358 Private,
359 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
360 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
361 );
362
363 return EFI_SUCCESS;
364
365 FreeInfo:
366 FreePool (Private->GraphicsOutput.Mode->Info);
367
368 FreeMode:
369 FreePool (Private->GraphicsOutput.Mode);
370 Private->GraphicsOutput.Mode = NULL;
371
372 return Status;
373 }
374
375 EFI_STATUS
376 QemuVideoGraphicsOutputDestructor (
377 QEMU_VIDEO_PRIVATE_DATA *Private
378 )
379 /*++
380
381 Routine Description:
382
383 Arguments:
384
385 Returns:
386
387 None
388
389 --*/
390 {
391 if (Private->FrameBufferBltConfigure != NULL) {
392 FreePool (Private->FrameBufferBltConfigure);
393 }
394
395 if (Private->GraphicsOutput.Mode != NULL) {
396 if (Private->GraphicsOutput.Mode->Info != NULL) {
397 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
398 }
399 gBS->FreePool (Private->GraphicsOutput.Mode);
400 }
401
402 return EFI_SUCCESS;
403 }
404
405