--- /dev/null
+/** @file\r
+ Provides services to display completion progress of a firmware update on a\r
+ graphical console that supports the Graphics Output Protocol.\r
+\r
+ Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+ 1. Redistributions of source code must retain the above copyright notice,\r
+ this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/BootLogo2.h>\r
+\r
+//\r
+// Values in percent of of logo height.\r
+//\r
+#define LOGO_BOTTOM_PADDING 20\r
+#define PROGRESS_BLOCK_HEIGHT 10\r
+\r
+//\r
+// Graphics Output Protocol instance to display progress bar\r
+//\r
+EFI_GRAPHICS_OUTPUT_PROTOCOL *mGop = NULL;\r
+\r
+//\r
+// Set to 100 percent so it is reset on first call.\r
+//\r
+UINTN mPreviousProgress = 100;\r
+\r
+//\r
+// Display coordinates for the progress bar.\r
+//\r
+UINTN mStartX = 0;\r
+UINTN mStartY = 0;\r
+\r
+//\r
+// Width and height of the progress bar.\r
+//\r
+UINTN mBlockWidth = 0;\r
+UINTN mBlockHeight = 0;\r
+\r
+//\r
+// GOP bitmap of the progress bar. Initialized on every new progress of 100%\r
+//\r
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mBlockBitmap;\r
+\r
+//\r
+// GOP bitmap of the progress bar backround. Initialized once.\r
+//\r
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mProgressBarBackground;\r
+\r
+//\r
+// Default mask used to detect the left, right , top, and bottom of logo. Only\r
+// green and blue pixels are used for logo detection.\r
+//\r
+const EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION mLogoDetectionColorMask = {\r
+ {\r
+ 0xFF, // Blue\r
+ 0xFF, // Green\r
+ 0x00, // Red\r
+ 0x00 // Reserved\r
+ }\r
+};\r
+\r
+//\r
+// Background color of progress bar. Grey.\r
+//\r
+const EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION mProgressBarBackgroundColor = {\r
+ {\r
+ 0x80, // Blue\r
+ 0x80, // Green\r
+ 0x80, // Red\r
+ 0x00 // Reserved\r
+ }\r
+};\r
+\r
+//\r
+// Default color of progress completion. White.\r
+//\r
+const EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION mProgressBarDefaultColor = {\r
+ {\r
+ 0xFF, // Blue\r
+ 0xFF, // Green\r
+ 0xFF, // Red\r
+ 0x00 // Reserved\r
+ }\r
+};\r
+\r
+//\r
+// Set to TRUE if a valid Graphics Output Protocol is found and the progress\r
+// bar fits under the boot logo using the current graphics mode.\r
+//\r
+BOOLEAN mGraphicsGood = FALSE;\r
+\r
+/*\r
+ Internal function used to find the bounds of the white logo (on black or\r
+ red background).\r
+\r
+ These bounds are then computed to find the block size, 0%, 100%, etc.\r
+\r
+*/\r
+VOID\r
+FindDim (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ INTN LogoX;\r
+ INTN LogoStartX;\r
+ INTN LogoEndX;\r
+ INTN LogoY;\r
+ INTN LogoStartY;\r
+ INTN LogoEndY;\r
+ UINTN OffsetX; // Logo screen coordinate\r
+ UINTN OffsetY; // Logo screen coordinate\r
+ UINTN Width; // Width of logo in pixels\r
+ UINTN Height; // Height of logo in pixels\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Logo;\r
+ EDKII_BOOT_LOGO2_PROTOCOL *BootLogo;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *Pixel;\r
+\r
+ Logo = NULL;\r
+ BootLogo = NULL;\r
+\r
+ //\r
+ // Return if a Graphics Output Protocol ha snot been found.\r
+ //\r
+ if (mGop == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "No GOP found. No progress bar support. \n"));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Get boot logo protocol so we know where on the screen to grab\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEdkiiBootLogo2ProtocolGuid,\r
+ NULL,\r
+ (VOID **)&BootLogo\r
+ );\r
+ if ((BootLogo == NULL) || (EFI_ERROR (Status))) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to locate gEdkiiBootLogo2ProtocolGuid. No Progress bar support. \n", Status));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Get logo location and size\r
+ //\r
+ Status = BootLogo->GetBootLogo (\r
+ BootLogo,\r
+ &Logo,\r
+ &OffsetX,\r
+ &OffsetY,\r
+ &Width,\r
+ &Height\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to Get Boot Logo Status = %r. No Progress bar support. \n", Status));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Within logo buffer find where the actual logo starts/ends\r
+ //\r
+ LogoEndX = 0;\r
+ LogoEndY = 0;\r
+\r
+ //\r
+ // Find left side of logo in logo coordinates\r
+ //\r
+ for (LogoX = 0, LogoStartX = Width; LogoX < LogoStartX; LogoX++) {\r
+ Pixel = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)(Logo + LogoX);\r
+ for (LogoY = 0; LogoY < (INTN)Height; LogoY++) {\r
+ if ((Pixel->Raw & mLogoDetectionColorMask.Raw) != 0x0) {\r
+ LogoStartX = LogoX;\r
+ //\r
+ // For loop searches from right side back to this column.\r
+ //\r
+ LogoEndX = LogoX;\r
+ DEBUG ((DEBUG_INFO, "StartX found at (%d, %d) Color is: 0x%X \n", LogoX, LogoY, Pixel->Raw));\r
+ break;\r
+ }\r
+ Pixel = Pixel + Width;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Find right side of logo\r
+ //\r
+ for (LogoX = Width - 1; LogoX >= LogoEndX; LogoX--) {\r
+ Pixel = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)(Logo + LogoX);\r
+ for (LogoY = 0; LogoY < (INTN)Height; LogoY++) {\r
+ if ((Pixel->Raw & mLogoDetectionColorMask.Raw) != 0x0) {\r
+ LogoEndX = LogoX;\r
+ DEBUG ((DEBUG_INFO, "EndX found at (%d, %d) Color is: 0x%X \n", LogoX, LogoY, Pixel->Raw));\r
+ break;\r
+ }\r
+ Pixel = Pixel + Width;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Compute mBlockWidth\r
+ //\r
+ mBlockWidth = ((LogoEndX - LogoStartX) + 99) / 100;\r
+\r
+ //\r
+ // Adjust mStartX based on block width so it is centered under logo\r
+ //\r
+ mStartX = LogoStartX + OffsetX - (((mBlockWidth * 100) - (LogoEndX - LogoStartX)) / 2);\r
+ DEBUG ((DEBUG_INFO, "mBlockWidth set to 0x%X\n", mBlockWidth));\r
+ DEBUG ((DEBUG_INFO, "mStartX set to 0x%X\n", mStartX));\r
+\r
+ //\r
+ // Find the top of the logo\r
+ //\r
+ for (LogoY = 0, LogoStartY = Height; LogoY < LogoStartY; LogoY++) {\r
+ Pixel = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)(Logo + (Width * LogoY));\r
+ for (LogoX = 0; LogoX < (INTN)Width; LogoX++) {\r
+ //not black or red\r
+ if ((Pixel->Raw & mLogoDetectionColorMask.Raw) != 0x0) {\r
+ LogoStartY = LogoY;\r
+ LogoEndY = LogoY; //for next loop will search from bottom side back to this row.\r
+ DEBUG ((DEBUG_INFO, "StartY found at (%d, %d) Color is: 0x%X \n", LogoX, LogoY, Pixel->Raw));\r
+ break;\r
+ }\r
+ Pixel++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Find the bottom of the logo\r
+ //\r
+ for (LogoY = Height - 1; LogoY >= LogoEndY; LogoY--) {\r
+ Pixel = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)(Logo + (Width * LogoY));\r
+ for (LogoX = 0; LogoX < (INTN)Width; LogoX++) {\r
+ if ((Pixel->Raw & mLogoDetectionColorMask.Raw) != 0x0) {\r
+ LogoEndY = LogoY;\r
+ DEBUG ((DEBUG_INFO, "EndY found at (%d, %d) Color is: 0x%X \n", LogoX, LogoY, Pixel->Raw));\r
+ break;\r
+ }\r
+ Pixel++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Compute bottom padding (distance between logo bottom and progress bar)\r
+ //\r
+ mStartY = (((LogoEndY - LogoStartY) * LOGO_BOTTOM_PADDING) / 100) + LogoEndY + OffsetY;\r
+\r
+ //\r
+ // Compute progress bar height\r
+ //\r
+ mBlockHeight = (((LogoEndY - LogoStartY) * PROGRESS_BLOCK_HEIGHT) / 100);\r
+\r
+ DEBUG ((DEBUG_INFO, "mBlockHeight set to 0x%X\n", mBlockHeight));\r
+\r
+ //\r
+ // Create progress bar background (one time init).\r
+ //\r
+ mProgressBarBackground = AllocatePool (mBlockWidth * 100 * mBlockHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ if (mProgressBarBackground == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to allocate progress bar background\n"));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Fill the progress bar with the background color\r
+ //\r
+ SetMem32 (\r
+ mProgressBarBackground,\r
+ (mBlockWidth * 100 * mBlockHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)),\r
+ mProgressBarBackgroundColor.Raw\r
+ );\r
+\r
+ //\r
+ // Allocate mBlockBitmap\r
+ //\r
+ mBlockBitmap = AllocatePool (mBlockWidth * mBlockHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ if (mBlockBitmap == NULL) {\r
+ FreePool (mProgressBarBackground);\r
+ DEBUG ((DEBUG_ERROR, "Failed to allocate block\n"));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Check screen width and height and make sure it fits.\r
+ //\r
+ if ((mBlockHeight > Height) || (mBlockWidth > Width) || (mBlockHeight < 1) || (mBlockWidth < 1)) {\r
+ DEBUG ((DEBUG_ERROR, "DisplayUpdateProgressLib - Progress - Failed to get valid width and height.\n"));\r
+ DEBUG ((DEBUG_ERROR, "DisplayUpdateProgressLib - Progress - mBlockHeight: 0x%X mBlockWidth: 0x%X.\n", mBlockHeight, mBlockWidth));\r
+ FreePool (mProgressBarBackground);\r
+ FreePool (mBlockBitmap);\r
+ return;\r
+ }\r
+\r
+ mGraphicsGood = TRUE;\r
+}\r
+\r
+/**\r
+ Function indicates the current completion progress of a firmware update.\r
+ Platform may override with its own specific function.\r
+\r
+ @param[in] Completion A value between 0 and 100 indicating the current\r
+ completion progress of a firmware update. This\r
+ value must the the same or higher than previous\r
+ calls to this service. The first call of 0 or a\r
+ value of 0 after reaching a value of 100 resets\r
+ the progress indicator to 0.\r
+ @param[in] Color Color of the progress indicator. Only used when\r
+ Completion is 0 to set the color of the progress\r
+ indicator. If Color is NULL, then the default color\r
+ is used.\r
+\r
+ @retval EFI_SUCCESS Progress displayed successfully.\r
+ @retval EFI_INVALID_PARAMETER Completion is not in range 0..100.\r
+ @retval EFI_INVALID_PARAMETER Completion is less than Completion value from\r
+ a previous call to this service.\r
+ @retval EFI_NOT_READY The device used to indicate progress is not\r
+ available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisplayUpdateProgress (\r
+ IN UINTN Completion,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *Color OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN PreX;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Check range\r
+ //\r
+ if (Completion > 100) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check to see if this Completion percentage has already been displayed\r
+ //\r
+ if (Completion == mPreviousProgress) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Find Graphics Output Protocol if not already set. 1 time.\r
+ //\r
+ if (mGop == NULL) {\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID**)&mGop\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&mGop);\r
+ if (EFI_ERROR (Status)) {\r
+ mGop = NULL;\r
+ DEBUG ((DEBUG_ERROR, "Show Progress Function could not locate GOP. Status = %r\n", Status));\r
+ return EFI_NOT_READY;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Run once\r
+ //\r
+ FindDim ();\r
+ }\r
+\r
+ //\r
+ // Make sure a valid start, end, and size info are available (find the Logo)\r
+ //\r
+ if (!mGraphicsGood) {\r
+ DEBUG ((DEBUG_INFO, "Graphics Not Good. Not doing any onscreen visual display\n"));\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ //\r
+ // Do special init on first call of each progress session\r
+ //\r
+ if (mPreviousProgress == 100) {\r
+ //\r
+ // Draw progress bar background\r
+ //\r
+ mGop->Blt (\r
+ mGop,\r
+ mProgressBarBackground,\r
+ EfiBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ mStartX,\r
+ mStartY,\r
+ (mBlockWidth * 100),\r
+ mBlockHeight,\r
+ 0\r
+ );\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "Color is 0x%X\n",\r
+ (Color == NULL) ? mProgressBarDefaultColor.Raw : Color->Raw\r
+ ));\r
+\r
+ //\r
+ // Update block bitmap with correct color\r
+ //\r
+ SetMem32 (\r
+ mBlockBitmap,\r
+ (mBlockWidth * mBlockHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)),\r
+ (Color == NULL) ? mProgressBarDefaultColor.Raw : Color->Raw\r
+ );\r
+\r
+ //\r
+ // Clear previous\r
+ //\r
+ mPreviousProgress = 0;\r
+ }\r
+\r
+ //\r
+ // Can not update progress bar if Completion is less than previous\r
+ //\r
+ if (Completion < mPreviousProgress) {\r
+ DEBUG ((DEBUG_WARN, "WARNING: Completion (%d) should not be lesss than Previous (%d)!!!\n", Completion, mPreviousProgress));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PreX = ((mPreviousProgress * mBlockWidth) + mStartX);\r
+ for (Index = 0; Index < (Completion - mPreviousProgress); Index++) {\r
+ //\r
+ // Show progress by coloring new area\r
+ //\r
+ mGop->Blt (\r
+ mGop,\r
+ mBlockBitmap,\r
+ EfiBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ PreX,\r
+ mStartY,\r
+ mBlockWidth,\r
+ mBlockHeight,\r
+ 0\r
+ );\r
+ PreX += mBlockWidth;\r
+ }\r
+\r
+ mPreviousProgress = Completion;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Provides services to display completion progress of a firmware update on a\r
+ text console.\r
+\r
+ Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+ 1. Redistributions of source code must retain the above copyright notice,\r
+ this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ this list of conditions and the following disclaimer in the documentation\r
+ and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+//\r
+// Control Style. Set to 100 so it is reset on first call.\r
+//\r
+UINTN mPreviousProgress = 100;\r
+\r
+//\r
+// Text foreground color of progress bar\r
+//\r
+UINTN mProgressBarForegroundColor;\r
+\r
+/**\r
+ Function indicates the current completion progress of a firmware update.\r
+ Platform may override with its own specific function.\r
+\r
+ @param[in] Completion A value between 0 and 100 indicating the current\r
+ completion progress of a firmware update. This\r
+ value must the the same or higher than previous\r
+ calls to this service. The first call of 0 or a\r
+ value of 0 after reaching a value of 100 resets\r
+ the progress indicator to 0.\r
+ @param[in] Color Color of the progress indicator. Only used when\r
+ Completion is 0 to set the color of the progress\r
+ indicator. If Color is NULL, then the default color\r
+ is used.\r
+\r
+ @retval EFI_SUCCESS Progress displayed successfully.\r
+ @retval EFI_INVALID_PARAMETER Completion is not in range 0..100.\r
+ @retval EFI_INVALID_PARAMETER Completion is less than Completion value from\r
+ a previous call to this service.\r
+ @retval EFI_NOT_READY The device used to indicate progress is not\r
+ available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisplayUpdateProgress (\r
+ IN UINTN Completion,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *Color OPTIONAL\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN CurrentAttribute;\r
+\r
+ //\r
+ // Check range\r
+ //\r
+ if (Completion > 100) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check to see if this Completion percentage has already been displayed\r
+ //\r
+ if (Completion == mPreviousProgress) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Do special init on first call of each progress session\r
+ //\r
+ if (mPreviousProgress == 100) {\r
+ Print (L"\n");\r
+\r
+ //\r
+ // Convert pixel color to text foreground color\r
+ //\r
+ if (Color == NULL) {\r
+ mProgressBarForegroundColor = EFI_WHITE;\r
+ } else {\r
+ mProgressBarForegroundColor = EFI_BLACK;\r
+ if (Color->Pixel.Blue >= 0x40) {\r
+ mProgressBarForegroundColor |= EFI_BLUE;\r
+ }\r
+ if (Color->Pixel.Green >= 0x40) {\r
+ mProgressBarForegroundColor |= EFI_GREEN;\r
+ }\r
+ if (Color->Pixel.Red >= 0x40) {\r
+ mProgressBarForegroundColor |= EFI_RED;\r
+ }\r
+ if (Color->Pixel.Blue >= 0xC0 || Color->Pixel.Green >= 0xC0 || Color->Pixel.Red >= 0xC0) {\r
+ mProgressBarForegroundColor |= EFI_BRIGHT;\r
+ }\r
+ if (mProgressBarForegroundColor == EFI_BLACK) {\r
+ mProgressBarForegroundColor = EFI_WHITE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Clear previous\r
+ //\r
+ mPreviousProgress = 0;\r
+ }\r
+\r
+ //\r
+ // Can not update progress bar if Completion is less than previous\r
+ //\r
+ if (Completion < mPreviousProgress) {\r
+ DEBUG ((DEBUG_WARN, "WARNING: Completion (%d) should not be lesss than Previous (%d)!!!\n", Completion, mPreviousProgress));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Save current text color\r
+ //\r
+ CurrentAttribute = (UINTN)gST->ConOut->Mode->Attribute;\r
+\r
+ //\r
+ // Print progress percentage\r
+ //\r
+ Print (L"\rUpdate Progress - %3d%% ", Completion);\r
+\r
+ //\r
+ // Set progress bar color\r
+ //\r
+ gST->ConOut->SetAttribute (\r
+ gST->ConOut,\r
+ EFI_TEXT_ATTR (mProgressBarForegroundColor, EFI_BLACK)\r
+ );\r
+\r
+ //\r
+ // Print completed portion of progress bar\r
+ //\r
+ for (Index = 0; Index < Completion / 2; Index++) {\r
+ Print (L"%c", BLOCKELEMENT_FULL_BLOCK);\r
+ }\r
+\r
+ //\r
+ // Restore text color\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+\r
+ //\r
+ // Print remaining portion of progress bar\r
+ //\r
+ for (; Index < 50; Index++) {\r
+ Print (L"%c", BLOCKELEMENT_LIGHT_SHADE);\r
+ }\r
+\r
+ mPreviousProgress = Completion;\r
+\r
+ return EFI_SUCCESS;\r
+}\r