summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c')
-rw-r--r--EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c575
1 files changed, 575 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c
new file mode 100644
index 0000000000..7f42842755
--- /dev/null
+++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c
@@ -0,0 +1,575 @@
+/**@file
+Framework to UEFI 2.1 Setup Browser Thunk. The file consume EFI_FORM_BROWSER2_PROTOCOL
+to produce a EFI_FORM_BROWSER_PROTOCOL.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HiiDatabase.h"
+#include "SetupBrowser.h"
+
+EFI_GUID gFrameworkBdsFrontPageFormsetGuid = FRAMEWORK_BDS_FRONTPAGE_FORMSET_GUID;
+EFI_HII_HANDLE gStringPackHandle = NULL;
+BOOLEAN mFrontPageDisplayed = FALSE;
+//
+// 106F3545-B788-4cb5-9D2A-CE0CDB208DF5
+//
+EFI_GUID gEfiHiiThunkProducerGuid = { 0x106f3545, 0xb788, 0x4cb5, { 0x9d, 0x2a, 0xce, 0xc, 0xdb, 0x20, 0x8d, 0xf5 } };
+
+
+/**
+ Get string by string id from HII Interface
+
+
+ @param Id String ID.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+{
+ CHAR16 *String;
+
+ String = NULL;
+ HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);
+
+ return String;
+}
+/**
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar
+
+**/
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINTN BlockHeight;
+ UINTN BlockWidth;
+ UINTN BlockNum;
+ UINTN PosX;
+ UINTN PosY;
+ UINTN Index;
+
+ if (Progress > 100) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UgaDraw = NULL;
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SizeOfX = 0;
+ SizeOfY = 0;
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ Status = UgaDraw->GetMode (
+ UgaDraw,
+ &SizeOfX,
+ &SizeOfY,
+ &ColorDepth,
+ &RefreshRate
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ BlockWidth = SizeOfX / 100;
+ BlockHeight = SizeOfY / 50;
+
+ BlockNum = Progress;
+
+ PosX = 0;
+ PosY = SizeOfY * 48 / 50;
+
+ if (BlockNum == 0) {
+ //
+ // Clear progress area
+ //
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &Color,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+ //
+ // Show progress by drawing blocks
+ //
+ for (Index = PreviousValue; Index < BlockNum; Index++) {
+ PosX = Index * BlockWidth;
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &ProgressColor,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+
+ PrintXY (
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ &TitleForeground,
+ &TitleBackground,
+ Title
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function waits for a given event to fire, or for an optional timeout to expire.
+
+
+ @param Event The event to wait for
+
+ @param Timeout An optional timeout value in 100 ns units.
+
+ @retval EFI_SUCCESS Event fired before Timeout expired.
+ @retval EFI_TIME_OUT Timout expired before Event fired..
+
+**/
+EFI_STATUS
+WaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[2];
+
+ if (Timeout != 0) {
+ //
+ // Create a timer event
+ //
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ gBS->CloseEvent (TimerEvent);
+
+ //
+ // If the timer expired, change the return to timed out
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ }
+ }
+ } else {
+ //
+ // No timeout... just wait on the event
+ //
+ Status = gBS->WaitForEvent (1, &Event, &Index);
+ ASSERT (!EFI_ERROR (Status));
+ ASSERT (Index == 0);
+ }
+
+ return Status;
+}
+
+/**
+ Function show progress bar to wait for user input.
+
+
+ @param TimeoutDefault - The fault time out value before the system
+ continue to boot.
+
+ @retval EFI_SUCCESS User pressed some key except "Enter"
+ @retval EFI_TIME_OUT Timout expired or user press "Enter"
+
+**/
+EFI_STATUS
+ShowProgress (
+ IN UINT16 TimeoutDefault
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ EFI_INPUT_KEY Key;
+ UINT16 TimeoutRemain;
+
+ if (TimeoutDefault == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ //
+ // Clear the progress status bar first
+ //
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
+ }
+
+ TimeoutRemain = TimeoutDefault;
+ while (TimeoutRemain != 0) {
+ DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
+
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
+ if (Status != EFI_TIMEOUT) {
+ break;
+ }
+ TimeoutRemain--;
+
+ //
+ // Show progress
+ //
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
+ 0
+ );
+ }
+ }
+ gBS->FreePool (TmpStr);
+
+ //
+ // Timeout expired
+ //
+ if (TimeoutRemain == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ //
+ // User pressed some key
+ //
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ //
+ // User pressed enter, equivalent to select "continue"
+ //
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the default value for system Timeout variable.
+
+ @return Timeout value.
+
+**/
+UINT16
+EFIAPI
+GetTimeout (
+ VOID
+ )
+{
+ UINT16 Timeout;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ //
+ // Return Timeout variable or 0xffff if no valid
+ // Timeout variable exists.
+ //
+ Size = sizeof (UINT16);
+ Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
+ if (EFI_ERROR (Status)) {
+ //
+ // According to UEFI 2.0 spec, it should treat the Timeout value as 0xffff
+ // (default value PcdPlatformBootTimeOutDefault) when L"Timeout" variable is not present.
+ // To make the current EFI Automatic-Test activity possible, platform can choose other value
+ // for automatic boot when the variable is not present.
+ //
+ Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);
+ }
+
+ return Timeout;
+}
+
+
+/**
+ This is the Framework Setup Browser interface which displays a FormSet.
+
+ @param This The EFI_FORM_BROWSER_PROTOCOL context.
+ @param UseDatabase TRUE if the FormSet is from HII database. The Thunk implementation
+ only support UseDatabase is TRUE.
+ @param Handle The Handle buffer.
+ @param HandleCount The number of Handle in the Handle Buffer. It must be 1 for this implementation.
+ @param Packet The pointer to data buffer containing IFR and String package. Not supported.
+ @param CallbackHandle Not supported.
+ @param NvMapOverride The buffer is used only when there is no NV variable to define the
+ current settings and the caller needs to provide to the browser the
+ current settings for the the "fake" NV variable. If used, no saving of
+ an NV variable is possbile. This parameter is also ignored if Handle is NULL.
+
+ @retval EFI_SUCCESS If the Formset is displayed correctly.
+ @retval EFI_UNSUPPORTED If UseDatabase is FALSE or HandleCount is not 1.
+ @retval EFI_INVALID_PARAMETER If the *Handle passed in is not found in the database.
+**/
+
+EFI_STATUS
+EFIAPI
+ThunkSendForm (
+ IN EFI_FORM_BROWSER_PROTOCOL *This,
+ IN BOOLEAN UseDatabase,
+ IN FRAMEWORK_EFI_HII_HANDLE *Handle,
+ IN UINTN HandleCount,
+ IN FRAMEWORK_EFI_IFR_PACKET *Packet, OPTIONAL
+ IN EFI_HANDLE CallbackHandle, OPTIONAL
+ IN UINT8 *NvMapOverride, OPTIONAL
+ IN FRAMEWORK_EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT BOOLEAN *ResetRequired OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ HII_THUNK_CONTEXT *ThunkContext;
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_FORMBROWSER_THUNK_PRIVATE_DATA *BrowserPrivate;
+
+ if (!UseDatabase) {
+ //
+ // ThunkSendForm only support displays forms registered into the HII database.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (HandleCount != 1 ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ BrowserPrivate = EFI_FORMBROWSER_THUNK_PRIVATE_DATA_FROM_THIS (This);
+ Private = BrowserPrivate->ThunkPrivate;
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, *Handle);
+ if (ThunkContext == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Following UEFI spec to do auto booting after a time-out. This feature is implemented
+ // in Framework Setup Browser and moved to MdeModulePkg/Universal/BdsDxe. The auto booting is
+ // moved here in HII Thunk module.
+ //
+ if (CompareGuid (&gFrameworkBdsFrontPageFormsetGuid, &ThunkContext->FormSet->Guid) && !mFrontPageDisplayed) {
+ //
+ // Send form is called before entering the
+ //
+ mFrontPageDisplayed = TRUE;
+ Status = ShowProgress (GetTimeout ());
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (NvMapOverride != NULL) {
+ ThunkContext->NvMapOverride = NvMapOverride;
+ }
+
+ Status = mFormBrowser2Protocol->SendForm (
+ mFormBrowser2Protocol,
+ &ThunkContext->UefiHiiHandle,
+ 1,
+ NULL,
+ 0,
+ (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions,
+ &ActionRequest
+ );
+
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ *ResetRequired = TRUE;
+ }
+
+ return Status;
+}
+
+/**
+
+ Rountine used to display a generic dialog interface and return
+ the Key or Input from user input.
+
+ @param NumberOfLines The number of lines for the dialog box.
+ @param HotKey Defines if a single character is parsed (TRUE) and returned in KeyValue
+ or if a string is returned in StringBuffer.
+ @param MaximumStringSize The maximum size in bytes of a typed-in string.
+ @param StringBuffer On return contains the typed-in string if HotKey
+ is FALSE.
+ @param KeyValue The EFI_INPUT_KEY value returned if HotKey is TRUE.
+ @param String The pointer to the first string in the list of strings
+ that comprise the dialog box.
+ @param ... A series of NumberOfLines text strings that will be used
+ to construct the dialog box.
+ @retval EFI_SUCCESS The dialog is created successfully and user interaction was received.
+ @retval EFI_DEVICE_ERROR The user typed in an ESC.
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid.(StringBuffer == NULL && HotKey == FALSE).
+**/
+EFI_STATUS
+EFIAPI
+ThunkCreatePopUp (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+
+ if (HotKey != TRUE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ VA_START (Marker, String);
+
+ Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, String, Marker);
+
+ VA_END (Marker);
+
+ return Status;
+}
+
+/**
+
+ Initialize string packages in HII database.
+
+**/
+VOID
+InitSetBrowserStrings (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initialize strings to HII database
+ //
+ Status = HiiLibAddPackages (1, &gEfiHiiThunkProducerGuid, NULL, &gStringPackHandle, STRING_ARRAY_NAME);
+ ASSERT_EFI_ERROR (Status);
+
+}