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