]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg: require GCC48 or later
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Gop.c
1 /** @file
2 Graphics Output Protocol functions for the QEMU video controller.
3
4 Copyright (c) 2007 - 2018, 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 Private->FrameBufferVramBarIndex,
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 Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (
72 EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)
73 );
74 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
75 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));
76
77 FreePool (FrameBufDesc);
78 return EFI_SUCCESS;
79 }
80
81 //
82 // Graphics Output Protocol Member Functions
83 //
84 EFI_STATUS
85 EFIAPI
86 QemuVideoGraphicsOutputQueryMode (
87 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
88 IN UINT32 ModeNumber,
89 OUT UINTN *SizeOfInfo,
90 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
91 )
92 /*++
93
94 Routine Description:
95
96 Graphics Output protocol interface to query video mode
97
98 Arguments:
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.
103
104 Returns:
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.
110
111 --*/
112 {
113 QEMU_VIDEO_PRIVATE_DATA *Private;
114 QEMU_VIDEO_MODE_DATA *ModeData;
115
116 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
117
118 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
119 return EFI_INVALID_PARAMETER;
120 }
121
122 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
123 if (*Info == NULL) {
124 return EFI_OUT_OF_RESOURCES;
125 }
126
127 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
128
129 ModeData = &Private->ModeData[ModeNumber];
130 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
131 (*Info)->VerticalResolution = ModeData->VerticalResolution;
132 QemuVideoCompleteModeInfo (ModeData, *Info);
133
134 return EFI_SUCCESS;
135 }
136
137 EFI_STATUS
138 EFIAPI
139 QemuVideoGraphicsOutputSetMode (
140 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
141 IN UINT32 ModeNumber
142 )
143 /*++
144
145 Routine Description:
146
147 Graphics Output protocol interface to set video mode
148
149 Arguments:
150 This - Protocol instance pointer.
151 ModeNumber - The mode number to be set.
152
153 Returns:
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.
157
158 --*/
159 {
160 QEMU_VIDEO_PRIVATE_DATA *Private;
161 QEMU_VIDEO_MODE_DATA *ModeData;
162 RETURN_STATUS Status;
163 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
164
165 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
166
167 if (ModeNumber >= This->Mode->MaxMode) {
168 return EFI_UNSUPPORTED;
169 }
170
171 ModeData = &Private->ModeData[ModeNumber];
172
173 switch (Private->Variant) {
174 case QEMU_VIDEO_CIRRUS_5430:
175 case QEMU_VIDEO_CIRRUS_5446:
176 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
177 break;
178 case QEMU_VIDEO_BOCHS_MMIO:
179 case QEMU_VIDEO_BOCHS:
180 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
181 break;
182 default:
183 ASSERT (FALSE);
184 return EFI_DEVICE_ERROR;
185 }
186
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);
191
192 QemuVideoCompleteModeData (Private, This->Mode);
193
194 //
195 // Re-initialize the frame buffer configure when mode changes.
196 //
197 Status = FrameBufferBltConfigure (
198 (VOID*) (UINTN) This->Mode->FrameBufferBase,
199 This->Mode->Info,
200 Private->FrameBufferBltConfigure,
201 &Private->FrameBufferBltConfigureSize
202 );
203 if (Status == RETURN_BUFFER_TOO_SMALL) {
204 //
205 // Frame buffer configure may be larger in new mode.
206 //
207 if (Private->FrameBufferBltConfigure != NULL) {
208 FreePool (Private->FrameBufferBltConfigure);
209 }
210 Private->FrameBufferBltConfigure =
211 AllocatePool (Private->FrameBufferBltConfigureSize);
212 ASSERT (Private->FrameBufferBltConfigure != NULL);
213
214 //
215 // Create the configuration for FrameBufferBltLib
216 //
217 Status = FrameBufferBltConfigure (
218 (VOID*) (UINTN) This->Mode->FrameBufferBase,
219 This->Mode->Info,
220 Private->FrameBufferBltConfigure,
221 &Private->FrameBufferBltConfigureSize
222 );
223 }
224 ASSERT (Status == RETURN_SUCCESS);
225
226 //
227 // Per UEFI Spec, need to clear the visible portions of the output display to black.
228 //
229 ZeroMem (&Black, sizeof (Black));
230 Status = FrameBufferBlt (
231 Private->FrameBufferBltConfigure,
232 &Black,
233 EfiBltVideoFill,
234 0, 0,
235 0, 0,
236 This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution,
237 0
238 );
239 ASSERT_RETURN_ERROR (Status);
240
241 return EFI_SUCCESS;
242 }
243
244 EFI_STATUS
245 EFIAPI
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,
250 IN UINTN SourceX,
251 IN UINTN SourceY,
252 IN UINTN DestinationX,
253 IN UINTN DestinationY,
254 IN UINTN Width,
255 IN UINTN Height,
256 IN UINTN Delta
257 )
258 /*++
259
260 Routine Description:
261
262 Graphics Output protocol instance to block transfer for CirrusLogic device
263
264 Arguments:
265
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.
279
280 Returns:
281
282 EFI_INVALID_PARAMETER - Invalid parameter passed in
283 EFI_SUCCESS - Blt operation success
284
285 --*/
286 {
287 EFI_STATUS Status;
288 EFI_TPL OriginalTPL;
289 QEMU_VIDEO_PRIVATE_DATA *Private;
290
291 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
292 //
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.
296 //
297 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
298
299 switch (BltOperation) {
300 case EfiBltVideoToBltBuffer:
301 case EfiBltBufferToVideo:
302 case EfiBltVideoFill:
303 case EfiBltVideoToVideo:
304 Status = FrameBufferBlt (
305 Private->FrameBufferBltConfigure,
306 BltBuffer,
307 BltOperation,
308 SourceX,
309 SourceY,
310 DestinationX,
311 DestinationY,
312 Width,
313 Height,
314 Delta
315 );
316 break;
317
318 default:
319 Status = EFI_INVALID_PARAMETER;
320 break;
321 }
322
323 gBS->RestoreTPL (OriginalTPL);
324
325 return Status;
326 }
327
328 EFI_STATUS
329 QemuVideoGraphicsOutputConstructor (
330 QEMU_VIDEO_PRIVATE_DATA *Private
331 )
332 {
333 EFI_STATUS Status;
334 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
335
336
337 GraphicsOutput = &Private->GraphicsOutput;
338 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
339 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
340 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
341
342 //
343 // Initialize the private data
344 //
345 Status = gBS->AllocatePool (
346 EfiBootServicesData,
347 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
348 (VOID **) &Private->GraphicsOutput.Mode
349 );
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353
354 Status = gBS->AllocatePool (
355 EfiBootServicesData,
356 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
357 (VOID **) &Private->GraphicsOutput.Mode->Info
358 );
359 if (EFI_ERROR (Status)) {
360 goto FreeMode;
361 }
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;
366
367 //
368 // Initialize the hardware
369 //
370 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
371 if (EFI_ERROR (Status)) {
372 goto FreeInfo;
373 }
374
375 DrawLogo (
376 Private,
377 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
378 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
379 );
380
381 return EFI_SUCCESS;
382
383 FreeInfo:
384 FreePool (Private->GraphicsOutput.Mode->Info);
385
386 FreeMode:
387 FreePool (Private->GraphicsOutput.Mode);
388 Private->GraphicsOutput.Mode = NULL;
389
390 return Status;
391 }
392
393 EFI_STATUS
394 QemuVideoGraphicsOutputDestructor (
395 QEMU_VIDEO_PRIVATE_DATA *Private
396 )
397 /*++
398
399 Routine Description:
400
401 Arguments:
402
403 Returns:
404
405 None
406
407 --*/
408 {
409 if (Private->FrameBufferBltConfigure != NULL) {
410 FreePool (Private->FrameBufferBltConfigure);
411 }
412
413 if (Private->GraphicsOutput.Mode != NULL) {
414 if (Private->GraphicsOutput.Mode->Info != NULL) {
415 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
416 }
417 gBS->FreePool (Private->GraphicsOutput.Mode);
418 }
419
420 return EFI_SUCCESS;
421 }
422
423