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