Logo.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /** @file
  2. BDS Lib functions which contain all the code to connect console device
  3. Copyright (c) 2006 - 2019 Intel Corporation. All rights reserved. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiDxe.h>
  7. #include <Protocol/SimpleTextOut.h>
  8. #include <OemBadging.h>
  9. #include <Protocol/GraphicsOutput.h>
  10. #include <Protocol/UgaDraw.h>
  11. #include <Library/BaseLib.h>
  12. #include <Library/UefiLib.h>
  13. #include <Library/BaseMemoryLib.h>
  14. #include <Library/UefiBootServicesTableLib.h>
  15. #include <Library/DxeServicesLib.h>
  16. #include <Library/PcdLib.h>
  17. #include <Library/MemoryAllocationLib.h>
  18. #include <Library/DebugLib.h>
  19. #include <IndustryStandard/Bmp.h>
  20. #include <Protocol/BootLogo.h>
  21. /**
  22. Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
  23. is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
  24. buffer is passed in it will be used if it is big enough.
  25. @param BmpImage Pointer to BMP file
  26. @param BmpImageSize Number of bytes in BmpImage
  27. @param GopBlt Buffer containing GOP version of BmpImage.
  28. @param GopBltSize Size of GopBlt in bytes.
  29. @param PixelHeight Height of GopBlt/BmpImage in pixels
  30. @param PixelWidth Width of GopBlt/BmpImage in pixels
  31. @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
  32. @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
  33. @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
  34. GopBltSize will contain the required size.
  35. @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
  36. **/
  37. EFI_STATUS
  38. ConvertBmpToGopBlt (
  39. IN VOID *BmpImage,
  40. IN UINTN BmpImageSize,
  41. IN OUT VOID **GopBlt,
  42. IN OUT UINTN *GopBltSize,
  43. OUT UINTN *PixelHeight,
  44. OUT UINTN *PixelWidth
  45. )
  46. {
  47. UINT8 *Image;
  48. UINT8 *ImageHeader;
  49. BMP_IMAGE_HEADER *BmpHeader;
  50. BMP_COLOR_MAP *BmpColorMap;
  51. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
  52. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
  53. UINT64 BltBufferSize;
  54. UINTN Index;
  55. UINTN Height;
  56. UINTN Width;
  57. UINTN ImageIndex;
  58. UINT32 DataSizePerLine;
  59. BOOLEAN IsAllocated;
  60. UINT32 ColorMapNum;
  61. if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
  62. return EFI_INVALID_PARAMETER;
  63. }
  64. BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
  65. if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
  66. return EFI_UNSUPPORTED;
  67. }
  68. //
  69. // Doesn't support compress.
  70. //
  71. if (BmpHeader->CompressionType != 0) {
  72. return EFI_UNSUPPORTED;
  73. }
  74. //
  75. // Only support BITMAPINFOHEADER format.
  76. // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
  77. //
  78. if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
  79. return EFI_UNSUPPORTED;
  80. }
  81. //
  82. // The data size in each line must be 4 byte alignment.
  83. //
  84. DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
  85. BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
  86. if (BltBufferSize > (UINT32) ~0) {
  87. return EFI_INVALID_PARAMETER;
  88. }
  89. if ((BmpHeader->Size != BmpImageSize) ||
  90. (BmpHeader->Size < BmpHeader->ImageOffset) ||
  91. (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {
  92. return EFI_INVALID_PARAMETER;
  93. }
  94. //
  95. // Calculate Color Map offset in the image.
  96. //
  97. Image = BmpImage;
  98. BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
  99. if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
  100. return EFI_INVALID_PARAMETER;
  101. }
  102. if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
  103. switch (BmpHeader->BitPerPixel) {
  104. case 1:
  105. ColorMapNum = 2;
  106. break;
  107. case 4:
  108. ColorMapNum = 16;
  109. break;
  110. case 8:
  111. ColorMapNum = 256;
  112. break;
  113. default:
  114. ColorMapNum = 0;
  115. break;
  116. }
  117. //
  118. // BMP file may has padding data between the bmp header section and the bmp data section.
  119. //
  120. if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
  121. return EFI_INVALID_PARAMETER;
  122. }
  123. }
  124. //
  125. // Calculate graphics image data address in the image
  126. //
  127. Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
  128. ImageHeader = Image;
  129. //
  130. // Calculate the BltBuffer needed size.
  131. //
  132. BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
  133. //
  134. // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
  135. //
  136. if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
  137. return EFI_UNSUPPORTED;
  138. }
  139. BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
  140. IsAllocated = FALSE;
  141. if (*GopBlt == NULL) {
  142. //
  143. // GopBlt is not allocated by caller.
  144. //
  145. *GopBltSize = (UINTN) BltBufferSize;
  146. *GopBlt = AllocatePool (*GopBltSize);
  147. IsAllocated = TRUE;
  148. if (*GopBlt == NULL) {
  149. return EFI_OUT_OF_RESOURCES;
  150. }
  151. } else {
  152. //
  153. // GopBlt has been allocated by caller.
  154. //
  155. if (*GopBltSize < (UINTN) BltBufferSize) {
  156. *GopBltSize = (UINTN) BltBufferSize;
  157. return EFI_BUFFER_TOO_SMALL;
  158. }
  159. }
  160. *PixelWidth = BmpHeader->PixelWidth;
  161. *PixelHeight = BmpHeader->PixelHeight;
  162. //
  163. // Convert image from BMP to Blt buffer format
  164. //
  165. BltBuffer = *GopBlt;
  166. for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
  167. Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
  168. for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
  169. switch (BmpHeader->BitPerPixel) {
  170. case 1:
  171. //
  172. // Convert 1-bit (2 colors) BMP to 24-bit color
  173. //
  174. for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
  175. Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
  176. Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
  177. Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
  178. Blt++;
  179. Width++;
  180. }
  181. Blt--;
  182. Width--;
  183. break;
  184. case 4:
  185. //
  186. // Convert 4-bit (16 colors) BMP Palette to 24-bit color
  187. //
  188. Index = (*Image) >> 4;
  189. Blt->Red = BmpColorMap[Index].Red;
  190. Blt->Green = BmpColorMap[Index].Green;
  191. Blt->Blue = BmpColorMap[Index].Blue;
  192. if (Width < (BmpHeader->PixelWidth - 1)) {
  193. Blt++;
  194. Width++;
  195. Index = (*Image) & 0x0f;
  196. Blt->Red = BmpColorMap[Index].Red;
  197. Blt->Green = BmpColorMap[Index].Green;
  198. Blt->Blue = BmpColorMap[Index].Blue;
  199. }
  200. break;
  201. case 8:
  202. //
  203. // Convert 8-bit (256 colors) BMP Palette to 24-bit color
  204. //
  205. Blt->Red = BmpColorMap[*Image].Red;
  206. Blt->Green = BmpColorMap[*Image].Green;
  207. Blt->Blue = BmpColorMap[*Image].Blue;
  208. break;
  209. case 24:
  210. //
  211. // It is 24-bit BMP.
  212. //
  213. Blt->Blue = *Image++;
  214. Blt->Green = *Image++;
  215. Blt->Red = *Image;
  216. break;
  217. default:
  218. //
  219. // Other bit format BMP is not supported.
  220. //
  221. if (IsAllocated) {
  222. FreePool (*GopBlt);
  223. *GopBlt = NULL;
  224. }
  225. return EFI_UNSUPPORTED;
  226. break;
  227. };
  228. }
  229. ImageIndex = (UINTN) (Image - ImageHeader);
  230. if ((ImageIndex % 4) != 0) {
  231. //
  232. // Bmp Image starts each row on a 32-bit boundary!
  233. //
  234. Image = Image + (4 - (ImageIndex % 4));
  235. }
  236. }
  237. return EFI_SUCCESS;
  238. }
  239. /**
  240. Use SystemTable Conout to stop video based Simple Text Out consoles from going
  241. to the video device. Put up LogoFile on every video device that is a console.
  242. @param[in] LogoFile File name of logo to display on the center of the screen.
  243. @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.
  244. @retval EFI_UNSUPPORTED Logo not found
  245. **/
  246. EFI_STATUS
  247. EFIAPI
  248. EnableBootLogo (
  249. IN EFI_GUID *LogoFile
  250. )
  251. {
  252. EFI_STATUS Status;
  253. EFI_OEM_BADGING_PROTOCOL *Badging;
  254. UINT32 SizeOfX;
  255. UINT32 SizeOfY;
  256. INTN DestX;
  257. INTN DestY;
  258. UINT8 *ImageData;
  259. UINTN ImageSize;
  260. UINTN BltSize;
  261. UINT32 Instance;
  262. EFI_BADGING_FORMAT Format;
  263. EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
  264. UINTN CoordinateX;
  265. UINTN CoordinateY;
  266. UINTN Height;
  267. UINTN Width;
  268. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
  269. EFI_UGA_DRAW_PROTOCOL *UgaDraw;
  270. UINT32 ColorDepth;
  271. UINT32 RefreshRate;
  272. EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
  273. EFI_BOOT_LOGO_PROTOCOL *BootLogo;
  274. UINTN NumberOfLogos;
  275. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
  276. UINTN LogoDestX;
  277. UINTN LogoDestY;
  278. UINTN LogoHeight;
  279. UINTN LogoWidth;
  280. UINTN NewDestX;
  281. UINTN NewDestY;
  282. UINTN NewHeight;
  283. UINTN NewWidth;
  284. UINT64 BufferSize;
  285. UgaDraw = NULL;
  286. //
  287. // Try to open GOP first
  288. //
  289. Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
  290. if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
  291. GraphicsOutput = NULL;
  292. //
  293. // Open GOP failed, try to open UGA
  294. //
  295. Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
  296. }
  297. if (EFI_ERROR (Status)) {
  298. return EFI_UNSUPPORTED;
  299. }
  300. //
  301. // Try to open Boot Logo Protocol.
  302. //
  303. BootLogo = NULL;
  304. gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
  305. //
  306. // Erase Cursor from screen
  307. //
  308. gST->ConOut->EnableCursor (gST->ConOut, FALSE);
  309. Badging = NULL;
  310. Status = gBS->LocateProtocol (&gEfiOemBadgingProtocolGuid, NULL, (VOID **) &Badging);
  311. if (GraphicsOutput != NULL) {
  312. SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
  313. SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
  314. } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
  315. Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
  316. if (EFI_ERROR (Status)) {
  317. return EFI_UNSUPPORTED;
  318. }
  319. } else {
  320. return EFI_UNSUPPORTED;
  321. }
  322. Blt = NULL;
  323. NumberOfLogos = 0;
  324. LogoDestX = 0;
  325. LogoDestY = 0;
  326. LogoHeight = 0;
  327. LogoWidth = 0;
  328. NewDestX = 0;
  329. NewDestY = 0;
  330. NewHeight = 0;
  331. NewWidth = 0;
  332. Instance = 0;
  333. while (1) {
  334. ImageData = NULL;
  335. ImageSize = 0;
  336. if (Badging != NULL) {
  337. //
  338. // Get image from OEMBadging protocol.
  339. //
  340. Status = Badging->GetImage (
  341. Badging,
  342. &Instance,
  343. &Format,
  344. &ImageData,
  345. &ImageSize,
  346. &Attribute,
  347. &CoordinateX,
  348. &CoordinateY
  349. );
  350. if (EFI_ERROR (Status)) {
  351. goto Done;
  352. }
  353. } else {
  354. //
  355. // Get the specified image from FV.
  356. //
  357. Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
  358. if (EFI_ERROR (Status)) {
  359. return EFI_UNSUPPORTED;
  360. }
  361. CoordinateX = 0;
  362. CoordinateY = 0;
  363. Attribute = EfiBadgingDisplayAttributeCenter;
  364. }
  365. if (Blt != NULL) {
  366. FreePool (Blt);
  367. }
  368. //
  369. // Try BMP decoder
  370. //
  371. Blt = NULL;
  372. Status = ConvertBmpToGopBlt (
  373. ImageData,
  374. ImageSize,
  375. (VOID **) &Blt,
  376. &BltSize,
  377. &Height,
  378. &Width
  379. );
  380. if (EFI_ERROR (Status)) {
  381. FreePool (ImageData);
  382. if (Badging == NULL) {
  383. return Status;
  384. } else {
  385. continue;
  386. }
  387. }
  388. //
  389. // Calculate the display position according to Attribute.
  390. //
  391. switch (Attribute) {
  392. case EfiBadgingDisplayAttributeLeftTop:
  393. DestX = CoordinateX;
  394. DestY = CoordinateY;
  395. break;
  396. case EfiBadgingDisplayAttributeCenterTop:
  397. DestX = (SizeOfX - Width) / 2;
  398. DestY = CoordinateY;
  399. break;
  400. case EfiBadgingDisplayAttributeRightTop:
  401. DestX = (SizeOfX - Width - CoordinateX);
  402. DestY = CoordinateY;;
  403. break;
  404. case EfiBadgingDisplayAttributeCenterRight:
  405. DestX = (SizeOfX - Width - CoordinateX);
  406. DestY = (SizeOfY - Height) / 2;
  407. break;
  408. case EfiBadgingDisplayAttributeRightBottom:
  409. DestX = (SizeOfX - Width - CoordinateX);
  410. DestY = (SizeOfY - Height - CoordinateY);
  411. break;
  412. case EfiBadgingDisplayAttributeCenterBottom:
  413. DestX = (SizeOfX - Width) / 2;
  414. DestY = (SizeOfY - Height - CoordinateY);
  415. break;
  416. case EfiBadgingDisplayAttributeLeftBottom:
  417. DestX = CoordinateX;
  418. DestY = (SizeOfY - Height - CoordinateY);
  419. break;
  420. case EfiBadgingDisplayAttributeCenterLeft:
  421. DestX = CoordinateX;
  422. DestY = (SizeOfY - Height) / 2;
  423. break;
  424. case EfiBadgingDisplayAttributeCenter:
  425. DestX = (SizeOfX - Width) / 2;
  426. DestY = (SizeOfY - Height) / 2;
  427. break;
  428. default:
  429. DestX = CoordinateX;
  430. DestY = CoordinateY;
  431. break;
  432. }
  433. if ((DestX >= 0) && (DestY >= 0)) {
  434. if (GraphicsOutput != NULL) {
  435. Status = GraphicsOutput->Blt (
  436. GraphicsOutput,
  437. Blt,
  438. EfiBltBufferToVideo,
  439. 0,
  440. 0,
  441. (UINTN) DestX,
  442. (UINTN) DestY,
  443. Width,
  444. Height,
  445. Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
  446. );
  447. } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
  448. Status = UgaDraw->Blt (
  449. UgaDraw,
  450. (EFI_UGA_PIXEL *) Blt,
  451. EfiUgaBltBufferToVideo,
  452. 0,
  453. 0,
  454. (UINTN) DestX,
  455. (UINTN) DestY,
  456. Width,
  457. Height,
  458. Width * sizeof (EFI_UGA_PIXEL)
  459. );
  460. } else {
  461. Status = EFI_UNSUPPORTED;
  462. }
  463. //
  464. // Report displayed Logo information.
  465. //
  466. if (!EFI_ERROR (Status)) {
  467. NumberOfLogos++;
  468. if (LogoWidth == 0) {
  469. //
  470. // The first Logo.
  471. //
  472. LogoDestX = (UINTN) DestX;
  473. LogoDestY = (UINTN) DestY;
  474. LogoWidth = Width;
  475. LogoHeight = Height;
  476. } else {
  477. //
  478. // Merge new logo with old one.
  479. //
  480. NewDestX = MIN ((UINTN) DestX, LogoDestX);
  481. NewDestY = MIN ((UINTN) DestY, LogoDestY);
  482. NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;
  483. NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;
  484. LogoDestX = NewDestX;
  485. LogoDestY = NewDestY;
  486. LogoWidth = NewWidth;
  487. LogoHeight = NewHeight;
  488. }
  489. }
  490. }
  491. FreePool (ImageData);
  492. if (Badging == NULL) {
  493. break;
  494. }
  495. }
  496. Done:
  497. if (BootLogo == NULL || NumberOfLogos == 0) {
  498. //
  499. // No logo displayed.
  500. //
  501. if (Blt != NULL) {
  502. FreePool (Blt);
  503. }
  504. return Status;
  505. }
  506. //
  507. // Advertise displayed Logo information.
  508. //
  509. if (NumberOfLogos == 1) {
  510. //
  511. // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
  512. //
  513. LogoBlt = Blt;
  514. Status = EFI_SUCCESS;
  515. } else {
  516. //
  517. // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
  518. //
  519. if (Blt != NULL) {
  520. FreePool (Blt);
  521. }
  522. //
  523. // Ensure the LogoHeight * LogoWidth doesn't overflow
  524. //
  525. if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) {
  526. return EFI_UNSUPPORTED;
  527. }
  528. BufferSize = MultU64x64 (LogoWidth, LogoHeight);
  529. //
  530. // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
  531. //
  532. if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
  533. return EFI_UNSUPPORTED;
  534. }
  535. LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
  536. if (LogoBlt == NULL) {
  537. return EFI_OUT_OF_RESOURCES;
  538. }
  539. if (GraphicsOutput != NULL) {
  540. Status = GraphicsOutput->Blt (
  541. GraphicsOutput,
  542. LogoBlt,
  543. EfiBltVideoToBltBuffer,
  544. LogoDestX,
  545. LogoDestY,
  546. 0,
  547. 0,
  548. LogoWidth,
  549. LogoHeight,
  550. LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
  551. );
  552. } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {
  553. Status = UgaDraw->Blt (
  554. UgaDraw,
  555. (EFI_UGA_PIXEL *) LogoBlt,
  556. EfiUgaVideoToBltBuffer,
  557. LogoDestX,
  558. LogoDestY,
  559. 0,
  560. 0,
  561. LogoWidth,
  562. LogoHeight,
  563. LogoWidth * sizeof (EFI_UGA_PIXEL)
  564. );
  565. } else {
  566. Status = EFI_UNSUPPORTED;
  567. }
  568. }
  569. if (!EFI_ERROR (Status)) {
  570. BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);
  571. }
  572. FreePool (LogoBlt);
  573. return Status;
  574. }