]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg: Add QemuVideoDxe driver
[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
4 Copyright (c) 2007 - 2010, 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#include <IndustryStandard/Acpi.h>\r
18#include <Library/BltLib.h>\r
19\r
20STATIC\r
21VOID\r
22QemuVideoCompleteModeInfo (\r
23 IN QEMU_VIDEO_MODE_DATA *ModeData,\r
24 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info\r
25 )\r
26{\r
27 Info->Version = 0;\r
28 if (ModeData->ColorDepth == 8) {\r
29 Info->PixelFormat = PixelBitMask;\r
30 Info->PixelInformation.RedMask = PIXEL_RED_MASK;\r
31 Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;\r
32 Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;\r
33 Info->PixelInformation.ReservedMask = 0;\r
34 } else if (ModeData->ColorDepth == 24) {\r
35 Info->PixelFormat = PixelBitMask;\r
36 Info->PixelInformation.RedMask = PIXEL24_RED_MASK;\r
37 Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;\r
38 Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;\r
39 Info->PixelInformation.ReservedMask = 0;\r
40 } else if (ModeData->ColorDepth == 32) {\r
41 DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));\r
42 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
43 }\r
44 Info->PixelsPerScanLine = Info->HorizontalResolution;\r
45}\r
46\r
47\r
48STATIC\r
49EFI_STATUS\r
50QemuVideoCompleteModeData (\r
51 IN QEMU_VIDEO_PRIVATE_DATA *Private,\r
52 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode\r
53 )\r
54{\r
55 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
56 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;\r
57 QEMU_VIDEO_MODE_DATA *ModeData;\r
58\r
59 ModeData = &Private->ModeData[Mode->Mode];\r
60 Info = Mode->Info;\r
61 QemuVideoCompleteModeInfo (ModeData, Info);\r
62\r
63 Private->PciIo->GetBarAttributes (\r
64 Private->PciIo,\r
65 0,\r
66 NULL,\r
67 (VOID**) &FrameBufDesc\r
68 );\r
69\r
70 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;\r
71 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;\r
72 Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);\r
73 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", Mode->FrameBufferBase, Mode->FrameBufferSize));\r
74\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 (Private->HardwareNeedsStarting) {\r
117 return EFI_NOT_STARTED;\r
118 }\r
119\r
120 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
121 return EFI_INVALID_PARAMETER;\r
122 }\r
123\r
124 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
125 if (*Info == NULL) {\r
126 return EFI_OUT_OF_RESOURCES;\r
127 }\r
128\r
129 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
130\r
131 ModeData = &Private->ModeData[ModeNumber];\r
132 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
133 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
134 QemuVideoCompleteModeInfo (ModeData, *Info);\r
135\r
136 return EFI_SUCCESS;\r
137}\r
138\r
139EFI_STATUS\r
140EFIAPI\r
141QemuVideoGraphicsOutputSetMode (\r
142 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
143 IN UINT32 ModeNumber\r
144 )\r
145/*++\r
146\r
147Routine Description:\r
148\r
149 Graphics Output protocol interface to set video mode\r
150\r
151 Arguments:\r
152 This - Protocol instance pointer.\r
153 ModeNumber - The mode number to be set.\r
154\r
155 Returns:\r
156 EFI_SUCCESS - Graphics mode was changed.\r
157 EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
158 EFI_UNSUPPORTED - ModeNumber is not supported by this device.\r
159\r
160--*/\r
161{\r
162 QEMU_VIDEO_PRIVATE_DATA *Private;\r
163 QEMU_VIDEO_MODE_DATA *ModeData;\r
164// UINTN Count;\r
165\r
166 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
167\r
168 if (ModeNumber >= This->Mode->MaxMode) {\r
169 return EFI_UNSUPPORTED;\r
170 }\r
171\r
172 ModeData = &Private->ModeData[ModeNumber];\r
173\r
174 if (Private->LineBuffer) {\r
175 gBS->FreePool (Private->LineBuffer);\r
176 }\r
177\r
178 Private->LineBuffer = NULL;\r
179 Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution);\r
180 if (Private->LineBuffer == NULL) {\r
181 return EFI_OUT_OF_RESOURCES;\r
182 }\r
183\r
184 InitializeGraphicsMode (Private, &QemuVideoVideoModes[ModeData->ModeNumber]);\r
185\r
186 This->Mode->Mode = ModeNumber;\r
187 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
188 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
189 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
190\r
191 QemuVideoCompleteModeData (Private, This->Mode);\r
192\r
193 BltLibConfigure (\r
194 (VOID*)(UINTN) This->Mode->FrameBufferBase,\r
195 This->Mode->Info\r
196 );\r
197\r
198 Private->HardwareNeedsStarting = FALSE;\r
199\r
200 return EFI_SUCCESS;\r
201}\r
202\r
203EFI_STATUS\r
204EFIAPI\r
205QemuVideoGraphicsOutputBlt (\r
206 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
207 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
208 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
209 IN UINTN SourceX,\r
210 IN UINTN SourceY,\r
211 IN UINTN DestinationX,\r
212 IN UINTN DestinationY,\r
213 IN UINTN Width,\r
214 IN UINTN Height,\r
215 IN UINTN Delta\r
216 )\r
217/*++\r
218\r
219Routine Description:\r
220\r
221 Graphics Output protocol instance to block transfer for CirrusLogic device\r
222\r
223Arguments:\r
224\r
225 This - Pointer to Graphics Output protocol instance\r
226 BltBuffer - The data to transfer to screen\r
227 BltOperation - The operation to perform\r
228 SourceX - The X coordinate of the source for BltOperation\r
229 SourceY - The Y coordinate of the source for BltOperation\r
230 DestinationX - The X coordinate of the destination for BltOperation\r
231 DestinationY - The Y coordinate of the destination for BltOperation\r
232 Width - The width of a rectangle in the blt rectangle in pixels\r
233 Height - The height of a rectangle in the blt rectangle in pixels\r
234 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
235 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
236 If a subrectangle of the BltBuffer is used, then Delta represents\r
237 the number of bytes in a row of the BltBuffer.\r
238\r
239Returns:\r
240\r
241 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
242 EFI_SUCCESS - Blt operation success\r
243\r
244--*/\r
245{\r
246 EFI_STATUS Status;\r
247 EFI_TPL OriginalTPL;\r
248\r
249 //\r
250 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
251 // We would not want a timer based event (Cursor, ...) to come in while we are\r
252 // doing this operation.\r
253 //\r
254 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
255\r
256 switch (BltOperation) {\r
257 case EfiBltVideoToBltBuffer:\r
258 case EfiBltBufferToVideo:\r
259 case EfiBltVideoFill:\r
260 case EfiBltVideoToVideo:\r
261 Status = BltLibGopBlt (\r
262 BltBuffer,\r
263 BltOperation,\r
264 SourceX,\r
265 SourceY,\r
266 DestinationX,\r
267 DestinationY,\r
268 Width,\r
269 Height,\r
270 Delta\r
271 );\r
272 break;\r
273\r
274 default:\r
275 Status = EFI_INVALID_PARAMETER;\r
276 ASSERT (FALSE);\r
277 }\r
278\r
279 gBS->RestoreTPL (OriginalTPL);\r
280\r
281 return Status;\r
282}\r
283\r
284EFI_STATUS\r
285QemuVideoGraphicsOutputConstructor (\r
286 QEMU_VIDEO_PRIVATE_DATA *Private\r
287 )\r
288{\r
289 EFI_STATUS Status;\r
290 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
291\r
292\r
293 GraphicsOutput = &Private->GraphicsOutput;\r
294 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;\r
295 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;\r
296 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;\r
297\r
298 //\r
299 // Initialize the private data\r
300 //\r
301 Status = gBS->AllocatePool (\r
302 EfiBootServicesData,\r
303 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
304 (VOID **) &Private->GraphicsOutput.Mode\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 return Status;\r
308 }\r
309 Status = gBS->AllocatePool (\r
310 EfiBootServicesData,\r
311 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
312 (VOID **) &Private->GraphicsOutput.Mode->Info\r
313 );\r
314 if (EFI_ERROR (Status)) {\r
315 return Status;\r
316 }\r
317 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
318 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
319 Private->HardwareNeedsStarting = TRUE;\r
320 Private->LineBuffer = NULL;\r
321\r
322 //\r
323 // Initialize the hardware\r
324 //\r
325 GraphicsOutput->SetMode (GraphicsOutput, 0);\r
326 DrawLogo (\r
327 Private,\r
328 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
329 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution\r
330 );\r
331\r
332 return EFI_SUCCESS;\r
333}\r
334\r
335EFI_STATUS\r
336QemuVideoGraphicsOutputDestructor (\r
337 QEMU_VIDEO_PRIVATE_DATA *Private\r
338 )\r
339/*++\r
340\r
341Routine Description:\r
342\r
343Arguments:\r
344\r
345Returns:\r
346\r
347 None\r
348\r
349--*/\r
350{\r
351 if (Private->GraphicsOutput.Mode != NULL) {\r
352 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
353 gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r
354 }\r
355 gBS->FreePool (Private->GraphicsOutput.Mode);\r
356 }\r
357\r
358 return EFI_SUCCESS;\r
359}\r
360\r
361\r