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