]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg: require GCC48 or later
[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
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
d021868c 63 Private->FrameBufferVramBarIndex,\r
eaf4f336 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
dd776047
GH
71 Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (\r
72 EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)\r
73 );\r
6394c35a
LE
74 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",\r
75 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));\r
eaf4f336 76\r
5cdb96fa 77 FreePool (FrameBufDesc);\r
eaf4f336 78 return EFI_SUCCESS;\r
79}\r
80\r
eaf4f336 81//\r
82// Graphics Output Protocol Member Functions\r
83//\r
84EFI_STATUS\r
85EFIAPI\r
86QemuVideoGraphicsOutputQueryMode (\r
87 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
88 IN UINT32 ModeNumber,\r
89 OUT UINTN *SizeOfInfo,\r
90 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
91 )\r
92/*++\r
93\r
94Routine Description:\r
95\r
96 Graphics Output protocol interface to query video mode\r
97\r
98 Arguments:\r
99 This - Protocol instance pointer.\r
100 ModeNumber - The mode number to return information on.\r
101 Info - Caller allocated buffer that returns information about ModeNumber.\r
102 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.\r
103\r
104 Returns:\r
105 EFI_SUCCESS - Mode information returned.\r
106 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.\r
107 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
108 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
109 EFI_INVALID_PARAMETER - One of the input args was NULL.\r
110\r
111--*/\r
112{\r
113 QEMU_VIDEO_PRIVATE_DATA *Private;\r
114 QEMU_VIDEO_MODE_DATA *ModeData;\r
115\r
116 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
117\r
eaf4f336 118 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
119 return EFI_INVALID_PARAMETER;\r
120 }\r
121\r
122 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
123 if (*Info == NULL) {\r
124 return EFI_OUT_OF_RESOURCES;\r
125 }\r
126\r
127 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
128\r
1358ecb7
YCL
129 ModeData = &Private->ModeData[ModeNumber];\r
130 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
131 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
132 QemuVideoCompleteModeInfo (ModeData, *Info);\r
eaf4f336 133\r
134 return EFI_SUCCESS;\r
135}\r
136\r
137EFI_STATUS\r
138EFIAPI\r
139QemuVideoGraphicsOutputSetMode (\r
140 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
141 IN UINT32 ModeNumber\r
142 )\r
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
81feb6d3
RN
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
174 case QEMU_VIDEO_CIRRUS_5430:\r
175 case QEMU_VIDEO_CIRRUS_5446:\r
cd152610 176 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);\r
212aac55 177 break;\r
cdb4f5dc 178 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 179 case QEMU_VIDEO_BOCHS:\r
cd152610 180 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);\r
54f9b9ac 181 break;\r
212aac55 182 default:\r
183 ASSERT (FALSE);\r
212aac55 184 return EFI_DEVICE_ERROR;\r
185 }\r
eaf4f336 186\r
187 This->Mode->Mode = ModeNumber;\r
188 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
189 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
190 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
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
RN
197 Status = FrameBufferBltConfigure (\r
198 (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
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
5b2291f9
RN
210 Private->FrameBufferBltConfigure =\r
211 AllocatePool (Private->FrameBufferBltConfigureSize);\r
6a125386 212 ASSERT (Private->FrameBufferBltConfigure != NULL);\r
5b2291f9 213\r
6a125386
RN
214 //\r
215 // Create the configuration for FrameBufferBltLib\r
216 //\r
217 Status = FrameBufferBltConfigure (\r
218 (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
219 This->Mode->Info,\r
220 Private->FrameBufferBltConfigure,\r
221 &Private->FrameBufferBltConfigureSize\r
222 );\r
223 }\r
5b2291f9 224 ASSERT (Status == RETURN_SUCCESS);\r
eaf4f336 225\r
81feb6d3
RN
226 //\r
227 // Per UEFI Spec, need to clear the visible portions of the output display to black.\r
228 //\r
229 ZeroMem (&Black, sizeof (Black));\r
230 Status = FrameBufferBlt (\r
231 Private->FrameBufferBltConfigure,\r
232 &Black,\r
233 EfiBltVideoFill,\r
234 0, 0,\r
235 0, 0,\r
236 This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution,\r
237 0\r
238 );\r
239 ASSERT_RETURN_ERROR (Status);\r
240\r
eaf4f336 241 return EFI_SUCCESS;\r
242}\r
243\r
244EFI_STATUS\r
245EFIAPI\r
246QemuVideoGraphicsOutputBlt (\r
247 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
248 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
249 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
250 IN UINTN SourceX,\r
251 IN UINTN SourceY,\r
252 IN UINTN DestinationX,\r
253 IN UINTN DestinationY,\r
254 IN UINTN Width,\r
255 IN UINTN Height,\r
256 IN UINTN Delta\r
257 )\r
258/*++\r
259\r
260Routine Description:\r
261\r
262 Graphics Output protocol instance to block transfer for CirrusLogic device\r
263\r
264Arguments:\r
265\r
266 This - Pointer to Graphics Output protocol instance\r
267 BltBuffer - The data to transfer to screen\r
268 BltOperation - The operation to perform\r
269 SourceX - The X coordinate of the source for BltOperation\r
270 SourceY - The Y coordinate of the source for BltOperation\r
271 DestinationX - The X coordinate of the destination for BltOperation\r
272 DestinationY - The Y coordinate of the destination for BltOperation\r
273 Width - The width of a rectangle in the blt rectangle in pixels\r
274 Height - The height of a rectangle in the blt rectangle in pixels\r
275 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
276 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
277 If a subrectangle of the BltBuffer is used, then Delta represents\r
278 the number of bytes in a row of the BltBuffer.\r
279\r
280Returns:\r
281\r
282 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
283 EFI_SUCCESS - Blt operation success\r
284\r
285--*/\r
286{\r
287 EFI_STATUS Status;\r
288 EFI_TPL OriginalTPL;\r
5b2291f9 289 QEMU_VIDEO_PRIVATE_DATA *Private;\r
eaf4f336 290\r
5b2291f9 291 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
eaf4f336 292 //\r
293 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
294 // We would not want a timer based event (Cursor, ...) to come in while we are\r
295 // doing this operation.\r
296 //\r
297 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
298\r
299 switch (BltOperation) {\r
300 case EfiBltVideoToBltBuffer:\r
301 case EfiBltBufferToVideo:\r
302 case EfiBltVideoFill:\r
303 case EfiBltVideoToVideo:\r
5b2291f9
RN
304 Status = FrameBufferBlt (\r
305 Private->FrameBufferBltConfigure,\r
eaf4f336 306 BltBuffer,\r
307 BltOperation,\r
308 SourceX,\r
309 SourceY,\r
310 DestinationX,\r
311 DestinationY,\r
312 Width,\r
313 Height,\r
314 Delta\r
315 );\r
316 break;\r
317\r
318 default:\r
319 Status = EFI_INVALID_PARAMETER;\r
e1fb4416 320 break;\r
eaf4f336 321 }\r
322\r
323 gBS->RestoreTPL (OriginalTPL);\r
324\r
325 return Status;\r
326}\r
327\r
328EFI_STATUS\r
329QemuVideoGraphicsOutputConstructor (\r
330 QEMU_VIDEO_PRIVATE_DATA *Private\r
331 )\r
332{\r
333 EFI_STATUS Status;\r
334 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
335\r
336\r
337 GraphicsOutput = &Private->GraphicsOutput;\r
338 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;\r
339 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;\r
340 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;\r
341\r
342 //\r
343 // Initialize the private data\r
344 //\r
345 Status = gBS->AllocatePool (\r
346 EfiBootServicesData,\r
347 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
348 (VOID **) &Private->GraphicsOutput.Mode\r
349 );\r
350 if (EFI_ERROR (Status)) {\r
351 return Status;\r
352 }\r
d89186bc 353\r
eaf4f336 354 Status = gBS->AllocatePool (\r
355 EfiBootServicesData,\r
356 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
357 (VOID **) &Private->GraphicsOutput.Mode->Info\r
358 );\r
359 if (EFI_ERROR (Status)) {\r
d89186bc 360 goto FreeMode;\r
eaf4f336 361 }\r
362 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
363 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
5b2291f9
RN
364 Private->FrameBufferBltConfigure = NULL;\r
365 Private->FrameBufferBltConfigureSize = 0;\r
eaf4f336 366\r
367 //\r
368 // Initialize the hardware\r
369 //\r
d89186bc
LE
370 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);\r
371 if (EFI_ERROR (Status)) {\r
372 goto FreeInfo;\r
373 }\r
374\r
eaf4f336 375 DrawLogo (\r
376 Private,\r
377 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
378 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution\r
379 );\r
380\r
381 return EFI_SUCCESS;\r
d89186bc
LE
382\r
383FreeInfo:\r
384 FreePool (Private->GraphicsOutput.Mode->Info);\r
385\r
386FreeMode:\r
387 FreePool (Private->GraphicsOutput.Mode);\r
388 Private->GraphicsOutput.Mode = NULL;\r
389\r
390 return Status;\r
eaf4f336 391}\r
392\r
393EFI_STATUS\r
394QemuVideoGraphicsOutputDestructor (\r
395 QEMU_VIDEO_PRIVATE_DATA *Private\r
396 )\r
397/*++\r
398\r
399Routine Description:\r
400\r
401Arguments:\r
402\r
403Returns:\r
404\r
405 None\r
406\r
407--*/\r
408{\r
5b2291f9
RN
409 if (Private->FrameBufferBltConfigure != NULL) {\r
410 FreePool (Private->FrameBufferBltConfigure);\r
411 }\r
412\r
eaf4f336 413 if (Private->GraphicsOutput.Mode != NULL) {\r
414 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
415 gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r
416 }\r
417 gBS->FreePool (Private->GraphicsOutput.Mode);\r
418 }\r
419\r
420 return EFI_SUCCESS;\r
421}\r
422\r
423\r