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