]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg: QemuVideoDxe uses MdeModulePkg/FrameBufferLib
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Gop.c
1 /** @file
2 Graphics Output Protocol functions for the QEMU video controller.
3
4 Copyright (c) 2007 - 2016, 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 if (Private->LineBuffer) {
171 gBS->FreePool (Private->LineBuffer);
172 }
173
174 Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution);
175 if (Private->LineBuffer == NULL) {
176 return EFI_OUT_OF_RESOURCES;
177 }
178
179 switch (Private->Variant) {
180 case QEMU_VIDEO_CIRRUS_5430:
181 case QEMU_VIDEO_CIRRUS_5446:
182 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
183 break;
184 case QEMU_VIDEO_BOCHS_MMIO:
185 case QEMU_VIDEO_BOCHS:
186 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
187 break;
188 default:
189 ASSERT (FALSE);
190 gBS->FreePool (Private->LineBuffer);
191 Private->LineBuffer = NULL;
192 return EFI_DEVICE_ERROR;
193 }
194
195 This->Mode->Mode = ModeNumber;
196 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
197 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
198 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
199
200 QemuVideoCompleteModeData (Private, This->Mode);
201
202 //
203 // Allocate when using first time.
204 //
205 if (Private->FrameBufferBltConfigure == NULL) {
206 Status = FrameBufferBltConfigure (
207 (VOID*) (UINTN) This->Mode->FrameBufferBase,
208 This->Mode->Info,
209 Private->FrameBufferBltConfigure,
210 &Private->FrameBufferBltConfigureSize
211 );
212 ASSERT (Status == RETURN_BUFFER_TOO_SMALL);
213 Private->FrameBufferBltConfigure =
214 AllocatePool (Private->FrameBufferBltConfigureSize);
215 }
216
217 //
218 // Create the configuration for FrameBufferBltLib
219 //
220 ASSERT (Private->FrameBufferBltConfigure != NULL);
221 Status = FrameBufferBltConfigure (
222 (VOID*) (UINTN) This->Mode->FrameBufferBase,
223 This->Mode->Info,
224 Private->FrameBufferBltConfigure,
225 &Private->FrameBufferBltConfigureSize
226 );
227 ASSERT (Status == RETURN_SUCCESS);
228
229 return EFI_SUCCESS;
230 }
231
232 EFI_STATUS
233 EFIAPI
234 QemuVideoGraphicsOutputBlt (
235 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
236 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
237 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
238 IN UINTN SourceX,
239 IN UINTN SourceY,
240 IN UINTN DestinationX,
241 IN UINTN DestinationY,
242 IN UINTN Width,
243 IN UINTN Height,
244 IN UINTN Delta
245 )
246 /*++
247
248 Routine Description:
249
250 Graphics Output protocol instance to block transfer for CirrusLogic device
251
252 Arguments:
253
254 This - Pointer to Graphics Output protocol instance
255 BltBuffer - The data to transfer to screen
256 BltOperation - The operation to perform
257 SourceX - The X coordinate of the source for BltOperation
258 SourceY - The Y coordinate of the source for BltOperation
259 DestinationX - The X coordinate of the destination for BltOperation
260 DestinationY - The Y coordinate of the destination for BltOperation
261 Width - The width of a rectangle in the blt rectangle in pixels
262 Height - The height of a rectangle in the blt rectangle in pixels
263 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
264 If a Delta of 0 is used, the entire BltBuffer will be operated on.
265 If a subrectangle of the BltBuffer is used, then Delta represents
266 the number of bytes in a row of the BltBuffer.
267
268 Returns:
269
270 EFI_INVALID_PARAMETER - Invalid parameter passed in
271 EFI_SUCCESS - Blt operation success
272
273 --*/
274 {
275 EFI_STATUS Status;
276 EFI_TPL OriginalTPL;
277 QEMU_VIDEO_PRIVATE_DATA *Private;
278
279 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
280 //
281 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
282 // We would not want a timer based event (Cursor, ...) to come in while we are
283 // doing this operation.
284 //
285 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
286
287 switch (BltOperation) {
288 case EfiBltVideoToBltBuffer:
289 case EfiBltBufferToVideo:
290 case EfiBltVideoFill:
291 case EfiBltVideoToVideo:
292 Status = FrameBufferBlt (
293 Private->FrameBufferBltConfigure,
294 BltBuffer,
295 BltOperation,
296 SourceX,
297 SourceY,
298 DestinationX,
299 DestinationY,
300 Width,
301 Height,
302 Delta
303 );
304 break;
305
306 default:
307 Status = EFI_INVALID_PARAMETER;
308 ASSERT (FALSE);
309 }
310
311 gBS->RestoreTPL (OriginalTPL);
312
313 return Status;
314 }
315
316 EFI_STATUS
317 QemuVideoGraphicsOutputConstructor (
318 QEMU_VIDEO_PRIVATE_DATA *Private
319 )
320 {
321 EFI_STATUS Status;
322 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
323
324
325 GraphicsOutput = &Private->GraphicsOutput;
326 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
327 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
328 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
329
330 //
331 // Initialize the private data
332 //
333 Status = gBS->AllocatePool (
334 EfiBootServicesData,
335 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
336 (VOID **) &Private->GraphicsOutput.Mode
337 );
338 if (EFI_ERROR (Status)) {
339 return Status;
340 }
341
342 Status = gBS->AllocatePool (
343 EfiBootServicesData,
344 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
345 (VOID **) &Private->GraphicsOutput.Mode->Info
346 );
347 if (EFI_ERROR (Status)) {
348 goto FreeMode;
349 }
350 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;
351 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
352 Private->LineBuffer = NULL;
353 Private->FrameBufferBltConfigure = NULL;
354 Private->FrameBufferBltConfigureSize = 0;
355
356 //
357 // Initialize the hardware
358 //
359 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
360 if (EFI_ERROR (Status)) {
361 goto FreeInfo;
362 }
363
364 DrawLogo (
365 Private,
366 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
367 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
368 );
369
370 return EFI_SUCCESS;
371
372 FreeInfo:
373 FreePool (Private->GraphicsOutput.Mode->Info);
374
375 FreeMode:
376 FreePool (Private->GraphicsOutput.Mode);
377 Private->GraphicsOutput.Mode = NULL;
378
379 return Status;
380 }
381
382 EFI_STATUS
383 QemuVideoGraphicsOutputDestructor (
384 QEMU_VIDEO_PRIVATE_DATA *Private
385 )
386 /*++
387
388 Routine Description:
389
390 Arguments:
391
392 Returns:
393
394 None
395
396 --*/
397 {
398 if (Private->LineBuffer != NULL) {
399 FreePool (Private->LineBuffer);
400 }
401
402 if (Private->FrameBufferBltConfigure != NULL) {
403 FreePool (Private->FrameBufferBltConfigure);
404 }
405
406 if (Private->GraphicsOutput.Mode != NULL) {
407 if (Private->GraphicsOutput.Mode->Info != NULL) {
408 gBS->FreePool (Private->GraphicsOutput.Mode->Info);
409 }
410 gBS->FreePool (Private->GraphicsOutput.Mode);
411 }
412
413 return EFI_SUCCESS;
414 }
415
416