**/\r
\r
#include "HiiDatabase.h"\r
+#include "SetupBrowser.h"\r
+\r
+EFI_GUID gFrameworkBdsFrontPageFormsetGuid = FRAMEWORK_BDS_FRONTPAGE_FORMSET_GUID;\r
+EFI_HII_HANDLE gStringPackHandle = NULL;\r
+BOOLEAN mFrontPageDisplayed = FALSE;\r
+//\r
+// 106F3545-B788-4cb5-9D2A-CE0CDB208DF5\r
+//\r
+EFI_GUID gEfiHiiThunkProducerGuid = { 0x106f3545, 0xb788, 0x4cb5, { 0x9d, 0x2a, 0xce, 0xc, 0xdb, 0x20, 0x8d, 0xf5 } }; \r
+\r
+\r
+/**\r
+ Get string by string id from HII Interface\r
+\r
+\r
+ @param Id String ID.\r
+\r
+ @retval CHAR16 * String from ID.\r
+ @retval NULL If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+GetStringById (\r
+ IN EFI_STRING_ID Id\r
+ )\r
+{\r
+ CHAR16 *String;\r
+\r
+ String = NULL;\r
+ HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);\r
+\r
+ return String;\r
+}\r
+/**\r
+\r
+ Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+\r
+ @param TitleForeground Foreground color for Title.\r
+ @param TitleBackground Background color for Title.\r
+ @param Title Title above progress bar.\r
+ @param ProgressColor Progress bar color.\r
+ @param Progress Progress (0-100)\r
+ @param PreviousValue The previous value of the progress.\r
+\r
+ @retval EFI_STATUS Success update the progress bar\r
+\r
+**/\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ IN CHAR16 *Title,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ IN UINTN Progress,\r
+ IN UINTN PreviousValue\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ UINT32 SizeOfX;\r
+ UINT32 SizeOfY;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINTN BlockHeight;\r
+ UINTN BlockWidth;\r
+ UINTN BlockNum;\r
+ UINTN PosX;\r
+ UINTN PosY;\r
+ UINTN Index;\r
+\r
+ if (Progress > 100) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UgaDraw = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID **) &GraphicsOutput\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ GraphicsOutput = NULL;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ (VOID **) &UgaDraw\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SizeOfX = 0;\r
+ SizeOfY = 0;\r
+ if (GraphicsOutput != NULL) {\r
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+ } else {\r
+ Status = UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &SizeOfX,\r
+ &SizeOfY,\r
+ &ColorDepth,\r
+ &RefreshRate\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ BlockWidth = SizeOfX / 100;\r
+ BlockHeight = SizeOfY / 50;\r
+\r
+ BlockNum = Progress;\r
+\r
+ PosX = 0;\r
+ PosY = SizeOfY * 48 / 50;\r
+\r
+ if (BlockNum == 0) {\r
+ //\r
+ // Clear progress area\r
+ //\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &Color,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - EFI_GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &Color,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - EFI_GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+ //\r
+ // Show progress by drawing blocks\r
+ //\r
+ for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+ PosX = Index * BlockWidth;\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &ProgressColor,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &ProgressColor,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+\r
+ PrintXY (\r
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
+ PosY - EFI_GLYPH_HEIGHT - 1,\r
+ &TitleForeground,\r
+ &TitleBackground,\r
+ Title\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Function waits for a given event to fire, or for an optional timeout to expire.\r
+\r
+\r
+ @param Event The event to wait for\r
+ \r
+ @param Timeout An optional timeout value in 100 ns units.\r
+\r
+ @retval EFI_SUCCESS Event fired before Timeout expired.\r
+ @retval EFI_TIME_OUT Timout expired before Event fired..\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForSingleEvent (\r
+ IN EFI_EVENT Event,\r
+ IN UINT64 Timeout OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_EVENT TimerEvent;\r
+ EFI_EVENT WaitList[2];\r
+\r
+ if (Timeout != 0) {\r
+ //\r
+ // Create a timer event\r
+ //\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set the timer event\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ Timeout\r
+ );\r
+\r
+ //\r
+ // Wait for the original event or the timer\r
+ //\r
+ WaitList[0] = Event;\r
+ WaitList[1] = TimerEvent;\r
+ Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+ gBS->CloseEvent (TimerEvent);\r
+\r
+ //\r
+ // If the timer expired, change the return to timed out\r
+ //\r
+ if (!EFI_ERROR (Status) && Index == 1) {\r
+ Status = EFI_TIMEOUT;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // No timeout... just wait on the event\r
+ //\r
+ Status = gBS->WaitForEvent (1, &Event, &Index);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ ASSERT (Index == 0);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Function show progress bar to wait for user input.\r
+\r
+\r
+ @param TimeoutDefault - The fault time out value before the system\r
+ continue to boot.\r
+\r
+ @retval EFI_SUCCESS User pressed some key except "Enter"\r
+ @retval EFI_TIME_OUT Timout expired or user press "Enter"\r
+\r
+**/\r
+EFI_STATUS\r
+ShowProgress (\r
+ IN UINT16 TimeoutDefault\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *TmpStr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ EFI_INPUT_KEY Key;\r
+ UINT16 TimeoutRemain;\r
+\r
+ if (TimeoutDefault == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));\r
+ \r
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+ //\r
+ // Clear the progress status bar first\r
+ //\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);\r
+ }\r
+\r
+ TimeoutRemain = TimeoutDefault;\r
+ while (TimeoutRemain != 0) {\r
+ DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));\r
+ \r
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);\r
+ if (Status != EFI_TIMEOUT) {\r
+ break;\r
+ }\r
+ TimeoutRemain--;\r
+\r
+ //\r
+ // Show progress\r
+ //\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),\r
+ 0\r
+ );\r
+ }\r
+ }\r
+ gBS->FreePool (TmpStr);\r
+\r
+ //\r
+ // Timeout expired\r
+ //\r
+ if (TimeoutRemain == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ //\r
+ // User pressed some key\r
+ //\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ //\r
+ // User pressed enter, equivalent to select "continue"\r
+ //\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Return the default value for system Timeout variable.\r
+\r
+ @return Timeout value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+GetTimeout (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 Timeout;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Return Timeout variable or 0xffff if no valid\r
+ // Timeout variable exists.\r
+ //\r
+ Size = sizeof (UINT16);\r
+ Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // According to UEFI 2.0 spec, it should treat the Timeout value as 0xffff\r
+ // (default value PcdPlatformBootTimeOutDefault) when L"Timeout" variable is not present.\r
+ // To make the current EFI Automatic-Test activity possible, platform can choose other value\r
+ // for automatic boot when the variable is not present.\r
+ //\r
+ Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);\r
+ }\r
+\r
+ return Timeout;\r
+}\r
+\r
\r
/**\r
This is the Framework Setup Browser interface which displays a FormSet.\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ //\r
+ // Following UEFI spec to do auto booting after a time-out. This feature is implemented \r
+ // in Framework Setup Browser and moved to MdeModulePkg/Universal/BdsDxe. The auto booting is\r
+ // moved here in HII Thunk module. \r
+ //\r
+ if (CompareGuid (&gFrameworkBdsFrontPageFormsetGuid, &ThunkContext->FormSet->Guid) && !mFrontPageDisplayed) {\r
+ //\r
+ // Send form is called before entering the \r
+ //\r
+ mFrontPageDisplayed = TRUE;\r
+ Status = ShowProgress (GetTimeout ());\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ \r
if (NvMapOverride != NULL) {\r
ThunkContext->NvMapOverride = NvMapOverride;\r
}\r
return Status;\r
}\r
\r
+/** \r
+\r
+ Initialize string packages in HII database.\r
+\r
+**/\r
+VOID\r
+InitSetBrowserStrings (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ \r
+ //\r
+ // Initialize strings to HII database\r
+ //\r
+ Status = HiiLibAddPackages (1, &gEfiHiiThunkProducerGuid, NULL, &gStringPackHandle, STRING_ARRAY_NAME);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+}\r