GopScreen.c 13 KB

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