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