Gop.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /** @file
  2. Graphics Output Protocol functions for the QEMU video controller.
  3. Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Qemu.h"
  7. STATIC
  8. VOID
  9. QemuVideoCompleteModeInfo (
  10. IN QEMU_VIDEO_MODE_DATA *ModeData,
  11. OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
  12. )
  13. {
  14. Info->Version = 0;
  15. if (ModeData->ColorDepth == 8) {
  16. Info->PixelFormat = PixelBitMask;
  17. Info->PixelInformation.RedMask = PIXEL_RED_MASK;
  18. Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
  19. Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
  20. Info->PixelInformation.ReservedMask = 0;
  21. } else if (ModeData->ColorDepth == 24) {
  22. Info->PixelFormat = PixelBitMask;
  23. Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
  24. Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
  25. Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
  26. Info->PixelInformation.ReservedMask = 0;
  27. } else if (ModeData->ColorDepth == 32) {
  28. DEBUG ((DEBUG_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));
  29. Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
  30. Info->PixelInformation.RedMask = 0;
  31. Info->PixelInformation.GreenMask = 0;
  32. Info->PixelInformation.BlueMask = 0;
  33. Info->PixelInformation.ReservedMask = 0;
  34. } else {
  35. DEBUG ((DEBUG_ERROR, "%a: Invalid ColorDepth %u", __FUNCTION__, ModeData->ColorDepth));
  36. ASSERT (FALSE);
  37. }
  38. Info->PixelsPerScanLine = Info->HorizontalResolution;
  39. }
  40. STATIC
  41. EFI_STATUS
  42. QemuVideoCompleteModeData (
  43. IN QEMU_VIDEO_PRIVATE_DATA *Private,
  44. OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode
  45. )
  46. {
  47. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
  48. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;
  49. QEMU_VIDEO_MODE_DATA *ModeData;
  50. ModeData = &Private->ModeData[Mode->Mode];
  51. Info = Mode->Info;
  52. QemuVideoCompleteModeInfo (ModeData, Info);
  53. Private->PciIo->GetBarAttributes (
  54. Private->PciIo,
  55. Private->FrameBufferVramBarIndex,
  56. NULL,
  57. (VOID **)&FrameBufDesc
  58. );
  59. Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;
  60. Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;
  61. Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);
  62. Mode->FrameBufferSize = EFI_PAGES_TO_SIZE (
  63. EFI_SIZE_TO_PAGES (Mode->FrameBufferSize)
  64. );
  65. DEBUG ((
  66. DEBUG_INFO,
  67. "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n",
  68. Mode->FrameBufferBase,
  69. (UINT64)Mode->FrameBufferSize
  70. ));
  71. FreePool (FrameBufDesc);
  72. return EFI_SUCCESS;
  73. }
  74. //
  75. // Graphics Output Protocol Member Functions
  76. //
  77. EFI_STATUS
  78. EFIAPI
  79. QemuVideoGraphicsOutputQueryMode (
  80. IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  81. IN UINT32 ModeNumber,
  82. OUT UINTN *SizeOfInfo,
  83. OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  84. )
  85. /*++
  86. Routine Description:
  87. Graphics Output protocol interface to query video mode
  88. Arguments:
  89. This - Protocol instance pointer.
  90. ModeNumber - The mode number to return information on.
  91. Info - Caller allocated buffer that returns information about ModeNumber.
  92. SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
  93. Returns:
  94. EFI_SUCCESS - Mode information returned.
  95. EFI_BUFFER_TOO_SMALL - The Info buffer was too small.
  96. EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
  97. EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
  98. EFI_INVALID_PARAMETER - One of the input args was NULL.
  99. --*/
  100. {
  101. QEMU_VIDEO_PRIVATE_DATA *Private;
  102. QEMU_VIDEO_MODE_DATA *ModeData;
  103. Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
  104. if ((Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode)) {
  105. return EFI_INVALID_PARAMETER;
  106. }
  107. *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
  108. if (*Info == NULL) {
  109. return EFI_OUT_OF_RESOURCES;
  110. }
  111. *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  112. ModeData = &Private->ModeData[ModeNumber];
  113. (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
  114. (*Info)->VerticalResolution = ModeData->VerticalResolution;
  115. QemuVideoCompleteModeInfo (ModeData, *Info);
  116. return EFI_SUCCESS;
  117. }
  118. EFI_STATUS
  119. EFIAPI
  120. QemuVideoGraphicsOutputSetMode (
  121. IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  122. IN UINT32 ModeNumber
  123. )
  124. /*++
  125. Routine Description:
  126. Graphics Output protocol interface to set video mode
  127. Arguments:
  128. This - Protocol instance pointer.
  129. ModeNumber - The mode number to be set.
  130. Returns:
  131. EFI_SUCCESS - Graphics mode was changed.
  132. EFI_DEVICE_ERROR - The device had an error and could not complete the request.
  133. EFI_UNSUPPORTED - ModeNumber is not supported by this device.
  134. --*/
  135. {
  136. QEMU_VIDEO_PRIVATE_DATA *Private;
  137. QEMU_VIDEO_MODE_DATA *ModeData;
  138. RETURN_STATUS Status;
  139. EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
  140. Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
  141. if (ModeNumber >= This->Mode->MaxMode) {
  142. return EFI_UNSUPPORTED;
  143. }
  144. ModeData = &Private->ModeData[ModeNumber];
  145. switch (Private->Variant) {
  146. case QEMU_VIDEO_CIRRUS_5430:
  147. case QEMU_VIDEO_CIRRUS_5446:
  148. InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
  149. break;
  150. case QEMU_VIDEO_BOCHS_MMIO:
  151. case QEMU_VIDEO_BOCHS:
  152. InitializeBochsGraphicsMode (Private, ModeData);
  153. break;
  154. default:
  155. ASSERT (FALSE);
  156. return EFI_DEVICE_ERROR;
  157. }
  158. This->Mode->Mode = ModeNumber;
  159. This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
  160. This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
  161. This->Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  162. QemuVideoCompleteModeData (Private, This->Mode);
  163. //
  164. // Re-initialize the frame buffer configure when mode changes.
  165. //
  166. Status = FrameBufferBltConfigure (
  167. (VOID *)(UINTN)This->Mode->FrameBufferBase,
  168. This->Mode->Info,
  169. Private->FrameBufferBltConfigure,
  170. &Private->FrameBufferBltConfigureSize
  171. );
  172. if (Status == RETURN_BUFFER_TOO_SMALL) {
  173. //
  174. // Frame buffer configure may be larger in new mode.
  175. //
  176. if (Private->FrameBufferBltConfigure != NULL) {
  177. FreePool (Private->FrameBufferBltConfigure);
  178. }
  179. Private->FrameBufferBltConfigure =
  180. AllocatePool (Private->FrameBufferBltConfigureSize);
  181. ASSERT (Private->FrameBufferBltConfigure != NULL);
  182. //
  183. // Create the configuration for FrameBufferBltLib
  184. //
  185. Status = FrameBufferBltConfigure (
  186. (VOID *)(UINTN)This->Mode->FrameBufferBase,
  187. This->Mode->Info,
  188. Private->FrameBufferBltConfigure,
  189. &Private->FrameBufferBltConfigureSize
  190. );
  191. }
  192. ASSERT (Status == RETURN_SUCCESS);
  193. //
  194. // Per UEFI Spec, need to clear the visible portions of the output display to black.
  195. //
  196. ZeroMem (&Black, sizeof (Black));
  197. Status = FrameBufferBlt (
  198. Private->FrameBufferBltConfigure,
  199. &Black,
  200. EfiBltVideoFill,
  201. 0,
  202. 0,
  203. 0,
  204. 0,
  205. This->Mode->Info->HorizontalResolution,
  206. This->Mode->Info->VerticalResolution,
  207. 0
  208. );
  209. ASSERT_RETURN_ERROR (Status);
  210. return EFI_SUCCESS;
  211. }
  212. EFI_STATUS
  213. EFIAPI
  214. QemuVideoGraphicsOutputBlt (
  215. IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  216. IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
  217. IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  218. IN UINTN SourceX,
  219. IN UINTN SourceY,
  220. IN UINTN DestinationX,
  221. IN UINTN DestinationY,
  222. IN UINTN Width,
  223. IN UINTN Height,
  224. IN UINTN Delta
  225. )
  226. /*++
  227. Routine Description:
  228. Graphics Output protocol instance to block transfer for CirrusLogic device
  229. Arguments:
  230. This - Pointer to Graphics Output protocol instance
  231. BltBuffer - The data to transfer to screen
  232. BltOperation - The operation to perform
  233. SourceX - The X coordinate of the source for BltOperation
  234. SourceY - The Y coordinate of the source for BltOperation
  235. DestinationX - The X coordinate of the destination for BltOperation
  236. DestinationY - The Y coordinate of the destination for BltOperation
  237. Width - The width of a rectangle in the blt rectangle in pixels
  238. Height - The height of a rectangle in the blt rectangle in pixels
  239. Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
  240. If a Delta of 0 is used, the entire BltBuffer will be operated on.
  241. If a subrectangle of the BltBuffer is used, then Delta represents
  242. the number of bytes in a row of the BltBuffer.
  243. Returns:
  244. EFI_INVALID_PARAMETER - Invalid parameter passed in
  245. EFI_SUCCESS - Blt operation success
  246. --*/
  247. {
  248. EFI_STATUS Status;
  249. EFI_TPL OriginalTPL;
  250. QEMU_VIDEO_PRIVATE_DATA *Private;
  251. Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);
  252. //
  253. // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
  254. // We would not want a timer based event (Cursor, ...) to come in while we are
  255. // doing this operation.
  256. //
  257. OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
  258. switch (BltOperation) {
  259. case EfiBltVideoToBltBuffer:
  260. case EfiBltBufferToVideo:
  261. case EfiBltVideoFill:
  262. case EfiBltVideoToVideo:
  263. Status = FrameBufferBlt (
  264. Private->FrameBufferBltConfigure,
  265. BltBuffer,
  266. BltOperation,
  267. SourceX,
  268. SourceY,
  269. DestinationX,
  270. DestinationY,
  271. Width,
  272. Height,
  273. Delta
  274. );
  275. break;
  276. default:
  277. Status = EFI_INVALID_PARAMETER;
  278. break;
  279. }
  280. gBS->RestoreTPL (OriginalTPL);
  281. return Status;
  282. }
  283. EFI_STATUS
  284. QemuVideoGraphicsOutputConstructor (
  285. QEMU_VIDEO_PRIVATE_DATA *Private
  286. )
  287. {
  288. EFI_STATUS Status;
  289. EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
  290. GraphicsOutput = &Private->GraphicsOutput;
  291. GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;
  292. GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;
  293. GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;
  294. //
  295. // Initialize the private data
  296. //
  297. Status = gBS->AllocatePool (
  298. EfiBootServicesData,
  299. sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
  300. (VOID **)&Private->GraphicsOutput.Mode
  301. );
  302. if (EFI_ERROR (Status)) {
  303. return Status;
  304. }
  305. Status = gBS->AllocatePool (
  306. EfiBootServicesData,
  307. sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
  308. (VOID **)&Private->GraphicsOutput.Mode->Info
  309. );
  310. if (EFI_ERROR (Status)) {
  311. goto FreeMode;
  312. }
  313. Private->GraphicsOutput.Mode->MaxMode = (UINT32)Private->MaxMode;
  314. Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;
  315. Private->FrameBufferBltConfigure = NULL;
  316. Private->FrameBufferBltConfigureSize = 0;
  317. //
  318. // Initialize the hardware
  319. //
  320. Status = GraphicsOutput->SetMode (GraphicsOutput, 0);
  321. if (EFI_ERROR (Status)) {
  322. goto FreeInfo;
  323. }
  324. DrawLogo (
  325. Private,
  326. Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,
  327. Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution
  328. );
  329. return EFI_SUCCESS;
  330. FreeInfo:
  331. FreePool (Private->GraphicsOutput.Mode->Info);
  332. FreeMode:
  333. FreePool (Private->GraphicsOutput.Mode);
  334. Private->GraphicsOutput.Mode = NULL;
  335. return Status;
  336. }
  337. EFI_STATUS
  338. QemuVideoGraphicsOutputDestructor (
  339. QEMU_VIDEO_PRIVATE_DATA *Private
  340. )
  341. /*++
  342. Routine Description:
  343. Arguments:
  344. Returns:
  345. None
  346. --*/
  347. {
  348. if (Private->FrameBufferBltConfigure != NULL) {
  349. FreePool (Private->FrameBufferBltConfigure);
  350. }
  351. if (Private->GraphicsOutput.Mode != NULL) {
  352. if (Private->GraphicsOutput.Mode->Info != NULL) {
  353. gBS->FreePool (Private->GraphicsOutput.Mode->Info);
  354. }
  355. gBS->FreePool (Private->GraphicsOutput.Mode);
  356. }
  357. return EFI_SUCCESS;
  358. }