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. 

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7062 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
qwang12 2008-12-17 06:41:02 +00:00
parent 878670eaa6
commit a235abd2c9
6 changed files with 478 additions and 2 deletions

View File

@ -37,6 +37,7 @@
#
[Sources.common]
SetupBrowser.c
HiiHandle.c
HiiHandle.h
ConfigAccess.c
@ -57,8 +58,7 @@
HiiDatabase.c
Utility.c
Utility.h
SetupBrowser.c
Strings.uni
[Packages]
@ -79,6 +79,8 @@
IfrSupportLib
ExtendedIfrSupportLib
PrintLib
UefiLib
PcdLib
[Protocols]
gEfiHiiImageProtocolGuid
@ -92,6 +94,9 @@
gEfiHiiCompatibilityProtocolGuid
gEfiFormBrowserCompatibilityProtocolGuid
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault
[Depex]
gEfiHiiDatabaseProtocolGuid AND
gEfiHiiStringProtocolGuid AND

View File

@ -218,6 +218,8 @@ InitializeHiiDatabase (
);
ASSERT_EFI_ERROR (Status);
InitSetBrowserStrings ();
mBrowserThunkPrivateDataTemplate.ThunkPrivate = Private;
Status = gBS->InstallProtocolInterface (
&mBrowserThunkPrivateDataTemplate.Handle,

View File

@ -34,6 +34,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/HiiDatabase.h>
#include <Protocol/HiiConfigRouting.h>
#include <Protocol/HiiConfigAccess.h>
#include <Protocol/UgaDraw.h>
#include <Library/BaseLib.h>
@ -45,9 +46,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/HiiLib.h>
#include <Library/ExtendedHiiLib.h>
#include <Library/UefiLib.h>
#include <Library/IfrSupportLib.h>
#include <Library/ExtendedIfrSupportLib.h>
#include <Library/PcdLib.h>
#include <MdeModuleHii.h>
@ -444,6 +447,17 @@ FwUpdateDataToUefiUpdateData (
)
;
/**
Initialize string packages in HII database.
**/
VOID
InitSetBrowserStrings (
VOID
)
;
#include "Utility.h"
#include "ConfigAccess.h"

View File

@ -14,6 +14,400 @@ 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.
@ -74,6 +468,23 @@ ThunkSendForm (
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;
}
@ -143,3 +554,22 @@ ThunkCreatePopUp (
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);
}

View File

@ -0,0 +1,25 @@
/**@file
This file contains macros to be included by SetupBrowser.c.
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.
**/
#ifndef _HIITHUNK_SETUPBROWSER_H_
#define _HIITHUNK_SETUPBROWSER_H_
//
// In order to follow UEFI spec to do auto booting after a time-out, the GUID of Formset of Frontpage must match this value.
//
#define FRAMEWORK_BDS_FRONTPAGE_FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }}
#define ONE_SECOND 10000000
#endif