]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Gop.c
Revert "OvmfPkg/QemuVideoDxe: list "UnalignedIoInternal.h" in the INF file"
[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
81feb6d3 4 Copyright (c) 2007 - 2018, 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
2e77f0e7 16#include <IndustryStandard/VmwareSvga.h>\r
eaf4f336 17#include "Qemu.h"\r
eaf4f336 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
dd776047
GH
72 Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (\r
73 EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)\r
74 );\r
6394c35a
LE
75 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",\r
76 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));\r
eaf4f336 77\r
5cdb96fa 78 FreePool (FrameBufDesc);\r
eaf4f336 79 return EFI_SUCCESS;\r
80}\r
81\r
2e77f0e7
LE
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
eaf4f336 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
eaf4f336 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
2e77f0e7
LE
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
eaf4f336 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
81feb6d3
RN
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
eaf4f336 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
212aac55 218 switch (Private->Variant) {\r
219 case QEMU_VIDEO_CIRRUS_5430:\r
220 case QEMU_VIDEO_CIRRUS_5446:\r
cd152610 221 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);\r
212aac55 222 break;\r
cdb4f5dc 223 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 224 case QEMU_VIDEO_BOCHS:\r
cd152610 225 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);\r
54f9b9ac 226 break;\r
2e77f0e7
LE
227 case QEMU_VIDEO_VMWARE_SVGA:\r
228 InitializeVmwareSvgaGraphicsMode (\r
229 Private,\r
230 &QemuVideoBochsModes[ModeData->InternalModeIndex]\r
231 );\r
232 break;\r
212aac55 233 default:\r
234 ASSERT (FALSE);\r
212aac55 235 return EFI_DEVICE_ERROR;\r
236 }\r
eaf4f336 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
2e77f0e7
LE
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
eaf4f336 248\r
5b2291f9 249 //\r
6a125386 250 // Re-initialize the frame buffer configure when mode changes.\r
5b2291f9 251 //\r
6a125386
RN
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
5b2291f9
RN
265 Private->FrameBufferBltConfigure =\r
266 AllocatePool (Private->FrameBufferBltConfigureSize);\r
6a125386 267 ASSERT (Private->FrameBufferBltConfigure != NULL);\r
5b2291f9 268\r
6a125386
RN
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
5b2291f9 279 ASSERT (Status == RETURN_SUCCESS);\r
eaf4f336 280\r
81feb6d3
RN
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
eaf4f336 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
5b2291f9 344 QEMU_VIDEO_PRIVATE_DATA *Private;\r
eaf4f336 345\r
5b2291f9 346 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
eaf4f336 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
5b2291f9
RN
359 Status = FrameBufferBlt (\r
360 Private->FrameBufferBltConfigure,\r
eaf4f336 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
e1fb4416 375 break;\r
eaf4f336 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
d89186bc 408\r
eaf4f336 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
d89186bc 415 goto FreeMode;\r
eaf4f336 416 }\r
417 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
418 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
5b2291f9
RN
419 Private->FrameBufferBltConfigure = NULL;\r
420 Private->FrameBufferBltConfigureSize = 0;\r
eaf4f336 421\r
422 //\r
423 // Initialize the hardware\r
424 //\r
d89186bc
LE
425 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);\r
426 if (EFI_ERROR (Status)) {\r
427 goto FreeInfo;\r
428 }\r
429\r
eaf4f336 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
d89186bc
LE
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
eaf4f336 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
5b2291f9
RN
464 if (Private->FrameBufferBltConfigure != NULL) {\r
465 FreePool (Private->FrameBufferBltConfigure);\r
466 }\r
467\r
eaf4f336 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