]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / Bhyve / BhyveRfbDxe / GopScreen.c
... / ...
CommitLineData
1/*++ @file\r
2\r
3Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
4Copyright (c) 2015, Nahanni Systems, Inc.\r
5Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
6Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.\r
7\r
8SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10Module Name:\r
11\r
12 EmuGopScreen.c\r
13\r
14Abstract:\r
15\r
16 This file produces the graphics abstration of UGA. It is called by\r
17 EmuGopDriver.c file which deals with the EFI 1.1 driver model.\r
18 This file just does graphics.\r
19\r
20**/\r
21\r
22#include "Gop.h"\r
23#include <Library/FrameBufferBltLib.h>\r
24\r
25EFI_EVENT mGopScreenExitBootServicesEvent;\r
26\r
27GOP_MODE_DATA mGopModeData[] = {\r
28 { 0, 0, 32, 0 }, // Filled in with user-spec'd resolution\r
29 { 1024, 768, 32, 0 },\r
30 { 800, 600, 32, 0 },\r
31 { 640, 480, 32, 0 }\r
32};\r
33\r
34STATIC\r
35VOID\r
36BhyveGopCompleteModeInfo (\r
37 IN GOP_MODE_DATA *ModeData,\r
38 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info\r
39 )\r
40{\r
41 Info->Version = 0;\r
42 if (ModeData->ColorDepth == 8) {\r
43 Info->PixelFormat = PixelBitMask;\r
44 Info->PixelInformation.RedMask = PIXEL_RED_MASK;\r
45 Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;\r
46 Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;\r
47 Info->PixelInformation.ReservedMask = 0;\r
48 } else if (ModeData->ColorDepth == 24) {\r
49 Info->PixelFormat = PixelBitMask;\r
50 Info->PixelInformation.RedMask = PIXEL24_RED_MASK;\r
51 Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;\r
52 Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;\r
53 Info->PixelInformation.ReservedMask = 0;\r
54 } else if (ModeData->ColorDepth == 32) {\r
55 DEBUG ((\r
56 DEBUG_INFO,\r
57 "%dx%d PixelBlueGreenRedReserved8BitPerColor\n",\r
58 ModeData->HorizontalResolution,\r
59 ModeData->VerticalResolution\r
60 ));\r
61 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
62 }\r
63\r
64 Info->PixelsPerScanLine = Info->HorizontalResolution;\r
65}\r
66\r
67/**\r
68 Returns information for an available graphics mode that the graphics device\r
69 and the set of active video output devices supports.\r
70\r
71 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.\r
72 @param ModeNumber The mode number to return information on.\r
73 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.\r
74 @param Info A pointer to callee allocated buffer that returns information about ModeNumber.\r
75\r
76 @retval EFI_SUCCESS Mode information returned.\r
77 @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.\r
78 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.\r
79 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()\r
80 @retval EFI_INVALID_PARAMETER One of the input args was NULL.\r
81\r
82**/\r
83EFI_STATUS\r
84EFIAPI\r
85EmuGopQuerytMode (\r
86 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
87 IN UINT32 ModeNumber,\r
88 OUT UINTN *SizeOfInfo,\r
89 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
90 )\r
91{\r
92 GOP_PRIVATE_DATA *Private;\r
93 GOP_MODE_DATA *ModeData;\r
94\r
95 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
96\r
97 if ((Info == NULL) || (SizeOfInfo == NULL) || ((UINTN)ModeNumber >= This->Mode->MaxMode)) {\r
98 return EFI_INVALID_PARAMETER;\r
99 }\r
100\r
101 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
102 if (*Info == NULL) {\r
103 return EFI_OUT_OF_RESOURCES;\r
104 }\r
105\r
106 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
107\r
108 ModeData = &Private->ModeData[ModeNumber];\r
109 (*Info)->Version = 0;\r
110 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
111 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
112 (*Info)->PixelFormat = PixelBitMask;\r
113 (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;\r
114 BhyveGopCompleteModeInfo (ModeData, *Info);\r
115 return EFI_SUCCESS;\r
116}\r
117\r
118/**\r
119 Set the video device into the specified mode and clears the visible portions of\r
120 the output display to black.\r
121\r
122 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.\r
123 @param ModeNumber Abstraction that defines the current video mode.\r
124\r
125 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.\r
126 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.\r
127 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.\r
128\r
129**/\r
130\r
131FRAME_BUFFER_CONFIGURE *fbconf;\r
132\r
133EFI_STATUS\r
134EFIAPI\r
135EmuGopSetMode (\r
136 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
137 IN UINT32 ModeNumber\r
138 )\r
139{\r
140 GOP_PRIVATE_DATA *Private;\r
141 GOP_MODE_DATA *ModeData;\r
142 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;\r
143 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
144\r
145 UINTN confsize = 0;\r
146\r
147 fbconf = NULL;\r
148\r
149 Private = GOP_PRIVATE_DATA_FROM_THIS (This);\r
150\r
151 if (ModeNumber >= This->Mode->MaxMode) {\r
152 // Tell bhyve that we are switching out of vesa\r
153 BhyveSetGraphicsMode (Private, 0, 0, 0);\r
154 return EFI_UNSUPPORTED;\r
155 }\r
156\r
157 DEBUG ((DEBUG_INFO, "BHYVE GopSetMode %d\n", ModeNumber));\r
158\r
159 ModeData = &Private->ModeData[ModeNumber];\r
160 This->Mode->Mode = ModeNumber;\r
161 Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
162 Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
163 Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;\r
164\r
165 Info = This->Mode->Info;\r
166 BhyveGopCompleteModeInfo (ModeData, Info);\r
167\r
168 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
169 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
170 This->Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
171 This->Mode->FrameBufferBase = Private->GraphicsOutput.Mode->FrameBufferBase;\r
172\r
173 /*\r
174 This->Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution\r
175 * ((ModeData->ColorDepth + 7) / 8);\r
176 */\r
177 This->Mode->FrameBufferSize = Private->FbSize;\r
178 DEBUG ((DEBUG_INFO, "BHYVE GOP FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", This->Mode->FrameBufferBase, This->Mode->FrameBufferSize));\r
179\r
180 BhyveSetGraphicsMode (Private, (UINT16)ModeData->HorizontalResolution, (UINT16)ModeData->VerticalResolution, (UINT16)ModeData->ColorDepth);\r
181\r
182 RETURN_STATUS ret = FrameBufferBltConfigure (\r
183 (VOID *)(UINTN)This->Mode->FrameBufferBase,\r
184 This->Mode->Info,\r
185 fbconf,\r
186 &confsize\r
187 );\r
188\r
189 if ((ret == EFI_BUFFER_TOO_SMALL) || (ret == EFI_INVALID_PARAMETER)) {\r
190 fbconf = AllocatePool (confsize);\r
191 ret = FrameBufferBltConfigure (\r
192 (VOID *)(UINTN)This->Mode->FrameBufferBase,\r
193 This->Mode->Info,\r
194 fbconf,\r
195 &confsize\r
196 );\r
197 ASSERT (ret == EFI_SUCCESS);\r
198 }\r
199\r
200 Fill.Red = 0;\r
201 Fill.Green = 0;\r
202 Fill.Blue = 0;\r
203 This->Blt (\r
204 This,\r
205 &Fill,\r
206 EfiBltVideoFill,\r
207 0,\r
208 0,\r
209 0,\r
210 0,\r
211 ModeData->HorizontalResolution,\r
212 ModeData->VerticalResolution,\r
213 ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
214 );\r
215 return EFI_SUCCESS;\r
216}\r
217\r
218/**\r
219 Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.\r
220\r
221 @param This Protocol instance pointer.\r
222 @param BltBuffer Buffer containing data to blit into video buffer. This\r
223 buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
224 @param BltOperation Operation to perform on BlitBuffer and video memory\r
225 @param SourceX X coordinate of source for the BltBuffer.\r
226 @param SourceY Y coordinate of source for the BltBuffer.\r
227 @param DestinationX X coordinate of destination for the BltBuffer.\r
228 @param DestinationY Y coordinate of destination for the BltBuffer.\r
229 @param Width Width of rectangle in BltBuffer in pixels.\r
230 @param Height Hight of rectangle in BltBuffer in pixels.\r
231 @param Delta OPTIONAL\r
232\r
233 @retval EFI_SUCCESS The Blt operation completed.\r
234 @retval EFI_INVALID_PARAMETER BltOperation is not valid.\r
235 @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.\r
236\r
237**/\r
238EFI_STATUS\r
239EFIAPI\r
240EmuGopBlt (\r
241 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
242 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
243 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
244 IN UINTN SourceX,\r
245 IN UINTN SourceY,\r
246 IN UINTN DestinationX,\r
247 IN UINTN DestinationY,\r
248 IN UINTN Width,\r
249 IN UINTN Height,\r
250 IN UINTN Delta OPTIONAL\r
251 )\r
252{\r
253 EFI_TPL OriginalTPL;\r
254 EFI_STATUS Status;\r
255\r
256 if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {\r
257 return EFI_INVALID_PARAMETER;\r
258 }\r
259\r
260 if ((Width == 0) || (Height == 0)) {\r
261 return EFI_INVALID_PARAMETER;\r
262 }\r
263\r
264 //\r
265 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
266 // We would not want a timer based event (Cursor, ...) to come in while we are\r
267 // doing this operation.\r
268 //\r
269 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
270\r
271 switch (BltOperation) {\r
272 case EfiBltVideoToBltBuffer:\r
273 case EfiBltBufferToVideo:\r
274 case EfiBltVideoFill:\r
275 case EfiBltVideoToVideo:\r
276 Status = FrameBufferBlt (\r
277 fbconf,\r
278 BltBuffer,\r
279 BltOperation,\r
280 SourceX,\r
281 SourceY,\r
282 DestinationX,\r
283 DestinationY,\r
284 Width,\r
285 Height,\r
286 Delta\r
287 );\r
288 break;\r
289\r
290 default:\r
291 Status = EFI_INVALID_PARAMETER;\r
292 ASSERT (FALSE);\r
293 }\r
294\r
295 gBS->RestoreTPL (OriginalTPL);\r
296\r
297 return Status;\r
298}\r
299\r
300//\r
301// Construction and Destruction functions\r
302//\r
303\r
304EFI_STATUS\r
305EmuGopConstructor (\r
306 GOP_PRIVATE_DATA *Private\r
307 )\r
308{\r
309 // Set mode 0 to be the requested resolution\r
310 mGopModeData[0].HorizontalResolution = PcdGet32 (PcdVideoHorizontalResolution);\r
311 mGopModeData[0].VerticalResolution = PcdGet32 (PcdVideoVerticalResolution);\r
312\r
313 Private->ModeData = mGopModeData;\r
314\r
315 Private->GraphicsOutput.QueryMode = EmuGopQuerytMode;\r
316 Private->GraphicsOutput.SetMode = EmuGopSetMode;\r
317 Private->GraphicsOutput.Blt = EmuGopBlt;\r
318\r
319 //\r
320 // Allocate buffer for Graphics Output Protocol mode information\r
321 //\r
322 Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));\r
323 if (Private->GraphicsOutput.Mode == NULL) {\r
324 return EFI_OUT_OF_RESOURCES;\r
325 }\r
326\r
327 Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
328 if (Private->GraphicsOutput.Mode->Info == NULL) {\r
329 return EFI_OUT_OF_RESOURCES;\r
330 }\r
331\r
332 DEBUG ((DEBUG_INFO, "BHYVE Gop Constructor\n"));\r
333\r
334 Private->GraphicsOutput.Mode->MaxMode = sizeof (mGopModeData) / sizeof (GOP_MODE_DATA);\r
335 //\r
336 // Till now, we have no idea about the window size.\r
337 //\r
338 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALID_MODE_NUMBER;\r
339 Private->GraphicsOutput.Mode->Info->Version = 0;\r
340 Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;\r
341 Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;\r
342 Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBitMask;\r
343 Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
344 Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)Private->FbAddr;\r
345 Private->GraphicsOutput.Mode->FrameBufferSize = Private->FbSize;\r
346\r
347 return EFI_SUCCESS;\r
348}\r
349\r
350EFI_STATUS\r
351EmuGopDestructor (\r
352 GOP_PRIVATE_DATA *Private\r
353 )\r
354{\r
355 //\r
356 // Free graphics output protocol occupied resource\r
357 //\r
358 if (Private->GraphicsOutput.Mode != NULL) {\r
359 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
360 FreePool (Private->GraphicsOutput.Mode->Info);\r
361 }\r
362\r
363 FreePool (Private->GraphicsOutput.Mode);\r
364 Private->GraphicsOutput.Mode = NULL;\r
365 }\r
366\r
367 return EFI_SUCCESS;\r
368}\r
369\r
370VOID\r
371EFIAPI\r
372ShutdownGopEvent (\r
373 IN EFI_EVENT Event,\r
374 IN VOID *Context\r
375 )\r
376\r
377/*++\r
378\r
379Routine Description:\r
380\r
381 This is the UGA screen's callback notification function for exit-boot-services.\r
382 All we do here is call EmuGopDestructor().\r
383\r
384Arguments:\r
385\r
386 Event - not used\r
387 Context - pointer to the Private structure.\r
388\r
389Returns:\r
390\r
391 None.\r
392\r
393**/\r
394{\r
395 EmuGopDestructor (Context);\r
396}\r