]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Gop.c
OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O.
[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
6a125386 4 Copyright (c) 2007 - 2017, 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 191 //\r
6a125386 192 // Re-initialize the frame buffer configure when mode changes.\r
5b2291f9 193 //\r
6a125386
RN
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
5b2291f9
RN
207 Private->FrameBufferBltConfigure =\r
208 AllocatePool (Private->FrameBufferBltConfigureSize);\r
6a125386 209 ASSERT (Private->FrameBufferBltConfigure != NULL);\r
5b2291f9 210\r
6a125386
RN
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
5b2291f9 221 ASSERT (Status == RETURN_SUCCESS);\r
eaf4f336 222\r
eaf4f336 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
5b2291f9 271 QEMU_VIDEO_PRIVATE_DATA *Private;\r
eaf4f336 272\r
5b2291f9 273 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
eaf4f336 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
5b2291f9
RN
286 Status = FrameBufferBlt (\r
287 Private->FrameBufferBltConfigure,\r
eaf4f336 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
d89186bc 335\r
eaf4f336 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
d89186bc 342 goto FreeMode;\r
eaf4f336 343 }\r
344 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
345 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
5b2291f9
RN
346 Private->FrameBufferBltConfigure = NULL;\r
347 Private->FrameBufferBltConfigureSize = 0;\r
eaf4f336 348\r
349 //\r
350 // Initialize the hardware\r
351 //\r
d89186bc
LE
352 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);\r
353 if (EFI_ERROR (Status)) {\r
354 goto FreeInfo;\r
355 }\r
356\r
eaf4f336 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
d89186bc
LE
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
eaf4f336 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
5b2291f9
RN
391 if (Private->FrameBufferBltConfigure != NULL) {\r
392 FreePool (Private->FrameBufferBltConfigure);\r
393 }\r
394\r
eaf4f336 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