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