]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/QemuVideoDxe/Gop.c
MdePkg/BasePrintLib: Add safe print functions [A|U]ValueToStringS
[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 - 2017, 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 "Qemu.h"\r
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
71 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",\r
72 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));\r
73\r
74 FreePool (FrameBufDesc);\r
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
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
160 RETURN_STATUS Status;\r
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 switch (Private->Variant) {\r
171 case QEMU_VIDEO_CIRRUS_5430:\r
172 case QEMU_VIDEO_CIRRUS_5446:\r
173 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);\r
174 break;\r
175 case QEMU_VIDEO_BOCHS_MMIO:\r
176 case QEMU_VIDEO_BOCHS:\r
177 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);\r
178 break;\r
179 default:\r
180 ASSERT (FALSE);\r
181 return EFI_DEVICE_ERROR;\r
182 }\r
183\r
184 This->Mode->Mode = ModeNumber;\r
185 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
186 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
187 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
188\r
189 QemuVideoCompleteModeData (Private, This->Mode);\r
190\r
191 //\r
192 // Re-initialize the frame buffer configure when mode changes.\r
193 //\r
194 Status = FrameBufferBltConfigure (\r
195 (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
196 This->Mode->Info,\r
197 Private->FrameBufferBltConfigure,\r
198 &Private->FrameBufferBltConfigureSize\r
199 );\r
200 if (Status == RETURN_BUFFER_TOO_SMALL) {\r
201 //\r
202 // Frame buffer configure may be larger in new mode.\r
203 //\r
204 if (Private->FrameBufferBltConfigure != NULL) {\r
205 FreePool (Private->FrameBufferBltConfigure);\r
206 }\r
207 Private->FrameBufferBltConfigure =\r
208 AllocatePool (Private->FrameBufferBltConfigureSize);\r
209 ASSERT (Private->FrameBufferBltConfigure != NULL);\r
210\r
211 //\r
212 // Create the configuration for FrameBufferBltLib\r
213 //\r
214 Status = FrameBufferBltConfigure (\r
215 (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
216 This->Mode->Info,\r
217 Private->FrameBufferBltConfigure,\r
218 &Private->FrameBufferBltConfigureSize\r
219 );\r
220 }\r
221 ASSERT (Status == RETURN_SUCCESS);\r
222\r
223 return EFI_SUCCESS;\r
224}\r
225\r
226EFI_STATUS\r
227EFIAPI\r
228QemuVideoGraphicsOutputBlt (\r
229 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
230 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
231 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
232 IN UINTN SourceX,\r
233 IN UINTN SourceY,\r
234 IN UINTN DestinationX,\r
235 IN UINTN DestinationY,\r
236 IN UINTN Width,\r
237 IN UINTN Height,\r
238 IN UINTN Delta\r
239 )\r
240/*++\r
241\r
242Routine Description:\r
243\r
244 Graphics Output protocol instance to block transfer for CirrusLogic device\r
245\r
246Arguments:\r
247\r
248 This - Pointer to Graphics Output protocol instance\r
249 BltBuffer - The data to transfer to screen\r
250 BltOperation - The operation to perform\r
251 SourceX - The X coordinate of the source for BltOperation\r
252 SourceY - The Y coordinate of the source for BltOperation\r
253 DestinationX - The X coordinate of the destination for BltOperation\r
254 DestinationY - The Y coordinate of the destination for BltOperation\r
255 Width - The width of a rectangle in the blt rectangle in pixels\r
256 Height - The height of a rectangle in the blt rectangle in pixels\r
257 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
258 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
259 If a subrectangle of the BltBuffer is used, then Delta represents\r
260 the number of bytes in a row of the BltBuffer.\r
261\r
262Returns:\r
263\r
264 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
265 EFI_SUCCESS - Blt operation success\r
266\r
267--*/\r
268{\r
269 EFI_STATUS Status;\r
270 EFI_TPL OriginalTPL;\r
271 QEMU_VIDEO_PRIVATE_DATA *Private;\r
272\r
273 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
274 //\r
275 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
276 // We would not want a timer based event (Cursor, ...) to come in while we are\r
277 // doing this operation.\r
278 //\r
279 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
280\r
281 switch (BltOperation) {\r
282 case EfiBltVideoToBltBuffer:\r
283 case EfiBltBufferToVideo:\r
284 case EfiBltVideoFill:\r
285 case EfiBltVideoToVideo:\r
286 Status = FrameBufferBlt (\r
287 Private->FrameBufferBltConfigure,\r
288 BltBuffer,\r
289 BltOperation,\r
290 SourceX,\r
291 SourceY,\r
292 DestinationX,\r
293 DestinationY,\r
294 Width,\r
295 Height,\r
296 Delta\r
297 );\r
298 break;\r
299\r
300 default:\r
301 Status = EFI_INVALID_PARAMETER;\r
302 ASSERT (FALSE);\r
303 }\r
304\r
305 gBS->RestoreTPL (OriginalTPL);\r
306\r
307 return Status;\r
308}\r
309\r
310EFI_STATUS\r
311QemuVideoGraphicsOutputConstructor (\r
312 QEMU_VIDEO_PRIVATE_DATA *Private\r
313 )\r
314{\r
315 EFI_STATUS Status;\r
316 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
317\r
318\r
319 GraphicsOutput = &Private->GraphicsOutput;\r
320 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;\r
321 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;\r
322 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;\r
323\r
324 //\r
325 // Initialize the private data\r
326 //\r
327 Status = gBS->AllocatePool (\r
328 EfiBootServicesData,\r
329 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
330 (VOID **) &Private->GraphicsOutput.Mode\r
331 );\r
332 if (EFI_ERROR (Status)) {\r
333 return Status;\r
334 }\r
335\r
336 Status = gBS->AllocatePool (\r
337 EfiBootServicesData,\r
338 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
339 (VOID **) &Private->GraphicsOutput.Mode->Info\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
342 goto FreeMode;\r
343 }\r
344 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
345 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
346 Private->FrameBufferBltConfigure = NULL;\r
347 Private->FrameBufferBltConfigureSize = 0;\r
348\r
349 //\r
350 // Initialize the hardware\r
351 //\r
352 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);\r
353 if (EFI_ERROR (Status)) {\r
354 goto FreeInfo;\r
355 }\r
356\r
357 DrawLogo (\r
358 Private,\r
359 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
360 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution\r
361 );\r
362\r
363 return EFI_SUCCESS;\r
364\r
365FreeInfo:\r
366 FreePool (Private->GraphicsOutput.Mode->Info);\r
367\r
368FreeMode:\r
369 FreePool (Private->GraphicsOutput.Mode);\r
370 Private->GraphicsOutput.Mode = NULL;\r
371\r
372 return Status;\r
373}\r
374\r
375EFI_STATUS\r
376QemuVideoGraphicsOutputDestructor (\r
377 QEMU_VIDEO_PRIVATE_DATA *Private\r
378 )\r
379/*++\r
380\r
381Routine Description:\r
382\r
383Arguments:\r
384\r
385Returns:\r
386\r
387 None\r
388\r
389--*/\r
390{\r
391 if (Private->FrameBufferBltConfigure != NULL) {\r
392 FreePool (Private->FrameBufferBltConfigure);\r
393 }\r
394\r
395 if (Private->GraphicsOutput.Mode != NULL) {\r
396 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
397 gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r
398 }\r
399 gBS->FreePool (Private->GraphicsOutput.Mode);\r
400 }\r
401\r
402 return EFI_SUCCESS;\r
403}\r
404\r
405\r