]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Gop.c
EmbeddedPkg: Correct the way of handling sections with a large size
[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
c137d950 16#include <IndustryStandard/VmwareSvga.h>\r
eaf4f336 17#include "Qemu.h"\r
eaf4f336 18\r
19STATIC\r
20VOID\r
21QemuVideoCompleteModeInfo (\r
22 IN QEMU_VIDEO_MODE_DATA *ModeData,\r
23 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info\r
24 )\r
25{\r
26 Info->Version = 0;\r
27 if (ModeData->ColorDepth == 8) {\r
28 Info->PixelFormat = PixelBitMask;\r
29 Info->PixelInformation.RedMask = PIXEL_RED_MASK;\r
30 Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;\r
31 Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;\r
32 Info->PixelInformation.ReservedMask = 0;\r
33 } else if (ModeData->ColorDepth == 24) {\r
34 Info->PixelFormat = PixelBitMask;\r
35 Info->PixelInformation.RedMask = PIXEL24_RED_MASK;\r
36 Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;\r
37 Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;\r
38 Info->PixelInformation.ReservedMask = 0;\r
39 } else if (ModeData->ColorDepth == 32) {\r
40 DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));\r
41 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
42 }\r
43 Info->PixelsPerScanLine = Info->HorizontalResolution;\r
44}\r
45\r
46\r
47STATIC\r
48EFI_STATUS\r
49QemuVideoCompleteModeData (\r
50 IN QEMU_VIDEO_PRIVATE_DATA *Private,\r
51 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode\r
52 )\r
53{\r
54 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
55 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;\r
56 QEMU_VIDEO_MODE_DATA *ModeData;\r
57\r
58 ModeData = &Private->ModeData[Mode->Mode];\r
59 Info = Mode->Info;\r
60 QemuVideoCompleteModeInfo (ModeData, Info);\r
61\r
62 Private->PciIo->GetBarAttributes (\r
63 Private->PciIo,\r
64 0,\r
65 NULL,\r
66 (VOID**) &FrameBufDesc\r
67 );\r
68\r
69 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;\r
70 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;\r
71 Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);\r
6394c35a
LE
72 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",\r
73 Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize));\r
eaf4f336 74\r
5cdb96fa 75 FreePool (FrameBufDesc);\r
eaf4f336 76 return EFI_SUCCESS;\r
77}\r
78\r
c137d950
PDJ
79STATIC\r
80EFI_STATUS\r
81QemuVideoVmwareSvgaCompleteModeData (\r
82 IN QEMU_VIDEO_PRIVATE_DATA *Private,\r
83 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode\r
84 )\r
85{\r
86 EFI_STATUS Status;\r
87 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
88 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;\r
89 UINT32 BytesPerLine, FbOffset, BytesPerPixel;\r
90\r
91 Info = Mode->Info;\r
92 CopyMem (Info, &Private->VmwareSvgaModeInfo[Mode->Mode], sizeof (*Info));\r
93 BytesPerPixel = Private->ModeData[Mode->Mode].ColorDepth / 8;\r
94 BytesPerLine = Info->PixelsPerScanLine * BytesPerPixel;\r
95\r
96 FbOffset = VmwareSvgaRead (Private, VmwareSvgaRegFbOffset);\r
97\r
98 Status = Private->PciIo->GetBarAttributes (\r
99 Private->PciIo,\r
100 PCI_BAR_IDX1,\r
101 NULL,\r
102 (VOID**) &FrameBufDesc\r
103 );\r
104 if (EFI_ERROR (Status)) {\r
105 return EFI_DEVICE_ERROR;\r
106 }\r
107\r
108 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FbOffset;\r
109 Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution;\r
110\r
111 FreePool (FrameBufDesc);\r
112 return Status;\r
113}\r
114\r
eaf4f336 115\r
116//\r
117// Graphics Output Protocol Member Functions\r
118//\r
119EFI_STATUS\r
120EFIAPI\r
121QemuVideoGraphicsOutputQueryMode (\r
122 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
123 IN UINT32 ModeNumber,\r
124 OUT UINTN *SizeOfInfo,\r
125 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
126 )\r
127/*++\r
128\r
129Routine Description:\r
130\r
131 Graphics Output protocol interface to query video mode\r
132\r
133 Arguments:\r
134 This - Protocol instance pointer.\r
135 ModeNumber - The mode number to return information on.\r
136 Info - Caller allocated buffer that returns information about ModeNumber.\r
137 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.\r
138\r
139 Returns:\r
140 EFI_SUCCESS - Mode information returned.\r
141 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.\r
142 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
143 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
144 EFI_INVALID_PARAMETER - One of the input args was NULL.\r
145\r
146--*/\r
147{\r
148 QEMU_VIDEO_PRIVATE_DATA *Private;\r
149 QEMU_VIDEO_MODE_DATA *ModeData;\r
150\r
151 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
152\r
eaf4f336 153 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
154 return EFI_INVALID_PARAMETER;\r
155 }\r
156\r
157 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
158 if (*Info == NULL) {\r
159 return EFI_OUT_OF_RESOURCES;\r
160 }\r
161\r
162 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
163\r
c137d950
PDJ
164 if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
165 CopyMem (*Info, &Private->VmwareSvgaModeInfo[ModeNumber], sizeof (**Info));\r
166 } else {\r
167 ModeData = &Private->ModeData[ModeNumber];\r
168 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
169 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
170 QemuVideoCompleteModeInfo (ModeData, *Info);\r
171 }\r
eaf4f336 172\r
173 return EFI_SUCCESS;\r
174}\r
175\r
176EFI_STATUS\r
177EFIAPI\r
178QemuVideoGraphicsOutputSetMode (\r
179 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
180 IN UINT32 ModeNumber\r
181 )\r
182/*++\r
183\r
184Routine Description:\r
185\r
186 Graphics Output protocol interface to set video mode\r
187\r
188 Arguments:\r
189 This - Protocol instance pointer.\r
190 ModeNumber - The mode number to be set.\r
191\r
192 Returns:\r
193 EFI_SUCCESS - Graphics mode was changed.\r
194 EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
195 EFI_UNSUPPORTED - ModeNumber is not supported by this device.\r
196\r
197--*/\r
198{\r
199 QEMU_VIDEO_PRIVATE_DATA *Private;\r
200 QEMU_VIDEO_MODE_DATA *ModeData;\r
5b2291f9 201 RETURN_STATUS Status;\r
eaf4f336 202\r
203 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
204\r
205 if (ModeNumber >= This->Mode->MaxMode) {\r
206 return EFI_UNSUPPORTED;\r
207 }\r
208\r
209 ModeData = &Private->ModeData[ModeNumber];\r
210\r
212aac55 211 switch (Private->Variant) {\r
212 case QEMU_VIDEO_CIRRUS_5430:\r
213 case QEMU_VIDEO_CIRRUS_5446:\r
cd152610 214 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);\r
212aac55 215 break;\r
cdb4f5dc 216 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 217 case QEMU_VIDEO_BOCHS:\r
cd152610 218 InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);\r
54f9b9ac 219 break;\r
c137d950
PDJ
220 case QEMU_VIDEO_VMWARE_SVGA:\r
221 InitializeVmwareSvgaGraphicsMode (\r
222 Private,\r
223 &QemuVideoBochsModes[ModeData->InternalModeIndex]\r
224 );\r
225 break;\r
212aac55 226 default:\r
227 ASSERT (FALSE);\r
212aac55 228 return EFI_DEVICE_ERROR;\r
229 }\r
eaf4f336 230\r
231 This->Mode->Mode = ModeNumber;\r
232 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
233 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
234 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
235\r
c137d950
PDJ
236 if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
237 QemuVideoVmwareSvgaCompleteModeData (Private, This->Mode);\r
238 } else {\r
239 QemuVideoCompleteModeData (Private, This->Mode);\r
240 }\r
eaf4f336 241\r
5b2291f9 242 //\r
6a125386 243 // Re-initialize the frame buffer configure when mode changes.\r
5b2291f9 244 //\r
6a125386
RN
245 Status = FrameBufferBltConfigure (\r
246 (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
247 This->Mode->Info,\r
248 Private->FrameBufferBltConfigure,\r
249 &Private->FrameBufferBltConfigureSize\r
250 );\r
251 if (Status == RETURN_BUFFER_TOO_SMALL) {\r
252 //\r
253 // Frame buffer configure may be larger in new mode.\r
254 //\r
255 if (Private->FrameBufferBltConfigure != NULL) {\r
256 FreePool (Private->FrameBufferBltConfigure);\r
257 }\r
5b2291f9
RN
258 Private->FrameBufferBltConfigure =\r
259 AllocatePool (Private->FrameBufferBltConfigureSize);\r
6a125386 260 ASSERT (Private->FrameBufferBltConfigure != NULL);\r
5b2291f9 261\r
6a125386
RN
262 //\r
263 // Create the configuration for FrameBufferBltLib\r
264 //\r
265 Status = FrameBufferBltConfigure (\r
266 (VOID*) (UINTN) This->Mode->FrameBufferBase,\r
267 This->Mode->Info,\r
268 Private->FrameBufferBltConfigure,\r
269 &Private->FrameBufferBltConfigureSize\r
270 );\r
271 }\r
5b2291f9 272 ASSERT (Status == RETURN_SUCCESS);\r
eaf4f336 273\r
eaf4f336 274 return EFI_SUCCESS;\r
275}\r
276\r
277EFI_STATUS\r
278EFIAPI\r
279QemuVideoGraphicsOutputBlt (\r
280 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
281 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
282 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
283 IN UINTN SourceX,\r
284 IN UINTN SourceY,\r
285 IN UINTN DestinationX,\r
286 IN UINTN DestinationY,\r
287 IN UINTN Width,\r
288 IN UINTN Height,\r
289 IN UINTN Delta\r
290 )\r
291/*++\r
292\r
293Routine Description:\r
294\r
295 Graphics Output protocol instance to block transfer for CirrusLogic device\r
296\r
297Arguments:\r
298\r
299 This - Pointer to Graphics Output protocol instance\r
300 BltBuffer - The data to transfer to screen\r
301 BltOperation - The operation to perform\r
302 SourceX - The X coordinate of the source for BltOperation\r
303 SourceY - The Y coordinate of the source for BltOperation\r
304 DestinationX - The X coordinate of the destination for BltOperation\r
305 DestinationY - The Y coordinate of the destination for BltOperation\r
306 Width - The width of a rectangle in the blt rectangle in pixels\r
307 Height - The height of a rectangle in the blt rectangle in pixels\r
308 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
309 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
310 If a subrectangle of the BltBuffer is used, then Delta represents\r
311 the number of bytes in a row of the BltBuffer.\r
312\r
313Returns:\r
314\r
315 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
316 EFI_SUCCESS - Blt operation success\r
317\r
318--*/\r
319{\r
320 EFI_STATUS Status;\r
321 EFI_TPL OriginalTPL;\r
5b2291f9 322 QEMU_VIDEO_PRIVATE_DATA *Private;\r
eaf4f336 323\r
5b2291f9 324 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
eaf4f336 325 //\r
326 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
327 // We would not want a timer based event (Cursor, ...) to come in while we are\r
328 // doing this operation.\r
329 //\r
330 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
331\r
332 switch (BltOperation) {\r
333 case EfiBltVideoToBltBuffer:\r
334 case EfiBltBufferToVideo:\r
335 case EfiBltVideoFill:\r
336 case EfiBltVideoToVideo:\r
5b2291f9
RN
337 Status = FrameBufferBlt (\r
338 Private->FrameBufferBltConfigure,\r
eaf4f336 339 BltBuffer,\r
340 BltOperation,\r
341 SourceX,\r
342 SourceY,\r
343 DestinationX,\r
344 DestinationY,\r
345 Width,\r
346 Height,\r
347 Delta\r
348 );\r
349 break;\r
350\r
351 default:\r
352 Status = EFI_INVALID_PARAMETER;\r
353 ASSERT (FALSE);\r
354 }\r
355\r
356 gBS->RestoreTPL (OriginalTPL);\r
357\r
358 return Status;\r
359}\r
360\r
361EFI_STATUS\r
362QemuVideoGraphicsOutputConstructor (\r
363 QEMU_VIDEO_PRIVATE_DATA *Private\r
364 )\r
365{\r
366 EFI_STATUS Status;\r
367 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
368\r
369\r
370 GraphicsOutput = &Private->GraphicsOutput;\r
371 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;\r
372 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;\r
373 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;\r
374\r
375 //\r
376 // Initialize the private data\r
377 //\r
378 Status = gBS->AllocatePool (\r
379 EfiBootServicesData,\r
380 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
381 (VOID **) &Private->GraphicsOutput.Mode\r
382 );\r
383 if (EFI_ERROR (Status)) {\r
384 return Status;\r
385 }\r
d89186bc 386\r
eaf4f336 387 Status = gBS->AllocatePool (\r
388 EfiBootServicesData,\r
389 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
390 (VOID **) &Private->GraphicsOutput.Mode->Info\r
391 );\r
392 if (EFI_ERROR (Status)) {\r
d89186bc 393 goto FreeMode;\r
eaf4f336 394 }\r
395 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
396 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
5b2291f9
RN
397 Private->FrameBufferBltConfigure = NULL;\r
398 Private->FrameBufferBltConfigureSize = 0;\r
eaf4f336 399\r
400 //\r
401 // Initialize the hardware\r
402 //\r
d89186bc
LE
403 Status = GraphicsOutput->SetMode (GraphicsOutput, 0);\r
404 if (EFI_ERROR (Status)) {\r
405 goto FreeInfo;\r
406 }\r
407\r
eaf4f336 408 DrawLogo (\r
409 Private,\r
410 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
411 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution\r
412 );\r
413\r
414 return EFI_SUCCESS;\r
d89186bc
LE
415\r
416FreeInfo:\r
417 FreePool (Private->GraphicsOutput.Mode->Info);\r
418\r
419FreeMode:\r
420 FreePool (Private->GraphicsOutput.Mode);\r
421 Private->GraphicsOutput.Mode = NULL;\r
422\r
423 return Status;\r
eaf4f336 424}\r
425\r
426EFI_STATUS\r
427QemuVideoGraphicsOutputDestructor (\r
428 QEMU_VIDEO_PRIVATE_DATA *Private\r
429 )\r
430/*++\r
431\r
432Routine Description:\r
433\r
434Arguments:\r
435\r
436Returns:\r
437\r
438 None\r
439\r
440--*/\r
441{\r
5b2291f9
RN
442 if (Private->FrameBufferBltConfigure != NULL) {\r
443 FreePool (Private->FrameBufferBltConfigure);\r
444 }\r
445\r
eaf4f336 446 if (Private->GraphicsOutput.Mode != NULL) {\r
447 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
448 gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r
449 }\r
450 gBS->FreePool (Private->GraphicsOutput.Mode);\r
451 }\r
452\r
453 return EFI_SUCCESS;\r
454}\r
455\r
456\r