EdkGenericPlatformBdsLib added
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2368 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -0,0 +1,497 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, 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.
|
||||
|
||||
Module Name:
|
||||
|
||||
DeviceManager.c
|
||||
|
||||
Abstract:
|
||||
|
||||
The platform device manager reference implement
|
||||
|
||||
--*/
|
||||
#include "DeviceManager.h"
|
||||
|
||||
STATIC UINT16 mTokenCount;
|
||||
EFI_FRONTPAGE_CALLBACK_INFO FPCallbackInfo;
|
||||
extern UINTN gCallbackKey;
|
||||
extern EFI_FORM_BROWSER_PROTOCOL *gBrowser;
|
||||
extern EFI_GUID gBdsStringPackGuid;
|
||||
extern BOOLEAN gConnectAllHappened;
|
||||
|
||||
STRING_REF gStringTokenTable[] = {
|
||||
STR_VIDEO_DEVICE,
|
||||
STR_NETWORK_DEVICE,
|
||||
STR_INPUT_DEVICE,
|
||||
STR_ON_BOARD_DEVICE,
|
||||
STR_OTHER_DEVICE,
|
||||
STR_EMPTY_STRING,
|
||||
0xFFFF
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DeviceManagerCallbackRoutine (
|
||||
IN EFI_FORM_CALLBACK_PROTOCOL *This,
|
||||
IN UINT16 KeyValue,
|
||||
IN EFI_IFR_DATA_ARRAY *DataArray,
|
||||
OUT EFI_HII_CALLBACK_PACKET **Packet
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This is the function that is called to provide results data to the driver. This data
|
||||
consists of a unique key which is used to identify what data is either being passed back
|
||||
or being asked for.
|
||||
|
||||
Arguments:
|
||||
|
||||
KeyValue - A unique value which is sent to the original exporting driver so that it
|
||||
can identify the type of data to expect. The format of the data tends to
|
||||
vary based on the op-code that geerated the callback.
|
||||
|
||||
Data - A pointer to the data being sent to the original exporting driver.
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// The KeyValue corresponds in this case to the handle which was requested to be displayed
|
||||
//
|
||||
EFI_FRONTPAGE_CALLBACK_INFO *CallbackInfo;
|
||||
|
||||
CallbackInfo = EFI_FP_CALLBACK_DATA_FROM_THIS (This);
|
||||
switch (KeyValue) {
|
||||
case 0x2000:
|
||||
CallbackInfo->Data.VideoBIOS = (UINT8) (UINTN) (((EFI_IFR_DATA_ENTRY *)(DataArray + 1))->Data);
|
||||
gRT->SetVariable (
|
||||
L"VBIOS",
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||
sizeof (UINT8),
|
||||
&CallbackInfo->Data.VideoBIOS
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gCallbackKey = KeyValue;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
InitializeDeviceManager (
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize HII information for the FrontPage
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HII_PACKAGES *PackageList;
|
||||
EFI_HII_UPDATE_DATA *UpdateData;
|
||||
|
||||
//
|
||||
// Allocate space for creation of UpdateData Buffer
|
||||
//
|
||||
UpdateData = AllocateZeroPool (0x1000);
|
||||
ASSERT (UpdateData != NULL);
|
||||
|
||||
PackageList = PreparePackages (1, &gBdsStringPackGuid, DeviceManagerVfrBin);
|
||||
Status = Hii->NewPack (Hii, PackageList, &FPCallbackInfo.DevMgrHiiHandle);
|
||||
gBS->FreePool (PackageList);
|
||||
|
||||
//
|
||||
// This example does not implement worker functions for the NV accessor functions. Only a callback evaluator
|
||||
//
|
||||
FPCallbackInfo.Signature = EFI_FP_CALLBACK_DATA_SIGNATURE;
|
||||
FPCallbackInfo.DevMgrCallback.NvRead = NULL;
|
||||
FPCallbackInfo.DevMgrCallback.NvWrite = NULL;
|
||||
FPCallbackInfo.DevMgrCallback.Callback = DeviceManagerCallbackRoutine;
|
||||
|
||||
//
|
||||
// Install protocol interface
|
||||
//
|
||||
FPCallbackInfo.CallbackHandle = NULL;
|
||||
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&FPCallbackInfo.CallbackHandle,
|
||||
&gEfiFormCallbackProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&FPCallbackInfo.DevMgrCallback
|
||||
);
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Flag update pending in FormSet
|
||||
//
|
||||
UpdateData->FormSetUpdate = TRUE;
|
||||
//
|
||||
// Register CallbackHandle data for FormSet
|
||||
//
|
||||
UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FPCallbackInfo.CallbackHandle;
|
||||
//
|
||||
// Simply registering the callback handle
|
||||
//
|
||||
Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);
|
||||
|
||||
gBS->FreePool (UpdateData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
CallDeviceManager (
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Call the browser and display the device manager
|
||||
|
||||
Arguments:
|
||||
|
||||
None
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Operation is successful.
|
||||
EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BufferSize;
|
||||
UINTN Count;
|
||||
EFI_HII_HANDLE Index;
|
||||
UINT8 *Buffer;
|
||||
EFI_IFR_FORM_SET *FormSetData;
|
||||
CHAR16 *String;
|
||||
UINTN StringLength;
|
||||
EFI_HII_UPDATE_DATA *UpdateData;
|
||||
STRING_REF Token;
|
||||
STRING_REF TokenHelp;
|
||||
IFR_OPTION *IfrOptionList;
|
||||
UINT8 *VideoOption;
|
||||
UINTN VideoOptionSize;
|
||||
EFI_HII_HANDLE *HiiHandles;
|
||||
UINT16 HandleBufferLength;
|
||||
BOOLEAN BootDeviceMngrMenuResetRequired;
|
||||
|
||||
IfrOptionList = NULL;
|
||||
VideoOption = NULL;
|
||||
HiiHandles = NULL;
|
||||
HandleBufferLength = 0;
|
||||
|
||||
//
|
||||
// Connect all prior to entering the platform setup menu.
|
||||
//
|
||||
if (!gConnectAllHappened) {
|
||||
BdsLibConnectAllDriversToAllControllers ();
|
||||
gConnectAllHappened = TRUE;
|
||||
}
|
||||
//
|
||||
// Allocate space for creation of UpdateData Buffer
|
||||
//
|
||||
UpdateData = AllocateZeroPool (0x1000);
|
||||
ASSERT (UpdateData != NULL);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Buffer = NULL;
|
||||
FormSetData = NULL;
|
||||
gCallbackKey = 0;
|
||||
if (mTokenCount == 0) {
|
||||
Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &mTokenCount, L" ");
|
||||
}
|
||||
|
||||
Token = mTokenCount;
|
||||
TokenHelp = (UINT16) (Token + 1);
|
||||
|
||||
//
|
||||
// Reset the menu
|
||||
//
|
||||
for (Index = 0, Count = 1; Count < 0x10000; Count <<= 1, Index++) {
|
||||
//
|
||||
// We will strip off all previous menu entries
|
||||
//
|
||||
UpdateData->DataCount = 0xFF;
|
||||
|
||||
//
|
||||
// Erase entries on this label
|
||||
//
|
||||
Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, FALSE, UpdateData);
|
||||
|
||||
//
|
||||
// Did we reach the end of the Token Table?
|
||||
//
|
||||
if (gStringTokenTable[Index] == 0xFFFF) {
|
||||
break;
|
||||
}
|
||||
|
||||
CreateSubTitleOpCode (gStringTokenTable[Index], &UpdateData->Data);
|
||||
//
|
||||
// Add a single menu item - in this case a subtitle for the device type
|
||||
//
|
||||
UpdateData->DataCount = 1;
|
||||
|
||||
//
|
||||
// Add default title for this label
|
||||
//
|
||||
Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);
|
||||
}
|
||||
//
|
||||
// Add a space and an exit string. Remember since we add things at the label and push other things beyond the
|
||||
// label down, we add this in reverse order
|
||||
//
|
||||
CreateSubTitleOpCode (STRING_TOKEN (STR_EXIT_STRING), &UpdateData->Data);
|
||||
Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);
|
||||
CreateSubTitleOpCode (STR_EMPTY_STRING, &UpdateData->Data);
|
||||
Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);
|
||||
|
||||
//
|
||||
// Get all the Hii handles
|
||||
//
|
||||
Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandles);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
for (Index = 1, BufferSize = 0; Index < HandleBufferLength; Index++) {
|
||||
//
|
||||
// Am not initializing Buffer since the first thing checked is the size
|
||||
// this way I can get the real buffersize in the smallest code size
|
||||
//
|
||||
Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);
|
||||
|
||||
if (Status != EFI_NOT_FOUND) {
|
||||
//
|
||||
// BufferSize should have the real size of the forms now
|
||||
//
|
||||
Buffer = AllocateZeroPool (BufferSize);
|
||||
ASSERT (Buffer != NULL);
|
||||
|
||||
//
|
||||
// Am not initializing Buffer since the first thing checked is the size
|
||||
// this way I can get the real buffersize in the smallest code size
|
||||
//
|
||||
Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);
|
||||
|
||||
//
|
||||
// Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data.
|
||||
//
|
||||
FormSetData = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACK_HEADER));
|
||||
|
||||
//
|
||||
// If this formset belongs in the device manager, add it to the menu
|
||||
//
|
||||
if (FormSetData->Class != EFI_NON_DEVICE_CLASS) {
|
||||
|
||||
StringLength = 0x1000;
|
||||
String = AllocateZeroPool (StringLength);
|
||||
ASSERT (String != NULL);
|
||||
|
||||
Status = Hii->GetString (Hii, Index, FormSetData->FormSetTitle, TRUE, NULL, &StringLength, String);
|
||||
Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);
|
||||
|
||||
//
|
||||
// If token value exceeded real token value - we need to add a new token values
|
||||
//
|
||||
if (Status == EFI_INVALID_PARAMETER) {
|
||||
Token = 0;
|
||||
TokenHelp = 0;
|
||||
Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);
|
||||
}
|
||||
|
||||
StringLength = 0x1000;
|
||||
if (FormSetData->Help == 0) {
|
||||
TokenHelp = 0;
|
||||
} else {
|
||||
Status = Hii->GetString (Hii, Index, FormSetData->Help, TRUE, NULL, &StringLength, String);
|
||||
if (StringLength == 0x02) {
|
||||
TokenHelp = 0;
|
||||
} else {
|
||||
Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);
|
||||
if (Status == EFI_INVALID_PARAMETER) {
|
||||
TokenHelp = 0;
|
||||
Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBS->FreePool (String);
|
||||
|
||||
CreateGotoOpCode (
|
||||
0x1000, // Device Manager Page
|
||||
Token, // Description String Token
|
||||
TokenHelp, // Description Help String Token
|
||||
EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // Flag designating callback is active
|
||||
(UINT16) Index, // Callback key value
|
||||
&UpdateData->Data // Buffer to fill with op-code
|
||||
);
|
||||
|
||||
//
|
||||
// In the off-chance that we have lots of extra tokens allocated to the DeviceManager
|
||||
// this ensures we are fairly re-using the tokens instead of constantly growing the token
|
||||
// storage for this one handle. If we incremented the token value beyond what it normally
|
||||
// would use, we will fall back into the error path which seeds the token value with a 0
|
||||
// so that we can correctly add a token value.
|
||||
//
|
||||
if (TokenHelp == 0) {
|
||||
//
|
||||
// Since we didn't add help, only advance Token by 1
|
||||
//
|
||||
Token++;
|
||||
} else {
|
||||
Token = (UINT16) (Token + 2);
|
||||
TokenHelp = (UINT16) (TokenHelp + 2);
|
||||
}
|
||||
//
|
||||
// This for loop basically will take the Class value which is a bitmask and
|
||||
// update the form for every active bit. There will be a label at each bit
|
||||
// location. So if someone had a device which a class of EFI_DISK_DEVICE_CLASS |
|
||||
// EFI_ON_BOARD_DEVICE_CLASS, this routine will unwind that mask and drop the menu entry
|
||||
// on each corresponding label.
|
||||
//
|
||||
for (Count = 1; Count < 0x10000; Count <<= 1) {
|
||||
//
|
||||
// This is an active bit, so update the form
|
||||
//
|
||||
if (FormSetData->Class & Count) {
|
||||
Hii->UpdateForm (
|
||||
Hii,
|
||||
FPCallbackInfo.DevMgrHiiHandle,
|
||||
(EFI_FORM_LABEL) (FormSetData->Class & Count),
|
||||
TRUE,
|
||||
UpdateData
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BufferSize = 0;
|
||||
//
|
||||
// Reset Buffer pointer to original location
|
||||
//
|
||||
gBS->FreePool (Buffer);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Add oneof for video BIOS selection
|
||||
//
|
||||
VideoOption = BdsLibGetVariableAndSize (
|
||||
L"VBIOS",
|
||||
&gEfiGlobalVariableGuid,
|
||||
&VideoOptionSize
|
||||
);
|
||||
if (NULL == VideoOption) {
|
||||
FPCallbackInfo.Data.VideoBIOS = 0;
|
||||
} else {
|
||||
FPCallbackInfo.Data.VideoBIOS = VideoOption[0];
|
||||
gBS->FreePool (VideoOption);
|
||||
}
|
||||
|
||||
ASSERT (FPCallbackInfo.Data.VideoBIOS <= 1);
|
||||
|
||||
Status = gBS->AllocatePool (EfiBootServicesData, 2 * sizeof (IFR_OPTION), (VOID**) &IfrOptionList);
|
||||
if (IfrOptionList != NULL) {
|
||||
IfrOptionList[0].Flags = EFI_IFR_FLAG_INTERACTIVE;
|
||||
IfrOptionList[0].Key = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;
|
||||
IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI);
|
||||
IfrOptionList[0].Value = 0;
|
||||
IfrOptionList[0].OptionString = NULL;
|
||||
IfrOptionList[1].Flags = EFI_IFR_FLAG_INTERACTIVE;
|
||||
IfrOptionList[1].Key = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;
|
||||
IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP);
|
||||
IfrOptionList[1].Value = 1;
|
||||
IfrOptionList[1].OptionString = NULL;
|
||||
IfrOptionList[FPCallbackInfo.Data.VideoBIOS].Flags |= EFI_IFR_FLAG_DEFAULT;
|
||||
|
||||
CreateOneOfOpCode (
|
||||
SET_VIDEO_BIOS_TYPE_QUESTION_ID,
|
||||
(UINT8) 1,
|
||||
STRING_TOKEN (STR_ONE_OF_VBIOS),
|
||||
STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),
|
||||
IfrOptionList,
|
||||
2,
|
||||
&UpdateData->Data
|
||||
);
|
||||
|
||||
UpdateData->DataCount = 4;
|
||||
Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) EFI_VBIOS_CLASS, TRUE, UpdateData);
|
||||
gBS->FreePool (IfrOptionList);
|
||||
}
|
||||
|
||||
BootDeviceMngrMenuResetRequired = FALSE;
|
||||
Status = gBrowser->SendForm (
|
||||
gBrowser,
|
||||
TRUE, // Use the database
|
||||
&FPCallbackInfo.DevMgrHiiHandle, // The HII Handle
|
||||
1,
|
||||
NULL,
|
||||
FPCallbackInfo.CallbackHandle,
|
||||
(UINT8 *) &FPCallbackInfo.Data,
|
||||
NULL,
|
||||
&BootDeviceMngrMenuResetRequired
|
||||
);
|
||||
|
||||
if (BootDeviceMngrMenuResetRequired) {
|
||||
EnableResetRequired ();
|
||||
}
|
||||
|
||||
Hii->ResetStrings (Hii, FPCallbackInfo.DevMgrHiiHandle);
|
||||
|
||||
//
|
||||
// We will have returned from processing a callback - user either hit ESC to exit, or selected
|
||||
// a target to display
|
||||
//
|
||||
if (gCallbackKey != 0 && gCallbackKey < 0x2000) {
|
||||
BootDeviceMngrMenuResetRequired = FALSE;
|
||||
Status = gBrowser->SendForm (
|
||||
gBrowser,
|
||||
TRUE, // Use the database
|
||||
(EFI_HII_HANDLE *) &gCallbackKey, // The HII Handle
|
||||
1,
|
||||
NULL,
|
||||
NULL, // This is the handle that the interface to the callback was installed on
|
||||
NULL,
|
||||
NULL,
|
||||
&BootDeviceMngrMenuResetRequired
|
||||
);
|
||||
|
||||
if (BootDeviceMngrMenuResetRequired) {
|
||||
EnableResetRequired ();
|
||||
}
|
||||
//
|
||||
// Force return to Device Manager
|
||||
//
|
||||
gCallbackKey = 4;
|
||||
}
|
||||
|
||||
if (gCallbackKey >= 0x2000) {
|
||||
gCallbackKey = 4;
|
||||
}
|
||||
|
||||
gBS->FreePool (UpdateData);
|
||||
gBS->FreePool (HiiHandles);
|
||||
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user