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