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