diff --git a/EdkModulePkg/Include/Library/EdkGenericPlatformBdsLib.h b/EdkModulePkg/Include/Library/EdkGenericPlatformBdsLib.h new file mode 100644 index 0000000000..699abd830d --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkGenericPlatformBdsLib.h @@ -0,0 +1,140 @@ +/*++ + +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: + + BdsPlatform.h + +Abstract: + + Head file for BDS Platform specific code + +--*/ + +#ifndef _BDS_PLATFORM_LIB_H +#define _BDS_PLATFORM_LIB_H + +extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[]; +// +// Bds AP Context data +// +#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 's', 'A') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + + EFI_BDS_ARCH_PROTOCOL Bds; + + // + // Save the current boot mode + // + EFI_BOOT_MODE BootMode; + + // + // Set true if boot with default settings + // + BOOLEAN DefaultBoot; + + // + // The system default timeout for choose the boot option + // + UINT16 TimeoutDefault; + + // + // Memory Test Level + // + EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel; + +} EFI_BDS_ARCH_PROTOCOL_INSTANCE; + +#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \ + CR (_this, \ + EFI_BDS_ARCH_PROTOCOL_INSTANCE, \ + Bds, \ + EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \ + ) + + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE,\ + END_ENTIRE_DEVICE_PATH_SUBTYPE,\ + {\ + END_DEVICE_PATH_LENGTH,\ + 0\ + }\ + } + +// +// Platform BDS Functions +// +VOID +PlatformBdsInit ( + IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData + ) +; + +VOID +PlatformBdsPolicyBehavior ( + IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData, + IN LIST_ENTRY *DriverOptionList, + IN LIST_ENTRY *BootOptionList + ) +; + +EFI_STATUS +BdsMemoryTest ( + EXTENDMEM_COVERAGE_LEVEL Level + ) +; + +EFI_STATUS +PlatformBdsShowProgress ( + EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + CHAR16 *Title, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + UINTN Progress, + UINTN PreviousValue + ) +; + +VOID +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +; + +VOID +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +; + +EFI_STATUS +ProcessCapsules ( + EFI_BOOT_MODE BootMode + ) +; + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + +#endif // _BDS_PLATFORM_LIB_H diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.dxs b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.dxs new file mode 100644 index 0000000000..6647561959 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.dxs @@ -0,0 +1,27 @@ +/*++ + +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: + + Bds.dxs + +Abstract: + + Dependency expression source file. This driver produces an arch protocol, so + must dipatch early. + +--*/ +#include +#include + +DEPENDENCY_START + EFI_HII_PROTOCOL_GUID +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.h new file mode 100644 index 0000000000..2548aaf925 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.h @@ -0,0 +1,44 @@ +/*++ + +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: + + Bds.h + +Abstract: + + Head file for BDS Architectural Protocol implementation + +Revision History + +--*/ + +#ifndef _BDS_H +#define _BDS_H + + +// +// Prototypes +// +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +#endif diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsBoot.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsBoot.c new file mode 100644 index 0000000000..0a9d359cfc --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsBoot.c @@ -0,0 +1,103 @@ +/*++ + +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: + + BdsPlatform.c + +Abstract: + + This file include all platform action which can be customized + by IBV/OEM. + +--*/ + +#include "String.h" + +VOID +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +/*++ + +Routine Description: + + Hook point after a boot attempt succeeds. We don't expect a boot option to + return, so the EFI 1.0 specification defines that you will default to an + interactive mode and stop processing the BootOrder list in this case. This + is alos a platform implementation and can be customized by IBV/OEM. + +Arguments: + + Option - Pointer to Boot Option that succeeded to boot. + +Returns: + + None. + +--*/ +{ + CHAR16 *TmpStr; + + // + // If Boot returned with EFI_SUCCESS and there is not in the boot device + // select loop then we need to pop up a UI and wait for user input. + // + TmpStr = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + gBS->FreePool (TmpStr); + } +} + +VOID +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +/*++ + +Routine Description: + + Hook point after a boot attempt fails. + +Arguments: + + Option - Pointer to Boot Option that failed to boot. + + Status - Status returned from failed boot. + + ExitData - Exit data returned from failed boot. + + ExitDataSize - Exit data size returned from failed boot. + +Returns: + + None. + +--*/ +{ + CHAR16 *TmpStr; + + // + // If Boot returned with failed status then we need to pop up a UI and wait + // for user input. + // + TmpStr = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + gBS->FreePool (TmpStr); + } + +} + diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsEntry.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsEntry.c new file mode 100644 index 0000000000..7c219b637c --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsEntry.c @@ -0,0 +1,363 @@ +/*++ + +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: + + BdsEntry.c + +Abstract: + + The entry of the bds + +--*/ + +#include "Bds.h" +#include "FrontPage.h" +#include "Language.h" + +EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = { + EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE, + NULL, + { + BdsEntry + }, + 0xFFFF, + TRUE, + EXTENSIVE +}; + +UINT16 *mBootNext = NULL; + +EFI_HANDLE mBdsImageHandle; + +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install Boot Device Selection Protocol + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCEESS - BDS has finished initializing. + Rerun the + dispatcher and recall BDS.Entry + + Other - Return value from EfiLibAllocatePool() + or gBS->InstallProtocolInterface + +--*/ +{ + EFI_STATUS Status; + + mBdsImageHandle = ImageHandle; + + // + // Install protocol interface + // + Status = gBS->InstallProtocolInterface ( + &gBdsInstanceTemplate.Handle, + &gEfiBdsArchProtocolGuid, + EFI_NATIVE_INTERFACE, + &gBdsInstanceTemplate.Bds + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +VOID +BdsBootDeviceSelect ( + VOID + ) +/*++ + +Routine Description: + + In the loop of attempt to boot for the boot order + +Arguments: + + None. + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + BDS_COMMON_OPTION *BootOption; + UINTN ExitDataSize; + CHAR16 *ExitData; + UINT16 Timeout; + LIST_ENTRY BootLists; + CHAR16 Buffer[20]; + BOOLEAN BootNextExist; + LIST_ENTRY *LinkBootNext; + + // + // Got the latest boot option + // + BootNextExist = FALSE; + LinkBootNext = NULL; + InitializeListHead (&BootLists); + + // + // First check the boot next option + // + ZeroMem (Buffer, sizeof (Buffer)); + + if (mBootNext != NULL) { + // + // Indicate we have the boot next variable, so this time + // boot will always have this boot option + // + BootNextExist = TRUE; + + // + // Clear the this variable so it's only exist in this time boot + // + gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + mBootNext + ); + + // + // Add the boot next boot option + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); + BootOption = BdsLibVariableToOption (&BootLists, Buffer); + } + // + // Parse the boot order to get boot option + // + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + + // + // Parameter check, make sure the loop will be valid + // + if (Link == NULL) { + return ; + } + // + // Here we make the boot in a loop, every boot success will + // return to the front page + // + for (;;) { + // + // Check the boot option list first + // + if (Link == &BootLists) { + // + // There are two ways to enter here: + // 1. There is no active boot option, give user chance to + // add new boot option + // 2. All the active boot option processed, and there is no + // one is success to boot, then we back here to allow user + // add new active boot option + // + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + InitializeListHead (&BootLists); + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + continue; + } + // + // Get the boot option from the link list + // + BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // According to EFI Specification, if a load option is not marked + // as LOAD_OPTION_ACTIVE, the boot manager will not automatically + // load the option. + // + if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { + // + // skip the header of the link list, becuase it has no boot option + // + Link = Link->ForwardLink; + continue; + } + // + // Make sure the boot option device path connected, + // but ignore the BBS device path + // + if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { + // + // Notes: the internal shell can not been connected with device path + // so we do not check the status here + // + BdsLibConnectDevicePath (BootOption->DevicePath); + } + // + // All the driver options should have been processed since + // now boot will be performed. + // + PERF_END (0, BDS_TOK, NULL, 0); + Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); + if (EFI_ERROR (Status)) { + // + // Call platform action to indicate the boot fail + // + PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); + + // + // Check the next boot option + // + Link = Link->ForwardLink; + + } else { + // + // Call platform action to indicate the boot success + // + PlatformBdsBootSuccess (BootOption); + + // + // Boot success, then stop process the boot order, and + // present the boot manager menu, front page + // + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Rescan the boot option list, avoid pertential risk of the boot + // option change in front page + // + if (BootNextExist) { + LinkBootNext = BootLists.ForwardLink; + } + + InitializeListHead (&BootLists); + if (LinkBootNext != NULL) { + // + // Reserve the boot next option + // + InsertTailList (&BootLists, LinkBootNext); + } + + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + } + } + + return ; + +} + +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + +Arguments: + + This - Protocol Instance structure. + +Returns: + + EFI_SUCEESS - BDS->Entry has finished executing. + +--*/ +{ + EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData; + LIST_ENTRY DriverOptionList; + LIST_ENTRY BootOptionList; + UINTN BootNextSize; + + // + // Insert the performance probe + // + PERF_END (0, DXE_TOK, NULL, 0); + PERF_START (0, BDS_TOK, NULL, 0); + + // + // Initialize the global system boot option and driver option + // + InitializeListHead (&DriverOptionList); + InitializeListHead (&BootOptionList); + + // + // Get the BDS private data + // + PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This); + + // + // Do the platform init, can be customized by OEM/IBV + // + PERF_START (0, "PlatformBds", "BDS", 0); + PlatformBdsInit (PrivateData); + + // + // Initialize the platform specific string and language + // + InitializeStringSupport (); + InitializeLanguage (TRUE); + InitializeFrontPage (FALSE); + // + // Set up the device list based on EFI 1.1 variables + // process Driver#### and Load the driver's in the + // driver option list + // + BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); + if (!IsListEmpty (&DriverOptionList)) { + BdsLibLoadDrivers (&DriverOptionList); + } + // + // Check if we have the boot next option + // + mBootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + // + // Setup some platform policy here + // + PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList); + PERF_END (0, "PlatformBds", "BDS", 0); + + // + // BDS select the boot device to load OS + // + BdsBootDeviceSelect (); + + // + // Only assert here since this is the right behavior, we should never + // return back to DxeCore. + // + ASSERT (FALSE); +} + diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.c new file mode 100644 index 0000000000..76dd54f0c7 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.c @@ -0,0 +1,1605 @@ +/*++ + +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: + + BBSsupport.c + +Abstract: + + This function deal with the legacy boot option, it create, delete + and manage the legacy boot option, all legacy boot option is getting from + the legacy BBS table. + +--*/ + +#include "BBSsupport.h" + +EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +VOID +AsciiToUnicodeSize ( + IN UINT8 *a, + IN UINTN Size, + OUT UINT16 *u + ) +/*++ + + Routine Description: + + Translate the first n characters of an Ascii string to + Unicode characters. The count n is indicated by parameter + Size. If Size is greater than the length of string, then + the entire string is translated. + + Arguments: + + a - Pointer to input Ascii string. + Size - The number of characters to translate. + u - Pointer to output Unicode string buffer. + + Returns: + + None + +--*/ +{ + UINTN i; + + i = 0; + while (a[i] != 0) { + u[i] = (CHAR16) a[i]; + if (i == Size) { + break; + } + + i++; + } + u[i] = 0; +} + +VOID +BdsBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ) +{ + CHAR16 *Fmt; + CHAR16 *Type; + UINT8 *StringDesc; + CHAR16 temp[80]; + + switch (Index) { + // + // Primary Master + // + case 1: + Fmt = L"Primary Master %s"; + break; + + // + // Primary Slave + // + case 2: + Fmt = L"Primary Slave %s"; + break; + + // + // Secondary Master + // + case 3: + Fmt = L"Secondary Master %s"; + break; + + // + // Secondary Slave + // + case 4: + Fmt = L"Secondary Slave %s"; + break; + + default: + Fmt = L"%s"; + break; + } + + switch (CurBBSEntry->DeviceType) { + case BBS_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_HARDDISK: + Type = L"Harddisk"; + break; + + case BBS_CDROM: + Type = L"CDROM"; + break; + + case BBS_PCMCIA: + Type = L"PCMCIAe"; + break; + + case BBS_USB: + Type = L"USB"; + break; + + case BBS_EMBED_NETWORK: + Type = L"Network"; + break; + + case BBS_BEV_DEVICE: + Type = L"BEVe"; + break; + + case BBS_UNKNOWN: + default: + Type = L"Unknown"; + break; + } + // + // If current BBS entry has its description then use it. + // + StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset); + if (NULL != StringDesc) { + // + // Only get fisrt 32 characters, this is suggested by BBS spec + // + AsciiToUnicodeSize (StringDesc, 32, temp); + Fmt = L"%s"; + Type = temp; + } + + UnicodeSPrint (BootString, BufSize, Fmt, Type); +} + +EFI_STATUS +BdsCreateLegacyBootOption ( + IN BBS_TABLE *CurrentBbsEntry, + IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath, + IN UINTN Index, + IN OUT UINT16 **BootOrderList, + IN OUT UINTN *BootOrderListSize + ) +/*++ + + Routine Description: + + Create a legacy boot option for the specified entry of + BBS table, save it as variable, and append it to the boot + order list. + + Arguments: + + CurrentBbsEntry - Pointer to current BBS table. + CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS + Index - Index of the specified entry in BBS table. + BootOrderList - On input, the original boot order list. + On output, the new boot order list attached with the + created node. + BootOrderListSize - On input, the original size of boot order list. + - On output, the size of new boot order list. + + Returns: + + EFI_SUCCESS - Boot Option successfully created. + EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory. + Other - Error occurs while setting variable. + +--*/ +{ + EFI_STATUS Status; + UINT16 CurrentBootOptionNo; + UINT16 BootString[10]; + UINT16 BootDesc[100]; + UINT16 *NewBootOrderList; + UINTN BufferSize; + VOID *Buffer; + UINT8 *Ptr; + UINT16 CurrentBbsDevPathSize; + UINTN BootOrderIndex; + UINTN BootOrderLastIndex; + UINTN ArrayIndex; + BOOLEAN IndexNotFound; + + if (NULL == (*BootOrderList)) { + CurrentBootOptionNo = 0; + } else { + for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) { + IndexNotFound = TRUE; + for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) { + if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) { + IndexNotFound = FALSE; + break; + } + } + + if (!IndexNotFound) { + continue; + } else { + break; + } + } + + CurrentBootOptionNo = (UINT16) ArrayIndex; + } + + UnicodeSPrint ( + BootString, + sizeof (BootString), + L"Boot%04x", + CurrentBootOptionNo + ); + + BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc); + + CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath)); + + BufferSize = sizeof (UINT32) + + sizeof (UINT16) + + StrSize (BootDesc) + + CurrentBbsDevPathSize + + sizeof (BBS_TABLE) + + sizeof (UINT16); + + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = (UINT8 *) Buffer; + + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; + Ptr += sizeof (UINT32); + + *((UINT16 *) Ptr) = CurrentBbsDevPathSize; + Ptr += sizeof (UINT16); + + CopyMem ( + Ptr, + BootDesc, + StrSize (BootDesc) + ); + Ptr += StrSize (BootDesc); + + CopyMem ( + Ptr, + CurrentBbsDevPath, + CurrentBbsDevPathSize + ); + Ptr += CurrentBbsDevPathSize; + + CopyMem ( + Ptr, + CurrentBbsEntry, + sizeof (BBS_TABLE) + ); + + Ptr += sizeof (BBS_TABLE); + *((UINT16 *) Ptr) = (UINT16) Index; + + Status = gRT->SetVariable ( + BootString, + &gEfiGlobalVariableGuid, + VAR_FLAG, + BufferSize, + Buffer + ); + + SafeFreePool (Buffer); + Buffer = NULL; + + NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16)); + if (NULL == NewBootOrderList) { + return EFI_OUT_OF_RESOURCES; + } + + if (NULL != *BootOrderList) { + CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize); + } + + SafeFreePool (*BootOrderList); + + BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16)); + NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo; + *BootOrderListSize += sizeof (UINT16); + *BootOrderList = NewBootOrderList; + + return Status; +} + +BOOLEAN +BdsIsLegacyBootOption ( + IN UINT8 *BootOptionVar, + OUT BBS_TABLE **BbsEntry, + OUT UINT16 *BbsIndex + ) +{ + UINT8 *Ptr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN Ret; + UINT16 DevPathLen; + + Ptr = BootOptionVar; + Ptr += sizeof (UINT32); + DevPathLen = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + Ptr += StrSize ((UINT16 *) Ptr); + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + Ptr += DevPathLen; + *BbsEntry = (BBS_TABLE *) Ptr; + Ptr += sizeof (BBS_TABLE); + *BbsIndex = *(UINT16 *) Ptr; + Ret = TRUE; + } else { + *BbsEntry = NULL; + Ret = FALSE; + } + + return Ret; +} + +EFI_STATUS +BdsDeleteBootOption ( + IN UINTN OptionNumber, + IN OUT UINT16 *BootOrder, + IN OUT UINTN *BootOrderSize + ) +{ + UINT16 BootOption[100]; + UINTN Index; + EFI_STATUS Status; + UINTN Index2Del; + + Status = EFI_SUCCESS; + Index2Del = 0; + + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber); + Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid); + // + // adjust boot order array + // + for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) { + if (BootOrder[Index] == OptionNumber) { + Index2Del = Index; + break; + } + } + + if (Index != *BootOrderSize / sizeof (UINT16)) { + for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) { + if (Index >= Index2Del) { + BootOrder[Index] = BootOrder[Index + 1]; + } + } + + *BootOrderSize -= sizeof (UINT16); + } + + return Status; + +} + +EFI_STATUS +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ) +/*++ + + Routine Description: + + Delete all the invalid legacy boot options. + + Arguments: + + None. + + Returns: + + EFI_SUCCESS - All invalide legacy boot options are deleted. + EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory. + EFI_NOT_FOUND - Fail to retrive variable of boot order. + Other - Error occurs while setting variable or locating + protocol. + +--*/ +{ + UINT16 *BootOrder; + UINT8 *BootOptionVar; + UINTN BootOrderSize; + UINTN BootOptionSize; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + BBS_TABLE *BbsEntry; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 BootOption[10]; + UINT16 BootDesc[100]; + BOOLEAN DescStringMatch; + + Status = EFI_SUCCESS; + BootOrder = NULL; + BootOrderSize = 0; + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + BbsEntry = NULL; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (NULL == BootOrder) { + return EFI_NOT_FOUND; + } + + Index = 0; + while (Index < BootOrderSize / sizeof (UINT16)) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + SafeFreePool (BootOrder); + return EFI_OUT_OF_RESOURCES; + } + + if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) { + SafeFreePool (BootOptionVar); + Index++; + continue; + } + + // + // Check if BBS Description String is changed + // + DescStringMatch = FALSE; + + BdsBuildLegacyDevNameString ( + &LocalBbsTable[BbsIndex], + BbsIndex, + sizeof(BootDesc), + BootDesc + ); + + if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) { + DescStringMatch = TRUE; + } + + if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[BbsIndex].BootPriority == BBS_LOWEST_PRIORITY)) && + (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) && + DescStringMatch) { + Index++; + continue; + } + + SafeFreePool (BootOptionVar); + // + // should delete + // + BdsDeleteBootOption ( + BootOrder[Index], + BootOrder, + &BootOrderSize + ); + } + + if (BootOrderSize) { + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + } else { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + } + + SafeFreePool (BootOrder); + + return Status; +} + +BOOLEAN +BdsFindLegacyBootOptionByDevType ( + IN UINT16 *BootOrder, + IN UINTN BootOptionNum, + IN UINT16 DevType, + OUT UINT32 *Attribute, + OUT UINT16 *BbsIndex, + OUT UINTN *OptionNumber + ) +{ + UINTN Index; + UINTN BootOrderIndex; + UINT16 BootOption[100]; + UINTN BootOptionSize; + UINT8 *BootOptionVar; + BBS_TABLE *BbsEntry; + BOOLEAN Found; + + BbsEntry = NULL; + Found = FALSE; + + if (NULL == BootOrder) { + return Found; + } + + for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) { + Index = (UINTN) BootOrder[BootOrderIndex]; + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + continue; + } + + if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) { + SafeFreePool (BootOptionVar); + continue; + } + + if (BbsEntry->DeviceType != DevType) { + SafeFreePool (BootOptionVar); + continue; + } + + *Attribute = *(UINT32 *) BootOptionVar; + *OptionNumber = Index; + Found = TRUE; + SafeFreePool (BootOptionVar); + break; + } + + return Found; +} + +EFI_STATUS +BdsCreateOneLegacyBootOption ( + IN BBS_TABLE *BbsItem, + IN UINTN Index, + IN OUT UINT16 **BootOrderList, + IN OUT UINTN *BootOrderListSize + ) +{ + BBS_BBS_DEVICE_PATH BbsDevPathNode; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + DevPath = NULL; + + BbsDevPathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevPathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH)); + BbsDevPathNode.DeviceType = BbsItem->DeviceType; + CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16)); + + DevPath = AppendDevicePathNode ( + EndDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode + ); + if (NULL == DevPath) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BdsCreateLegacyBootOption ( + BbsItem, + DevPath, + Index, + BootOrderList, + BootOrderListSize + ); + BbsItem->BootPriority = 0x00; + + gBS->FreePool (DevPath); + + return Status; +} + +EFI_STATUS +BdsAddNonExistingLegacyBootOptions ( + VOID + ) +/*++ + +Routine Description: + + Add the legacy boot options from BBS table if they do not exist. + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - The boot options are added successfully or they are already in boot options. + others - An error occurred when creating legacy boot options. + +--*/ +{ + UINT16 *BootOrder; + UINTN BootOrderSize; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT32 Attribute; + UINTN OptionNumber; + BOOLEAN Ret; + + BootOrder = NULL; + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**)&LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (NULL == BootOrder) { + BootOrderSize = 0; + } + + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) + ) { + continue; + } + + Ret = BdsFindLegacyBootOptionByDevType ( + BootOrder, + BootOrderSize / sizeof (UINT16), + LocalBbsTable[Index].DeviceType, + &Attribute, + &BbsIndex, + &OptionNumber + ); + if (Ret && (Attribute & LOAD_OPTION_ACTIVE) != 0) { + continue; + } + + if (Ret) { + if (Index != BbsIndex) { + BdsDeleteBootOption ( + OptionNumber, + BootOrder, + &BootOrderSize + ); + } else { + continue; + } + } + // + // Not found such type of legacy device in boot options or we found but it's disabled + // so we have to create one and put it to the tail of boot order list + // + Status = BdsCreateOneLegacyBootOption ( + &LocalBbsTable[Index], + Index, + &BootOrder, + &BootOrderSize + ); + if (EFI_ERROR (Status)) { + break; + } + } + + if (BootOrderSize > 0) { + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + } else { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + } + + if (BootOrder != NULL) { + SafeFreePool (BootOrder); + } + + return Status; +} + +UINT16 * +BdsFillDevOrderBuf ( + IN BBS_TABLE *BbsTable, + IN BBS_TYPE BbsType, + IN UINTN BbsCount, + IN UINT16 *Buf + ) +{ + UINTN Index; + + for (Index = 0; Index < BbsCount; Index++) { + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + if (BbsTable[Index].DeviceType != BbsType) { + continue; + } + + *Buf = (UINT16) (Index & 0xFF); + Buf++; + } + + return Buf; +} + +EFI_STATUS +BdsCreateDevOrder ( + IN BBS_TABLE *BbsTable, + IN UINT16 BbsCount + ) +{ + UINTN Index; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + UINT8 *DevOrder; + UINT8 *Ptr; + EFI_STATUS Status; + + FDCount = 0; + HDCount = 0; + CDCount = 0; + NETCount = 0; + BEVCount = 0; + TotalSize = 0; + HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16); + DevOrder = NULL; + Ptr = NULL; + Status = EFI_SUCCESS; + + for (Index = 0; Index < BbsCount; Index++) { + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize += (HeaderSize + sizeof (UINT16) * FDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * HDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * CDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * NETCount); + TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount); + + DevOrder = AllocateZeroPool (TotalSize); + if (NULL == DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = DevOrder; + + *((BBS_TYPE *) Ptr) = BBS_FLOPPY; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (FDCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_HARDDISK; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (HDCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_CDROM; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (CDCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (NETCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (BEVCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr); + } + + Status = gRT->SetVariable ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + VAR_FLAG, + TotalSize, + DevOrder + ); + SafeFreePool (DevOrder); + + return Status; +} + +EFI_STATUS +BdsUpdateLegacyDevOrder ( + VOID + ) +/*++ +Format of LegacyDevOrder variable: +|----------------------------------------------------------------------------------------------------------------- +| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ... +|----------------------------------------------------------------------------------------------------------------- + +Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself. +Index# is a 16 bit integer, the low byte of it stands for the index in BBS table + the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been + disabled by user. +--*/ +{ + UINT8 *DevOrder; + UINT8 *NewDevOrder; + UINTN DevOrderSize; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINTN Index; + UINTN Index2; + UINTN *Idx; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + UINT8 *Ptr; + UINT8 *NewPtr; + UINT16 *NewFDPtr; + UINT16 *NewHDPtr; + UINT16 *NewCDPtr; + UINT16 *NewNETPtr; + UINT16 *NewBEVPtr; + UINT16 *NewDevPtr; + UINT16 Length; + UINT16 tmp; + UINTN FDIndex; + UINTN HDIndex; + UINTN CDIndex; + UINTN NETIndex; + UINTN BEVIndex; + + LocalHddInfo = NULL; + LocalBbsTable = NULL; + Idx = NULL; + FDCount = 0; + HDCount = 0; + CDCount = 0; + NETCount = 0; + BEVCount = 0; + TotalSize = 0; + HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16); + FDIndex = 0; + HDIndex = 0; + CDIndex = 0; + NETIndex = 0; + BEVIndex = 0; + NewDevPtr = NULL; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + DevOrder = (UINT8 *) BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &DevOrderSize + ); + if (NULL == DevOrder) { + return BdsCreateDevOrder (LocalBbsTable, BbsCount); + } + // + // First we figure out how many boot devices with same device type respectively + // + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize += (HeaderSize + FDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + HDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + CDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + NETCount * sizeof (UINT16)); + TotalSize += (HeaderSize + BEVCount * sizeof (UINT16)); + + NewDevOrder = AllocateZeroPool (TotalSize); + if (NULL == NewDevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize); + NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize); + NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize); + NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize); + NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize); + + // + // copy FD + // + Ptr = DevOrder; + NewPtr = NewDevOrder; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewFDPtr[FDIndex] = *(UINT16 *) Ptr; + FDIndex++; + Ptr += sizeof (UINT16); + } + // + // copy HD + // + NewPtr = (UINT8 *) NewHDPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewHDPtr[HDIndex] = *(UINT16 *) Ptr; + HDIndex++; + Ptr += sizeof (UINT16); + } + // + // copy CD + // + NewPtr = (UINT8 *) NewCDPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_CDROM + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewCDPtr[CDIndex] = *(UINT16 *) Ptr; + CDIndex++; + Ptr += sizeof (UINT16); + } + // + // copy NET + // + NewPtr = (UINT8 *) NewNETPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewNETPtr[NETIndex] = *(UINT16 *) Ptr; + NETIndex++; + Ptr += sizeof (UINT16); + } + // + // copy BEV + // + NewPtr = (UINT8 *) NewBEVPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr; + BEVIndex++; + Ptr += sizeof (UINT16); + } + + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + Idx = &FDIndex; + NewDevPtr = NewFDPtr; + break; + + case BBS_HARDDISK: + Idx = &HDIndex; + NewDevPtr = NewHDPtr; + break; + + case BBS_CDROM: + Idx = &CDIndex; + NewDevPtr = NewCDPtr; + break; + + case BBS_EMBED_NETWORK: + Idx = &NETIndex; + NewDevPtr = NewNETPtr; + break; + + case BBS_BEV_DEVICE: + Idx = &BEVIndex; + NewDevPtr = NewBEVPtr; + break; + + default: + Idx = NULL; + break; + } + // + // at this point we have copied those valid indexes to new buffer + // and we should check if there is any new appeared boot device + // + if (Idx) { + for (Index2 = 0; Index2 < *Idx; Index2++) { + if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) { + break; + } + } + + if (Index2 == *Idx) { + // + // Index2 == *Idx means we didn't find Index + // so Index is a new appeared device's index in BBS table + // save it. + // + NewDevPtr[*Idx] = (UINT16) (Index & 0xFF); + (*Idx)++; + } + } + } + + if (FDCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < FDIndex - 1; Index++) { + if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < FDIndex; Index2++) { + if (0 == (NewFDPtr[Index2] & 0xFF00)) { + tmp = NewFDPtr[Index]; + NewFDPtr[Index] = NewFDPtr[Index2]; + NewFDPtr[Index2] = tmp; + break; + } + } + } + } + + if (HDCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < HDIndex - 1; Index++) { + if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < HDIndex; Index2++) { + if (0 == (NewHDPtr[Index2] & 0xFF00)) { + tmp = NewHDPtr[Index]; + NewHDPtr[Index] = NewHDPtr[Index2]; + NewHDPtr[Index2] = tmp; + break; + } + } + } + } + + if (CDCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < CDIndex - 1; Index++) { + if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < CDIndex; Index2++) { + if (0 == (NewCDPtr[Index2] & 0xFF00)) { + tmp = NewCDPtr[Index]; + NewCDPtr[Index] = NewCDPtr[Index2]; + NewCDPtr[Index2] = tmp; + break; + } + } + } + } + + if (NETCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < NETIndex - 1; Index++) { + if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < NETIndex; Index2++) { + if (0 == (NewNETPtr[Index2] & 0xFF00)) { + tmp = NewNETPtr[Index]; + NewNETPtr[Index] = NewNETPtr[Index2]; + NewNETPtr[Index2] = tmp; + break; + } + } + } + } + + if (BEVCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < BEVIndex - 1; Index++) { + if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) { + if (0 == (NewBEVPtr[Index2] & 0xFF00)) { + tmp = NewBEVPtr[Index]; + NewBEVPtr[Index] = NewBEVPtr[Index2]; + NewBEVPtr[Index2] = tmp; + break; + } + } + } + } + + SafeFreePool (DevOrder); + + Status = gRT->SetVariable ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + VAR_FLAG, + TotalSize, + NewDevOrder + ); + SafeFreePool (NewDevOrder); + + return Status; +} + +EFI_STATUS +BdsSetBootPriority4SameTypeDev ( + IN UINT16 DeviceType, + IN OUT BBS_TABLE *LocalBbsTable, + IN OUT UINT16 *Priority + ) +/*++ +DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on +LocalBbsTable - BBS table instance +Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot + priority can be used next time. +--*/ +{ + UINT8 *DevOrder; + + UINT8 *OrigBuffer; + UINT16 *DevIndex; + UINTN DevOrderSize; + UINTN DevCount; + UINTN Index; + + DevOrder = BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &DevOrderSize + ); + if (NULL == DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + OrigBuffer = DevOrder; + while (DevOrder < OrigBuffer + DevOrderSize) { + if (DeviceType == * (BBS_TYPE *) DevOrder) { + break; + } + + DevOrder += sizeof (BBS_TYPE); + DevOrder += *(UINT16 *) DevOrder; + } + + if (DevOrder >= OrigBuffer + DevOrderSize) { + SafeFreePool (OrigBuffer); + return EFI_NOT_FOUND; + } + + DevOrder += sizeof (BBS_TYPE); + DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16); + DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16)); + // + // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled. + // + for (Index = 0; Index < DevCount; Index++) { + if ((DevIndex[Index] & 0xFF00) == 0xFF00) { + // + // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY; + // + } else { + LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority; + (*Priority)++; + } + } + + SafeFreePool (OrigBuffer); + return EFI_SUCCESS; +} + +VOID +PrintBbsTable ( + IN BBS_TABLE *LocalBbsTable + ) +{ + UINT16 Idx; + + DEBUG ((EFI_D_ERROR, "\n")); + DEBUG ((EFI_D_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n")); + DEBUG ((EFI_D_ERROR, "=============================================\n")); + for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) { + if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + DEBUG ( + (EFI_D_ERROR, + " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n", + (UINTN) Idx, + (UINTN) LocalBbsTable[Idx].BootPriority, + (UINTN) LocalBbsTable[Idx].Bus, + (UINTN) LocalBbsTable[Idx].Device, + (UINTN) LocalBbsTable[Idx].Function, + (UINTN) LocalBbsTable[Idx].Class, + (UINTN) LocalBbsTable[Idx].SubClass, + (UINTN) LocalBbsTable[Idx].DeviceType, + (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags, + (UINTN) LocalBbsTable[Idx].BootHandlerSegment, + (UINTN) LocalBbsTable[Idx].BootHandlerOffset, + (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset), + (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset)) + ); + } + + DEBUG ((EFI_D_ERROR, "\n")); +} + +EFI_STATUS +BdsRefreshBbsTableForBoot ( + IN BDS_COMMON_OPTION *Entry + ) +{ + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 DevType; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 Priority; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINT8 *BootOptionVar; + UINTN BootOptionSize; + UINT16 BootOption[100]; + UINT8 *Ptr; + UINT16 DevPathLen; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + DevType = BBS_UNKNOWN; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + // + // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY + // We will set them according to the settings setup by user + // + for (Index = 0; Index < BbsCount; Index++) { + if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) || + (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) || + (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) { + LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } + } + // + // boot priority always starts at 0 + // + Priority = 0; + if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) { + // + // If Entry stands for a legacy boot option, we prioritize the devices with the same type first. + // + DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType; + Status = BdsSetBootPriority4SameTypeDev ( + DevType, + LocalBbsTable, + &Priority + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // we have to set the boot priority for other BBS entries with different device types + // + BootOrder = (UINT16 *) BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + continue; + } + + Ptr = BootOptionVar; + + Ptr += sizeof (UINT32); + DevPathLen = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + Ptr += StrSize ((UINT16 *) Ptr); + DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) { + SafeFreePool (BootOptionVar); + continue; + } + + Ptr += DevPathLen; + if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) { + // + // We don't want to process twice for a device type + // + SafeFreePool (BootOptionVar); + continue; + } + + Status = BdsSetBootPriority4SameTypeDev ( + ((BBS_TABLE *) Ptr)->DeviceType, + LocalBbsTable, + &Priority + ); + SafeFreePool (BootOptionVar); + if (EFI_ERROR (Status)) { + break; + } + } + + if (BootOrder) { + SafeFreePool (BootOrder); + } + // + // For debug + // + PrintBbsTable (LocalBbsTable); + + return Status; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.h new file mode 100644 index 0000000000..572beb11ab --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.h @@ -0,0 +1,83 @@ +/*++ + +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: + + BBSsupport.h + +Abstract: + + declares interface functions + +Revision History + +--*/ + +#ifndef _EFI_BDS_BBS_SUPPORT_H +#define _EFI_BDS_BBS_SUPPORT_H + +#include "BootMaint/BootMaint.h" + +#ifdef EFI32 +#define REFRESH_LEGACY_BOOT_OPTIONS \ + BdsDeleteAllInvalidLegacyBootOptions ();\ + BdsAddNonExistingLegacyBootOptions (); \ + BdsUpdateLegacyDevOrder () +#else +#define REFRESH_LEGACY_BOOT_OPTIONS +#endif + +VOID +BdsBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ); + +EFI_STATUS +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ); + +EFI_STATUS +BdsAddNonExistingLegacyBootOptions ( + VOID + ) +/*++ + +Routine Description: + + Add the legacy boot options from BBS table if they do not exist. + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - The boot options are added successfully or they are already in boot options. + others - An error occurred when creating legacy boot options. + +--*/ +; + +EFI_STATUS +BdsUpdateLegacyDevOrder ( + VOID + ); + +EFI_STATUS +BdsRefreshBbsTableForBoot ( + IN BDS_COMMON_OPTION *Entry + ); + +#endif diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Bm.vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Bm.vfr new file mode 100644 index 0000000000..b5364c34ca --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Bm.vfr @@ -0,0 +1,495 @@ +// *++ +// +// 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: +// +// bm.vfr +// +// Abstract: +// +// Boot Maintenance Utility Formset +// +// Revision History: +// +// --*/ + +#include "EdkGenericPlatformBdsLibStrDefs.h" +#include "FormGuid.h" + +#pragma pack(1) + +// +// This is the structure that will be used to store the +// question's current value. Use it at initialize time to +// set default value for each question. When using at run +// time, this map is returned by the callback function, +// so dynamically changing the question's value will be +// possible through this mechanism +// +typedef struct { + +// +// Three questions displayed at the main page +// for Timeout, BootNext Variables respectively +// + UINT16 BootTimeOut; + UINT16 BootNext; + +// +// This is the COM1 Attributes value storage +// + UINT8 COM1BaudRate; + UINT8 COM1DataRate; + UINT8 COM1StopBits; + UINT8 COM1Parity; + UINT8 COM1TerminalType; + +// +// This is the COM2 Attributes value storage +// + UINT8 COM2BaudRate; + UINT8 COM2DataRate; + UINT8 COM2StopBits; + UINT8 COM2Parity; + UINT8 COM2TerminalType; + +// +// Driver Option Add Handle page storage +// + UINT16 DriverAddHandleDesc[100]; + UINT16 DriverAddHandleOptionalData[100]; + UINT8 DriverAddActive; + UINT8 DriverAddForceReconnect; + +// +// Console Input/Output/Errorout using COM port check storage +// + UINT8 ConsoleInputCOM1; + UINT8 ConsoleInputCOM2; + UINT8 ConsoleOutputCOM1; + UINT8 ConsoleOutputCOM2; + UINT8 ConsoleErrorCOM1; + UINT8 ConsoleErrorCOM2; + +// +// At most 100 input/output/errorout device for console storage +// + UINT8 ConsoleCheck[100]; + +// +// Boot or Driver Option Order storage +// + UINT8 OptionOrder[100]; + UINT8 DriverOptionToBeDeleted[100]; + +// +// Boot Option Delete storage +// + UINT8 BootOptionDel[100]; + UINT8 DriverOptionDel[100]; + +// +// This is the Terminal Attributes value storage +// + UINT8 COMBaudRate; + UINT8 COMDataRate; + UINT8 COMStopBits; + UINT8 COMParity; + UINT8 COMTerminalType; + +// +// Legacy Device Order Selection Storage +// + UINT8 LegacyFD[100]; + UINT8 LegacyHD[100]; + UINT8 LegacyCD[100]; + UINT8 LegacyNET[100]; + UINT8 LegacyBEV[100]; +} BMM_FAKE_NV_DATA; +#pragma pack() + + +#define FORM_MAIN_ID 0x0001 +#define FORM_BOOT_ADD_ID 0x0002 +#define FORM_BOOT_DEL_ID 0x0003 +#define FORM_BOOT_CHG_ID 0x0004 +#define FORM_DRV_ADD_ID 0x0005 +#define FORM_DRV_DEL_ID 0x0006 +#define FORM_DRV_CHG_ID 0x0007 +#define FORM_CON_MAIN_ID 0x0008 +#define FORM_CON_IN_ID 0x0009 +#define FORM_CON_OUT_ID 0x000A +#define FORM_CON_ERR_ID 0x000B +#define FORM_FILE_SEEK_ID 0x000C +#define FORM_FILE_NEW_SEEK_ID 0x000D +#define FORM_DRV_ADD_FILE_ID 0x000E +#define FORM_DRV_ADD_HANDLE_ID 0x000F +#define FORM_DRV_ADD_HANDLE_DESC_ID 0x0010 +#define FORM_BOOT_NEXT_ID 0x0011 +#define FORM_TIME_OUT_ID 0x0012 +#define FORM_RESET 0x0013 +#define FORM_BOOT_SETUP_ID 0x0014 +#define FORM_DRIVER_SETUP_ID 0x0015 +#define FORM_BOOT_LEGACY_DEVICE_ID 0x0016 +#define FORM_CON_COM_ID 0x0017 +#define FORM_CON_COM_SETUP_ID 0x0018 +#define FORM_SET_FD_ORDER_ID 0x0019 +#define FORM_SET_HD_ORDER_ID 0x001A +#define FORM_SET_CD_ORDER_ID 0x001B +#define FORM_SET_NET_ORDER_ID 0x001C +#define FORM_SET_BEV_ORDER_ID 0x001D + +#define KEY_VALUE_BOOT_FROM_FILE 0x0092 + +formset + guid = MAIN_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE), // uint8 opcode, uint8 length, guid Handle, uint16 Title + help = STRING_TOKEN(STR_NULL_STRING), + class = 0, + subclass = 0, + + form formid = FORM_MAIN_ID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE); + + goto FORM_BOOT_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_DRIVER_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRIVER_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_CON_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_MAIN_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP), + text = STRING_TOKEN(STR_BOOT_FROM_FILE), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_BOOT_FROM_FILE; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + +// label FORM_MAIN_ID; + + goto FORM_BOOT_NEXT_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_NEXT_ID; + + goto FORM_TIME_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_TIME_OUT_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_RESET), + help = STRING_TOKEN(STR_RESET), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_RESET; + + endform; + + form formid = FORM_BOOT_SETUP_ID, + title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_BOOT_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_ADD_ID; + + goto FORM_BOOT_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_DEL_ID; + + goto FORM_BOOT_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_CHG_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive" + // here dynamically + // + label FORM_BOOT_LEGACY_DEVICE_ID; + + endform; + + form formid = FORM_DRIVER_SETUP_ID, + title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_ADD_ID; + + goto FORM_DRV_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_DEL_ID; + + goto FORM_DRV_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_CHG_ID; + endform; + + form formid = FORM_BOOT_ADD_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_BOOT_ADD_ID; + endform; + + form formid = FORM_BOOT_DEL_ID, + title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE); + + label FORM_BOOT_DEL_ID; + endform; + + form formid = FORM_BOOT_CHG_ID, + title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE); + + label FORM_BOOT_CHG_ID; + + // + // This tag is added for bypassing issue of setup browser + // setup browser could not support dynamic form very well. + // + checkbox varid = BMM_FAKE_NV_DATA.OptionOrder[0], + prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + flags = 1, + key = 0, + endcheckbox; + + endform; + + form formid = FORM_BOOT_NEXT_ID, + title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE); + + label FORM_BOOT_NEXT_ID; + endform; + + form formid = FORM_TIME_OUT_ID, + title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE); + + label FORM_TIME_OUT_ID; + endform; + + form formid = FORM_DRV_ADD_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_FILE_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_ADD_FILE_ID; + + endform; + + form formid = FORM_DRV_DEL_ID, + title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE); + + label FORM_DRV_DEL_ID; + + endform; + + form formid = FORM_DRV_CHG_ID, + title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE); + + label FORM_DRV_CHG_ID; + + // + // This tag is added for bypassing issue of setup browser + // setup browser could not support dynamic form very well. + // + checkbox varid = BMM_FAKE_NV_DATA.OptionOrder[0], + prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + flags = 1, + key = 0, + endcheckbox; + + endform; + + form formid = FORM_CON_MAIN_ID, + title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_CON_IN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_IN_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_IN_ID; + + goto FORM_CON_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_CON_OUT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_OUT_ID; + + goto FORM_CON_ERR_ID, + prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE), + help = STRING_TOKEN(STR_FORM_STD_ERR_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_ERR_ID; + + goto FORM_CON_COM_ID, + prompt = STRING_TOKEN(STR_FORM_COM_TITLE), + help = STRING_TOKEN(STR_FORM_COM_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_COM_ID; + endform; + + form formid = FORM_CON_COM_ID, + title = STRING_TOKEN(STR_FORM_COM_TITLE); + + label FORM_CON_COM_ID; + endform; + + form formid = FORM_CON_COM_SETUP_ID, + title = STRING_TOKEN(STR_CON_COM_SETUP); + + label FORM_CON_COM_SETUP_ID; + endform; + + form formid = FORM_FILE_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_SEEK_ID; + endform; + + form formid = FORM_FILE_NEW_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_NEW_SEEK_ID; + endform; + + form formid = FORM_DRV_ADD_FILE_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE); + + label FORM_DRV_ADD_FILE_ID; + endform; + + form formid = FORM_DRV_ADD_HANDLE_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE); + + label FORM_DRV_ADD_HANDLE_ID; + endform; + + form formid = FORM_DRV_ADD_HANDLE_DESC_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRV_ADD_HANDLE_DESC_ID; + + endform; + + form formid = FORM_CON_IN_ID, + title = STRING_TOKEN(STR_FORM_CON_IN_TITLE); + + label FORM_CON_IN_ID; + + endform; + + form formid = FORM_CON_OUT_ID, + title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE); + + label FORM_CON_OUT_ID; + + endform; + + form formid = FORM_CON_ERR_ID, + title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE); + + label FORM_CON_ERR_ID; + + endform; + + form formid = FORM_SET_FD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE); + + label FORM_SET_FD_ORDER_ID; + endform; + + form formid = FORM_SET_HD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE); + + label FORM_SET_HD_ORDER_ID; + endform; + + form formid = FORM_SET_CD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE); + + label FORM_SET_CD_ORDER_ID; + endform; + + form formid = FORM_SET_NET_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE); + + label FORM_SET_NET_ORDER_ID; + endform; + + form formid = FORM_SET_BEV_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE); + + label FORM_SET_BEV_ORDER_ID; + endform; + +endformset; diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmLib.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmLib.c new file mode 100644 index 0000000000..e9245d2fb6 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmLib.c @@ -0,0 +1,627 @@ +/*++ + +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: + + BmLib.c + +AgBStract: + + Boot Maintainence Helper functions + +--*/ + +#include "BootMaint.h" + +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Find the first instance of this Protocol + in the system and return it's interface + +Arguments: + + ProtocolGuid - Provides the protocol to search for + Interface - On return, a pointer to the first interface + that matches ProtocolGuid + +Returns: + + EFI_SUCCESS - A protocol instance matching ProtocolGuid was found + + EFI_NOT_FOUND - No protocol instances were found that match ProtocolGuid + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + ProtocolGuid, + NULL, + Interface + ); + return Status; +} + +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ) +/*++ + +Routine Description: + + Function opens and returns a file handle to the root directory of a volume. + +Arguments: + + DeviceHandle - A handle for a device + +Returns: + + A valid file handle or NULL is returned + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE File; + + File = NULL; + + // + // File the file system interface to the device + // + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID *) &Volume + ); + + // + // Open the root directory of the volume + // + if (!EFI_ERROR (Status)) { + Status = Volume->OpenVolume ( + Volume, + &File + ); + } + // + // Done + // + return EFI_ERROR (Status) ? NULL : File; +} + +BOOLEAN +EfiGrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + +Arguments: + + Status - Current status + + Buffer - Current allocated buffer, or NULL + + BufferSize - Current buffer size needed + +Returns: + + TRUE - if the buffer was reallocated and the caller + should try the API again. + +--*/ +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + if (!*Buffer && BufferSize) { + *Status = EFI_BUFFER_TOO_SMALL; + } + // + // If the status code is "buffer too small", resize the buffer + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + SafeFreePool (*Buffer); + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + // + // If there's an error, free the buffer + // + if (!TryAgain && EFI_ERROR (*Status) && *Buffer) { + SafeFreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + +VOID * +EfiLibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + Function returns the value of the specified variable. + +Arguments: + Name - A Null-terminated Unicode string that is + the name of the vendor's variable. + + VendorGuid - A unique identifier for the vendor. + +Returns: + + None + +--*/ +{ + UINTN VarSize; + + return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize); +} + +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ) +/*++ + +Routine Description: + Function deletes the variable specified by VarName and VarGuid. + +Arguments: + VarName - A Null-terminated Unicode string that is + the name of the vendor's variable. + + VendorGuid - A unique identifier for the vendor. + +Returns: + + EFI_SUCCESS - The variable was found and removed + + EFI_UNSUPPORTED - The variable store was inaccessible + + EFI_OUT_OF_RESOURCES - The temporary buffer was not available + + EFI_NOT_FOUND - The variable was not found + +--*/ +{ + VOID *VarBuf; + EFI_STATUS Status; + + VarBuf = EfiLibGetVariable (VarName, VarGuid); + Status = EFI_NOT_FOUND; + + if (VarBuf) { + // + // Delete variable from Storage + // + Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL); + ASSERT (!EFI_ERROR (Status)); + SafeFreePool (VarBuf); + } + + return Status; +} + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +/*++ + +Routine Description: + + Function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + +Arguments: + + Fhand - A file handle + +Returns: + + A pointer to a buffer with file information or NULL is returned + +--*/ +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer; + UINTN BufferSize; + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileSystemVolumeLabelInfoIdGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ) +{ + CHAR16 *Dest; + UINTN Size; + + Size = StrSize (Src); + Dest = AllocateZeroPool (Size); + ASSERT (Dest != NULL); + if (Dest) { + CopyMem (Dest, Src, Size); + } + + return Dest; +} + +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ) +/*++ + +Routine Description: + + Function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + +Arguments: + + Fhand - A file handle + +Returns: + + A pointer to a buffer with file information or NULL is returned + +--*/ +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileInfoGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Function is used to determine the number of device path instances + that exist in a device path. + +Arguments: + DevicePath - A pointer to a device path data structure. + +Returns: + + This function counts and returns the number of device path instances + in DevicePath. + +--*/ +{ + UINTN Count; + UINTN Size; + + Count = 0; + while (GetNextDevicePathInstance (&DevicePath, &Size)) { + Count += 1; + } + + return Count; +} + +VOID * +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +/*++ + +Routine Description: + Adjusts the size of a previously allocated buffer. + +Arguments: + OldPool - A pointer to the buffer whose size is being adjusted. + OldSize - The size of the current buffer. + NewSize - The size of the new buffer. + +Returns: + + EFI_SUCEESS - The requested number of bytes were allocated. + + EFI_OUT_OF_RESOURCES - The pool requested could not be allocated. + + EFI_INVALID_PARAMETER - The buffer was invalid. + +--*/ +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool) { + if (NewPool) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + SafeFreePool (OldPool); + } + + return NewPool; +} + +EFI_STATUS +EfiLibGetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Acquire the string associated with the ProducerGuid and return it. + +Arguments: + + ProducerGuid - The Guid to search the HII database for + Token - The token value of the string to extract + String - The string that is extracted + +Returns: + + EFI_SUCCESS - Buffer filled with the requested forms. BufferLength + was updated. + EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored. + +--*/ +{ + EFI_STATUS Status; + UINT16 HandleBufferLength; + EFI_HII_HANDLE *HiiHandleBuffer; + UINTN StringBufferLength; + UINTN NumberOfHiiHandles; + UINTN Index; + UINT16 Length; + EFI_GUID HiiGuid; + EFI_HII_PROTOCOL *Hii; + + // + // Initialize params. + // + HandleBufferLength = 0; + HiiHandleBuffer = NULL; + + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID**) &Hii + ); + if (EFI_ERROR (Status)) { + *String = NULL; + return Status; + } + // + // Get all the Hii handles + // + Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandleBuffer); + ASSERT_EFI_ERROR (Status); + + // + // Get the Hii Handle that matches the StructureNode->ProducerName + // + NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < NumberOfHiiHandles; Index++) { + Length = 0; + Status = ExtractDataFromHiiHandle ( + HiiHandleBuffer[Index], + &Length, + NULL, + &HiiGuid + ); + if (CompareGuid (ProducerGuid, &HiiGuid)) { + break; + } + } + // + // Find the string based on the current language + // + StringBufferLength = 0x100; + *String = AllocateZeroPool (0x100); + ASSERT (*String != NULL); + + Status = Hii->GetString ( + Hii, + HiiHandleBuffer[Index], + Token, + FALSE, + NULL, + &StringBufferLength, + *String + ); + + gBS->FreePool (HiiHandleBuffer); + + return Status; +} + +BOOLEAN +TimeCompare ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ) +/*++ + +Routine Description: + Compare two EFI_TIME data. + +Arguments: + + FirstTime - A pointer to the first EFI_TIME data. + SecondTime - A pointer to the second EFI_TIME data. + +Returns: + TRUE The FirstTime is not later than the SecondTime. + FALSE The FirstTime is later than the SecondTime. + +--*/ +{ + if (FirstTime->Year != SecondTime->Year) { + return (BOOLEAN) (FirstTime->Year < SecondTime->Year); + } else if (FirstTime->Month != SecondTime->Month) { + return (BOOLEAN) (FirstTime->Month < SecondTime->Month); + } else if (FirstTime->Day != SecondTime->Day) { + return (BOOLEAN) (FirstTime->Day < SecondTime->Day); + } else if (FirstTime->Hour != SecondTime->Hour) { + return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour); + } else if (FirstTime->Minute != SecondTime->Minute) { + return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute); + } else if (FirstTime->Second != SecondTime->Second) { + return (BOOLEAN) (FirstTime->Second < SecondTime->Second); + } + + return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond); +} + +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + EFI_STATUS Status; + UINT16 *Desc; + EFI_DATA_HUB_PROTOCOL *Datahub; + UINT64 Count; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHdr; + EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID; + EFI_MISC_ONBOARD_DEVICE_DATA *ob; + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port; + EFI_TIME CurTime; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID**) &Datahub + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + Status = gRT->GetTime (&CurTime, NULL); + if (EFI_ERROR (Status)) { + return NULL; + } + + Count = 0; + do { + Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record); + + if (EFI_ERROR (Status)) { + break; + } + + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) { + // + // This record is what we need + // + DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) { + ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1); + if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) { + EfiLibGetStringFromToken (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc); + return Desc; + } + } + + if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) { + Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1); + if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) { + EfiLibGetStringFromToken (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc); + return Desc; + } + } + } + + } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0); + + return NULL; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni new file mode 100644 index 0000000000..f646d8b331 Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni differ diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.c new file mode 100644 index 0000000000..0f5087ad98 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.c @@ -0,0 +1,1315 @@ +/*++ + +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: + + BootMaint.c + +Abstract: + + Boot Maintainence Main File + +--*/ + +#include "Bds.h" +#include "BootMaint.h" +#include "FormGuid.h" + +// +// Form binary for Boot Maintenance +// +extern UINT8 BmBin[]; +extern UINT8 FEBin[]; +extern EFI_GUID gBdsStringPackGuid; +extern BOOLEAN gConnectAllHappened; + +EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID; + +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +FreeAllMenu ( + VOID + ); + +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ) +/*++ +Routine Description: + + Create string tokens for a menu from its help strings and display strings + +Arguments: + + HiiHandle - Hii Handle of the package to be updated. + + MenuOption - The Menu whose string tokens need to be created + +Returns: + + EFI_SUCCESS - string tokens created successfully + + others - contain some errors + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + HiiHandle, + &NewMenuEntry->DisplayStringToken, + NewMenuEntry->DisplayString + ); + + if (NULL == NewMenuEntry->HelpString) { + NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; + } else { + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + HiiHandle, + &NewMenuEntry->HelpStringToken, + NewMenuEntry->HelpString + ); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DriverCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ +Routine Description: + + Callback Function for boot maintenance utility user interface interaction. + +Arguments: + + This - File explorer callback protocol pointer. + KeyValue - Key value to identify the type of data to expect. + Data - A pointer to the data being sent to the original exporting driver. + Packet - A pointer to a packet of information which a driver passes back to the browser. + +Returns: + + EFI_SUCCESS - Callback ended successfully. + Others - Contain some errors. + +--*/ +{ + BMM_CALLBACK_DATA *Private; + BM_MENU_ENTRY *NewMenuEntry; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + EFI_STATUS Status; + UINTN OldValue; + UINTN NewValue; + UINTN Number; + UINTN Pos; + UINTN Bit; + UINT16 NewValuePos; + UINT16 Index2; + UINT16 Index; + UINT8 *OldLegacyDev; + UINT8 *NewLegacyDev; + UINT8 *Location; + UINT8 *DisMap; + FORM_ID FormId; + + OldValue = 0; + NewValue = 0; + Number = 0; + OldLegacyDev = NULL; + NewLegacyDev = NULL; + NewValuePos = 0; + DisMap = NULL; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->BmmCallbackHandle; + CurrentFakeNVMap = (BMM_FAKE_NV_DATA *) Data->NvRamMap; + Private->BmmFakeNvData = CurrentFakeNVMap; + Location = (UINT8 *) &UpdateData->Data; + + UpdatePageId (Private, KeyValue); + + // + // need to be subtituded. + // + // Update Select FD/HD/CD/NET/BEV Order Form + // + if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId || + ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) && + (KeyValue >= LEGACY_FD_QUESTION_ID) && + (KeyValue < (LEGACY_BEV_QUESTION_ID + 100)) ) + ) { + + DisMap = Private->BmmOldFakeNVData.DisableMap; + + FormId = Private->BmmPreviousPageId; + if (FormId == FORM_BOOT_SETUP_ID) { + FormId = Private->BmmCurrentPageId; + } + + switch (FormId) { + case FORM_SET_FD_ORDER_ID: + Number = (UINT16) LegacyFDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; + NewLegacyDev = CurrentFakeNVMap->LegacyFD; + break; + + case FORM_SET_HD_ORDER_ID: + Number = (UINT16) LegacyHDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; + NewLegacyDev = CurrentFakeNVMap->LegacyHD; + break; + + case FORM_SET_CD_ORDER_ID: + Number = (UINT16) LegacyCDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; + NewLegacyDev = CurrentFakeNVMap->LegacyCD; + break; + + case FORM_SET_NET_ORDER_ID: + Number = (UINT16) LegacyNETMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; + NewLegacyDev = CurrentFakeNVMap->LegacyNET; + break; + + case FORM_SET_BEV_ORDER_ID: + Number = (UINT16) LegacyBEVMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; + NewLegacyDev = CurrentFakeNVMap->LegacyBEV; + break; + + default: + break; + } + // + // First, find the different position + // if there is change, it should be only one + // + for (Index = 0; Index < Number; Index++) { + if (OldLegacyDev[Index] != NewLegacyDev[Index]) { + OldValue = OldLegacyDev[Index]; + NewValue = NewLegacyDev[Index]; + break; + } + } + + if (Index != Number) { + // + // there is change, now process + // + if (0xFF == NewValue) { + // + // This item will be disable + // Just move the items behind this forward to overlap it + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] |= (UINT8) (1 << Bit); + for (Index2 = Index; Index2 < Number - 1; Index2++) { + NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; + } + + NewLegacyDev[Index2] = 0xFF; + } else { + for (Index2 = 0; Index2 < Number; Index2++) { + if (Index2 == Index) { + continue; + } + + if (OldLegacyDev[Index2] == NewValue) { + // + // If NewValue is in OldLegacyDev array + // remember its old position + // + NewValuePos = Index2; + break; + } + } + + if (Index2 != Number) { + // + // We will change current item to an existing item + // (It's hard to describe here, please read code, it's like a cycle-moving) + // + for (Index2 = NewValuePos; Index2 != Index;) { + if (NewValuePos < Index) { + NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; + Index2++; + } else { + NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; + Index2--; + } + } + } else { + // + // If NewValue is not in OldlegacyDev array, we are changing to a disabled item + // so we should modify DisMap to reflect the change + // + Pos = NewValue / 8; + Bit = 7 - (NewValue % 8); + DisMap[Pos] &= ~ (UINT8) (1 << Bit); + if (0xFF != OldValue) { + // + // Because NewValue is a item that was disabled before + // so after changing the OldValue should be disabled + // actually we are doing a swap of enable-disable states of two items + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] |= (UINT8) (1 << Bit); + } + } + } + // + // To prevent DISABLE appears in the middle of the list + // we should perform a re-ordering + // + Index = 0; + while (Index < Number) { + if (0xFF != NewLegacyDev[Index]) { + Index++; + continue; + } + + Index2 = Index; + Index2++; + while (Index2 < Number) { + if (0xFF != NewLegacyDev[Index2]) { + break; + } + + Index2++; + } + + if (Index2 < Number) { + NewLegacyDev[Index] = NewLegacyDev[Index2]; + NewLegacyDev[Index2] = 0xFF; + } + + Index++; + } + + CopyMem ( + OldLegacyDev, + NewLegacyDev, + Number + ); + } + } + + if (KeyValue < FILE_OPTION_OFFSET) { + if (KeyValue < NORMAL_GOTO_OFFSET) { + switch (KeyValue) { + case KEY_VALUE_BOOT_FROM_FILE: + Private->FeCurrentState = BOOT_FROM_FILE_STATE; + + // + // Exit Bmm main formset to send File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + + break; + + case FORM_BOOT_ADD_ID: + Private->FeCurrentState = ADD_BOOT_OPTION_STATE; + + // + // Exit Bmm main formset to send File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + break; + + case FORM_DRV_ADD_FILE_ID: + Private->FeCurrentState = ADD_DRIVER_OPTION_STATE; + + // + // Exit Bmm main formset to send File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + + break; + + case FORM_DRV_ADD_HANDLE_ID: + CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); + UpdateDrvAddHandlePage (Private); + break; + + case FORM_BOOT_DEL_ID: + CleanUpPage (FORM_BOOT_DEL_ID, Private); + UpdateBootDelPage (Private); + break; + + case FORM_BOOT_CHG_ID: + case FORM_DRV_CHG_ID: + UpdatePageBody (KeyValue, Private); + break; + + case FORM_DRV_DEL_ID: + CleanUpPage (FORM_DRV_DEL_ID, Private); + UpdateDrvDelPage (Private); + break; + + case FORM_BOOT_NEXT_ID: + CleanUpPage (FORM_BOOT_NEXT_ID, Private); + UpdateBootNextPage (Private); + break; + + case FORM_TIME_OUT_ID: + CleanUpPage (FORM_TIME_OUT_ID, Private); + UpdateTimeOutPage (Private); + break; + + case FORM_RESET: + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + return EFI_UNSUPPORTED; + + case FORM_CON_IN_ID: + case FORM_CON_OUT_ID: + case FORM_CON_ERR_ID: + UpdatePageBody (KeyValue, Private); + break; + + case FORM_CON_COM_ID: + CleanUpPage (FORM_CON_COM_ID, Private); + UpdateConCOMPage (Private); + break; + + case FORM_SET_FD_ORDER_ID: + case FORM_SET_HD_ORDER_ID: + case FORM_SET_CD_ORDER_ID: + case FORM_SET_NET_ORDER_ID: + case FORM_SET_BEV_ORDER_ID: + CleanUpPage (KeyValue, Private); + UpdateSetLegacyDeviceOrderPage (KeyValue, Private); + break; + + case KEY_VALUE_SAVE_AND_EXIT: + case KEY_VALUE_NO_SAVE_AND_EXIT: + + if (KeyValue == KEY_VALUE_SAVE_AND_EXIT) { + Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId); + if (EFI_ERROR (Status)) { + return Status; + } + } else if (KeyValue == KEY_VALUE_NO_SAVE_AND_EXIT) { + DiscardChangeHandler (Private, CurrentFakeNVMap); + } + // + // Tell browser not to ask for confirmation of changes, + // since we have already applied or discarded. + // + CreateCallbackPacket (Packet, NV_NOT_CHANGED); + break; + + default: + break; + } + } else if ((KeyValue >= TERMINAL_OPTION_OFFSET) && (KeyValue < CONSOLE_OPTION_OFFSET)) { + Index2 = (UINT16) (KeyValue - TERMINAL_OPTION_OFFSET); + Private->CurrentTerminal = Index2; + + CleanUpPage (FORM_CON_COM_SETUP_ID, Private); + UpdateTerminalPage (Private); + + } else if (KeyValue >= HANDLE_OPTION_OFFSET) { + Index2 = (UINT16) (KeyValue - HANDLE_OPTION_OFFSET); + + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); + Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + + CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); + + Private->MenuEntry = NewMenuEntry; + Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; + + UpdateDriverAddHandleDescPage (Private); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN FORM_ID FormId + ) +/*++ + +Routine Description: + + Function handling request to apply changes for BMM pages. + +Arguments: + + Private - Pointer to callback data buffer. + CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM + FormId - ID of the form which has sent the request to apply change. + +Returns: + + EFI_SUCCESS - Change successfully applied. + Other - Error occurs while trying to apply changes. + +--*/ +{ + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_LOAD_CONTEXT *NewLoadContext; + BM_MENU_ENTRY *NewMenuEntry; + EFI_STATUS Status; + UINT16 Index; + + Status = EFI_SUCCESS; + + switch (FormId) { + case FORM_SET_FD_ORDER_ID: + case FORM_SET_HD_ORDER_ID: + case FORM_SET_CD_ORDER_ID: + case FORM_SET_NET_ORDER_ID: + case FORM_SET_BEV_ORDER_ID: + Var_UpdateBBSOption (Private); + break; + + case FORM_BOOT_DEL_ID: + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index]; + } + + Var_DelBootOption (); + break; + + case FORM_DRV_DEL_ID: + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index]; + } + + Var_DelDriverOption (); + break; + + case FORM_BOOT_CHG_ID: + Status = Var_UpdateBootOrder (Private); + break; + + case FORM_DRV_CHG_ID: + Status = Var_UpdateDriverOrder (Private); + break; + + case FORM_TIME_OUT_ID: + Status = gRT->SetVariable ( + L"Timeout", + &gEfiGlobalVariableGuid, + VAR_FLAG, + sizeof (UINT16), + &(CurrentFakeNVMap->BootTimeOut) + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut; + break; + + case FORM_BOOT_NEXT_ID: + Status = Var_UpdateBootNext (Private); + break; + + case FORM_CON_COM_ID: + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate; + NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value; + NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate; + NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value; + NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits; + NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value; + NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity; + NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value; + NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType; + + ChangeTerminalDevicePath ( + NewTerminalContext->DevicePath, + FALSE + ); + + Var_UpdateConsoleInpOption (); + Var_UpdateConsoleOutOption (); + Var_UpdateErrorOutOption (); + break; + + case FORM_CON_IN_ID: + for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber]; + } + + Var_UpdateConsoleInpOption (); + break; + + case FORM_CON_OUT_ID: + for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber]; + } + + Var_UpdateConsoleOutOption (); + break; + + case FORM_CON_ERR_ID: + for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber]; + } + + Var_UpdateErrorOutOption (); + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + Status = Var_UpdateDriverOption ( + Private, + Private->BmmHiiHandle, + CurrentFakeNVMap->DriverAddHandleDesc, + CurrentFakeNVMap->DriverAddHandleOptionalData, + CurrentFakeNVMap->DriverAddForceReconnect + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu); + break; + + default: + break; + } + +Error: + return Status; +} + +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ) +{ + UINT16 Index; + + switch (Private->BmmPreviousPageId) { + case FORM_BOOT_CHG_ID: + case FORM_DRV_CHG_ID: + CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100); + break; + + case FORM_BOOT_DEL_ID: + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->BootOptionDel[Index] = 0x00; + } + break; + + case FORM_DRV_DEL_ID: + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->DriverOptionDel[Index] = 0x00; + } + break; + + case FORM_BOOT_NEXT_ID: + CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; + break; + + case FORM_TIME_OUT_ID: + CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + case FORM_DRV_ADD_FILE_ID: + case FORM_DRV_ADD_HANDLE_ID: + CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; + CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; + break; + + default: + break; + } +} + +EFI_STATUS +EFIAPI +NvWrite ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 Attributes OPTIONAL, + IN OUT UINTN DataSize, + OUT VOID *Buffer, + OUT BOOLEAN *ResetRequired + ) +{ + // + // Do nothing here. Just to catch the F10, we use "Apply Changes" tag to save. + // + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeBM ( + VOID + ) +/*++ +Routine Description: + + Initialize the Boot Maintenance Utitliy + +Arguments: + + ImageHandle - caller provided handle + + SystemTable - caller provided system tables + +Returns: + + EFI_SUCCESS - utility ended successfully + + others - contain some errors + +--*/ +{ + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_HII_PACKAGES *PackageList; + BMM_CALLBACK_DATA *BmmCallbackInfo; + EFI_HII_PROTOCOL *Hii; + EFI_HII_HANDLE HiiHandle; + EFI_STATUS Status; + EFI_HANDLE Handle; + UINT8 *Ptr; + UINT8 *Location; + + Status = EFI_SUCCESS; + UpdateData = NULL; + // + // Initialize EfiUtilityLib and EfiDriverLib + // Since many functions in UtilityLib must be used and + // SetupBrowser use DriverLib + // + // + // There should be only one EFI_HII_PROTOCOL Image + // + Status = EfiLibLocateProtocol (&gEfiHiiProtocolGuid, (VOID**)&Hii); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Create CallbackData structures for Driver Callback + // + BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); + if (!BmmCallbackInfo) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create LoadOption in BmmCallbackInfo for Driver Callback + // + Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); + if (!Ptr) { + SafeFreePool (BmmCallbackInfo); + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize Bmm callback data. + // + BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; + Ptr += sizeof (BM_LOAD_CONTEXT); + + BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; + Ptr += sizeof (BM_FILE_CONTEXT); + + BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; + Ptr += sizeof (BM_HANDLE_CONTEXT); + + BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; + + BmmCallbackInfo->BmmFakeNvData = &BmmCallbackInfo->BmmOldFakeNVData; + + ZeroMem (BmmCallbackInfo->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); + + BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; + BmmCallbackInfo->Hii = Hii; + BmmCallbackInfo->BmmDriverCallback.NvRead = NULL; + BmmCallbackInfo->BmmDriverCallback.NvWrite = NvWrite; + BmmCallbackInfo->BmmDriverCallback.Callback = DriverCallback; + BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; + BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; + BmmCallbackInfo->FeDriverCallback.NvRead = NULL; + BmmCallbackInfo->FeDriverCallback.NvWrite = NvWrite; + BmmCallbackInfo->FeDriverCallback.Callback = FileExplorerCallback; + BmmCallbackInfo->FeCurrentState = INACTIVE_STATE; + BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT; + + // + // Install bmm callback protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &BmmCallbackInfo->BmmDriverCallback + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + BmmCallbackInfo->BmmCallbackHandle = Handle; + + // + // Install file explorer callback protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &BmmCallbackInfo->FeDriverCallback + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + BmmCallbackInfo->FeCallbackHandle = Handle; + + // + // Post our VFR to the HII database. + // + PackageList = PreparePackages (1, &gBdsStringPackGuid, BmBin); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + BmmCallbackInfo->BmmHiiHandle = HiiHandle; + + PackageList = PreparePackages (1, &gBdsStringPackGuid, FEBin); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + BmmCallbackInfo->FeHiiHandle = HiiHandle; + + // + // Allocate space for creation of Buffer + // + UpdateData = AllocateZeroPool (UPDATE_DATA_SIZE); + if (!UpdateData) { + SafeFreePool (BmmCallbackInfo->LoadContext); + SafeFreePool (BmmCallbackInfo); + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize UpdateData structure + // + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) BmmCallbackInfo->BmmCallbackHandle, FALSE, 0, 0); + + Location = (UINT8 *) &UpdateData->Data; + + InitializeStringDepository (); + + InitAllMenu (BmmCallbackInfo); + + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); + + UpdateBootDelPage (BmmCallbackInfo); + UpdateDrvDelPage (BmmCallbackInfo); + + if (TerminalMenu.MenuNumber > 0) { + BmmCallbackInfo->CurrentTerminal = 0; + UpdateTerminalPage (BmmCallbackInfo); + } + + Location = (UINT8 *) &UpdateData->Data; + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios); + if (!EFI_ERROR (Status)) { + // + // If LegacyBios Protocol is installed, add 3 tags about legacy boot option + // in BootOption form: legacy FD/HD/CD/NET/BEV + // + UpdateData->DataCount = 5; + CreateGotoOpCode ( + FORM_SET_FD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_FD_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_HD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_HD_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_CD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_CD_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_NET_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_NET_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_BEV_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_BEV_ORDER_ID, + Location + ); + + Hii->UpdateForm ( + Hii, + BmmCallbackInfo->BmmHiiHandle, + (EFI_FORM_LABEL) FORM_BOOT_LEGACY_DEVICE_ID, + TRUE, + UpdateData + ); + } + // + // Dispatch BMM main formset and File Explorer formset. + // + FormSetDispatcher (BmmCallbackInfo); + + Hii->ResetStrings (Hii, HiiHandle); + + CleanUpStringDepository (); + + if (EFI_ERROR (Status)) { + return Status; + } + + FreeAllMenu (); + + SafeFreePool (BmmCallbackInfo->LoadContext); + BmmCallbackInfo->LoadContext = NULL; + SafeFreePool (BmmCallbackInfo); + BmmCallbackInfo = NULL; + SafeFreePool (UpdateData); + UpdateData = NULL; + + return Status; +} + +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + InitializeListHead (&BootOptionMenu.Head); + InitializeListHead (&DriverOptionMenu.Head); + BOpt_GetBootOptions (CallbackData); + BOpt_GetDriverOptions (CallbackData); + BOpt_GetLegacyOptions (); + InitializeListHead (&FsOptionMenu.Head); + BOpt_FindDrivers (); + InitializeListHead (&DirectoryMenu.Head); + InitializeListHead (&ConsoleInpMenu.Head); + InitializeListHead (&ConsoleOutMenu.Head); + InitializeListHead (&ConsoleErrMenu.Head); + InitializeListHead (&TerminalMenu.Head); + LocateSerialIo (); + GetAllConsoles (); +} + +VOID +FreeAllMenu ( + VOID + ) +{ + BOpt_FreeMenu (&DirectoryMenu); + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FreeMenu (&BootOptionMenu); + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_FreeMenu (&DriverMenu); + BOpt_FreeLegacyOptions (); + FreeAllConsoles (); +} + +VOID +InitializeStringDepository ( + VOID + ) +/*++ +Routine Description: + Intialize all the string depositories. + +Arguments: + None. + +Returns: + None. +--*/ +{ + STRING_DEPOSITORY *StringDepository; + StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); + FileOptionStrDepository = StringDepository++; + ConsoleOptionStrDepository = StringDepository++; + BootOptionStrDepository = StringDepository++; + BootOptionHelpStrDepository = StringDepository++; + DriverOptionStrDepository = StringDepository++; + DriverOptionHelpStrDepository = StringDepository++; + TerminalStrDepository = StringDepository; +} + +STRING_REF +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ) +/*++ +Routine Description: + Fetch a usable string node from the string depository and return the string token. + +Arguments: + StringDepository - Pointer of the string depository. + +Returns: + STRING_REF - String token. +--*/ +{ + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + + CurrentListNode = StringDepository->CurrentNode; + + if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { + // + // Fetch one reclaimed node from the list. + // + NextListNode = StringDepository->CurrentNode->Next; + } else { + // + // If there is no usable node in the list, update the list. + // + NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); + + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->BmmHiiHandle, + &(NextListNode->StringToken), + L" " + ); + + ASSERT (NextListNode->StringToken != 0); + + StringDepository->TotalNodeNumber++; + + if (NULL == CurrentListNode) { + StringDepository->ListHead = NextListNode; + } else { + CurrentListNode->Next = NextListNode; + } + } + + StringDepository->CurrentNode = NextListNode; + + return StringDepository->CurrentNode->StringToken; +} + +VOID +ReclaimStringDepository ( + VOID + ) +/*++ +Routine Description: + Reclaim string depositories by moving the current node pointer to list head.. + +Arguments: + None. + +Returns: + None. +--*/ +{ + UINTN DepositoryIndex; + STRING_DEPOSITORY *StringDepository; + + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + StringDepository->CurrentNode = StringDepository->ListHead; + StringDepository++; + } +} + +VOID +CleanUpStringDepository ( + VOID + ) +/*++ +Routine Description: + Release resource for all the string depositories. + +Arguments: + None. + +Returns: + None. +--*/ +{ + UINTN NodeIndex; + UINTN DepositoryIndex; + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + STRING_DEPOSITORY *StringDepository; + + // + // Release string list nodes. + // + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + CurrentListNode = StringDepository->ListHead; + for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { + NextListNode = CurrentListNode->Next; + SafeFreePool (CurrentListNode); + CurrentListNode = NextListNode; + } + + StringDepository++; + } + // + // Release string depository. + // + SafeFreePool (FileOptionStrDepository); +} + +EFI_STATUS +BdsStartBootMaint ( + VOID + ) +/*++ + +Routine Description: + Start boot maintenance manager + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY BdsBootOptionList; + + InitializeListHead (&BdsBootOptionList); + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + // + // Have chance to enumerate boot device + // + BdsLibEnumerateAllBootOption (&BdsBootOptionList); + + // + // Init the BMM + // + Status = InitializeBM (); + + return Status; +} + +EFI_STATUS +FormSetDispatcher ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description: + Dispatch BMM formset and FileExplorer formset. + +Arguments: + +Returns: + +--*/ +{ + EFI_FORM_BROWSER_PROTOCOL *FormConfig; + UINT8 *Location; + EFI_STATUS Status; + UINTN Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + BOOLEAN BootMaintMenuResetRequired; + + Location = NULL; + Index = 0; + NewMenuEntry = NULL; + NewFileContext = NULL; + + // + // There should only be one Form Configuration protocol + // + Status = EfiLibLocateProtocol (&gEfiFormBrowserProtocolGuid, (VOID**) &FormConfig); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + UpdatePageId (CallbackData, FORM_MAIN_ID); + + BootMaintMenuResetRequired = FALSE; + Status = FormConfig->SendForm ( + FormConfig, + TRUE, + &(CallbackData->BmmHiiHandle), + 1, + NULL, + NULL, + (UINT8 *) CallbackData->BmmFakeNvData, + NULL, + &BootMaintMenuResetRequired + ); + + if (BootMaintMenuResetRequired) { + EnableResetRequired (); + } + + ReclaimStringDepository (); + + // + // When this Formset returns, check if we are going to explore files. + // + if (INACTIVE_STATE != CallbackData->FeCurrentState) { + UpdateFileExplorer (CallbackData, 0); + + BootMaintMenuResetRequired = FALSE; + Status = FormConfig->SendForm ( + FormConfig, + TRUE, + &(CallbackData->FeHiiHandle), + 1, + NULL, + NULL, + NULL, + NULL, + &BootMaintMenuResetRequired + ); + + if (BootMaintMenuResetRequired) { + EnableResetRequired (); + } + + CallbackData->FeCurrentState = INACTIVE_STATE; + CallbackData->FeDisplayContext = UNKNOWN_CONTEXT; + ReclaimStringDepository (); + } else { + break; + } + } + + return Status; +} + +VOID +CreateCallbackPacket ( + OUT EFI_HII_CALLBACK_PACKET **Packet, + IN UINT16 Flags + ) +{ + *Packet = (EFI_HII_CALLBACK_PACKET *) AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2); + ASSERT (*Packet != NULL); + + (*Packet)->DataArray.EntryCount = 1; + (*Packet)->DataArray.NvRamMap = NULL; + ((EFI_IFR_DATA_ENTRY *) (&((*Packet)->DataArray) + 1))->Flags = Flags; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.h new file mode 100644 index 0000000000..6c3489f269 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.h @@ -0,0 +1,1161 @@ +/*++ + +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: + + BootMaint.h + +Abstract: + +Revision History + +--*/ + +#ifndef _BOOT_MAINT_H +#define _BOOT_MAINT_H + +#include "EdkGenericPlatformBdsLibStrDefs.h" +#include "BootMaint/BBSsupport.h" + +// +// Constants which are variable names used to access variables +// +#define VarLegacyDevOrder L"LegacyDevOrder" + +// +// Guid of a NV Variable which store the information about the +// FD/HD/CD/NET/BEV order +// +#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \ + { \ + 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 } \ + } + +// +// String Contant +// +#define StrFloppy L"Floppy Drive #%02x" +#define StrHardDisk L"HardDisk Drive #%02x" +#define StrCDROM L"ATAPI CDROM Drive #%02x" +#define StrNET L"NET Drive #%02x" +#define StrBEV L"BEV Drive #%02x" +#define StrFloppyHelp L"Select Floppy Drive #%02x" +#define StrHardDiskHelp L"Select HardDisk Drive #%02x" +#define StrCDROMHelp L"Select ATAPI CDROM Drive #%02x" +#define StrNETHelp L"NET Drive #%02x" +#define StrBEVHelp L"BEV Drive #%02x" + +// +// Constant will be used in display and file system navigation +// +#define UPDATE_DATA_SIZE 0x100000 +#define MAX_BBS_OFFSET 0xE000 +#define NET_OPTION_OFFSET 0xD800 +#define BEV_OPTION_OFFSET 0xD000 +#define FD_OPTION_OFFSET 0xC000 +#define HD_OPTION_OFFSET 0xB000 +#define CD_OPTION_OFFSET 0xA000 +#define FILE_OPTION_OFFSET 0x8000 +#define FILE_OPTION_MASK 0x7FFF +#define HANDLE_OPTION_OFFSET 0x7000 +#define CONSOLE_OPTION_OFFSET 0x0A00 +#define TERMINAL_OPTION_OFFSET 0x0700 +#define NORMAL_GOTO_OFFSET 0x0100 +#define MAX_STRING_TOKEN_COUNT 0x00FF +// +// Variable created with this flag will be "Efi:...." +// +#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE + +// +// Define Maxmim characters that will be accepted +// +#define MAX_CHAR 480 +#define MAX_CHAR_SIZE (MAX_CHAR * 2) + +// +// Check to see if current build support option active feature of +// some driver option +// +#ifndef LOAD_OPTION_ACTIVE +#define LOAD_OPTION_ACTIVE 0x00000001 +#endif +// +// Check to see if current build support force reconnect feature of +// some driver option +// +#ifndef LOAD_OPTION_FORCE_RECONNECT +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 +#endif +// +// Below are the form ids for display, form id is used as callback key value, +// some key value definitions are also defined here. By defining this enum type, +// We can easy know where we are. The int to UINT16 convertion should be ok because +// there is a MAXIMUM_FORM_ID which in within the range of UINT16. +// +typedef enum { + IplRelative, + BcvRelative +} BBS_TYPE; + +typedef enum { + FORM_RESERVED_ID = 0, + FORM_MAIN_ID, // 0x0001 + FORM_BOOT_ADD_ID, // 0x0002 + FORM_BOOT_DEL_ID, // 0x0003 + FORM_BOOT_CHG_ID, // 0x0004 + FORM_DRV_ADD_ID, // 0x0005 + FORM_DRV_DEL_ID, // 0x0006 + FORM_DRV_CHG_ID, // 0x0007 + FORM_CON_MAIN_ID, // 0x0008 + FORM_CON_IN_ID, // 0x0009 + FORM_CON_OUT_ID, // 0x000A + FORM_CON_ERR_ID, // 0x000B + FORM_FILE_SEEK_ID, // 0x000C + FORM_FILE_NEW_SEEK_ID, // 0x000D + FORM_DRV_ADD_FILE_ID, // 0x000E + FORM_DRV_ADD_HANDLE_ID, // 0x000F + FORM_DRV_ADD_HANDLE_DESC_ID, // 0x0010 + FORM_BOOT_NEXT_ID, // 0x0011 + FORM_TIME_OUT_ID, // 0x0012 + FORM_RESET, // 0x0013 + FORM_BOOT_SETUP_ID, // 0x0014 + FORM_DRIVER_SETUP_ID, // 0x0015 + FORM_BOOT_LEGACY_DEVICE_ID, // 0x0016 + FORM_CON_COM_ID, // 0x0017 + FORM_CON_COM_SETUP_ID, // 0x0018 + FORM_SET_FD_ORDER_ID, // 0x0019 + FORM_SET_HD_ORDER_ID, // 0x001A + FORM_SET_CD_ORDER_ID, // 0x001B + FORM_SET_NET_ORDER_ID, // 0x001C + FORM_SET_BEV_ORDER_ID, // 0x001D + FORM_FILE_EXPLORER_ID, // 0x001E + FORM_BOOT_ADD_DESCRIPTION_ID, // 0x001F + FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, // 0x0020 +} FORM_ID; + +#define MAXIMUM_FORM_ID 0x007F + +#define KEY_VALUE_COM_SET_BAUD_RATE 0x0080 +#define KEY_VALUE_COM_SET_DATA_BITS 0x0081 +#define KEY_VALUE_COM_SET_STOP_BITS 0x0082 +#define KEY_VALUE_COM_SET_PARITY 0x0083 +#define KEY_VALUE_COM_SET_TERMI_TYPE 0x0084 +#define KEY_VALUE_MAIN_BOOT_NEXT 0x0085 +#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x0086 +#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x0087 +#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x0088 +#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x0089 +#define KEY_VALUE_SAVE_AND_EXIT 0x0090 +#define KEY_VALUE_NO_SAVE_AND_EXIT 0x0091 +#define KEY_VALUE_BOOT_FROM_FILE 0x0092 + +#define MAXIMUM_NORMAL_KEY_VALUE NORMAL_GOTO_OFFSET +// +// Below are the number of options in Baudrate, Databits, +// Parity and Stopbits selection for serial ports. +// +#define BM_COM_ATTR_BUADRATE 19 +#define BM_COM_ATTR_DATABITS 4 +#define BM_COM_ATTR_PARITY 5 +#define BM_COM_ATTR_STOPBITS 3 + +// +// Callback function helper +// +#define BMM_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('C', 'b', 'c', 'k') +#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmDriverCallback, BMM_CALLBACK_DATA_SIGNATURE) + +#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeDriverCallback, BMM_CALLBACK_DATA_SIGNATURE) + +// +// Enumeration type definition +// +typedef enum { + PC_ANSI = 0, + VT_100, + VT_100_PLUS, + VT_UTF8 +} TYPE_OF_TERMINAL; + +typedef enum { + COM1 = 0, + COM2, + UNKNOW_COM +} TYPE_OF_COM; + +typedef enum { + CONIN = 0, + CONOUT, + CONERR, + UNKNOWN_CON +} TYPE_OF_CON; + +typedef enum { + BAUDRATE = 0, + DATABITS, + PARITY, + STOPBITS, + UNKNOW_ATTR +} TYPE_OF_ATTRIBUTE; + +typedef enum { + MANNER_GOTO = 0, + MANNER_CHECK, + MANNER_ONEOF, + MANNER_USER_DEFINE +} TYPE_OF_UPATE_MANNER; + +typedef enum { + INACTIVE_STATE = 0, + BOOT_FROM_FILE_STATE, + ADD_BOOT_OPTION_STATE, + ADD_DRIVER_OPTION_STATE, + UNKNOWN_STATE +} FILE_EXPLORER_STATE; + +typedef enum { + FILE_SYSTEM, + DIRECTORY, + UNKNOWN_CONTEXT +} FILE_EXPLORER_DISPLAY_CONTEXT; + +// +// All of the signatures that will be used in list structure +// +#define BM_MENU_OPTION_SIGNATURE EFI_SIGNATURE_32 ('m', 'e', 'n', 'u') +#define BM_LOAD_OPTION_SIGNATURE EFI_SIGNATURE_32 ('l', 'o', 'a', 'd') +#define BM_CONSOLE_OPTION_SIGNATURE EFI_SIGNATURE_32 ('c', 'n', 's', 'l') +#define BM_FILE_OPTION_SIGNATURE EFI_SIGNATURE_32 ('f', 'i', 'l', 'e') +#define BM_HANDLE_OPTION_SIGNATURE EFI_SIGNATURE_32 ('h', 'n', 'd', 'l') +#define BM_TERMINAL_OPTION_SIGNATURE EFI_SIGNATURE_32 ('t', 'r', 'm', 'l') +#define BM_MENU_ENTRY_SIGNATURE EFI_SIGNATURE_32 ('e', 'n', 't', 'r') + +#define BM_LOAD_CONTEXT_SELECT 0x0 +#define BM_CONSOLE_CONTEXT_SELECT 0x1 +#define BM_FILE_CONTEXT_SELECT 0x2 +#define BM_HANDLE_CONTEXT_SELECT 0x3 +#define BM_TERMINAL_CONTEXT_SELECT 0x5 + +#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6 +#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7 +#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8 +#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9 + +// +// Question Id that will be used to create question +// all these values are computed from the structure +// defined below +// +#define QUESTION_ID(Field) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)) + +#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut) +#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext) +#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate) +#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate) +#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits) +#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity) +#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate) +#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate) +#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits) +#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity) +#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc) +#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive) +#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect) +#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1) +#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2) +#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1) +#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2) +#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1) +#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2) +#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck) +#define OPTION_ORDER_QUESTION_ID QUESTION_ID (OptionOrder) +#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted) +#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel) +#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel) +#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData) +#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate) +#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate) +#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits) +#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity) +#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType) +#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) +#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) +#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) +#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) +#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) + +#define STRING_DEPOSITORY_NUMBER 8 + +// +// #pragma pack(1) +// +// Serial Ports attributes, first one is the value for +// return from callback function, stringtoken is used to +// display the value properly +// +typedef struct { + UINTN Value; + UINT16 StringToken; +} COM_ATTR; + +// +// This is the structure that will be used to store the +// question's current value. Use it at initialize time to +// set default value for each question. When using at run +// time, this map is returned by the callback function, +// so dynamically changing the question's value will be +// possible through this mechanism +// +typedef struct { + // + // Three questions displayed at the main page + // for Timeout, BootNext Variables respectively + // + UINT16 BootTimeOut; + UINT16 BootNext; + + // + // This is the COM1 Attributes value storage + // + UINT8 COM1BaudRate; + UINT8 COM1DataRate; + UINT8 COM1StopBits; + UINT8 COM1Parity; + UINT8 COM1TerminalType; + + // + // This is the COM2 Attributes value storage + // + UINT8 COM2BaudRate; + UINT8 COM2DataRate; + UINT8 COM2StopBits; + UINT8 COM2Parity; + UINT8 COM2TerminalType; + + // + // Driver Option Add Handle page storage + // + UINT16 DriverAddHandleDesc[100]; + UINT16 DriverAddHandleOptionalData[100]; + UINT8 DriverAddActive; + UINT8 DriverAddForceReconnect; + + // + // Console Input/Output/Errorout using COM port check storage + // + UINT8 ConsoleInputCOM1; + UINT8 ConsoleInputCOM2; + UINT8 ConsoleOutputCOM1; + UINT8 ConsoleOutputCOM2; + UINT8 ConsoleErrorCOM1; + UINT8 ConsoleErrorCOM2; + + // + // At most 100 input/output/errorout device for console storage + // + UINT8 ConsoleCheck[100]; + + // + // Boot or Driver Option Order storage + // + UINT8 OptionOrder[100]; + UINT8 DriverOptionToBeDeleted[100]; + + // + // Boot Option Delete storage + // + UINT8 BootOptionDel[100]; + UINT8 DriverOptionDel[100]; + + // + // This is the Terminal Attributes value storage + // + UINT8 COMBaudRate; + UINT8 COMDataRate; + UINT8 COMStopBits; + UINT8 COMParity; + UINT8 COMTerminalType; + + // + // Legacy Device Order Selection Storage + // + UINT8 LegacyFD[100]; + UINT8 LegacyHD[100]; + UINT8 LegacyCD[100]; + UINT8 LegacyNET[100]; + UINT8 LegacyBEV[100]; + + // + // We use DisableMap array to record the enable/disable state of each boot device + // It should be taken as a bit array, from left to right there are totally 256 bits + // the most left one stands for BBS table item 0, and the most right one stands for item 256 + // If the bit is 1, it means the boot device has been disabled. + // + UINT8 DisableMap[32]; + + // + // UINT16 PadArea[10]; + // +} BMM_FAKE_NV_DATA; + +typedef struct { + UINT16 DescriptionData[75]; + UINT16 OptionalData[127]; + UINT8 Active; + UINT8 ForceReconnect; +} FILE_EXPLORER_NV_DATA; + +typedef struct { + BBS_TYPE BbsType; + // + // Length = sizeof (UINT16) + SIZEOF (Data) + // + UINT16 Length; + UINT16 *Data; +} BM_LEGACY_DEV_ORDER_CONTEXT; + +typedef struct { + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; + + UINT8 BaudRateIndex; + UINT8 DataBitsIndex; + UINT8 ParityIndex; + UINT8 StopBitsIndex; + + UINT8 IsConIn; + UINT8 IsConOut; + UINT8 IsStdErr; + UINT8 TerminalType; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_TERMINAL_CONTEXT; + +typedef struct { + BOOLEAN IsBootNext; + BOOLEAN LoadOptionModified; + BOOLEAN Deleted; + + BOOLEAN IsLegacy; + BOOLEAN IsActive; + BOOLEAN ForceReconnect; + UINTN OptionalDataSize; + + UINTN LoadOptionSize; + UINT8 *LoadOption; + + UINT32 Attributes; + UINT16 FilePathListLength; + UINT16 *Description; + EFI_DEVICE_PATH_PROTOCOL *FilePathList; + UINT8 *OptionalData; + + UINT16 BbsIndex; +} BM_LOAD_CONTEXT; + +typedef struct { + BBS_TABLE *BbsTable; + UINTN Index; + UINTN BbsCount; + UINT16 *Description; +} BM_LEGACY_DEVICE_CONTEXT; + +typedef struct { + + BOOLEAN IsActive; + + BOOLEAN IsTerminal; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_CONSOLE_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info; + + BOOLEAN IsRoot; + BOOLEAN IsDir; + BOOLEAN IsRemovableMedia; + BOOLEAN IsLoadFile; + BOOLEAN IsBootLegacy; +} BM_FILE_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_HANDLE_CONTEXT; + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} BM_MENU_OPTION; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + STRING_REF DisplayStringToken; + STRING_REF HelpStringToken; + UINTN ContextSelection; + VOID *VariableContext; +} BM_MENU_ENTRY; + +typedef struct { + // + // Shared callback data. + // + UINTN Signature; + EFI_HII_PROTOCOL *Hii; + BM_MENU_ENTRY *MenuEntry; + BM_HANDLE_CONTEXT *HandleContext; + BM_FILE_CONTEXT *FileContext; + BM_LOAD_CONTEXT *LoadContext; + BM_TERMINAL_CONTEXT *TerminalContext; + UINTN CurrentTerminal; + BBS_TYPE BbsType; + + // + // BMM main formset callback data. + // + EFI_HII_HANDLE BmmHiiHandle; + EFI_HANDLE BmmCallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL BmmDriverCallback; + FORM_ID BmmCurrentPageId; + FORM_ID BmmPreviousPageId; + BOOLEAN BmmAskSaveOrNot; + BMM_FAKE_NV_DATA *BmmFakeNvData; + BMM_FAKE_NV_DATA BmmOldFakeNVData; + + // + // File explorer formset callback data. + // + EFI_HII_HANDLE FeHiiHandle; + EFI_HANDLE FeCallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL FeDriverCallback; + FILE_EXPLORER_STATE FeCurrentState; + FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext; +} BMM_CALLBACK_DATA; + +typedef struct _STRING_LIST_NODE { + STRING_REF StringToken; + struct _STRING_LIST_NODE *Next; +} STRING_LIST_NODE; + +typedef struct _STRING_DEPOSITORY { + UINTN TotalNodeNumber; + STRING_LIST_NODE *CurrentNode; + STRING_LIST_NODE *ListHead; +} STRING_DEPOSITORY; + +// +// #pragma pack() +// +// For initializing File System menu +// +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ) +; + +// +// For cleaning up File System menu +// +VOID +BOpt_FreeFileSystem ( + VOID + ) +; + +// +// For initializing File Navigation menu +// +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ) +; + +// +// For cleaning up File Navigation menu +// +VOID +BOpt_FreeFiles ( + VOID + ) +; + +// +// For Initializing handle navigation menu +// +EFI_STATUS +BOpt_FindDrivers ( + VOID + ) +; + +// +// For Cleaning up handle navigation menu +// +VOID +BOpt_FreeDrivers(); + +// +// For initializing Boot Option menu +// +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// For Initializing Driver option menu +// +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// For Cleaning up boot option menu +// +VOID +BOpt_FreeBootOptions (); + +// +// For cleaning up driver option menu +// +VOID +BOpt_FreeDriverOptions(); + +// +// For Initializing HD/FD/CD/NET/BEV option menu +// +EFI_STATUS +BOpt_GetLegacyOptions(); + +// +// For cleaning up driver option menu +// +VOID +BOpt_FreeLegacyOptions(); + +// +// this function is used to take place of all other free menu actions +// +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ); + + +// +// Following are the helper functions used +// +CHAR16 * +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ); + +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ); + +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ); + +// +// Get current unused boot option number +// +UINT16 +BOpt_GetBootOptionNumber (); + +// +// Get current unused driver option number +// +UINT16 +BOpt_GetDriverOptionNumber (); + +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ); + +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ); + +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ); + +// +// a helper function used to free pool type memory +// +VOID +SafeFreePool ( + IN VOID *Buffer + ); + +// +// Locate all serial io devices for console +// +EFI_STATUS +LocateSerialIo (); + +// +// Initializing Console menu +// +EFI_STATUS +GetAllConsoles(); + +// +// Cleaning up console menu +// +EFI_STATUS +FreeAllConsoles(); + +VOID +ChangeVariableDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath +); + +EFI_STATUS +ChangeTerminalDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + BOOLEAN ChangeTerminal +); +// +// Variable operation by menu selection +// +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ); + +EFI_STATUS +Var_DelBootOption (); + +EFI_STATUS +Var_ChangeBootOrder (); + +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ); + +EFI_STATUS +Var_DelDriverOption (); + +EFI_STATUS +Var_ChangeDriverOrder (); + +EFI_STATUS +Var_UpdateConsoleInpOption (); + +EFI_STATUS +Var_UpdateConsoleOutOption (); + +EFI_STATUS +Var_UpdateErrorOutOption (); + +VOID +Var_UpdateAllConsoleOption (); + +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +Var_UpdateBBSOption ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Following are page create and refresh functions +// +VOID +RefreshUpdateData ( + IN BOOLEAN FormSetUpdate, + IN EFI_PHYSICAL_ADDRESS FormCallbackHandle, + IN BOOLEAN FormUpdate, + IN STRING_REF FormTitle, + IN UINT16 DataCount + ); + +VOID +CleanUpPage ( + IN EFI_FORM_LABEL LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +UpdatePage ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_OPTION *UpdatingMenu, + IN UINT16 UpdatingPage, + IN UINT16 UpdatingManner, + IN UINT16 QuestionIdStart, + IN UINT16 GotoForm, + IN UINT16 GotoAlternateForm, + IN STRING_REF DisplayTokenStart, + IN STRING_REF HelpTokenStart, + IN UINT16 KeyValueStart + ); + +VOID +UpdateBootAddPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDrvAddFilePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootTimeOut ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateConInPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateConOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateStdErrPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateCOM1Page ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateCOM2Page ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootOrderPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDriverOrderPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateSetLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData +); + +EFI_STATUS +BootLegacy ( + IN UINT16 BbsType, + IN UINT16 BbsFlag +); + +BM_MENU_ENTRY * +GetCurrentTerminal ( + UINTN TerminalNumber +); + +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ); + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ); + +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ); + +VOID * +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +VOID * +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize + ); + +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ); + +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ); + +BOOLEAN +EfiLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ); + +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +VOID * +GetLegacyBootOptionVar ( + IN UINTN DeviceType, + OUT UINTN *OptionIndex, + OUT UINTN *OptionSize + ); + +EFI_STATUS +InitializeBM ( + VOID + ); + +EFI_STATUS +BdsStartBootMaint ( + VOID + ); + +VOID +InitializeStringDepository (); + +STRING_REF +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ) ; + +VOID +ReclaimStringDepository ( + VOID + ); + +VOID +CleanUpStringDepository ( + VOID + ); + +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN FORM_ID FormId + ); + +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ); + +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ); + +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ); + +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ); + +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ); + +EFI_STATUS +FormSetDispatcher ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID CreateCallbackPacket ( + OUT EFI_HII_CALLBACK_PACKET **Packet, + IN UINT16 Flags + ); + +// +// Global variable in this program (defined in data.c) +// +extern BM_MENU_OPTION BootOptionMenu; +extern BM_MENU_OPTION DriverOptionMenu; +extern BM_MENU_OPTION FsOptionMenu; +extern BM_MENU_OPTION ConsoleInpMenu; +extern BM_MENU_OPTION ConsoleOutMenu; +extern BM_MENU_OPTION ConsoleErrMenu; +extern BM_MENU_OPTION DirectoryMenu; +extern BM_MENU_OPTION DriverMenu; +extern BM_MENU_OPTION TerminalMenu; +extern BM_MENU_OPTION LegacyFDMenu; +extern BM_MENU_OPTION LegacyHDMenu; +extern BM_MENU_OPTION LegacyCDMenu; +extern BM_MENU_OPTION LegacyNETMenu; +extern BM_MENU_OPTION LegacyBEVMenu; +extern UINT16 TerminalType[]; +extern COM_ATTR BaudRateList[19]; +extern COM_ATTR DataBitsList[4]; +extern COM_ATTR ParityList[5]; +extern COM_ATTR StopBitsList[3]; +extern EFI_GUID Guid[4]; +extern EFI_HII_UPDATE_DATA *UpdateData; +extern STRING_DEPOSITORY *FileOptionStrDepository; +extern STRING_DEPOSITORY *ConsoleOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionHelpStrDepository; +extern STRING_DEPOSITORY *DriverOptionStrDepository; +extern STRING_DEPOSITORY *DriverOptionHelpStrDepository; +extern STRING_DEPOSITORY *TerminalStrDepository; +extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[]; +extern EFI_GUID EfiLegacyDevOrderGuid; + +#endif diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootOption.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootOption.c new file mode 100644 index 0000000000..2d67e0b94a --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootOption.c @@ -0,0 +1,1685 @@ +/*++ +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: + + BootOption.c + +Abstract: + + Provide boot option support for Application "BootMaint" + + Include file system navigation, system handle selection + + Boot option manipulation + +Revision History + +--*/ + +#include "BootMaint.h" +#include "BBSsupport.h" + +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ) +/*++ + +Routine Description + Create Menu Entry for future use, make all types together + in order to reduce code size + +Arguments: + MenuType Use this parameter to identify current + Menu type + +Returns: + NULL Cannot allocate memory for current menu + entry + Others A valid pointer pointing to the allocated + memory pool for current menu entry + +--*/ +{ + BM_MENU_ENTRY *MenuEntry; + UINTN ContextSize; + + switch (MenuType) { + case BM_LOAD_CONTEXT_SELECT: + ContextSize = sizeof (BM_LOAD_CONTEXT); + break; + + case BM_FILE_CONTEXT_SELECT: + ContextSize = sizeof (BM_FILE_CONTEXT); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_CONSOLE_CONTEXT); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + ContextSize = sizeof (BM_TERMINAL_CONTEXT); + break; + + case BM_HANDLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_HANDLE_CONTEXT); + break; + + case BM_LEGACY_DEV_CONTEXT_SELECT: + ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT); + break; + + default: + ContextSize = 0; + break; + + } + + if (0 == ContextSize) { + return NULL; + } + + MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); + if (NULL == MenuEntry) { + return MenuEntry; + } + + MenuEntry->VariableContext = AllocateZeroPool (ContextSize); + if (NULL == MenuEntry->VariableContext) { + SafeFreePool (MenuEntry); + MenuEntry = NULL; + return MenuEntry; + } + + MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE; + MenuEntry->ContextSelection = MenuType; + return MenuEntry; +} + +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ) +/*++ + Routine Description : + Destroy the menu entry passed in + + Arguments : + The menu entry need to be destroyed + + Returns : + None + +--*/ +{ + BM_LOAD_CONTEXT *LoadContext; + BM_FILE_CONTEXT *FileContext; + BM_CONSOLE_CONTEXT *ConsoleContext; + BM_TERMINAL_CONTEXT *TerminalContext; + BM_HANDLE_CONTEXT *HandleContext; + BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext; + + // + // Select by the type in Menu entry for current context type + // + switch (MenuEntry->ContextSelection) { + case BM_LOAD_CONTEXT_SELECT: + LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (LoadContext->FilePathList); + SafeFreePool (LoadContext->LoadOption); + SafeFreePool (LoadContext->OptionalData); + SafeFreePool (LoadContext); + break; + + case BM_FILE_CONTEXT_SELECT: + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + if (!FileContext->IsRoot) { + SafeFreePool (FileContext->DevicePath); + } else { + if (FileContext->FHandle != NULL) { + FileContext->FHandle->Close (FileContext->FHandle); + } + } + + SafeFreePool (FileContext->FileName); + SafeFreePool (FileContext->Info); + SafeFreePool (FileContext); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (ConsoleContext->DevicePath); + SafeFreePool (ConsoleContext); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (TerminalContext->DevicePath); + SafeFreePool (TerminalContext); + break; + + case BM_HANDLE_CONTEXT_SELECT: + HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (HandleContext); + break; + + case BM_LEGACY_DEV_CONTEXT_SELECT: + LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (LegacyDevContext); + + default: + break; + } + + SafeFreePool (MenuEntry->DisplayString); + if (NULL != MenuEntry->HelpString) { + SafeFreePool (MenuEntry->HelpString); + } + + SafeFreePool (MenuEntry); +} + +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +/*++ + Rountine Description : + Use this routine to get one particular menu entry in specified + menu + + Arguments : + MenuOption The menu that we will search + + MenuNumber The menunubmer that we want + + Returns : + The desired menu entry + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + if (MenuNumber >= MenuOption->MenuNumber) { + return NULL; + } + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description + Find file systems for current Extensible Firmware + Including Handles that support Simple File System + protocol, Load File protocol. + + Building up the FileSystem Menu for user selection + All file system will be stored in FsOptionMenu + for future use. + +Arguments: + CallbackData - BMM context data + +Returns: + EFI_SUCCESS - Success find the file system + EFI_OUT_OF_RESOURCES - Can not create menu entry + +--*/ +{ + UINTN NoSimpleFsHandles; + UINTN NoLoadFileHandles; + EFI_HANDLE *SimpleFsHandle; + EFI_HANDLE *LoadFileHandle; + UINT16 *VolumeLabel; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *MenuEntry; + BM_FILE_CONTEXT *FileContext; + UINT16 *TempStr; + UINTN OptionNumber; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 DeviceType; + BBS_BBS_DEVICE_PATH BbsDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN RemovableMedia; + + + NoSimpleFsHandles = 0; + NoLoadFileHandles = 0; + OptionNumber = 0; + InitializeListHead (&FsOptionMenu.Head); + + // + // Locate Handles that support Simple File System protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NoSimpleFsHandles, + &SimpleFsHandle + ); + if (!EFI_ERROR (Status)) { + // + // Find all the instances of the File System prototocol + // + for (Index = 0; Index < NoSimpleFsHandles; Index++) { + Status = gBS->HandleProtocol ( + SimpleFsHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID**) &BlkIo + ); + if (EFI_ERROR (Status)) { + // + // If no block IO exists assume it's NOT a removable media + // + RemovableMedia = FALSE; + } else { + // + // If block IO exists check to see if it's remobable media + // + RemovableMedia = BlkIo->Media->RemovableMedia; + } + + // + // Allocate pool for this load option + // + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + SafeFreePool (SimpleFsHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->Handle = SimpleFsHandle[Index]; + MenuEntry->OptionNumber = Index; + FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle); + if (!FileContext->FHandle) { + BOpt_DestroyMenuEntry (MenuEntry); + continue; + } + + MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle)); + FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle); + FileContext->FileName = EfiStrDuplicate (L"\\"); + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + FileContext->IsDir = TRUE; + FileContext->IsRoot = TRUE; + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = FALSE; + + // + // Get current file system's Volume Label + // + if (FileContext->Info == NULL) { + VolumeLabel = L"NO FILE SYSTEM INFO"; + } else { + if (FileContext->Info->VolumeLabel == NULL) { + VolumeLabel = L"NULL VOLUME LABEL"; + } else { + VolumeLabel = FileContext->Info->VolumeLabel; + if (*VolumeLabel == 0x0000) { + VolumeLabel = L"NO VOLUME LABEL"; + } + } + } + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"%s, [%s]", + VolumeLabel, + TempStr + ); + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoSimpleFsHandles != 0) { + SafeFreePool (SimpleFsHandle); + } + // + // Searching for handles that support Load File protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadFileProtocolGuid, + NULL, + &NoLoadFileHandles, + &LoadFileHandle + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoLoadFileHandles; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + SafeFreePool (LoadFileHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->Handle = LoadFileHandle[Index]; + FileContext->IsRoot = TRUE; + + FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle); + + MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Load File [%s]", + TempStr + ); + + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoLoadFileHandles != 0) { + SafeFreePool (LoadFileHandle); + } + + // + // Add Legacy Boot Option Support Here + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID**) &LegacyBios + ); + if (!EFI_ERROR (Status)) { + + for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->IsBootLegacy = TRUE; + DeviceType = (UINT16) Index; + BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevicePathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength ( + &BbsDevicePathNode.Header, + sizeof (BBS_BBS_DEVICE_PATH) + ); + BbsDevicePathNode.DeviceType = DeviceType; + BbsDevicePathNode.StatusFlag = 0; + BbsDevicePathNode.String[0] = 0; + DevicePath = AppendDevicePathNode ( + EndDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode + ); + + FileContext->DevicePath = DevicePath; + MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Boot Legacy [%s]", + TempStr + ); + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + // + // Remember how many file system options are here + // + FsOptionMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ) +/*++ + +Routine Description + Free resources allocated in Allocate Rountine + +Arguments: + FreeMenu Menu to be freed + +Returns: + VOID + +--*/ +{ + BM_MENU_ENTRY *MenuEntry; + while (!IsListEmpty (&FreeMenu->Head)) { + MenuEntry = CR ( + FreeMenu->Head.ForwardLink, + BM_MENU_ENTRY, + Link, + BM_MENU_ENTRY_SIGNATURE + ); + RemoveEntryList (&MenuEntry->Link); + BOpt_DestroyMenuEntry (MenuEntry); + } +} + +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ) +/*++ + +Routine Description + Find files under current directory + All files and sub-directories in current directory + will be stored in DirectoryMenu for future use. + +Arguments: + FileOption -- Pointer for Dir to explore + +Returns: + TRUE -- Get files from current dir successfully + FALSE -- Can't get files from current dir + +--*/ +{ + EFI_FILE_HANDLE NewDir; + EFI_FILE_HANDLE Dir; + EFI_FILE_INFO *DirInfo; + UINTN BufferSize; + UINTN DirBufferSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *FileContext; + BM_FILE_CONTEXT *NewFileContext; + UINTN Pass; + EFI_STATUS Status; + UINTN OptionNumber; + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + Dir = FileContext->FHandle; + OptionNumber = 0; + // + // Open current directory to get files from it + // + Status = Dir->Open ( + Dir, + &NewDir, + FileContext->FileName, + EFI_FILE_READ_ONLY, + 0 + ); + if (!FileContext->IsRoot) { + Dir->Close (Dir); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + DirInfo = EfiLibFileInfo (NewDir); + if (!DirInfo) { + return EFI_NOT_FOUND; + } + + if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) { + return EFI_INVALID_PARAMETER; + } + + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + + DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; + DirInfo = AllocateZeroPool (DirBufferSize); + if (!DirInfo) { + return EFI_OUT_OF_RESOURCES; + } + // + // Get all files in current directory + // Pass 1 to get Directories + // Pass 2 to get files that are EFI images + // + for (Pass = 1; Pass <= 2; Pass++) { + NewDir->SetPosition (NewDir, 0); + for (;;) { + BufferSize = DirBufferSize; + Status = NewDir->Read (NewDir, &BufferSize, DirInfo); + if (EFI_ERROR (Status) || BufferSize == 0) { + break; + } + + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) || + (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1) + ) { + // + // Pass 1 is for Directories + // Pass 2 is for file names + // + continue; + } + + if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) { + // + // Slip file unless it is a directory entry or a .EFI file + // + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + NewFileContext->Handle = FileContext->Handle; + NewFileContext->FileName = BOpt_AppendFileName ( + FileContext->FileName, + DirInfo->FileName + ); + NewFileContext->FHandle = NewDir; + NewFileContext->DevicePath = FileDevicePath ( + NewFileContext->Handle, + NewFileContext->FileName + ); + NewMenuEntry->HelpString = NULL; + + MenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + FileOptionStrDepository + ); + + NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); + + if (NewFileContext->IsDir) { + BufferSize = StrLen (DirInfo->FileName) * 2 + 6; + NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); + + UnicodeSPrint ( + NewMenuEntry->DisplayString, + BufferSize, + L"<%s>", + DirInfo->FileName + ); + + } else { + NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName); + } + + NewFileContext->IsRoot = FALSE; + NewFileContext->IsLoadFile = FALSE; + NewFileContext->IsRemovableMedia = FALSE; + + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); + } + } + + DirectoryMenu.MenuNumber = OptionNumber; + SafeFreePool (DirInfo); + return TRUE; +} + +EFI_STATUS +BOpt_GetLegacyOptions ( + VOID + ) +/*++ +Routine Description: + + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). + +Arguments: + None + +Returns: + The device info of legacy device. + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 HddCount; + HDD_INFO *HddInfo; + UINT16 BbsCount; + BBS_TABLE *BbsTable; + UINTN Index; + CHAR16 DescString[100]; + UINTN FDNum; + UINTN HDNum; + UINTN CDNum; + UINTN NETNum; + UINTN BEVNum; + + NewMenuEntry = NULL; + HddInfo = NULL; + BbsTable = NULL; + BbsCount = 0; + + // + // Initialize Bbs Table Context from BBS info data + // + InitializeListHead (&LegacyFDMenu.Head); + InitializeListHead (&LegacyHDMenu.Head); + InitializeListHead (&LegacyCDMenu.Head); + InitializeListHead (&LegacyNETMenu.Head); + InitializeListHead (&LegacyBEVMenu.Head); + + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + (VOID**) &LegacyBios + ); + if (!EFI_ERROR (Status)) { + Status = LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + FDNum = 0; + HDNum = 0; + CDNum = 0; + NETNum = 0; + BEVNum = 0; + + for (Index = 0; Index < BbsCount; Index++) { + if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) || + (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority) || + (BBS_LOWEST_PRIORITY == BbsTable[Index].BootPriority) + ) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + break; + } + + NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; + NewLegacyDevContext->BbsTable = &BbsTable[Index]; + NewLegacyDevContext->Index = Index; + NewLegacyDevContext->BbsCount = BbsCount; + BdsBuildLegacyDevNameString ( + &BbsTable[Index], + Index, + sizeof (DescString), + DescString + ); + NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString)); + if (NULL == NewLegacyDevContext->Description) { + break; + } + + CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString)); + NewMenuEntry->DisplayString = NewLegacyDevContext->Description; + NewMenuEntry->HelpString = NULL; + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); + FDNum++; + break; + + case BBS_HARDDISK: + InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); + HDNum++; + break; + + case BBS_CDROM: + InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); + CDNum++; + break; + + case BBS_EMBED_NETWORK: + InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); + NETNum++; + break; + + case BBS_BEV_DEVICE: + InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); + BEVNum++; + break; + } + } + + if (Index != BbsCount) { + BOpt_FreeLegacyOptions (); + return EFI_OUT_OF_RESOURCES; + } + + LegacyFDMenu.MenuNumber = FDNum; + LegacyHDMenu.MenuNumber = HDNum; + LegacyCDMenu.MenuNumber = CDNum; + LegacyNETMenu.MenuNumber = NETNum; + LegacyBEVMenu.MenuNumber = BEVNum; + return EFI_SUCCESS; +} + +VOID +BOpt_FreeLegacyOptions ( + VOID + ) +{ + BOpt_FreeMenu (&LegacyFDMenu); + BOpt_FreeMenu (&LegacyHDMenu); + BOpt_FreeMenu (&LegacyCDMenu); + BOpt_FreeMenu (&LegacyNETMenu); + BOpt_FreeMenu (&LegacyBEVMenu); +} + +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description: + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION + +Arguments: + None + +Returns: + The number of the Var Boot#### + +--*/ +{ + UINTN Index; + UINT16 BootString[10]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN BootOptionSize; + BOOLEAN BootNextFlag; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 *BootNext; + UINTN BootNextSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN MenuCount; + UINT8 *Ptr; + + MenuCount = 0; + BootOrderListSize = 0; + BootNextSize = 0; + BootOrderList = NULL; + BootNext = NULL; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&BootOptionMenu); + InitializeListHead (&BootOptionMenu.Head); + + // + // Get the BootOrder from the Var + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + + // + // Get the BootNext from the Var + // + BootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + if (BootNext) { + if (BootNextSize != sizeof (UINT16)) { + SafeFreePool (BootNext); + BootNext = NULL; + } + } + + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); + // + // Get all loadoptions from the VAR + // + LoadOptionFromVar = BdsLibGetVariableAndSize ( + BootString, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (!LoadOptionFromVar) { + continue; + } + + LoadOption = AllocateZeroPool (BootOptionSize); + if (!LoadOption) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize); + SafeFreePool (LoadOptionFromVar); + + if (BootNext) { + BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); + } else { + BootNextFlag = FALSE; + } + + if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) { + SafeFreePool (LoadOption); + continue; + } + // + // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly. + // the buffer allocated already should be freed before returning. + // + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + BootOptionSize; + + NewMenuEntry->OptionNumber = BootOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsBootNext = BootNextFlag; + + // + // Is a Legacy Device? + // + Ptr = (UINT8 *) LoadOption; + + // + // Attribute = *(UINT32 *)Ptr; + // + Ptr += sizeof (UINT32); + + // + // FilePathSize = *(UINT16 *)Ptr; + // + Ptr += sizeof (UINT16); + + // + // Description = (CHAR16 *)Ptr; + // + Ptr += StrSize ((CHAR16 *) Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + NewLoadContext->IsLegacy = TRUE; + } else { + NewLoadContext->IsLegacy = FALSE; + } + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = BootOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize ((UINT16 *) LoadOptionPtr); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + CopyMem ( + NewLoadContext->Description, + (UINT16 *) LoadOptionPtr, + StringSize + ); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = BootOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + MenuCount++; + } + + SafeFreePool (BootNext); + SafeFreePool (BootOrderList); + BootOptionMenu.MenuNumber = MenuCount; + return MenuCount; +} + +CHAR16 * +BdsStrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ) +{ + CHAR16 *ReturnValue; + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + + ReturnValue = Destination; + while (*Source) { + *(Destination++) = *(Source++); + } + *Destination = 0; + return ReturnValue; +} + +CHAR16 * +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ) +/*++ + +Routine Description + Append file name to existing file name. + +Arguments: + Str1 - existing file name + Str2 - file name to be appended + +Returns: + Allocate a new string to hold the appended result. + Caller is responsible to free the returned string. + +--*/ +{ + UINTN Size1; + UINTN Size2; + CHAR16 *Str; + CHAR16 *Ptr; + CHAR16 *LastSlash; + + Size1 = StrSize (Str1); + Size2 = StrSize (Str2); + Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); + ASSERT (Str != NULL); + + StrCat (Str, Str1); + if (!((*Str == '\\') && (*(Str + 1) == 0))) { + StrCat (Str, L"\\"); + } + + StrCat (Str, Str2); + + Ptr = Str; + LastSlash = Str; + while (*Ptr != 0) { + if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) { + // + // Convert "\Name\..\" to "\" + // DO NOT convert the .. if it is at the end of the string. This will + // break the .. behavior in changing directories. + // + BdsStrCpy (LastSlash, Ptr + 3); + Ptr = LastSlash; + } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { + // + // Convert a "\.\" to a "\" + // + BdsStrCpy (Ptr, Ptr + 2); + Ptr = LastSlash; + } else if (*Ptr == '\\') { + LastSlash = Ptr; + } + + Ptr++; + } + + return Str; +} + +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ) +/*++ + +Routine Description + Check whether current FileName point to a valid + Efi Image File. + +Arguments: + FileName - File need to be checked. + +Returns: + TRUE - Is Efi Image + FALSE - Not a valid Efi Image + +--*/ +{ + // + // Search for ".efi" extension + // + while (*FileName) { + if (FileName[0] == '.') { + if (FileName[1] == 'e' || FileName[1] == 'E') { + if (FileName[2] == 'f' || FileName[2] == 'F') { + if (FileName[3] == 'i' || FileName[3] == 'I') { + return TRUE; + } else if (FileName[3] == 0x0000) { + return FALSE; + } + } else if (FileName[2] == 0x0000) { + return FALSE; + } + } else if (FileName[1] == 0x0000) { + return FALSE; + } + } + + FileName += 1; + } + + return FALSE; +} + + +RETURN_STATUS +EFIAPI +IsEfiAppReadFromFile ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE File; + + File = (EFI_FILE_HANDLE)FileHandle; + Status = File->SetPosition (File, FileOffset); + if (EFI_ERROR (Status)) { + return Status; + } + + return File->Read (File, ReadSize, Buffer); +} + + + +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ) +/*++ + +Routine Description: + Check whether current FileName point to a valid Efi Application + +Arguments: + Dir - Pointer to current Directory + FileName - Pointer to current File name. + +Returns: + TRUE - Is a valid Efi Application + FALSE - not a valid Efi Application + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_FILE_HANDLE File; + + Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + return FALSE; + } + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = (VOID *)File; + ImageContext.ImageRead = IsEfiAppReadFromFile; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + File->Close (File); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + return TRUE; + } else { + return FALSE; + } + } + + +EFI_STATUS +BOpt_FindDrivers ( + VOID + ) +/*++ + +Routine Description + Find drivers that will be added as Driver#### variables from handles + in current system environment + All valid handles in the system except those consume SimpleFs, LoadFile + are stored in DriverMenu for future use. + +Arguments: + None + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + UINTN NoDevicePathHandles; + EFI_HANDLE *DevicePathHandle; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + BM_HANDLE_CONTEXT *NewHandleContext; + EFI_HANDLE CurHandle; + UINTN OptionNumber; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; + EFI_LOAD_FILE_PROTOCOL *LoadFile; + + SimpleFs = NULL; + LoadFile = NULL; + + InitializeListHead (&DriverMenu.Head); + + // + // At first, get all handles that support Device Path + // protocol which is the basic requirement for + // Driver#### + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &NoDevicePathHandles, + &DevicePathHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OptionNumber = 0; + for (Index = 0; Index < NoDevicePathHandles; Index++) { + CurHandle = DevicePathHandle[Index]; + + // + // Check whether this handle support + // driver binding + // + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**) &SimpleFs + ); + if (Status == EFI_SUCCESS) { + continue; + } + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiLoadFileProtocolGuid, + (VOID**) &LoadFile + ); + if (Status == EFI_SUCCESS) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + NewHandleContext->Handle = CurHandle; + NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); + NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath); + NewMenuEntry->HelpString = NULL; + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); + + } + + DriverMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +UINT16 +BOpt_GetBootOptionNumber ( + VOID + ) +/*++ + +Routine Description: + Get the Option Number that does not used + +Arguments: + +Returns: + The Option Number + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 Number; + UINTN Index; + UINTN Index2; + BOOLEAN Found; + CHAR16 StrTemp[100]; + UINT16 *OptionBuffer; + UINTN OptionSize; + + BootOrderListSize = 0; + BootOrderList = NULL; + + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + if (BootOrderList) { + // + // already have Boot#### + // + // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16); + // + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + Found = TRUE; + for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2); + if (Index == NewMenuEntry->OptionNumber) { + Found = FALSE; + break; + } + } + + if (Found) { + UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index); + DEBUG((EFI_D_ERROR,"INdex= %s\n", StrTemp)); + OptionBuffer = BdsLibGetVariableAndSize ( + StrTemp, + &gEfiGlobalVariableGuid, + &OptionSize + ); + if (NULL == OptionBuffer) + break; + } + } + // + // end for Index + // + Number = (UINT16) Index; + } else { + // + // No Boot#### + // + Number = 0; + } + + return Number; +} + +UINT16 +BOpt_GetDriverOptionNumber ( + VOID + ) +/*++ + +Routine Description: + Get the Option Number that does not used + +Arguments: + +Returns: + The Option Number + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *DriverOrderList; + UINTN DriverOrderListSize; + UINT16 Number; + UINTN Index; + UINTN Index2; + BOOLEAN Found; + + DriverOrderListSize = 0; + DriverOrderList = NULL; + + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + if (DriverOrderList) { + // + // already have Driver#### + // + // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16); + // + for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { + Found = TRUE; + for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2); + if (Index == NewMenuEntry->OptionNumber) { + Found = FALSE; + break; + } + } + + if (Found) { + break; + } + } + // + // end for Index + // + Number = (UINT16) Index; + } else { + // + // No Driver#### + // + Number = 0; + } + + return Number; +} + +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description: + Build up all DriverOptionMenu + +Arguments: + +Returns: + The Option Number + +--*/ +{ + UINTN Index; + UINT16 DriverString[12]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN DriverOptionSize; + + UINT16 *DriverOrderList; + UINTN DriverOrderListSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + + DriverOrderListSize = 0; + DriverOrderList = NULL; + DriverOptionSize = 0; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&DriverOptionMenu); + InitializeListHead (&DriverOptionMenu.Head); + // + // Get the DriverOrder from the Var + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + + for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + DriverOrderList[Index] + ); + // + // Get all loadoptions from the VAR + // + LoadOptionFromVar = BdsLibGetVariableAndSize ( + DriverString, + &gEfiGlobalVariableGuid, + &DriverOptionSize + ); + if (!LoadOptionFromVar) { + continue; + } + + LoadOption = AllocateZeroPool (DriverOptionSize); + if (!LoadOption) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize); + SafeFreePool (LoadOptionFromVar); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + DriverOptionSize; + NewMenuEntry->OptionNumber = DriverOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsLegacy = FALSE; + + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = DriverOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize ((UINT16 *) LoadOptionPtr); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + CopyMem ( + NewLoadContext->Description, + (UINT16 *) LoadOptionPtr, + StringSize + ); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = DriverOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + + } + + SafeFreePool (DriverOrderList); + DriverOptionMenu.MenuNumber = Index; + return EFI_SUCCESS; + +} + +VOID +SafeFreePool ( + IN VOID *Buffer + ) +/*++ + +Routine Description: + Wrap original FreePool gBS call + in order to decrease code length + +Arguments: + +Returns: + +--*/ +{ + if (Buffer != NULL) { + gBS->FreePool (Buffer); + Buffer = NULL; + } +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/ConsoleOption.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/ConsoleOption.c new file mode 100644 index 0000000000..297c2cfc55 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/ConsoleOption.c @@ -0,0 +1,840 @@ +/*++ +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: + + ConsoleOption.c + +Abstract: + + handles console redirection from boot manager + + +Revision History + +--*/ + +#include "BootMaint.h" + +EFI_DEVICE_PATH_PROTOCOL * +DevicePathInstanceDup ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +ChangeTerminalDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + BOOLEAN ChangeTerminal + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *Node1; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINTN Com; + UINT32 Match; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Match = EISA_PNP_ID (0x0501); + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + } + + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + // + // Change the device path in the ComPort + // + if (ChangeTerminal) { + Node1 = NewTerminalContext->DevicePath; + Node1 = NextDevicePathNode (Node1); + while (!IsDevicePathEnd (Node1)) { + if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) { + Uart1 = (UART_DEVICE_PATH *) Node1; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + break; + } + // + // end if + // + Node1 = NextDevicePathNode (Node1); + } + // + // end while + // + break; + } + } + + Node = NextDevicePathNode (Node); + } + + return EFI_SUCCESS; + +} + +VOID +ChangeVariableDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UINTN Com; + UINT32 Match; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Match = EISA_PNP_ID (0x0501); + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + Com + ); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + } + + Node = NextDevicePathNode (Node); + } + + return ; +} + +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ); + +EFI_STATUS +LocateSerialIo ( + VOID + ) +/*++ + +Routine Description: + Build a list containing all serial devices + +Arguments: + +Returns: + +--*/ +{ + UINT8 *Ptr; + UINTN Index; + UINTN Index2; + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINT32 Match; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + VENDOR_DEVICE_PATH Vendor; + // + // Get all handles that have SerialIo protocol installed + // + InitializeListHead (&TerminalMenu.Head); + TerminalMenu.MenuNumber = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSerialIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + // + // No serial ports present + // + return EFI_UNSUPPORTED; + } + + for (Index = 0; Index < NoHandles; Index++) { + // + // Check to see whether the handle has DevicePath Protocol installed + // + gBS->HandleProtocol ( + Handles[Index], + &gEfiDevicePathProtocolGuid, + (VOID**) &DevicePath + ); + Ptr = (UINT8 *) DevicePath; + while (*Ptr != END_DEVICE_PATH_TYPE) { + Ptr++; + } + + Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH); + Acpi = (ACPI_HID_DEVICE_PATH *) Ptr; + Match = EISA_PNP_ID (0x0501); + + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); + if (!NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); + NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath); + // + // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! + // coz' the misc data for each platform is not correct, actually it's the device path stored in + // datahub which is not completed, so a searching for end of device path will enter a + // dead-loop. + // + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = DevicePathToStr (DevicePath); + } + + NewMenuEntry->HelpString = NULL; + + gBS->HandleProtocol ( + Handles[Index], + &gEfiSerialIoProtocolGuid, + (VOID**) &SerialIo + ); + + CopyMem ( + &NewTerminalContext->BaudRate, + &SerialIo->Mode->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &SerialIo->Mode->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &SerialIo->Mode->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &SerialIo->Mode->StopBits, + sizeof (UINT8) + ); + InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); + TerminalMenu.MenuNumber++; + } + } + // + // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var + // + OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); + InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); + ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); + if (OutDevicePath) { + UpdateComAttributeFromVariable (OutDevicePath); + } + + if (InpDevicePath) { + UpdateComAttributeFromVariable (InpDevicePath); + } + + if (ErrDevicePath) { + UpdateComAttributeFromVariable (ErrDevicePath); + } + + 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; + + NewTerminalContext->TerminalType = 0; + NewTerminalContext->IsConIn = FALSE; + NewTerminalContext->IsConOut = FALSE; + NewTerminalContext->IsStdErr = FALSE; + + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + + for (Index2 = 0; Index2 < 4; Index2++) { + CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID)); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + NewDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + SafeFreePool (NewMenuEntry->HelpString); + // + // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath); + // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; + // + NewMenuEntry->HelpString = NULL; + + if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) { + NewTerminalContext->IsConOut = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) { + NewTerminalContext->IsConIn = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) { + NewTerminalContext->IsStdErr = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Update Com Ports attributes from DevicePath + +Arguments: + DevicePath - DevicePath that contains Com ports + +Returns: + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *SerialNode; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINT32 Match; + UINTN TerminalNumber; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINTN Index; + + Match = EISA_PNP_ID (0x0501); + Node = DevicePath; + Node = NextDevicePathNode (Node); + TerminalNumber = 0; + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32)); + } + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem ( + &NewTerminalContext->BaudRate, + &Uart->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &Uart->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &Uart->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &Uart->StopBits, + sizeof (UINT8) + ); + + SerialNode = NewTerminalContext->DevicePath; + SerialNode = NextDevicePathNode (SerialNode); + while (!IsDevicePathEnd (SerialNode)) { + if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) { + // + // Update following device paths according to + // previous acquired uart attributes + // + Uart1 = (UART_DEVICE_PATH *) SerialNode; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + + break; + } + + SerialNode = NextDevicePathNode (SerialNode); + } + // + // end while + // + } + + Node = NextDevicePathNode (Node); + } + // + // end while + // + } + + return EFI_SUCCESS; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevicePathInstanceDup ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + +Routine Description: + Function creates a device path data structure that identically matches the + device path passed in. + +Arguments: + DevPath - A pointer to a device path data structure. + +Returns: + + The new copy of DevPath is created to identically match the input. + Otherwise, NULL is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevPath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + EFI_DEVICE_PATH_PROTOCOL *Temp; + UINT8 *Ptr; + UINTN Size; + + // + // get the size of an instance from the input + // + Temp = DevPath; + DevicePathInst = GetNextDevicePathInstance (&Temp, &Size); + + // + // Make a copy and set proper end type + // + NewDevPath = NULL; + if (Size) { + NewDevPath = AllocateZeroPool (Size); + ASSERT (NewDevPath != NULL); + } + + if (NewDevPath) { + CopyMem (NewDevPath, DevicePathInst, Size); + Ptr = (UINT8 *) NewDevPath; + Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL); + Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + SetDevicePathEndNode (Temp); + } + + return NewDevPath; +} + +EFI_STATUS +GetConsoleMenu ( + IN UINTN ConsoleMenuType + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; + EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + UINTN AllCount; + UINTN Index; + UINTN Index2; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + TYPE_OF_TERMINAL Terminal; + BM_MENU_ENTRY *NewTerminalMenuEntry; + UINTN Com; + BM_MENU_OPTION *ConsoleMenu; + + DevicePath = NULL; + AllDevicePath = NULL; + AllCount = 0; + switch (ConsoleMenuType) { + case BM_CONSOLE_IN_CONTEXT_SELECT: + ConsoleMenu = &ConsoleInpMenu; + DevicePath = EfiLibGetVariable ( + L"ConIn", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ConInDev", + &gEfiGlobalVariableGuid + ); + break; + + case BM_CONSOLE_OUT_CONTEXT_SELECT: + ConsoleMenu = &ConsoleOutMenu; + DevicePath = EfiLibGetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ConOutDev", + &gEfiGlobalVariableGuid + ); + break; + + case BM_CONSOLE_ERR_CONTEXT_SELECT: + ConsoleMenu = &ConsoleErrMenu; + DevicePath = EfiLibGetVariable ( + L"ErrOut", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ErrOutDev", + &gEfiGlobalVariableGuid + ); + break; + + default: + return EFI_UNSUPPORTED; + } + + if (NULL == AllDevicePath) { + return EFI_NOT_FOUND; + } + + InitializeListHead (&ConsoleMenu->Head); + + AllCount = EfiDevicePathInstanceCount (AllDevicePath); + ConsoleMenu->MenuNumber = 0; + // + // Following is menu building up for Console Out Devices + // + MultiDevicePath = AllDevicePath; + Index2 = 0; + for (Index = 0; Index < AllCount; Index++) { + DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewMenuEntry->OptionNumber = Index2; + + NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst); + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath); + } + + NewConsoleContext->IsTerminal = IsTerminalDevicePath ( + NewConsoleContext->DevicePath, + &Terminal, + &Com + ); + + NewConsoleContext->IsActive = BdsLibMatchDevicePaths ( + DevicePath, + NewConsoleContext->DevicePath + ); + NewTerminalMenuEntry = NULL; + NewTerminalContext = NULL; + + if (NewConsoleContext->IsTerminal) { + BOpt_DestroyMenuEntry (NewMenuEntry); + } else { + Index2++; + ConsoleMenu->MenuNumber++; + InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetAllConsoles ( + VOID + ) +/*++ + +Routine Description: + Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + +Arguments: + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT); + return EFI_SUCCESS; +} + +EFI_STATUS +FreeAllConsoles ( + VOID + ) +/*++ + +Routine Description: + Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + +Arguments: + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + BOpt_FreeMenu (&ConsoleOutMenu); + BOpt_FreeMenu (&ConsoleInpMenu); + BOpt_FreeMenu (&ConsoleErrMenu); + BOpt_FreeMenu (&TerminalMenu); + return EFI_SUCCESS; +} + +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ) +/*++ + +Routine Description: + Test whether DevicePath is a valid Terminal + +Arguments: + DevicePath - DevicePath to be checked + Termi - If is terminal, give its type + Com - If is Com Port, give its type + +Returns: + TRUE - If DevicePath point to a Terminal + FALSE + +--*/ +{ + UINT8 *Ptr; + BOOLEAN IsTerminal; + VENDOR_DEVICE_PATH *Vendor; + ACPI_HID_DEVICE_PATH *Acpi; + UINT32 Match; + EFI_GUID TempGuid; + + IsTerminal = FALSE; + + // + // Parse the Device Path, should be change later!!! + // + Ptr = (UINT8 *) DevicePath; + while (*Ptr != END_DEVICE_PATH_TYPE) { + Ptr++; + } + + Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH); + Vendor = (VENDOR_DEVICE_PATH *) Ptr; + + // + // There are four kinds of Terminal types + // check to see whether this devicepath + // is one of that type + // + CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID)); + + if (CompareGuid (&TempGuid, &Guid[0])) { + *Termi = PC_ANSI; + IsTerminal = TRUE; + } else { + if (CompareGuid (&TempGuid, &Guid[1])) { + *Termi = VT_100; + IsTerminal = TRUE; + } else { + if (CompareGuid (&TempGuid, &Guid[2])) { + *Termi = VT_100_PLUS; + IsTerminal = TRUE; + } else { + if (CompareGuid (&TempGuid, &Guid[3])) { + *Termi = VT_UTF8; + IsTerminal = TRUE; + } else { + IsTerminal = FALSE; + } + } + } + } + + if (!IsTerminal) { + return FALSE; + } + + Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH); + Acpi = (ACPI_HID_DEVICE_PATH *) Ptr; + Match = EISA_PNP_ID (0x0501); + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (Com, &Acpi->UID, sizeof (UINT32)); + } else { + return FALSE; + } + + return TRUE; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Data.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Data.c new file mode 100644 index 0000000000..196bbe2385 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Data.c @@ -0,0 +1,324 @@ +/*++ + +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: + + Data.c + +Abstract: + + Define some data used for Boot Maint + +Revision History + +--*/ + +#include "BootMaint.h" + +EFI_HII_UPDATE_DATA *UpdateData; +STRING_DEPOSITORY *FileOptionStrDepository; +STRING_DEPOSITORY *ConsoleOptionStrDepository; +STRING_DEPOSITORY *BootOptionStrDepository; +STRING_DEPOSITORY *BootOptionHelpStrDepository; +STRING_DEPOSITORY *DriverOptionStrDepository; +STRING_DEPOSITORY *DriverOptionHelpStrDepository; +STRING_DEPOSITORY *TerminalStrDepository; + +// +// Terminal type string token storage +// +UINT16 TerminalType[] = { + STRING_TOKEN(STR_COM_TYPE_0), + STRING_TOKEN(STR_COM_TYPE_1), + STRING_TOKEN(STR_COM_TYPE_2), + STRING_TOKEN(STR_COM_TYPE_3), +}; + +// +// File system selection menu +// +BM_MENU_OPTION FsOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Console Input Device Selection Menu +// +BM_MENU_OPTION ConsoleInpMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Console Output Device Selection Menu +// +BM_MENU_OPTION ConsoleOutMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Error Output Device Selection Menu +// +BM_MENU_OPTION ConsoleErrMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Boot Option from variable Menu +// +BM_MENU_OPTION BootOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Driver Option from variable menu +// +BM_MENU_OPTION DriverOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Legacy FD Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyFDMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Legacy HD Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyHDMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Legacy CD Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyCDMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Legacy NET Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyNETMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Legacy NET Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyBEVMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Files and sub-directories in current directory menu +// +BM_MENU_OPTION DirectoryMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Handles in current system selection menu +// +BM_MENU_OPTION DriverMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +BM_MENU_OPTION TerminalMenu = { + BM_MENU_OPTION_SIGNATURE, + { NULL, NULL}, + 0 +}; + +// +// Value and string token correspondency for BaudRate +// +COM_ATTR BaudRateList[19] = { + { + 115200, + STRING_TOKEN(STR_COM_BAUD_RATE_0) + }, + { + 57600, + STRING_TOKEN(STR_COM_BAUD_RATE_1) + }, + { + 38400, + STRING_TOKEN(STR_COM_BAUD_RATE_2) + }, + { + 19200, + STRING_TOKEN(STR_COM_BAUD_RATE_3) + }, + { + 9600, + STRING_TOKEN(STR_COM_BAUD_RATE_4) + }, + { + 7200, + STRING_TOKEN(STR_COM_BAUD_RATE_5) + }, + { + 4800, + STRING_TOKEN(STR_COM_BAUD_RATE_6) + }, + { + 3600, + STRING_TOKEN(STR_COM_BAUD_RATE_7) + }, + { + 2400, + STRING_TOKEN(STR_COM_BAUD_RATE_8) + }, + { + 2000, + STRING_TOKEN(STR_COM_BAUD_RATE_9) + }, + { + 1800, + STRING_TOKEN(STR_COM_BAUD_RATE_10) + }, + { + 1200, + STRING_TOKEN(STR_COM_BAUD_RATE_11) + }, + { + 600, + STRING_TOKEN(STR_COM_BAUD_RATE_12) + }, + { + 300, + STRING_TOKEN(STR_COM_BAUD_RATE_13) + }, + { + 150, + STRING_TOKEN(STR_COM_BAUD_RATE_14) + }, + { + 134, + STRING_TOKEN(STR_COM_BAUD_RATE_15) + }, + { + 110, + STRING_TOKEN(STR_COM_BAUD_RATE_16) + }, + { + 75, + STRING_TOKEN(STR_COM_BAUD_RATE_17) + }, + { + 50, + STRING_TOKEN(STR_COM_BAUD_RATE_18) + } +}; + +// +// Value and string token correspondency for DataBits +// +COM_ATTR DataBitsList[4] = { + { + 5, + STRING_TOKEN(STR_COM_DATA_BITS_0) + }, + { + 6, + STRING_TOKEN(STR_COM_DATA_BITS_1) + }, + { + 7, + STRING_TOKEN(STR_COM_DATA_BITS_2) + }, + { + 8, + STRING_TOKEN(STR_COM_DATA_BITS_3) + } +}; + +// +// Value and string token correspondency for Parity +// +COM_ATTR ParityList[5] = { + { + NoParity, + STRING_TOKEN(STR_COM_PAR_0) + }, + { + EvenParity, + STRING_TOKEN(STR_COM_PAR_1) + }, + { + OddParity, + STRING_TOKEN(STR_COM_PAR_2) + }, + { + MarkParity, + STRING_TOKEN(STR_COM_PAR_3) + }, + { + SpaceParity, + STRING_TOKEN(STR_COM_PAR_4) + } +}; + +// +// Value and string token correspondency for Baudreate +// +COM_ATTR StopBitsList[3] = { + { + OneStopBit, + STRING_TOKEN(STR_COM_STOP_BITS_0) + }, + { + OneFiveStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_1) + }, + { + TwoStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_2) + } +}; + +// +// Guid for messaging path, used in Serial port setting. +// +EFI_GUID Guid[4] = { + DEVICE_PATH_MESSAGING_PC_ANSI, + DEVICE_PATH_MESSAGING_VT_100, + DEVICE_PATH_MESSAGING_VT_100_PLUS, + DEVICE_PATH_MESSAGING_VT_UTF8 +}; diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FE.vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FE.vfr new file mode 100644 index 0000000000..b9c5bb36a8 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FE.vfr @@ -0,0 +1,138 @@ +// *++ +// +// 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: +// +// FE.vfr +// +// Abstract: +// +// File Explorer Formset +// +// Revision History: +// +// --*/ + +#include "EdkGenericPlatformBdsLibStrDefs.h" +#include "FormGuid.h" + +#pragma pack(1) +typedef struct { + UINT16 DescriptionData[75]; + UINT16 OptionalData[127]; + UINT8 Active; + UINT8 ForceReconnect; +} FILE_EXPLORER_NV_DATA; +#pragma pack() + +#define FORM_FILE_EXPLORER_ID 0x001E +#define FORM_BOOT_ADD_DESCRIPTION_ID 0x001F +#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x0020 +#define KEY_VALUE_SAVE_AND_EXIT 0x0090 +#define KEY_VALUE_NO_SAVE_AND_EXIT 0x0091 + + + +formset + guid = FILE_EXPLORE_FORMSET_GUID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + class = 0, + subclass = 0, + + form formid = FORM_FILE_EXPLORER_ID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + endform; + + form formid = FORM_BOOT_ADD_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE); + + label FORM_BOOT_ADD_DESCRIPTION_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FILE_EXPLORER_NV_DATA.DescriptionData, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 6, + maxsize = 75, + endstring; + + string varid = FILE_EXPLORER_NV_DATA.OptionalData, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 0, + maxsize = 120, + endstring; + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_SAVE_AND_EXIT; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_NO_SAVE_AND_EXIT; + + endform; + + form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FILE_EXPLORER_NV_DATA.DescriptionData, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 6, + maxsize = 75, + endstring; + + string varid = FILE_EXPLORER_NV_DATA.OptionalData, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 0, + maxsize = 120, + endstring; + + checkbox varid = FILE_EXPLORER_NV_DATA.ForceReconnect, + prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + flags = 1, + key = 0, + endcheckbox; + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_SAVE_AND_EXIT; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_NO_SAVE_AND_EXIT; + + endform; + +endformset; diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c new file mode 100644 index 0000000000..2c8ec5208c --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c @@ -0,0 +1,339 @@ +/*++ + +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: + + FileExplorer.c + +AgBStract: + + File explorer related functions. + +--*/ + +#include "Bds.h" +#include "BootMaint.h" + +VOID +UpdateFileExplorePage ( + IN BMM_CALLBACK_DATA *CallbackData, + BM_MENU_OPTION *MenuOption + ) +/*++ +Routine Description: + Update the File Explore page. + +Arguments: + MenuOption - Pointer to menu options to display. + +Returns: + None. + +--*/ +{ + UINT8 *Location; + UINTN Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + FORM_ID FormId; + + NewMenuEntry = NULL; + NewFileContext = NULL; + FormId = 0; + + // + // Clean up file explore page. + // + RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff); + + // + // Remove all op-codes from dynamic page + // + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FORM_FILE_EXPLORER_ID, + FALSE, + UpdateData + ); + + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 0); + + Location = (UINT8 *) &UpdateData->Data; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsBootLegacy) { + continue; + } + + if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) { + // + // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE. + // + CreateTextOpCode ( + NewMenuEntry->DisplayStringToken, + STR_NULL_STRING, + STR_NULL_STRING, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (FILE_OPTION_OFFSET + Index), + Location + ); + } else { + // + // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE. + // + if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + CreateGotoOpCode ( + FormId, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (FILE_OPTION_OFFSET + Index), + Location + ); + } + + UpdateData->DataCount++; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + } + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FORM_FILE_EXPLORER_ID, + TRUE, + UpdateData + ); +} + +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ) +/*++ + +Routine Description: + Update the file explower page with the refershed file system. + +Arguments: + CallbackData - BMM context data + KeyValue - Key value to identify the type of data to expect. + +Returns: + TRUE - Inform the caller to create a callback packet to exit file explorer. + FALSE - Indicate that there is no need to exit file explorer. + +--*/ +{ + UINT16 FileOptionMask; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + FORM_ID FormId; + BOOLEAN ExitFileExplorer; + EFI_STATUS Status; + + NewMenuEntry = NULL; + NewFileContext = NULL; + ExitFileExplorer = FALSE; + + FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); + + if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) { + // + // First in, display file system. + // + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FindFileSystem (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu); + + UpdateFileExplorePage (CallbackData, &FsOptionMenu); + + CallbackData->FeDisplayContext = FILE_SYSTEM; + } else { + if (FILE_SYSTEM == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask); + } else if (DIRECTORY == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask); + } + + CallbackData->FeDisplayContext = DIRECTORY; + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsDir ) { + RemoveEntryList (&NewMenuEntry->Link); + BOpt_FreeMenu (&DirectoryMenu); + Status = BOpt_FindFiles (CallbackData, NewMenuEntry); + if (EFI_ERROR (Status)) { + ExitFileExplorer = TRUE; + goto exit; + } + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu); + BOpt_DestroyMenuEntry (NewMenuEntry); + + UpdateFileExplorePage (CallbackData, &DirectoryMenu); + + } else { + switch (CallbackData->FeCurrentState) { + case BOOT_FROM_FILE_STATE: + // + // Here boot from file + // + BootThisFile (NewFileContext); + ExitFileExplorer = TRUE; + break; + + case ADD_BOOT_OPTION_STATE: + case ADD_DRIVER_OPTION_STATE: + if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + CallbackData->MenuEntry = NewMenuEntry; + CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath; + + // + // Clean up file explore page. + // + RefreshUpdateData (FALSE, 0, FALSE, 0, 1); + + // + // Remove the Subtitle op-code. + // + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FormId, + FALSE, + UpdateData + ); + + // + // Create Subtitle op-code for the display string of the option. + // + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 1); + + CreateSubTitleOpCode ( + NewMenuEntry->DisplayStringToken, + &UpdateData->Data + ); + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FormId, + TRUE, + UpdateData + ); + break; + + default: + break; + } + } + } +exit: + return ExitFileExplorer; +} + +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ +Routine Description: + Callback Function for file exploration and file interaction. + +Arguments: + This - File explorer callback protocol pointer. + KeyValue - Key value to identify the type of data to expect. + Data - A pointer to the data being sent to the original exporting driver. + Packet - A pointer to a packet of information which a driver passes back to the browser. + +Returns: + EFI_SUCCESS - Callback ended successfully. + Others - Contain some errors. + +--*/ +{ + BMM_CALLBACK_DATA *Private; + FILE_EXPLORER_NV_DATA *NvRamMap; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + Private = FE_CALLBACK_DATA_FROM_THIS (This); + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->FeCallbackHandle; + NvRamMap = (FILE_EXPLORER_NV_DATA *) Data->NvRamMap; + + if (KEY_VALUE_SAVE_AND_EXIT == KeyValue) { + // + // Apply changes and exit formset. + // + if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) { + Status = Var_UpdateBootOption (Private, NvRamMap); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetBootOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); + } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) { + Status = Var_UpdateDriverOption ( + Private, + Private->FeHiiHandle, + NvRamMap->DescriptionData, + NvRamMap->OptionalData, + NvRamMap->ForceReconnect + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); + } + + CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED); + } else if (KEY_VALUE_NO_SAVE_AND_EXIT == KeyValue) { + // + // Discard changes and exit formset. + // + NvRamMap->OptionalData[0] = 0x0000; + NvRamMap->DescriptionData[0] = 0x0000; + CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED); + } else if (KeyValue < FILE_OPTION_OFFSET) { + // + // Exit File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + } else { + if (UpdateFileExplorer (Private, KeyValue)) { + CreateCallbackPacket (Packet, EXIT_REQUIRED); + } + } + + return Status; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FormGuid.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FormGuid.h new file mode 100644 index 0000000000..8b55159f8b --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FormGuid.h @@ -0,0 +1,32 @@ +// *++ +// +// 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: +// +// FormGuid.h +// +// Abstract: +// +// Formset guids for Boot Maintenance Manager +// +// Revision History: +// +// --*/ +// +#define MAIN_FORMSET_GUID \ + { \ + 0x642237c7, 0x35d4, 0x472d, { 0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22 } \ + } + +#define FILE_EXPLORE_FORMSET_GUID \ + { \ + 0x1f2d63e1, 0xfebd, 0x4dc7, { 0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b } \ + } diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/UpdatePage.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/UpdatePage.c new file mode 100644 index 0000000000..dfc12dca93 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/UpdatePage.c @@ -0,0 +1,1274 @@ +/*++ + +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: + + UpdatePage.c + +AgBStract: + + Dynamically Update the pages + +--*/ + +#include "Bds.h" +#include "BootMaint.h" + +EFI_GUID gTerminalDriverGuid = { + 0x10634d8e, 0x1c05, 0x46cb, {0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8} +}; + +VOID +RefreshUpdateData ( + IN BOOLEAN FormSetUpdate, + IN EFI_PHYSICAL_ADDRESS FormCallbackHandle, + IN BOOLEAN FormUpdate, + IN STRING_REF FormTitle, + IN UINT16 DataCount + ) +/*++ +Routine Description: + Refresh the global UpdateData structure. + +Arguments: + FormSetUpdate - If TRUE, next variable is significant + FormCallbackHandle - If not 0, will update FormSet with this info + FormUpdate - If TRUE, next variable is significant + FormTitle - If not 0, will update Form with this info + DataCount - The number of Data entries in this structure + +Returns: + None. +--*/ +{ + UpdateData->FormSetUpdate = FormSetUpdate; + if (FormSetUpdate) { + ASSERT (0 != FormCallbackHandle); + UpdateData->FormCallbackHandle = FormCallbackHandle; + } + + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = FormTitle; + UpdateData->DataCount = DataCount; +} + +VOID +UpdatePageStart ( + IN BMM_CALLBACK_DATA *CallbackData, + IN OUT UINT8 **CurrentLocation + ) +{ + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->BmmCallbackHandle, FALSE, 0, 0); + + if (!(CallbackData->BmmAskSaveOrNot)) { + // + // Add a "Go back to main page" tag in front of the form when there are no + // "Apply changes" and "Discard changes" tags in the end of the form. + // + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_FORM_GOTO_MAIN), + STRING_TOKEN (STR_FORM_GOTO_MAIN), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_MAIN_ID, + *CurrentLocation + ); + + UpdateData->DataCount++; + + *CurrentLocation = *CurrentLocation + ((EFI_IFR_OP_HEADER *) (*CurrentLocation))->Length; + } + +} + +VOID +UpdatePageEnd ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT8 *CurrentLocation + ) +{ + // + // Create the "Apply changes" and "Discard changes" tags. + // + if (CallbackData->BmmAskSaveOrNot) { + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_SAVE_AND_EXIT, + CurrentLocation + ); + + UpdateData->DataCount++; + + CurrentLocation = CurrentLocation + ((EFI_IFR_OP_HEADER *) CurrentLocation)->Length; + + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_NO_SAVE_AND_EXIT, + CurrentLocation + ); + + UpdateData->DataCount++; + } + // + // Ensure user can return to the main page. + // + if (0 == UpdateData->DataCount) { + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_NO_SAVE_AND_EXIT, + CurrentLocation + ); + + UpdateData->DataCount++; + } + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->BmmHiiHandle, + CallbackData->BmmCurrentPageId, + TRUE, + UpdateData + ); +} + +VOID +CleanUpPage ( + IN EFI_FORM_LABEL LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff); + + // + // Remove all op-codes from dynamic page + // + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->BmmHiiHandle, + LabelId, + FALSE, + UpdateData + ); +} + +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ) +{ + EFI_STATUS Status; + UINTN ExitDataSize; + CHAR16 *ExitData; + BDS_COMMON_OPTION *Option; + + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (BDS_COMMON_OPTION), (VOID**) &Option); + Option->Description = FileContext->FileName; + Option->DevicePath = FileContext->DevicePath; + Option->LoadOptionsSize = 0; + Option->LoadOptions = NULL; + + // + // Since current no boot from removable media directly is allowed */ + // + gST->ConOut->ClearScreen (gST->ConOut); + + ExitDataSize = 0; + + Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData); + + return Status; + +} + +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 *Location; + EFI_STATUS Status; + VOID *Interface; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData, &Location); + + Status = EfiLibLocateProtocol (&gTerminalDriverGuid, &Interface); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + + CreateGotoOpCode ( + FORM_CON_COM_SETUP_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (TERMINAL_OPTION_OFFSET + Index), + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (NewLoadContext->IsLegacy) { + continue; + } + + NewLoadContext->Deleted = FALSE; + CallbackData->BmmFakeNvData->BootOptionDel[Index] = 0x00; + + CreateCheckBoxOpCode ( + (UINT16) (BOOT_OPTION_DEL_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) BOOT_OPTION_DEL_QUESTION_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData, &Location); + + for (Index = 0; Index < DriverMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); + + CreateGotoOpCode ( + FORM_DRV_ADD_HANDLE_DESC_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (HANDLE_OPTION_OFFSET + Index), + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu); + + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + CallbackData->BmmFakeNvData->DriverOptionDel[Index] = 0x00; + + CreateCheckBoxOpCode ( + (UINT16) (DRIVER_OPTION_DEL_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) DRIVER_OPTION_DEL_QUESTION_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmFakeNvData->DriverAddActive = 0x01; + CallbackData->BmmFakeNvData->DriverAddForceReconnect = 0x00; + CallbackData->BmmAskSaveOrNot = TRUE; + NewMenuEntry = CallbackData->MenuEntry; + + UpdatePageStart (CallbackData, &Location); + + UpdateData->DataCount += (UINT16) 4; + + CreateSubTitleOpCode ( + NewMenuEntry->DisplayStringToken, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateStringOpCode ( + DRV_ADD_HANDLE_DESC_QUESTION_ID, + (UINT8) 150, + STRING_TOKEN (STR_LOAD_OPTION_DESC), + STRING_TOKEN (STR_NULL_STRING), + 6, + 75, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_DRIVER_ADD_DESC_DATA, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateCheckBoxOpCode ( + DRV_ADD_RECON_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + DRV_ADD_RECON_QUESTION_ID, + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateStringOpCode ( + DRIVER_ADD_OPTION_QUESTION_ID, + (UINT8) 150, + STRING_TOKEN (STR_OPTIONAL_DATA), + STRING_TOKEN (STR_NULL_STRING), + 6, + 75, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_DRIVER_ADD_OPT_DATA, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateConsolePage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *ConsoleMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINT16 Index; + UINT16 Index2; + UINT8 *Location; + UINT8 CheckFlags; + EFI_STATUS Status; + VOID *Interface; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewConsoleContext->IsActive) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = TRUE; + } else { + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = FALSE; + } + + CreateCheckBoxOpCode ( + (UINT16) (CON_DEVICE_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + CheckFlags, + (UINT16) (CONSOLE_OPTION_OFFSET + Index), + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + Status = EfiLibLocateProtocol (&gTerminalDriverGuid, &Interface); + if (!EFI_ERROR (Status)) { + for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2); + 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)) + ) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = TRUE; + } else { + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = FALSE; + } + + CreateCheckBoxOpCode ( + (UINT16) (CON_DEVICE_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + CheckFlags, + (UINT16) (CONSOLE_OPTION_OFFSET + Index), + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + Index++; + } + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateOrderPage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *OptionMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 *Location; + IFR_OPTION *IfrOptionList; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + ZeroMem (CallbackData->BmmFakeNvData->OptionOrder, 100); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber); + if (NULL == IfrOptionList) { + return ; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken; + IfrOptionList[Index].Value = (UINT16) (NewMenuEntry->OptionNumber + 1); + IfrOptionList[Index].OptionString = NULL; + CallbackData->BmmFakeNvData->OptionOrder[Index] = (UINT8) (IfrOptionList[Index].Value); + } + + if (OptionMenu->MenuNumber > 0) { + CreateOrderedListOpCode ( + (UINT16) OPTION_ORDER_QUESTION_ID, + (UINT8) 100, + STRING_TOKEN (STR_CHANGE_ORDER), + STRING_TOKEN (STR_CHANGE_ORDER), + IfrOptionList, + OptionMenu->MenuNumber, + Location + ); + + for (Index = 0; Index < OptionMenu->MenuNumber + 2; Index++) { + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + } + + UpdateData->DataCount = (UINT16) (UpdateData->DataCount + OptionMenu->MenuNumber + 2); + } + + SafeFreePool (IfrOptionList); + + UpdatePageEnd (CallbackData, Location); + + CopyMem ( + CallbackData->BmmOldFakeNVData.OptionOrder, + CallbackData->BmmFakeNvData->OptionOrder, + 100 + ); +} + +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT8 *Location; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + IFR_OPTION *IfrOptionList; + UINTN NumberOfOptions; + UINT16 Index; + + Location = (UINT8 *) &UpdateData->Data; + IfrOptionList = NULL; + NumberOfOptions = BootOptionMenu.MenuNumber; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + if (NumberOfOptions > 0) { + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + NumberOfOptions); + IfrOptionList = AllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION)); + + ASSERT (IfrOptionList); + + CallbackData->BmmFakeNvData->BootNext = (UINT16) (BootOptionMenu.MenuNumber); + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (NewLoadContext->IsBootNext) { + IfrOptionList[Index].Flags = EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_INTERACTIVE; + CallbackData->BmmFakeNvData->BootNext = Index; + } else { + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + } + + IfrOptionList[Index].Key = (UINT16) KEY_VALUE_MAIN_BOOT_NEXT; + IfrOptionList[Index].Value = Index; + IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken; + IfrOptionList[Index].OptionString = NULL; + } + + IfrOptionList[Index].Key = (UINT16) KEY_VALUE_MAIN_BOOT_NEXT; + IfrOptionList[Index].Value = Index; + IfrOptionList[Index].StringToken = STRING_TOKEN (STR_NONE); + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + if (CallbackData->BmmFakeNvData->BootNext == Index) { + IfrOptionList[Index].Flags |= EFI_IFR_FLAG_DEFAULT; + } + + IfrOptionList[Index].OptionString = NULL; + + CreateOneOfOpCode ( + (UINT16) BOOT_NEXT_QUESTION_ID, + (UINT8) 2, + STRING_TOKEN (STR_BOOT_NEXT), + STRING_TOKEN (STR_BOOT_NEXT_HELP), + IfrOptionList, + (UINTN) (NumberOfOptions + 1), + Location + ); + Location = Location + (NumberOfOptions + 2) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + UpdateData->DataCount += 3; + SafeFreePool (IfrOptionList); + IfrOptionList = NULL; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT8 *Location; + UINT16 BootTimeOut; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + BootTimeOut = BdsLibGetTimeout (); + + CreateNumericOpCode ( + (UINT16) BOOT_TIME_OUT_QUESTION_ID, + (UINT8) 2, + STRING_TOKEN (STR_NUM_AUTO_BOOT), + STRING_TOKEN (STR_HLP_AUTO_BOOT), + 0, + 65535, + 0, + 10, + 0, + 0, + Location + ); + + CallbackData->BmmFakeNvData->BootTimeOut = (UINT16) BootTimeOut; + UpdateData->DataCount++; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 Index; + UINT8 *Location; + UINT8 CheckFlags; + IFR_OPTION *IfrOptionList; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + + ZeroMem (UpdateData, UPDATE_DATA_SIZE); + Location = (UINT8 *) &UpdateData->Data; + UpdatePageStart (CallbackData, &Location); + + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + CallbackData->CurrentTerminal + ); + + if (!NewMenuEntry) { + return ; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 19); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 19; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + NewTerminalContext->BaudRateIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMBaudRate = NewTerminalContext->BaudRateIndex; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_BAUD_RATE; + IfrOptionList[Index].StringToken = BaudRateList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_BAUD_RATE_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_BAUD_RATE), + STRING_TOKEN (STR_COM_BAUD_RATE), + IfrOptionList, + 19, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 4); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 4; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + + if (NewTerminalContext->DataBits == DataBitsList[Index].Value) { + NewTerminalContext->DataBitsIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMDataRate = NewTerminalContext->DataBitsIndex; + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_DATA_BITS; + IfrOptionList[Index].StringToken = DataBitsList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_DATA_RATE_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_DATA_BITS), + STRING_TOKEN (STR_COM_DATA_BITS), + IfrOptionList, + 4, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 5); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 5; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->Parity == ParityList[Index].Value) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + NewTerminalContext->ParityIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMParity = NewTerminalContext->ParityIndex; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_PARITY; + IfrOptionList[Index].StringToken = ParityList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_PARITY_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_PARITY), + STRING_TOKEN (STR_COM_PARITY), + IfrOptionList, + 5, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 3); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 3; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->StopBits == StopBitsList[Index].Value) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + NewTerminalContext->StopBitsIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMStopBits = NewTerminalContext->StopBitsIndex; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_STOP_BITS; + IfrOptionList[Index].StringToken = StopBitsList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_STOP_BITS_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_STOP_BITS), + STRING_TOKEN (STR_COM_STOP_BITS), + IfrOptionList, + 3, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 4); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 4; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->TerminalType == Index) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + CallbackData->BmmFakeNvData->COMTerminalType = NewTerminalContext->TerminalType; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_TERMI_TYPE; + IfrOptionList[Index].StringToken = (STRING_REF) TerminalType[Index]; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_TERMINAL_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_TERMI_TYPE), + STRING_TOKEN (STR_COM_TERMI_TYPE), + IfrOptionList, + 4, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_SAVE_AND_EXIT, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_NO_SAVE_AND_EXIT, + Location + ); + + UpdateData->DataCount++; + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->BmmHiiHandle, + (EFI_FORM_LABEL) FORM_CON_COM_SETUP_ID, + TRUE, + UpdateData + ); + +} + +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + CleanUpPage (UpdatePageId, CallbackData); + switch (UpdatePageId) { + case FORM_CON_IN_ID: + UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData); + break; + + case FORM_CON_OUT_ID: + UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData); + break; + + case FORM_CON_ERR_ID: + UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData); + break; + + case FORM_BOOT_CHG_ID: + UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData); + break; + + case FORM_DRV_CHG_ID: + UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData); + break; + + default: + break; + } +} + +VOID * +GetLegacyBootOptionVar ( + IN UINTN DeviceType, + OUT UINTN *OptionIndex, + OUT UINTN *OptionSize + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VOID *OptionBuffer; + UINTN OrderSize; + UINTN Index; + UINT32 Attribute; + UINT16 *OrderBuffer; + CHAR16 StrTemp[100]; + UINT16 FilePathSize; + CHAR16 *Description; + UINT8 *Ptr; + UINT8 *OptionalData; + + // + // Get Boot Option number from the size of BootOrder + // + OrderBuffer = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &OrderSize + ); + + for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]); + OptionBuffer = BdsLibGetVariableAndSize ( + StrTemp, + &gEfiGlobalVariableGuid, + OptionSize + ); + if (NULL == OptionBuffer) { + continue; + } + + Ptr = (UINT8 *) OptionBuffer; + Attribute = *(UINT32 *) Ptr; + Ptr += sizeof (UINT32); + + FilePathSize = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + + Description = (CHAR16 *) Ptr; + Ptr += StrSize ((CHAR16 *) Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + Ptr += FilePathSize; + + // + // Now Ptr point to Optional Data + // + OptionalData = Ptr; + + if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) && + (BBS_DEVICE_PATH == DevicePath->Type) && + (BBS_BBS_DP == DevicePath->SubType) + ) { + *OptionIndex = OrderBuffer[Index]; + SafeFreePool (OrderBuffer); + return OptionBuffer; + } else { + SafeFreePool (OptionBuffer); + } + } + + SafeFreePool (OrderBuffer); + return NULL; +} + +VOID +UpdateSetLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder; + BM_MENU_OPTION *OptionMenu; + BM_MENU_ENTRY *NewMenuEntry; + IFR_OPTION *IfrOptionList; + STRING_REF StrRef; + STRING_REF StrRefHelp; + BBS_TYPE BbsType; + UINTN VarSize; + UINTN Pos; + UINTN Bit; + UINT16 Index; + UINT16 Index2; + UINT16 Key; + CHAR16 String[100]; + CHAR16 *TypeStr; + CHAR16 *TypeStrHelp; + UINT16 VarDevOrder; + UINT8 *Location; + UINT8 *VarData; + UINT8 *OriginalPtr; + UINT8 *LegacyOrder; + UINT8 *OldData; + UINT8 *DisMap; + + OptionMenu = NULL; + Key = 0; + StrRef = 0; + StrRefHelp = 0; + TypeStr = NULL; + TypeStrHelp = NULL; + BbsType = BBS_FLOPPY; + LegacyOrder = NULL; + OldData = NULL; + DisMap = NULL; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + DisMap = CallbackData->BmmOldFakeNVData.DisableMap; + + SetMem (DisMap, 32, 0); + // + // Create oneof option list + // + switch (UpdatePageId) { + case FORM_SET_FD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; + Key = LEGACY_FD_QUESTION_ID; + TypeStr = StrFloppy; + TypeStrHelp = StrFloppyHelp; + BbsType = BBS_FLOPPY; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyFD; + OldData = CallbackData->BmmOldFakeNVData.LegacyFD; + break; + + case FORM_SET_HD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; + Key = LEGACY_HD_QUESTION_ID; + TypeStr = StrHardDisk; + TypeStrHelp = StrHardDiskHelp; + BbsType = BBS_HARDDISK; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyHD; + OldData = CallbackData->BmmOldFakeNVData.LegacyHD; + break; + + case FORM_SET_CD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; + Key = LEGACY_CD_QUESTION_ID; + TypeStr = StrCDROM; + TypeStrHelp = StrCDROMHelp; + BbsType = BBS_CDROM; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyCD; + OldData = CallbackData->BmmOldFakeNVData.LegacyCD; + break; + + case FORM_SET_NET_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; + Key = LEGACY_NET_QUESTION_ID; + TypeStr = StrNET; + TypeStrHelp = StrNETHelp; + BbsType = BBS_EMBED_NETWORK; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyNET; + OldData = CallbackData->BmmOldFakeNVData.LegacyNET; + break; + + case FORM_SET_BEV_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; + Key = LEGACY_BEV_QUESTION_ID; + TypeStr = StrBEV; + TypeStrHelp = StrBEVHelp; + BbsType = BBS_BEV_DEVICE; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyBEV; + OldData = CallbackData->BmmOldFakeNVData.LegacyBEV; + break; + + } + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1)); + if (NULL == IfrOptionList) { + return ; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + if (0 == Index) { + IfrOptionList[Index].Flags |= EFI_IFR_FLAG_DEFAULT; + } + + IfrOptionList[Index].Key = Key; + IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken; + IfrOptionList[Index].Value = (UINT16) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index; + IfrOptionList[Index].OptionString = NULL; + } + // + // for item "Disabled" + // + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + IfrOptionList[Index].Key = Key; + IfrOptionList[Index].StringToken = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE); + IfrOptionList[Index].Value = 0xFF; + IfrOptionList[Index].OptionString = NULL; + + // + // Get Device Order from variable + // + VarData = BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &VarSize + ); + + if (NULL != VarData) { + OriginalPtr = VarData; + DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData; + while (VarData < VarData + VarSize) { + if (DevOrder->BbsType == BbsType) { + break; + } + + VarData += sizeof (BBS_TYPE); + VarData += *(UINT16 *) VarData; + DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData; + } + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + for (Index2 = 0; Index2 <= OptionMenu->MenuNumber; Index2++) { + IfrOptionList[Index2].Key = (UINT16) (Key + Index); + } + // + // Create the string for oneof tag + // + UnicodeSPrint (String, sizeof (String), TypeStr, Index); + StrRef = 0; + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->BmmHiiHandle, + &StrRef, + String + ); + + UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); + StrRefHelp = 0; + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->BmmHiiHandle, + &StrRefHelp, + String + ); + + CreateOneOfOpCode ( + (UINT16) (Key + Index), + (UINT8) 1, + StrRef, + StrRefHelp, + IfrOptionList, + OptionMenu->MenuNumber + 1, + Location + ); + + VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16)); + + if (0xFF00 == (VarDevOrder & 0xFF00)) { + LegacyOrder[Index] = 0xFF; + Pos = (VarDevOrder & 0xFF) / 8; + Bit = 7 - ((VarDevOrder & 0xFF) % 8); + DisMap[Pos] |= (UINT8) (1 << Bit); + } else { + LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF); + } + + Location = Location + (OptionMenu->MenuNumber + 2) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT16) (UpdateData->DataCount + (OptionMenu->MenuNumber + 3)); + } + } + + CopyMem ( + OldData, + LegacyOrder, + 100 + ); + + if (IfrOptionList != NULL) { + SafeFreePool (IfrOptionList); + IfrOptionList = NULL; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ) +{ + UINT16 FileOptionMask; + + FileOptionMask = (UINT16) (FILE_OPTION_MASK & NewPageId); + + if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) { + // + // If we select a handle to add driver option, advance to the add handle description page. + // + NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID; + } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) { + // + // Return to main page after "Save Changes" or "Discard Changes". + // + NewPageId = FORM_MAIN_ID; + } + + if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) { + Private->BmmPreviousPageId = Private->BmmCurrentPageId; + Private->BmmCurrentPageId = NewPageId; + } +} 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; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c new file mode 100644 index 0000000000..4cdad1c03a --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c @@ -0,0 +1,355 @@ +/*++ + +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: + + BootManager.c + +Abstract: + + The platform boot manager reference implement + +--*/ +#include "BootManager.h" + +UINT16 mKeyInput; +LIST_ENTRY *mBootOptionsList; +BDS_COMMON_OPTION *gOption; +EFI_HII_HANDLE gBootManagerHandle; +EFI_HANDLE BootManagerCallbackHandle; +EFI_FORM_CALLBACK_PROTOCOL BootManagerCallback; +EFI_GUID gBmGuid = BOOT_MANAGER_GUID; + +extern EFI_FORM_BROWSER_PROTOCOL *gBrowser; +extern UINT8 BootManagerVfrBin[]; +extern UINT8 EdkGenericPlatformBdsLibStrings[]; +extern BOOLEAN gConnectAllHappened; + +EFI_STATUS +EFIAPI +BootManagerCallbackRoutine ( + 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: + +--*/ +{ + BDS_COMMON_OPTION *Option; + LIST_ENTRY *Link; + UINT16 KeyCount; + EFI_HII_CALLBACK_PACKET *DataPacket; + + // + // Initialize the key count + // + KeyCount = 0; + + for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + KeyCount++; + + gOption = Option; + + // + // Is this device the one chosen? + // + if (KeyCount == KeyValue) { + // + // Assigning the returned Key to a global allows the original routine to know what was chosen + // + mKeyInput = KeyValue; + + *Packet = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2); + ASSERT (*Packet != NULL); + + // + // Assign the buffer address to DataPacket + // + DataPacket = *Packet; + + DataPacket->DataArray.EntryCount = 1; + DataPacket->DataArray.NvRamMap = NULL; + ((EFI_IFR_DATA_ENTRY *) (((EFI_IFR_DATA_ARRAY *)DataPacket) + 1))->Flags = EXIT_REQUIRED | NV_NOT_CHANGED; + return EFI_SUCCESS; + } else { + continue; + } + } + + return EFI_SUCCESS; +} + +VOID +CallBootManager ( + VOID + ) +/*++ + +Routine Description: + Hook to enable UI timeout override behavior. + +Arguments: + BdsDeviceList - Device List that BDS needs to connect. + + Entry - Pointer to current Boot Entry. + +Returns: + NONE + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + BDS_COMMON_OPTION *Option; + LIST_ENTRY *Link; + EFI_HII_UPDATE_DATA *UpdateData; + CHAR16 *ExitData; + UINTN ExitDataSize; + STRING_REF Token; + STRING_REF LastToken; + EFI_INPUT_KEY Key; + UINT8 *Location; + EFI_GUID BmGuid; + LIST_ENTRY BdsBootOptionList; + BOOLEAN BootMngrMenuResetRequired; + + gOption = NULL; + InitializeListHead (&BdsBootOptionList); + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + // + // BugBug: Here we can not remove the legacy refresh macro, so we need + // get the boot order every time from "BootOrder" variable. + // Recreate the boot option list base on the BootOrder variable + // + BdsLibEnumerateAllBootOption (&BdsBootOptionList); + + // + // This GUID must be the same as what is defined in BootManagerVfr.vfr + // + BmGuid = gBmGuid; + + mBootOptionsList = &BdsBootOptionList; + + // + // Post our VFR to the HII database + // + PackageList = PreparePackages (2, &BmGuid, BootManagerVfrBin, EdkGenericPlatformBdsLibStrings); + Status = Hii->NewPack (Hii, PackageList, &gBootManagerHandle); + gBS->FreePool (PackageList); + + // + // This example does not implement worker functions + // for the NV accessor functions. Only a callback evaluator + // + BootManagerCallback.NvRead = NULL; + BootManagerCallback.NvWrite = NULL; + BootManagerCallback.Callback = BootManagerCallbackRoutine; + + // + // Install protocol interface + // + BootManagerCallbackHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &BootManagerCallbackHandle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &BootManagerCallback + ); + ASSERT_EFI_ERROR (Status); + + LastToken = 0; + Hii->NewString (Hii, NULL, gBootManagerHandle, &LastToken, L" "); + + // + // Allocate space for creation of UpdateData Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + // + // Flag update pending in FormSet + // + UpdateData->FormSetUpdate = TRUE; + // + // Register CallbackHandle data for FormSet + // + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) BootManagerCallbackHandle; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + // + // Create blank space. Since when we update the contents of IFR data at a label, it is + // inserted at the location of the label. So if you want to add a string with an empty + // space afterwards, you need to add the space first and then the string like below. + // + Status = CreateSubTitleOpCode ( + LastToken, // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData); + + // + // Create "Boot Option Menu" title + // + Status = CreateSubTitleOpCode ( + STRING_TOKEN (STR_BOOT_OPTION_BANNER), // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData); + + Token = LastToken; + mKeyInput = 0; + + UpdateData->DataCount = 0; + Location = (UINT8 *) &UpdateData->Data; + + for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // At this stage we are creating a menu entry, thus the Keys are reproduceable + // + mKeyInput++; + Token++; + + Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description); + + // + // If we got an error it is almost certainly due to the token value being invalid. + // Therefore we will set the Token to 0 to automatically add a token. + // + if (EFI_ERROR (Status)) { + Token = 0; + Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description); + } + + Status = CreateGotoOpCode ( + 0x1000, // Form ID + Token, // Token Value for the string + 0, // Help String (none) + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // The Op-Code flags + mKeyInput, // The Key to get a callback on + Location // Buffer containing created op-code + ); + + UpdateData->DataCount++; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + } + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0001, TRUE, UpdateData); + + UpdateData->DataCount = 1; + + // + // Create "Boot Option Menu" title + // + Status = CreateSubTitleOpCode ( + STRING_TOKEN (STR_HELP_FOOTER), // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData); + + Status = CreateSubTitleOpCode ( + LastToken, // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData); + + gBS->FreePool (UpdateData); + + ASSERT (gBrowser); + + BootMngrMenuResetRequired = FALSE; + gBrowser->SendForm ( + gBrowser, + TRUE, + &gBootManagerHandle, + 1, + NULL, + NULL, + NULL, + NULL, + &BootMngrMenuResetRequired + ); + + if (BootMngrMenuResetRequired) { + EnableResetRequired (); + } + + Hii->ResetStrings (Hii, gBootManagerHandle); + + if (gOption == NULL) { + return ; + } + + // + //Will leave browser, check any reset required change is applied? if yes, reset system + // + SetupResetReminder (); + + // + // BugBug: This code looks repeated from the BDS. Need to save code space. + // + + // + // parse the selected option + // + Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); + + if (!EFI_ERROR (Status)) { + PlatformBdsBootSuccess (gOption); + } else { + PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); + gST->ConOut->OutputString ( + gST->ConOut, + GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) + ); + + // + // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0); + // + + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + } +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.h new file mode 100644 index 0000000000..f9b6bbafb0 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.h @@ -0,0 +1,50 @@ +/*++ + +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: + + BootManager.h + +Abstract: + + The platform boot manager reference implement + +Revision History + +--*/ + +#ifndef _EFI_BOOT_MANAGER_H +#define _EFI_BOOT_MANAGER_H + +#include "Bds.h" +//#include "EdkGenericPlatformBdsLib.h" +#include "String.h" + +EFI_STATUS +EFIAPI +BootManagerCallbackRoutine ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *DataArray, + OUT EFI_HII_CALLBACK_PACKET **Packet + ); + +VOID +CallBootManager ( + VOID +); + +#define BOOT_MANAGER_GUID \ + { \ + 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } \ + } + +#endif diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni new file mode 100644 index 0000000000..684ac2f348 Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni differ diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerVfr.Vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerVfr.Vfr new file mode 100644 index 0000000000..9daf7b8226 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerVfr.Vfr @@ -0,0 +1,55 @@ +// *++ +// +// 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: +// +// BootManager.vfr +// +// Abstract: +// +// Browser formset. +// +// Revision History: +// +// --*/ + +#include "EdkGenericPlatformBdsLibStrDefs.h" + +#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, { 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } } + +#define BOOT_MANAGER_HEADER 0x00 +#define BOOT_MANAGER_LABEL 0x01 +#define BOOT_MANAGER_TAIL 0x02 + + +#define BOOT_MANAGER_CLASS 0x00 +#define BOOT_MANAGER_SUBCLASS 0x01 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_BM_BANNER), + help = STRING_TOKEN(STR_LAST_STRING), + class = BOOT_MANAGER_CLASS, + subclass = BOOT_MANAGER_SUBCLASS, + + form formid = 0x1000, + title = STRING_TOKEN(STR_BM_BANNER); + + label BOOT_MANAGER_HEADER; + label BOOT_MANAGER_LABEL; + // + // This is where we will dynamically add choices for the Boot Manager + // + + label BOOT_MANAGER_TAIL; + endform; + +endformset; diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Capsules.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Capsules.c new file mode 100644 index 0000000000..23b83a3c44 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Capsules.c @@ -0,0 +1,213 @@ +/*++ + +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: + + Capsules.c + +Abstract: + + BDS routines to handle capsules. + +--*/ + + +#include + +VOID +BdsLockFv ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN EFI_FLASH_SUBAREA_ENTRY *FlashEntry + ); + +VOID +BdsLockFv ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN EFI_FLASH_SUBAREA_ENTRY *FlashEntry + ) +{ + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT64 BaseAddress; + UINT8 Data; + UINT32 BlockLength; + UINTN Index; + + BaseAddress = FlashEntry->Base - 0x400000 + 2; + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (FlashEntry->Base)); + BlockMap = &(FvHeader->FvBlockMap[0]); + + while ((BlockMap->NumBlocks != 0) && (BlockMap->BlockLength != 0)) { + BlockLength = BlockMap->BlockLength; + for (Index = 0; Index < BlockMap->NumBlocks; Index++) { + CpuIo->Mem.Read ( + CpuIo, + EfiCpuIoWidthUint8, + BaseAddress, + 1, + &Data + ); + Data = (UINT8) (Data | 0x3); + CpuIo->Mem.Write ( + CpuIo, + EfiCpuIoWidthUint8, + BaseAddress, + 1, + &Data + ); + BaseAddress += BlockLength; + } + + BlockMap++; + } +} + +VOID +BdsLockNonUpdatableFlash ( + VOID + ) +{ + EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntryData; + EFI_PEI_HOB_POINTERS GuidHob; + EFI_STATUS Status; + EFI_CPU_IO_PROTOCOL *CpuIo; + + Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (VOID**)&CpuIo); + ASSERT_EFI_ERROR (Status); + + GuidHob.Raw = GetHobList (); + while ((GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw)) != NULL) { + FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid); + + // + // Get the variable store area + // + if ((FlashMapEntryData->AreaType == EFI_FLASH_AREA_RECOVERY_BIOS) || + (FlashMapEntryData->AreaType == EFI_FLASH_AREA_MAIN_BIOS) + ) { + BdsLockFv (CpuIo, &(FlashMapEntryData->Entries[0])); + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + + return ; +} + +EFI_STATUS +ProcessCapsules ( + EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This routine is called to see if there are any capsules we need to process. + If the boot mode is not UPDATE, then we do nothing. Otherwise find the + capsule HOBS and produce firmware volumes for them via the DXE service. + Then call the dispatcher to dispatch drivers from them. Finally, check + the status of the updates. + +Arguments: + + BootMode - the current boot mode + +Returns: + + EFI_INVALID_PARAMETER - boot mode is not correct for an update + +Note: + + This function should be called by BDS in case we need to do some + sort of processing even if there is no capsule to process. We + need to do this if an earlier update went awry and we need to + clear the capsule variable so on the next reset PEI does not see it and + think there is a capsule available. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_CAPSULE_VOLUME *CvHob; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_HANDLE FvProtocolHandle; + + // + // We don't do anything else if the boot mode is not flash-update + // + if (BootMode != BOOT_ON_FLASH_UPDATE) { + return EFI_INVALID_PARAMETER; + } + // + // Only one capsule HOB allowed. + // + CvHob = GetFirstHob (EFI_HOB_TYPE_CV); + if (CvHob == NULL) { + // + // We didn't find a hob, so had no errors. + // + BdsLockNonUpdatableFlash (); + return EFI_SUCCESS; + } + + BaseAddress = CvHob->BaseAddress; + Length = CvHob->Length; + + Status = EFI_SUCCESS; + // + // Now walk the capsule and call the core to process each + // firmware volume in it. + // + while (Length != 0) { + // + // Point to the next firmware volume header, and then + // call the DXE service to process it. + // + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + if (FwVolHeader->FvLength > Length) { + // + // Notes: need to stuff this status somewhere so that the + // error can be detected at OS runtime + // + Status = EFI_VOLUME_CORRUPTED; + break; + } + + Status = gDS->ProcessFirmwareVolume ( + (VOID *) (UINTN) BaseAddress, + (UINTN) FwVolHeader->FvLength, + &FvProtocolHandle + ); + if (EFI_ERROR (Status)) { + break; + } + // + // Call the dispatcher to dispatch any drivers from the produced firmware volume + // + gDS->Dispatch (); + // + // On to the next FV in the capsule + // + Length -= FwVolHeader->FvLength; + BaseAddress = (EFI_PHYSICAL_ADDRESS) ((UINTN) BaseAddress + FwVolHeader->FvLength); + // + // Notes: when capsule spec is finalized, if the requirement is made to + // have each FV in a capsule aligned, then we will need to align the + // BaseAddress and Length here. + // + } + + + BdsLockNonUpdatableFlash (); + + return Status; +} + diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.c new file mode 100644 index 0000000000..3de404ba7c --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.c @@ -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; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.h new file mode 100644 index 0000000000..54aeb4508d --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.h @@ -0,0 +1,59 @@ +/*++ + +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 + +Revision History + +--*/ + +#ifndef _DEVICE_MANAGER_H +#define _DEVICE_MANAGER_H + +#include "FrontPage.h" + +#define EFI_NON_DEVICE_CLASS 0x00 // Useful when you do not want something in the Device Manager +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 + +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 + ) +; + +EFI_STATUS +InitializeDeviceManager ( + VOID + ) +; + +EFI_STATUS +CallDeviceManager ( + VOID + ) +; + +#endif diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni new file mode 100644 index 0000000000..f549ff28ac Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni differ diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerVfr.Vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerVfr.Vfr new file mode 100644 index 0000000000..34195831a8 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerVfr.Vfr @@ -0,0 +1,75 @@ +// *++ +// +// 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: +// +// DeviceManagerVfr.vfr +// +// Abstract: +// +// Device Manager formset. +// +// Revision History: +// +// --*/ + +#include "EdkGenericPlatformBdsLibStrDefs.h" + +#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, { 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 } } + +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 +#define EFI_VBIOS_CLASS 0x40 + +#define DEVICE_MANAGER_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0003 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE), + help = STRING_TOKEN(STR_EMPTY_STRING), + class = DEVICE_MANAGER_CLASS, + subclass = FRONT_PAGE_SUBCLASS, + + form formid = 0x1000, + title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE); + + // + // This is where devices get added to the device manager hierarchy + // + subtitle text = STRING_TOKEN(STR_DISK_DEVICE); + label EFI_DISK_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_VIDEO_DEVICE); + label EFI_VIDEO_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE); + label EFI_NETWORK_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_INPUT_DEVICE); + label EFI_INPUT_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_ON_BOARD_DEVICE); + label EFI_ON_BOARD_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_OTHER_DEVICE); + label EFI_OTHER_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label EFI_VBIOS_CLASS; + + endform; +endformset; + diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/EdkGenericPlatformBdsLib.msa b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/EdkGenericPlatformBdsLib.msa new file mode 100644 index 0000000000..828ab8d100 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/EdkGenericPlatformBdsLib.msa @@ -0,0 +1,230 @@ + + + + EdkPlatformGenericBdsLib + DXE_DRIVER + f392b762-8985-11db-be87-0040d02b1835 + 1.0 + Generic BDS library + Do generic action. + 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + EdkGenericPlatformBdsLib + + + + DebugLib + + + UefiLib + + + UefiDriverEntryPoint + + + BaseLib + + + EdkGraphicsLib + + + DxeServicesTableLib + + + PerformanceLib + + + PrintLib + + + EdkIfrSupportLib + + + ReportStatusCodeLib + + + HobLib + + + EdkGenericBdsLib + + + MemoryAllocationLib + + + BaseMemoryLib + + + UefiBootServicesTableLib + + + UefiRuntimeServicesTableLib + + + DevicePathLib + + + HiiLib + + + EdkGenericPlatformBdsLib + + + PeCoffLib + + + + Bds.h + BdsEntry.c + BdsBoot.c + FrontPage.h + FrontPage.c + FrontPageStrings.uni + FrontPageVfr.Vfr + Language.h + Language.c + String.h + String.c + Strings.uni + Capsules.c + MemoryTest.c + BootMaint/BmString.uni + BootMaint/Bm.vfr + BootMaint/BBSsupport.h + BootMaint/BootMaint.h + BootMaint/FormGuid.h + BootMaint/BmLib.c + BootMaint/BootOption.c + BootMaint/ConsoleOption.c + BootMaint/Data.c + BootMaint/Variable.c + BootMaint/UpdatePage.c + BootMaint/BBSsupport.c + BootMaint/BootMaint.c + BootMaint/FileExplorer.c + BootMaint/FE.vfr + BootMngr/BootManager.h + BootMngr/BootManager.c + BootMngr/BootManagerStrings.uni + BootMngr/BootManagerVfr.Vfr + DeviceMngr/DeviceManager.h + DeviceMngr/DeviceManager.c + DeviceMngr/DeviceManagerStrings.uni + DeviceMngr/DeviceManagerVfr.Vfr + + + + + + + + + gEfiBdsArchProtocolGuid + + + gEfiLegacyBiosProtocolGuid + + + gEfiUgaSplashProtocolGuid + + + gEfiHiiProtocolGuid + + + gEfiFormCallbackProtocolGuid + + + gEfiDataHubProtocolGuid + + + gEfiFormBrowserProtocolGuid + + + gEfiConsoleControlProtocolGuid + + + gEfiCpuIoProtocolGuid + + + gEfiUgaDrawProtocolGuid + + + gEfiLoadFileProtocolGuid + + + gEfiSimpleFileSystemProtocolGuid + + + gEfiDevicePathProtocolGuid + + + gEfiBlockIoProtocolGuid + + + gEfiSerialIoProtocolGuid + + + gEfiGenericMemTestProtocolGuid + + + gEfiCpuArchProtocolGuid + + + gEfiDriverBindingProtocolGuid + + + + + BiosVendor + + + SystemManufacturer + + + ProcessorVersion + + + ProcessorFrequency + + + MemoryArray + + + SerialIoDevice + + + SerialIoPort + + + + + gEfiBootStateGuid + + + gEfiGlobalVariableGuid + + + gEfiFlashMapHobGuid + + + gEfiFileSystemVolumeLabelInfoIdGuid + + + gEfiFileInfoGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.c new file mode 100644 index 0000000000..bcbde1a793 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.c @@ -0,0 +1,901 @@ +/*++ + +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: + + FrontPage.c + +Abstract: + + FrontPage routines to handle the callbacks and browser calls + +--*/ + +#include "Bds.h" +#include "FrontPage.h" +#include "String.h" + +EFI_GUID mProcessorSubClass = EFI_PROCESSOR_SUBCLASS_GUID; +EFI_GUID mMemorySubClass = EFI_MEMORY_SUBCLASS_GUID; +EFI_GUID mMiscSubClass = EFI_MISC_SUBCLASS_GUID; + +UINT16 mLastSelection; +EFI_HII_HANDLE gFrontPageHandle; +EFI_HANDLE FrontPageCallbackHandle; +EFI_FORM_CALLBACK_PROTOCOL FrontPageCallback; +EFI_FORM_BROWSER_PROTOCOL *gBrowser; +UINTN gCallbackKey; +BOOLEAN gConnectAllHappened = FALSE; + +extern EFI_HII_HANDLE gFrontPageHandle; +extern EFI_GUID gBdsStringPackGuid; + +EFI_STATUS +EFIAPI +FrontPageCallbackRoutine ( + 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: + +--*/ +{ + CHAR16 *LanguageString; + UINTN Count; + CHAR16 UnicodeLang[3]; + CHAR8 Lang[3]; + EFI_STATUS Status; + UINTN Index; + CHAR16 *TmpStr; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + + 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); + + Count = 0; + + // + // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can + // describe to their customers in documentation how to find their setup information (namely + // under the device manager and specific buckets) + // + switch (KeyValue) { + case 0x0001: + // + // This is the continue - clear the screen and return an error to get out of FrontPage loop + // + gCallbackKey = 1; + break; + + case 0x1234: + // + // Collect the languages from what our current Language support is based on our VFR + // + Hii->GetPrimaryLanguages (Hii, gFrontPageHandle, &LanguageString); + + // + // Based on the DataArray->Data->Data value, we can determine + // which language was chosen by the user + // + for (Index = 0; Count != (UINTN) (((EFI_IFR_DATA_ENTRY *) (DataArray + 1))->Data); Index += 3) { + Count++; + } + // + // Preserve the choice the user made + // + mLastSelection = (UINT16) Count; + + // + // The Language (in Unicode format) the user chose + // + CopyMem (UnicodeLang, &LanguageString[Index], 6); + + // + // Convert Unicode to ASCII (Since the ISO standard assumes ASCII equivalent abbreviations + // we can be safe in converting this Unicode stream to ASCII without any loss in meaning. + // + for (Index = 0; Index < 3; Index++) { + Lang[Index] = (CHAR8) UnicodeLang[Index]; + } + + Status = gRT->SetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 3, + Lang + ); + + gBS->FreePool (LanguageString); + gCallbackKey = 2; + break; + + case 0x1064: + // + // Boot Manager + // + gCallbackKey = 3; + break; + + case 0x8567: + // + // Device Manager + // + gCallbackKey = 4; + break; + + case 0x9876: + // + // Boot Maintenance Manager + // + gCallbackKey = 5; + break; + + case 0xFFFE: + + break; + + case 0xFFFF: + // + // FrontPage TimeOut Callback + // + TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + (UINTN) (((EFI_IFR_DATA_ENTRY *) (DataArray+1))->Data), + 0 + ); + gBS->FreePool (TmpStr); + } + break; + + default: + gCallbackKey = 0; + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeFrontPage ( + BOOLEAN ReInitializeStrings + ) +/*++ + +Routine Description: + + Initialize HII information for the FrontPage + +Arguments: + None + +Returns: + EFI_SUCCESS - The operation is successful. + EFI_DEVICE_ERROR - If the dynamic opcode creation failed. + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + EFI_HII_UPDATE_DATA *UpdateData; + IFR_OPTION *OptionList; + CHAR16 *LanguageString; + UINTN OptionCount; + UINTN Index; + STRING_REF Token; + UINT16 Key; + CHAR8 AsciiLang[4]; + CHAR16 UnicodeLang[4]; + CHAR16 Lang[4]; + CHAR16 *StringBuffer; + UINTN BufferSize; + UINT8 *TempBuffer; + + UpdateData = NULL; + OptionList = NULL; + + if (ReInitializeStrings) { + // + // BugBug: Dont' use a goto + // + goto ReInitStrings; + } + // + // Go ahead and initialize the Device Manager + // + InitializeDeviceManager (); + + // + // BugBug: if FrontPageVfrBin is generated by a tool, why are we patching it here + // + TempBuffer = (UINT8 *) FrontPageVfrBin; + TempBuffer = TempBuffer + sizeof (EFI_HII_PACK_HEADER); + TempBuffer = (UINT8 *) &((EFI_IFR_FORM_SET *) TempBuffer)->NvDataSize; + *TempBuffer = 1; + + gCallbackKey = 0; + + PackageList = PreparePackages (1, &gBdsStringPackGuid, FrontPageVfrBin); + + Status = Hii->NewPack (Hii, PackageList, &gFrontPageHandle); + + gBS->FreePool (PackageList); + + // + // There will be only one FormConfig in the system + // If there is another out there, someone is trying to install us + // again. Fail that scenario. + // + Status = gBS->LocateProtocol ( + &gEfiFormBrowserProtocolGuid, + NULL, + (VOID**)&gBrowser + ); + + // + // This example does not implement worker functions + // for the NV accessor functions. Only a callback evaluator + // + FrontPageCallback.NvRead = NULL; + FrontPageCallback.NvWrite = NULL; + FrontPageCallback.Callback = FrontPageCallbackRoutine; + + // + // Install protocol interface + // + FrontPageCallbackHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &FrontPageCallbackHandle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &FrontPageCallback + ); + ASSERT_EFI_ERROR (Status); + +ReInitStrings: + // + // BugBug: This logic is in BdsInitLanguage. It should not be in two places! + // + BufferSize = 4; + Status = gRT->GetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &BufferSize, + AsciiLang + ); + + for (Index = 0; Index < 3; Index++) { + UnicodeLang[Index] = (CHAR16) AsciiLang[Index]; + } + + UnicodeLang[3] = 0; + + // + // Allocate space for creation of UpdateData Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + OptionList = AllocateZeroPool (0x1000); + ASSERT (OptionList != NULL); + + // + // Flag update pending in FormSet + // + UpdateData->FormSetUpdate = TRUE; + // + // Register CallbackHandle data for FormSet + // + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FrontPageCallbackHandle; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + // + // Collect the languages from what our current Language support is based on our VFR + // + Hii->GetPrimaryLanguages (Hii, gFrontPageHandle, &LanguageString); + + OptionCount = 0; + + // + // Try for a 512 byte Buffer + // + BufferSize = 0x200; + + // + // Allocate memory for our Form binary + // + StringBuffer = AllocateZeroPool (BufferSize); + ASSERT (StringBuffer != NULL); + + for (Index = 0; LanguageString[Index] != 0; Index += 3) { + Token = 0; + CopyMem (Lang, &LanguageString[Index], 6); + Lang[3] = 0; + + if (!StrCmp (Lang, UnicodeLang)) { + mLastSelection = (UINT16) OptionCount; + } + + Status = Hii->GetString (Hii, gStringPackHandle, 1, TRUE, Lang, &BufferSize, StringBuffer); + Hii->NewString (Hii, NULL, gStringPackHandle, &Token, StringBuffer); + CopyMem (&OptionList[OptionCount].StringToken, &Token, sizeof (UINT16)); + CopyMem (&OptionList[OptionCount].Value, &OptionCount, sizeof (UINT16)); + Key = 0x1234; + CopyMem (&OptionList[OptionCount].Key, &Key, sizeof (UINT16)); + OptionList[OptionCount].Flags = EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS; + OptionCount++; + } + + gBS->FreePool (LanguageString); + + if (ReInitializeStrings) { + gBS->FreePool (StringBuffer); + gBS->FreePool (OptionList); + return EFI_SUCCESS; + } + + Status = CreateOneOfOpCode ( + FRONT_PAGE_QUESTION_ID, // Question ID + FRONT_PAGE_DATA_WIDTH, // Data Width + (STRING_REF) STRING_TOKEN (STR_LANGUAGE_SELECT), // Prompt Token + (STRING_REF) STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), // Help Token + OptionList, // List of Options + OptionCount, // Number of Options + &UpdateData->Data // Data Buffer + ); + + // + // Assign the number of options and the oneof and endoneof op-codes to count + // + UpdateData->DataCount = (UINT8) (OptionCount + 2); + + Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData); + + gBS->FreePool (UpdateData); + // + // gBS->FreePool (OptionList); + // + gBS->FreePool (StringBuffer); + return Status; +} + +EFI_STATUS +CallFrontPage ( + VOID + ) +/*++ + +Routine Description: + + Call the browser and display the front page + +Arguments: + + None + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINT8 FakeNvRamMap[1]; + BOOLEAN FrontPageMenuResetRequired; + + // + // Begin waiting for USER INPUT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT) + ); + + FakeNvRamMap[0] = (UINT8) mLastSelection; + FrontPageMenuResetRequired = FALSE; + Status = gBrowser->SendForm ( + gBrowser, + TRUE, // Use the database + &gFrontPageHandle, // The HII Handle + 1, + NULL, + FrontPageCallbackHandle, // This is the handle that the interface to the callback was installed on + FakeNvRamMap, + NULL, + &FrontPageMenuResetRequired + ); + // + // Check whether user change any option setting which needs a reset to be effective + // + if (FrontPageMenuResetRequired) { + EnableResetRequired (); + } + + Hii->ResetStrings (Hii, gFrontPageHandle); + + return Status; +} + +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Acquire the string associated with the ProducerGuid and return it. + +Arguments: + + ProducerGuid - The Guid to search the HII database for + Token - The token value of the string to extract + String - The string that is extracted + +Returns: + + EFI_SUCCESS - The function returns EFI_SUCCESS always. + +--*/ +{ + EFI_STATUS Status; + UINT16 HandleBufferLength; + EFI_HII_HANDLE *HiiHandleBuffer; + UINTN StringBufferLength; + UINTN NumberOfHiiHandles; + UINTN Index; + UINT16 Length; + EFI_GUID HiiGuid; + + // + // Initialize params. + // + HandleBufferLength = 0; + HiiHandleBuffer = NULL; + + // + // Get all the Hii handles + // + Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandleBuffer); + ASSERT_EFI_ERROR (Status); + + // + // Get the Hii Handle that matches the StructureNode->ProducerName + // + NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < NumberOfHiiHandles; Index++) { + Length = 0; + Status = ExtractDataFromHiiHandle ( + HiiHandleBuffer[Index], + &Length, + NULL, + &HiiGuid + ); + if (CompareGuid (ProducerGuid, &HiiGuid)) { + break; + } + } + // + // Find the string based on the current language + // + StringBufferLength = 0x100; + *String = AllocateZeroPool (0x100); + Status = Hii->GetString ( + Hii, + HiiHandleBuffer[Index], + Token, + FALSE, + NULL, + &StringBufferLength, + *String + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (*String); + *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); + } + + gBS->FreePool (HiiHandleBuffer); + return EFI_SUCCESS; +} + +VOID +ConvertProcessorToString ( + IN EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Convert Processor Frequency Data to a string + +Arguments: + + ProcessorFrequency - The frequency data to process + String - The string that is created + +Returns: + +--*/ +{ + CHAR16 *StringBuffer; + UINTN Index; + UINT32 FreqMhz; + + if (ProcessorFrequency->Exponent >= 6) { + FreqMhz = ProcessorFrequency->Value; + for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) { + FreqMhz *= 10; + } + } else { + FreqMhz = 0; + } + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3); + StrCat (StringBuffer, L"."); + UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2); + StrCat (StringBuffer, L" GHz"); + + *String = (CHAR16 *) StringBuffer; + + return ; +} + +VOID +ConvertMemorySizeToString ( + IN UINT32 MemorySize, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Convert Memory Size to a string + +Arguments: + + MemorySize - The size of the memory to process + String - The string that is created + +Returns: + +--*/ +{ + CHAR16 *StringBuffer; + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6); + StrCat (StringBuffer, L" MB RAM"); + + *String = (CHAR16 *) StringBuffer; + + return ; +} + +VOID +UpdateFrontPageStrings ( + VOID + ) +/*++ + +Routine Description: + + Update the banner information for the Front Page based on DataHub information + +Arguments: + + None + +Returns: + +--*/ +{ + EFI_STATUS Status; + STRING_REF TokenToUpdate; + CHAR16 *NewString; + UINT64 MonotonicCount; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + EFI_MISC_BIOS_VENDOR_DATA *BiosVendor; + EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer; + EFI_PROCESSOR_VERSION_DATA *ProcessorVersion; + EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency; + EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray; + CHAR8 LangCode[3]; + CHAR16 Lang[3]; + UINTN Size; + UINTN Index; + BOOLEAN Find[5]; + + ZeroMem (Find, sizeof (Find)); + + // + // Update Front Page strings + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID**)&DataHub + ); + ASSERT_EFI_ERROR (Status); + + Size = 3; + + Status = gRT->GetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + LangCode + ); + + for (Index = 0; Index < 3; Index++) { + Lang[Index] = (CHAR16) LangCode[Index]; + } + + MonotonicCount = 0; + Record = NULL; + do { + Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record); + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) && + (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER) + ) { + BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1); + GetStringFromToken (&Record->ProducerName, BiosVendor->BiosVersion, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_BIOS_VERSION; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[0] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) && + (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER) + ) { + SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1); + GetStringFromToken (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_COMPUTER_MODEL; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[1] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mProcessorSubClass) && + (DataHeader->RecordType == ProcessorVersionRecordType) + ) { + ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1); + GetStringFromToken (&Record->ProducerName, *ProcessorVersion, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_CPU_MODEL; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[2] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mProcessorSubClass) && + (DataHeader->RecordType == ProcessorCoreFrequencyRecordType) + ) { + ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1); + ConvertProcessorToString (ProcessorFrequency, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_CPU_SPEED; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[3] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mMemorySubClass) && + (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER) + ) { + MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1); + ConvertMemorySizeToString((UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - + MemoryArray->MemoryArrayStartAddress + 1), 20)), + &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_MEMORY_SIZE; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[4] = TRUE; + } + } + } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4])); + + return ; +} + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ) +/*++ + +Routine Description: + This function is the main entry of the platform setup entry. + The function will present the main menu of the system setup, + this is the platform reference part and can be customize. + +Arguments: + TimeoutDefault - The fault time out value before the system + continue to boot. + ConnectAllHappened - The indicater to check if the connect all have + already happended. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_HII_UPDATE_DATA *UpdateData; + EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; + + // + // Indicate if we need connect all in the platform setup + // + if (ConnectAllHappened) { + gConnectAllHappened = TRUE; + } + // + // Allocate space for creation of Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + UpdateData->FormSetUpdate = FALSE; + UpdateData->FormCallbackHandle = 0; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + // + // Remove Banner Op-code if any at this label + // + Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0xFFFF, FALSE, UpdateData); + + // + // Create Banner Op-code which reflects correct timeout value + // + CreateBannerOpCode ( + STRING_TOKEN (STR_TIME_OUT_PROMPT), + TimeoutDefault, + (UINT8) EFI_IFR_BANNER_TIMEOUT, + &UpdateData->Data + ); + + // + // Add Banner Op-code at this label + // + Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0xFFFF, TRUE, UpdateData); + + do { + + InitializeFrontPage (TRUE); + + // + // Update Front Page strings + // + UpdateFrontPageStrings (); + + gCallbackKey = 0; + PERF_START (0, "BdsTimeOut", "BDS", 0); + Status = CallFrontPage (); + PERF_END (0, "BdsTimeOut", "BDS", 0); + + // + // If gCallbackKey is greater than 1 and less or equal to 5, + // it will lauch configuration utilities. + // 2 = set language + // 3 = boot manager + // 4 = device manager + // 5 = boot maintainenance manager + // + if ((gCallbackKey > 0x0001) && (gCallbackKey <= 0x0005)) { + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) + ); + } + // + // Based on the key that was set, we can determine what to do + // + switch (gCallbackKey) { + // + // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can + // describe to their customers in documentation how to find their setup information (namely + // under the device manager and specific buckets) + // + // These entries consist of the Continue, Select language, Boot Manager, and Device Manager + // + case 0x0001: + // + // User hit continue + // + break; + + case 0x0002: + // + // User made a language setting change - display front page again + // + break; + + case 0x0003: + // + // User chose to run the Boot Manager + // + CallBootManager (); + break; + + case 0x0004: + // + // Display the Device Manager + // + do { + CallDeviceManager(); + } while (gCallbackKey == 4); + break; + + case 0x0005: + // + // Display the Boot Maintenance Manager + // + BdsStartBootMaint (); + break; + } + + } while ((Status == EFI_SUCCESS) && (gCallbackKey != 1)); + + // + //Will leave browser, check any reset required change is applied? if yes, reset system + // + SetupResetReminder (); + + // + // Automatically load current entry + // Note: The following lines of code only execute when Auto boot + // takes affect + // + Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID**)&ConsoleControl); + ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText); + +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.h new file mode 100644 index 0000000000..2899125428 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.h @@ -0,0 +1,94 @@ +/*++ + +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: + + FrontPage.h + +Abstract: + + FrontPage routines to handle the callbacks and browser calls + +Revision History + +--*/ + +#ifndef _FRONT_PAGE_H +#define _FRONT_PAGE_H + +#include "DeviceMngr/DeviceManager.h" +#include "BootMaint/BootMaint.h" +#include "BootMngr/BootManager.h" + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#include "EdkGenericPlatformBdsLibStrDefs.h" +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 +#define EFI_VBIOS_CLASS 0x40 + +#define SET_VIDEO_BIOS_TYPE_QUESTION_ID 0x00 + +#pragma pack(1) +typedef struct { + UINT8 VideoBIOS; +} MyDevMgrIfrNVData; +#pragma pack() + +#define EFI_FP_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('F', 'P', 'C', 'B') +#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \ + CR (a, \ + EFI_FRONTPAGE_CALLBACK_INFO, \ + DevMgrCallback, \ + EFI_FP_CALLBACK_DATA_SIGNATURE \ + ) + +typedef struct { + UINTN Signature; + MyDevMgrIfrNVData Data; + EFI_HII_HANDLE DevMgrHiiHandle; + EFI_HANDLE CallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL DevMgrCallback; +} EFI_FRONTPAGE_CALLBACK_INFO; + +// +// These are the VFR compiler generated data representing our VFR data. +// +// BugBug: we should put g in front of these tool generated globals. +// maybe even gVrf would be a better prefix +// +extern UINT8 FrontPageVfrBin[]; +extern UINT8 FrontPageStringsStr[]; +extern UINT8 DeviceManagerVfrBin[]; +extern UINT8 DeviceManagerStringsStr[]; + +#define FRONT_PAGE_QUESTION_ID 0x0000 +#define FRONT_PAGE_DATA_WIDTH 0x01 + +EFI_STATUS +InitializeFrontPage ( + IN BOOLEAN ReInitializeStrings + ); + +BOOLEAN +TimeCompare ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ); + +#endif // _FRONT_PAGE_H_ + diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni new file mode 100644 index 0000000000..76dbdcfd4f Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni differ diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageVfr.Vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageVfr.Vfr new file mode 100644 index 0000000000..8457784cc0 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageVfr.Vfr @@ -0,0 +1,159 @@ +// *++ +// +// 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: +// +// FrontPageVfr.vfr +// +// Abstract: +// +// Browser formset. +// +// Revision History: +// +// --*/ + +#include "EdkGenericPlatformBdsLibStrDefs.h" + +#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, { 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe } } + +#define FRONT_PAGE_ITEM_ONE 0x0001 +#define FRONT_PAGE_ITEM_TWO 0x0002 +#define FRONT_PAGE_ITEM_THREE 0x0003 +#define FRONT_PAGE_ITEM_FOUR 0x0004 +#define FRONT_PAGE_ITEM_FIVE 0x0005 + +#define FRONT_PAGE_TIMEOUT 0xFFFF +#define FRONT_PAGE_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0002 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + class = FRONT_PAGE_CLASS, + subclass = FRONT_PAGE_SUBCLASS, + + form formid = 0x1000, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL), + line 0, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), + line 1, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED), + line 1, + align right; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION), + line 2, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), + line 2, + align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT), +// line 0, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT), +// line 0, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT), +// line 1, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT), +// line 1, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT), +// line 2, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT), +// line 3, +// align left; + + goto FRONT_PAGE_ITEM_ONE, + prompt = STRING_TOKEN(STR_CONTINUE_PROMPT), + help = STRING_TOKEN(STR_CONTINUE_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x0001; + + label FRONT_PAGE_ITEM_TWO; + // + // This is where we will dynamically add a OneOf type op-code to select Languages from the + // currently available choices + // + + goto FRONT_PAGE_ITEM_THREE, + prompt = STRING_TOKEN(STR_BOOT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MANAGER_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x1064; + + goto FRONT_PAGE_ITEM_FOUR, + prompt = STRING_TOKEN(STR_DEVICE_MANAGER), + help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x8567; + + goto FRONT_PAGE_ITEM_FIVE, + prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x9876; + + label FRONT_PAGE_TIMEOUT; +// If one wanted to hard-code a value one could do it below, but our implementation follows EFI architecture +// and honors the TimeOut NV variable +// +// banner +// title = STRING_TOKEN(STR_TIME_OUT_PROMPT), +// timeout = 0x000A; + + endform; + + form formid = FRONT_PAGE_ITEM_ONE, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + + form formid = FRONT_PAGE_ITEM_THREE, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + + form formid = FRONT_PAGE_ITEM_FOUR, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + + form formid = FRONT_PAGE_ITEM_FIVE, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + +endformset; diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.c new file mode 100644 index 0000000000..5091f20ac0 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.c @@ -0,0 +1,435 @@ +/*++ + +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: + + language.c + +Abstract: + + Language settings + +Revision History + +--*/ + +#include "String.h" +#include "Language.h" + +#define NARROW_GLYPH_NUMBER 8 +#define WIDE_GLYPH_NUMBER 75 + +// +// Default language code, currently is English +// +CHAR8 *mDefaultLangCode = "eng"; + +typedef struct { + EFI_HII_FONT_PACK FixedLength; + EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER]; + EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER]; +} FONT_PACK; + +FONT_PACK mFontPack = { + { + { + sizeof (EFI_HII_FONT_PACK) + (NARROW_GLYPH_NUMBER * sizeof (EFI_NARROW_GLYPH)) + (WIDE_GLYPH_NUMBER * sizeof (EFI_WIDE_GLYPH)), + EFI_HII_FONT + }, + NARROW_GLYPH_NUMBER, + WIDE_GLYPH_NUMBER + }, + { // Narrow Glyphs + { + 0x05d0, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x4E, + 0x6E, + 0x62, + 0x32, + 0x32, + 0x3C, + 0x68, + 0x4C, + 0x4C, + 0x46, + 0x76, + 0x72, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d1, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x7E, + 0x7E, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d2, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x1C, + 0x3E, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d3, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7E, + 0x7E, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d4, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7C, + 0x7E, + 0x06, + 0x06, + 0x06, + 0x06, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d5, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x3C, + 0x3C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d6, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x1E, + 0x1E, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x0000, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + } + } + }, + { // Wide Glyphs + { + 0x0020, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }, + { + 0x00, + 0x00, + 0x00 + } + }, // + } +}; + +VOID +ExportFonts ( + VOID + ) +/*++ + +Routine Description: + Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. + +Arguments: + None + +Returns: + +--*/ +{ + EFI_HII_HANDLE HiiHandle; + EFI_HII_PACKAGES *PackageList; + + PackageList = PreparePackages (1, NULL, &mFontPack); + // + // Register our Fonts into the global database + // + HiiHandle = 0; + Hii->NewPack (Hii, PackageList, &HiiHandle); + + gBS->FreePool (PackageList); +} + +VOID +InitializeLanguage ( + BOOLEAN LangCodesSettingRequired + ) +/*++ + +Routine Description: + Determine the current language that will be used + based on language related EFI Variables + +Arguments: + LangCodesSettingRequired - If required to set LangCode variable + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + UINTN Size; + CHAR8 LangCode[ISO_639_2_ENTRY_SIZE]; + CHAR8 *LangCodes; + CHAR16 *LanguageString; + + LanguageString = NULL; + LangCodes = NULL; + + ExportFonts (); + + // + // Collect the languages from what our current Language support is based on our VFR + // + Hii->GetPrimaryLanguages (Hii, gStringPackHandle, &LanguageString); + + LangCodes = AllocatePool (StrLen (LanguageString)); + ASSERT (LangCodes); + + // + // Convert LanguageString from Unicode to EFI defined ASCII LangCodes + // + for (Index = 0; LanguageString[Index] != 0x0000; Index++) { + LangCodes[Index] = (CHAR8) LanguageString[Index]; + } + + LangCodes[Index] = 0; + + if (LangCodesSettingRequired) { + Status = gRT->SetVariable ( + L"LangCodes", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrLen (LangCodes), + LangCodes + ); + } + // + // Find current LangCode from Lang NV Variable + // + Size = ISO_639_2_ENTRY_SIZE; + Status = gRT->GetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + &LangCode + ); + + if (!EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) { + if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) { + Status = EFI_SUCCESS; + break; + } + } + } + // + // If we cannot get language code from Lang variable, + // or LangCode cannot be found from language table, + // set the mDefaultLangCode to Lang variable. + // + if (EFI_ERROR (Status)) { + Status = gRT->SetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + ISO_639_2_ENTRY_SIZE, + mDefaultLangCode + ); + } + + if (LangCodes) { + gBS->FreePool (LangCodes); + } + + if (LanguageString != NULL) { + gBS->FreePool (LanguageString); + } + +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.h new file mode 100644 index 0000000000..6b6d887040 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.h @@ -0,0 +1,36 @@ +/*++ + +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: + + Language.h + +Abstract: + + Language setting + +Revision History + +--*/ + +#ifndef _LANGUAGE_H +#define _LANGUAGE_H + +#ifndef ISO_639_2_ENTRY_SIZE +#define ISO_639_2_ENTRY_SIZE 3 +#endif + +VOID +InitializeLanguage ( + BOOLEAN LangCodesSettingRequired + ); + +#endif // _LANGUAGE_H_ diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/MemoryTest.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/MemoryTest.c new file mode 100644 index 0000000000..f4046b518a --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/MemoryTest.c @@ -0,0 +1,430 @@ +/*++ + +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: + + MemoryTest.c + +Abstract: + + Perform the platform memory test + +--*/ + +#include "Bds.h" +#include "String.h" + +// +// BDS Platform Functions +// +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 + ) +/*++ + +Routine Description: + + Show progress bar with title above it. It only works in UGA mode. + +Arguments: + + TitleForeground - Foreground color for Title. + TitleBackground - Background color for Title. + Title - Title above progress bar. + ProgressColor - Progress bar color. + Progress - Progress (0-100) + +Returns: + + EFI_STATUS - Success update the progress bar + +--*/ +{ + 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; + } + } + + 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 - GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) &Color, + EfiUgaVideoFill, + 0, + 0, + 0, + PosY - GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - 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) * GLYPH_WIDTH) / 2, + PosY - GLYPH_HEIGHT - 1, + &TitleForeground, + &TitleBackground, + Title + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +BdsMemoryTest ( + IN EXTENDMEM_COVERAGE_LEVEL Level + ) +/*++ + +Routine Description: + + Perform the memory test base on the memory test intensive level, + and update the memory resource. + +Arguments: + + Level - The memory test intensive level. + +Returns: + + EFI_STATUS - Success test all the system memory and update + the memory resource + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS InitStatus; + EFI_STATUS KeyStatus; + EFI_STATUS ReturnStatus; + BOOLEAN RequireSoftECCInit; + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; + UINT64 TestedMemorySize; + UINT64 TotalMemorySize; + UINTN TestPercent; + UINT64 PreviousValue; + BOOLEAN ErrorOut; + BOOLEAN TestAbort; + EFI_INPUT_KEY Key; + CHAR16 StrPercent[16]; + CHAR16 *StrTotalMemory; + CHAR16 *Pos; + CHAR16 *TmpStr; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + UINT8 Value; + UINTN DataSize; + + ReturnStatus = EFI_SUCCESS; + ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); + + Pos = AllocatePool (128); + + if (Pos == NULL) { + return ReturnStatus; + } + + StrTotalMemory = Pos; + + TestedMemorySize = 0; + TotalMemorySize = 0; + PreviousValue = 0; + ErrorOut = FALSE; + TestAbort = FALSE; + + 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); + + RequireSoftECCInit = FALSE; + + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + Status = gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID**)&GenMemoryTest + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Pos); + return EFI_SUCCESS; + } + + InitStatus = GenMemoryTest->MemoryTestInit ( + GenMemoryTest, + Level, + &RequireSoftECCInit + ); + if (InitStatus == EFI_NO_MEDIA) { + // + // The PEI codes also have the relevant memory test code to check the memory, + // it can select to test some range of the memory or all of them. If PEI code + // checks all the memory, this BDS memory test will has no not-test memory to + // do the test, and then the status of EFI_NO_MEDIA will be returned by + // "MemoryTestInit". So it does not need to test memory again, just return. + // + gBS->FreePool (Pos); + return EFI_SUCCESS; + } + + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2); + TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); + + if (TmpStr != NULL) { + gST->ConOut->OutputString (gST->ConOut, TmpStr); + gBS->FreePool (TmpStr); + } + + do { + Status = GenMemoryTest->PerformMemoryTest ( + GenMemoryTest, + &TestedMemorySize, + &TotalMemorySize, + &ErrorOut, + TestAbort + ); + if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { + TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); + if (TmpStr != NULL) { + PrintXY (10, 10, NULL, NULL, TmpStr); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4); + gST->ConOut->OutputString (gST->ConOut, TmpStr); + gBS->FreePool (TmpStr); + } + + ASSERT (0); + } + + TestPercent = (UINTN) DivU64x32 ( + DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), + (UINTN)DivU64x32 (TotalMemorySize, 16) + ); + if (TestPercent != PreviousValue) { + UnicodeValueToString (StrPercent, 0, TestPercent, 0); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0); + TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL); + gBS->FreePool (TmpStr); + } + + TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + TestPercent, + (UINTN) PreviousValue + ); + gBS->FreePool (TmpStr); + } + } + + PreviousValue = TestPercent; + + KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (Key.ScanCode == SCAN_ESC) { + if (!RequireSoftECCInit) { + TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + 100, + (UINTN) PreviousValue + ); + gBS->FreePool (TmpStr); + } + + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0); + gST->ConOut->OutputString (gST->ConOut, L"100"); + Status = GenMemoryTest->Finished (GenMemoryTest); + goto Done; + } + + TestAbort = TRUE; + } + } while (Status != EFI_NOT_FOUND); + + Status = GenMemoryTest->Finished (GenMemoryTest); + +Done: + UnicodeValueToString (StrTotalMemory, COMMA_TYPE, (UINTN) TotalMemorySize, 0); + if (StrTotalMemory[0] == L',') { + StrTotalMemory++; + } + + TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); + if (TmpStr != NULL) { + StrCat (StrTotalMemory, TmpStr); + gBS->FreePool (TmpStr); + } + + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + gST->ConOut->OutputString (gST->ConOut, StrTotalMemory); + PlatformBdsShowProgress ( + Foreground, + Background, + StrTotalMemory, + Color, + 100, + (UINTN) PreviousValue + ); + + gBS->FreePool (Pos); + + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + L"BootState", + &gEfiBootStateGuid, + NULL, + &DataSize, + &Value + ); + + if (EFI_ERROR (Status)) { + Value = 1; + gRT->SetVariable ( + L"BootState", + &gEfiBootStateGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value + ); + } + + return ReturnStatus; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.c new file mode 100644 index 0000000000..1b04f02e17 --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.c @@ -0,0 +1,136 @@ +/*++ + +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: + + string.c + +Abstract: + + String support + +Revision History + +--*/ + +#include "Bds.h" +#include "String.h" +#include "Language.h" + +extern UINT8 EdkGenericPlatformBdsLibStrings[]; + +EFI_GUID gBdsStringPackGuid = { 0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a} }; + +EFI_HII_HANDLE gStringPackHandle; +EFI_HII_PROTOCOL *Hii; + +EFI_STATUS +InitializeStringSupport ( + VOID + ) +/*++ + +Routine Description: + + Initialize HII global accessor for string support + +Arguments: + None + +Returns: + String from ID. + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + // + // There should only ever be one HII protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID**)&Hii + ); + if (!EFI_ERROR (Status)) { + PackageList = PreparePackages (1, &gBdsStringPackGuid, EdkGenericPlatformBdsLibStrings); + Status = Hii->NewPack (Hii, PackageList, &gStringPackHandle); + gBS->FreePool (PackageList); + } + + return Status; +} + +CHAR16 * +GetStringById ( + IN STRING_REF Id + ) +/*++ + +Routine Description: + + Get string by string id from HII Interface + +Arguments: + + Id - String ID. + +Returns: + + CHAR16 * - String from ID. + NULL - If error occurs. + +--*/ +{ + CHAR16 *String; + UINTN StringLength; + EFI_STATUS Status; + + // + // Set default string size assumption at no more than 256 bytes + // + StringLength = 0x100; + + String = AllocateZeroPool (StringLength); + if (String == NULL) { + // + // If this happens, we are oh-so-dead, but return a NULL in any case. + // + return NULL; + } + // + // Get the current string for the current Language + // + Status = Hii->GetString (Hii, gStringPackHandle, Id, FALSE, NULL, &StringLength, String); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Free the old pool + // + gBS->FreePool (String); + + // + // Allocate new pool with correct value + // + String = AllocatePool (StringLength); + ASSERT (String != NULL); + + Status = Hii->GetString (Hii, gStringPackHandle, Id, FALSE, NULL, &StringLength, String); + if (!EFI_ERROR (Status)) { + return String; + } + } + + return NULL; + } + + return String; +} diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.h new file mode 100644 index 0000000000..da6a912d0b --- /dev/null +++ b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.h @@ -0,0 +1,59 @@ +/*++ + +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: + + string.h + +Abstract: + + String support + +Revision History + +--*/ + +#ifndef _STRING_H_ +#define _STRING_H_ + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#include "EdkGenericPlatformBdsLibStrDefs.h" + +// +// String Definition Guid for BDS Platform +// +#define EFI_BDS_PLATFORM_GUID \ + { \ + 0x7777E939, 0xD57E, 0x4DCB, {0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F } \ + } + +extern EFI_HII_HANDLE gStringPackHandle; +extern EFI_HII_PROTOCOL *Hii; + +CHAR16 * +GetStringById ( + IN STRING_REF Id + ); + +EFI_STATUS +InitializeStringSupport ( + VOID + ); + +EFI_STATUS +CallFrontPage ( + VOID + ); + +#endif // _STRING_H_ diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni new file mode 100644 index 0000000000..41a6b9acde Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni differ