summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c')
-rw-r--r--EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c1278
1 files changed, 1278 insertions, 0 deletions
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c
new file mode 100644
index 0000000000..c65f841b42
--- /dev/null
+++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c
@@ -0,0 +1,1278 @@
+/*++
+
+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:
+
+ Variable.c
+
+Abstract:
+
+ Variable operation that will be used by BootMaint
+
+--*/
+
+#include "Bds.h"
+#include "BootMaint.h"
+
+EFI_STATUS
+Var_DelBootOption (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.
+ After deleting this boot option, call Var_ChangeBootOrder to
+ make sure BootOrder is in valid state.
+
+Arguments:
+ LoadOption -- Pointer to the boot option that to be deleted
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+
+ UINT16 BootString[10];
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+
+ Status = EFI_SUCCESS;
+ Index2 = 0;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (!NewLoadContext->Deleted) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ BootString,
+ sizeof (BootString),
+ L"Boot%04x",
+ NewMenuEntry->OptionNumber
+ );
+
+ EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);
+ Index2++;
+ //
+ // If current Load Option is the same as BootNext,
+ // must delete BootNext in order to make sure
+ // there will be no panic on next boot
+ //
+ if (NewLoadContext->IsBootNext) {
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
+ }
+
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ NewMenuEntry = NULL;
+ }
+
+ BootOptionMenu.MenuNumber -= Index2;
+
+ Status = Var_ChangeBootOrder ();
+ return Status;
+}
+
+EFI_STATUS
+Var_ChangeBootOrder (
+ VOID
+ )
+/*++
+
+Routine Description:
+ After any operation on Boot####, there will be a discrepancy in BootOrder.
+ Since some are missing but in BootOrder, while some are present but are
+ not reflected by BootOrder. Then a function rebuild BootOrder from
+ scratch by content from BootOptionMenu is needed.
+
+Arguments:
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *BootOrderList;
+ UINT16 *BootOrderListPtr;
+ UINTN BootOrderListSize;
+ UINTN Index;
+
+ BootOrderList = NULL;
+ BootOrderListSize = 0;
+
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ //
+ // If exists, delete it to hold new BootOrder
+ //
+ if (BootOrderList) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ SafeFreePool (BootOrderList);
+ BootOrderList = NULL;
+ }
+ //
+ // Maybe here should be some check method to ensure that
+ // no new added boot options will be added
+ // but the setup engine now will give only one callback
+ // that is to say, user are granted only one chance to
+ // decide whether the boot option will be added or not
+ // there should be no indictor to show whether this
+ // is a "new" boot option
+ //
+ BootOrderListSize = BootOptionMenu.MenuNumber;
+
+ if (BootOrderListSize > 0) {
+ BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));
+ ASSERT (BootOrderList != NULL);
+ BootOrderListPtr = BootOrderList;
+
+ //
+ // Get all current used Boot#### from BootOptionMenu.
+ // OptionNumber in each BM_LOAD_OPTION is really its
+ // #### value.
+ //
+ for (Index = 0; Index < BootOrderListSize; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;
+ BootOrderList++;
+ }
+
+ BootOrderList = BootOrderListPtr;
+
+ //
+ // After building the BootOrderList, write it back
+ //
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize * sizeof (UINT16),
+ BootOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_DelDriverOption (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Delete Load Option that represent a Deleted state in BootOptionMenu.
+ After deleting this Driver option, call Var_ChangeDriverOrder to
+ make sure DriverOrder is in valid state.
+
+Arguments:
+ LoadOption -- Pointer to the Driver option that to be deleted
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+
+ UINT16 DriverString[12];
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+
+ Status = EFI_SUCCESS;
+ Index2 = 0;
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (!NewLoadContext->Deleted) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ NewMenuEntry->OptionNumber
+ );
+
+ EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);
+ Index2++;
+
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ NewMenuEntry = NULL;
+ }
+
+ DriverOptionMenu.MenuNumber -= Index2;
+
+ Status = Var_ChangeDriverOrder ();
+ return Status;
+}
+
+EFI_STATUS
+Var_ChangeDriverOrder (
+ VOID
+ )
+/*++
+
+Routine Description:
+ After any operation on Driver####, there will be a discrepancy in
+ DriverOrder. Since some are missing but in DriverOrder, while some
+ are present but are not reflected by DriverOrder. Then a function
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is
+ needed.
+
+Arguments:
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *DriverOrderList;
+ UINT16 *DriverOrderListPtr;
+ UINTN DriverOrderListSize;
+ UINTN Index;
+
+ DriverOrderList = NULL;
+ DriverOrderListSize = 0;
+
+ //
+ // First check whether DriverOrder is present in current configuration
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+
+ //
+ // If exists, delete it to hold new DriverOrder
+ //
+ if (DriverOrderList) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ SafeFreePool (DriverOrderList);
+ DriverOrderList = NULL;
+ }
+
+ DriverOrderListSize = DriverOptionMenu.MenuNumber;
+
+ if (DriverOrderListSize > 0) {
+ DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));
+ ASSERT (DriverOrderList != NULL);
+ DriverOrderListPtr = DriverOrderList;
+
+ //
+ // Get all current used Driver#### from DriverOptionMenu.
+ // OptionNumber in each BM_LOAD_OPTION is really its
+ // #### value.
+ //
+ for (Index = 0; Index < DriverOrderListSize; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;
+ DriverOrderList++;
+ }
+
+ DriverOrderList = DriverOrderListPtr;
+
+ //
+ // After building the DriverOrderList, write it back
+ //
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize * sizeof (UINT16),
+ DriverOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+VOID
+Var_UpdateAllConsoleOption (
+ VOID
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
+ EFI_STATUS Status;
+
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
+ if (OutDevicePath) {
+ ChangeVariableDevicePath (OutDevicePath);
+ Status = gRT->SetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (OutDevicePath),
+ OutDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+
+ if (InpDevicePath) {
+ ChangeVariableDevicePath (InpDevicePath);
+ Status = gRT->SetVariable (
+ L"ConIn",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (InpDevicePath),
+ InpDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+
+ if (ErrDevicePath) {
+ ChangeVariableDevicePath (ErrDevicePath);
+ Status = gRT->SetVariable (
+ L"ErrOut",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (ErrDevicePath),
+ ErrDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+}
+
+EFI_STATUS
+Var_UpdateConsoleOption (
+ IN UINT16 *ConsoleName,
+ IN BM_MENU_OPTION *ConsoleMenu,
+ IN UINT16 UpdatePageId
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ EFI_STATUS Status;
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
+ UINTN Index;
+ UINT16 *Temp;
+
+ ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);
+ if (ConDevicePath != NULL) {
+ EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
+ SafeFreePool (ConDevicePath);
+ ConDevicePath = NULL;
+ };
+
+ //
+ // First add all console input device to it from console input menu
+ //
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewConsoleContext->IsActive) {
+ ConDevicePath = AppendDevicePathInstance (
+ ConDevicePath,
+ NewConsoleContext->DevicePath
+ );
+ }
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||
+ (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||
+ (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))
+ ) {
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;
+ Vendor.Header.SubType = MSG_VENDOR_DP;
+ CopyMem (
+ &Vendor.Guid,
+ &Guid[NewTerminalContext->TerminalType],
+ sizeof (EFI_GUID)
+ );
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
+ TerminalDevicePath = AppendDevicePathNode (
+ NewTerminalContext->DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
+ );
+ ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
+ Temp = DevicePathToStr (TerminalDevicePath);
+ ConDevicePath = AppendDevicePathInstance (
+ ConDevicePath,
+ TerminalDevicePath
+ );
+ }
+ }
+
+ if (ConDevicePath) {
+ Status = gRT->SetVariable (
+ ConsoleName,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (ConDevicePath),
+ ConDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+Var_UpdateConsoleInpOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
+}
+
+EFI_STATUS
+Var_UpdateConsoleOutOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
+}
+
+EFI_STATUS
+Var_UpdateErrorOutOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
+}
+
+EFI_STATUS
+Var_UpdateDriverOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN UINT16 *DescriptionData,
+ IN UINT16 *OptionalData,
+ IN UINT8 ForceReconnect
+ )
+{
+ UINT16 Index;
+ UINT16 *DriverOrderList;
+ UINT16 *NewDriverOrderList;
+ UINT16 DriverString[12];
+ UINTN DriverOrderListSize;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT8 *Ptr;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN OptionalDataExist;
+ EFI_STATUS Status;
+
+ OptionalDataExist = FALSE;
+
+ Index = BOpt_GetDriverOptionNumber ();
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ Index
+ );
+
+ if (*DescriptionData == 0x0000) {
+ StrCpy (DescriptionData, DriverString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (*OptionalData != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (OptionalData);
+ }
+
+ Buffer = AllocateZeroPool (BufferSize);
+ if (NULL == Buffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->LoadOptionSize = BufferSize;
+ Ptr = (UINT8 *) Buffer;
+ NewLoadContext->LoadOption = Ptr;
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);
+ NewLoadContext->IsActive = TRUE;
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ Ptr += sizeof (UINT32);
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
+
+ Ptr += sizeof (UINT16);
+ CopyMem (
+ Ptr,
+ DescriptionData,
+ StrSize (DescriptionData)
+ );
+
+ NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (DescriptionData)
+ );
+
+ Ptr += StrSize (DescriptionData);
+ CopyMem (
+ Ptr,
+ CallbackData->LoadContext->FilePathList,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
+ ASSERT (NewLoadContext->FilePathList != NULL);
+
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (VOID *) Ptr,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionStrDepository
+ );
+ CallbackData->Hii->NewString (
+ CallbackData->Hii,
+ NULL,
+ HiiHandle,
+ &NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->DisplayString
+ );
+
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionHelpStrDepository
+ );
+ CallbackData->Hii->NewString (
+ CallbackData->Hii,
+ NULL,
+ HiiHandle,
+ &NewMenuEntry->HelpStringToken,
+ NewMenuEntry->HelpString
+ );
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (
+ Ptr,
+ OptionalData,
+ StrSize (OptionalData)
+ );
+ }
+
+ Status = gRT->SetVariable (
+ DriverString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
+ ASSERT (NewDriverOrderList != NULL);
+ CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
+ NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
+ if (DriverOrderList != NULL) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ }
+
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize + sizeof (UINT16),
+ NewDriverOrderList
+ );
+ SafeFreePool (DriverOrderList);
+ DriverOrderList = NULL;
+ SafeFreePool (NewDriverOrderList);
+ NewDriverOrderList = NULL;
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
+ DriverOptionMenu.MenuNumber++;
+
+ *DescriptionData = 0x0000;
+ *OptionalData = 0x0000;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_UpdateBootOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN FILE_EXPLORER_NV_DATA *NvRamMap
+ )
+{
+ UINT16 *BootOrderList;
+ UINT16 *NewBootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 BootString[10];
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT8 *Ptr;
+ UINT16 Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN OptionalDataExist;
+ EFI_STATUS Status;
+
+ OptionalDataExist = FALSE;
+
+ Index = BOpt_GetBootOptionNumber ();
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
+
+ if (NvRamMap->DescriptionData[0] == 0x0000) {
+ StrCpy (NvRamMap->DescriptionData, BootString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (NvRamMap->OptionalData[0] != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (NvRamMap->OptionalData);
+ }
+
+ Buffer = AllocateZeroPool (BufferSize);
+ if (NULL == Buffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->LoadOptionSize = BufferSize;
+ Ptr = (UINT8 *) Buffer;
+ NewLoadContext->LoadOption = Ptr;
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);
+ NewLoadContext->IsActive = TRUE;
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ Ptr += sizeof (UINT32);
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
+ Ptr += sizeof (UINT16);
+
+ CopyMem (
+ Ptr,
+ NvRamMap->DescriptionData,
+ StrSize (NvRamMap->DescriptionData)
+ );
+
+ NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (NvRamMap->DescriptionData)
+ );
+
+ Ptr += StrSize (NvRamMap->DescriptionData);
+ CopyMem (
+ Ptr,
+ CallbackData->LoadContext->FilePathList,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
+ ASSERT (NewLoadContext->FilePathList != NULL);
+
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (VOID *) Ptr,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionStrDepository
+ );
+ CallbackData->Hii->NewString (
+ CallbackData->Hii,
+ NULL,
+ CallbackData->FeHiiHandle,
+ &NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->DisplayString
+ );
+
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionHelpStrDepository
+ );
+
+ CallbackData->Hii->NewString (
+ CallbackData->Hii,
+ NULL,
+ CallbackData->FeHiiHandle,
+ &NewMenuEntry->HelpStringToken,
+ NewMenuEntry->HelpString
+ );
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));
+ }
+
+ Status = gRT->SetVariable (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));
+ ASSERT (NewBootOrderList != NULL);
+ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
+ NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
+
+ if (BootOrderList != NULL) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize + sizeof (UINT16),
+ NewBootOrderList
+ );
+
+ SafeFreePool (BootOrderList);
+ BootOrderList = NULL;
+ SafeFreePool (NewBootOrderList);
+ NewBootOrderList = NULL;
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
+ BootOptionMenu.MenuNumber++;
+
+ NvRamMap->DescriptionData[0] = 0x0000;
+ NvRamMap->OptionalData[0] = 0x0000;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_UpdateBootNext (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;
+ UINT16 Index;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ CurrentFakeNVMap = CallbackData->BmmFakeNvData;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->IsBootNext = FALSE;
+ }
+
+ if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
+ return EFI_SUCCESS;
+ }
+
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &BootOptionMenu,
+ CurrentFakeNVMap->BootNext
+ );
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ Status = gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ sizeof (UINT16),
+ &NewMenuEntry->OptionNumber
+ );
+ NewLoadContext->IsBootNext = TRUE;
+ CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
+ return Status;
+}
+
+EFI_STATUS
+Var_UpdateBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 *BootOrderList;
+ UINT16 *NewBootOrderList;
+ UINTN BootOrderListSize;
+ UINT8 *Map;
+
+ BootOrderList = NULL;
+ BootOrderListSize = 0;
+
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize);
+ if (!NewBootOrderList) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Map = AllocateZeroPool (BootOrderListSize / sizeof (UINT16));
+ if (!Map) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // If exists, delete it to hold new BootOrder
+ //
+ if (BootOrderList) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewBootOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize,
+ NewBootOrderList
+ );
+ SafeFreePool (BootOrderList);
+ SafeFreePool (NewBootOrderList);
+ SafeFreePool (Map);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_GetBootOptions (CallbackData);
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+Var_UpdateDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 *DriverOrderList;
+ UINT16 *NewDriverOrderList;
+ UINTN DriverOrderListSize;
+
+ DriverOrderList = NULL;
+ DriverOrderListSize = 0;
+
+ //
+ // First check whether DriverOrder is present in current configuration
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);
+
+ if (!NewDriverOrderList) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // If exists, delete it to hold new DriverOrder
+ //
+ if (DriverOrderList) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ }
+
+ for (Index = 0; Index < DriverOrderListSize; Index++) {
+ NewDriverOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;
+ }
+
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize,
+ NewDriverOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SafeFreePool (DriverOrderList);
+
+ BOpt_FreeMenu (&DriverOptionMenu);
+ BOpt_GetDriverOptions (CallbackData);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_UpdateBBSOption (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Index;
+ UINTN Index2;
+ VOID *BootOptionVar;
+ CHAR16 VarName[100];
+ UINTN OptionSize;
+ UINT16 FilePathSize;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+ CHAR16 DescString[100];
+ UINTN NewOptionSize;
+ UINT8 *NewOptionPtr;
+ UINT8 *TempPtr;
+ UINT32 *Attribute;
+
+ BM_MENU_OPTION *OptionMenu;
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;
+ UINT8 *LegacyDev;
+ UINT8 *VarData;
+ UINTN VarSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
+ UINT8 *OriginalPtr;
+ UINT8 *DisMap;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 *NewOrder;
+ UINT16 Tmp;
+
+ LegacyDeviceContext = NULL;
+ DisMap = NULL;
+ NewOrder = NULL;
+
+ if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData->LegacyFD;
+ CallbackData->BbsType = BBS_FLOPPY;
+ } else {
+ if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData->LegacyHD;
+ CallbackData->BbsType = BBS_HARDDISK;
+ } else {
+ if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData->LegacyCD;
+ CallbackData->BbsType = BBS_CDROM;
+ } else {
+ if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
+ LegacyDev = CallbackData->BmmFakeNvData->LegacyNET;
+ CallbackData->BbsType = BBS_EMBED_NETWORK;
+ } else {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
+ LegacyDev = CallbackData->BmmFakeNvData->LegacyBEV;
+ CallbackData->BbsType = BBS_BEV_DEVICE;
+ }
+ }
+ }
+ }
+
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
+ Status = EFI_SUCCESS;
+
+ //
+ // Find the first device's context
+ // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
+ // because we just use it to fill the desc string, and user can not see the string in UI
+ //
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {
+ DEBUG ((EFI_D_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));
+ break;
+ }
+ }
+ //
+ // Update the Variable "LegacyDevOrder"
+ //
+ VarData = (UINT8 *) BdsLibGetVariableAndSize (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ &VarSize
+ );
+
+ if (NULL == VarData) {
+ return EFI_NOT_FOUND;
+ }
+
+ OriginalPtr = VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+
+ while (VarData < VarData + VarSize) {
+ if (DevOrder->BbsType == CallbackData->BbsType) {
+ break;
+ }
+
+ VarData += sizeof (BBS_TYPE);
+ VarData += *(UINT16 *) VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ }
+
+ if (VarData >= VarData + VarSize) {
+ SafeFreePool (OriginalPtr);
+ return EFI_NOT_FOUND;
+ }
+
+ NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));
+ if (NULL == NewOrder) {
+ SafeFreePool (VarData);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ if (0xFF == LegacyDev[Index]) {
+ break;
+ }
+
+ NewOrder[Index] = LegacyDev[Index];
+ }
+ //
+ // Only the enable/disable state of each boot device with same device type can be changed,
+ // so we can count on the index information in DevOrder.
+ // DisMap bit array is the only reliable source to check a device's en/dis state,
+ // so we use DisMap to set en/dis state of each item in NewOrder array
+ //
+ for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
+ Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));
+ Tmp &= 0xFF;
+ Pos = Tmp / 8;
+ Bit = 7 - (Tmp % 8);
+ if (DisMap[Pos] & (1 << Bit)) {
+ NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
+ Index++;
+ }
+ }
+
+ CopyMem (
+ (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),
+ NewOrder,
+ DevOrder->Length - sizeof (UINT16)
+ );
+ SafeFreePool (NewOrder);
+
+ Status = gRT->SetVariable (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ VarSize,
+ OriginalPtr
+ );
+
+ SafeFreePool (OriginalPtr);
+
+ //
+ // Update Optional Data of Boot####
+ //
+ BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);
+
+ if (NULL != BootOptionVar) {
+ CopyMem (
+ DescString,
+ LegacyDeviceContext->Description,
+ StrSize (LegacyDeviceContext->Description)
+ );
+
+ NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) + sizeof (BBS_TABLE) + sizeof (UINT16);
+
+ UnicodeSPrint (VarName, 100, L"Boot%04x", Index);
+
+ Ptr = BootOptionVar;
+
+ Attribute = (UINT32 *) Ptr;
+ *Attribute |= LOAD_OPTION_ACTIVE;
+ if (0xFF == LegacyDev[0]) {
+ //
+ // Disable this legacy boot option
+ //
+ *Attribute &= ~LOAD_OPTION_ACTIVE;
+ }
+
+ Ptr += sizeof (UINT32);
+
+ FilePathSize = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+
+ NewOptionSize += FilePathSize;
+
+ NewOptionPtr = AllocateZeroPool (NewOptionSize);
+ if (NULL == NewOptionPtr) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TempPtr = NewOptionPtr;
+
+ //
+ // Copy previous option data to new option except the description string
+ //
+ CopyMem (
+ TempPtr,
+ BootOptionVar,
+ sizeof (UINT32) + sizeof (UINT16)
+ );
+
+ TempPtr += (sizeof (UINT32) + sizeof (UINT16));
+
+ CopyMem (
+ TempPtr,
+ DescString,
+ StrSize (DescString)
+ );
+
+ TempPtr += StrSize (DescString);
+
+ //
+ // Description = (CHAR16 *)Ptr;
+ //
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ CopyMem (
+ TempPtr,
+ Ptr,
+ FilePathSize
+ );
+
+ TempPtr += FilePathSize;
+
+ //
+ // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr;
+ //
+ Ptr += FilePathSize;
+
+ //
+ // Now Ptr point to optional data, i.e. Bbs Table
+ //
+ CopyMem (
+ TempPtr,
+ LegacyDeviceContext->BbsTable,
+ sizeof (BBS_TABLE)
+ );
+
+ TempPtr += sizeof (BBS_TABLE);
+ *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;
+
+ Status = gRT->SetVariable (
+ VarName,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ NewOptionSize,
+ NewOptionPtr
+ );
+
+ SafeFreePool (NewOptionPtr);
+ SafeFreePool (BootOptionVar);
+ }
+
+ BOpt_GetBootOptions (CallbackData);
+ return Status;
+}