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