Gop.c 12 KB

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