S3Lib|IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf\r
RecoveryLib|IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf\r
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+ IfrSupportLib|MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrSupportLib.inf\r
+ ExtendedIfrSupportLib|MdeModulePkg/Library/ExtendedIfrSupportLib/ExtendedIfrSupportLib.inf\r
+ GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
+ ExtendedHiiLib|MdeModulePkg/Library/ExtendedHiiLib/ExtendedHiiLib.inf\r
+ PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
\r
[LibraryClasses.common.PEIM]\r
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf\r
IntelFrameworkModulePkg/Library/BaseReportStatusCodeLib/BaseReportStatusCodeLib.inf\r
IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf\r
-\r
+ IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+ \r
IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf\r
IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf\r
IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf\r
IntelFrameworkModulePkg/Universal/PcatSingleSegmentPciCfgPei/PcatSingleSegmentPciCfgPei.inf\r
IntelFrameworkModulePkg/Universal/VariablePei/VariablePei.inf\r
IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf\r
-\r
+ IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf\r
+ \r
[Components.IA32]\r
IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf\r
\r
--- /dev/null
+/** @file\r
+ BDS Lib functions which relate with create or process the boot option.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+BOOLEAN mEnumBootDevice = FALSE;\r
+\r
+///\r
+/// This GUID is used for an EFI Variable that stores the front device pathes\r
+/// for a partial device path that starts with the HD node.\r
+///\r
+EFI_GUID mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };\r
+\r
+\r
+\r
+/**\r
+ Boot the legacy system with the boot option\r
+\r
+ @param Option The legacy boot option which have BBS device path\r
+\r
+ @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support\r
+ legacy boot.\r
+ @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot ().\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLibDoLegacyBoot (\r
+ IN BDS_COMMON_OPTION *Option\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no LegacyBios protocol we do not support legacy boot\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Notes: if we separate the int 19, then we don't need to refresh BBS\r
+ //\r
+ BdsRefreshBbsTableForBoot (Option);\r
+\r
+ //\r
+ // Write boot to OS performance data to a file\r
+ //\r
+ PERF_CODE (\r
+ WriteBootToOsPerformanceData ();\r
+ );\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description));\r
+ return LegacyBios->LegacyBoot (\r
+ LegacyBios,\r
+ (BBS_BBS_DEVICE_PATH *) Option->DevicePath,\r
+ Option->LoadOptionsSize,\r
+ Option->LoadOptions\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Process the boot option follow the UEFI specification and\r
+ special treat the legacy boot option with BBS_DEVICE_PATH.\r
+\r
+ @param Option The boot option need to be processed\r
+ @param DevicePath The device path which describe where to load the\r
+ boot image or the legacy BBS device path to boot\r
+ the legacy OS\r
+ @param ExitDataSize The size of exit data.\r
+ @param ExitData Data returned when Boot image failed.\r
+\r
+ @retval EFI_SUCCESS Boot from the input boot option successfully.\r
+ @retval EFI_NOT_FOUND If the Device Path is not found in the system\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibBootViaBootOption (\r
+ IN BDS_COMMON_OPTION *Option,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT UINTN *ExitDataSize,\r
+ OUT CHAR16 **ExitData OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+ EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath;\r
+ EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;\r
+ LIST_ENTRY TempBootLists;\r
+\r
+ //\r
+ // Record the performance data for End of BDS\r
+ //\r
+ PERF_END (0, BDS_TOK, NULL, 0);\r
+\r
+ *ExitDataSize = 0;\r
+ *ExitData = NULL;\r
+\r
+ //\r
+ // Notes: put EFI64 ROM Shadow Solution\r
+ //\r
+ EFI64_SHADOW_ALL_LEGACY_ROM ();\r
+\r
+ //\r
+ // Notes: this code can be remove after the s3 script table\r
+ // hook on the event EVT_SIGNAL_READY_TO_BOOT or\r
+ // EVT_SIGNAL_LEGACY_BOOT\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &AcpiS3Save);\r
+ if (!EFI_ERROR (Status)) {\r
+ AcpiS3Save->S3Save (AcpiS3Save, NULL);\r
+ }\r
+ //\r
+ // If it's Device Path that starts with a hard drive path, append it with the front part to compose a\r
+ // full device path\r
+ //\r
+ WorkingDevicePath = NULL;\r
+ if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {\r
+ WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull (\r
+ (HARDDRIVE_DEVICE_PATH *)DevicePath\r
+ );\r
+ if (WorkingDevicePath != NULL) {\r
+ DevicePath = WorkingDevicePath;\r
+ }\r
+ }\r
+ //\r
+ // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
+ //\r
+ EfiSignalEventReadyToBoot();\r
+ \r
+ \r
+ //\r
+ // Set Boot Current\r
+ //\r
+ gRT->SetVariable (\r
+ L"BootCurrent",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (UINT16),\r
+ &Option->BootCurrent\r
+ );\r
+\r
+ ASSERT (Option->DevicePath != NULL);\r
+ if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
+ (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
+ ) {\r
+ //\r
+ // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
+ //\r
+ return BdsLibDoLegacyBoot (Option);\r
+ }\r
+\r
+ //\r
+ // If the boot option point to Internal FV shell, make sure it is valid\r
+ //\r
+ Status = BdsLibUpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);\r
+ if (!EFI_ERROR(Status)) {\r
+ if (Option->DevicePath != NULL) {\r
+ FreePool(Option->DevicePath);\r
+ }\r
+ Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
+ ASSERT(Option->DevicePath != NULL);\r
+ CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
+ //\r
+ // Update the shell boot option\r
+ //\r
+ InitializeListHead (&TempBootLists);\r
+ BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
+ \r
+ //\r
+ // free the temporary device path created by BdsLibUpdateFvFileDevicePath()\r
+ //\r
+ FreePool (DevicePath); \r
+ DevicePath = Option->DevicePath;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
+\r
+ Status = gBS->LoadImage (\r
+ TRUE,\r
+ mBdsImageHandle,\r
+ DevicePath,\r
+ NULL,\r
+ 0,\r
+ &ImageHandle\r
+ );\r
+\r
+ //\r
+ // If we didn't find an image directly, we need to try as if it is a removable device boot opotion\r
+ // and load the image according to the default boot behavior for removable device.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // check if there is a bootable removable media could be found in this device path ,\r
+ // and get the bootable media handle\r
+ //\r
+ Handle = BdsLibGetBootableHandle(DevicePath);\r
+ if (Handle == NULL) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+ // machinename is ia32, ia64, x64, ...\r
+ //\r
+ FilePath = FileDevicePath (Handle, (CONST CHAR16*)PcdGetPtr(PcdDefaultBootFileName));\r
+ if (FilePath != NULL) {\r
+ Status = gBS->LoadImage (\r
+ TRUE,\r
+ mBdsImageHandle,\r
+ FilePath,\r
+ NULL,\r
+ 0,\r
+ &ImageHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The DevicePath failed, and it's not a valid\r
+ // removable media device.\r
+ //\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // It there is any error from the Boot attempt exit now.\r
+ //\r
+ goto Done;\r
+ }\r
+ //\r
+ // Provide the image with it's load options\r
+ //\r
+ Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (Option->LoadOptionsSize != 0) {\r
+ ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
+ ImageInfo->LoadOptions = Option->LoadOptions;\r
+ }\r
+ //\r
+ // Before calling the image, enable the Watchdog Timer for\r
+ // the 5 Minute period\r
+ //\r
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+ Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
+\r
+ //\r
+ // Clear the Watchdog Timer after the image returns\r
+ //\r
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+\r
+Done:\r
+ //\r
+ // Clear Boot Current\r
+ //\r
+ gRT->SetVariable (\r
+ L"BootCurrent",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ 0,\r
+ &Option->BootCurrent\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Expand a device path that starts with a hard drive media device path node to be a\r
+ full device path that includes the full hardware path to the device. We need\r
+ to do this so it can be booted. As an optimization the front match (the part point\r
+ to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable\r
+ so a connect all is not required on every boot. All successful history device path\r
+ which point to partition node (the front part) will be saved.\r
+\r
+ @param HardDriveDevicePath EFI Device Path to boot, if it starts with a hard\r
+ drive media device path.\r
+ @return A Pointer to the full device path or NULL if a valid Hard Drive devic path\r
+ cannot be found.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsExpandPartitionPartialDevicePathToFull (\r
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BlockIoHandleCount;\r
+ EFI_HANDLE *BlockIoBuffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN Index;\r
+ UINTN InstanceNum;\r
+ EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+ UINTN CachedDevicePathSize;\r
+ BOOLEAN DeviceExist;\r
+ BOOLEAN NeedAdjust;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ UINTN Size;\r
+\r
+ FullDevicePath = NULL;\r
+ //\r
+ // Check if there is prestore 'HDDP' variable.\r
+ // If exist, search the front path which point to partition node in the variable instants.\r
+ // If fail to find or 'HDDP' not exist, reconnect all and search in all system\r
+ //\r
+ CachedDevicePath = BdsLibGetVariableAndSize (\r
+ L"HDDP",\r
+ &mHdBootVariablePrivateGuid,\r
+ &CachedDevicePathSize\r
+ );\r
+ \r
+ if (CachedDevicePath != NULL) {\r
+ TempNewDevicePath = CachedDevicePath;\r
+ DeviceExist = FALSE;\r
+ NeedAdjust = FALSE;\r
+ do {\r
+ //\r
+ // Check every instance of the variable\r
+ // First, check whether the instance contain the partition node, which is needed for distinguishing multi\r
+ // partial partition boot option. Second, check whether the instance could be connected.\r
+ //\r
+ Instance = GetNextDevicePathInstance (&TempNewDevicePath, &Size);\r
+ if (MatchPartitionDevicePathNode (Instance, HardDriveDevicePath)) {\r
+ //\r
+ // Connect the device path instance, the device path point to hard drive media device path node\r
+ // e.g. ACPI() /PCI()/ATA()/Partition()\r
+ //\r
+ Status = BdsLibConnectDevicePath (Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Come here means the first instance is not matched\r
+ //\r
+ NeedAdjust = TRUE;\r
+ FreePool(Instance);\r
+ } while (TempNewDevicePath != NULL);\r
+\r
+ if (DeviceExist) {\r
+ //\r
+ // Find the matched device path.\r
+ // Append the file path information from the boot option and return the fully expanded device path.\r
+ //\r
+ DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+ FullDevicePath = AppendDevicePath (Instance, DevicePath);\r
+\r
+ //\r
+ // Adjust the 'HDDP' instances sequence if the matched one is not first one.\r
+ //\r
+ if (NeedAdjust) {\r
+ //\r
+ // First delete the matched instance.\r
+ //\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, Instance );\r
+ FreePool (TempNewDevicePath);\r
+ \r
+ //\r
+ // Second, append the remaining path after the matched instance\r
+ //\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = AppendDevicePathInstance (Instance, CachedDevicePath );\r
+ FreePool (TempNewDevicePath);\r
+ //\r
+ // Save the matching Device Path so we don't need to do a connect all next time\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"HDDP",\r
+ &mHdBootVariablePrivateGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ GetDevicePathSize (CachedDevicePath),\r
+ CachedDevicePath\r
+ );\r
+ }\r
+ \r
+ FreePool (Instance);\r
+ FreePool (CachedDevicePath);\r
+ return FullDevicePath;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If we get here we fail to find or 'HDDP' not exist, and now we need\r
+ // to search all devices in the system for a matched partition\r
+ //\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
+ if (EFI_ERROR (Status) || BlockIoHandleCount == 0 || BlockIoBuffer == NULL) {\r
+ //\r
+ // If there was an error or there are no device handles that support\r
+ // the BLOCK_IO Protocol, then return.\r
+ //\r
+ return NULL;\r
+ }\r
+ //\r
+ // Loop through all the device handles that support the BLOCK_IO Protocol\r
+ //\r
+ for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
+\r
+ Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);\r
+ if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {\r
+ continue;\r
+ }\r
+\r
+ if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {\r
+ //\r
+ // Find the matched partition device path\r
+ //\r
+ DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+ FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
+\r
+ //\r
+ // Save the matched partition device path in 'HDDP' variable\r
+ //\r
+ if (CachedDevicePath != NULL) {\r
+ //\r
+ // Save the matched partition device path as first instance of 'HDDP' variable\r
+ //\r
+ if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);\r
+ FreePool(TempNewDevicePath);\r
+\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
+ FreePool(TempNewDevicePath);\r
+ } else {\r
+ TempNewDevicePath = CachedDevicePath;\r
+ CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
+ FreePool(TempNewDevicePath);\r
+ }\r
+ //\r
+ // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller\r
+ // If the user try to boot many OS in different HDs or partitions, in theory, the 'HDDP' variable maybe become larger and larger.\r
+ //\r
+ InstanceNum = 0;\r
+ ASSERT (CachedDevicePath != NULL);\r
+ TempNewDevicePath = CachedDevicePath;\r
+ while (!IsDevicePathEnd (TempNewDevicePath)) {\r
+ TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
+ //\r
+ // Parse one instance\r
+ //\r
+ while (!IsDevicePathEndType (TempNewDevicePath)) {\r
+ TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
+ }\r
+ InstanceNum++;\r
+ //\r
+ // If the CachedDevicePath variable contain too much instance, only remain 12 instances.\r
+ //\r
+ if (InstanceNum >= 12) {\r
+ SetDevicePathEndNode (TempNewDevicePath);\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);\r
+ }\r
+\r
+ //\r
+ // Save the matching Device Path so we don't need to do a connect all next time\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"HDDP",\r
+ &mHdBootVariablePrivateGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ GetDevicePathSize (CachedDevicePath),\r
+ CachedDevicePath\r
+ );\r
+\r
+ break;\r
+ }\r
+ }\r
+ \r
+ FreePool (CachedDevicePath);\r
+ if (BlockIoBuffer != NULL) {\r
+ FreePool (BlockIoBuffer);\r
+ }\r
+ return FullDevicePath;\r
+}\r
+\r
+/**\r
+ Check whether there is a instance in BlockIoDevicePath, which contain multi device path\r
+ instances, has the same partition node with HardDriveDevicePath device path\r
+\r
+ @param BlockIoDevicePath Multi device path instances which need to check\r
+ @param HardDriveDevicePath A device path which starts with a hard drive media\r
+ device path.\r
+\r
+ @retval TRUE There is a matched device path instance.\r
+ @retval FALSE There is no matched device path instance.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+MatchPartitionDevicePathNode (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,\r
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
+ )\r
+{\r
+ HARDDRIVE_DEVICE_PATH *TmpHdPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BOOLEAN Match;\r
+ EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePathNode;\r
+\r
+ if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {\r
+ return FALSE;\r
+ }\r
+ \r
+ //\r
+ // Make PreviousDevicePath == the device path node before the end node\r
+ //\r
+ DevicePath = BlockIoDevicePath;\r
+ BlockIoHdDevicePathNode = NULL;\r
+\r
+ //\r
+ // find the partition device path node\r
+ //\r
+ while (!IsDevicePathEnd (DevicePath)) {\r
+ if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
+ ) {\r
+ BlockIoHdDevicePathNode = DevicePath;\r
+ break;\r
+ }\r
+\r
+ DevicePath = NextDevicePathNode (DevicePath);\r
+ }\r
+\r
+ if (BlockIoHdDevicePathNode == NULL) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
+ //\r
+ TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;\r
+ Match = FALSE;\r
+ \r
+ //\r
+ // Check for the match\r
+ //\r
+ if ((TmpHdPath->MBRType == HardDriveDevicePath->MBRType) &&\r
+ (TmpHdPath->SignatureType == HardDriveDevicePath->SignatureType)) {\r
+ switch (TmpHdPath->SignatureType) {\r
+ case SIGNATURE_TYPE_GUID:\r
+ Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)HardDriveDevicePath->Signature);\r
+ break;\r
+ case SIGNATURE_TYPE_MBR:\r
+ Match = (BOOLEAN)(*((UINT32 *)(&(TmpHdPath->Signature[0]))) == ReadUnaligned32((UINT32 *)(&(HardDriveDevicePath->Signature[0]))));\r
+ break;\r
+ default:\r
+ Match = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Match;\r
+}\r
+\r
+/**\r
+ Delete the boot option associated with the handle passed in.\r
+\r
+ @param Handle The handle which present the device path to create\r
+ boot option\r
+\r
+ @retval EFI_SUCCESS Delete the boot option success\r
+ @retval EFI_NOT_FOUND If the Device Path is not found in the system\r
+ @retval EFI_OUT_OF_RESOURCES Lack of memory resource\r
+ @retval Other Error return value from SetVariable()\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLibDeleteOptionFromHandle (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ UINT16 *BootOrder;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOrderSize;\r
+ UINTN BootOptionSize;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
+ UINTN DevicePathSize;\r
+ UINTN OptionDevicePathSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ UINT8 *TempPtr;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BootOrder = NULL;\r
+ BootOrderSize = 0;\r
+\r
+ //\r
+ // Check "BootOrder" variable, if no, means there is no any boot order.\r
+ //\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (BootOrder == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Convert device handle to device path protocol instance\r
+ //\r
+ DevicePath = DevicePathFromHandle (Handle);\r
+ if (DevicePath == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ DevicePathSize = GetDevicePathSize (DevicePath);\r
+\r
+ //\r
+ // Loop all boot order variable and find the matching device path\r
+ //\r
+ Index = 0;\r
+ while (Index < BootOrderSize / sizeof (UINT16)) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ \r
+ if (BootOptionVar == NULL) {\r
+ FreePool (BootOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TempPtr = BootOptionVar;\r
+ TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+ OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);\r
+\r
+ //\r
+ // Check whether the device path match\r
+ //\r
+ if ((OptionDevicePathSize == DevicePathSize) &&\r
+ (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {\r
+ BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
+ FreePool (BootOptionVar);\r
+ break;\r
+ }\r
+\r
+ FreePool (BootOptionVar);\r
+ Index++;\r
+ }\r
+\r
+ //\r
+ // Adjust number of boot option for "BootOrder" variable.\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ BootOrderSize,\r
+ BootOrder\r
+ );\r
+\r
+ FreePool (BootOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Delete all invalid EFI boot options. The probable invalid boot option could\r
+ be Removable media or Network boot device.\r
+\r
+ @retval EFI_SUCCESS Delete all invalid boot option success\r
+ @retval EFI_NOT_FOUND Variable "BootOrder" is not found\r
+ @retval EFI_OUT_OF_RESOURCES Lack of memory resource\r
+ @retval Other Error return value from SetVariable()\r
+\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidEfiBootOption (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 *BootOrder;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOrderSize;\r
+ UINTN BootOptionSize;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINT16 BootOption[BOOT_OPTION_MAX_CHAR];\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ UINT8 *TempPtr;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BootOrder = NULL;\r
+ BootOrderSize = 0;\r
+\r
+ //\r
+ // Check "BootOrder" variable firstly, this variable hold the number of boot options\r
+ //\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Index = 0;\r
+ while (Index < BootOrderSize / sizeof (UINT16)) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ FreePool (BootOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TempPtr = BootOptionVar;\r
+ TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+\r
+ //\r
+ // Skip legacy boot option (BBS boot device)\r
+ //\r
+ if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&\r
+ (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {\r
+ FreePool (BootOptionVar);\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ if (!BdsLibIsValidEFIBootOptDevicePath (OptionDevicePath, FALSE)) {\r
+ //\r
+ // Delete this invalid boot option "Boot####"\r
+ //\r
+ Status = gRT->SetVariable (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ NULL\r
+ );\r
+ //\r
+ // Mark this boot option in boot order as deleted\r
+ //\r
+ BootOrder[Index] = 0xffff;\r
+ }\r
+\r
+ FreePool (BootOptionVar);\r
+ Index++;\r
+ }\r
+\r
+ //\r
+ // Adjust boot order array\r
+ //\r
+ Index2 = 0;\r
+ for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+ if (BootOrder[Index] != 0xffff) {\r
+ BootOrder[Index2] = BootOrder[Index];\r
+ Index2 ++;\r
+ }\r
+ }\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ Index2 * sizeof (UINT16),\r
+ BootOrder\r
+ );\r
+\r
+ FreePool (BootOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function will enumerate all possible boot device in the system,\r
+ it will only execute once of every boot.\r
+\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+\r
+ @retval EFI_SUCCESS Finished all the boot device enumerate and create\r
+ the boot option base on that boot device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibEnumerateAllBootOption (\r
+ IN OUT LIST_ENTRY *BdsBootOptionList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 FloppyNumber;\r
+ UINT16 CdromNumber;\r
+ UINT16 UsbNumber;\r
+ UINT16 MiscNumber;\r
+ UINT16 NonBlockNumber;\r
+ UINTN NumberBlockIoHandles;\r
+ EFI_HANDLE *BlockIoHandles;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ UINTN Index;\r
+ UINTN NumberSimpleNetworkHandles;\r
+ EFI_HANDLE *SimpleNetworkHandles;\r
+ UINTN FvHandleCount;\r
+ EFI_HANDLE *FvHandleBuffer;\r
+ EFI_FV_FILETYPE Type;\r
+ UINTN Size;\r
+ EFI_FV_FILE_ATTRIBUTES Attributes;\r
+ UINT32 AuthenticationStatus;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN DevicePathType;\r
+ CHAR16 Buffer[40];\r
+ EFI_HANDLE *FileSystemHandles;\r
+ UINTN NumberFileSystemHandles;\r
+ BOOLEAN NeedDelete;\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+\r
+ FloppyNumber = 0;\r
+ CdromNumber = 0;\r
+ UsbNumber = 0;\r
+ MiscNumber = 0;\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+ \r
+ //\r
+ // If the boot device enumerate happened, just get the boot\r
+ // device from the boot order variable\r
+ //\r
+ if (mEnumBootDevice) {\r
+ BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ //\r
+ // Notes: this dirty code is to get the legacy boot option from the\r
+ // BBS table and create to variable as the EFI boot option, it should\r
+ // be removed after the CSM can provide legacy boot option directly\r
+ //\r
+ REFRESH_LEGACY_BOOT_OPTIONS;\r
+\r
+ //\r
+ // Delete invalid boot option\r
+ //\r
+ BdsDeleteAllInvalidEfiBootOption ();\r
+ \r
+ //\r
+ // Parse removable media\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiBlockIoProtocolGuid,\r
+ NULL,\r
+ &NumberBlockIoHandles,\r
+ &BlockIoHandles\r
+ );\r
+ \r
+ for (Index = 0; Index < NumberBlockIoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ BlockIoHandles[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (!BlkIo->Media->RemovableMedia) {\r
+ //\r
+ // skip the non-removable block devices\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+ DevicePath = DevicePathFromHandle (BlockIoHandles[Index]);\r
+ DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);\r
+\r
+ switch (DevicePathType) {\r
+ case BDS_EFI_ACPI_FLOPPY_BOOT:\r
+ if (FloppyNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy %d", FloppyNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ FloppyNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
+ if (CdromNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM %d", CdromNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ CdromNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
+ if (UsbNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device %d", UsbNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ UsbNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_SCSI_BOOT:\r
+ if (UsbNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device %d", UsbNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ UsbNumber++;\r
+ break;\r
+\r
+ case BDS_EFI_MESSAGE_MISC_BOOT:\r
+ if (MiscNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device %d", MiscNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+ MiscNumber++;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (NumberBlockIoHandles != 0) {\r
+ FreePool (BlockIoHandles);\r
+ }\r
+\r
+ //\r
+ // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.\r
+ //\r
+ NonBlockNumber = 0;\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &NumberFileSystemHandles,\r
+ &FileSystemHandles\r
+ );\r
+ for (Index = 0; Index < NumberFileSystemHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ FileSystemHandles[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Skip if the file system handle supports a BlkIo protocol,\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI\r
+ // machinename is ia32, ia64, x64, ...\r
+ //\r
+ Hdr.Union = &HdrData;\r
+ NeedDelete = TRUE;\r
+ Status = BdsLibGetImageHeader (\r
+ FileSystemHandles[Index],\r
+ (CHAR16*)PcdGetPtr (PcdDefaultBootFileName),\r
+ &DosHeader,\r
+ Hdr\r
+ );\r
+ if (!EFI_ERROR (Status) &&\r
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
+ Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ NeedDelete = FALSE;\r
+ }\r
+\r
+ if (NeedDelete) {\r
+ //\r
+ // No such file or the file is not a EFI application, delete this boot option\r
+ //\r
+ BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
+ } else {\r
+ if (NonBlockNumber == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);\r
+ }\r
+ BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);\r
+ NonBlockNumber++;\r
+ }\r
+ }\r
+\r
+ if (NumberFileSystemHandles != 0) {\r
+ FreePool (FileSystemHandles);\r
+ }\r
+\r
+ //\r
+ // Parse Network Boot Device\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ NULL,\r
+ &NumberSimpleNetworkHandles,\r
+ &SimpleNetworkHandles\r
+ );\r
+ for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {\r
+ if (Index == 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network");\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network %d", Index);\r
+ }\r
+ BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);\r
+ }\r
+\r
+ if (NumberSimpleNetworkHandles != 0) {\r
+ FreePool (SimpleNetworkHandles);\r
+ }\r
+\r
+ //\r
+ // Check if we have on flash shell\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &FvHandleCount,\r
+ &FvHandleBuffer\r
+ );\r
+ for (Index = 0; Index < FvHandleCount; Index++) {\r
+ //\r
+ // Only care the dispatched FV. If no dispatch protocol on the FV, it is not dispatched, then skip it.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ FvHandleBuffer[Index],\r
+ &gEfiFirmwareVolumeDispatchProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ \r
+ gBS->HandleProtocol (\r
+ FvHandleBuffer[Index],\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ &gEfiShellFileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Skip if no shell file in the FV\r
+ //\r
+ continue;\r
+ }\r
+ //\r
+ // Build the shell boot option\r
+ //\r
+ BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);\r
+ }\r
+\r
+ if (FvHandleCount != 0) {\r
+ FreePool (FvHandleBuffer);\r
+ }\r
+ //\r
+ // Make sure every boot only have one time\r
+ // boot device enumerate\r
+ //\r
+ BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+ mEnumBootDevice = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build the boot option with the handle parsed in\r
+\r
+ @param Handle The handle which present the device path to create\r
+ boot option\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+ @param String The description of the boot option.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBuildOptionFromHandle (\r
+ IN EFI_HANDLE Handle,\r
+ IN LIST_ENTRY *BdsBootOptionList,\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ DevicePath = DevicePathFromHandle (Handle);\r
+\r
+ //\r
+ // Create and register new boot option\r
+ //\r
+ BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder");\r
+}\r
+\r
+\r
+/**\r
+ Build the on flash shell boot option with the handle parsed in.\r
+\r
+ @param Handle The handle which present the device path to create\r
+ on flash shell boot option\r
+ @param BdsBootOptionList The header of the link list which indexed all\r
+ current boot options\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBuildOptionFromShell (\r
+ IN EFI_HANDLE Handle,\r
+ IN OUT LIST_ENTRY *BdsBootOptionList\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;\r
+\r
+ DevicePath = DevicePathFromHandle (Handle);\r
+\r
+ //\r
+ // Build the shell device path\r
+ //\r
+ EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);\r
+\r
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
+\r
+ //\r
+ // Create and register the shell boot option\r
+ //\r
+ BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
+\r
+}\r
+\r
+/**\r
+ Boot from the UEFI spec defined "BootNext" variable.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBootNext (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 *BootNext;\r
+ UINTN BootNextSize;\r
+ CHAR16 Buffer[20];\r
+ BDS_COMMON_OPTION *BootOption;\r
+ LIST_ENTRY TempList;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+\r
+ //\r
+ // Init the boot option name buffer and temp link list\r
+ //\r
+ InitializeListHead (&TempList);\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+ BootNext = BdsLibGetVariableAndSize (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootNextSize\r
+ );\r
+\r
+ //\r
+ // Clear the boot next variable first\r
+ //\r
+ if (BootNext != NULL) {\r
+ gRT->SetVariable (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ BootNext\r
+ );\r
+\r
+ //\r
+ // Start to build the boot option and try to boot\r
+ //\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);\r
+ BootOption = BdsLibVariableToOption (&TempList, Buffer);\r
+ ASSERT (BootOption != NULL);\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+ BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Return the bootable media handle.\r
+ First, check the device is connected\r
+ Second, check whether the device path point to a device which support SimpleFileSystemProtocol,\r
+ Third, detect the the default boot file in the Media, and return the removable Media handle.\r
+\r
+ @param DevicePath Device Path to a bootable device\r
+\r
+ @retval NULL The media on the DevicePath is not bootable\r
+\r
+**/\r
+EFI_HANDLE\r
+EFIAPI\r
+BdsLibGetBootableHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
+ EFI_HANDLE Handle;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ VOID *Buffer;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ UINTN Size;\r
+ UINTN TempSize;\r
+ EFI_HANDLE ReturnHandle;\r
+ EFI_HANDLE *SimpleFileSystemHandles;\r
+\r
+ UINTN NumberSimpleFileSystemHandles;\r
+ UINTN Index;\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+\r
+ UpdatedDevicePath = DevicePath;\r
+ \r
+ //\r
+ // Check whether the device is connected\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Fail to find the proper BlockIo and simple file protocol, maybe because device not present, we need to connect it firstly\r
+ //\r
+ UpdatedDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+ }\r
+ } else {\r
+ //\r
+ // Get BlockIo protocol and check removable attribute\r
+ //\r
+ Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
+ //\r
+ // Issue a dummy read to the device to check for media change.\r
+ // When the removable media is changed, any Block IO read/write will\r
+ // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is\r
+ // returned. After the Block IO protocol is reinstalled, subsequent\r
+ // Block IO read/write will success.\r
+ //\r
+ Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
+ if (Buffer != NULL) {\r
+ BlockIo->ReadBlocks (\r
+ BlockIo,\r
+ BlockIo->Media->MediaId,\r
+ 0,\r
+ BlockIo->Media->BlockSize,\r
+ Buffer\r
+ );\r
+ FreePool(Buffer);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Detect the the default boot file from removable Media\r
+ //\r
+\r
+ //\r
+ // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus\r
+ // Try to locate the USB node device path first, if fail then use its previous PCI node to search\r
+ //\r
+ DupDevicePath = DuplicateDevicePath (DevicePath);\r
+ ASSERT (DupDevicePath != NULL);\r
+ \r
+ UpdatedDevicePath = DupDevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ //\r
+ // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node\r
+ // Acpi()/Pci()/Usb() --> Acpi()/Pci()\r
+ //\r
+ if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) &&\r
+ (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) {\r
+ //\r
+ // Remove the usb node, let the device path only point to PCI node\r
+ //\r
+ SetDevicePathEndNode (UpdatedDevicePath);\r
+ UpdatedDevicePath = DupDevicePath;\r
+ } else {\r
+ UpdatedDevicePath = DevicePath;\r
+ }\r
+\r
+ //\r
+ // Get the device path size of boot option\r
+ //\r
+ Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
+ ReturnHandle = NULL;\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &NumberSimpleFileSystemHandles,\r
+ &SimpleFileSystemHandles\r
+ );\r
+ for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {\r
+ //\r
+ // Get the device path size of SimpleFileSystem handle\r
+ //\r
+ TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);\r
+ TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
+ //\r
+ // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path\r
+ //\r
+ if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) {\r
+ //\r
+ // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+ // machinename is ia32, ia64, x64, ...\r
+ //\r
+ Hdr.Union = &HdrData;\r
+ Status = BdsLibGetImageHeader (\r
+ SimpleFileSystemHandles[Index],\r
+ (CHAR16*)PcdGetPtr(PcdDefaultBootFileName),\r
+ &DosHeader,\r
+ Hdr\r
+ );\r
+ if (!EFI_ERROR (Status) &&\r
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
+ Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ ReturnHandle = SimpleFileSystemHandles[Index];\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool(DupDevicePath);\r
+\r
+ if (SimpleFileSystemHandles != NULL) {\r
+ FreePool(SimpleFileSystemHandles);\r
+ }\r
+\r
+ return ReturnHandle;\r
+}\r
+\r
+/**\r
+ Check to see if the network cable is plugged in. If the DevicePath is not\r
+ connected it will be connected.\r
+\r
+ @param DevicePath Device Path to check\r
+\r
+ @retval TRUE DevicePath points to an Network that is connected\r
+ @retval FALSE DevicePath does not point to a bootable network\r
+\r
+**/\r
+BOOLEAN\r
+BdsLibNetworkBootWithMediaPresent (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath;\r
+ EFI_HANDLE Handle;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+ BOOLEAN MediaPresent;\r
+\r
+ MediaPresent = FALSE;\r
+\r
+ UpdatedDevicePath = DevicePath;\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Device not present so see if we need to connect it\r
+ //\r
+ Status = BdsLibConnectDevicePath (DevicePath);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // This one should work after we did the connect\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Snp->Mode->MediaPresentSupported) {\r
+ if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
+ //\r
+ // In case some one else is using the SNP check to see if it's connected\r
+ //\r
+ MediaPresent = Snp->Mode->MediaPresent;\r
+ } else {\r
+ //\r
+ // No one is using SNP so we need to Start and Initialize so\r
+ // MediaPresent will be valid.\r
+ //\r
+ Status = Snp->Start (Snp);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Snp->Initialize (Snp, 0, 0);\r
+ if (!EFI_ERROR (Status)) {\r
+ MediaPresent = Snp->Mode->MediaPresent;\r
+ Snp->Shutdown (Snp);\r
+ }\r
+ Snp->Stop (Snp);\r
+ }\r
+ }\r
+ } else {\r
+ MediaPresent = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return MediaPresent;\r
+}\r
+\r
+/**\r
+ For a bootable Device path, return its boot type.\r
+\r
+ @param DevicePath The bootable device Path to check\r
+\r
+ @retval BDS_EFI_MEDIA_HD_BOOT If the device path contains any media device path node, it is media boot type\r
+ For the floppy node, handle it as media node\r
+ @retval BDS_EFI_MEDIA_CDROM_BOOT If the device path contains any media device path node, it is media boot type\r
+ For the floppy node, handle it as media node\r
+ @retval BDS_EFI_ACPI_FLOPPY_BOOT If the device path contains any media device path node, it is media boot type\r
+ For the floppy node, handle it as media node\r
+ @retval BDS_EFI_MESSAGE_ATAPI_BOOT If the device path not contains any media device path node, and\r
+ its last device path node point to a message device path node, it is\r
+ \r
+ @retval BDS_EFI_MESSAGE_SCSI_BOOT If the device path not contains any media device path node, and\r
+ its last device path node point to a message device path node, it is\r
+ @retval BDS_EFI_MESSAGE_USB_DEVICE_BOOT If the device path not contains any media device path node, and\r
+ its last device path node point to a message device path node, it is\r
+ @retval BDS_EFI_MESSAGE_MISC_BOOT If the device path not contains any media device path node, and\r
+ its last device path node point to a message device path node, it is\r
+ @retval BDS_LEGACY_BBS_BOOT Legacy boot type\r
+ @retval BDS_EFI_UNSUPPORT An EFI Removable BlockIO device path not point to a media and message device, \r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+BdsGetBootTypeFromDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
+\r
+\r
+ if (NULL == DevicePath) {\r
+ return BDS_EFI_UNSUPPORT;\r
+ }\r
+\r
+ TempDevicePath = DevicePath;\r
+\r
+ while (!IsDevicePathEndType (TempDevicePath)) {\r
+ switch (DevicePathType (TempDevicePath)) {\r
+ case BBS_DEVICE_PATH:\r
+ return BDS_LEGACY_BBS_BOOT;\r
+ case MEDIA_DEVICE_PATH:\r
+ if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) {\r
+ return BDS_EFI_MEDIA_HD_BOOT;\r
+ } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) {\r
+ return BDS_EFI_MEDIA_CDROM_BOOT;\r
+ }\r
+ break;\r
+ case ACPI_DEVICE_PATH:\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath;\r
+ if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {\r
+ return BDS_EFI_ACPI_FLOPPY_BOOT;\r
+ }\r
+ break;\r
+ case MESSAGING_DEVICE_PATH:\r
+ //\r
+ // Get the last device path node\r
+ //\r
+ LastDeviceNode = NextDevicePathNode (TempDevicePath);\r
+ if (DevicePathSubType(LastDeviceNode) == MSG_DEVICE_LOGICAL_UNIT_DP) {\r
+ //\r
+ // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN),\r
+ // skit it\r
+ //\r
+ LastDeviceNode = NextDevicePathNode (LastDeviceNode);\r
+ }\r
+ //\r
+ // if the device path not only point to driver device, it is not a messaging device path,\r
+ //\r
+ if (!IsDevicePathEndType (LastDeviceNode)) {\r
+ break; \r
+ }\r
+\r
+ if (DevicePathSubType(TempDevicePath) == MSG_ATAPI_DP) {\r
+ return BDS_EFI_MESSAGE_ATAPI_BOOT;\r
+ } else if (DevicePathSubType(TempDevicePath) == MSG_USB_DP) {\r
+ return BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
+ } else if (DevicePathSubType(TempDevicePath) == MSG_SCSI_DP) {\r
+ return BDS_EFI_MESSAGE_SCSI_BOOT;\r
+ }\r
+ return BDS_EFI_MESSAGE_MISC_BOOT;\r
+ default:\r
+ break;\r
+ }\r
+ TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+ }\r
+\r
+ return BDS_EFI_UNSUPPORT;\r
+}\r
+\r
+/**\r
+ Check whether the Device path in a boot option point to a valid bootable device,\r
+ And if CheckMedia is true, check the device is ready to boot now.\r
+\r
+ @param DevPath the Device path in a boot option\r
+ @param CheckMedia if true, check the device is ready to boot now.\r
+\r
+ @retval TRUE the Device path is valid\r
+ @retval FALSE the Device path is invalid .\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BdsLibIsValidEFIBootOptDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath,\r
+ IN BOOLEAN CheckMedia\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+\r
+ TempDevicePath = DevPath;\r
+ LastDeviceNode = DevPath;\r
+ \r
+ //\r
+ // Check if it's a valid boot option for network boot device\r
+ // Only check if there is SimpleNetworkProtocol installed. If yes, that means\r
+ // there is the network card there.\r
+ //\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &TempDevicePath,\r
+ &Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Device not present so see if we need to connect it\r
+ //\r
+ TempDevicePath = DevPath;\r
+ BdsLibConnectDevicePath (TempDevicePath);\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiSimpleNetworkProtocolGuid,\r
+ &TempDevicePath,\r
+ &Handle\r
+ );\r
+ }\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ if (CheckMedia) {\r
+ //\r
+ // Test if it is ready to boot now\r
+ //\r
+ if (BdsLibNetworkBootWithMediaPresent(DevPath)) {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If the boot option point to a file, it is a valid EFI boot option,\r
+ // and assume it is ready to boot now\r
+ //\r
+ while (!IsDevicePathEnd (TempDevicePath)) {\r
+ LastDeviceNode = TempDevicePath;\r
+ TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+ }\r
+ if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check if it's a valid boot option for internal Shell\r
+ //\r
+ if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {\r
+ //\r
+ // If the boot option point to Internal FV shell, make sure it is valid\r
+ //\r
+ TempDevicePath = DevPath; \r
+ Status = BdsLibUpdateFvFileDevicePath (&TempDevicePath, &gEfiShellFileGuid);\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return TRUE;\r
+ } else {\r
+ if (Status == EFI_SUCCESS) {\r
+ FreePool (TempDevicePath); \r
+ }\r
+ return FALSE;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // If the boot option point to a blockIO device, no matter whether or not it is a removeable device, it is a valid EFI boot option\r
+ //\r
+ TempDevicePath = DevPath;\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Device not present so see if we need to connect it\r
+ //\r
+ Status = BdsLibConnectDevicePath (DevPath);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Try again to get the Block Io protocol after we did the connect\r
+ //\r
+ TempDevicePath = DevPath;\r
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+ }\r
+ }\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (CheckMedia) {\r
+ //\r
+ // Test if it is ready to boot now\r
+ //\r
+ if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option,\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ if (CheckMedia) {\r
+ //\r
+ // Test if it is ready to boot now\r
+ //\r
+ if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ According to a file guild, check a Fv file device path is valid. If it is invalid,\r
+ try to return the valid device path.\r
+ FV address maybe changes for memory layout adjust from time to time, use this function\r
+ could promise the Fv file device path is right.\r
+\r
+ @param DevicePath on input, the Fv file device path need to check on\r
+ output, the updated valid Fv file device path\r
+ @param FileGuid the Fv file guild\r
+\r
+ @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid\r
+ parameter\r
+ @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file\r
+ guild at all\r
+ @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it is\r
+ valid\r
+ @retval EFI_SUCCESS has successfully updated the invalid DevicePath,\r
+ and return the updated device path in DevicePath\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateFvFileDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,\r
+ IN EFI_GUID *FileGuid\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
+ EFI_STATUS Status;\r
+ EFI_GUID *GuidPoint;\r
+ UINTN Index;\r
+ UINTN FvHandleCount;\r
+ EFI_HANDLE *FvHandleBuffer;\r
+ EFI_FV_FILETYPE Type;\r
+ UINTN Size;\r
+ EFI_FV_FILE_ATTRIBUTES Attributes;\r
+ UINT32 AuthenticationStatus;\r
+ BOOLEAN FindFvFile;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;\r
+ EFI_HANDLE FoundFvHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+\r
+ if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (FileGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ //\r
+ // Check whether the device path point to the default the input Fv file\r
+ //\r
+ TempDevicePath = *DevicePath;\r
+ LastDeviceNode = TempDevicePath;\r
+ while (!IsDevicePathEnd (TempDevicePath)) {\r
+ LastDeviceNode = TempDevicePath;\r
+ TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+ }\r
+ GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (\r
+ (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode\r
+ );\r
+ if (GuidPoint == NULL) {\r
+ //\r
+ // if this option does not points to a Fv file, just return EFI_UNSUPPORTED\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ if (!CompareGuid (GuidPoint, FileGuid)) {\r
+ //\r
+ // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Check whether the input Fv file device path is valid\r
+ //\r
+ TempDevicePath = *DevicePath;\r
+ FoundFvHandle = NULL;\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ &TempDevicePath,\r
+ &FoundFvHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (\r
+ FoundFvHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there\r
+ //\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ FileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Look for the input wanted FV file in current FV\r
+ // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV\r
+ //\r
+ FindFvFile = FALSE;\r
+ FoundFvHandle = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ mBdsImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &LoadedImage\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol (\r
+ LoadedImage->DeviceHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ FileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ FindFvFile = TRUE;\r
+ FoundFvHandle = LoadedImage->DeviceHandle;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Second, if fail to find, try to enumerate all FV\r
+ //\r
+ if (!FindFvFile) {\r
+ FvHandleBuffer = NULL;\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &FvHandleCount,\r
+ &FvHandleBuffer\r
+ );\r
+ for (Index = 0; Index < FvHandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ FvHandleBuffer[Index],\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &Fv\r
+ );\r
+\r
+ Status = Fv->ReadFile (\r
+ Fv,\r
+ FileGuid,\r
+ NULL,\r
+ &Size,\r
+ &Type,\r
+ &Attributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Skip if input Fv file not in the FV\r
+ //\r
+ continue;\r
+ }\r
+ FindFvFile = TRUE;\r
+ FoundFvHandle = FvHandleBuffer[Index];\r
+ break;\r
+ }\r
+\r
+ if (FvHandleBuffer != NULL) {\r
+ FreePool (FvHandleBuffer); \r
+ }\r
+ }\r
+\r
+ if (FindFvFile) {\r
+ //\r
+ // Build the shell device path\r
+ //\r
+ NewDevicePath = DevicePathFromHandle (FoundFvHandle);\r
+ EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);\r
+ NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);\r
+ *DevicePath = NewDevicePath;\r
+ return EFI_SUCCESS;\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
--- /dev/null
+/** @file\r
+ BDS Lib functions which relate with connect the device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+\r
+/**\r
+ This function will connect all the system driver to controller\r
+ first, and then special connect the default console, this make\r
+ sure all the system controller available and the platform default\r
+ console connected.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAll (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Connect the platform console first\r
+ //\r
+ BdsLibConnectAllDefaultConsoles ();\r
+\r
+ //\r
+ // Generic way to connect all the drivers\r
+ //\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+\r
+ //\r
+ // Here we have the assumption that we have already had\r
+ // platform default console\r
+ //\r
+ BdsLibConnectAllDefaultConsoles ();\r
+}\r
+\r
+\r
+/**\r
+ This function will connect all the system drivers to all controllers\r
+ first, and then connect all the console devices the system current\r
+ have. After this we should get all the device work and console available\r
+ if the system have console device.\r
+\r
+**/\r
+VOID\r
+BdsLibGenericConnectAll (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Most generic way to connect all the drivers\r
+ //\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ BdsLibConnectAllConsoles ();\r
+}\r
+\r
+\r
+/**\r
+ This function will create all handles associate with every device\r
+ path node. If the handle associate with one device path node can not\r
+ be created success, then still give one chance to do the dispatch,\r
+ which load the missing drivers if possible.\r
+\r
+ @param DevicePathToConnect The device path which will be connected, it can be\r
+ a multi-instance device path\r
+\r
+ @retval EFI_SUCCESS All handles associate with every device path node\r
+ have been created\r
+ @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles\r
+ @retval EFI_NOT_FOUND Create the handle associate with one device path\r
+ node failed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Next;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE PreviousHandle;\r
+ UINTN Size;\r
+\r
+ if (DevicePathToConnect == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ DevicePath = DuplicateDevicePath (DevicePathToConnect);\r
+ if (DevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyOfDevicePath = DevicePath;\r
+ \r
+ do {\r
+ //\r
+ // The outer loop handles multi instance device paths.\r
+ // Only console variables contain multiple instance device paths.\r
+ //\r
+ // After this call DevicePath points to the next Instance\r
+ //\r
+ Instance = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ if (Instance == NULL) {\r
+ FreePool (CopyOfDevicePath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ Next = Instance;\r
+ while (!IsDevicePathEndType (Next)) {\r
+ Next = NextDevicePathNode (Next);\r
+ }\r
+\r
+ SetDevicePathEndNode (Next);\r
+\r
+ //\r
+ // Start the real work of connect with RemainingDevicePath\r
+ //\r
+ PreviousHandle = NULL;\r
+ do {\r
+ //\r
+ // Find the handle that best matches the Device Path. If it is only a\r
+ // partial match the remaining part of the device path is returned in\r
+ // RemainingDevicePath.\r
+ //\r
+ RemainingDevicePath = Instance;\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Handle == PreviousHandle) {\r
+ //\r
+ // If no forward progress is made try invoking the Dispatcher.\r
+ // A new FV may have been added to the system an new drivers\r
+ // may now be found.\r
+ // Status == EFI_SUCCESS means a driver was dispatched\r
+ // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+ //\r
+ Status = gDS->Dispatch ();\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ PreviousHandle = Handle;\r
+ //\r
+ // Connect all drivers that apply to Handle and RemainingDevicePath,\r
+ // the Recursive flag is FALSE so only one level will be expanded.\r
+ //\r
+ // Do not check the connect status here, if the connect controller fail,\r
+ // then still give the chance to do dispatch, because partial\r
+ // RemainingDevicepath may be in the new FV\r
+ //\r
+ // 1. If the connect fail, RemainingDevicepath and handle will not\r
+ // change, so next time will do the dispatch, then dispatch's status\r
+ // will take effect\r
+ // 2. If the connect success, the RemainingDevicepath and handle will\r
+ // change, then avoid the dispatch, we have chance to continue the\r
+ // next connection\r
+ //\r
+ gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
+ }\r
+ }\r
+ //\r
+ // Loop until RemainingDevicePath is an empty device path\r
+ //\r
+ } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
+\r
+ } while (DevicePath != NULL);\r
+\r
+ if (CopyOfDevicePath != NULL) {\r
+ FreePool (CopyOfDevicePath);\r
+ }\r
+ //\r
+ // All handle with DevicePath exists in the handle database\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function will connect all current system handles recursively. The\r
+ connection will finish until every handle's child handle created if it have.\r
+\r
+ @retval EFI_SUCCESS All handles and it's child handle have been\r
+ connected\r
+ @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllEfi (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will disconnect all current system handles. The disconnection\r
+ will finish until every handle have been disconnected.\r
+\r
+ @retval EFI_SUCCESS All handles have been disconnected\r
+ @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibDisconnectAllEfi (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Disconnect all\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Connects all drivers to all controllers.\r
+ This function make sure all the current system driver will manage\r
+ the correspoinding controllers if have. And at the same time, make\r
+ sure all the system controllers have driver to manage it if have.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllDriversToAllControllers (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ do {\r
+ //\r
+ // Connect All EFI 1.10 drivers following EFI 1.10 algorithm\r
+ //\r
+ BdsLibConnectAllEfi ();\r
+\r
+ //\r
+ // Check to see if it's possible to dispatch an more DXE drivers.\r
+ // The BdsLibConnectAllEfi () may have made new DXE drivers show up.\r
+ // If anything is Dispatched Status == EFI_SUCCESS and we will try\r
+ // the connect again.\r
+ //\r
+ Status = gDS->Dispatch ();\r
+\r
+ } while (!EFI_ERROR (Status));\r
+\r
+}\r
+\r
+\r
+/**\r
+ Connect the specific Usb device which match the short form device path,\r
+ and whose bus is determined by Host Controller (Uhci or Ehci).\r
+\r
+ @param HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci\r
+ (0xFF)\r
+ @param RemainingDevicePath a short-form device path that starts with the first\r
+ element being a USB WWID or a USB Class device\r
+ path\r
+\r
+ @return EFI_INVALID_PARAMETER RemainingDevicePath is NULL pointer.\r
+ RemainingDevicePath is not a USB device path.\r
+ Invalid HostControllerPI type.\r
+ @return EFI_SUCCESS Success to connect USB device\r
+ @return EFI_NOT_FOUND Fail to find handle for USB controller to connect.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectUsbDevByShortFormDP(\r
+ IN UINT8 HostControllerPI,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleArray;\r
+ UINTN HandleArrayCount;\r
+ UINTN Index;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT8 Class[3];\r
+ BOOLEAN AtLeastOneConnected;\r
+\r
+ //\r
+ // Check the passed in parameters\r
+ //\r
+ if (RemainingDevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||\r
+ ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)\r
+ && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)\r
+ )) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (HostControllerPI != 0xFF &&\r
+ HostControllerPI != 0x00 &&\r
+ HostControllerPI != 0x20) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Find the usb host controller firstly, then connect with the remaining device path\r
+ //\r
+ AtLeastOneConnected = FALSE;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiPciIoProtocolGuid,\r
+ NULL,\r
+ &HandleArrayCount,\r
+ &HandleArray\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < HandleArrayCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleArray[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **)&PciIo\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Check whether the Pci device is the wanted usb host controller\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((PCI_CLASS_SERIAL == Class[2]) &&\r
+ (PCI_CLASS_SERIAL_USB == Class[1])) {\r
+ if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {\r
+ Status = gBS->ConnectController (\r
+ HandleArray[Index],\r
+ NULL,\r
+ RemainingDevicePath,\r
+ FALSE\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ AtLeastOneConnected = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (AtLeastOneConnected) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
--- /dev/null
+/** @file\r
+ BDS Lib functions which contain all the code to connect console device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+/**\r
+ Check if we need to save the EFI variable with "ConVarName" as name\r
+ as NV type\r
+\r
+ @param ConVarName The name of the EFI variable.\r
+\r
+ @retval TRUE Set the EFI variable as NV type.\r
+ @retval FALSE EFI variable as NV type can be set NonNV.\r
+**/\r
+BOOLEAN\r
+IsNvNeed (\r
+ IN CHAR16 *ConVarName\r
+ )\r
+{\r
+ CHAR16 *Ptr;\r
+\r
+ Ptr = ConVarName;\r
+\r
+ //\r
+ // If the variable includes "Dev" at last, we consider\r
+ // it does not support NV attribute.\r
+ //\r
+ while (*Ptr != L'\0') {\r
+ Ptr++;\r
+ }\r
+\r
+ if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
+ return FALSE;\r
+ } else {\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+/**\r
+ This function update console variable based on ConVarName, it can\r
+ add or remove one specific console device path from the variable\r
+\r
+ @param ConVarName Console related variable name, ConIn, ConOut,\r
+ ErrOut.\r
+ @param CustomizedConDevicePath The console device path which will be added to\r
+ the console variable ConVarName, this parameter\r
+ can not be multi-instance.\r
+ @param ExclusiveDevicePath The console device path which will be removed\r
+ from the console variable ConVarName, this\r
+ parameter can not be multi-instance.\r
+\r
+ @retval EFI_UNSUPPORTED The added device path is same to the removed one.\r
+ @retval EFI_SUCCESS Success add or remove the device path from the\r
+ console variable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateConsoleVariable (\r
+ IN CHAR16 *ConVarName,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *VarConsole;\r
+ UINTN DevicePathSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+ UINT32 Attributes;\r
+\r
+ VarConsole = NULL;\r
+ DevicePathSize = 0;\r
+\r
+ //\r
+ // Notes: check the device path point, here should check\r
+ // with compare memory\r
+ //\r
+ if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Delete the ExclusiveDevicePath from current default console\r
+ //\r
+ VarConsole = BdsLibGetVariableAndSize (\r
+ ConVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ &DevicePathSize\r
+ );\r
+\r
+ //\r
+ // Initialize NewDevicePath\r
+ //\r
+ NewDevicePath = VarConsole;\r
+\r
+ //\r
+ // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
+ // In the end, NewDevicePath is the final device path.\r
+ //\r
+ if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
+ NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
+ }\r
+ //\r
+ // Try to append customized device path to NewDevicePath.\r
+ //\r
+ if (CustomizedConDevicePath != NULL) {\r
+ if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
+ //\r
+ // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
+ //\r
+ NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
+ //\r
+ // In the first check, the default console variable will be _ModuleEntryPoint,\r
+ // just append current customized device path\r
+ //\r
+ TempNewDevicePath = NewDevicePath;\r
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
+ if (TempNewDevicePath != NULL) {\r
+ FreePool(TempNewDevicePath);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
+ //\r
+ if (IsNvNeed(ConVarName)) {\r
+ //\r
+ // ConVarName has NV attribute.\r
+ //\r
+ Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
+ } else {\r
+ //\r
+ // ConVarName does not have NV attribute.\r
+ //\r
+ Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
+ }\r
+\r
+ //\r
+ // Finally, Update the variable of the default console by NewDevicePath\r
+ //\r
+ gRT->SetVariable (\r
+ ConVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ Attributes,\r
+ GetDevicePathSize (NewDevicePath),\r
+ NewDevicePath\r
+ );\r
+\r
+ if (VarConsole == NewDevicePath) {\r
+ if (VarConsole != NULL) {\r
+ FreePool(VarConsole);\r
+ }\r
+ } else {\r
+ if (VarConsole != NULL) {\r
+ FreePool(VarConsole);\r
+ }\r
+ if (NewDevicePath != NULL) {\r
+ FreePool(NewDevicePath);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Connect the console device base on the variable ConVarName, if\r
+ device path of the ConVarName is multi-instance device path, if\r
+ anyone of the instances is connected success, then this function\r
+ will return success.\r
+\r
+ @param ConVarName Console related variable name, ConIn, ConOut,\r
+ ErrOut.\r
+\r
+ @retval EFI_NOT_FOUND There is not any console devices connected\r
+ success\r
+ @retval EFI_SUCCESS Success connect any one instance of the console\r
+ device path base on the variable ConVarName.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectConsoleVariable (\r
+ IN CHAR16 *ConVarName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;\r
+ UINTN VariableSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *Next;\r
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
+ UINTN Size;\r
+ BOOLEAN DeviceExist;\r
+\r
+ Status = EFI_SUCCESS;\r
+ DeviceExist = FALSE;\r
+\r
+ //\r
+ // Check if the console variable exist\r
+ //\r
+ StartDevicePath = BdsLibGetVariableAndSize (\r
+ ConVarName,\r
+ &gEfiGlobalVariableGuid,\r
+ &VariableSize\r
+ );\r
+ if (StartDevicePath == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CopyOfDevicePath = StartDevicePath;\r
+ do {\r
+ //\r
+ // Check every instance of the console variable\r
+ //\r
+ Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
+ if (Instance == NULL) {\r
+ FreePool (StartDevicePath);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ Next = Instance;\r
+ while (!IsDevicePathEndType (Next)) {\r
+ Next = NextDevicePathNode (Next);\r
+ }\r
+\r
+ SetDevicePathEndNode (Next);\r
+ //\r
+ // Check USB1.1 console\r
+ //\r
+ if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
+ ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
+ || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
+ )) {\r
+ //\r
+ // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus\r
+ //\r
+ Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ }\r
+\r
+ Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);\r
+ if (!EFI_ERROR (Status)) {\r
+ DeviceExist = TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // Connect the instance device path\r
+ //\r
+ Status = BdsLibConnectDevicePath (Instance);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Delete the instance from the console varialbe\r
+ //\r
+ BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
+ } else {\r
+ DeviceExist = TRUE;\r
+ }\r
+ }\r
+ FreePool(Instance);\r
+ } while (CopyOfDevicePath != NULL);\r
+\r
+ FreePool (StartDevicePath);\r
+\r
+ if (!DeviceExist) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will search every simpletext device in current system,\r
+ and make every simpletext device as pertantial console device.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllConsoles (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+\r
+ Index = 0;\r
+ HandleCount = 0;\r
+ HandleBuffer = NULL;\r
+ ConDevicePath = NULL;\r
+\r
+ //\r
+ // Update all the console variables\r
+ //\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ConDevicePath\r
+ );\r
+ BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool(HandleBuffer);\r
+ HandleBuffer = NULL;\r
+ }\r
+\r
+ gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ConDevicePath\r
+ );\r
+ BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
+ BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool(HandleBuffer);\r
+ }\r
+\r
+ //\r
+ // Connect all console variables\r
+ //\r
+ BdsLibConnectAllDefaultConsoles ();\r
+\r
+}\r
+\r
+/**\r
+ This function will connect console device base on the console\r
+ device variable ConIn, ConOut and ErrOut.\r
+\r
+ @retval EFI_SUCCESS At least one of the ConIn and ConOut device have\r
+ been connected success.\r
+ @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllDefaultConsoles (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Connect all default console variables\r
+ //\r
+\r
+ //\r
+ // It seems impossible not to have any ConOut device on platform,\r
+ // so we check the status here.\r
+ //\r
+ Status = BdsLibConnectConsoleVariable (L"ConOut");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Insert the performance probe for Console Out\r
+ //\r
+ PERF_START (NULL, "ConOut", "BDS", 1);\r
+ PERF_END (NULL, "ConOut", "BDS", 0);\r
+\r
+ //\r
+ // Because possibly the platform is legacy free, in such case,\r
+ // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
+ // so we need not check the status.\r
+ //\r
+ BdsLibConnectConsoleVariable (L"ConIn");\r
+\r
+ //\r
+ // The _ModuleEntryPoint err out var is legal.\r
+ //\r
+ BdsLibConnectConsoleVariable (L"ErrOut");\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
+ buffer is passed in it will be used if it is big enough.\r
+\r
+ @param BmpImage Pointer to BMP file\r
+ @param BmpImageSize Number of bytes in BmpImage\r
+ @param GopBlt Buffer containing GOP version of BmpImage.\r
+ @param GopBltSize Size of GopBlt in bytes.\r
+ @param PixelHeight Height of GopBlt/BmpImage in pixels\r
+ @param PixelWidth Width of GopBlt/BmpImage in pixels\r
+\r
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.\r
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image\r
+ @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.\r
+ GopBltSize will contain the required size.\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.\r
+\r
+**/\r
+EFI_STATUS\r
+ConvertBmpToGopBlt (\r
+ IN VOID *BmpImage,\r
+ IN UINTN BmpImageSize,\r
+ IN OUT VOID **GopBlt,\r
+ IN OUT UINTN *GopBltSize,\r
+ OUT UINTN *PixelHeight,\r
+ OUT UINTN *PixelWidth\r
+ )\r
+{\r
+ UINT8 *Image;\r
+ UINT8 *ImageHeader;\r
+ BMP_IMAGE_HEADER *BmpHeader;\r
+ BMP_COLOR_MAP *BmpColorMap;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ UINTN BltBufferSize;\r
+ UINTN Index;\r
+ UINTN Height;\r
+ UINTN Width;\r
+ UINTN ImageIndex;\r
+ BOOLEAN IsAllocated;\r
+\r
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
+\r
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Doesn't support compress.\r
+ //\r
+ if (BmpHeader->CompressionType != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Calculate Color Map offset in the image.\r
+ //\r
+ Image = BmpImage;\r
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
+\r
+ //\r
+ // Calculate graphics image data address in the image\r
+ //\r
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
+ ImageHeader = Image;\r
+\r
+ //\r
+ // Calculate the BltBuffer needed size.\r
+ //\r
+ BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+ IsAllocated = FALSE;\r
+ if (*GopBlt == NULL) {\r
+ //\r
+ // GopBlt is not allocated by caller.\r
+ //\r
+ *GopBltSize = BltBufferSize;\r
+ *GopBlt = AllocatePool (*GopBltSize);\r
+ IsAllocated = TRUE;\r
+ if (*GopBlt == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ //\r
+ // GopBlt has been allocated by caller.\r
+ //\r
+ if (*GopBltSize < BltBufferSize) {\r
+ *GopBltSize = BltBufferSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ }\r
+\r
+ *PixelWidth = BmpHeader->PixelWidth;\r
+ *PixelHeight = BmpHeader->PixelHeight;\r
+\r
+ //\r
+ // Convert image from BMP to Blt buffer format\r
+ //\r
+ BltBuffer = *GopBlt;\r
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
+ switch (BmpHeader->BitPerPixel) {\r
+ case 1:\r
+ //\r
+ // Convert 1-bit (2 colors) BMP to 24-bit color\r
+ //\r
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
+ Blt++;\r
+ Width++;\r
+ }\r
+\r
+ Blt--;\r
+ Width--;\r
+ break;\r
+\r
+ case 4:\r
+ //\r
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
+ //\r
+ Index = (*Image) >> 4;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ if (Width < (BmpHeader->PixelWidth - 1)) {\r
+ Blt++;\r
+ Width++;\r
+ Index = (*Image) & 0x0f;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ }\r
+ break;\r
+\r
+ case 8:\r
+ //\r
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
+ //\r
+ Blt->Red = BmpColorMap[*Image].Red;\r
+ Blt->Green = BmpColorMap[*Image].Green;\r
+ Blt->Blue = BmpColorMap[*Image].Blue;\r
+ break;\r
+\r
+ case 24:\r
+ //\r
+ // It is 24-bit BMP.\r
+ //\r
+ Blt->Blue = *Image++;\r
+ Blt->Green = *Image++;\r
+ Blt->Red = *Image;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Other bit format BMP is not supported.\r
+ //\r
+ if (IsAllocated) {\r
+ FreePool (*GopBlt);\r
+ *GopBlt = NULL;\r
+ }\r
+ return EFI_UNSUPPORTED;\r
+ break;\r
+ };\r
+\r
+ }\r
+\r
+ ImageIndex = (UINTN) (Image - ImageHeader);\r
+ if ((ImageIndex % 4) != 0) {\r
+ //\r
+ // Bmp Image starts each row on a 32-bit boundary!\r
+ //\r
+ Image = Image + (4 - (ImageIndex % 4));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Use Console Control Protocol to lock the Console In Spliter virtual handle.\r
+ This is the ConInHandle and ConIn handle in the EFI system table. All key\r
+ presses will be ignored until the Password is typed in. The only way to\r
+ disable the password is to type it in to a ConIn device.\r
+\r
+ @param Password Password used to lock ConIn device.\r
+\r
+ @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.\r
+ @retval EFI_UNSUPPORTED Password not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LockKeyboards (\r
+ IN CHAR16 *Password\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = ConsoleControl->LockStdIn (ConsoleControl, Password);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Use Console Control to turn off UGA based Simple Text Out consoles from going\r
+ to the UGA device. Put up LogoFile on every UGA device that is a console\r
+\r
+ @param[in] LogoFile File name of logo to display on the center of the screen.\r
+\r
+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed.\r
+ @retval EFI_UNSUPPORTED Logo not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EnableQuietBoot (\r
+ IN EFI_GUID *LogoFile\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+ EFI_OEM_BADGING_PROTOCOL *Badging;\r
+ UINT32 SizeOfX;\r
+ UINT32 SizeOfY;\r
+ INTN DestX;\r
+ INTN DestY;\r
+ UINT8 *ImageData;\r
+ UINTN ImageSize;\r
+ UINTN BltSize;\r
+ UINT32 Instance;\r
+ EFI_BADGING_FORMAT Format;\r
+ EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
+ UINTN CoordinateX;\r
+ UINTN CoordinateY;\r
+ UINTN Height;\r
+ UINTN Width;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ UgaDraw = NULL;\r
+ //\r
+ // Try to open GOP first\r
+ //\r
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ GraphicsOutput = NULL;\r
+ //\r
+ // Open GOP failed, try to open UGA\r
+ //\r
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Badging = NULL;\r
+ Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
+\r
+ //\r
+ // Set console control to graphics mode.\r
+ //\r
+ Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+\r
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Instance = 0;\r
+ while (1) {\r
+ ImageData = NULL;\r
+ ImageSize = 0;\r
+\r
+ if (Badging != NULL) {\r
+ //\r
+ // Get image from OEMBadging protocol.\r
+ //\r
+ Status = Badging->GetImage (\r
+ Badging,\r
+ &Instance,\r
+ &Format,\r
+ &ImageData,\r
+ &ImageSize,\r
+ &Attribute,\r
+ &CoordinateX,\r
+ &CoordinateY\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Currently only support BMP format.\r
+ //\r
+ if (Format != EfiBadgingFormatBMP) {\r
+ if (ImageData != NULL) {\r
+ FreePool (ImageData);\r
+ }\r
+ continue;\r
+ }\r
+ } else {\r
+ //\r
+ // Get the specified image from FV.\r
+ //\r
+ Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CoordinateX = 0;\r
+ CoordinateY = 0;\r
+ Attribute = EfiBadgingDisplayAttributeCenter;\r
+ }\r
+\r
+ Blt = NULL;\r
+ Status = ConvertBmpToGopBlt (\r
+ ImageData,\r
+ ImageSize,\r
+ (VOID **) &Blt,\r
+ &BltSize,\r
+ &Height,\r
+ &Width\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (ImageData);\r
+\r
+ if (Badging == NULL) {\r
+ return Status;\r
+ } else {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Calculate the display position according to Attribute.\r
+ //\r
+ switch (Attribute) {\r
+ case EfiBadgingDisplayAttributeLeftTop:\r
+ DestX = CoordinateX;\r
+ DestY = CoordinateY;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterTop:\r
+ DestX = (SizeOfX - Width) / 2;\r
+ DestY = CoordinateY;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeRightTop:\r
+ DestX = (SizeOfX - Width - CoordinateX);\r
+ DestY = CoordinateY;;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterRight:\r
+ DestX = (SizeOfX - Width - CoordinateX);\r
+ DestY = (SizeOfY - Height) / 2;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeRightBottom:\r
+ DestX = (SizeOfX - Width - CoordinateX);\r
+ DestY = (SizeOfY - Height - CoordinateY);\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterBottom:\r
+ DestX = (SizeOfX - Width) / 2;\r
+ DestY = (SizeOfY - Height - CoordinateY);\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeLeftBottom:\r
+ DestX = CoordinateX;\r
+ DestY = (SizeOfY - Height - CoordinateY);\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterLeft:\r
+ DestX = CoordinateX;\r
+ DestY = (SizeOfY - Height) / 2;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenter:\r
+ DestX = (SizeOfX - Width) / 2;\r
+ DestY = (SizeOfY - Height) / 2;\r
+ break;\r
+\r
+ default:\r
+ DestX = CoordinateX;\r
+ DestY = CoordinateY;\r
+ break;\r
+ }\r
+\r
+ if ((DestX >= 0) && (DestY >= 0)) {\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ Blt,\r
+ EfiBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ (UINTN) DestX,\r
+ (UINTN) DestY,\r
+ Width,\r
+ Height,\r
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) Blt,\r
+ EfiUgaBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ (UINTN) DestX,\r
+ (UINTN) DestY,\r
+ Width,\r
+ Height,\r
+ Width * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ FreePool (ImageData);\r
+\r
+ if (Blt != NULL) {\r
+ FreePool (Blt);\r
+ }\r
+\r
+ if (Badging == NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Use Console Control to turn on UGA based Simple Text Out consoles. The UGA\r
+ Simple Text Out screens will now be synced up with all non UGA output devices\r
+\r
+ @retval EFI_SUCCESS UGA devices are back in text mode and synced up.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisableQuietBoot (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Set console control to text mode.\r
+ //\r
+ return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Misc BDS library function\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+\r
+#define MAX_STRING_LEN 200\r
+\r
+BOOLEAN mFeaturerSwitch = TRUE;\r
+BOOLEAN mResetRequired = FALSE;\r
+\r
+extern UINT16 gPlatformBootTimeOutDefault;\r
+\r
+\r
+/**\r
+ Return the default value for system Timeout variable.\r
+\r
+ @return Timeout value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+BdsLibGetTimeout (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 Timeout;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Return Timeout variable or 0xffff if no valid\r
+ // Timeout variable exists.\r
+ //\r
+ Size = sizeof (UINT16);\r
+ Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // According to UEFI 2.0 spec, it should treat the Timeout value as 0xffff\r
+ // (default value PcdPlatformBootTimeOutDefault) when L"Timeout" variable is not present.\r
+ // To make the current EFI Automatic-Test activity possible, platform can choose other value\r
+ // for automatic boot when the variable is not present.\r
+ //\r
+ Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);\r
+ }\r
+\r
+ return Timeout;\r
+}\r
+\r
+/**\r
+ The function will go through the driver option link list, load and start\r
+ every driver the driver option device path point to.\r
+\r
+ @param BdsDriverLists The header of the current driver option link list\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibLoadDrivers (\r
+ IN LIST_ENTRY *BdsDriverLists\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BDS_COMMON_OPTION *Option;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ BOOLEAN ReconnectAll;\r
+\r
+ ReconnectAll = FALSE;\r
+\r
+ //\r
+ // Process the driver option\r
+ //\r
+ for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+ \r
+ //\r
+ // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
+ // the boot manager will not automatically load the option.\r
+ //\r
+ if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
+ // then all of the EFI drivers in the system will be disconnected and\r
+ // reconnected after the last driver load option is processed.\r
+ //\r
+ if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {\r
+ ReconnectAll = TRUE;\r
+ }\r
+ \r
+ //\r
+ // Make sure the driver path is connected.\r
+ //\r
+ BdsLibConnectDevicePath (Option->DevicePath);\r
+\r
+ //\r
+ // Load and start the image that Driver#### describes\r
+ //\r
+ Status = gBS->LoadImage (\r
+ FALSE,\r
+ mBdsImageHandle,\r
+ Option->DevicePath,\r
+ NULL,\r
+ 0,\r
+ &ImageHandle\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+\r
+ //\r
+ // Verify whether this image is a driver, if not,\r
+ // exit it and continue to parse next load option\r
+ //\r
+ if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
+ gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
+ continue;\r
+ }\r
+\r
+ if (Option->LoadOptionsSize != 0) {\r
+ ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;\r
+ ImageInfo->LoadOptions = Option->LoadOptions;\r
+ }\r
+ //\r
+ // Before calling the image, enable the Watchdog Timer for\r
+ // the 5 Minute period\r
+ //\r
+ gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+ Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));\r
+\r
+ //\r
+ // Clear the Watchdog Timer after the image returns\r
+ //\r
+ gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
+ //\r
+ if (ReconnectAll) {\r
+ BdsLibDisconnectAllEfi ();\r
+ BdsLibConnectAll ();\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Get the Option Number that does not used.\r
+ Try to locate the specific option variable one by one utile find a free number.\r
+\r
+ @param VariableName Indicate if the boot#### or driver#### option\r
+\r
+ @return The Minimal Free Option Number\r
+\r
+**/\r
+UINT16\r
+BdsLibGetFreeOptionNumber (\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ UINTN Index;\r
+ CHAR16 StrTemp[10];\r
+ UINT16 *OptionBuffer;\r
+ UINTN OptionSize;\r
+\r
+ //\r
+ // Try to find the minimum free number from 0, 1, 2, 3....\r
+ //\r
+ Index = 0;\r
+ do {\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);\r
+ } else {\r
+ UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);\r
+ }\r
+ //\r
+ // try if the option number is used\r
+ //\r
+ OptionBuffer = BdsLibGetVariableAndSize (\r
+ StrTemp,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionSize\r
+ );\r
+ if (OptionBuffer == NULL) {\r
+ break;\r
+ }\r
+ Index++;\r
+ } while (TRUE);\r
+\r
+ return ((UINT16) Index);\r
+}\r
+\r
+\r
+/**\r
+ This function will register the new boot#### or driver#### option base on\r
+ the VariableName. The new registered boot#### or driver#### will be linked\r
+ to BdsOptionList and also update to the VariableName. After the boot#### or\r
+ driver#### updated, the BootOrder or DriverOrder will also be updated.\r
+\r
+ @param BdsOptionList The header of the boot#### or driver#### link list\r
+ @param DevicePath The device path which the boot#### or driver####\r
+ option present\r
+ @param String The description of the boot#### or driver####\r
+ @param VariableName Indicate if the boot#### or driver#### option\r
+\r
+ @retval EFI_SUCCESS The boot#### or driver#### have been success\r
+ registered\r
+ @retval EFI_STATUS Return the status of gRT->SetVariable ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibRegisterNewOption (\r
+ IN LIST_ENTRY *BdsOptionList,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN CHAR16 *String,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINT16 RegisterOptionNumber;\r
+ UINT16 *TempOptionPtr;\r
+ UINTN TempOptionSize;\r
+ UINT16 *OptionOrderPtr;\r
+ VOID *OptionPtr;\r
+ UINTN OptionSize;\r
+ UINT8 *TempPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;\r
+ CHAR16 *Description;\r
+ CHAR16 OptionName[10];\r
+ BOOLEAN UpdateDescription;\r
+ UINT16 BootOrderEntry;\r
+ UINTN OrderItemNum;\r
+\r
+\r
+ OptionPtr = NULL;\r
+ OptionSize = 0;\r
+ TempPtr = NULL;\r
+ OptionDevicePath = NULL;\r
+ Description = NULL;\r
+ OptionOrderPtr = NULL;\r
+ UpdateDescription = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (OptionName, sizeof (OptionName));\r
+\r
+ TempOptionSize = 0;\r
+ TempOptionPtr = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &TempOptionSize\r
+ );\r
+ //\r
+ // Compare with current option variable if the previous option is set in global variable.\r
+ //\r
+ for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {\r
+ //\r
+ // TempOptionPtr must not be NULL if we have non-zero TempOptionSize.\r
+ //\r
+ ASSERT (TempOptionPtr != NULL);\r
+\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);\r
+ } else {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);\r
+ }\r
+\r
+ OptionPtr = BdsLibGetVariableAndSize (\r
+ OptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionSize\r
+ );\r
+ if (OptionPtr == NULL) {\r
+ continue;\r
+ }\r
+ TempPtr = OptionPtr;\r
+ TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+ Description = (CHAR16 *) TempPtr;\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+ OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+\r
+ //\r
+ // Notes: the description may will change base on the GetStringToken\r
+ //\r
+ if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {\r
+ if (CompareMem (Description, String, StrSize (Description)) == 0) { \r
+ //\r
+ // Got the option, so just return\r
+ //\r
+ FreePool (OptionPtr);\r
+ FreePool (TempOptionPtr);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Option description changed, need update.\r
+ //\r
+ UpdateDescription = TRUE;\r
+ FreePool (OptionPtr);\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (OptionPtr);\r
+ }\r
+\r
+ OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);\r
+ OptionSize += GetDevicePathSize (DevicePath);\r
+ OptionPtr = AllocateZeroPool (OptionSize);\r
+ ASSERT (OptionPtr != NULL);\r
+ \r
+ TempPtr = OptionPtr;\r
+ *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;\r
+ TempPtr += sizeof (UINT32);\r
+ *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);\r
+ TempPtr += sizeof (UINT16);\r
+ CopyMem (TempPtr, String, StrSize (String));\r
+ TempPtr += StrSize (String);\r
+ CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));\r
+\r
+ if (UpdateDescription) {\r
+ //\r
+ // The number in option#### to be updated. \r
+ // In this case, we must have non-NULL TempOptionPtr.\r
+ //\r
+ ASSERT (TempOptionPtr != NULL);\r
+ RegisterOptionNumber = TempOptionPtr[Index];\r
+ } else {\r
+ //\r
+ // The new option#### number\r
+ //\r
+ RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);\r
+ }\r
+\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);\r
+ } else {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ OptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ OptionSize,\r
+ OptionPtr\r
+ );\r
+ //\r
+ // Return if only need to update a changed description or fail to set option.\r
+ //\r
+ if (EFI_ERROR (Status) || UpdateDescription) {\r
+ FreePool (OptionPtr);\r
+ if (TempOptionPtr != NULL) {\r
+ FreePool (TempOptionPtr);\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ FreePool (OptionPtr);\r
+\r
+ //\r
+ // Update the option order variable\r
+ //\r
+\r
+ //\r
+ // If no option order\r
+ //\r
+ if (TempOptionSize == 0) {\r
+ BootOrderEntry = 0;\r
+ Status = gRT->SetVariable (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT16),\r
+ &BootOrderEntry\r
+ );\r
+ if (TempOptionPtr != NULL) {\r
+ FreePool (TempOptionPtr);\r
+ }\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // TempOptionPtr must not be NULL if TempOptionSize is not zero.\r
+ //\r
+ ASSERT (TempOptionPtr != NULL);\r
+ //\r
+ // Append the new option number to the original option order\r
+ //\r
+ OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;\r
+ OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));\r
+ ASSERT (OptionOrderPtr!= NULL);\r
+ CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));\r
+\r
+ OptionOrderPtr[Index] = RegisterOptionNumber;\r
+\r
+ Status = gRT->SetVariable (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ OrderItemNum * sizeof (UINT16),\r
+ OptionOrderPtr\r
+ );\r
+ FreePool (TempOptionPtr);\r
+ FreePool (OptionOrderPtr);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Build the boot#### or driver#### option from the VariableName, the\r
+ build boot#### or driver#### will also be linked to BdsCommonOptionList.\r
+\r
+ @param BdsCommonOptionList The header of the boot#### or driver#### option\r
+ link list\r
+ @param VariableName EFI Variable name indicate if it is boot#### or\r
+ driver####\r
+\r
+ @retval BDS_COMMON_OPTION Get the option just been created\r
+ @retval NULL Failed to get the new option\r
+\r
+**/\r
+BDS_COMMON_OPTION *\r
+EFIAPI\r
+BdsLibVariableToOption (\r
+ IN OUT LIST_ENTRY *BdsCommonOptionList,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ UINT32 Attribute;\r
+ UINT16 FilePathSize;\r
+ UINT8 *Variable;\r
+ UINT8 *TempPtr;\r
+ UINTN VariableSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BDS_COMMON_OPTION *Option;\r
+ VOID *LoadOptions;\r
+ UINT32 LoadOptionsSize;\r
+ CHAR16 *Description;\r
+ UINT8 NumOff;\r
+ //\r
+ // Read the variable. We will never free this data.\r
+ //\r
+ Variable = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &VariableSize\r
+ );\r
+ if (Variable == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // Notes: careful defined the variable of Boot#### or\r
+ // Driver####, consider use some macro to abstract the code\r
+ //\r
+ //\r
+ // Get the option attribute\r
+ //\r
+ TempPtr = Variable;\r
+ Attribute = *(UINT32 *) Variable;\r
+ TempPtr += sizeof (UINT32);\r
+\r
+ //\r
+ // Get the option's device path size\r
+ //\r
+ FilePathSize = *(UINT16 *) TempPtr;\r
+ TempPtr += sizeof (UINT16);\r
+\r
+ //\r
+ // Get the option's description string\r
+ //\r
+ Description = (CHAR16 *) TempPtr;\r
+\r
+ //\r
+ // Get the option's description string size\r
+ //\r
+ TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+\r
+ //\r
+ // Get the option's device path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+ TempPtr += FilePathSize;\r
+\r
+ LoadOptions = TempPtr;\r
+ LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));\r
+\r
+ //\r
+ // The Console variables may have multiple device paths, so make\r
+ // an Entry for each one.\r
+ //\r
+ Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));\r
+ if (Option == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Option->Signature = BDS_LOAD_OPTION_SIGNATURE;\r
+ Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
+ ASSERT(Option->DevicePath != NULL);\r
+ CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
+\r
+ Option->Attribute = Attribute;\r
+ Option->Description = AllocateZeroPool (StrSize (Description));\r
+ ASSERT(Option->Description != NULL);\r
+ CopyMem (Option->Description, Description, StrSize (Description));\r
+\r
+ Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);\r
+ ASSERT(Option->LoadOptions != NULL);\r
+ CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);\r
+ Option->LoadOptionsSize = LoadOptionsSize;\r
+\r
+ //\r
+ // Get the value from VariableName Unicode string\r
+ // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this\r
+ // Unicode stream to ASCII without any loss in meaning.\r
+ //\r
+ if (*VariableName == 'B') {\r
+ NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;\r
+ Option->BootCurrent = (UINT16) ((VariableName[NumOff] -'0') * 0x1000);\r
+ Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));\r
+ Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+2]-'0') * 0x10));\r
+ Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+3]-'0')));\r
+ }\r
+ //\r
+ // Insert active entry to BdsDeviceList\r
+ //\r
+ if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
+ InsertTailList (BdsCommonOptionList, &Option->Link);\r
+ FreePool (Variable);\r
+ return Option;\r
+ }\r
+\r
+ FreePool (Variable);\r
+ FreePool (Option);\r
+ return NULL;\r
+\r
+}\r
+\r
+/**\r
+ Process BootOrder, or DriverOrder variables, by calling\r
+ BdsLibVariableToOption () for each UINT16 in the variables.\r
+\r
+ @param BdsCommonOptionList The header of the option list base on variable\r
+ VariableName\r
+ @param VariableName EFI Variable name indicate the BootOrder or\r
+ DriverOrder\r
+\r
+ @retval EFI_SUCCESS Success create the boot option or driver option\r
+ list\r
+ @retval EFI_OUT_OF_RESOURCES Failed to get the boot option or driver option list\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibBuildOptionFromVar (\r
+ IN LIST_ENTRY *BdsCommonOptionList,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ UINT16 *OptionOrder;\r
+ UINTN OptionOrderSize;\r
+ UINTN Index;\r
+ BDS_COMMON_OPTION *Option;\r
+ CHAR16 OptionName[20];\r
+\r
+ //\r
+ // Zero Buffer in order to get all BOOT#### variables\r
+ //\r
+ ZeroMem (OptionName, sizeof (OptionName));\r
+\r
+ //\r
+ // Read the BootOrder, or DriverOrder variable.\r
+ //\r
+ OptionOrder = BdsLibGetVariableAndSize (\r
+ VariableName,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionOrderSize\r
+ );\r
+ if (OptionOrder == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {\r
+ if (*VariableName == 'B') {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);\r
+ } else {\r
+ UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);\r
+ }\r
+\r
+ Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName);\r
+ ASSERT (Option != NULL);\r
+ Option->BootCurrent = OptionOrder[Index];\r
+\r
+ }\r
+\r
+ FreePool (OptionOrder);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get boot mode by looking up configuration table and parsing HOB list\r
+\r
+ @param BootMode Boot mode from PEI handoff HOB.\r
+\r
+ @retval EFI_SUCCESS Successfully get boot mode\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibGetBootMode (\r
+ OUT EFI_BOOT_MODE *BootMode\r
+ )\r
+{\r
+ *BootMode = GetBootModeHob ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
+ buffer, and the size of the buffer. If failure return NULL.\r
+\r
+ @param Name String part of EFI variable name\r
+ @param VendorGuid GUID part of EFI variable name\r
+ @param VariableSize Returns the size of the EFI variable that was read\r
+\r
+ @return Dynamically allocated memory that contains a copy of the EFI variable\r
+ Caller is responsible freeing the buffer.\r
+ @retval NULL Variable was not read\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+BdsLibGetVariableAndSize (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VariableSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ VOID *Buffer;\r
+\r
+ Buffer = NULL;\r
+\r
+ //\r
+ // Pass in a zero size buffer to find the required buffer size.\r
+ //\r
+ BufferSize = 0;\r
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // Allocate the buffer to return\r
+ //\r
+ Buffer = AllocateZeroPool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // Read variable into the allocated buffer.\r
+ //\r
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ BufferSize = 0;\r
+ }\r
+ }\r
+\r
+ *VariableSize = BufferSize;\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Delete the instance in Multi which matches partly with Single instance\r
+\r
+ @param Multi A pointer to a multi-instance device path data\r
+ structure.\r
+ @param Single A pointer to a single-instance device path data\r
+ structure.\r
+\r
+ @return This function will remove the device path instances in Multi which partly\r
+ match with the Single, and return the result device path. If there is no\r
+ remaining device path as a result, this function will return NULL.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsLibDelPartMatchInstance (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Instance;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;\r
+ UINTN InstanceSize;\r
+ UINTN SingleDpSize;\r
+ UINTN Size;\r
+\r
+ NewDevicePath = NULL;\r
+ TempNewDevicePath = NULL;\r
+\r
+ if (Multi == NULL || Single == NULL) {\r
+ return Multi;\r
+ }\r
+\r
+ Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+ SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;\r
+ InstanceSize -= END_DEVICE_PATH_LENGTH;\r
+\r
+ while (Instance != NULL) {\r
+\r
+ Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;\r
+\r
+ if ((CompareMem (Instance, Single, Size) != 0)) {\r
+ //\r
+ // Append the device path instance which does not match with Single\r
+ //\r
+ TempNewDevicePath = NewDevicePath;\r
+ NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);\r
+ if (TempNewDevicePath != NULL) {\r
+ FreePool(TempNewDevicePath);\r
+ }\r
+ }\r
+ FreePool(Instance);\r
+ Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+ InstanceSize -= END_DEVICE_PATH_LENGTH;\r
+ }\r
+\r
+ return NewDevicePath;\r
+}\r
+\r
+/**\r
+ Function compares a device path data structure to that of all the nodes of a\r
+ second device path instance.\r
+\r
+ @param Multi A pointer to a multi-instance device path data\r
+ structure.\r
+ @param Single A pointer to a single-instance device path data\r
+ structure.\r
+\r
+ @retval TRUE If the Single device path is contained within Multi device path.\r
+ @retval FALSE The Single device path is not match within Multi device path.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BdsLibMatchDevicePaths (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ UINTN Size;\r
+\r
+ if (Multi == NULL || Single == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ DevicePath = Multi;\r
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+\r
+ //\r
+ // Search for the match of 'Single' in 'Multi'\r
+ //\r
+ while (DevicePathInst != NULL) {\r
+ //\r
+ // If the single device path is found in multiple device paths,\r
+ // return success\r
+ //\r
+ if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+ FreePool (DevicePathInst);\r
+ return TRUE;\r
+ }\r
+\r
+ FreePool (DevicePathInst);\r
+ DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ This function prints a series of strings.\r
+\r
+ @param ConOut Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+ @param ... A variable argument list containing series of\r
+ strings, the last string must be NULL.\r
+\r
+ @retval EFI_SUCCESS Success print out the string using ConOut.\r
+ @retval EFI_STATUS Return the status of the ConOut->OutputString ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibOutputStrings (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Args;\r
+ EFI_STATUS Status;\r
+ CHAR16 *String;\r
+\r
+ Status = EFI_SUCCESS;\r
+ VA_START (Args, ConOut);\r
+\r
+ while (!EFI_ERROR (Status)) {\r
+ //\r
+ // If String is NULL, then it's the end of the list\r
+ //\r
+ String = VA_ARG (Args, CHAR16 *);\r
+ if (String != NULL) {\r
+ break;\r
+ }\r
+\r
+ Status = ConOut->OutputString (ConOut, String);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+ \r
+ VA_END(Args);\r
+ return Status;\r
+}\r
+\r
+//\r
+// Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.\r
+// Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser if\r
+// user change any option setting which needs a reset to be effective, and the reset will be applied according to the user selection.\r
+//\r
+\r
+\r
+/**\r
+ Enable the setup browser reset reminder feature.\r
+ This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableResetReminderFeature (\r
+ VOID\r
+ )\r
+{\r
+ mFeaturerSwitch = TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Disable the setup browser reset reminder feature.\r
+ This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableResetReminderFeature (\r
+ VOID\r
+ )\r
+{\r
+ mFeaturerSwitch = FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Record the info that a reset is required.\r
+ A module boolean variable is used to record whether a reset is required.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableResetRequired (\r
+ VOID\r
+ )\r
+{\r
+ mResetRequired = TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Record the info that no reset is required.\r
+ A module boolean variable is used to record whether a reset is required.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableResetRequired (\r
+ VOID\r
+ )\r
+{\r
+ mResetRequired = FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Check whether platform policy enable the reset reminder feature. The default is enabled.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsResetReminderFeatureEnable (\r
+ VOID\r
+ )\r
+{\r
+ return mFeaturerSwitch;\r
+}\r
+\r
+\r
+/**\r
+ Check if user changed any option setting which needs a system reset to be effective.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsResetRequired (\r
+ VOID\r
+ )\r
+{\r
+ return mResetRequired;\r
+}\r
+\r
+\r
+/**\r
+ Check whether a reset is needed, and finish the reset reminder feature.\r
+ If a reset is needed, Popup a menu to notice user, and finish the feature\r
+ according to the user selection.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetupResetReminder (\r
+ VOID\r
+ )\r
+{\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 *StringBuffer1;\r
+ CHAR16 *StringBuffer2;\r
+\r
+\r
+ //\r
+ //check any reset required change is applied? if yes, reset system\r
+ //\r
+ if (IsResetReminderFeatureEnable ()) {\r
+ if (IsResetRequired ()) {\r
+\r
+ StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+ ASSERT (StringBuffer1 != NULL);\r
+ StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+ ASSERT (StringBuffer2 != NULL);\r
+ StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
+ StrCpy (StringBuffer2, L"Enter (YES) / Esc (NO)");\r
+ //\r
+ // Popup a menu to notice user\r
+ //\r
+ do {\r
+ IfrLibCreatePopUp (2, &Key, StringBuffer1, StringBuffer2);\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ FreePool (StringBuffer1);\r
+ FreePool (StringBuffer2);\r
+ //\r
+ // If the user hits the YES Response key, reset\r
+ //\r
+ if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+ }\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get the headers (dos, image, optional header) from an image\r
+\r
+ @param Device SimpleFileSystem device handle\r
+ @param FileName File name for the image\r
+ @param DosHeader Pointer to dos header\r
+ @param Hdr The buffer in which to return the PE32, PE32+, or TE header.\r
+\r
+ @retval EFI_SUCCESS Successfully get the machine type.\r
+ @retval EFI_NOT_FOUND The file is not found.\r
+ @retval EFI_LOAD_ERROR File is not a valid image file.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibGetImageHeader (\r
+ IN EFI_HANDLE Device,\r
+ IN CHAR16 *FileName,\r
+ OUT EFI_IMAGE_DOS_HEADER *DosHeader,\r
+ OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+ EFI_FILE_HANDLE Root;\r
+ EFI_FILE_HANDLE ThisFile;\r
+ UINTN BufferSize;\r
+ UINT64 FileSize;\r
+ EFI_FILE_INFO *Info;\r
+\r
+ Root = NULL;\r
+ ThisFile = NULL;\r
+ //\r
+ // Handle the file system interface to the device\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Device,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (VOID *) &Volume\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = Volume->OpenVolume (\r
+ Volume,\r
+ &Root\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Root = NULL;\r
+ goto Done;\r
+ }\r
+\r
+ Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get file size\r
+ //\r
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
+ do {\r
+ Info = NULL;\r
+ Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ Status = ThisFile->GetInfo (\r
+ ThisFile,\r
+ &gEfiFileInfoGuid,\r
+ &BufferSize,\r
+ Info\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (Info);\r
+ goto Done;\r
+ }\r
+ FreePool (Info);\r
+ } while (TRUE);\r
+\r
+ FileSize = Info->FileSize;\r
+ FreePool (Info);\r
+\r
+ //\r
+ // Read dos header\r
+ //\r
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+ Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);\r
+ if (EFI_ERROR (Status) ||\r
+ BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||\r
+ FileSize <= DosHeader->e_lfanew ||\r
+ DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Move to PE signature\r
+ //\r
+ Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Read and check PE signature\r
+ //\r
+ BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
+ Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);\r
+ if (EFI_ERROR (Status) ||\r
+ BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||\r
+ Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check PE32 or PE32+ magic\r
+ //\r
+ if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&\r
+ Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ Status = EFI_LOAD_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ Done:\r
+ if (ThisFile != NULL) {\r
+ ThisFile->Close (ThisFile);\r
+ }\r
+ if (Root != NULL) {\r
+ Root->Close (Root);\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This routine is a notification function for legayc boot or exit boot\r
+ service event. It will adjust the memory information for different\r
+ memory type and save them into the variables for next boot.\r
+\r
+\r
+ @param Event The event that triggered this notification function.\r
+ @param Context Pointer to the notification functions context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsSetMemoryTypeInformationVariable (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;\r
+ EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;\r
+ UINTN VariableSize;\r
+ BOOLEAN UpdateRequired;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINT32 Previous;\r
+ UINT32 Current;\r
+ UINT32 Next;\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+\r
+ UpdateRequired = FALSE;\r
+\r
+ //\r
+ // Retrieve the current memory usage statistics. If they are not found, then\r
+ // no adjustments can be made to the Memory Type Information variable.\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiMemoryTypeInformationGuid,\r
+ (VOID **) &CurrentMemoryTypeInformation\r
+ );\r
+ if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Get the Memory Type Information settings from Hob if they exist,\r
+ // PEI is responsible for getting them from variable and build a Hob to save them.\r
+ // If the previous Memory Type Information is not available, then set defaults\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
+ if (GuidHob == NULL) {\r
+ //\r
+ // If Platform has not built Memory Type Info into the Hob, just return.\r
+ //\r
+ return;\r
+ }\r
+ PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
+ VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
+\r
+ //\r
+ // Use a heuristic to adjust the Memory Type Information for the next boot\r
+ //\r
+ for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
+\r
+ Current = 0;\r
+ for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {\r
+ if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {\r
+ Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {\r
+ continue;\r
+ }\r
+\r
+ Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;\r
+\r
+ //\r
+ // Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail\r
+ //\r
+ if (Current > Previous) {\r
+ Next = Current + (Current >> 2);\r
+ } else {\r
+ Next = Previous;\r
+ }\r
+ if (Next > 0 && Next < 4) {\r
+ Next = 4;\r
+ }\r
+\r
+ if (Next != Previous) {\r
+ PreviousMemoryTypeInformation[Index].NumberOfPages = Next;\r
+ UpdateRequired = TRUE;\r
+ }\r
+\r
+ }\r
+\r
+ //\r
+ // If any changes were made to the Memory Type Information settings, then set the new variable value\r
+ //\r
+ if (UpdateRequired) {\r
+ Status = gRT->SetVariable (\r
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+ &gEfiMemoryTypeInformationGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ VariableSize,\r
+ PreviousMemoryTypeInformation\r
+ );\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ This routine register a function to adjust the different type memory page number\r
+ just before booting and save the updated info into the variable for next boot to use.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibSaveMemoryTypeInformation (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT ReadyToBootEvent;\r
+\r
+ Status = EfiCreateEventReadyToBootEx (\r
+ TPL_CALLBACK,\r
+ BdsSetMemoryTypeInformationVariable,\r
+ NULL,\r
+ &ReadyToBootEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));\r
+ }\r
+\r
+}\r
+\r
+\r
--- /dev/null
+/** @file\r
+ BDS internal function define the default device path string, it can be\r
+ replaced by platform device path.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+/**\r
+ Concatenates a formatted unicode string to allocated pool.\r
+ The caller must free the resulting buffer.\r
+\r
+ @param Str Tracks the allocated pool, size in use, and amount of pool allocated.\r
+ @param fmt The format string\r
+ @param ... The data will be printed.\r
+\r
+ @return Allocated buffer with the formatted string printed in it.\r
+ The caller must free the allocated buffer.\r
+ The buffer allocation is not packed.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+CatPrint (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN CHAR16 *fmt,\r
+ ...\r
+ )\r
+{\r
+ UINT16 *AppendStr;\r
+ VA_LIST Args;\r
+ UINTN StringSize;\r
+\r
+ AppendStr = AllocateZeroPool (0x1000);\r
+ if (AppendStr == NULL) {\r
+ return Str->str;\r
+ }\r
+\r
+ VA_START (Args, fmt);\r
+ UnicodeVSPrint (AppendStr, 0x1000, fmt, Args);\r
+ VA_END (Args);\r
+ if (NULL == Str->str) {\r
+ StringSize = StrSize (AppendStr);\r
+ Str->str = AllocateZeroPool (StringSize);\r
+ ASSERT (Str->str != NULL);\r
+ } else {\r
+ StringSize = StrSize (AppendStr);\r
+ StringSize += (StrSize (Str->str) - sizeof (UINT16));\r
+\r
+ Str->str = ReallocatePool (\r
+ StrSize (Str->str),\r
+ StringSize,\r
+ Str->str\r
+ );\r
+ ASSERT (Str->str != NULL);\r
+ }\r
+\r
+ Str->maxlen = MAX_CHAR * sizeof (UINT16);\r
+ if (StringSize < Str->maxlen) {\r
+ StrCat (Str->str, AppendStr);\r
+ Str->len = StringSize - sizeof (UINT16);\r
+ }\r
+\r
+ FreePool (AppendStr);\r
+ return Str->str;\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathPci (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ PCI_DEVICE_PATH *Pci;\r
+\r
+ Pci = DevPath;\r
+ CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathPccard (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ PCCARD_DEVICE_PATH *Pccard;\r
+\r
+ Pccard = DevPath;\r
+ CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMemMap (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEMMAP_DEVICE_PATH *MemMap;\r
+\r
+ MemMap = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"MemMap(%d:%lx-%lx)",\r
+ MemMap->MemoryType,\r
+ MemMap->StartingAddress,\r
+ MemMap->EndingAddress\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathController (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CONTROLLER_DEVICE_PATH *Controller;\r
+\r
+ Controller = DevPath;\r
+ CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);\r
+}\r
+\r
+\r
+/**\r
+ Convert Vendor device path to device name.\r
+\r
+ @param Str The buffer store device name\r
+ @param DevPath Pointer to vendor device path\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DevPathVendor (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ VENDOR_DEVICE_PATH *Vendor;\r
+ CHAR16 *Type;\r
+ UINTN DataLength;\r
+ UINTN Index;\r
+ UINT32 FlowControlMap;\r
+\r
+ UINT16 Info;\r
+\r
+ Vendor = DevPath;\r
+\r
+ switch (DevicePathType (&Vendor->Header)) {\r
+ case HARDWARE_DEVICE_PATH:\r
+ Type = L"Hw";\r
+ break;\r
+\r
+ case MESSAGING_DEVICE_PATH:\r
+ Type = L"Msg";\r
+ if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {\r
+ CatPrint (Str, L"VenPcAnsi()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {\r
+ CatPrint (Str, L"VenVt100()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {\r
+ CatPrint (Str, L"VenVt100Plus()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {\r
+ CatPrint (Str, L"VenUft8()");\r
+ return ;\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid )) {\r
+ FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);\r
+ switch (FlowControlMap & 0x00000003) {\r
+ case 0:\r
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"None");\r
+ break;\r
+\r
+ case 1:\r
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");\r
+ break;\r
+\r
+ case 2:\r
+ CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return ;\r
+\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {\r
+ CatPrint (\r
+ Str,\r
+ L"SAS(%lx,%lx,%x,",\r
+ ((SAS_DEVICE_PATH *) Vendor)->SasAddress,\r
+ ((SAS_DEVICE_PATH *) Vendor)->Lun,\r
+ ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort\r
+ );\r
+ Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);\r
+ if ((Info & 0x0f) == 0) {\r
+ CatPrint (Str, L"NoTopology,0,0,0,");\r
+ } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {\r
+ CatPrint (\r
+ Str,\r
+ L"%s,%s,%s,",\r
+ ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",\r
+ ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal",\r
+ ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"\r
+ );\r
+ if ((Info & 0x0f) == 1) {\r
+ CatPrint (Str, L"0,");\r
+ } else {\r
+ CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));\r
+ }\r
+ } else {\r
+ CatPrint (Str, L"0,0,0,0,");\r
+ }\r
+\r
+ CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);\r
+ return ;\r
+\r
+ } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {\r
+ CatPrint (Str, L"DebugPort()");\r
+ return ;\r
+ }\r
+ break;\r
+\r
+ case MEDIA_DEVICE_PATH:\r
+ Type = L"Media";\r
+ break;\r
+\r
+ default:\r
+ Type = L"?";\r
+ break;\r
+ }\r
+\r
+ CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);\r
+ DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);\r
+ if (DataLength > 0) {\r
+ CatPrint (Str, L",");\r
+ for (Index = 0; Index < DataLength; Index++) {\r
+ CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);\r
+ }\r
+ }\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+\r
+ Acpi = DevPath;\r
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);\r
+ } else {\r
+ CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);\r
+ }\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathExtendedAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi;\r
+ \r
+ //\r
+ // Index for HID, UID and CID strings, 0 for non-exist\r
+ //\r
+ UINT16 HIDSTRIdx;\r
+ UINT16 UIDSTRIdx;\r
+ UINT16 CIDSTRIdx;\r
+ UINT16 Index;\r
+ UINT16 Length;\r
+ UINT16 Anchor;\r
+ CHAR8 *AsChar8Array;\r
+\r
+ ASSERT (Str != NULL);\r
+ ASSERT (DevPath != NULL);\r
+\r
+ HIDSTRIdx = 0;\r
+ UIDSTRIdx = 0;\r
+ CIDSTRIdx = 0;\r
+ ExtendedAcpi = DevPath;\r
+ Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);\r
+\r
+ ASSERT (Length >= 19);\r
+ AsChar8Array = (CHAR8 *) ExtendedAcpi;\r
+\r
+ //\r
+ // find HIDSTR\r
+ //\r
+ Anchor = 16;\r
+ for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+ ;\r
+ }\r
+ if (Index > Anchor) {\r
+ HIDSTRIdx = Anchor;\r
+ }\r
+ //\r
+ // find UIDSTR\r
+ //\r
+ Anchor = (UINT16) (Index + 1);\r
+ for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+ ;\r
+ }\r
+ if (Index > Anchor) {\r
+ UIDSTRIdx = Anchor;\r
+ }\r
+ //\r
+ // find CIDSTR\r
+ //\r
+ Anchor = (UINT16) (Index + 1);\r
+ for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+ ;\r
+ }\r
+ if (Index > Anchor) {\r
+ CIDSTRIdx = Anchor;\r
+ }\r
+\r
+ if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {\r
+ CatPrint (Str, L"AcpiExp(");\r
+ if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+ }\r
+ if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);\r
+ }\r
+ if (UIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\")");\r
+ }\r
+ } else {\r
+ CatPrint (Str, L"AcpiEx(");\r
+ if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+ }\r
+ if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+ CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+ } else {\r
+ CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);\r
+ }\r
+ CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);\r
+\r
+ if (HIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\",");\r
+ }\r
+ if (CIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\",");\r
+ }\r
+ if (UIDSTRIdx != 0) {\r
+ CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+ } else {\r
+ CatPrint (Str, L"\"\")");\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAdrAcpi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ACPI_ADR_DEVICE_PATH *AcpiAdr;\r
+ UINT16 Index;\r
+ UINT16 Length;\r
+ UINT16 AdditionalAdrCount;\r
+\r
+ AcpiAdr = DevPath;\r
+ Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);\r
+ AdditionalAdrCount = (UINT16) ((Length - 8) / 4);\r
+\r
+ CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);\r
+ for (Index = 0; Index < AdditionalAdrCount; Index++) {\r
+ CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));\r
+ }\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAtapi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ATAPI_DEVICE_PATH *Atapi;\r
+\r
+ Atapi = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Ata(%s,%s)",\r
+ Atapi->PrimarySecondary ? L"Secondary" : L"Primary",\r
+ Atapi->SlaveMaster ? L"Slave" : L"Master"\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathScsi (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ SCSI_DEVICE_PATH *Scsi;\r
+\r
+ Scsi = DevPath;\r
+ CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFibre (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ FIBRECHANNEL_DEVICE_PATH *Fibre;\r
+\r
+ Fibre = DevPath;\r
+ CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPath1394 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ F1394_DEVICE_PATH *F1394Path;\r
+\r
+ F1394Path = DevPath;\r
+ CatPrint (Str, L"1394(%g)", &F1394Path->Guid);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsb (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_DEVICE_PATH *Usb;\r
+\r
+ Usb = DevPath;\r
+ CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsbWWID (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_WWID_DEVICE_PATH *UsbWWId;\r
+\r
+ UsbWWId = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"UsbWwid(%x,%x,%x,\"WWID\")",\r
+ (UINTN) UsbWWId->VendorId,\r
+ (UINTN) UsbWWId->ProductId,\r
+ (UINTN) UsbWWId->InterfaceNumber\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathLogicalUnit (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;\r
+\r
+ LogicalUnit = DevPath;\r
+ CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsbClass (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ USB_CLASS_DEVICE_PATH *UsbClass;\r
+\r
+ UsbClass = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Usb Class(%x,%x,%x,%x,%x)",\r
+ (UINTN) UsbClass->VendorId,\r
+ (UINTN) UsbClass->ProductId,\r
+ (UINTN) UsbClass->DeviceClass,\r
+ (UINTN) UsbClass->DeviceSubClass,\r
+ (UINTN) UsbClass->DeviceProtocol\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathSata (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ SATA_DEVICE_PATH *Sata;\r
+\r
+ Sata = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Sata(%x,%x,%x)",\r
+ (UINTN) Sata->HBAPortNumber,\r
+ (UINTN) Sata->PortMultiplierPortNumber,\r
+ (UINTN) Sata->Lun\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathI2O (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ I2O_DEVICE_PATH *I2OPath;\r
+\r
+ I2OPath = DevPath;\r
+ CatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMacAddr (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MAC_ADDR_DEVICE_PATH *MACDevPath;\r
+ UINTN HwAddressSize;\r
+ UINTN Index;\r
+\r
+ MACDevPath = DevPath;\r
+\r
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
+ if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) {\r
+ HwAddressSize = 6;\r
+ }\r
+\r
+ CatPrint (Str, L"Mac(");\r
+\r
+ for (Index = 0; Index < HwAddressSize; Index++) {\r
+ CatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]);\r
+ }\r
+\r
+ CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathIPv4 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ IPv4_DEVICE_PATH *IPDevPath;\r
+\r
+ IPDevPath = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"IPv4(%d.%d.%d.%d:%d)",\r
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[0],\r
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[1],\r
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[2],\r
+ (UINTN) IPDevPath->RemoteIpAddress.Addr[3],\r
+ (UINTN) IPDevPath->RemotePort\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathIPv6 (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ IPv6_DEVICE_PATH *IPv6DevPath;\r
+\r
+ IPv6DevPath = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[0],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[1],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[2],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[3],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[4],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[5],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[6],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[7],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[8],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[9],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[10],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[11],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[12],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[13],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[14],\r
+ (UINTN) IPv6DevPath->RemoteIpAddress.Addr[15]\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathInfiniBand (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ INFINIBAND_DEVICE_PATH *InfiniBand;\r
+\r
+ InfiniBand = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"Infiniband(%x,%g,%lx,%lx,%lx)",\r
+ (UINTN) InfiniBand->ResourceFlags,\r
+ InfiniBand->PortGid,\r
+ InfiniBand->ServiceId,\r
+ InfiniBand->TargetPortId,\r
+ InfiniBand->DeviceId\r
+ );\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUart (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ UART_DEVICE_PATH *Uart;\r
+ CHAR8 Parity;\r
+\r
+ Uart = DevPath;\r
+ switch (Uart->Parity) {\r
+ case 0:\r
+ Parity = 'D';\r
+ break;\r
+\r
+ case 1:\r
+ Parity = 'N';\r
+ break;\r
+\r
+ case 2:\r
+ Parity = 'E';\r
+ break;\r
+\r
+ case 3:\r
+ Parity = 'O';\r
+ break;\r
+\r
+ case 4:\r
+ Parity = 'M';\r
+ break;\r
+\r
+ case 5:\r
+ Parity = 'S';\r
+ break;\r
+\r
+ default:\r
+ Parity = 'x';\r
+ break;\r
+ }\r
+\r
+ if (Uart->BaudRate == 0) {\r
+ CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);\r
+ } else {\r
+ CatPrint (Str, L"Uart(%d,%c,", Uart->BaudRate, Parity);\r
+ }\r
+\r
+ if (Uart->DataBits == 0) {\r
+ CatPrint (Str, L"D,");\r
+ } else {\r
+ CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);\r
+ }\r
+\r
+ switch (Uart->StopBits) {\r
+ case 0:\r
+ CatPrint (Str, L"D)");\r
+ break;\r
+\r
+ case 1:\r
+ CatPrint (Str, L"1)");\r
+ break;\r
+\r
+ case 2:\r
+ CatPrint (Str, L"1.5)");\r
+ break;\r
+\r
+ case 3:\r
+ CatPrint (Str, L"2)");\r
+ break;\r
+\r
+ default:\r
+ CatPrint (Str, L"x)");\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathiSCSI (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ ISCSI_DEVICE_PATH_WITH_NAME *IScsi;\r
+ UINT16 Options;\r
+\r
+ ASSERT (Str != NULL);\r
+ ASSERT (DevPath != NULL);\r
+\r
+ IScsi = DevPath;\r
+ CatPrint (\r
+ Str,\r
+ L"iSCSI(%s,%x,%lx,",\r
+ IScsi->iSCSITargetName,\r
+ IScsi->TargetPortalGroupTag,\r
+ IScsi->Lun\r
+ );\r
+\r
+ Options = IScsi->LoginOption;\r
+ CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None");\r
+ CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None");\r
+ if (((Options >> 11) & 0x0001) != 0) {\r
+ CatPrint (Str, L"%s,", L"None");\r
+ } else if (((Options >> 12) & 0x0001) != 0) {\r
+ CatPrint (Str, L"%s,", L"CHAP_UNI");\r
+ } else {\r
+ CatPrint (Str, L"%s,", L"CHAP_BI");\r
+\r
+ }\r
+\r
+ CatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved");\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathHardDrive (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ HARDDRIVE_DEVICE_PATH *Hd;\r
+\r
+ Hd = DevPath;\r
+ switch (Hd->SignatureType) {\r
+ case SIGNATURE_TYPE_MBR:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,Sig%08x)",\r
+ (UINTN) Hd->PartitionNumber,\r
+ (UINTN) *((UINT32 *) (&(Hd->Signature[0])))\r
+ );\r
+ break;\r
+\r
+ case SIGNATURE_TYPE_GUID:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,Sig%g)",\r
+ (UINTN) Hd->PartitionNumber,\r
+ (EFI_GUID *) &(Hd->Signature[0])\r
+ );\r
+ break;\r
+\r
+ default:\r
+ CatPrint (\r
+ Str,\r
+ L"HD(Part%d,MBRType=%02x,SigType=%02x)",\r
+ (UINTN) Hd->PartitionNumber,\r
+ (UINTN) Hd->MBRType,\r
+ (UINTN) Hd->SignatureType\r
+ );\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathCDROM (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CDROM_DEVICE_PATH *Cd;\r
+\r
+ Cd = DevPath;\r
+ CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFilePath (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ FILEPATH_DEVICE_PATH *Fp;\r
+\r
+ Fp = DevPath;\r
+ CatPrint (Str, L"%s", Fp->PathName);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMediaProtocol (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;\r
+\r
+ MediaProt = DevPath;\r
+ CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFvFilePath (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
+\r
+ FvFilePath = DevPath;\r
+ CatPrint (Str, L"%g", &FvFilePath->FvFileName);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathBssBss (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ BBS_BBS_DEVICE_PATH *Bbs;\r
+ CHAR16 *Type;\r
+\r
+ Bbs = DevPath;\r
+ switch (Bbs->DeviceType) {\r
+ case BBS_TYPE_FLOPPY:\r
+ Type = L"Floppy";\r
+ break;\r
+\r
+ case BBS_TYPE_HARDDRIVE:\r
+ Type = L"Harddrive";\r
+ break;\r
+\r
+ case BBS_TYPE_CDROM:\r
+ Type = L"CDROM";\r
+ break;\r
+\r
+ case BBS_TYPE_PCMCIA:\r
+ Type = L"PCMCIA";\r
+ break;\r
+\r
+ case BBS_TYPE_USB:\r
+ Type = L"Usb";\r
+ break;\r
+\r
+ case BBS_TYPE_EMBEDDED_NETWORK:\r
+ Type = L"Net";\r
+ break;\r
+\r
+ case BBS_TYPE_BEV:\r
+ Type = L"BEV";\r
+ break;\r
+\r
+ default:\r
+ Type = L"?";\r
+ break;\r
+ }\r
+ CatPrint (Str, L"Legacy-%s", Type);\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathEndInstance (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CatPrint (Str, L",");\r
+}\r
+\r
+/**\r
+ Convert Device Path to a Unicode string for printing.\r
+\r
+ @param Str The buffer holding the output string.\r
+ This buffer contains the length of the\r
+ string and the maixmum length reserved\r
+ for the string buffer.\r
+ @param DevPath The device path.\r
+\r
+**/\r
+VOID\r
+DevPathNodeUnknown (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+{\r
+ CatPrint (Str, L"?");\r
+}\r
+\r
+DEVICE_PATH_STRING_TABLE DevPathTable[] = {\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_PCI_DP,\r
+ DevPathPci\r
+ },\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_PCCARD_DP,\r
+ DevPathPccard\r
+ },\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_MEMMAP_DP,\r
+ DevPathMemMap\r
+ },\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_VENDOR_DP,\r
+ DevPathVendor\r
+ },\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_CONTROLLER_DP,\r
+ DevPathController\r
+ },\r
+ {\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_DP,\r
+ DevPathAcpi\r
+ },\r
+ {\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_EXTENDED_DP,\r
+ DevPathExtendedAcpi\r
+ },\r
+ {\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_ADR_DP,\r
+ DevPathAdrAcpi\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_ATAPI_DP,\r
+ DevPathAtapi\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_SCSI_DP,\r
+ DevPathScsi\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_FIBRECHANNEL_DP,\r
+ DevPathFibre\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_1394_DP,\r
+ DevPath1394\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_DP,\r
+ DevPathUsb\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_WWID_DP,\r
+ DevPathUsbWWID\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_DEVICE_LOGICAL_UNIT_DP,\r
+ DevPathLogicalUnit\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_CLASS_DP,\r
+ DevPathUsbClass\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_SATA_DP,\r
+ DevPathSata\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_I2O_DP,\r
+ DevPathI2O\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_MAC_ADDR_DP,\r
+ DevPathMacAddr\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_IPv4_DP,\r
+ DevPathIPv4\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_IPv6_DP,\r
+ DevPathIPv6\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_INFINIBAND_DP,\r
+ DevPathInfiniBand\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_UART_DP,\r
+ DevPathUart\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_VENDOR_DP,\r
+ DevPathVendor\r
+ },\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_ISCSI_DP,\r
+ DevPathiSCSI\r
+ },\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_HARDDRIVE_DP,\r
+ DevPathHardDrive\r
+ },\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_CDROM_DP,\r
+ DevPathCDROM\r
+ },\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_VENDOR_DP,\r
+ DevPathVendor\r
+ },\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_FILEPATH_DP,\r
+ DevPathFilePath\r
+ },\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_PROTOCOL_DP,\r
+ DevPathMediaProtocol\r
+ },\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_PIWG_FW_FILE_DP,\r
+ DevPathFvFilePath\r
+ },\r
+ {\r
+ BBS_DEVICE_PATH,\r
+ BBS_BBS_DP,\r
+ DevPathBssBss\r
+ },\r
+ {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_INSTANCE_DEVICE_PATH_SUBTYPE,\r
+ DevPathEndInstance\r
+ },\r
+ {\r
+ 0,\r
+ 0,\r
+ NULL\r
+ }\r
+};\r
+\r
+\r
+/**\r
+ This function converts an input device structure to a Unicode string.\r
+\r
+ @param DevPath A pointer to the device path structure.\r
+\r
+ @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+DevicePathToStr (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ POOL_PRINT Str;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
+ VOID (*DumpNode) (POOL_PRINT *, VOID *);\r
+\r
+ UINTN Index;\r
+ UINTN NewSize;\r
+\r
+ EFI_STATUS Status;\r
+ CHAR16 *ToText;\r
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
+\r
+ ZeroMem (&Str, sizeof (Str));\r
+\r
+ if (DevPath == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathToTextProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DevPathToText\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ ToText = DevPathToText->ConvertDevicePathToText (\r
+ DevPath,\r
+ FALSE,\r
+ TRUE\r
+ );\r
+ ASSERT (ToText != NULL);\r
+ return ToText;\r
+ }\r
+\r
+ //\r
+ // Process each device path node\r
+ //\r
+ DevPathNode = DevPath;\r
+ while (!IsDevicePathEnd (DevPathNode)) {\r
+ //\r
+ // Find the handler to dump this device path node\r
+ //\r
+ DumpNode = NULL;\r
+ for (Index = 0; DevPathTable[Index].Function; Index += 1) {\r
+\r
+ if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&\r
+ DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType\r
+ ) {\r
+ DumpNode = DevPathTable[Index].Function;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // If not found, use a generic function\r
+ //\r
+ if (!DumpNode) {\r
+ DumpNode = DevPathNodeUnknown;\r
+ }\r
+ //\r
+ // Put a path seperator in if needed\r
+ //\r
+ if (Str.len && DumpNode != DevPathEndInstance) {\r
+ CatPrint (&Str, L"/");\r
+ }\r
+ //\r
+ // Print this node of the device path\r
+ //\r
+ DumpNode (&Str, DevPathNode);\r
+\r
+ //\r
+ // Next device path node\r
+ //\r
+ DevPathNode = NextDevicePathNode (DevPathNode);\r
+ }\r
+\r
+Done:\r
+ NewSize = (Str.len + 1) * sizeof (CHAR16);\r
+ Str.str = ReallocatePool (NewSize, NewSize, Str.str);\r
+ ASSERT (Str.str != NULL);\r
+ Str.str[Str.len] = 0;\r
+ return Str.str;\r
+}\r
--- /dev/null
+#/** @file\r
+# \r
+# General BDS defines and produce general interfaces for platform BDS driver including:\r
+# 1) BDS boot policy interface;\r
+# 2) BDS boot device connect interface;\r
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.\r
+# \r
+# Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# \r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = GenericBdsLib\r
+ FILE_GUID = e405ec31-ccaa-4dd4-83e8-0aec01703f7e\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = GenericBdsLib|DXE_DRIVER UEFI_APPLICATION \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ DevicePath.c\r
+ Performance.c\r
+ BdsConnect.c\r
+ BdsMisc.c\r
+ BdsConsole.c\r
+ BdsBoot.c\r
+ InternalBdsLib.h\r
+\r
+[Sources.IPF]\r
+ Ipf/ShadowRom.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ #\r
+ #This dependency is because of gEfiLegacyBiosProtocolGuid. It may be removed if a Library class is created to\r
+ #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols.\r
+ #\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ DevicePathLib\r
+ PeCoffGetEntryPointLib\r
+ BaseLib\r
+ HobLib\r
+ UefiRuntimeServicesTableLib\r
+ DxeServicesTableLib\r
+ MemoryAllocationLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ PcdLib\r
+ PerformanceLib\r
+ TimerLib\r
+ PcdLib\r
+ DxeServicesLib\r
+\r
+[Guids]\r
+ gEfiVT100PlusGuid # ALWAYS_CONSUMED\r
+ gEfiMemoryTypeInformationGuid # ALWAYS_CONSUMED\r
+ gEfiVTUTF8Guid # ALWAYS_CONSUMED\r
+ gEfiShellFileGuid # ALWAYS_CONSUMED\r
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED\r
+ gEfiVT100Guid # ALWAYS_CONSUMED\r
+ gEfiFileInfoGuid # ALWAYS_CONSUMED\r
+ gEfiPcAnsiGuid # ALWAYS_CONSUMED\r
+ gEfiGenericPlatformVariableGuid # ALWAYS_CONSUMED\r
+ gEfiUartDevicePathGuid # ALWAYS_CONSUMED\r
+ gEfiSasDevicePathGuid # ALWAYS_CONSUMED\r
+ \r
+[Protocols]\r
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathToTextProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDebugPortProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFirmwareVolumeDispatchProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiAcpiS3SaveProtocolGuid\r
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiOEMBadgingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiFontProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[FeaturePcd.common]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport\r
+\r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDefaultBootFileName
\ No newline at end of file
--- /dev/null
+/** @file\r
+ BDS library definition, include the file and data structure\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _INTERNAL_BDS_LIB_H_\r
+#define _INTERNAL_BDS_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/DebugPort.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/DevicePathToText.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/AcpiS3Save.h>\r
+#include <Protocol/Performance.h>\r
+#include <Protocol/FirmwareVolumeDispatch.h>\r
+#include <Protocol/OEMBadging.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/HiiFont.h>\r
+#include <Protocol/HiiImage.h>\r
+\r
+\r
+#include <Guid/MemoryTypeInformation.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/PcAnsi.h>\r
+#include <Guid/ShellFile.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+#include <Guid/Bmp.h>\r
+\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+\r
+#define PERFORMANCE_SIGNATURE SIGNATURE_32 ('P', 'e', 'r', 'f')\r
+#define PERF_TOKEN_SIZE 28\r
+#define PERF_TOKEN_LENGTH (PERF_TOKEN_SIZE - 1)\r
+#define PERF_PEI_ENTRY_MAX_NUM 50\r
+\r
+typedef struct {\r
+ CHAR8 Token[PERF_TOKEN_SIZE];\r
+ UINT32 Duration;\r
+} PERF_DATA;\r
+\r
+typedef struct {\r
+ UINT64 BootToOs;\r
+ UINT64 S3Resume;\r
+ UINT32 S3EntryNum;\r
+ PERF_DATA S3Entry[PERF_PEI_ENTRY_MAX_NUM];\r
+ UINT64 CpuFreq;\r
+ UINT64 BDSRaw;\r
+ UINT32 Count;\r
+ UINT32 Signiture;\r
+} PERF_HEADER;\r
+\r
+/**\r
+\r
+ Allocates a block of memory and writes performance data of booting into it.\r
+ OS can processing these record.\r
+ \r
+**/\r
+VOID\r
+WriteBootToOsPerformanceData (\r
+ VOID\r
+ );\r
+\r
+#endif // _BDS_LIB_H_\r
--- /dev/null
+/** @file\r
+ Shadow all option rom\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+UINT8 mShadowRomFlag = 0;\r
+\r
+/**\r
+ Shadow all opton ROM if the it is not done.\r
+**/\r
+VOID\r
+ShadowAllOptionRom(\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ //\r
+ // Rom shadow only do once.\r
+ //\r
+ if (mShadowRomFlag == 0) {\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ LegacyBios->PrepareToBootEfi (LegacyBios, NULL, NULL);\r
+ }\r
+\r
+ mShadowRomFlag = 1;\r
+ }\r
+\r
+ return ;\r
+}\r
--- /dev/null
+/** @file\r
+ This file include the file which can help to get the system\r
+ performance, all the function will only include if the performance\r
+ switch is set.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+PERF_HEADER mPerfHeader;\r
+PERF_DATA mPerfData;\r
+\r
+/**\r
+ Get the short verion of PDB file name to be\r
+ used in performance data logging.\r
+\r
+ @param PdbFileName The long PDB file name.\r
+ @param GaugeString The output string to be logged by performance logger.\r
+\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+ IN CONST CHAR8 *PdbFileName,\r
+ OUT CHAR8 *GaugeString\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINTN StartIndex;\r
+ UINTN EndIndex;\r
+\r
+ if (PdbFileName == NULL) {\r
+ AsciiStrCpy (GaugeString, " ");\r
+ } else {\r
+ StartIndex = 0;\r
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
+ ;\r
+\r
+ for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
+ if (PdbFileName[Index] == '\\') {\r
+ StartIndex = Index + 1;\r
+ }\r
+\r
+ if (PdbFileName[Index] == '.') {\r
+ EndIndex = Index;\r
+ }\r
+ }\r
+\r
+ Index1 = 0;\r
+ for (Index = StartIndex; Index < EndIndex; Index++) {\r
+ GaugeString[Index1] = PdbFileName[Index];\r
+ Index1++;\r
+ if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ GaugeString[Index1] = 0;\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Get the name from the Driver handle, which can be a handle with\r
+ EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.\r
+ This name can be used in performance data logging.\r
+\r
+ @param Handle Driver handle.\r
+ @param GaugeString The output string to be logged by performance logger.\r
+\r
+**/\r
+VOID\r
+GetNameFromHandle (\r
+ IN EFI_HANDLE Handle,\r
+ OUT CHAR8 *GaugeString\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOADED_IMAGE_PROTOCOL *Image;\r
+ CHAR8 *PdbFileName;\r
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
+\r
+ AsciiStrCpy (GaugeString, " ");\r
+\r
+ //\r
+ // Get handle name from image protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &Image\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ (VOID **) &DriverBinding,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+ //\r
+ // Get handle name from image protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverBinding->ImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &Image\r
+ );\r
+ }\r
+\r
+ PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
+\r
+ if (PdbFileName != NULL) {\r
+ GetShortPdbFileName (PdbFileName, GaugeString);\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+\r
+ Allocates a block of memory and writes performance data of booting into it.\r
+ OS can processing these record.\r
+ \r
+**/\r
+VOID\r
+WriteBootToOsPerformanceData (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase;\r
+ UINT32 AcpiLowMemoryLength;\r
+ UINT32 LimitCount;\r
+ EFI_HANDLE *Handles;\r
+ UINTN NoHandles;\r
+ CHAR8 GaugeString[PERF_TOKEN_LENGTH];\r
+ UINT8 *Ptr;\r
+ UINT32 Index;\r
+ UINT64 Ticker;\r
+ UINT64 Freq;\r
+ UINT32 Duration;\r
+ UINTN LogEntryKey;\r
+ CONST VOID *Handle;\r
+ CONST CHAR8 *Token;\r
+ CONST CHAR8 *Module;\r
+ UINT64 StartTicker;\r
+ UINT64 EndTicker;\r
+ UINT64 StartValue;\r
+ UINT64 EndValue;\r
+ BOOLEAN CountUp;\r
+\r
+ //\r
+ // Retrive time stamp count as early as possilbe\r
+ //\r
+ Ticker = GetPerformanceCounter ();\r
+\r
+ Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
+ \r
+ Freq = DivU64x32 (Freq, 1000);\r
+\r
+ mPerfHeader.CpuFreq = Freq;\r
+\r
+ //\r
+ // Record BDS raw performance data\r
+ //\r
+ if (EndValue >= StartValue) {\r
+ mPerfHeader.BDSRaw = Ticker - StartValue;\r
+ CountUp = TRUE;\r
+ } else {\r
+ mPerfHeader.BDSRaw = StartValue - Ticker;\r
+ CountUp = FALSE;\r
+ }\r
+\r
+ AcpiLowMemoryLength = 0x2000;\r
+\r
+ //\r
+ // Allocate a block of memory that contain performance data to OS\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages,\r
+ EfiACPIReclaimMemory,\r
+ EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),\r
+ &AcpiLowMemoryBase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
+\r
+ Ptr = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));\r
+ LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
+\r
+ //\r
+ // Put Detailed performance data into memory\r
+ //\r
+ Handles = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &NoHandles,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (AcpiLowMemoryBase, 1);\r
+ return ;\r
+ }\r
+ \r
+ //\r
+ // Get DXE drivers performance\r
+ //\r
+ for (Index = 0; Index < NoHandles; Index++) {\r
+ Ticker = 0;\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Handle,\r
+ &Token,\r
+ &Module,\r
+ &StartTicker,\r
+ &EndTicker)) != 0) {\r
+ if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
+ Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+ }\r
+ }\r
+\r
+ Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+ if (Duration > 0) {\r
+\r
+ GetNameFromHandle (Handles[Index], GaugeString);\r
+\r
+ AsciiStrCpy (mPerfData.Token, GaugeString);\r
+ mPerfData.Duration = Duration;\r
+\r
+ CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
+ Ptr += sizeof (PERF_DATA);\r
+\r
+ mPerfHeader.Count++;\r
+ if (mPerfHeader.Count == LimitCount) {\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (Handles);\r
+\r
+ //\r
+ // Get inserted performance data\r
+ //\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Handle,\r
+ &Token,\r
+ &Module,\r
+ &StartTicker,\r
+ &EndTicker)) != 0) {\r
+ if (Handle == NULL && EndTicker != 0) {\r
+\r
+ ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
+\r
+ AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
+ Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+\r
+ mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+ CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
+ Ptr += sizeof (PERF_DATA);\r
+\r
+ mPerfHeader.Count++;\r
+ if (mPerfHeader.Count == LimitCount) {\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+\r
+ mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
+\r
+ //\r
+ // Put performance data to ACPI memory\r
+ //\r
+ CopyMem (\r
+ (UINTN *) (UINTN) AcpiLowMemoryBase,\r
+ &mPerfHeader,\r
+ sizeof (PERF_HEADER)\r
+ );\r
+\r
+ gRT->SetVariable (\r
+ L"PerfDataMemAddr",\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (EFI_PHYSICAL_ADDRESS),\r
+ &AcpiLowMemoryBase\r
+ );\r
+\r
+ return ;\r
+}\r
--- /dev/null
+/** @file\r
+ Head file for BDS Architectural Protocol implementation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BDS_MODULE_H_\r
+#define _BDS_MODULE_H_\r
+\r
+#include <PiDxe.h>\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Guid/BootState.h>\r
+#include <Guid/DataHubRecords.h>\r
+#include <Protocol/LoadFile.h>\r
+#include <Protocol/CpuIo.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/DataHub.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+#include <Guid/CapsuleVendor.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+#include <Protocol/SerialIo.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
+#include <Protocol/Performance.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/ExtendedIfrSupportLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CapsuleLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/ExtendedHiiLib.h>\r
+\r
+\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \\r
+ CR ((_this), \\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE, \\r
+ Bds, \\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \\r
+ )\r
+\r
+/**\r
+\r
+ Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+ @param TitleForeground Foreground color for Title.\r
+ @param TitleBackground Background color for Title.\r
+ @param Title Title above progress bar.\r
+ @param ProgressColor Progress bar color.\r
+ @param Progress Progress (0-100)\r
+ @param PreviousValue The previous value of the progress.\r
+\r
+ @retval EFI_STATUS Success update the progress bar\r
+\r
+**/\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ IN CHAR16 *Title,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ IN UINTN Progress,\r
+ IN UINTN PreviousValue\r
+ );\r
+\r
+//\r
+// Prototypes\r
+//\r
+\r
+/**\r
+\r
+ Install Boot Device Selection Protocol\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCEESS BDS has finished initializing.\r
+ Return the dispatcher and recall BDS.Entry\r
+ @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+/**\r
+\r
+ Service routine for BdsInstance->Entry(). Devices are connected, the\r
+ consoles are initialized, and the boot options are tried.\r
+\r
+ @param This Protocol Instance structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+ IN EFI_BDS_ARCH_PROTOCOL *This\r
+ );\r
+\r
+#endif\r
--- /dev/null
+#/** @file\r
+#\r
+# BDSDxe module is core driver for BDS phase. \r
+# When DxeCore dispatching all DXE driver, this module will produce architecture protocol \r
+# gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry\r
+# interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered.\r
+#\r
+# Generally, this module take reposiblity to connect all necessary devices for platform boot, \r
+# these boot device path are hold in PlatformBdsLib library instance produced by platform.\r
+# For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select.\r
+# For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, \r
+# EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader.\r
+#\r
+# BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which\r
+# is used for user to configure boot option or maintain hardware device.\r
+# \r
+# Copyright (c) 2008, Intel Corporation. <BR>\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# \r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = BdsDxe\r
+ FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0 \r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+ ENTRY_POINT = BdsInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ FrontPage.h\r
+ Language.h\r
+ Bds.h\r
+ Hotkey.h\r
+ BootMaint/BBSsupport.h\r
+ BootMngr/BootManager.h\r
+ BootMaint/BootMaint.h\r
+ String.h\r
+ BootMaint/FormGuid.h\r
+ HwErrRecSupport.c\r
+ HwErrRecSupport.h\r
+\r
+ DeviceMngr/DeviceManager.h\r
+ DeviceMngr/DeviceManagerVfr.Vfr\r
+ DeviceMngr/DeviceManagerStrings.uni\r
+ DeviceMngr/DeviceManager.c\r
+ BootMngr/BootManagerVfr.Vfr\r
+ BootMngr/BootManagerStrings.uni\r
+ BootMngr/BootManager.c\r
+ BootMaint/FE.vfr\r
+ BootMaint/FileExplorer.c\r
+ BootMaint/BootMaint.c\r
+ BootMaint/BBSsupport.c\r
+ BootMaint/UpdatePage.c\r
+ BootMaint/Variable.c\r
+ BootMaint/Data.c\r
+ BootMaint/ConsoleOption.c\r
+ BootMaint/BootOption.c\r
+ BootMaint/BmLib.c\r
+ BootMaint/Bm.vfr\r
+ BootMaint/Bmstring.uni\r
+ Hotkey.c\r
+ MemoryTest.c\r
+ Capsules.c\r
+ Strings.uni\r
+ String.c\r
+ Language.c\r
+ FrontPageVfr.Vfr\r
+ FrontPageStrings.uni\r
+ FrontPage.c\r
+ BdsEntry.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ #\r
+ #This dependency is because of gEfiLegacyBiosProtocolGuid and gEfiDataHubProtocolGuid. It may be removed if a Library class is created to\r
+ #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols and Data Hub Protocols.\r
+ #\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ DevicePathLib\r
+ BaseLib\r
+ HobLib\r
+ UefiRuntimeServicesTableLib\r
+ IfrSupportLib\r
+ ExtendedIfrSupportLib\r
+ GenericBdsLib\r
+ ReportStatusCodeLib\r
+ PerformanceLib\r
+ MemoryAllocationLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ HiiLib\r
+ ExtendedHiiLib\r
+ UefiDriverEntryPoint\r
+ PlatformBdsLib\r
+ CapsuleLib\r
+\r
+[Guids]\r
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED\r
+ gEfiBootStateGuid # ALWAYS_CONSUMED\r
+ gEfiFileSystemVolumeLabelInfoIdGuid # ALWAYS_CONSUMED\r
+ gEfiFileInfoGuid # ALWAYS_CONSUMED\r
+ gEfiGenericPlatformVariableGuid\r
+ gEfiMiscSubClassGuid\r
+ gEfiMemorySubClassGuid\r
+ gEfiProcessorSubClassGuid\r
+ gEfiCapsuleVendorGuid\r
+\r
+[Protocols]\r
+ gEfiHiiStringProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLoadFileProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBdsArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED\r
+ gEfiDataHubProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiGenericMemTestProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFormBrowser2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSerialIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[FeaturePcd.common]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord\r
+ gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport\r
+\r
+[Pcd.common]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel\r
+\r
+[Depex]\r
+ gEfiHiiDatabaseProtocolGuid\r
+\r
--- /dev/null
+/** @file\r
+ This module produce main entry for BDS phase - BdsEntry. \r
+ When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed\r
+ which contains interface of BdsEntry.\r
+ After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked\r
+ to enter BDS phase.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+#include "Hotkey.h"\r
+#include "HwErrRecSupport.h"\r
+\r
+///\r
+/// BDS arch protocol instance initial value.\r
+///\r
+/// Note: Current BDS not directly get the BootMode, DefaultBoot,\r
+/// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol.\r
+/// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout \r
+/// and PlatformBdsDiagnostics in BdsPlatform.c\r
+///\r
+EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,\r
+ NULL,\r
+ {BdsEntry},\r
+ 0xFFFF,\r
+ TRUE,\r
+ 0,\r
+ EXTENSIVE\r
+};\r
+\r
+UINT16 *mBootNext = NULL;\r
+\r
+EFI_HANDLE mBdsImageHandle;\r
+\r
+/**\r
+\r
+ Install Boot Device Selection Protocol\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCEESS BDS has finished initializing.\r
+ Return the dispatcher and recall BDS.Entry\r
+ @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ mBdsImageHandle = ImageHandle;\r
+\r
+ //\r
+ // Install protocol interface\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gBdsInstanceTemplate.Handle,\r
+ &gEfiBdsArchProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gBdsInstanceTemplate.Bds\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This function attempts to boot for the boot order specified\r
+ by platform policy.\r
+\r
+**/\r
+VOID\r
+BdsBootDeviceSelect (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BDS_COMMON_OPTION *BootOption;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ UINT16 Timeout;\r
+ LIST_ENTRY BootLists;\r
+ CHAR16 Buffer[20];\r
+ BOOLEAN BootNextExist;\r
+ LIST_ENTRY *LinkBootNext;\r
+\r
+ //\r
+ // Got the latest boot option\r
+ //\r
+ BootNextExist = FALSE;\r
+ LinkBootNext = NULL;\r
+ InitializeListHead (&BootLists);\r
+\r
+ //\r
+ // First check the boot next option\r
+ //\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+ if (mBootNext != NULL) {\r
+ //\r
+ // Indicate we have the boot next variable, so this time\r
+ // boot will always have this boot option\r
+ //\r
+ BootNextExist = TRUE;\r
+\r
+ //\r
+ // Clear the this variable so it's only exist in this time boot\r
+ //\r
+ gRT->SetVariable (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ mBootNext\r
+ );\r
+\r
+ //\r
+ // Add the boot next boot option\r
+ //\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);\r
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+ \r
+ //\r
+ // If fail to get boot option from variable, just return and do nothing.\r
+ //\r
+ if (BootOption == NULL) {\r
+ return;\r
+ }\r
+ \r
+ BootOption->BootCurrent = *mBootNext;\r
+ }\r
+ //\r
+ // Parse the boot order to get boot option\r
+ //\r
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+ Link = BootLists.ForwardLink;\r
+\r
+ //\r
+ // Parameter check, make sure the loop will be valid\r
+ //\r
+ if (Link == NULL) {\r
+ return ;\r
+ }\r
+ //\r
+ // Here we make the boot in a loop, every boot success will\r
+ // return to the front page\r
+ //\r
+ for (;;) {\r
+ //\r
+ // Check the boot option list first\r
+ //\r
+ if (Link == &BootLists) {\r
+ //\r
+ // There are two ways to enter here:\r
+ // 1. There is no active boot option, give user chance to\r
+ // add new boot option\r
+ // 2. All the active boot option processed, and there is no\r
+ // one is success to boot, then we back here to allow user\r
+ // add new active boot option\r
+ //\r
+ Timeout = 0xffff;\r
+ PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+ InitializeListHead (&BootLists);\r
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+ Link = BootLists.ForwardLink;\r
+ continue;\r
+ }\r
+ //\r
+ // Get the boot option from the link list\r
+ //\r
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ //\r
+ // According to EFI Specification, if a load option is not marked\r
+ // as LOAD_OPTION_ACTIVE, the boot manager will not automatically\r
+ // load the option.\r
+ //\r
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
+ //\r
+ // skip the header of the link list, becuase it has no boot option\r
+ //\r
+ Link = Link->ForwardLink;\r
+ continue;\r
+ }\r
+ //\r
+ // Make sure the boot option device path connected,\r
+ // but ignore the BBS device path\r
+ //\r
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
+ //\r
+ // Notes: the internal shell can not been connected with device path\r
+ // so we do not check the status here\r
+ //\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+ }\r
+ //\r
+ // All the driver options should have been processed since\r
+ // now boot will be performed.\r
+ //\r
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Call platform action to indicate the boot fail\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+\r
+ //\r
+ // Check the next boot option\r
+ //\r
+ Link = Link->ForwardLink;\r
+\r
+ } else {\r
+ //\r
+ // Call platform action to indicate the boot success\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); \r
+ PlatformBdsBootSuccess (BootOption);\r
+\r
+ //\r
+ // Boot success, then stop process the boot order, and\r
+ // present the boot manager menu, front page\r
+ //\r
+ Timeout = 0xffff;\r
+ PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+\r
+ //\r
+ // Rescan the boot option list, avoid pertential risk of the boot\r
+ // option change in front page\r
+ //\r
+ if (BootNextExist) {\r
+ LinkBootNext = BootLists.ForwardLink;\r
+ }\r
+\r
+ InitializeListHead (&BootLists);\r
+ if (LinkBootNext != NULL) {\r
+ //\r
+ // Reserve the boot next option\r
+ //\r
+ InsertTailList (&BootLists, LinkBootNext);\r
+ }\r
+\r
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+ Link = BootLists.ForwardLink;\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+\r
+ Service routine for BdsInstance->Entry(). Devices are connected, the\r
+ consoles are initialized, and the boot options are tried.\r
+\r
+ @param This Protocol Instance structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+ IN EFI_BDS_ARCH_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;\r
+ LIST_ENTRY DriverOptionList;\r
+ LIST_ENTRY BootOptionList;\r
+ UINTN BootNextSize;\r
+\r
+ //\r
+ // Insert the performance probe\r
+ //\r
+ PERF_END (0, DXE_TOK, NULL, 0);\r
+ PERF_START (0, BDS_TOK, NULL, 0);\r
+\r
+ //\r
+ // Initialize the global system boot option and driver option\r
+ //\r
+ InitializeListHead (&DriverOptionList);\r
+ InitializeListHead (&BootOptionList);\r
+\r
+ //\r
+ // Initialize hotkey service\r
+ //\r
+ InitializeHotkeyService ();\r
+\r
+ //\r
+ // Get the BDS private data\r
+ //\r
+ PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);\r
+\r
+ //\r
+ // Do the platform init, can be customized by OEM/IBV\r
+ //\r
+ PERF_START (0, "PlatformBds", "BDS", 0);\r
+ PlatformBdsInit (PrivateData);\r
+\r
+ if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {\r
+ InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));\r
+ }\r
+ //\r
+ // bugbug: platform specific code\r
+ // Initialize the platform specific string and language\r
+ //\r
+ InitializeStringSupport ();\r
+ InitializeLanguage (TRUE);\r
+ InitializeFrontPage (TRUE);\r
+\r
+ //\r
+ // Set up the device list based on EFI 1.1 variables\r
+ // process Driver#### and Load the driver's in the\r
+ // driver option list\r
+ //\r
+ BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");\r
+ if (!IsListEmpty (&DriverOptionList)) {\r
+ BdsLibLoadDrivers (&DriverOptionList);\r
+ }\r
+ //\r
+ // Check if we have the boot next option\r
+ //\r
+ mBootNext = BdsLibGetVariableAndSize (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootNextSize\r
+ );\r
+\r
+ //\r
+ // Setup some platform policy here\r
+ //\r
+ PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);\r
+ PERF_END (0, "PlatformBds", "BDS", 0);\r
+\r
+ //\r
+ // BDS select the boot device to load OS\r
+ //\r
+ BdsBootDeviceSelect ();\r
+\r
+ //\r
+ // Only assert here since this is the right behavior, we should never\r
+ // return back to DxeCore.\r
+ //\r
+ ASSERT (FALSE);\r
+\r
+ return ;\r
+}\r
--- /dev/null
+/** @file\r
+ This function deal with the legacy boot option, it create, delete\r
+ and manage the legacy boot option, all legacy boot option is getting from\r
+ the legacy BBS table.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BBSsupport.h"\r
+\r
+/**\r
+\r
+ Translate the first n characters of an Ascii string to\r
+ Unicode characters. The count n is indicated by parameter\r
+ Size. If Size is greater than the length of string, then\r
+ the entire string is translated.\r
+\r
+\r
+ @param AStr Pointer to input Ascii string.\r
+ @param Size The number of characters to translate.\r
+ @param UStr Pointer to output Unicode string buffer.\r
+\r
+**/\r
+VOID\r
+AsciiToUnicodeSize (\r
+ IN UINT8 *AStr,\r
+ IN UINTN Size,\r
+ OUT UINT16 *UStr\r
+ )\r
+{\r
+ UINTN Idx;\r
+\r
+ Idx = 0;\r
+ while (AStr[Idx] != 0) {\r
+ UStr[Idx] = (CHAR16) AStr[Idx];\r
+ if (Idx == Size) {\r
+ break;\r
+ }\r
+\r
+ Idx++;\r
+ }\r
+ UStr[Idx] = 0;\r
+}\r
+\r
+/**\r
+ Build Legacy Device Name String according.\r
+\r
+ @param CurBBSEntry BBS Table.\r
+ @param Index Index.\r
+ @param BufSize The buffer size.\r
+ @param BootString The output string.\r
+\r
+**/\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+ IN BBS_TABLE *CurBBSEntry,\r
+ IN UINTN Index,\r
+ IN UINTN BufSize,\r
+ OUT CHAR16 *BootString\r
+ )\r
+{\r
+ CHAR16 *Fmt;\r
+ CHAR16 *Type;\r
+ UINT8 *StringDesc;\r
+ CHAR16 Temp[80];\r
+\r
+ switch (Index) {\r
+ //\r
+ // Primary Master\r
+ //\r
+ case 1:\r
+ Fmt = L"Primary Master %s";\r
+ break;\r
+\r
+ //\r
+ // Primary Slave\r
+ //\r
+ case 2:\r
+ Fmt = L"Primary Slave %s";\r
+ break;\r
+\r
+ //\r
+ // Secondary Master\r
+ //\r
+ case 3:\r
+ Fmt = L"Secondary Master %s";\r
+ break;\r
+\r
+ //\r
+ // Secondary Slave\r
+ //\r
+ case 4:\r
+ Fmt = L"Secondary Slave %s";\r
+ break;\r
+\r
+ default:\r
+ Fmt = L"%s";\r
+ break;\r
+ }\r
+\r
+ switch (CurBBSEntry->DeviceType) {\r
+ case BBS_FLOPPY:\r
+ Type = L"Floppy";\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ Type = L"Harddisk";\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ Type = L"CDROM";\r
+ break;\r
+\r
+ case BBS_PCMCIA:\r
+ Type = L"PCMCIAe";\r
+ break;\r
+\r
+ case BBS_USB:\r
+ Type = L"USB";\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ Type = L"Network";\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ Type = L"BEVe";\r
+ break;\r
+\r
+ case BBS_UNKNOWN:\r
+ default:\r
+ Type = L"Unknown";\r
+ break;\r
+ }\r
+ //\r
+ // If current BBS entry has its description then use it.\r
+ //\r
+ StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
+ if (NULL != StringDesc) {\r
+ //\r
+ // Only get fisrt 32 characters, this is suggested by BBS spec\r
+ //\r
+ AsciiToUnicodeSize (StringDesc, 32, Temp);\r
+ Fmt = L"%s";\r
+ Type = Temp;\r
+ }\r
+\r
+ //\r
+ // BbsTable 16 entries are for onboard IDE.\r
+ // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11\r
+ //\r
+ if (Index >= 5 && Index <= 16 && CurBBSEntry->DeviceType == BBS_HARDDISK) {\r
+ Fmt = L"%s %d";\r
+ UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);\r
+ } else {\r
+ UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Create a legacy boot option for the specified entry of\r
+ BBS table, save it as variable, and append it to the boot\r
+ order list.\r
+\r
+\r
+ @param CurrentBbsEntry Pointer to current BBS table.\r
+ @param CurrentBbsDevPath Pointer to the Device Path Protocol instance of BBS\r
+ @param Index Index of the specified entry in BBS table.\r
+ @param BootOrderList On input, the original boot order list.\r
+ On output, the new boot order list attached with the\r
+ created node.\r
+ @param BootOrderListSize On input, the original size of boot order list.\r
+ On output, the size of new boot order list.\r
+\r
+ @retval EFI_SUCCESS Boot Option successfully created.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
+ @retval Other Error occurs while setting variable.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsCreateLegacyBootOption (\r
+ IN BBS_TABLE *CurrentBbsEntry,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,\r
+ IN UINTN Index,\r
+ IN OUT UINT16 **BootOrderList,\r
+ IN OUT UINTN *BootOrderListSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 CurrentBootOptionNo;\r
+ UINT16 BootString[10];\r
+ UINT16 BootDesc[100];\r
+ CHAR8 HelpString[100];\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BufferSize;\r
+ UINTN StringLen;\r
+ VOID *Buffer;\r
+ UINT8 *Ptr;\r
+ UINT16 CurrentBbsDevPathSize;\r
+ UINTN BootOrderIndex;\r
+ UINTN BootOrderLastIndex;\r
+ UINTN ArrayIndex;\r
+ BOOLEAN IndexNotFound;\r
+ BBS_BBS_DEVICE_PATH *NewBbsDevPathNode;\r
+\r
+ if ((*BootOrderList) == NULL) {\r
+ CurrentBootOptionNo = 0;\r
+ } else {\r
+ for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {\r
+ IndexNotFound = TRUE;\r
+ for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {\r
+ if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {\r
+ IndexNotFound = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!IndexNotFound) {\r
+ continue;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ CurrentBootOptionNo = (UINT16) ArrayIndex;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ BootString,\r
+ sizeof (BootString),\r
+ L"Boot%04x",\r
+ CurrentBootOptionNo\r
+ );\r
+\r
+ BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);\r
+\r
+ //\r
+ // Create new BBS device path node with description string\r
+ //\r
+ UnicodeStrToAsciiStr ((CONST CHAR16*)&BootDesc, (CHAR8*)&HelpString);\r
+\r
+ StringLen = AsciiStrLen (HelpString);\r
+ NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+ if (NewBbsDevPathNode == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));\r
+ CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);\r
+ SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+\r
+ //\r
+ // Create entire new CurrentBbsDevPath with end node\r
+ //\r
+ CurrentBbsDevPath = AppendDevicePathNode (\r
+ EndDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode\r
+ );\r
+ if (CurrentBbsDevPath == NULL) {\r
+ FreePool (NewBbsDevPathNode);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));\r
+\r
+ BufferSize = sizeof (UINT32) +\r
+ sizeof (UINT16) +\r
+ StrSize (BootDesc) +\r
+ CurrentBbsDevPathSize +\r
+ sizeof (BBS_TABLE) +\r
+ sizeof (UINT16);\r
+\r
+ Buffer = AllocateZeroPool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ FreePool (NewBbsDevPathNode);\r
+ FreePool (CurrentBbsDevPath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Ptr = (UINT8 *) Buffer;\r
+\r
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+ Ptr += sizeof (UINT32);\r
+\r
+ *((UINT16 *) Ptr) = CurrentBbsDevPathSize;\r
+ Ptr += sizeof (UINT16);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ BootDesc,\r
+ StrSize (BootDesc)\r
+ );\r
+ Ptr += StrSize (BootDesc);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ CurrentBbsDevPath,\r
+ CurrentBbsDevPathSize\r
+ );\r
+ Ptr += CurrentBbsDevPathSize;\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ CurrentBbsEntry,\r
+ sizeof (BBS_TABLE)\r
+ );\r
+\r
+ Ptr += sizeof (BBS_TABLE);\r
+ *((UINT16 *) Ptr) = (UINT16) Index;\r
+\r
+ Status = gRT->SetVariable (\r
+ BootString,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+\r
+ FreePool (Buffer);\r
+ \r
+ Buffer = NULL;\r
+\r
+ NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
+ if (NULL == NewBootOrderList) {\r
+ FreePool (NewBbsDevPathNode);\r
+ FreePool (CurrentBbsDevPath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (*BootOrderList != NULL) {\r
+ CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
+ FreePool (*BootOrderList);\r
+ }\r
+\r
+ BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
+ NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;\r
+ *BootOrderListSize += sizeof (UINT16);\r
+ *BootOrderList = NewBootOrderList;\r
+\r
+ FreePool (NewBbsDevPathNode);\r
+ FreePool (CurrentBbsDevPath);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check if the boot option is a legacy one.\r
+\r
+ @param BootOptionVar The boot option data payload.\r
+ @param BbsEntry The BBS Table.\r
+ @param BbsIndex The table index.\r
+\r
+ @retval TRUE It is a legacy boot option.\r
+ @retval FALSE It is not a legacy boot option.\r
+\r
+**/\r
+BOOLEAN\r
+BdsIsLegacyBootOption (\r
+ IN UINT8 *BootOptionVar,\r
+ OUT BBS_TABLE **BbsEntry,\r
+ OUT UINT16 *BbsIndex\r
+ )\r
+{\r
+ UINT8 *Ptr;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BOOLEAN Ret;\r
+ UINT16 DevPathLen;\r
+\r
+ Ptr = BootOptionVar;\r
+ Ptr += sizeof (UINT32);\r
+ DevPathLen = *(UINT16 *) Ptr;\r
+ Ptr += sizeof (UINT16);\r
+ Ptr += StrSize ((UINT16 *) Ptr);\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+ Ptr += DevPathLen;\r
+ *BbsEntry = (BBS_TABLE *) Ptr;\r
+ Ptr += sizeof (BBS_TABLE);\r
+ *BbsIndex = *(UINT16 *) Ptr;\r
+ Ret = TRUE;\r
+ } else {\r
+ *BbsEntry = NULL;\r
+ Ret = FALSE;\r
+ }\r
+\r
+ return Ret;\r
+}\r
+\r
+/**\r
+ Delete all the invalid legacy boot options.\r
+\r
+ @retval EFI_SUCCESS All invalide legacy boot options are deleted.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
+ @retval EFI_NOT_FOUND Fail to retrive variable of boot order.\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 *BootOrder;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOrderSize;\r
+ UINTN BootOptionSize;\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ BBS_TABLE *BbsEntry;\r
+ UINT16 BbsIndex;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Index;\r
+ UINT16 BootOption[10];\r
+ UINT16 BootDesc[100];\r
+ BOOLEAN DescStringMatch;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BootOrder = NULL;\r
+ BootOrderSize = 0;\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+ BbsEntry = NULL;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Index = 0;\r
+ while (Index < BootOrderSize / sizeof (UINT16)) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ if (BootOrder != NULL) {\r
+ FreePool (BootOrder);\r
+ }\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ //\r
+ // Skip Non-Legacy boot options\r
+ // \r
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
+ if (BootOptionVar!= NULL) {\r
+ FreePool (BootOptionVar);\r
+ }\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check if BBS Description String is changed\r
+ //\r
+ DescStringMatch = FALSE;\r
+\r
+ BdsBuildLegacyDevNameString (\r
+ &LocalBbsTable[BbsIndex],\r
+ BbsIndex,\r
+ sizeof(BootDesc),\r
+ BootDesc\r
+ );\r
+\r
+ if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
+ DescStringMatch = TRUE;\r
+ }\r
+\r
+ if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&\r
+ (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
+ DescStringMatch) {\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ if (BootOptionVar != NULL) {\r
+ FreePool (BootOptionVar);\r
+ }\r
+ //\r
+ // should delete\r
+ //\r
+ BdsDeleteBootOption (\r
+ BootOrder[Index],\r
+ BootOrder,\r
+ &BootOrderSize\r
+ );\r
+ }\r
+\r
+ //\r
+ // Adjust the number of boot options.\r
+ //\r
+ if (BootOrderSize != 0) {\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderSize,\r
+ BootOrder\r
+ );\r
+ } else {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ if (BootOrder != NULL) {\r
+ FreePool (BootOrder);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Find all legacy boot option by device type.\r
+\r
+ @param BootOrder The boot order array.\r
+ @param BootOptionNum The number of boot option.\r
+ @param DevType Device type.\r
+ @param Attribute The boot option attribute.\r
+ @param BbsIndex The BBS table index.\r
+ @param OptionNumber The boot option index.\r
+\r
+ @retval TRUE The Legacy boot option is found.\r
+ @retval FALSE The legacy boot option is not found.\r
+\r
+**/\r
+BOOLEAN\r
+BdsFindLegacyBootOptionByDevType (\r
+ IN UINT16 *BootOrder,\r
+ IN UINTN BootOptionNum,\r
+ IN UINT16 DevType,\r
+ OUT UINT32 *Attribute,\r
+ OUT UINT16 *BbsIndex,\r
+ OUT UINTN *OptionNumber\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN BootOrderIndex;\r
+ UINT16 BootOption[100];\r
+ UINTN BootOptionSize;\r
+ UINT8 *BootOptionVar;\r
+ BBS_TABLE *BbsEntry;\r
+ BOOLEAN Found;\r
+\r
+ BbsEntry = NULL;\r
+ Found = FALSE;\r
+\r
+ if (NULL == BootOrder) {\r
+ return Found;\r
+ }\r
+\r
+ //\r
+ // Loop all boot option from variable\r
+ //\r
+ for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {\r
+ Index = (UINTN) BootOrder[BootOrderIndex];\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Skip Non-legacy boot option\r
+ //\r
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
+ FreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ if (BbsEntry->DeviceType != DevType) {\r
+ FreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ *Attribute = *(UINT32 *) BootOptionVar;\r
+ *OptionNumber = Index;\r
+ Found = TRUE;\r
+ FreePool (BootOptionVar);\r
+ break;\r
+ }\r
+\r
+ return Found;\r
+}\r
+\r
+/**\r
+ Create a legacy boot option.\r
+\r
+ @param BbsItem The BBS Table entry.\r
+ @param Index Index of the specified entry in BBS table.\r
+ @param BootOrderList The boot order list.\r
+ @param BootOrderListSize The size of boot order list.\r
+\r
+ @retval EFI_OUT_OF_RESOURCE No enough memory.\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return Other value if the legacy boot option is not created.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsCreateOneLegacyBootOption (\r
+ IN BBS_TABLE *BbsItem,\r
+ IN UINTN Index,\r
+ IN OUT UINT16 **BootOrderList,\r
+ IN OUT UINTN *BootOrderListSize\r
+ )\r
+{\r
+ BBS_BBS_DEVICE_PATH BbsDevPathNode;\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+\r
+ DevPath = NULL;\r
+\r
+ //\r
+ // Create device path node.\r
+ //\r
+ BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;\r
+ BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
+ SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
+ BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
+ CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
+\r
+ DevPath = AppendDevicePathNode (\r
+ EndDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
+ );\r
+ if (NULL == DevPath) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = BdsCreateLegacyBootOption (\r
+ BbsItem,\r
+ DevPath,\r
+ Index,\r
+ BootOrderList,\r
+ BootOrderListSize\r
+ );\r
+ BbsItem->BootPriority = 0x00;\r
+\r
+ FreePool (DevPath);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ Add the legacy boot options from BBS table if they do not exist.\r
+\r
+ @retval EFI_SUCCESS The boot options are added successfully \r
+ or they are already in boot options.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 *BootOrder;\r
+ UINTN BootOrderSize;\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINT16 BbsIndex;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Index;\r
+ UINT32 Attribute;\r
+ UINTN OptionNumber;\r
+ BOOLEAN Ret;\r
+\r
+ BootOrder = NULL;\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ BootOrderSize = 0;\r
+ }\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ Ret = BdsFindLegacyBootOptionByDevType (\r
+ BootOrder,\r
+ BootOrderSize / sizeof (UINT16),\r
+ LocalBbsTable[Index].DeviceType,\r
+ &Attribute,\r
+ &BbsIndex,\r
+ &OptionNumber\r
+ );\r
+ if (Ret) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Not found such type of legacy device in boot options or we found but it's disabled\r
+ // so we have to create one and put it to the tail of boot order list\r
+ //\r
+ Status = BdsCreateOneLegacyBootOption (\r
+ &LocalBbsTable[Index],\r
+ Index,\r
+ &BootOrder,\r
+ &BootOrderSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (BootOrderSize > 0) {\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderSize,\r
+ BootOrder\r
+ );\r
+ } else {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ if (BootOrder != NULL) {\r
+ FreePool (BootOrder);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Fill the device order buffer.\r
+\r
+ @param BbsTable The BBS table.\r
+ @param BbsType The BBS Type.\r
+ @param BbsCount The BBS Count.\r
+ @param Buf device order buffer.\r
+\r
+ @return The device order buffer.\r
+\r
+**/\r
+UINT16 *\r
+BdsFillDevOrderBuf (\r
+ IN BBS_TABLE *BbsTable,\r
+ IN BBS_TYPE BbsType,\r
+ IN UINTN BbsCount,\r
+ OUT UINT16 *Buf\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+ continue;\r
+ }\r
+\r
+ if (BbsTable[Index].DeviceType != BbsType) {\r
+ continue;\r
+ }\r
+\r
+ *Buf = (UINT16) (Index & 0xFF);\r
+ Buf++;\r
+ }\r
+\r
+ return Buf;\r
+}\r
+\r
+/**\r
+ Create the device order buffer.\r
+\r
+ @param BbsTable The BBS table.\r
+ @param BbsCount The BBS Count.\r
+\r
+ @retval EFI_SUCCES The buffer is created and the EFI variable named \r
+ VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is\r
+ set correctly.\r
+ @return Other value if the set of EFI variable fails. Check gRT->SetVariable\r
+ for detailed information.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsCreateDevOrder (\r
+ IN BBS_TABLE *BbsTable,\r
+ IN UINT16 BbsCount\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN FDCount;\r
+ UINTN HDCount;\r
+ UINTN CDCount;\r
+ UINTN NETCount;\r
+ UINTN BEVCount;\r
+ UINTN TotalSize;\r
+ UINTN HeaderSize;\r
+ UINT8 *DevOrder;\r
+ UINT8 *Ptr;\r
+ EFI_STATUS Status;\r
+\r
+ FDCount = 0;\r
+ HDCount = 0;\r
+ CDCount = 0;\r
+ NETCount = 0;\r
+ BEVCount = 0;\r
+ TotalSize = 0;\r
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+ DevOrder = NULL;\r
+ Ptr = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Count all boot devices\r
+ //\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+ continue;\r
+ }\r
+\r
+ switch (BbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ FDCount++;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ HDCount++;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ CDCount++;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ NETCount++;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ BEVCount++;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
+\r
+ //\r
+ // Create buffer to hold all boot device order\r
+ //\r
+ DevOrder = AllocateZeroPool (TotalSize);\r
+ if (NULL == DevOrder) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Ptr = DevOrder;\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_FLOPPY;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (FDCount != 0) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_HARDDISK;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (HDCount != 0) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_CDROM;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (CDCount != 0) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (NETCount != 0) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (BEVCount != 0) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ //\r
+ // Save device order for legacy boot device to variable.\r
+ //\r
+ Status = gRT->SetVariable (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ TotalSize,\r
+ DevOrder\r
+ );\r
+ FreePool (DevOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ Add the legacy boot devices from BBS table into \r
+ the legacy device boot order.\r
+\r
+ @retval EFI_SUCCESS The boot devices are added successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 *DevOrder;\r
+ UINT8 *NewDevOrder;\r
+ UINTN DevOrderSize;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN *Idx;\r
+ UINTN FDCount;\r
+ UINTN HDCount;\r
+ UINTN CDCount;\r
+ UINTN NETCount;\r
+ UINTN BEVCount;\r
+ UINTN TotalSize;\r
+ UINTN HeaderSize;\r
+ UINT8 *Ptr;\r
+ UINT8 *NewPtr;\r
+ UINT16 *NewFDPtr;\r
+ UINT16 *NewHDPtr;\r
+ UINT16 *NewCDPtr;\r
+ UINT16 *NewNETPtr;\r
+ UINT16 *NewBEVPtr;\r
+ UINT16 *NewDevPtr;\r
+ UINT16 Length;\r
+ UINT16 Tmp;\r
+ UINTN FDIndex;\r
+ UINTN HDIndex;\r
+ UINTN CDIndex;\r
+ UINTN NETIndex;\r
+ UINTN BEVIndex;\r
+\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+ Idx = NULL;\r
+ FDCount = 0;\r
+ HDCount = 0;\r
+ CDCount = 0;\r
+ NETCount = 0;\r
+ BEVCount = 0;\r
+ TotalSize = 0;\r
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+ FDIndex = 0;\r
+ HDIndex = 0;\r
+ CDIndex = 0;\r
+ NETIndex = 0;\r
+ BEVIndex = 0;\r
+ NewDevPtr = NULL;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ DevOrder = (UINT8 *) BdsLibGetVariableAndSize (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ &DevOrderSize\r
+ );\r
+ if (NULL == DevOrder) {\r
+ return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
+ }\r
+ //\r
+ // First we figure out how many boot devices with same device type respectively\r
+ //\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ switch (LocalBbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ FDCount++;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ HDCount++;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ CDCount++;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ NETCount++;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ BEVCount++;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
+\r
+ NewDevOrder = AllocateZeroPool (TotalSize);\r
+ if (NULL == NewDevOrder) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);\r
+ NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);\r
+ NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);\r
+ NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);\r
+ NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);\r
+\r
+ //\r
+ // copy FD\r
+ //\r
+ Ptr = DevOrder;\r
+ NewPtr = NewDevOrder;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewFDPtr[FDIndex] = *(UINT16 *) Ptr;\r
+ FDIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy HD\r
+ //\r
+ NewPtr = (UINT8 *) NewHDPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewHDPtr[HDIndex] = *(UINT16 *) Ptr;\r
+ HDIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy CD\r
+ //\r
+ NewPtr = (UINT8 *) NewCDPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_CDROM\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewCDPtr[CDIndex] = *(UINT16 *) Ptr;\r
+ CDIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy NET\r
+ //\r
+ NewPtr = (UINT8 *) NewNETPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewNETPtr[NETIndex] = *(UINT16 *) Ptr;\r
+ NETIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy BEV\r
+ //\r
+ NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;\r
+ BEVIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ switch (LocalBbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ Idx = &FDIndex;\r
+ NewDevPtr = NewFDPtr;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ Idx = &HDIndex;\r
+ NewDevPtr = NewHDPtr;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ Idx = &CDIndex;\r
+ NewDevPtr = NewCDPtr;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ Idx = &NETIndex;\r
+ NewDevPtr = NewNETPtr;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ Idx = &BEVIndex;\r
+ NewDevPtr = NewBEVPtr;\r
+ break;\r
+\r
+ default:\r
+ Idx = NULL;\r
+ break;\r
+ }\r
+ //\r
+ // at this point we have copied those valid indexes to new buffer\r
+ // and we should check if there is any new appeared boot device\r
+ //\r
+ if (Idx != 0) {\r
+ for (Index2 = 0; Index2 < *Idx; Index2++) {\r
+ if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index2 == *Idx) {\r
+ //\r
+ // Index2 == *Idx means we didn't find Index\r
+ // so Index is a new appeared device's index in BBS table\r
+ // save it.\r
+ //\r
+ NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
+ (*Idx)++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (FDCount != 0) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < FDIndex - 1; Index++) {\r
+ if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {\r
+ if (0 == (NewFDPtr[Index2] & 0xFF00)) {\r
+ Tmp = NewFDPtr[Index];\r
+ NewFDPtr[Index] = NewFDPtr[Index2];\r
+ NewFDPtr[Index2] = Tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (HDCount != 0) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < HDIndex - 1; Index++) {\r
+ if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {\r
+ if (0 == (NewHDPtr[Index2] & 0xFF00)) {\r
+ Tmp = NewHDPtr[Index];\r
+ NewHDPtr[Index] = NewHDPtr[Index2];\r
+ NewHDPtr[Index2] = Tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (CDCount != 0) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < CDIndex - 1; Index++) {\r
+ if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {\r
+ if (0 == (NewCDPtr[Index2] & 0xFF00)) {\r
+ Tmp = NewCDPtr[Index];\r
+ NewCDPtr[Index] = NewCDPtr[Index2];\r
+ NewCDPtr[Index2] = Tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (NETCount != 0) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < NETIndex - 1; Index++) {\r
+ if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {\r
+ if (0 == (NewNETPtr[Index2] & 0xFF00)) {\r
+ Tmp = NewNETPtr[Index];\r
+ NewNETPtr[Index] = NewNETPtr[Index2];\r
+ NewNETPtr[Index2] = Tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (BEVCount!= 0) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < BEVIndex - 1; Index++) {\r
+ if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {\r
+ if (0 == (NewBEVPtr[Index2] & 0xFF00)) {\r
+ Tmp = NewBEVPtr[Index];\r
+ NewBEVPtr[Index] = NewBEVPtr[Index2];\r
+ NewBEVPtr[Index2] = Tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (DevOrder);\r
+\r
+ Status = gRT->SetVariable (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ TotalSize,\r
+ NewDevOrder\r
+ );\r
+ FreePool (NewDevOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set Boot Priority for specified device type.\r
+\r
+ @param DeviceType The device type.\r
+ @param LocalBbsTable The BBS table.\r
+ @param Priority The prority table.\r
+\r
+ @retval EFI_SUCCESS The function completes successfully.\r
+ @retval EFI_NOT_FOUND Failed to find device.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsSetBootPriority4SameTypeDev (\r
+ IN UINT16 DeviceType,\r
+ IN OUT BBS_TABLE *LocalBbsTable,\r
+ IN OUT UINT16 *Priority\r
+ )\r
+{\r
+ UINT8 *DevOrder;\r
+\r
+ UINT8 *OrigBuffer;\r
+ UINT16 *DevIndex;\r
+ UINTN DevOrderSize;\r
+ UINTN DevCount;\r
+ UINTN Index;\r
+\r
+ DevOrder = BdsLibGetVariableAndSize (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ &DevOrderSize\r
+ );\r
+ if (NULL == DevOrder) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OrigBuffer = DevOrder;\r
+ while (DevOrder < OrigBuffer + DevOrderSize) {\r
+ if (DeviceType == * (BBS_TYPE *) DevOrder) {\r
+ break;\r
+ }\r
+\r
+ DevOrder += sizeof (BBS_TYPE);\r
+ DevOrder += *(UINT16 *) DevOrder;\r
+ }\r
+\r
+ if (DevOrder >= OrigBuffer + DevOrderSize) {\r
+ FreePool (OrigBuffer);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DevOrder += sizeof (BBS_TYPE);\r
+ DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);\r
+ DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));\r
+ //\r
+ // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
+ //\r
+ for (Index = 0; Index < DevCount; Index++) {\r
+ if ((DevIndex[Index] & 0xFF00) == 0xFF00) {\r
+ //\r
+ // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
+ //\r
+ } else {\r
+ LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;\r
+ (*Priority)++;\r
+ }\r
+ }\r
+\r
+ FreePool (OrigBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Print the BBS Table.\r
+\r
+ @param LocalBbsTable The BBS table.\r
+\r
+**/\r
+VOID\r
+PrintBbsTable (\r
+ IN BBS_TABLE *LocalBbsTable\r
+ )\r
+{\r
+ UINT16 Idx;\r
+\r
+ DEBUG ((DEBUG_ERROR, "\n"));\r
+ DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+ DEBUG ((DEBUG_ERROR, "=============================================\n"));\r
+ for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {\r
+ if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+ (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG (\r
+ (DEBUG_ERROR,\r
+ " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
+ (UINTN) Idx,\r
+ (UINTN) LocalBbsTable[Idx].BootPriority,\r
+ (UINTN) LocalBbsTable[Idx].Bus,\r
+ (UINTN) LocalBbsTable[Idx].Device,\r
+ (UINTN) LocalBbsTable[Idx].Function,\r
+ (UINTN) LocalBbsTable[Idx].Class,\r
+ (UINTN) LocalBbsTable[Idx].SubClass,\r
+ (UINTN) LocalBbsTable[Idx].DeviceType,\r
+ (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
+ (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
+ (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
+ (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
+ (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
+ );\r
+ }\r
+\r
+ DEBUG ((DEBUG_ERROR, "\n"));\r
+}\r
+\r
+/**\r
+\r
+ Set the boot priority for BBS entries based on boot option entry and boot order.\r
+\r
+ @param Entry The boot option is to be checked for refresh BBS table.\r
+ \r
+ @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.\r
+ @return status of BdsSetBootPriority4SameTypeDev()\r
+**/\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+ IN BDS_COMMON_OPTION *Entry\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINT16 DevType;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Index;\r
+ UINT16 Priority;\r
+ UINT16 *BootOrder;\r
+ UINTN BootOrderSize;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOptionSize;\r
+ UINT16 BootOption[100];\r
+ UINT8 *Ptr;\r
+ UINT16 DevPathLen;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+ DevType = BBS_UNKNOWN;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+ //\r
+ // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
+ // We will set them according to the settings setup by user\r
+ //\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
+ (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
+ (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
+ LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ }\r
+ }\r
+ //\r
+ // boot priority always starts at 0\r
+ //\r
+ Priority = 0;\r
+ if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
+ //\r
+ // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
+ //\r
+ DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
+ Status = BdsSetBootPriority4SameTypeDev (\r
+ DevType,\r
+ LocalBbsTable,\r
+ &Priority\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // we have to set the boot priority for other BBS entries with different device types\r
+ //\r
+ BootOrder = (UINT16 *) BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ continue;\r
+ }\r
+\r
+ Ptr = BootOptionVar;\r
+\r
+ Ptr += sizeof (UINT32);\r
+ DevPathLen = *(UINT16 *) Ptr;\r
+ Ptr += sizeof (UINT16);\r
+ Ptr += StrSize ((UINT16 *) Ptr);\r
+ DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
+ FreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ Ptr += DevPathLen;\r
+ if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {\r
+ //\r
+ // We don't want to process twice for a device type\r
+ //\r
+ FreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ Status = BdsSetBootPriority4SameTypeDev (\r
+ ((BBS_TABLE *) Ptr)->DeviceType,\r
+ LocalBbsTable,\r
+ &Priority\r
+ );\r
+ FreePool (BootOptionVar);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (BootOrder != NULL) {\r
+ FreePool (BootOrder);\r
+ }\r
+\r
+ DEBUG_CODE_BEGIN();\r
+ PrintBbsTable (LocalBbsTable);\r
+ DEBUG_CODE_END();\r
+ \r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ declares interface functions\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_BDS_BBS_SUPPORT_H_\r
+#define _EFI_BDS_BBS_SUPPORT_H_\r
+\r
+#include "BootMaint.h"\r
+\r
+#define MAX_BBS_ENTRIES 0x100\r
+\r
+/**\r
+ Build Legacy Device Name String according.\r
+\r
+ @param CurBBSEntry BBS Table.\r
+ @param Index Index.\r
+ @param BufSize The buffer size.\r
+ @param BootString The output string.\r
+\r
+ @return VOID No output.\r
+\r
+**/\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+ IN BBS_TABLE *CurBBSEntry,\r
+ IN UINTN Index,\r
+ IN UINTN BufSize,\r
+ OUT CHAR16 *BootString\r
+ );\r
+\r
+/**\r
+ Delete all the invalid legacy boot options.\r
+\r
+ \r
+\r
+ @retval EFI_SUCCESS All invalide legacy boot options are deleted.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory.\r
+ @retval EFI_NOT_FOUND Fail to retrive variable of boot order.\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+ VOID\r
+ );\r
+\r
+/**\r
+\r
+ Add the legacy boot options from BBS table if they do not exist.\r
+\r
+ @retval EFI_SUCCESS The boot options are added successfully or they are already in boot options.\r
+ @retval others An error occurred when creating legacy boot options.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+ VOID\r
+ );\r
+\r
+/**\r
+\r
+ Add the legacy boot devices from BBS table into \r
+ the legacy device boot order.\r
+\r
+ @retval EFI_SUCCESS The boot devices are added successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Set the boot priority for BBS entries based on boot option entry and boot order.\r
+\r
+ @param Entry The boot option is to be checked for refresh BBS table.\r
+ \r
+ @retval EFI_SUCCESS The boot priority for BBS entries is refreshed successfully.\r
+ @return status of BdsSetBootPriority4SameTypeDev()\r
+**/\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+ IN BDS_COMMON_OPTION *Entry\r
+ );\r
+\r
+#endif\r
--- /dev/null
+///** @file\r
+// \r
+// Boot Maintenance Utility Formset\r
+// \r
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+// \r
+//**/\r
+\r
+#include "FormGuid.h"\r
+\r
+#define LABEL_END 0xffff\r
+\r
+formset\r
+ guid = BOOT_MAINT_FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ class = 0,\r
+ subclass = 0,\r
+\r
+ varstore BMM_FAKE_NV_DATA,\r
+ varid = VARSTORE_ID_BOOT_MAINT,\r
+ name = BmmData,\r
+ guid = BOOT_MAINT_FORMSET_GUID;\r
+\r
+ form formid = FORM_MAIN_ID,\r
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE);\r
+\r
+ goto FORM_BOOT_SETUP_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_SETUP_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ goto FORM_DRIVER_SETUP_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRIVER_SETUP_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ goto FORM_CON_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_MAIN_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),\r
+ text = STRING_TOKEN(STR_BOOT_FROM_FILE),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_BOOT_FROM_FILE;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+// label FORM_MAIN_ID;\r
+\r
+ goto FORM_BOOT_NEXT_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_NEXT_ID;\r
+\r
+ goto FORM_TIME_OUT_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_TIME_OUT_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_RESET),\r
+ help = STRING_TOKEN(STR_RESET),\r
+ flags = INTERACTIVE,\r
+ key = FORM_RESET;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_SETUP_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_BOOT_ADD_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_ADD_ID;\r
+\r
+ goto FORM_BOOT_DEL_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_DEL_ID;\r
+\r
+ goto FORM_BOOT_CHG_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_CHG_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+ //\r
+ // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive"\r
+ // here dynamically\r
+ //\r
+ label FORM_BOOT_LEGACY_DEVICE_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRIVER_SETUP_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_DRV_ADD_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_ADD_ID;\r
+\r
+ goto FORM_DRV_DEL_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_DEL_ID;\r
+\r
+ goto FORM_DRV_CHG_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_CHG_ID;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_ADD_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+ label FORM_BOOT_ADD_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_DEL_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);\r
+\r
+ label FORM_BOOT_DEL_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_CHG_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);\r
+\r
+ label FORM_BOOT_CHG_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_NEXT_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);\r
+\r
+ label FORM_BOOT_NEXT_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_TIME_OUT_ID,\r
+ title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);\r
+\r
+ label FORM_TIME_OUT_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_DRV_ADD_FILE_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_ADD_FILE_ID;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRV_DEL_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);\r
+\r
+ label FORM_DRV_DEL_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRV_CHG_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);\r
+\r
+ label FORM_DRV_CHG_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_MAIN_ID,\r
+ title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_CON_IN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_CON_IN_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_IN_ID;\r
+\r
+ goto FORM_CON_OUT_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_OUT_ID;\r
+\r
+ goto FORM_CON_ERR_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_ERR_ID;\r
+\r
+ goto FORM_CON_MODE_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_MODE_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_MODE_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_MODE_ID;\r
+\r
+ goto FORM_CON_COM_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_COM_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_COM_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_COM_ID;\r
+ endform;\r
+\r
+ form formid = FORM_CON_MODE_ID,\r
+ title = STRING_TOKEN(STR_FORM_MODE_TITLE);\r
+\r
+ label FORM_CON_MODE_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_CON_COM_ID,\r
+ title = STRING_TOKEN(STR_FORM_COM_TITLE);\r
+\r
+ label FORM_CON_COM_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_CON_COM_SETUP_ID,\r
+ title = STRING_TOKEN(STR_CON_COM_SETUP);\r
+\r
+ label FORM_CON_COM_SETUP_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_FILE_SEEK_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+ label FORM_FILE_SEEK_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_FILE_NEW_SEEK_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+ label FORM_FILE_NEW_SEEK_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_FILE_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);\r
+\r
+ label FORM_DRV_ADD_FILE_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_HANDLE_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);\r
+\r
+ label FORM_DRV_ADD_HANDLE_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_HANDLE_DESC_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+ label FORM_DRV_ADD_HANDLE_DESC_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_IN_ID,\r
+ title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);\r
+\r
+ label FORM_CON_IN_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_OUT_ID,\r
+ title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);\r
+\r
+ label FORM_CON_OUT_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_ERR_ID,\r
+ title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);\r
+\r
+ label FORM_CON_ERR_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_SET_FD_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);\r
+\r
+ label FORM_SET_FD_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_HD_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);\r
+\r
+ label FORM_SET_HD_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_CD_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);\r
+\r
+ label FORM_SET_CD_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_NET_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);\r
+\r
+ label FORM_SET_NET_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_BEV_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);\r
+\r
+ label FORM_SET_BEV_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/** @file\r
+ Utility routines used by boot maintenance modules.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+\r
+/**\r
+\r
+ Find the first instance of this Protocol\r
+ in the system and return it's interface.\r
+\r
+\r
+ @param ProtocolGuid Provides the protocol to search for\r
+ @param Interface On return, a pointer to the first interface\r
+ that matches ProtocolGuid\r
+\r
+ @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found\r
+ @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->LocateProtocol (\r
+ ProtocolGuid,\r
+ NULL,\r
+ (VOID **) Interface\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ Function opens and returns a file handle to the root directory of a volume.\r
+\r
+ @param DeviceHandle A handle for a device\r
+\r
+ @return A valid file handle or NULL is returned\r
+\r
+**/\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+ EFI_FILE_HANDLE File;\r
+\r
+ File = NULL;\r
+\r
+ //\r
+ // File the file system interface to the device\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (VOID *) &Volume\r
+ );\r
+\r
+ //\r
+ // Open the root directory of the volume\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Volume->OpenVolume (\r
+ Volume,\r
+ &File\r
+ );\r
+ }\r
+ //\r
+ // Done\r
+ //\r
+ return EFI_ERROR (Status) ? NULL : File;\r
+}\r
+\r
+/**\r
+\r
+ Helper function called as part of the code needed\r
+ to allocate the proper sized buffer for various\r
+ EFI interfaces.\r
+\r
+\r
+ @param Status Current status\r
+ @param Buffer Current allocated buffer, or NULL\r
+ @param BufferSize Current buffer size needed\r
+\r
+ @retval TRUE if the buffer was reallocated and the caller\r
+ should try the API again.\r
+ @retval FALSE The caller should not call this function again.\r
+\r
+**/\r
+BOOLEAN\r
+EfiGrowBuffer (\r
+ IN OUT EFI_STATUS *Status,\r
+ IN OUT VOID **Buffer,\r
+ IN UINTN BufferSize\r
+ )\r
+{\r
+ BOOLEAN TryAgain;\r
+\r
+ //\r
+ // If this is an initial request, buffer will be null with a new buffer size\r
+ //\r
+ if ((*Buffer == NULL) && (BufferSize != 0)) {\r
+ *Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ //\r
+ // If the status code is "buffer too small", resize the buffer\r
+ //\r
+ TryAgain = FALSE;\r
+ if (*Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+ if (*Buffer != NULL) {\r
+ FreePool (*Buffer);\r
+ }\r
+\r
+ *Buffer = AllocateZeroPool (BufferSize);\r
+\r
+ if (*Buffer != NULL) {\r
+ TryAgain = TRUE;\r
+ } else {\r
+ *Status = EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // If there's an error, free the buffer\r
+ //\r
+ if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {\r
+ FreePool (*Buffer);\r
+ *Buffer = NULL;\r
+ }\r
+\r
+ return TryAgain;\r
+}\r
+\r
+/**\r
+ Function returns the value of the specified variable.\r
+\r
+\r
+ @param Name A Null-terminated Unicode string that is\r
+ the name of the vendor's variable.\r
+ @param VendorGuid A unique identifier for the vendor.\r
+\r
+ @return The payload of the variable.\r
+ @retval NULL If the variable can't be read.\r
+\r
+**/\r
+VOID *\r
+EfiLibGetVariable (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ UINTN VarSize;\r
+\r
+ return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
+}\r
+\r
+/**\r
+ Function deletes the variable specified by VarName and VarGuid.\r
+\r
+ @param VarName A Null-terminated Unicode string that is\r
+ the name of the vendor's variable.\r
+ \r
+ @param VarGuid A unique identifier for the vendor.\r
+\r
+ @retval EFI_SUCCESS The variable was found and removed\r
+ @retval EFI_UNSUPPORTED The variable store was inaccessible\r
+ @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available\r
+ @retval EFI_NOT_FOUND The variable was not found\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VarGuid\r
+ )\r
+{\r
+ VOID *VarBuf;\r
+ EFI_STATUS Status;\r
+\r
+ VarBuf = EfiLibGetVariable (VarName, VarGuid);\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ if (VarBuf != NULL) {\r
+ //\r
+ // Delete variable from Storage\r
+ //\r
+ Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ FreePool (VarBuf);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ Function gets the file system information from an open file descriptor,\r
+ and stores it in a buffer allocated from pool.\r
+\r
+\r
+ @param FHand The file handle.\r
+\r
+ @return A pointer to a buffer with file information.\r
+ @retval NULL is returned if failed to get Vaolume Label Info.\r
+\r
+**/\r
+EFI_FILE_SYSTEM_VOLUME_LABEL *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer;\r
+ UINTN BufferSize;\r
+ //\r
+ // Initialize for GrowBuffer loop\r
+ //\r
+ Buffer = NULL;\r
+ BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;\r
+\r
+ //\r
+ // Call the real function\r
+ //\r
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+ Status = FHand->GetInfo (\r
+ FHand,\r
+ &gEfiFileSystemVolumeLabelInfoIdGuid,\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ }\r
+\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Duplicate a string.\r
+\r
+ @param Src The source.\r
+\r
+ @return A new string which is duplicated copy of the source.\r
+ @retval NULL If there is not enough memory.\r
+\r
+**/\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+ IN CHAR16 *Src\r
+ )\r
+{\r
+ CHAR16 *Dest;\r
+ UINTN Size;\r
+\r
+ Size = StrSize (Src);\r
+ Dest = AllocateZeroPool (Size);\r
+ ASSERT (Dest != NULL);\r
+ if (Dest != NULL) {\r
+ CopyMem (Dest, Src, Size);\r
+ }\r
+\r
+ return Dest;\r
+}\r
+\r
+/**\r
+\r
+ Function gets the file information from an open file descriptor, and stores it\r
+ in a buffer allocated from pool.\r
+\r
+ @param FHand File Handle.\r
+\r
+ @return A pointer to a buffer with file information or NULL is returned\r
+\r
+**/\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FILE_INFO *Buffer;\r
+ UINTN BufferSize;\r
+\r
+ //\r
+ // Initialize for GrowBuffer loop\r
+ //\r
+ Buffer = NULL;\r
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
+\r
+ //\r
+ // Call the real function\r
+ //\r
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+ Status = FHand->GetInfo (\r
+ FHand,\r
+ &gEfiFileInfoGuid,\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ }\r
+\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Function is used to determine the number of device path instances\r
+ that exist in a device path.\r
+\r
+\r
+ @param DevicePath A pointer to a device path data structure.\r
+\r
+ @return This function counts and returns the number of device path instances\r
+ in DevicePath.\r
+\r
+**/\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ UINTN Count;\r
+ UINTN Size;\r
+\r
+ Count = 0;\r
+ while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
+ Count += 1;\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+/**\r
+ Adjusts the size of a previously allocated buffer.\r
+\r
+\r
+ @param OldPool - A pointer to the buffer whose size is being adjusted.\r
+ @param OldSize - The size of the current buffer.\r
+ @param NewSize - The size of the new buffer.\r
+\r
+ @return The newly allocated buffer.\r
+ @retval NULL Allocation failed.\r
+\r
+**/\r
+VOID *\r
+EfiReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ )\r
+{\r
+ VOID *NewPool;\r
+\r
+ NewPool = NULL;\r
+ if (NewSize != 0) {\r
+ NewPool = AllocateZeroPool (NewSize);\r
+ }\r
+\r
+ if (OldPool != NULL) {\r
+ if (NewPool != NULL) {\r
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+ }\r
+\r
+ FreePool (OldPool);\r
+ }\r
+\r
+ return NewPool;\r
+}\r
+\r
+/**\r
+ Compare two EFI_TIME data.\r
+\r
+\r
+ @param FirstTime - A pointer to the first EFI_TIME data.\r
+ @param SecondTime - A pointer to the second EFI_TIME data.\r
+\r
+ @retval TRUE The FirstTime is not later than the SecondTime.\r
+ @retval FALSE The FirstTime is later than the SecondTime.\r
+\r
+**/\r
+BOOLEAN\r
+TimeCompare (\r
+ IN EFI_TIME *FirstTime,\r
+ IN EFI_TIME *SecondTime\r
+ )\r
+{\r
+ if (FirstTime->Year != SecondTime->Year) {\r
+ return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
+ } else if (FirstTime->Month != SecondTime->Month) {\r
+ return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
+ } else if (FirstTime->Day != SecondTime->Day) {\r
+ return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
+ } else if (FirstTime->Hour != SecondTime->Hour) {\r
+ return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
+ } else if (FirstTime->Minute != SecondTime->Minute) {\r
+ return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
+ } else if (FirstTime->Second != SecondTime->Second) {\r
+ return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
+ }\r
+\r
+ return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
+}\r
+\r
+/**\r
+ Get a string from the Data Hub record based on \r
+ a device path.\r
+\r
+ @param DevPath The device Path.\r
+\r
+ @return A string located from the Data Hub records based on\r
+ the device path.\r
+ @retval NULL If failed to get the String from Data Hub.\r
+\r
+**/\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 *Desc;\r
+ EFI_DATA_HUB_PROTOCOL *Datahub;\r
+ UINT64 Count;\r
+ EFI_DATA_RECORD_HEADER *Record;\r
+ EFI_SUBCLASS_TYPE1_HEADER *DataHdr;\r
+ EFI_GUID MiscGuid;\r
+ EFI_MISC_ONBOARD_DEVICE_DATA *Ob;\r
+ EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
+ EFI_TIME CurTime;\r
+\r
+ CopyGuid (&MiscGuid, &gEfiMiscSubClassGuid);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDataHubProtocolGuid,\r
+ NULL,\r
+ (VOID **) &Datahub\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = gRT->GetTime (&CurTime, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Count = 0;\r
+ do {\r
+ Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
+ //\r
+ // This record is what we need\r
+ //\r
+ DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+ if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
+ Ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Ob->OnBoardDevicePath, DevPath)) {\r
+ GetProducerString (&Record->ProducerName, Ob->OnBoardDeviceDescription, &Desc);\r
+ return Desc;\r
+ }\r
+ }\r
+\r
+ if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
+ Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
+ GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
+ return Desc;\r
+ }\r
+ }\r
+ }\r
+\r
+ } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
+\r
+ return NULL;\r
+}\r
--- /dev/null
+/** @file\r
+ The functions for Boot Maintainence Main menu.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+#include "FormGuid.h"\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {\r
+ {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ {\r
+ END_DEVICE_PATH_LENGTH,\r
+ 0\r
+ }\r
+ }\r
+};\r
+\r
+\r
+EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
+EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;\r
+EFI_GUID mFileExplorerGuid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+CHAR16 mBootMaintStorageName[] = L"BmData";\r
+CHAR16 mFileExplorerStorageName[] = L"FeData";\r
+\r
+/**\r
+ Init all memu.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+InitAllMenu (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Free up all Menu Option list.\r
+\r
+**/\r
+VOID\r
+FreeAllMenu (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Create string tokens for a menu from its help strings and display strings\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param HiiHandle Hii Handle of the package to be updated.\r
+ @param MenuOption The Menu whose string tokens need to be created\r
+\r
+ @retval EFI_SUCCESS String tokens created successfully\r
+ @retval others contain some errors\r
+**/\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN BM_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+\r
+ HiiLibNewString (\r
+ HiiHandle,\r
+ &NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->DisplayString\r
+ );\r
+\r
+ if (NULL == NewMenuEntry->HelpString) {\r
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+ } else {\r
+ HiiLibNewString (\r
+ HiiHandle,\r
+ &NewMenuEntry->HelpStringToken,\r
+ NewMenuEntry->HelpString\r
+ );\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
+ @param Progress On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results is filled with the requested values.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ BMM_CALLBACK_DATA *Private;\r
+\r
+ if (Request == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+ //\r
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+ Status = gHiiConfigRouting->BlockToConfig (\r
+ gHiiConfigRouting,\r
+ Request,\r
+ (UINT8 *) &Private->BmmFakeNvData,\r
+ BufferSize,\r
+ Results,\r
+ Progress\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
+ @retval EFI_DEVICE_ERROR The variable could not be saved.\r
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
+ @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ BMM_CALLBACK_DATA *Private;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
+ EFI_STATUS Status;\r
+ UINTN OldValue;\r
+ UINTN NewValue;\r
+ UINTN Number;\r
+ UINTN Pos;\r
+ UINTN Bit;\r
+ UINT16 NewValuePos;\r
+ UINT16 Index2;\r
+ UINT16 Index;\r
+ UINT8 *OldLegacyDev;\r
+ UINT8 *NewLegacyDev;\r
+ UINT8 *DisMap;\r
+ EFI_FORM_ID FormId;\r
+ UINTN BufferSize;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldValue = 0;\r
+ NewValue = 0;\r
+ Number = 0;\r
+ OldLegacyDev = NULL;\r
+ NewLegacyDev = NULL;\r
+ NewValuePos = 0;\r
+ DisMap = NULL;\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+ UpdatePageId (Private, QuestionId);\r
+\r
+ //\r
+ // Retrive uncommitted data from Form Browser\r
+ //\r
+ CurrentFakeNVMap = &Private->BmmFakeNvData;\r
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) CurrentFakeNVMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // need to be subtituded.\r
+ //\r
+ // Update Select FD/HD/CD/NET/BEV Order Form\r
+ //\r
+ if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
+ ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
+ (QuestionId >= LEGACY_FD_QUESTION_ID) &&\r
+ (QuestionId < (LEGACY_BEV_QUESTION_ID + 100)) )\r
+ ) {\r
+\r
+ DisMap = Private->BmmOldFakeNVData.DisableMap;\r
+\r
+ FormId = Private->BmmPreviousPageId;\r
+ if (FormId == FORM_BOOT_SETUP_ID) {\r
+ FormId = Private->BmmCurrentPageId;\r
+ }\r
+\r
+ switch (FormId) {\r
+ case FORM_SET_FD_ORDER_ID:\r
+ Number = (UINT16) LegacyFDMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyFD;\r
+ break;\r
+\r
+ case FORM_SET_HD_ORDER_ID:\r
+ Number = (UINT16) LegacyHDMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyHD;\r
+ break;\r
+\r
+ case FORM_SET_CD_ORDER_ID:\r
+ Number = (UINT16) LegacyCDMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyCD;\r
+ break;\r
+\r
+ case FORM_SET_NET_ORDER_ID:\r
+ Number = (UINT16) LegacyNETMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyNET;\r
+ break;\r
+\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ Number = (UINT16) LegacyBEVMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyBEV;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ //\r
+ // First, find the different position\r
+ // if there is change, it should be only one\r
+ //\r
+ for (Index = 0; Index < Number; Index++) {\r
+ if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
+ OldValue = OldLegacyDev[Index];\r
+ NewValue = NewLegacyDev[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != Number) {\r
+ //\r
+ // there is change, now process\r
+ //\r
+ if (0xFF == NewValue) {\r
+ //\r
+ // This item will be disable\r
+ // Just move the items behind this forward to overlap it\r
+ //\r
+ Pos = OldValue / 8;\r
+ Bit = 7 - (OldValue % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+ for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
+ NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
+ }\r
+\r
+ NewLegacyDev[Index2] = 0xFF;\r
+ } else {\r
+ for (Index2 = 0; Index2 < Number; Index2++) {\r
+ if (Index2 == Index) {\r
+ continue;\r
+ }\r
+\r
+ if (OldLegacyDev[Index2] == NewValue) {\r
+ //\r
+ // If NewValue is in OldLegacyDev array\r
+ // remember its old position\r
+ //\r
+ NewValuePos = Index2;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index2 != Number) {\r
+ //\r
+ // We will change current item to an existing item\r
+ // (It's hard to describe here, please read code, it's like a cycle-moving)\r
+ //\r
+ for (Index2 = NewValuePos; Index2 != Index;) {\r
+ if (NewValuePos < Index) {\r
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
+ Index2++;\r
+ } else {\r
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
+ Index2--;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
+ // so we should modify DisMap to reflect the change\r
+ //\r
+ Pos = NewValue / 8;\r
+ Bit = 7 - (NewValue % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));\r
+ if (0xFF != OldValue) {\r
+ //\r
+ // Because NewValue is a item that was disabled before\r
+ // so after changing the OldValue should be disabled\r
+ // actually we are doing a swap of enable-disable states of two items\r
+ //\r
+ Pos = OldValue / 8;\r
+ Bit = 7 - (OldValue % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // To prevent DISABLE appears in the middle of the list\r
+ // we should perform a re-ordering\r
+ //\r
+ Index = 0;\r
+ while (Index < Number) {\r
+ if (0xFF != NewLegacyDev[Index]) {\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ Index2 = Index;\r
+ Index2++;\r
+ while (Index2 < Number) {\r
+ if (0xFF != NewLegacyDev[Index2]) {\r
+ break;\r
+ }\r
+\r
+ Index2++;\r
+ }\r
+\r
+ if (Index2 < Number) {\r
+ NewLegacyDev[Index] = NewLegacyDev[Index2];\r
+ NewLegacyDev[Index2] = 0xFF;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ CopyMem (\r
+ OldLegacyDev,\r
+ NewLegacyDev,\r
+ Number\r
+ );\r
+ }\r
+ }\r
+\r
+ if (QuestionId < FILE_OPTION_OFFSET) {\r
+ if (QuestionId < CONFIG_OPTION_OFFSET) {\r
+ switch (QuestionId) {\r
+ case KEY_VALUE_BOOT_FROM_FILE:\r
+ Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
+\r
+ //\r
+ // Exit Bmm main formset to send File Explorer formset.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case FORM_BOOT_ADD_ID:\r
+ Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
+\r
+ //\r
+ // Exit Bmm main formset to send File Explorer formset.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case FORM_DRV_ADD_FILE_ID:\r
+ Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
+\r
+ //\r
+ // Exit Bmm main formset to send File Explorer formset.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case FORM_DRV_ADD_HANDLE_ID:\r
+ CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
+ UpdateDrvAddHandlePage (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_DEL_ID:\r
+ CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
+ UpdateBootDelPage (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_CHG_ID:\r
+ case FORM_DRV_CHG_ID:\r
+ UpdatePageBody (QuestionId, Private);\r
+ break;\r
+\r
+ case FORM_DRV_DEL_ID:\r
+ CleanUpPage (FORM_DRV_DEL_ID, Private);\r
+ UpdateDrvDelPage (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_NEXT_ID:\r
+ CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
+ UpdateBootNextPage (Private);\r
+ break;\r
+\r
+ case FORM_TIME_OUT_ID:\r
+ CleanUpPage (FORM_TIME_OUT_ID, Private);\r
+ UpdateTimeOutPage (Private);\r
+ break;\r
+\r
+ case FORM_RESET:\r
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+ return EFI_UNSUPPORTED;\r
+\r
+ case FORM_CON_IN_ID:\r
+ case FORM_CON_OUT_ID:\r
+ case FORM_CON_ERR_ID:\r
+ UpdatePageBody (QuestionId, Private);\r
+ break;\r
+\r
+ case FORM_CON_MODE_ID:\r
+ CleanUpPage (FORM_CON_MODE_ID, Private);\r
+ UpdateConModePage (Private);\r
+ break;\r
+\r
+ case FORM_CON_COM_ID:\r
+ CleanUpPage (FORM_CON_COM_ID, Private);\r
+ UpdateConCOMPage (Private);\r
+ break;\r
+\r
+ case FORM_SET_FD_ORDER_ID:\r
+ case FORM_SET_HD_ORDER_ID:\r
+ case FORM_SET_CD_ORDER_ID:\r
+ case FORM_SET_NET_ORDER_ID:\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ CleanUpPage (QuestionId, Private);\r
+ UpdateSetLegacyDeviceOrderPage (QuestionId, Private);\r
+ break;\r
+\r
+ case KEY_VALUE_SAVE_AND_EXIT:\r
+ case KEY_VALUE_NO_SAVE_AND_EXIT:\r
+\r
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
+ Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
+ DiscardChangeHandler (Private, CurrentFakeNVMap);\r
+ }\r
+\r
+ //\r
+ // Tell browser not to ask for confirmation of changes,\r
+ // since we have already applied or discarded.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {\r
+ Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);\r
+ Private->CurrentTerminal = Index2;\r
+\r
+ CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
+ UpdateTerminalPage (Private);\r
+\r
+ } else if (QuestionId >= HANDLE_OPTION_OFFSET) {\r
+ Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
+ ASSERT (NewMenuEntry != NULL);\r
+ Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
+\r
+ Private->MenuEntry = NewMenuEntry;\r
+ Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;\r
+\r
+ UpdateDriverAddHandleDescPage (Private);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Pass changed uncommitted data back to Form Browser\r
+ //\r
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) CurrentFakeNVMap, NULL);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Function handling request to apply changes for BMM pages.\r
+\r
+ @param Private Pointer to callback data buffer.\r
+ @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM\r
+ @param FormId ID of the form which has sent the request to apply change.\r
+\r
+ @retval EFI_SUCCESS Change successfully applied.\r
+ @retval Other Error occurs while trying to apply changes.\r
+\r
+**/\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,\r
+ IN EFI_FORM_ID FormId\r
+ )\r
+{\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ EFI_STATUS Status;\r
+ UINT16 Index;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (FormId) {\r
+ case FORM_SET_FD_ORDER_ID:\r
+ case FORM_SET_HD_ORDER_ID:\r
+ case FORM_SET_CD_ORDER_ID:\r
+ case FORM_SET_NET_ORDER_ID:\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ Var_UpdateBBSOption (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_DEL_ID:\r
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (UINT8)));\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
+ }\r
+\r
+ Var_DelBootOption ();\r
+ break;\r
+\r
+ case FORM_DRV_DEL_ID:\r
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (UINT8)));\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
+ }\r
+\r
+ Var_DelDriverOption ();\r
+ break;\r
+\r
+ case FORM_BOOT_CHG_ID:\r
+ Status = Var_UpdateBootOrder (Private);\r
+ break;\r
+\r
+ case FORM_DRV_CHG_ID:\r
+ Status = Var_UpdateDriverOrder (Private);\r
+ break;\r
+\r
+ case FORM_TIME_OUT_ID:\r
+ Status = gRT->SetVariable (\r
+ L"Timeout",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ sizeof (UINT16),\r
+ &(CurrentFakeNVMap->BootTimeOut)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
+ break;\r
+\r
+ case FORM_BOOT_NEXT_ID:\r
+ Status = Var_UpdateBootNext (Private);\r
+ break;\r
+\r
+ case FORM_CON_MODE_ID:\r
+ Status = Var_UpdateConMode (Private);\r
+ break;\r
+\r
+ case FORM_CON_COM_SETUP_ID:\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
+\r
+ ASSERT (NewMenuEntry != NULL);\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
+ ASSERT (CurrentFakeNVMap->COMBaudRate < (sizeof (BaudRateList) / sizeof (BaudRateList[0])));\r
+ NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
+ NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
+ ASSERT (CurrentFakeNVMap->COMDataRate < (sizeof (DataBitsList) / sizeof (DataBitsList[0])));\r
+ NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
+ NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
+ ASSERT (CurrentFakeNVMap->COMStopBits < (sizeof (StopBitsList) / sizeof (StopBitsList[0])));\r
+ NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
+ NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity;\r
+ ASSERT (CurrentFakeNVMap->COMParity < (sizeof (ParityList) / sizeof (ParityList[0])));\r
+ NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
+ NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType;\r
+\r
+ ChangeTerminalDevicePath (\r
+ NewTerminalContext->DevicePath,\r
+ FALSE\r
+ );\r
+\r
+ Var_UpdateConsoleInpOption ();\r
+ Var_UpdateConsoleOutOption ();\r
+ Var_UpdateErrorOutOption ();\r
+ break;\r
+\r
+ case FORM_CON_IN_ID:\r
+ ASSERT ((ConsoleInpMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));\r
+ for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
+ }\r
+\r
+ Var_UpdateConsoleInpOption ();\r
+ break;\r
+\r
+ case FORM_CON_OUT_ID:\r
+ ASSERT ((ConsoleOutMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));\r
+ for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
+ }\r
+\r
+ Var_UpdateConsoleOutOption ();\r
+ break;\r
+\r
+ case FORM_CON_ERR_ID:\r
+ ASSERT ((ConsoleErrMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));\r
+ for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
+ }\r
+\r
+ Var_UpdateErrorOutOption ();\r
+ break;\r
+\r
+ case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+ Status = Var_UpdateDriverOption (\r
+ Private,\r
+ Private->BmmHiiHandle,\r
+ CurrentFakeNVMap->DriverAddHandleDesc,\r
+ CurrentFakeNVMap->DriverAddHandleOptionalData,\r
+ CurrentFakeNVMap->DriverAddForceReconnect\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ BOpt_GetDriverOptions (Private);\r
+ CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+Error:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Discard all changes done to the BMM pages such as Boot Order change,\r
+ Driver order change.\r
+\r
+ @param Private The BMM context data.\r
+ @param CurrentFakeNVMap The current Fack NV Map.\r
+\r
+**/\r
+VOID\r
+DiscardChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap\r
+ )\r
+{\r
+ UINT16 Index;\r
+\r
+ switch (Private->BmmPreviousPageId) {\r
+ case FORM_BOOT_CHG_ID:\r
+ case FORM_DRV_CHG_ID:\r
+ CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
+ break;\r
+\r
+ case FORM_BOOT_DEL_ID:\r
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
+ }\r
+ break;\r
+\r
+ case FORM_DRV_DEL_ID:\r
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
+ }\r
+ break;\r
+\r
+ case FORM_BOOT_NEXT_ID:\r
+ CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
+ break;\r
+\r
+ case FORM_TIME_OUT_ID:\r
+ CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
+ break;\r
+\r
+ case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+ case FORM_DRV_ADD_FILE_ID:\r
+ case FORM_DRV_ADD_HANDLE_ID:\r
+ CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;\r
+ CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Initialize the Boot Maintenance Utitliy.\r
+\r
+\r
+ @retval EFI_SUCCESS utility ended successfully\r
+ @retval others contain some errors\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBM (\r
+ VOID\r
+ )\r
+{\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ BMM_CALLBACK_DATA *BmmCallbackInfo;\r
+ EFI_STATUS Status;\r
+ UINT8 *Ptr;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Create CallbackData structures for Driver Callback\r
+ //\r
+ BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
+ if (BmmCallbackInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Create LoadOption in BmmCallbackInfo for Driver Callback\r
+ //\r
+ Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
+ if (Ptr == NULL) {\r
+ FreePool (BmmCallbackInfo);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Initialize Bmm callback data.\r
+ //\r
+ BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
+ Ptr += sizeof (BM_LOAD_CONTEXT);\r
+\r
+ BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
+ Ptr += sizeof (BM_FILE_CONTEXT);\r
+\r
+ BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
+ Ptr += sizeof (BM_HANDLE_CONTEXT);\r
+\r
+ BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;\r
+\r
+ BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE;\r
+ BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;\r
+ BmmCallbackInfo->BmmConfigAccess.RouteConfig = FakeRouteConfig;\r
+ BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback;\r
+ BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;\r
+ BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;\r
+ BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig;\r
+ BmmCallbackInfo->FeConfigAccess.RouteConfig = FakeRouteConfig;\r
+ BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback;\r
+ BmmCallbackInfo->FeCurrentState = INACTIVE_STATE;\r
+ BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->BmmDriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &BmmCallbackInfo->BmmDriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &BmmCallbackInfo->BmmConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->FeDriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &BmmCallbackInfo->FeDriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &BmmCallbackInfo->FeConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Post our Boot Maint VFR binnary to the HII database.\r
+ //\r
+ PackageList = HiiLibPreparePackageList (2, &mBootMaintGuid, BmBin, BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ BmmCallbackInfo->BmmDriverHandle,\r
+ &BmmCallbackInfo->BmmHiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ //\r
+ // Post our File Explorer VFR binary to the HII database.\r
+ //\r
+ PackageList = HiiLibPreparePackageList (2, &mFileExplorerGuid, FEBin, BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ BmmCallbackInfo->FeDriverHandle,\r
+ &BmmCallbackInfo->FeHiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ //\r
+ // Allocate space for creation of Buffer\r
+ //\r
+ gUpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+ gUpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+ if (gUpdateData.Data == NULL) {\r
+ FreePool (BmmCallbackInfo->LoadContext);\r
+ FreePool (BmmCallbackInfo);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ InitializeStringDepository ();\r
+\r
+ InitAllMenu (BmmCallbackInfo);\r
+\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
+\r
+ UpdateBootDelPage (BmmCallbackInfo);\r
+ UpdateDrvDelPage (BmmCallbackInfo);\r
+\r
+ if (TerminalMenu.MenuNumber > 0) {\r
+ BmmCallbackInfo->CurrentTerminal = 0;\r
+ UpdateTerminalPage (BmmCallbackInfo);\r
+ }\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (!EFI_ERROR (Status)) {\r
+ RefreshUpdateData ();\r
+\r
+ //\r
+ // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
+ // in BootOption form: legacy FD/HD/CD/NET/BEV\r
+ //\r
+ CreateGotoOpCode (\r
+ FORM_SET_FD_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_FD_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_HD_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_HD_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_CD_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_CD_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_NET_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_NET_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_BEV_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_BEV_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ BmmCallbackInfo->BmmHiiHandle,\r
+ &mBootMaintGuid,\r
+ FORM_MAIN_ID,\r
+ FORM_BOOT_LEGACY_DEVICE_ID,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ //\r
+ // Dispatch BMM main formset and File Explorer formset.\r
+ //\r
+ FormSetDispatcher (BmmCallbackInfo);\r
+\r
+ //\r
+ // Remove our IFR data from HII database\r
+ //\r
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle);\r
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle);\r
+\r
+ CleanUpStringDepository ();\r
+\r
+ FreeAllMenu ();\r
+\r
+ FreePool (BmmCallbackInfo->LoadContext);\r
+ FreePool (BmmCallbackInfo);\r
+ FreePool (gUpdateData.Data);\r
+ gUpdateData.Data = NULL;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Initialized all Menu Option List.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+InitAllMenu (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ InitializeListHead (&BootOptionMenu.Head);\r
+ InitializeListHead (&DriverOptionMenu.Head);\r
+ BOpt_GetBootOptions (CallbackData);\r
+ BOpt_GetDriverOptions (CallbackData);\r
+ BOpt_GetLegacyOptions ();\r
+ InitializeListHead (&FsOptionMenu.Head);\r
+ BOpt_FindDrivers ();\r
+ InitializeListHead (&DirectoryMenu.Head);\r
+ InitializeListHead (&ConsoleInpMenu.Head);\r
+ InitializeListHead (&ConsoleOutMenu.Head);\r
+ InitializeListHead (&ConsoleErrMenu.Head);\r
+ InitializeListHead (&TerminalMenu.Head);\r
+ LocateSerialIo ();\r
+ GetAllConsoles ();\r
+}\r
+\r
+/**\r
+ Free up all Menu Option list.\r
+\r
+**/\r
+VOID\r
+FreeAllMenu (\r
+ VOID\r
+ )\r
+{\r
+ BOpt_FreeMenu (&DirectoryMenu);\r
+ BOpt_FreeMenu (&FsOptionMenu);\r
+ BOpt_FreeMenu (&BootOptionMenu);\r
+ BOpt_FreeMenu (&DriverOptionMenu);\r
+ BOpt_FreeMenu (&DriverMenu);\r
+ BOpt_FreeLegacyOptions ();\r
+ FreeAllConsoles ();\r
+}\r
+\r
+/**\r
+ Intialize all the string depositories.\r
+\r
+**/\r
+VOID\r
+InitializeStringDepository (\r
+ VOID\r
+ )\r
+{\r
+ STRING_DEPOSITORY *StringDepository;\r
+ StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
+ FileOptionStrDepository = StringDepository++;\r
+ ConsoleOptionStrDepository = StringDepository++;\r
+ BootOptionStrDepository = StringDepository++;\r
+ BootOptionHelpStrDepository = StringDepository++;\r
+ DriverOptionStrDepository = StringDepository++;\r
+ DriverOptionHelpStrDepository = StringDepository++;\r
+ TerminalStrDepository = StringDepository;\r
+}\r
+\r
+/**\r
+ Fetch a usable string node from the string depository and return the string token.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param StringDepository The string repository.\r
+\r
+ @retval EFI_STRING_ID String token.\r
+\r
+**/\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN STRING_DEPOSITORY *StringDepository\r
+ )\r
+{\r
+ STRING_LIST_NODE *CurrentListNode;\r
+ STRING_LIST_NODE *NextListNode;\r
+\r
+ CurrentListNode = StringDepository->CurrentNode;\r
+\r
+ if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
+ //\r
+ // Fetch one reclaimed node from the list.\r
+ //\r
+ NextListNode = StringDepository->CurrentNode->Next;\r
+ } else {\r
+ //\r
+ // If there is no usable node in the list, update the list.\r
+ //\r
+ NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));\r
+ ASSERT (NextListNode != NULL);\r
+ HiiLibNewString (CallbackData->BmmHiiHandle, &(NextListNode->StringToken), L" ");\r
+ ASSERT (NextListNode->StringToken != 0);\r
+\r
+ StringDepository->TotalNodeNumber++;\r
+\r
+ if (NULL == CurrentListNode) {\r
+ StringDepository->ListHead = NextListNode;\r
+ } else {\r
+ CurrentListNode->Next = NextListNode;\r
+ }\r
+ }\r
+\r
+ StringDepository->CurrentNode = NextListNode;\r
+\r
+ return StringDepository->CurrentNode->StringToken;\r
+}\r
+\r
+/**\r
+ Reclaim string depositories by moving the current node pointer to list head..\r
+\r
+**/\r
+VOID\r
+ReclaimStringDepository (\r
+ VOID\r
+ )\r
+{\r
+ UINTN DepositoryIndex;\r
+ STRING_DEPOSITORY *StringDepository;\r
+\r
+ StringDepository = FileOptionStrDepository;\r
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+ StringDepository->CurrentNode = StringDepository->ListHead;\r
+ StringDepository++;\r
+ }\r
+}\r
+\r
+/**\r
+ Release resource for all the string depositories.\r
+\r
+**/\r
+VOID\r
+CleanUpStringDepository (\r
+ VOID\r
+ )\r
+{\r
+ UINTN NodeIndex;\r
+ UINTN DepositoryIndex;\r
+ STRING_LIST_NODE *CurrentListNode;\r
+ STRING_LIST_NODE *NextListNode;\r
+ STRING_DEPOSITORY *StringDepository;\r
+\r
+ //\r
+ // Release string list nodes.\r
+ //\r
+ StringDepository = FileOptionStrDepository;\r
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+ CurrentListNode = StringDepository->ListHead;\r
+ for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
+ NextListNode = CurrentListNode->Next;\r
+ FreePool (CurrentListNode);\r
+ CurrentListNode = NextListNode;\r
+ }\r
+\r
+ StringDepository++;\r
+ }\r
+ //\r
+ // Release string depository.\r
+ //\r
+ FreePool (FileOptionStrDepository);\r
+}\r
+\r
+/**\r
+ Start boot maintenance manager\r
+\r
+ @retval EFI_SUCCESS If BMM is invoked successfully.\r
+ @return Other value if BMM return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY BdsBootOptionList;\r
+\r
+ InitializeListHead (&BdsBootOptionList);\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+ //\r
+ // Have chance to enumerate boot device\r
+ //\r
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+ //\r
+ // Init the BMM\r
+ //\r
+ Status = InitializeBM ();\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Dispatch BMM formset and FileExplorer formset.\r
+\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS If function complete successfully.\r
+ @return Other value if the Setup Browser process BMM's pages and\r
+ return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+\r
+ while (TRUE) {\r
+ UpdatePageId (CallbackData, FORM_MAIN_ID);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &CallbackData->BmmHiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ ReclaimStringDepository ();\r
+\r
+ //\r
+ // When this Formset returns, check if we are going to explore files.\r
+ //\r
+ if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
+ UpdateFileExplorer (CallbackData, 0);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &CallbackData->FeHiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ CallbackData->FeCurrentState = INACTIVE_STATE;\r
+ CallbackData->FeDisplayContext = UNKNOWN_CONTEXT;\r
+ ReclaimStringDepository ();\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Deletete the Boot Option from EFI Variable. The Boot Order Arrray\r
+ is also updated.\r
+\r
+ @param OptionNumber The number of Boot option want to be deleted.\r
+ @param BootOrder The Boot Order array.\r
+ @param BootOrderSize The size of the Boot Order Array.\r
+\r
+ @return Other value if the Boot Option specified by OptionNumber is not deleteed succesfully.\r
+ @retval EFI_SUCCESS If function return successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+ IN UINTN OptionNumber,\r
+ IN OUT UINT16 *BootOrder,\r
+ IN OUT UINTN *BootOrderSize\r
+ )\r
+{\r
+ UINT16 BootOption[100];\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN Index2Del;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2Del = 0;\r
+\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
+ Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);\r
+ \r
+ //\r
+ // adjust boot order array\r
+ //\r
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
+ if (BootOrder[Index] == OptionNumber) {\r
+ Index2Del = Index;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != *BootOrderSize / sizeof (UINT16)) {\r
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {\r
+ if (Index >= Index2Del) {\r
+ BootOrder[Index] = BootOrder[Index + 1];\r
+ }\r
+ }\r
+\r
+ *BootOrderSize -= sizeof (UINT16);\r
+ }\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+\r
--- /dev/null
+/** @file\r
+ Header file for boot maintenance module.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BOOT_MAINT_H_\r
+#define _BOOT_MAINT_H_\r
+\r
+#include "Bds.h"\r
+#include "BBSsupport.h"\r
+#include "FormGuid.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder"\r
+\r
+#define VAR_CON_OUT_MODE L"ConOutMode"\r
+\r
+///\r
+/// Guid of a NV Variable which store the information about the\r
+/// FD/HD/CD/NET/BEV order\r
+///\r
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \\r
+ { \\r
+ 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \\r
+ }\r
+\r
+//\r
+// String Contant\r
+//\r
+#define STR_FLOPPY L"Floppy Drive #%02x"\r
+#define STR_HARDDISK L"HardDisk Drive #%02x"\r
+#define STR_CDROM L"ATAPI CDROM Drive #%02x"\r
+#define STR_NET L"NET Drive #%02x"\r
+#define STR_BEV L"BEV Drive #%02x"\r
+#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x"\r
+#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x"\r
+#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x"\r
+#define STR_NET_HELP L"NET Drive #%02x"\r
+#define STR_BEV_HELP L"BEV Drive #%02x"\r
+\r
+//\r
+// Variable created with this flag will be "Efi:...."\r
+//\r
+#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR 480\r
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)\r
+\r
+extern EFI_GUID mBootMaintGuid;\r
+extern EFI_GUID mFileExplorerGuid;\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 BmBin[];\r
+extern UINT8 FEBin[];\r
+\r
+//\r
+// Below are the number of options in Baudrate, Databits,\r
+// Parity and Stopbits selection for serial ports.\r
+//\r
+#define BM_COM_ATTR_BUADRATE 19\r
+#define BM_COM_ATTR_DATABITS 4\r
+#define BM_COM_ATTR_PARITY 5\r
+#define BM_COM_ATTR_STOPBITS 3\r
+\r
+//\r
+// Callback function helper\r
+//\r
+#define BMM_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('C', 'b', 'c', 'k')\r
+#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+//\r
+// Enumeration type definition\r
+//\r
+typedef UINT8 BBS_TYPE;\r
+\r
+typedef enum {\r
+ PC_ANSI = 0,\r
+ VT_100,\r
+ VT_100_PLUS,\r
+ VT_UTF8\r
+} TYPE_OF_TERMINAL;\r
+\r
+typedef enum {\r
+ COM1 = 0,\r
+ COM2,\r
+ UNKNOW_COM\r
+} TYPE_OF_COM;\r
+\r
+typedef enum {\r
+ CONIN = 0,\r
+ CONOUT,\r
+ CONERR,\r
+ UNKNOWN_CON\r
+} TYPE_OF_CON;\r
+\r
+typedef enum {\r
+ BAUDRATE = 0,\r
+ DATABITS,\r
+ PARITY,\r
+ STOPBITS,\r
+ UNKNOW_ATTR\r
+} TYPE_OF_ATTRIBUTE;\r
+\r
+typedef enum {\r
+ MANNER_GOTO = 0,\r
+ MANNER_CHECK,\r
+ MANNER_ONEOF,\r
+ MANNER_USER_DEFINE\r
+} TYPE_OF_UPATE_MANNER;\r
+\r
+typedef enum {\r
+ INACTIVE_STATE = 0,\r
+ BOOT_FROM_FILE_STATE,\r
+ ADD_BOOT_OPTION_STATE,\r
+ ADD_DRIVER_OPTION_STATE,\r
+ UNKNOWN_STATE\r
+} FILE_EXPLORER_STATE;\r
+\r
+typedef enum {\r
+ FILE_SYSTEM,\r
+ DIRECTORY,\r
+ UNKNOWN_CONTEXT\r
+} FILE_EXPLORER_DISPLAY_CONTEXT;\r
+\r
+//\r
+// All of the signatures that will be used in list structure\r
+//\r
+#define BM_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u')\r
+#define BM_LOAD_OPTION_SIGNATURE SIGNATURE_32 ('l', 'o', 'a', 'd')\r
+#define BM_CONSOLE_OPTION_SIGNATURE SIGNATURE_32 ('c', 'n', 's', 'l')\r
+#define BM_FILE_OPTION_SIGNATURE SIGNATURE_32 ('f', 'i', 'l', 'e')\r
+#define BM_HANDLE_OPTION_SIGNATURE SIGNATURE_32 ('h', 'n', 'd', 'l')\r
+#define BM_TERMINAL_OPTION_SIGNATURE SIGNATURE_32 ('t', 'r', 'm', 'l')\r
+#define BM_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r')\r
+\r
+#define BM_LOAD_CONTEXT_SELECT 0x0\r
+#define BM_CONSOLE_CONTEXT_SELECT 0x1\r
+#define BM_FILE_CONTEXT_SELECT 0x2\r
+#define BM_HANDLE_CONTEXT_SELECT 0x3\r
+#define BM_TERMINAL_CONTEXT_SELECT 0x5\r
+\r
+#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6\r
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7\r
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8\r
+#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9\r
+\r
+//\r
+// Buffer size for update data\r
+//\r
+#define UPDATE_DATA_SIZE 0x100000\r
+\r
+//\r
+// Namespace of callback keys used in display and file system navigation\r
+//\r
+#define MAX_BBS_OFFSET 0xE000\r
+#define NET_OPTION_OFFSET 0xD800\r
+#define BEV_OPTION_OFFSET 0xD000\r
+#define FD_OPTION_OFFSET 0xC000\r
+#define HD_OPTION_OFFSET 0xB000\r
+#define CD_OPTION_OFFSET 0xA000\r
+#define FILE_OPTION_OFFSET 0x8000\r
+#define FILE_OPTION_MASK 0x7FFF\r
+#define HANDLE_OPTION_OFFSET 0x7000\r
+#define CONSOLE_OPTION_OFFSET 0x6000\r
+#define TERMINAL_OPTION_OFFSET 0x5000\r
+#define CONFIG_OPTION_OFFSET 0x1200\r
+#define KEY_VALUE_OFFSET 0x1100\r
+#define FORM_ID_OFFSET 0x1000\r
+\r
+//\r
+// VarOffset that will be used to create question\r
+// all these values are computed from the structure\r
+// defined below\r
+//\r
+#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)))\r
+\r
+//\r
+// Question Id of Zero is invalid, so add an offset to it\r
+//\r
+#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET)\r
+\r
+#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut)\r
+#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext)\r
+#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate)\r
+#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate)\r
+#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits)\r
+#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity)\r
+#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)\r
+#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate)\r
+#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate)\r
+#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits)\r
+#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity)\r
+#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive)\r
+#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect)\r
+#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1)\r
+#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2)\r
+#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode)\r
+#define CON_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleCheck)\r
+#define OPTION_ORDER_VAR_OFFSET VAR_OFFSET (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate)\r
+#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate)\r
+#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits)\r
+#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity)\r
+#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType)\r
+#define LEGACY_FD_VAR_OFFSET VAR_OFFSET (LegacyFD)\r
+#define LEGACY_HD_VAR_OFFSET VAR_OFFSET (LegacyHD)\r
+#define LEGACY_CD_VAR_OFFSET VAR_OFFSET (LegacyCD)\r
+#define LEGACY_NET_VAR_OFFSET VAR_OFFSET (LegacyNET)\r
+#define LEGACY_BEV_VAR_OFFSET VAR_OFFSET (LegacyBEV)\r
+\r
+#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut)\r
+#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext)\r
+#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate)\r
+#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate)\r
+#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits)\r
+#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity)\r
+#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)\r
+#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate)\r
+#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate)\r
+#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits)\r
+#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity)\r
+#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive)\r
+#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect)\r
+#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1)\r
+#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2)\r
+#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode)\r
+#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck)\r
+#define OPTION_ORDER_QUESTION_ID QUESTION_ID (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate)\r
+#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate)\r
+#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits)\r
+#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity)\r
+#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType)\r
+#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD)\r
+#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD)\r
+#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD)\r
+#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET)\r
+#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV)\r
+\r
+#define STRING_DEPOSITORY_NUMBER 8\r
+\r
+///\r
+/// Serial Ports attributes, first one is the value for\r
+/// return from callback function, stringtoken is used to\r
+/// display the value properly\r
+///\r
+typedef struct {\r
+ UINTN Value;\r
+ UINT16 StringToken;\r
+} COM_ATTR;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ BBS_TYPE BbsType;\r
+ ///\r
+ /// Length = sizeof (UINT16) + SIZEOF (Data)\r
+ ///\r
+ UINT16 Length;\r
+ UINT16 *Data;\r
+} BM_LEGACY_DEV_ORDER_CONTEXT;\r
+#pragma pack()\r
+\r
+typedef struct {\r
+ UINT64 BaudRate;\r
+ UINT8 DataBits;\r
+ UINT8 Parity;\r
+ UINT8 StopBits;\r
+\r
+ UINT8 BaudRateIndex;\r
+ UINT8 DataBitsIndex;\r
+ UINT8 ParityIndex;\r
+ UINT8 StopBitsIndex;\r
+\r
+ UINT8 IsConIn;\r
+ UINT8 IsConOut;\r
+ UINT8 IsStdErr;\r
+ UINT8 TerminalType;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+} BM_TERMINAL_CONTEXT;\r
+\r
+typedef struct {\r
+ BOOLEAN IsBootNext;\r
+ BOOLEAN LoadOptionModified;\r
+ BOOLEAN Deleted;\r
+\r
+ BOOLEAN IsLegacy;\r
+ BOOLEAN IsActive;\r
+ BOOLEAN ForceReconnect;\r
+ UINTN OptionalDataSize;\r
+\r
+ UINTN LoadOptionSize;\r
+ UINT8 *LoadOption;\r
+\r
+ UINT32 Attributes;\r
+ UINT16 FilePathListLength;\r
+ UINT16 *Description;\r
+ EFI_DEVICE_PATH_PROTOCOL *FilePathList;\r
+ UINT8 *OptionalData;\r
+\r
+ UINT16 BbsIndex;\r
+} BM_LOAD_CONTEXT;\r
+\r
+typedef struct {\r
+ BBS_TABLE *BbsTable;\r
+ UINTN Index;\r
+ UINTN BbsCount;\r
+ UINT16 *Description;\r
+} BM_LEGACY_DEVICE_CONTEXT;\r
+\r
+typedef struct {\r
+\r
+ BOOLEAN IsActive;\r
+\r
+ BOOLEAN IsTerminal;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+} BM_CONSOLE_CONTEXT;\r
+\r
+typedef struct {\r
+ UINTN Column;\r
+ UINTN Row;\r
+} CONSOLE_OUT_MODE;\r
+\r
+typedef struct {\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_FILE_HANDLE FHandle;\r
+ UINT16 *FileName;\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL *Info;\r
+\r
+ BOOLEAN IsRoot;\r
+ BOOLEAN IsDir;\r
+ BOOLEAN IsRemovableMedia;\r
+ BOOLEAN IsLoadFile;\r
+ BOOLEAN IsBootLegacy;\r
+} BM_FILE_CONTEXT;\r
+\r
+typedef struct {\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+} BM_HANDLE_CONTEXT;\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Head;\r
+ UINTN MenuNumber;\r
+} BM_MENU_OPTION;\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ UINTN OptionNumber;\r
+ UINT16 *DisplayString;\r
+ UINT16 *HelpString;\r
+ EFI_STRING_ID DisplayStringToken;\r
+ EFI_STRING_ID HelpStringToken;\r
+ UINTN ContextSelection;\r
+ VOID *VariableContext;\r
+} BM_MENU_ENTRY;\r
+\r
+typedef struct {\r
+ //\r
+ // Shared callback data.\r
+ //\r
+ UINTN Signature;\r
+\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ BM_HANDLE_CONTEXT *HandleContext;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ BM_LOAD_CONTEXT *LoadContext;\r
+ BM_TERMINAL_CONTEXT *TerminalContext;\r
+ UINTN CurrentTerminal;\r
+ BBS_TYPE BbsType;\r
+\r
+ //\r
+ // BMM main formset callback data.\r
+ //\r
+ EFI_HII_HANDLE BmmHiiHandle;\r
+ EFI_HANDLE BmmDriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;\r
+ EFI_FORM_ID BmmCurrentPageId;\r
+ EFI_FORM_ID BmmPreviousPageId;\r
+ BOOLEAN BmmAskSaveOrNot;\r
+ BMM_FAKE_NV_DATA BmmFakeNvData;\r
+ BMM_FAKE_NV_DATA BmmOldFakeNVData;\r
+\r
+ //\r
+ // File explorer formset callback data.\r
+ //\r
+ EFI_HII_HANDLE FeHiiHandle;\r
+ EFI_HANDLE FeDriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;\r
+ FILE_EXPLORER_STATE FeCurrentState;\r
+ FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext;\r
+ FILE_EXPLORER_NV_DATA FeFakeNvData;\r
+} BMM_CALLBACK_DATA;\r
+\r
+typedef struct _STRING_LIST_NODE {\r
+ EFI_STRING_ID StringToken;\r
+ struct _STRING_LIST_NODE *Next;\r
+} STRING_LIST_NODE;\r
+\r
+typedef struct _STRING_DEPOSITORY {\r
+ UINTN TotalNodeNumber;\r
+ STRING_LIST_NODE *CurrentNode;\r
+ STRING_LIST_NODE *ListHead;\r
+} STRING_DEPOSITORY;\r
+\r
+//\r
+// #pragma pack()\r
+//\r
+// For initializing File System menu\r
+//\r
+\r
+/**\r
+ This function build the FsOptionMenu list which records all\r
+ available file system in the system. They includes all instances\r
+ of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
+ and all type of legacy boot device.\r
+\r
+ @param CallbackData BMM context data\r
+\r
+ @retval EFI_SUCCESS Success find the file system\r
+ @retval EFI_OUT_OF_RESOURCES Can not create menu entry\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Find files under current directory\r
+ All files and sub-directories in current directory\r
+ will be stored in DirectoryMenu for future use.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param MenuEntry The Menu Entry.\r
+\r
+ @retval EFI_SUCCESS Get files from current dir successfully.\r
+ @return Other value if can't get files from current dir.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN BM_MENU_ENTRY *MenuEntry\r
+ );\r
+\r
+/**\r
+\r
+ Find drivers that will be added as Driver#### variables from handles\r
+ in current system environment\r
+ All valid handles in the system except those consume SimpleFs, LoadFile\r
+ are stored in DriverMenu for future use.\r
+\r
+ @retval EFI_SUCCESS The function complets successfully.\r
+ @return Other value if failed to build the DriverMenu.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+ VOID\r
+ );\r
+\r
+/**\r
+\r
+ Build the BootOptionMenu according to BootOrder Variable.\r
+ This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @return The number of the Var Boot####.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+\r
+ Build up all DriverOptionMenu\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @return EFI_SUCESS The functin completes successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
+ \r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+\r
+/**\r
+ Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Free out resouce allocated from Legacy Boot Options.\r
+\r
+**/\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Free resources allocated in Allocate Rountine.\r
+\r
+ @param FreeMenu Menu to be freed\r
+\r
+**/\r
+VOID\r
+BOpt_FreeMenu (\r
+ BM_MENU_OPTION *FreeMenu\r
+ );\r
+\r
+\r
+/**\r
+\r
+ Append file name to existing file name.\r
+\r
+ @param Str1 The existing file name\r
+ @param Str2 The file name to be appended\r
+\r
+ @return Allocate a new string to hold the appended result.\r
+ Caller is responsible to free the returned string.\r
+\r
+**/\r
+CHAR16*\r
+BOpt_AppendFileName (\r
+ IN CHAR16 *Str1,\r
+ IN CHAR16 *Str2\r
+ );\r
+\r
+/**\r
+\r
+ Check whether current FileName point to a valid\r
+ Efi Image File.\r
+\r
+ @param FileName File need to be checked.\r
+\r
+ @retval TRUE Is Efi Image\r
+ @retval FALSE Not a valid Efi Image\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+ IN UINT16 *FileName\r
+ );\r
+\r
+/**\r
+\r
+ Check whether current FileName point to a valid Efi Application\r
+\r
+ @param Dir Pointer to current Directory\r
+ @param FileName Pointer to current File name.\r
+\r
+ @retval TRUE Is a valid Efi Application\r
+ @retval FALSE not a valid Efi Application\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+ IN EFI_FILE_HANDLE Dir,\r
+ IN UINT16 *FileName\r
+ );\r
+\r
+/**\r
+\r
+ Get the Option Number that has not been allocated for use.\r
+\r
+ @return The available Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+ VOID\r
+ );\r
+\r
+/**\r
+\r
+ Get the Option Number that is not in use.\r
+\r
+ @return The unused Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Create a menu entry give a Menu type.\r
+\r
+ @param MenuType The Menu type to be created.\r
+\r
+\r
+ @retval NULL If failed to create the menu.\r
+ @return The menu.\r
+\r
+**/\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+ UINTN MenuType\r
+ );\r
+\r
+/**\r
+ Free up all resource allocated for a BM_MENU_ENTRY.\r
+\r
+ @param MenuEntry A pointer to BM_MENU_ENTRY.\r
+\r
+**/\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+ BM_MENU_ENTRY *MenuEntry\r
+ );\r
+\r
+/**\r
+ Get the Menu Entry from the list in Menu Entry List.\r
+\r
+ If MenuNumber is great or equal to the number of Menu\r
+ Entry in the list, then ASSERT.\r
+\r
+ @param MenuOption The Menu Entry List to read the menu entry.\r
+ @param MenuNumber The index of Menu Entry.\r
+\r
+ @return The Menu Entry.\r
+\r
+**/\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+ BM_MENU_OPTION *MenuOption,\r
+ UINTN MenuNumber\r
+ );\r
+\r
+//\r
+// Locate all serial io devices for console\r
+//\r
+/**\r
+ Build a list containing all serial devices.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_UNSUPPORTED No serial ports present.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateSerialIo (\r
+ VOID\r
+ );\r
+\r
+//\r
+// Initializing Console menu\r
+//\r
+/**\r
+ Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+ @retval EFI_SUCCESS The function always complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAllConsoles(\r
+ VOID\r
+ );\r
+\r
+//\r
+// Get current mode information\r
+//\r
+/**\r
+ Get mode number according to column and row\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+GetConsoleOutMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// Cleaning up console menu\r
+//\r
+/**\r
+ Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+ @retval EFI_SUCCESS The function always complete successfully.\r
+**/\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Update the device path that describing a terminal device\r
+ based on the new BaudRate, Data Bits, parity and Stop Bits\r
+ set.\r
+\r
+ @param DevicePath The devicepath protocol instance wanted to be updated.\r
+\r
+**/\r
+VOID\r
+ChangeVariableDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+\r
+/**\r
+ Update the multi-instance device path of Terminal Device based on\r
+ the global TerminalMenu. If ChangeTernimal is TRUE, the terminal \r
+ device path in the Terminal Device in TerminalMenu is also updated.\r
+\r
+ @param DevicePath The multi-instance device path.\r
+ @param ChangeTerminal TRUE, then device path in the Terminal Device \r
+ in TerminalMenu is also updated; FALSE, no update.\r
+\r
+ @return EFI_SUCCESS The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN BOOLEAN ChangeTerminal\r
+ );\r
+\r
+//\r
+// Variable operation by menu selection\r
+//\r
+/**\r
+ This function create a currently loaded Boot Option from \r
+ the BMM. It then appends this Boot Option to the end of \r
+ the "BootOrder" list. It also append this Boot Opotion to the end\r
+ of BootOptionMenu.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param NvRamMap The file explorer formset internal state.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+ @retval EFI_SUCCESS If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN FILE_EXPLORER_NV_DATA *NvRamMap\r
+ );\r
+\r
+/**\r
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+ After deleting this boot option, call Var_ChangeBootOrder to\r
+ make sure BootOrder is in valid state.\r
+\r
+ @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to \r
+ BM_LOAD_CONTEXT marked for deletion is deleted\r
+ @return Others If failed to update the "BootOrder" variable after deletion. \r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+ Since some are missing but in BootOrder, while some are present but are\r
+ not reflected by BootOrder. Then a function rebuild BootOrder from\r
+ scratch by content from BootOptionMenu is needed.\r
+\r
+ @retval EFI_SUCCESS The boot order is updated successfully.\r
+ @return other than EFI_SUCCESS if failed to change the "BootOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function create a currently loaded Drive Option from \r
+ the BMM. It then appends this Driver Option to the end of \r
+ the "DriverOrder" list. It append this Driver Opotion to the end\r
+ of DriverOptionMenu.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param HiiHandle The HII handle associated with the BMM formset.\r
+ @param DescriptionData The description of this driver option.\r
+ @param OptionalData The optional load option.\r
+ @param ForceReconnect If to force reconnect.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+ @retval EFI_SUCCESS If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN UINT16 *DescriptionData,\r
+ IN UINT16 *OptionalData,\r
+ IN UINT8 ForceReconnect\r
+ );\r
+\r
+/**\r
+ Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+ After deleting this Driver option, call Var_ChangeDriverOrder to\r
+ make sure DriverOrder is in valid state.\r
+\r
+ @retval EFI_SUCCESS Load Option is successfully updated.\r
+ @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI\r
+ Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ After any operation on Driver####, there will be a discrepancy in\r
+ DriverOrder. Since some are missing but in DriverOrder, while some\r
+ are present but are not reflected by DriverOrder. Then a function\r
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
+ needed.\r
+\r
+ @retval EFI_SUCCESS The driver order is updated successfully.\r
+ @return other than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function delete and build multi-instance device path ConIn\r
+ console device.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function delete and build multi-instance device path ConOut console device.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function delete and build multi-instance device path ErrOut console device.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Update the device path of "ConOut", "ConIn" and "ErrOut" based on the new BaudRate, Data Bits, \r
+ parity and stop Bits set.\r
+\r
+**/\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function update the "BootNext" EFI Variable. If there is no "BootNex" specified in BMM, \r
+ this EFI Variable is deleted.\r
+ It also update the BMM context data specified the "BootNext" value.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ This function update the "BootOrder" EFI Variable based on BMM Formset's NV map. It then refresh \r
+ BootOptionMenu with the new "BootOrder" list.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
+ @return not The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ This function update the "DriverOrder" EFI Variable based on\r
+ BMM Formset's NV map. It then refresh DriverOptionMenu\r
+ with the new "DriverOrder" list.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable\r
+ is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
+ is also updated.\r
+\r
+ @param CallbackData The context data for BMM.\r
+\r
+ @return EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Update the Text Mode of Console.\r
+\r
+ @param CallbackData The context data for BMM.\r
+\r
+ @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
+ @return Other value if the Text Mode of Console is not updated.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// Following are page create and refresh functions\r
+//\r
+/**\r
+ Refresh the global UpdateData structure.\r
+\r
+**/\r
+VOID\r
+RefreshUpdateData (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Clean up the dynamic opcode at label and form specified by\r
+ both LabelId. \r
+\r
+ @param LabelId It is both the Form ID and Label ID for\r
+ opcode deletion.\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+CleanUpPage (\r
+ IN UINT16 LabelId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create a lit of boot option from global BootOptionMenu. It\r
+ allow user to delete the boot option.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateBootDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create a lit of driver option from global DriverMenu.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create a lit of driver option from global DriverOptionMenu. It\r
+ allow user to delete the driver option.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateDrvDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Prepare the page to allow user to add description for a Driver Option.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Dispatch the correct update page function to call based on the UpdatePageId.\r
+\r
+ @param UpdatePageId The form ID.\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdatePageBody (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create the dynamic page to allow user to set the "BootNext" vaule.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateBootNextPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create the dynamic page to allow user to set the "TimeOut" vaule.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateTimeOutPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,\r
+ Parity, Stop Bits, Terminal Type.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateTerminalPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Refresh the text mode page\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateConModePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create a list of Goto Opcode for all terminal devices logged\r
+ by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateConCOMPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Create a dynamic page so that Legacy Device boot order\r
+ can be set for specified device type.\r
+\r
+ @param UpdatePageId The form ID. It also spefies the legacy device type.\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+\r
+/**\r
+ Function opens and returns a file handle to the root directory of a volume.\r
+\r
+ @param DeviceHandle A handle for a device\r
+ @return A valid file handle or NULL is returned\r
+**/\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+ IN EFI_HANDLE DeviceHandle\r
+ );\r
+\r
+/**\r
+ Function gets the file system information from an open file descriptor,\r
+ and stores it in a buffer allocated from pool.\r
+\r
+ @param FHand The file handle.\r
+\r
+ @return A pointer to a buffer with file information.\r
+ NULL is returned if failed to get Vaolume Label Info.\r
+**/\r
+EFI_FILE_SYSTEM_VOLUME_LABEL *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ );\r
+\r
+/**\r
+\r
+ Function gets the file information from an open file descriptor, and stores it\r
+ in a buffer allocated from pool.\r
+\r
+ @param FHand File Handle.\r
+\r
+ @return A pointer to a buffer with file information or NULL is returned\r
+\r
+**/\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ );\r
+\r
+/**\r
+ This function converts an input device structure to a Unicode string.\r
+\r
+ @param DevPath A pointer to the device path structure.\r
+\r
+ @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+DevicePathToStr (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+/**\r
+ Find the first instance of this Protocol in the system and return it's interface.\r
+\r
+ @param ProtocolGuid Provides the protocol to search for\r
+ @param Interface On return, a pointer to the first interface\r
+ that matches ProtocolGuid\r
+\r
+ @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found\r
+ @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ OUT VOID **Interface\r
+ );\r
+\r
+/**\r
+ Adjusts the size of a previously allocated buffer.\r
+\r
+ @param OldPool A pointer to the buffer whose size is being adjusted.\r
+ @param OldSize The size of the current buffer.\r
+ @param NewSize The size of the new buffer.\r
+\r
+ @return The newly allocated buffer. if NULL, allocation failed.\r
+\r
+**/\r
+VOID*\r
+EfiReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ );\r
+\r
+/**\r
+ Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
+ buffer, and the size of the buffer. If failure return NULL.\r
+\r
+ @param Name String part of EFI variable name\r
+ @param VendorGuid GUID part of EFI variable name\r
+ @param VarSize Returns the size of the EFI variable that was read\r
+\r
+ @return Dynamically allocated memory that contains a copy of the EFI variable.\r
+ @return Caller is responsible freeing the buffer.\r
+ @retval NULL Variable was not read\r
+\r
+**/\r
+VOID *\r
+BdsLibGetVariableAndSize (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VarSize\r
+ );\r
+\r
+/**\r
+ Function deletes the variable specified by VarName and VarGuid.\r
+\r
+\r
+ @param VarName A Null-terminated Unicode string that is\r
+ the name of the vendor's variable.\r
+ \r
+ @param VarGuid A unique identifier for the vendor.\r
+\r
+ @retval EFI_SUCCESS The variable was found and removed\r
+ @retval EFI_UNSUPPORTED The variable store was inaccessible\r
+ @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available\r
+ @retval EFI_NOT_FOUND The variable was not found\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VarGuid\r
+ );\r
+\r
+/**\r
+ Duplicate a string.\r
+\r
+ @param Src The source.\r
+\r
+ @return A new string which is duplicated copy of the source.\r
+ @retval NULL If there is not enough memory.\r
+\r
+**/\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+ IN CHAR16 *Src\r
+ );\r
+\r
+/**\r
+ Function is used to determine the number of device path instances\r
+ that exist in a device path.\r
+\r
+\r
+ @param DevicePath A pointer to a device path data structure.\r
+\r
+ @return This function counts and returns the number of device path instances\r
+ in DevicePath.\r
+\r
+**/\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+\r
+/**\r
+ Create string tokens for a menu from its help strings and display strings\r
+\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param HiiHandle Hii Handle of the package to be updated.\r
+ @param MenuOption The Menu whose string tokens need to be created\r
+\r
+ @retval EFI_SUCCESS string tokens created successfully\r
+ @retval others contain some errors\r
+\r
+**/\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN BM_MENU_OPTION *MenuOption\r
+ );\r
+\r
+/**\r
+ Get a string from the Data Hub record based on \r
+ a device path.\r
+\r
+ @param DevPath The device Path.\r
+\r
+ @return A string located from the Data Hub records based on\r
+ the device path.\r
+ @retval NULL If failed to get the String from Data Hub.\r
+\r
+**/\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+/**\r
+ Get the index number (#### in Boot####) for the boot option pointed to a BBS legacy device type\r
+ specified by DeviceType.\r
+\r
+ @param DeviceType The legacy device type. It can be floppy, network, harddisk, cdrom,\r
+ etc.\r
+ @param OptionIndex Returns the index number (#### in Boot####).\r
+ @param OptionSize Return the size of the Boot### variable.\r
+\r
+**/\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+ IN UINTN DeviceType,\r
+ OUT UINTN *OptionIndex,\r
+ OUT UINTN *OptionSize\r
+ );\r
+\r
+/**\r
+ Initialize the Boot Maintenance Utitliy.\r
+\r
+ @retval EFI_SUCCESS utility ended successfully.\r
+ @retval others contain some errors.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBM (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Start boot maintenance manager\r
+\r
+ @retval EFI_SUCCESS If BMM is invoked successfully.\r
+ @return Other value if BMM return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Intialize all the string depositories.\r
+\r
+**/\r
+VOID\r
+InitializeStringDepository (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Fetch a usable string node from the string depository and return the string token.\r
+\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param StringDepository Pointer of the string depository.\r
+\r
+ @retval EFI_STRING_ID String token.\r
+\r
+**/\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN STRING_DEPOSITORY *StringDepository\r
+ );\r
+\r
+/**\r
+ Reclaim string depositories by moving the current node pointer to list head..\r
+**/\r
+VOID\r
+ReclaimStringDepository (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Release resource for all the string depositories.\r
+\r
+**/\r
+VOID\r
+CleanUpStringDepository (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Function handling request to apply changes for BMM pages.\r
+\r
+ @param Private Pointer to callback data buffer.\r
+ @param CurrentFakeNVMap Pointer to buffer holding data of various values used by BMM\r
+ @param FormId ID of the form which has sent the request to apply change.\r
+\r
+ @retval EFI_SUCCESS Change successfully applied.\r
+ @retval Other Error occurs while trying to apply changes.\r
+\r
+**/\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,\r
+ IN EFI_FORM_ID FormId\r
+ );\r
+\r
+/**\r
+ Discard all changes done to the BMM pages such as Boot Order change,\r
+ Driver order change.\r
+\r
+ @param Private The BMM context data.\r
+ @param CurrentFakeNVMap The current Fack NV Map.\r
+\r
+**/\r
+VOID\r
+DiscardChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap\r
+ );\r
+\r
+/**\r
+ Dispatch the display to the next page based on NewPageId.\r
+\r
+ @param Private The BMM context data.\r
+ @param NewPageId The original page ID.\r
+\r
+**/\r
+VOID\r
+UpdatePageId (\r
+ BMM_CALLBACK_DATA *Private,\r
+ UINT16 NewPageId\r
+ );\r
+\r
+/**\r
+ Boot a file selected by user at File Expoloer of BMM.\r
+\r
+ @param FileContext The file context data, which contains the device path\r
+ of the file to be boot from.\r
+\r
+ @retval EFI_SUCCESS The function completed successfull.\r
+ @return Other value if the boot from the file fails.\r
+\r
+**/\r
+EFI_STATUS\r
+BootThisFile (\r
+ IN BM_FILE_CONTEXT *FileContext\r
+ );\r
+\r
+/**\r
+ Update the file explower page with the refershed file system.\r
+\r
+\r
+ @param CallbackData BMM context data\r
+ @param KeyValue Key value to identify the type of data to expect.\r
+\r
+ @retval TRUE Inform the caller to create a callback packet to exit file explorer.\r
+ @retval FALSE Indicate that there is no need to exit file explorer.\r
+\r
+**/\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN UINT16 KeyValue\r
+ );\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+ When user select a interactive opcode, this callback will be triggered.\r
+ Based on the Question(QuestionId) that triggers the callback, the corresponding\r
+ actions is performed. It handles:\r
+\r
+ 1) the addition of boot option.\r
+ 2) the addition of driver option.\r
+ 3) exit from file browser\r
+ 4) update of file content if a dir is selected.\r
+ 5) boot the file if a file is selected in "boot from file"\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
+ @retval EFI_DEVICE_ERROR The variable could not be saved.\r
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ );\r
+\r
+/**\r
+ Dispatch BMM formset and FileExplorer formset.\r
+\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS If function complete successfully.\r
+ @return Other value if the Setup Browser process BMM's pages and\r
+ return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+/**\r
+ Function returns the value of the specified variable.\r
+\r
+ @param Name A Null-terminated Unicode string that is\r
+ the name of the vendor's variable.\r
+ @param VendorGuid A unique identifier for the vendor.\r
+\r
+ @return The payload of the variable.\r
+ @retval NULL If the variable can't be read.\r
+\r
+**/\r
+VOID *\r
+EfiLibGetVariable (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid\r
+ );\r
+\r
+//\r
+// Global variable in this program (defined in data.c)\r
+//\r
+extern BM_MENU_OPTION BootOptionMenu;\r
+extern BM_MENU_OPTION DriverOptionMenu;\r
+extern BM_MENU_OPTION FsOptionMenu;\r
+extern BM_MENU_OPTION ConsoleInpMenu;\r
+extern BM_MENU_OPTION ConsoleOutMenu;\r
+extern BM_MENU_OPTION ConsoleErrMenu;\r
+extern BM_MENU_OPTION DirectoryMenu;\r
+extern BM_MENU_OPTION DriverMenu;\r
+extern BM_MENU_OPTION TerminalMenu;\r
+extern BM_MENU_OPTION LegacyFDMenu;\r
+extern BM_MENU_OPTION LegacyHDMenu;\r
+extern BM_MENU_OPTION LegacyCDMenu;\r
+extern BM_MENU_OPTION LegacyNETMenu;\r
+extern BM_MENU_OPTION LegacyBEVMenu;\r
+extern UINT16 TerminalType[];\r
+extern COM_ATTR BaudRateList[19];\r
+extern COM_ATTR DataBitsList[4];\r
+extern COM_ATTR ParityList[5];\r
+extern COM_ATTR StopBitsList[3];\r
+extern EFI_GUID TerminalTypeGuid[4];\r
+extern EFI_HII_UPDATE_DATA gUpdateData;\r
+extern STRING_DEPOSITORY *FileOptionStrDepository;\r
+extern STRING_DEPOSITORY *ConsoleOptionStrDepository;\r
+extern STRING_DEPOSITORY *BootOptionStrDepository;\r
+extern STRING_DEPOSITORY *BootOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY *DriverOptionStrDepository;\r
+extern STRING_DEPOSITORY *DriverOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY *TerminalStrDepository;\r
+extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[];\r
+extern EFI_GUID EfiLegacyDevOrderGuid;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Provide boot option support for Application "BootMaint"\r
+\r
+ Include file system navigation, system handle selection\r
+\r
+ Boot option manipulation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+#include "BBSsupport.h"\r
+\r
+/**\r
+ Create a menu entry by given menu type.\r
+\r
+ @param MenuType The Menu type to be created.\r
+\r
+ @retval NULL If failed to create the menu.\r
+ @return the new menu entry.\r
+\r
+**/\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+ UINTN MenuType\r
+ )\r
+{\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ UINTN ContextSize;\r
+\r
+ //\r
+ // Get context size according to menu type\r
+ //\r
+ switch (MenuType) {\r
+ case BM_LOAD_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_LOAD_CONTEXT);\r
+ break;\r
+\r
+ case BM_FILE_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_FILE_CONTEXT);\r
+ break;\r
+\r
+ case BM_CONSOLE_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
+ break;\r
+\r
+ case BM_TERMINAL_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
+ break;\r
+\r
+ case BM_HANDLE_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
+ break;\r
+\r
+ case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
+ break;\r
+\r
+ default:\r
+ ContextSize = 0;\r
+ break;\r
+ }\r
+\r
+ if (ContextSize == 0) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Create new menu entry\r
+ //\r
+ MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
+ if (MenuEntry == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ MenuEntry->VariableContext = AllocateZeroPool (ContextSize);\r
+ if (MenuEntry->VariableContext == NULL) {\r
+ FreePool (MenuEntry);\r
+ return NULL;\r
+ }\r
+\r
+ MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;\r
+ MenuEntry->ContextSelection = MenuType;\r
+ return MenuEntry;\r
+}\r
+\r
+/**\r
+ Free up all resource allocated for a BM_MENU_ENTRY.\r
+\r
+ @param MenuEntry A pointer to BM_MENU_ENTRY.\r
+\r
+**/\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+ BM_MENU_ENTRY *MenuEntry\r
+ )\r
+{\r
+ BM_LOAD_CONTEXT *LoadContext;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ BM_CONSOLE_CONTEXT *ConsoleContext;\r
+ BM_TERMINAL_CONTEXT *TerminalContext;\r
+ BM_HANDLE_CONTEXT *HandleContext;\r
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;\r
+\r
+ //\r
+ // Select by the type in Menu entry for current context type\r
+ //\r
+ switch (MenuEntry->ContextSelection) {\r
+ case BM_LOAD_CONTEXT_SELECT:\r
+ LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
+ FreePool (LoadContext->FilePathList);\r
+ FreePool (LoadContext->LoadOption);\r
+ if (LoadContext->OptionalData != NULL) {\r
+ FreePool (LoadContext->OptionalData);\r
+ }\r
+ FreePool (LoadContext);\r
+ break;\r
+\r
+ case BM_FILE_CONTEXT_SELECT:\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+ if (!FileContext->IsRoot) {\r
+ FreePool (FileContext->DevicePath);\r
+ } else {\r
+ if (FileContext->FHandle != NULL) {\r
+ FileContext->FHandle->Close (FileContext->FHandle);\r
+ }\r
+ }\r
+\r
+ if (FileContext->FileName != NULL) {\r
+ FreePool (FileContext->FileName);\r
+ }\r
+ if (FileContext->Info != NULL) {\r
+ FreePool (FileContext->Info);\r
+ }\r
+ FreePool (FileContext);\r
+ break;\r
+\r
+ case BM_CONSOLE_CONTEXT_SELECT:\r
+ ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
+ FreePool (ConsoleContext->DevicePath);\r
+ FreePool (ConsoleContext);\r
+ break;\r
+\r
+ case BM_TERMINAL_CONTEXT_SELECT:\r
+ TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
+ FreePool (TerminalContext->DevicePath);\r
+ FreePool (TerminalContext);\r
+ break;\r
+\r
+ case BM_HANDLE_CONTEXT_SELECT:\r
+ HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
+ FreePool (HandleContext);\r
+ break;\r
+\r
+ case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+ LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
+ FreePool (LegacyDevContext);\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ FreePool (MenuEntry->DisplayString);\r
+ if (MenuEntry->HelpString != NULL) {\r
+ FreePool (MenuEntry->HelpString);\r
+ }\r
+\r
+ FreePool (MenuEntry);\r
+}\r
+\r
+/**\r
+ Get the Menu Entry from the list in Menu Entry List.\r
+\r
+ If MenuNumber is great or equal to the number of Menu\r
+ Entry in the list, then ASSERT.\r
+\r
+ @param MenuOption The Menu Entry List to read the menu entry.\r
+ @param MenuNumber The index of Menu Entry.\r
+\r
+ @return The Menu Entry.\r
+\r
+**/\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+ BM_MENU_OPTION *MenuOption,\r
+ UINTN MenuNumber\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINTN Index;\r
+ LIST_ENTRY *List;\r
+\r
+ ASSERT (MenuNumber < MenuOption->MenuNumber);\r
+\r
+ List = MenuOption->Head.ForwardLink;\r
+ for (Index = 0; Index < MenuNumber; Index++) {\r
+ List = List->ForwardLink;\r
+ }\r
+\r
+ NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
+\r
+ return NewMenuEntry;\r
+}\r
+\r
+/**\r
+ This function build the FsOptionMenu list which records all\r
+ available file system in the system. They includes all instances\r
+ of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
+ and all type of legacy boot device.\r
+\r
+ @param CallbackData BMM context data\r
+\r
+ @retval EFI_SUCCESS Success find the file system\r
+ @retval EFI_OUT_OF_RESOURCES Can not create menu entry\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN NoBlkIoHandles;\r
+ UINTN NoSimpleFsHandles;\r
+ UINTN NoLoadFileHandles;\r
+ EFI_HANDLE *BlkIoHandle;\r
+ EFI_HANDLE *SimpleFsHandle;\r
+ EFI_HANDLE *LoadFileHandle;\r
+ UINT16 *VolumeLabel;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ UINT16 *TempStr;\r
+ UINTN OptionNumber;\r
+ VOID *Buffer;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINT16 DeviceType;\r
+ BBS_BBS_DEVICE_PATH BbsDevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BOOLEAN RemovableMedia;\r
+\r
+\r
+ NoSimpleFsHandles = 0;\r
+ NoLoadFileHandles = 0;\r
+ OptionNumber = 0;\r
+ InitializeListHead (&FsOptionMenu.Head);\r
+\r
+ //\r
+ // Locate Handles that support BlockIo protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiBlockIoProtocolGuid,\r
+ NULL,\r
+ &NoBlkIoHandles,\r
+ &BlkIoHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ BlkIoHandle[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
+ //\r
+ if (BlkIo->Media->RemovableMedia) {\r
+ Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);\r
+ if (NULL == Buffer) {\r
+ FreePool (BlkIoHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BlkIo->ReadBlocks (\r
+ BlkIo,\r
+ BlkIo->Media->MediaId,\r
+ 0,\r
+ BlkIo->Media->BlockSize,\r
+ Buffer\r
+ );\r
+ FreePool (Buffer);\r
+ }\r
+ }\r
+ FreePool (BlkIoHandle);\r
+ }\r
+\r
+ //\r
+ // Locate Handles that support Simple File System protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &NoSimpleFsHandles,\r
+ &SimpleFsHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Find all the instances of the File System prototocol\r
+ //\r
+ for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ SimpleFsHandle[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no block IO exists assume it's NOT a removable media\r
+ //\r
+ RemovableMedia = FALSE;\r
+ } else {\r
+ //\r
+ // If block IO exists check to see if it's remobable media\r
+ //\r
+ RemovableMedia = BlkIo->Media->RemovableMedia;\r
+ }\r
+\r
+ //\r
+ // Allocate pool for this load option\r
+ //\r
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == MenuEntry) {\r
+ FreePool (SimpleFsHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+ FileContext->Handle = SimpleFsHandle[Index];\r
+ MenuEntry->OptionNumber = Index;\r
+ FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);\r
+ if (FileContext->FHandle == NULL) {\r
+ BOpt_DestroyMenuEntry (MenuEntry);\r
+ continue;\r
+ }\r
+\r
+ MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
+ FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
+ FileContext->FileName = EfiStrDuplicate (L"\\");\r
+ FileContext->DevicePath = FileDevicePath (\r
+ FileContext->Handle,\r
+ FileContext->FileName\r
+ );\r
+ FileContext->IsDir = TRUE;\r
+ FileContext->IsRoot = TRUE;\r
+ FileContext->IsRemovableMedia = RemovableMedia;\r
+ FileContext->IsLoadFile = FALSE;\r
+\r
+ //\r
+ // Get current file system's Volume Label\r
+ //\r
+ if (FileContext->Info == NULL) {\r
+ VolumeLabel = L"NO FILE SYSTEM INFO";\r
+ } else {\r
+ if (FileContext->Info->VolumeLabel == NULL) {\r
+ VolumeLabel = L"NULL VOLUME LABEL";\r
+ } else {\r
+ VolumeLabel = FileContext->Info->VolumeLabel;\r
+ if (*VolumeLabel == 0x0000) {\r
+ VolumeLabel = L"NO VOLUME LABEL";\r
+ }\r
+ }\r
+ }\r
+\r
+ TempStr = MenuEntry->HelpString;\r
+ MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
+ ASSERT (MenuEntry->DisplayString != NULL);\r
+ UnicodeSPrint (\r
+ MenuEntry->DisplayString,\r
+ MAX_CHAR,\r
+ L"%s, [%s]",\r
+ VolumeLabel,\r
+ TempStr\r
+ );\r
+ OptionNumber++;\r
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ if (NoSimpleFsHandles != 0) {\r
+ FreePool (SimpleFsHandle);\r
+ }\r
+ //\r
+ // Searching for handles that support Load File protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLoadFileProtocolGuid,\r
+ NULL,\r
+ &NoLoadFileHandles,\r
+ &LoadFileHandle\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == MenuEntry) {\r
+ FreePool (LoadFileHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+ FileContext->IsRemovableMedia = FALSE;\r
+ FileContext->IsLoadFile = TRUE;\r
+ FileContext->Handle = LoadFileHandle[Index];\r
+ FileContext->IsRoot = TRUE;\r
+\r
+ FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
+\r
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
+\r
+ TempStr = MenuEntry->HelpString;\r
+ MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
+ ASSERT (MenuEntry->DisplayString != NULL);\r
+ UnicodeSPrint (\r
+ MenuEntry->DisplayString,\r
+ MAX_CHAR,\r
+ L"Load File [%s]",\r
+ TempStr\r
+ );\r
+\r
+ MenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ if (NoLoadFileHandles != 0) {\r
+ FreePool (LoadFileHandle);\r
+ }\r
+\r
+ //\r
+ // Add Legacy Boot Option Support Here\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == MenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+ FileContext->IsRemovableMedia = FALSE;\r
+ FileContext->IsLoadFile = TRUE;\r
+ FileContext->IsBootLegacy = TRUE;\r
+ DeviceType = (UINT16) Index;\r
+ BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
+ BbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
+ SetDevicePathNodeLength (\r
+ &BbsDevicePathNode.Header,\r
+ sizeof (BBS_BBS_DEVICE_PATH)\r
+ );\r
+ BbsDevicePathNode.DeviceType = DeviceType;\r
+ BbsDevicePathNode.StatusFlag = 0;\r
+ BbsDevicePathNode.String[0] = 0;\r
+ DevicePath = AppendDevicePathNode (\r
+ EndDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
+ );\r
+\r
+ FileContext->DevicePath = DevicePath;\r
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
+\r
+ TempStr = MenuEntry->HelpString;\r
+ MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
+ ASSERT (MenuEntry->DisplayString != NULL);\r
+ UnicodeSPrint (\r
+ MenuEntry->DisplayString,\r
+ MAX_CHAR,\r
+ L"Boot Legacy [%s]",\r
+ TempStr\r
+ );\r
+ MenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+ }\r
+ }\r
+ //\r
+ // Remember how many file system options are here\r
+ //\r
+ FsOptionMenu.MenuNumber = OptionNumber;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free resources allocated in Allocate Rountine.\r
+\r
+ @param FreeMenu Menu to be freed\r
+**/\r
+VOID\r
+BOpt_FreeMenu (\r
+ BM_MENU_OPTION *FreeMenu\r
+ )\r
+{\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ while (!IsListEmpty (&FreeMenu->Head)) {\r
+ MenuEntry = CR (\r
+ FreeMenu->Head.ForwardLink,\r
+ BM_MENU_ENTRY,\r
+ Link,\r
+ BM_MENU_ENTRY_SIGNATURE\r
+ );\r
+ RemoveEntryList (&MenuEntry->Link);\r
+ BOpt_DestroyMenuEntry (MenuEntry);\r
+ }\r
+}\r
+\r
+/**\r
+ Find files under current directory\r
+ All files and sub-directories in current directory\r
+ will be stored in DirectoryMenu for future use.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param MenuEntry The Menu Entry.\r
+\r
+ @retval EFI_SUCCESS Get files from current dir successfully.\r
+ @return Other value if can't get files from current dir.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN BM_MENU_ENTRY *MenuEntry\r
+ )\r
+{\r
+ EFI_FILE_HANDLE NewDir;\r
+ EFI_FILE_HANDLE Dir;\r
+ EFI_FILE_INFO *DirInfo;\r
+ UINTN BufferSize;\r
+ UINTN DirBufferSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ BM_FILE_CONTEXT *NewFileContext;\r
+ UINTN Pass;\r
+ EFI_STATUS Status;\r
+ UINTN OptionNumber;\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+ Dir = FileContext->FHandle;\r
+ OptionNumber = 0;\r
+ //\r
+ // Open current directory to get files from it\r
+ //\r
+ Status = Dir->Open (\r
+ Dir,\r
+ &NewDir,\r
+ FileContext->FileName,\r
+ EFI_FILE_READ_ONLY,\r
+ 0\r
+ );\r
+ if (!FileContext->IsRoot) {\r
+ Dir->Close (Dir);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DirInfo = EfiLibFileInfo (NewDir);\r
+ if (DirInfo == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FileContext->DevicePath = FileDevicePath (\r
+ FileContext->Handle,\r
+ FileContext->FileName\r
+ );\r
+\r
+ DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
+ DirInfo = AllocateZeroPool (DirBufferSize);\r
+ if (DirInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Get all files in current directory\r
+ // Pass 1 to get Directories\r
+ // Pass 2 to get files that are EFI images\r
+ //\r
+ for (Pass = 1; Pass <= 2; Pass++) {\r
+ NewDir->SetPosition (NewDir, 0);\r
+ for (;;) {\r
+ BufferSize = DirBufferSize;\r
+ Status = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
+ if (EFI_ERROR (Status) || BufferSize == 0) {\r
+ break;\r
+ }\r
+\r
+ if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||\r
+ (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)\r
+ ) {\r
+ //\r
+ // Pass 1 is for Directories\r
+ // Pass 2 is for file names\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+ //\r
+ // Slip file unless it is a directory entry or a .EFI file\r
+ //\r
+ continue;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewFileContext->Handle = FileContext->Handle;\r
+ NewFileContext->FileName = BOpt_AppendFileName (\r
+ FileContext->FileName,\r
+ DirInfo->FileName\r
+ );\r
+ NewFileContext->FHandle = NewDir;\r
+ NewFileContext->DevicePath = FileDevicePath (\r
+ NewFileContext->Handle,\r
+ NewFileContext->FileName\r
+ );\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ FileOptionStrDepository\r
+ );\r
+\r
+ NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
+\r
+ if (NewFileContext->IsDir) {\r
+ BufferSize = StrLen (DirInfo->FileName) * 2 + 6;\r
+ NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
+\r
+ UnicodeSPrint (\r
+ NewMenuEntry->DisplayString,\r
+ BufferSize,\r
+ L"<%s>",\r
+ DirInfo->FileName\r
+ );\r
+\r
+ } else {\r
+ NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
+ }\r
+\r
+ NewFileContext->IsRoot = FALSE;\r
+ NewFileContext->IsLoadFile = FALSE;\r
+ NewFileContext->IsRemovableMedia = FALSE;\r
+\r
+ NewMenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ DirectoryMenu.MenuNumber = OptionNumber;\r
+ FreePool (DirInfo);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+ VOID\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINT16 HddCount;\r
+ HDD_INFO *HddInfo;\r
+ UINT16 BbsCount;\r
+ BBS_TABLE *BbsTable;\r
+ UINTN Index;\r
+ CHAR16 DescString[100];\r
+ UINTN FDNum;\r
+ UINTN HDNum;\r
+ UINTN CDNum;\r
+ UINTN NETNum;\r
+ UINTN BEVNum;\r
+\r
+ NewMenuEntry = NULL;\r
+ HddInfo = NULL;\r
+ BbsTable = NULL;\r
+ BbsCount = 0;\r
+\r
+ //\r
+ // Initialize Bbs Table Context from BBS info data\r
+ //\r
+ InitializeListHead (&LegacyFDMenu.Head);\r
+ InitializeListHead (&LegacyHDMenu.Head);\r
+ InitializeListHead (&LegacyCDMenu.Head);\r
+ InitializeListHead (&LegacyNETMenu.Head);\r
+ InitializeListHead (&LegacyBEVMenu.Head);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &HddInfo,\r
+ &BbsCount,\r
+ &BbsTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ FDNum = 0;\r
+ HDNum = 0;\r
+ CDNum = 0;\r
+ NETNum = 0;\r
+ BEVNum = 0;\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
+ (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ break;\r
+ }\r
+\r
+ NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLegacyDevContext->BbsTable = &BbsTable[Index];\r
+ NewLegacyDevContext->Index = Index;\r
+ NewLegacyDevContext->BbsCount = BbsCount;\r
+ BdsBuildLegacyDevNameString (\r
+ &BbsTable[Index],\r
+ Index,\r
+ sizeof (DescString),\r
+ DescString\r
+ );\r
+ NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString));\r
+ if (NULL == NewLegacyDevContext->Description) {\r
+ break;\r
+ }\r
+\r
+ CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));\r
+ NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ switch (BbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
+ FDNum++;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
+ HDNum++;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
+ CDNum++;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
+ NETNum++;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
+ BEVNum++;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != BbsCount) {\r
+ BOpt_FreeLegacyOptions ();\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ LegacyFDMenu.MenuNumber = FDNum;\r
+ LegacyHDMenu.MenuNumber = HDNum;\r
+ LegacyCDMenu.MenuNumber = CDNum;\r
+ LegacyNETMenu.MenuNumber = NETNum;\r
+ LegacyBEVMenu.MenuNumber = BEVNum;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free out resouce allocated from Legacy Boot Options.\r
+\r
+**/\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+ VOID\r
+ )\r
+{\r
+ BOpt_FreeMenu (&LegacyFDMenu);\r
+ BOpt_FreeMenu (&LegacyHDMenu);\r
+ BOpt_FreeMenu (&LegacyCDMenu);\r
+ BOpt_FreeMenu (&LegacyNETMenu);\r
+ BOpt_FreeMenu (&LegacyBEVMenu);\r
+}\r
+\r
+/**\r
+\r
+ Build the BootOptionMenu according to BootOrder Variable.\r
+ This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @return EFI_NOT_FOUND Fail to find "BootOrder" variable.\r
+ @return EFI_SUCESS Success build boot option menu.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 BootString[10];\r
+ UINT8 *LoadOptionFromVar;\r
+ UINT8 *LoadOption;\r
+ UINTN BootOptionSize;\r
+ BOOLEAN BootNextFlag;\r
+ UINT16 *BootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT16 *BootNext;\r
+ UINTN BootNextSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT8 *LoadOptionPtr;\r
+ UINTN StringSize;\r
+ UINTN OptionalDataSize;\r
+ UINT8 *LoadOptionEnd;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN MenuCount;\r
+ UINT8 *Ptr;\r
+\r
+ MenuCount = 0;\r
+ BootOrderListSize = 0;\r
+ BootNextSize = 0;\r
+ BootOrderList = NULL;\r
+ BootNext = NULL;\r
+ LoadOptionFromVar = NULL;\r
+ BOpt_FreeMenu (&BootOptionMenu);\r
+ InitializeListHead (&BootOptionMenu.Head);\r
+\r
+ //\r
+ // Get the BootOrder from the Var\r
+ //\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+ if (BootOrderList == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ //\r
+ // Get the BootNext from the Var\r
+ //\r
+ BootNext = BdsLibGetVariableAndSize (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootNextSize\r
+ );\r
+\r
+ if (BootNext != NULL) {\r
+ if (BootNextSize != sizeof (UINT16)) {\r
+ FreePool (BootNext);\r
+ BootNext = NULL;\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
+ //\r
+ // Get all loadoptions from the VAR\r
+ //\r
+ LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+ BootString,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (LoadOptionFromVar == NULL) {\r
+ continue;\r
+ }\r
+\r
+ LoadOption = AllocateZeroPool (BootOptionSize);\r
+ if (LoadOption == NULL) {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
+ FreePool (LoadOptionFromVar);\r
+\r
+ if (BootNext != NULL) {\r
+ BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
+ } else {\r
+ BootNextFlag = FALSE;\r
+ }\r
+\r
+ if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
+ FreePool (LoadOption);\r
+ continue;\r
+ }\r
+ //\r
+ // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
+ // the buffer allocated already should be freed before returning.\r
+ //\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ LoadOptionPtr = LoadOption;\r
+ LoadOptionEnd = LoadOption + BootOptionSize;\r
+\r
+ NewMenuEntry->OptionNumber = BootOrderList[Index];\r
+ NewLoadContext->LoadOptionModified = FALSE;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->IsBootNext = BootNextFlag;\r
+\r
+ //\r
+ // Is a Legacy Device?\r
+ //\r
+ Ptr = (UINT8 *) LoadOption;\r
+\r
+ //\r
+ // Attribute = *(UINT32 *)Ptr;\r
+ //\r
+ Ptr += sizeof (UINT32);\r
+\r
+ //\r
+ // FilePathSize = *(UINT16 *)Ptr;\r
+ //\r
+ Ptr += sizeof (UINT16);\r
+\r
+ //\r
+ // Description = (CHAR16 *)Ptr;\r
+ //\r
+ Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+ //\r
+ // Now Ptr point to Device Path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+ NewLoadContext->IsLegacy = TRUE;\r
+ } else {\r
+ NewLoadContext->IsLegacy = FALSE;\r
+ }\r
+ //\r
+ // LoadOption is a pointer type of UINT8\r
+ // for easy use with following LOAD_OPTION\r
+ // embedded in this struct\r
+ //\r
+ NewLoadContext->LoadOption = LoadOption;\r
+ NewLoadContext->LoadOptionSize = BootOptionSize;\r
+\r
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ LoadOptionPtr += sizeof (UINT32);\r
+\r
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+ LoadOptionPtr += sizeof (UINT16);\r
+\r
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
+ NewLoadContext->Description = AllocateZeroPool (StringSize);\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (UINT16 *) LoadOptionPtr,\r
+ StringSize\r
+ );\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+ LoadOptionPtr += StringSize;\r
+\r
+ NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+ NewLoadContext->FilePathListLength\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionStrDepository\r
+ );\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionHelpStrDepository\r
+ );\r
+ LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+ if (LoadOptionPtr < LoadOptionEnd) {\r
+ OptionalDataSize = BootOptionSize -\r
+ sizeof (UINT32) -\r
+ sizeof (UINT16) -\r
+ StringSize -\r
+ NewLoadContext->FilePathListLength;\r
+\r
+ NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
+ ASSERT (NewLoadContext->OptionalData != NULL);\r
+ CopyMem (\r
+ NewLoadContext->OptionalData,\r
+ LoadOptionPtr,\r
+ OptionalDataSize\r
+ );\r
+\r
+ NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+ }\r
+\r
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+ MenuCount++;\r
+ }\r
+\r
+ if (BootNext != NULL) {\r
+ FreePool (BootNext);\r
+ }\r
+ if (BootOrderList != NULL) {\r
+ FreePool (BootOrderList);\r
+ }\r
+ BootOptionMenu.MenuNumber = MenuCount;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Append file name to existing file name.\r
+\r
+ @param Str1 The existing file name\r
+ @param Str2 The file name to be appended\r
+\r
+ @return Allocate a new string to hold the appended result.\r
+ Caller is responsible to free the returned string.\r
+\r
+**/\r
+CHAR16 *\r
+BOpt_AppendFileName (\r
+ IN CHAR16 *Str1,\r
+ IN CHAR16 *Str2\r
+ )\r
+{\r
+ UINTN Size1;\r
+ UINTN Size2;\r
+ CHAR16 *Str;\r
+ CHAR16 *TmpStr;\r
+ CHAR16 *Ptr;\r
+ CHAR16 *LastSlash;\r
+\r
+ Size1 = StrSize (Str1);\r
+ Size2 = StrSize (Str2);\r
+ Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
+ ASSERT (Str != NULL);\r
+\r
+ TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); \r
+ ASSERT (TmpStr != NULL);\r
+\r
+ StrCat (Str, Str1);\r
+ if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
+ StrCat (Str, L"\\");\r
+ }\r
+\r
+ StrCat (Str, Str2);\r
+\r
+ Ptr = Str;\r
+ LastSlash = Str;\r
+ while (*Ptr != 0) {\r
+ if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {\r
+ //\r
+ // Convert "\Name\..\" to "\"\r
+ // DO NOT convert the .. if it is at the end of the string. This will\r
+ // break the .. behavior in changing directories.\r
+ //\r
+\r
+ //\r
+ // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
+ // that overlap.\r
+ //\r
+ StrCpy (TmpStr, Ptr + 3);\r
+ StrCpy (LastSlash, TmpStr);\r
+ Ptr = LastSlash;\r
+ } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
+ //\r
+ // Convert a "\.\" to a "\"\r
+ //\r
+\r
+ //\r
+ // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
+ // that overlap.\r
+ //\r
+ StrCpy (TmpStr, Ptr + 2);\r
+ StrCpy (Ptr, TmpStr);\r
+ Ptr = LastSlash;\r
+ } else if (*Ptr == '\\') {\r
+ LastSlash = Ptr;\r
+ }\r
+\r
+ Ptr++;\r
+ }\r
+\r
+ FreePool (TmpStr);\r
+ \r
+ return Str;\r
+}\r
+\r
+/**\r
+\r
+ Check whether current FileName point to a valid\r
+ Efi Image File.\r
+\r
+ @param FileName File need to be checked.\r
+\r
+ @retval TRUE Is Efi Image\r
+ @retval FALSE Not a valid Efi Image\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+ IN UINT16 *FileName\r
+ )\r
+{\r
+ //\r
+ // Search for ".efi" extension\r
+ //\r
+ while (*FileName != L'\0') {\r
+ if (FileName[0] == '.') {\r
+ if (FileName[1] == 'e' || FileName[1] == 'E') {\r
+ if (FileName[2] == 'f' || FileName[2] == 'F') {\r
+ if (FileName[3] == 'i' || FileName[3] == 'I') {\r
+ return TRUE;\r
+ } else if (FileName[3] == 0x0000) {\r
+ return FALSE;\r
+ }\r
+ } else if (FileName[2] == 0x0000) {\r
+ return FALSE;\r
+ }\r
+ } else if (FileName[1] == 0x0000) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ FileName += 1;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+\r
+ Check whether current FileName point to a valid Efi Application\r
+\r
+ @param Dir Pointer to current Directory\r
+ @param FileName Pointer to current File name.\r
+\r
+ @retval TRUE Is a valid Efi Application\r
+ @retval FALSE not a valid Efi Application\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+ IN EFI_FILE_HANDLE Dir,\r
+ IN UINT16 *FileName\r
+ )\r
+{\r
+ UINTN BufferSize;\r
+ EFI_IMAGE_DOS_HEADER DosHdr;\r
+ UINT16 Subsystem;\r
+ EFI_FILE_HANDLE File;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;\r
+\r
+ Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+ File->Read (File, &BufferSize, &DosHdr);\r
+ if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ File->Close (File);\r
+ return FALSE;\r
+ }\r
+\r
+ File->SetPosition (File, DosHdr.e_lfanew);\r
+ BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
+ File->Read (File, &BufferSize, &PeHdr);\r
+ if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ File->Close (File);\r
+ return FALSE;\r
+ }\r
+ //\r
+ // Determine PE type and read subsytem\r
+ //\r
+ if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem;\r
+ } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+\r
+ if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ File->Close (File);\r
+ return TRUE;\r
+ } else {\r
+ File->Close (File);\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Find drivers that will be added as Driver#### variables from handles\r
+ in current system environment\r
+ All valid handles in the system except those consume SimpleFs, LoadFile\r
+ are stored in DriverMenu for future use.\r
+\r
+ @retval EFI_SUCCESS The function complets successfully.\r
+ @return Other value if failed to build the DriverMenu.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+ VOID\r
+ )\r
+{\r
+ UINTN NoDevicePathHandles;\r
+ EFI_HANDLE *DevicePathHandle;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_HANDLE_CONTEXT *NewHandleContext;\r
+ EFI_HANDLE CurHandle;\r
+ UINTN OptionNumber;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+\r
+ SimpleFs = NULL;\r
+ LoadFile = NULL;\r
+\r
+ InitializeListHead (&DriverMenu.Head);\r
+\r
+ //\r
+ // At first, get all handles that support Device Path\r
+ // protocol which is the basic requirement for\r
+ // Driver####\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDevicePathProtocolGuid,\r
+ NULL,\r
+ &NoDevicePathHandles,\r
+ &DevicePathHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ OptionNumber = 0;\r
+ for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
+ CurHandle = DevicePathHandle[Index];\r
+\r
+ Status = gBS->HandleProtocol (\r
+ CurHandle,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (VOID **) &SimpleFs\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ continue;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ CurHandle,\r
+ &gEfiLoadFileProtocolGuid,\r
+ (VOID **) &LoadFile\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ continue;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ FreePool (DevicePathHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewHandleContext->Handle = CurHandle;\r
+ NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);\r
+ NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
+ NewMenuEntry->HelpString = NULL;\r
+ NewMenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
+\r
+ }\r
+\r
+ if (DevicePathHandle != NULL) {\r
+ FreePool (DevicePathHandle);\r
+ }\r
+\r
+ DriverMenu.MenuNumber = OptionNumber;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Get the Option Number that has not been allocated for use.\r
+\r
+ @return The available Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+ VOID\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *BootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT16 Number;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ BOOLEAN Found;\r
+ CHAR16 StrTemp[100];\r
+ UINT16 *OptionBuffer;\r
+ UINTN OptionSize;\r
+\r
+ BootOrderListSize = 0;\r
+ BootOrderList = NULL;\r
+\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+ if (BootOrderList != NULL) {\r
+ //\r
+ // already have Boot####\r
+ //\r
+ // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);\r
+ //\r
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+ Found = TRUE;\r
+ for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);\r
+ if (Index == NewMenuEntry->OptionNumber) {\r
+ Found = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Found) {\r
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);\r
+ DEBUG((DEBUG_ERROR,"INdex= %s\n", StrTemp));\r
+ OptionBuffer = BdsLibGetVariableAndSize (\r
+ StrTemp,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionSize\r
+ );\r
+ if (NULL == OptionBuffer) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // end for Index\r
+ //\r
+ Number = (UINT16) Index;\r
+ } else {\r
+ //\r
+ // No Boot####\r
+ //\r
+ Number = 0;\r
+ }\r
+\r
+ return Number;\r
+}\r
+\r
+/**\r
+\r
+ Get the Option Number that is not in use.\r
+\r
+ @return The unused Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+ VOID\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *DriverOrderList;\r
+ UINTN DriverOrderListSize;\r
+ UINT16 Number;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ BOOLEAN Found;\r
+\r
+ DriverOrderListSize = 0;\r
+ DriverOrderList = NULL;\r
+\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+ if (DriverOrderList != NULL) {\r
+ //\r
+ // already have Driver####\r
+ //\r
+ // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);\r
+ //\r
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+ Found = TRUE;\r
+ for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);\r
+ if (Index == NewMenuEntry->OptionNumber) {\r
+ Found = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Found) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // end for Index\r
+ //\r
+ Number = (UINT16) Index;\r
+ } else {\r
+ //\r
+ // No Driver####\r
+ //\r
+ Number = 0;\r
+ }\r
+\r
+ return Number;\r
+}\r
+\r
+/**\r
+\r
+ Build up all DriverOptionMenu\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCESS The functin completes successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
+ @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 DriverString[12];\r
+ UINT8 *LoadOptionFromVar;\r
+ UINT8 *LoadOption;\r
+ UINTN DriverOptionSize;\r
+\r
+ UINT16 *DriverOrderList;\r
+ UINTN DriverOrderListSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT8 *LoadOptionPtr;\r
+ UINTN StringSize;\r
+ UINTN OptionalDataSize;\r
+ UINT8 *LoadOptionEnd;\r
+\r
+ DriverOrderListSize = 0;\r
+ DriverOrderList = NULL;\r
+ DriverOptionSize = 0;\r
+ LoadOptionFromVar = NULL;\r
+ BOpt_FreeMenu (&DriverOptionMenu);\r
+ InitializeListHead (&DriverOptionMenu.Head);\r
+ //\r
+ // Get the DriverOrder from the Var\r
+ //\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+ if (DriverOrderList == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (\r
+ DriverString,\r
+ sizeof (DriverString),\r
+ L"Driver%04x",\r
+ DriverOrderList[Index]\r
+ );\r
+ //\r
+ // Get all loadoptions from the VAR\r
+ //\r
+ LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+ DriverString,\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOptionSize\r
+ );\r
+ if (LoadOptionFromVar == NULL) {\r
+ continue;\r
+ }\r
+\r
+ LoadOption = AllocateZeroPool (DriverOptionSize);\r
+ if (LoadOption == NULL) {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
+ FreePool (LoadOptionFromVar);\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ LoadOptionPtr = LoadOption;\r
+ LoadOptionEnd = LoadOption + DriverOptionSize;\r
+ NewMenuEntry->OptionNumber = DriverOrderList[Index];\r
+ NewLoadContext->LoadOptionModified = FALSE;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->IsLegacy = FALSE;\r
+\r
+ //\r
+ // LoadOption is a pointer type of UINT8\r
+ // for easy use with following LOAD_OPTION\r
+ // embedded in this struct\r
+ //\r
+ NewLoadContext->LoadOption = LoadOption;\r
+ NewLoadContext->LoadOptionSize = DriverOptionSize;\r
+\r
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ LoadOptionPtr += sizeof (UINT32);\r
+\r
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+ LoadOptionPtr += sizeof (UINT16);\r
+\r
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
+ NewLoadContext->Description = AllocateZeroPool (StringSize);\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (UINT16 *) LoadOptionPtr,\r
+ StringSize\r
+ );\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+ LoadOptionPtr += StringSize;\r
+\r
+ NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+ NewLoadContext->FilePathListLength\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionStrDepository\r
+ );\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionHelpStrDepository\r
+ );\r
+ LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+ if (LoadOptionPtr < LoadOptionEnd) {\r
+ OptionalDataSize = DriverOptionSize -\r
+ sizeof (UINT32) -\r
+ sizeof (UINT16) -\r
+ StringSize -\r
+ NewLoadContext->FilePathListLength;\r
+\r
+ NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
+ ASSERT (NewLoadContext->OptionalData != NULL);\r
+ CopyMem (\r
+ NewLoadContext->OptionalData,\r
+ LoadOptionPtr,\r
+ OptionalDataSize\r
+ );\r
+\r
+ NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+ }\r
+\r
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+\r
+ }\r
+\r
+ if (DriverOrderList != NULL) {\r
+ FreePool (DriverOrderList);\r
+ }\r
+ DriverOptionMenu.MenuNumber = Index;\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ handles console redirection from boot manager\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+\r
+/**\r
+ Update Com Ports attributes from DevicePath\r
+\r
+ @param DevicePath DevicePath that contains Com ports\r
+\r
+ @retval EFI_SUCCESS The update is successful.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+\r
+/**\r
+ Update the multi-instance device path of Terminal Device based on\r
+ the global TerminalMenu. If ChangeTernimal is TRUE, the terminal \r
+ device path in the Terminal Device in TerminalMenu is also updated.\r
+\r
+ @param DevicePath The multi-instance device path.\r
+ @param ChangeTerminal TRUE, then device path in the Terminal Device \r
+ in TerminalMenu is also updated; FALSE, no update.\r
+\r
+ @return EFI_SUCCESS The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN BOOLEAN ChangeTerminal\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node1;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UART_DEVICE_PATH *Uart;\r
+ UART_DEVICE_PATH *Uart1;\r
+ UINTN Com;\r
+ UINT32 Match;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+ Match = EISA_PNP_ID (0x0501);\r
+ Node = DevicePath;\r
+ Node = NextDevicePathNode (Node);\r
+ Com = 0;\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+ }\r
+ }\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+ Uart = (UART_DEVICE_PATH *) Node;\r
+ CopyMem (\r
+ &Uart->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ //\r
+ // Change the device path in the ComPort\r
+ //\r
+ if (ChangeTerminal) {\r
+ Node1 = NewTerminalContext->DevicePath;\r
+ Node1 = NextDevicePathNode (Node1);\r
+ while (!IsDevicePathEnd (Node1)) {\r
+ if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
+ Uart1 = (UART_DEVICE_PATH *) Node1;\r
+ CopyMem (\r
+ &Uart1->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ break;\r
+ }\r
+ //\r
+ // end if\r
+ //\r
+ Node1 = NextDevicePathNode (Node1);\r
+ }\r
+ //\r
+ // end while\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Update the device path that describing a terminal device\r
+ based on the new BaudRate, Data Bits, parity and Stop Bits\r
+ set.\r
+\r
+ @param DevicePath terminal device's path\r
+\r
+**/\r
+VOID\r
+ChangeVariableDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UART_DEVICE_PATH *Uart;\r
+ UINTN Com;\r
+ UINT32 Match;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+ Match = EISA_PNP_ID (0x0501);\r
+ Node = DevicePath;\r
+ Node = NextDevicePathNode (Node);\r
+ Com = 0;\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+ }\r
+ }\r
+\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (\r
+ &TerminalMenu,\r
+ Com\r
+ );\r
+ ASSERT (NewMenuEntry != NULL);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ Uart = (UART_DEVICE_PATH *) Node;\r
+ CopyMem (\r
+ &Uart->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ }\r
+\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+}\r
+\r
+/**\r
+ Retrieve ACPI UID of UART from device path\r
+\r
+ @param Handle The handle for the UART device.\r
+ @param AcpiUid The ACPI UID on output.\r
+\r
+ @retval TRUE Find valid UID from device path\r
+ @retval FALSE Can't find\r
+\r
+**/\r
+BOOLEAN\r
+RetrieveUartUid (\r
+ IN EFI_HANDLE Handle,\r
+ IN OUT UINT32 *AcpiUid\r
+ )\r
+{\r
+ UINT32 Match;\r
+ UINT8 *Ptr;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ Ptr = (UINT8 *) DevicePath;\r
+\r
+ while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+ Ptr++;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+ Match = EISA_PNP_ID (0x0501);\r
+\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ if (AcpiUid != NULL) {\r
+ *AcpiUid = Acpi->UID;\r
+ }\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Sort Uart handles array with Acpi->UID from low to high.\r
+\r
+ @param Handles EFI_SERIAL_IO_PROTOCOL handle buffer\r
+ @param NoHandles EFI_SERIAL_IO_PROTOCOL handle count\r
+**/\r
+VOID\r
+SortedUartHandle (\r
+ IN EFI_HANDLE *Handles,\r
+ IN UINTN NoHandles\r
+ )\r
+{\r
+ UINTN Index1;\r
+ UINTN Index2;\r
+ UINTN Position;\r
+ UINT32 AcpiUid1;\r
+ UINT32 AcpiUid2;\r
+ UINT32 TempAcpiUid;\r
+ EFI_HANDLE TempHandle;\r
+\r
+ for (Index1 = 0; Index1 < NoHandles-1; Index1++) {\r
+ if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {\r
+ continue;\r
+ }\r
+ TempHandle = Handles[Index1];\r
+ Position = Index1;\r
+ TempAcpiUid = AcpiUid1;\r
+\r
+ for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {\r
+ if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {\r
+ continue;\r
+ }\r
+ if (AcpiUid2 < TempAcpiUid) {\r
+ TempAcpiUid = AcpiUid2;\r
+ TempHandle = Handles[Index2];\r
+ Position = Index2;\r
+ }\r
+ }\r
+ Handles[Position] = Handles[Index1];\r
+ Handles[Index1] = TempHandle;\r
+ }\r
+}\r
+\r
+/**\r
+ Test whether DevicePath is a valid Terminal\r
+\r
+\r
+ @param DevicePath DevicePath to be checked\r
+ @param Termi If DevicePath is valid Terminal, terminal type is returned.\r
+ @param Com If DevicePath is valid Terminal, Com Port type is returned.\r
+\r
+ @retval TRUE If DevicePath point to a Terminal.\r
+ @retval FALSE If DevicePath does not point to a Terminal.\r
+\r
+**/\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT TYPE_OF_TERMINAL *Termi,\r
+ OUT UINTN *Com\r
+ );\r
+\r
+/**\r
+ Build a list containing all serial devices.\r
+\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_UNSUPPORTED No serial ports present.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateSerialIo (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 *Ptr;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN NoHandles;\r
+ EFI_HANDLE *Handles;\r
+ EFI_STATUS Status;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINT32 Match;\r
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ VENDOR_DEVICE_PATH Vendor;\r
+ //\r
+ // Get all handles that have SerialIo protocol installed\r
+ //\r
+ InitializeListHead (&TerminalMenu.Head);\r
+ TerminalMenu.MenuNumber = 0;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSerialIoProtocolGuid,\r
+ NULL,\r
+ &NoHandles,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // No serial ports present\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Sort Uart handles array with Acpi->UID from low to high\r
+ // then Terminal menu can be built from low Acpi->UID to high Acpi->UID\r
+ //\r
+ SortedUartHandle (Handles, NoHandles);\r
+\r
+ for (Index = 0; Index < NoHandles; Index++) {\r
+ //\r
+ // Check to see whether the handle has DevicePath Protocol installed\r
+ //\r
+ gBS->HandleProtocol (\r
+ Handles[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ Ptr = (UINT8 *) DevicePath;\r
+ while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+ Ptr++;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+ Match = EISA_PNP_ID (0x0501);\r
+\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
+ if (NewMenuEntry == NULL) {\r
+ FreePool (Handles);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
+ NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath);\r
+ //\r
+ // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
+ // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
+ // datahub which is not completed, so a searching for end of device path will enter a\r
+ // dead-loop.\r
+ //\r
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
+ if (NULL == NewMenuEntry->DisplayString) {\r
+ NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
+ }\r
+\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ gBS->HandleProtocol (\r
+ Handles[Index],\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &SerialIo\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->BaudRate,\r
+ &SerialIo->Mode->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->DataBits,\r
+ &SerialIo->Mode->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->Parity,\r
+ &SerialIo->Mode->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->StopBits,\r
+ &SerialIo->Mode->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
+ TerminalMenu.MenuNumber++;\r
+ }\r
+ }\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
+\r
+ //\r
+ // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
+ //\r
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+ if (OutDevicePath != NULL) {\r
+ UpdateComAttributeFromVariable (OutDevicePath);\r
+ }\r
+\r
+ if (InpDevicePath != NULL) {\r
+ UpdateComAttributeFromVariable (InpDevicePath);\r
+ }\r
+\r
+ if (ErrDevicePath != NULL) {\r
+ UpdateComAttributeFromVariable (ErrDevicePath);\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ NewTerminalContext->TerminalType = 0;\r
+ NewTerminalContext->IsConIn = FALSE;\r
+ NewTerminalContext->IsConOut = FALSE;\r
+ NewTerminalContext->IsStdErr = FALSE;\r
+\r
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Vendor.Header.SubType = MSG_VENDOR_DP;\r
+\r
+ for (Index2 = 0; Index2 < 4; Index2++) {\r
+ CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID));\r
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+ NewDevicePath = AppendDevicePathNode (\r
+ NewTerminalContext->DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+ );\r
+ if (NewMenuEntry->HelpString != NULL) {\r
+ FreePool (NewMenuEntry->HelpString);\r
+ }\r
+ //\r
+ // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
+ // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
+ //\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
+ NewTerminalContext->IsConOut = TRUE;\r
+ NewTerminalContext->TerminalType = (UINT8) Index2;\r
+ }\r
+\r
+ if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
+ NewTerminalContext->IsConIn = TRUE;\r
+ NewTerminalContext->TerminalType = (UINT8) Index2;\r
+ }\r
+\r
+ if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
+ NewTerminalContext->IsStdErr = TRUE;\r
+ NewTerminalContext->TerminalType = (UINT8) Index2;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update Com Ports attributes from DevicePath\r
+\r
+ @param DevicePath DevicePath that contains Com ports\r
+\r
+ @retval EFI_SUCCESS The update is successful.\r
+ @retval EFI_NOT_FOUND Can not find specific menu entry\r
+**/\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *SerialNode;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UART_DEVICE_PATH *Uart;\r
+ UART_DEVICE_PATH *Uart1;\r
+ UINT32 Match;\r
+ UINTN TerminalNumber;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ UINTN Index;\r
+\r
+ Match = EISA_PNP_ID (0x0501);\r
+ Node = DevicePath;\r
+ Node = NextDevicePathNode (Node);\r
+ TerminalNumber = 0;\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
+ }\r
+ }\r
+\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+ Uart = (UART_DEVICE_PATH *) Node;\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ CopyMem (\r
+ &NewTerminalContext->BaudRate,\r
+ &Uart->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->DataBits,\r
+ &Uart->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->Parity,\r
+ &Uart->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->StopBits,\r
+ &Uart->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ SerialNode = NewTerminalContext->DevicePath;\r
+ SerialNode = NextDevicePathNode (SerialNode);\r
+ while (!IsDevicePathEnd (SerialNode)) {\r
+ if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
+ //\r
+ // Update following device paths according to\r
+ // previous acquired uart attributes\r
+ //\r
+ Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
+ CopyMem (\r
+ &Uart1->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+ CopyMem (\r
+ &Uart1->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+ CopyMem (\r
+ &Uart1->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ break;\r
+ }\r
+\r
+ SerialNode = NextDevicePathNode (SerialNode);\r
+ }\r
+ //\r
+ // end while\r
+ //\r
+ }\r
+\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+ //\r
+ // end while\r
+ //\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build up Console Menu based on types passed in. The type can\r
+ be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT\r
+ and BM_CONSOLE_ERR_CONTEXT_SELECT.\r
+\r
+ @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT\r
+ and BM_CONSOLE_ERR_CONTEXT_SELECT.\r
+\r
+ @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined.\r
+ @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", \r
+ "ConInDev" or "ConErrDev" doesn't exists.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations.\r
+ @retval EFI_SUCCESS Function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetConsoleMenu (\r
+ IN UINTN ConsoleMenuType\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *AllDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ UINTN Size;\r
+ UINTN AllCount;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ TYPE_OF_TERMINAL Terminal;\r
+ UINTN Com;\r
+ BM_MENU_OPTION *ConsoleMenu;\r
+\r
+ DevicePath = NULL;\r
+ AllDevicePath = NULL;\r
+ AllCount = 0;\r
+ switch (ConsoleMenuType) {\r
+ case BM_CONSOLE_IN_CONTEXT_SELECT:\r
+ ConsoleMenu = &ConsoleInpMenu;\r
+ DevicePath = EfiLibGetVariable (\r
+ L"ConIn",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+\r
+ AllDevicePath = EfiLibGetVariable (\r
+ L"ConInDev",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+ break;\r
+\r
+ case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
+ ConsoleMenu = &ConsoleOutMenu;\r
+ DevicePath = EfiLibGetVariable (\r
+ L"ConOut",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+\r
+ AllDevicePath = EfiLibGetVariable (\r
+ L"ConOutDev",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+ break;\r
+\r
+ case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
+ ConsoleMenu = &ConsoleErrMenu;\r
+ DevicePath = EfiLibGetVariable (\r
+ L"ErrOut",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+\r
+ AllDevicePath = EfiLibGetVariable (\r
+ L"ErrOutDev",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (NULL == AllDevicePath) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ InitializeListHead (&ConsoleMenu->Head);\r
+\r
+ AllCount = EfiDevicePathInstanceCount (AllDevicePath);\r
+ ConsoleMenu->MenuNumber = 0;\r
+ //\r
+ // Following is menu building up for Console Devices selected.\r
+ //\r
+ MultiDevicePath = AllDevicePath;\r
+ Index2 = 0;\r
+ for (Index = 0; Index < AllCount; Index++) {\r
+ DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewMenuEntry->OptionNumber = Index2;\r
+\r
+ NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst);\r
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
+ if (NULL == NewMenuEntry->DisplayString) {\r
+ NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
+ }\r
+\r
+ NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
+ NewConsoleContext->DevicePath,\r
+ &Terminal,\r
+ &Com\r
+ );\r
+\r
+ NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
+ DevicePath,\r
+ NewConsoleContext->DevicePath\r
+ );\r
+\r
+ if (NewConsoleContext->IsTerminal) {\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+ } else {\r
+ Index2++;\r
+ ConsoleMenu->MenuNumber++;\r
+ InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+ @retval EFI_SUCCESS The function always complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAllConsoles (\r
+ VOID\r
+ )\r
+{\r
+ GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
+ GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
+ GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+ @retval EFI_SUCCESS The function always complete successfully.\r
+**/\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+ VOID\r
+ )\r
+{\r
+ BOpt_FreeMenu (&ConsoleOutMenu);\r
+ BOpt_FreeMenu (&ConsoleInpMenu);\r
+ BOpt_FreeMenu (&ConsoleErrMenu);\r
+ BOpt_FreeMenu (&TerminalMenu);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Test whether DevicePath is a valid Terminal\r
+\r
+\r
+ @param DevicePath DevicePath to be checked\r
+ @param Termi If DevicePath is valid Terminal, terminal type is returned.\r
+ @param Com If DevicePath is valid Terminal, Com Port type is returned.\r
+\r
+ @retval TRUE If DevicePath point to a Terminal.\r
+ @retval FALSE If DevicePath does not point to a Terminal.\r
+\r
+**/\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT TYPE_OF_TERMINAL *Termi,\r
+ OUT UINTN *Com\r
+ )\r
+{\r
+ UINT8 *Ptr;\r
+ BOOLEAN IsTerminal;\r
+ VENDOR_DEVICE_PATH *Vendor;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UINT32 Match;\r
+ EFI_GUID TempGuid;\r
+\r
+ IsTerminal = FALSE;\r
+\r
+ //\r
+ // Parse the Device Path, should be change later!!!\r
+ //\r
+ Ptr = (UINT8 *) DevicePath;\r
+ while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+ Ptr++;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
+ Vendor = (VENDOR_DEVICE_PATH *) Ptr;\r
+\r
+ //\r
+ // There are four kinds of Terminal types\r
+ // check to see whether this devicepath\r
+ // is one of that type\r
+ //\r
+ CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
+\r
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[0])) {\r
+ *Termi = PC_ANSI;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[1])) {\r
+ *Termi = VT_100;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[2])) {\r
+ *Termi = VT_100_PLUS;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ if (CompareGuid (&TempGuid, &TerminalTypeGuid[3])) {\r
+ *Termi = VT_UTF8;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ IsTerminal = FALSE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!IsTerminal) {\r
+ return FALSE;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+ Match = EISA_PNP_ID (0x0501);\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
+ } else {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Get mode number according to column and row\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+GetConsoleOutMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN Col;\r
+ UINTN Row;\r
+ UINTN CurrentCol;\r
+ UINTN CurrentRow;\r
+ UINTN Mode;\r
+ UINTN MaxMode;\r
+ EFI_STATUS Status;\r
+ CONSOLE_OUT_MODE *ModeInfo;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
+\r
+ ConOut = gST->ConOut;\r
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);\r
+ ModeInfo = EfiLibGetVariable (VAR_CON_OUT_MODE, &gEfiGenericPlatformVariableGuid);\r
+\r
+ if (ModeInfo != NULL) {\r
+ CurrentCol = ModeInfo->Column;\r
+ CurrentRow = ModeInfo->Row;\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+ if (!EFI_ERROR(Status)) {\r
+ if (CurrentCol == Col && CurrentRow == Row) {\r
+ CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ FreePool (ModeInfo);\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ Define some data used for Boot Maint\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_HII_UPDATE_DATA gUpdateData;\r
+STRING_DEPOSITORY *FileOptionStrDepository;\r
+STRING_DEPOSITORY *ConsoleOptionStrDepository;\r
+STRING_DEPOSITORY *BootOptionStrDepository;\r
+STRING_DEPOSITORY *BootOptionHelpStrDepository;\r
+STRING_DEPOSITORY *DriverOptionStrDepository;\r
+STRING_DEPOSITORY *DriverOptionHelpStrDepository;\r
+STRING_DEPOSITORY *TerminalStrDepository;\r
+\r
+///\r
+/// Terminal type string token storage\r
+///\r
+UINT16 TerminalType[] = {\r
+ STRING_TOKEN(STR_COM_TYPE_0),\r
+ STRING_TOKEN(STR_COM_TYPE_1),\r
+ STRING_TOKEN(STR_COM_TYPE_2),\r
+ STRING_TOKEN(STR_COM_TYPE_3),\r
+};\r
+\r
+///\r
+/// File system selection menu\r
+///\r
+BM_MENU_OPTION FsOptionMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Console Input Device Selection Menu\r
+///\r
+BM_MENU_OPTION ConsoleInpMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Console Output Device Selection Menu\r
+///\r
+BM_MENU_OPTION ConsoleOutMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Error Output Device Selection Menu\r
+///\r
+BM_MENU_OPTION ConsoleErrMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Boot Option from variable Menu\r
+///\r
+BM_MENU_OPTION BootOptionMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Driver Option from variable menu\r
+///\r
+BM_MENU_OPTION DriverOptionMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Legacy FD Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION LegacyFDMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Legacy HD Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION LegacyHDMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Legacy CD Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION LegacyCDMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION LegacyNETMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION LegacyBEVMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Files and sub-directories in current directory menu\r
+///\r
+BM_MENU_OPTION DirectoryMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Handles in current system selection menu\r
+///\r
+BM_MENU_OPTION DriverMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+BM_MENU_OPTION TerminalMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ {NULL},\r
+ 0\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for BaudRate\r
+///\r
+COM_ATTR BaudRateList[19] = {\r
+ {\r
+ 115200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_0)\r
+ },\r
+ {\r
+ 57600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_1)\r
+ },\r
+ {\r
+ 38400,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_2)\r
+ },\r
+ {\r
+ 19200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_3)\r
+ },\r
+ {\r
+ 9600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_4)\r
+ },\r
+ {\r
+ 7200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_5)\r
+ },\r
+ {\r
+ 4800,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_6)\r
+ },\r
+ {\r
+ 3600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_7)\r
+ },\r
+ {\r
+ 2400,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_8)\r
+ },\r
+ {\r
+ 2000,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_9)\r
+ },\r
+ {\r
+ 1800,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_10)\r
+ },\r
+ {\r
+ 1200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_11)\r
+ },\r
+ {\r
+ 600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_12)\r
+ },\r
+ {\r
+ 300,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_13)\r
+ },\r
+ {\r
+ 150,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_14)\r
+ },\r
+ {\r
+ 134,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_15)\r
+ },\r
+ {\r
+ 110,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_16)\r
+ },\r
+ {\r
+ 75,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_17)\r
+ },\r
+ {\r
+ 50,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_18)\r
+ }\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for DataBits\r
+///\r
+COM_ATTR DataBitsList[4] = {\r
+ {\r
+ 5,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_0)\r
+ },\r
+ {\r
+ 6,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_1)\r
+ },\r
+ {\r
+ 7,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_2)\r
+ },\r
+ {\r
+ 8,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_3)\r
+ }\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for Parity\r
+///\r
+COM_ATTR ParityList[5] = {\r
+ {\r
+ NoParity,\r
+ STRING_TOKEN(STR_COM_PAR_0)\r
+ },\r
+ {\r
+ EvenParity,\r
+ STRING_TOKEN(STR_COM_PAR_1)\r
+ },\r
+ {\r
+ OddParity,\r
+ STRING_TOKEN(STR_COM_PAR_2)\r
+ },\r
+ {\r
+ MarkParity,\r
+ STRING_TOKEN(STR_COM_PAR_3)\r
+ },\r
+ {\r
+ SpaceParity,\r
+ STRING_TOKEN(STR_COM_PAR_4)\r
+ }\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for Baudreate\r
+///\r
+COM_ATTR StopBitsList[3] = {\r
+ {\r
+ OneStopBit,\r
+ STRING_TOKEN(STR_COM_STOP_BITS_0)\r
+ },\r
+ {\r
+ OneFiveStopBits,\r
+ STRING_TOKEN(STR_COM_STOP_BITS_1)\r
+ },\r
+ {\r
+ TwoStopBits,\r
+ STRING_TOKEN(STR_COM_STOP_BITS_2)\r
+ }\r
+};\r
+\r
+///\r
+/// Guid for messaging path, used in Serial port setting.\r
+///\r
+EFI_GUID TerminalTypeGuid[4] = {\r
+ DEVICE_PATH_MESSAGING_PC_ANSI,\r
+ DEVICE_PATH_MESSAGING_VT_100,\r
+ DEVICE_PATH_MESSAGING_VT_100_PLUS,\r
+ DEVICE_PATH_MESSAGING_VT_UTF8\r
+};\r
--- /dev/null
+///** @file\r
+// \r
+// File Explorer Formset\r
+// \r
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+// \r
+//**/\r
+\r
+#include "FormGuid.h"\r
+\r
+#define LABEL_END 0xffff\r
+\r
+formset\r
+ guid = FILE_EXPLORE_FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ class = 0,\r
+ subclass = 0,\r
+\r
+ varstore FILE_EXPLORER_NV_DATA,\r
+ varid = VARSTORE_ID_BOOT_MAINT,\r
+ name = FeData,\r
+ guid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+ form formid = FORM_FILE_EXPLORER_ID,\r
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+ label FORM_FILE_EXPLORER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_ADD_DESCRIPTION_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);\r
+\r
+ label FORM_BOOT_ADD_DESCRIPTION_ID;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ string varid = FeData.DescriptionData,\r
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 6,\r
+ maxsize = 75,\r
+ endstring;\r
+\r
+ string varid = FeData.OptionalData,\r
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 0,\r
+ maxsize = 120,\r
+ endstring;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_SAVE_AND_EXIT_BOOT;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+ label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ string varid = FeData.DescriptionData,\r
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 6,\r
+ maxsize = 75,\r
+ endstring;\r
+\r
+ string varid = FeData.OptionalData,\r
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 0,\r
+ maxsize = 120,\r
+ endstring;\r
+\r
+ checkbox varid = FeData.ForceReconnect,\r
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+ help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+ flags = CHECKBOX_DEFAULT,\r
+ key = 0,\r
+ endcheckbox;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset???\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;\r
+\r
+ endform;\r
+\r
+endformset;
\ No newline at end of file
--- /dev/null
+/** @file\r
+ File explorer related functions.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+\r
+/**\r
+ Update the File Explore page.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param MenuOption Pointer to menu options to display.\r
+\r
+**/\r
+VOID\r
+UpdateFileExplorePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ BM_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ UINTN Index;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_FILE_CONTEXT *NewFileContext;\r
+ EFI_FORM_ID FormId;\r
+\r
+ NewMenuEntry = NULL;\r
+ NewFileContext = NULL;\r
+ FormId = 0;\r
+\r
+ RefreshUpdateData ();\r
+\r
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ if (NewFileContext->IsBootLegacy) {\r
+ continue;\r
+ }\r
+\r
+ if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {\r
+ //\r
+ // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.\r
+ //\r
+ CreateActionOpCode (\r
+ (UINT16) (FILE_OPTION_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+ } else {\r
+ //\r
+ // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.\r
+ //\r
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+ } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {\r
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+ }\r
+\r
+ CreateGotoOpCode (\r
+ FormId,\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (FILE_OPTION_OFFSET + Index),\r
+ &gUpdateData\r
+ );\r
+ }\r
+ }\r
+\r
+ IfrLibUpdateForm (\r
+ CallbackData->FeHiiHandle,\r
+ &mFileExplorerGuid,\r
+ FORM_FILE_EXPLORER_ID,\r
+ FORM_FILE_EXPLORER_ID,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+}\r
+\r
+/**\r
+ Update the file explower page with the refershed file system.\r
+\r
+\r
+ @param CallbackData BMM context data\r
+ @param KeyValue Key value to identify the type of data to expect.\r
+\r
+ @retval TRUE Inform the caller to create a callback packet to exit file explorer.\r
+ @retval FALSE Indicate that there is no need to exit file explorer.\r
+\r
+**/\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN UINT16 KeyValue\r
+ )\r
+{\r
+ UINT16 FileOptionMask;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_FILE_CONTEXT *NewFileContext;\r
+ EFI_FORM_ID FormId;\r
+ BOOLEAN ExitFileExplorer;\r
+ EFI_STATUS Status;\r
+\r
+ NewMenuEntry = NULL;\r
+ NewFileContext = NULL;\r
+ ExitFileExplorer = FALSE;\r
+\r
+ FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+\r
+ if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {\r
+ //\r
+ // First in, display file system.\r
+ //\r
+ BOpt_FreeMenu (&FsOptionMenu);\r
+ BOpt_FindFileSystem (CallbackData);\r
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);\r
+\r
+ UpdateFileExplorePage (CallbackData, &FsOptionMenu);\r
+\r
+ CallbackData->FeDisplayContext = FILE_SYSTEM;\r
+ } else {\r
+ if (FILE_SYSTEM == CallbackData->FeDisplayContext) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);\r
+ } else if (DIRECTORY == CallbackData->FeDisplayContext) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);\r
+ }\r
+\r
+ CallbackData->FeDisplayContext = DIRECTORY;\r
+\r
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ if (NewFileContext->IsDir ) {\r
+ RemoveEntryList (&NewMenuEntry->Link);\r
+ BOpt_FreeMenu (&DirectoryMenu);\r
+ Status = BOpt_FindFiles (CallbackData, NewMenuEntry);\r
+ if (EFI_ERROR (Status)) {\r
+ ExitFileExplorer = TRUE;\r
+ goto exit;\r
+ }\r
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+\r
+ UpdateFileExplorePage (CallbackData, &DirectoryMenu);\r
+\r
+ } else {\r
+ switch (CallbackData->FeCurrentState) {\r
+ case BOOT_FROM_FILE_STATE:\r
+ //\r
+ // Here boot from file\r
+ //\r
+ BootThisFile (NewFileContext);\r
+ ExitFileExplorer = TRUE;\r
+ break;\r
+\r
+ case ADD_BOOT_OPTION_STATE:\r
+ case ADD_DRIVER_OPTION_STATE:\r
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+ } else {\r
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+ }\r
+\r
+ CallbackData->MenuEntry = NewMenuEntry;\r
+ CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;\r
+\r
+ //\r
+ // Create Subtitle op-code for the display string of the option.\r
+ //\r
+ RefreshUpdateData ();\r
+\r
+ CreateSubTitleOpCode (\r
+ NewMenuEntry->DisplayStringToken,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ CallbackData->FeHiiHandle,\r
+ &mFileExplorerGuid,\r
+ FormId,\r
+ FormId,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ exit:\r
+ return ExitFileExplorer;\r
+}\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+ When user select a interactive opcode, this callback will be triggered.\r
+ Based on the Question(QuestionId) that triggers the callback, the corresponding\r
+ actions is performed. It handles:\r
+\r
+ 1) the addition of boot option.\r
+ 2) the addition of driver option.\r
+ 3) exit from file browser\r
+ 4) update of file content if a dir is selected.\r
+ 5) boot the file if a file is selected in "boot from file"\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
+ @retval EFI_DEVICE_ERROR The variable could not be saved.\r
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
+ @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ BMM_CALLBACK_DATA *Private;\r
+ FILE_EXPLORER_NV_DATA *NvRamMap;\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Private = FE_CALLBACK_DATA_FROM_THIS (This);\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ //\r
+ // Retrieve uncommitted data from Form Browser\r
+ //\r
+ NvRamMap = &Private->FeFakeNvData;\r
+ BufferSize = sizeof (FILE_EXPLORER_NV_DATA);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) NvRamMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
+ //\r
+ // Apply changes and exit formset\r
+ //\r
+ if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {\r
+ Status = Var_UpdateBootOption (Private, NvRamMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_GetBootOptions (Private);\r
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);\r
+ } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {\r
+ Status = Var_UpdateDriverOption (\r
+ Private,\r
+ Private->FeHiiHandle,\r
+ NvRamMap->DescriptionData,\r
+ NvRamMap->OptionalData,\r
+ NvRamMap->ForceReconnect\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_GetDriverOptions (Private);\r
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);\r
+ }\r
+\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
+ //\r
+ // Discard changes and exit formset\r
+ //\r
+ NvRamMap->OptionalData[0] = 0x0000;\r
+ NvRamMap->DescriptionData[0] = 0x0000;\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ } else if (QuestionId < FILE_OPTION_OFFSET) {\r
+ //\r
+ // Exit File Explorer formset\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ } else {\r
+ if (UpdateFileExplorer (Private, QuestionId)) {\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ Formset guids, form id and VarStore data structure for Boot Maintenance Manager.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef _FORM_GUID_H_\r
+#define _FORM_GUID_H_\r
+\r
+#define BOOT_MAINT_FORMSET_GUID \\r
+ { \\r
+ 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \\r
+ }\r
+\r
+#define FILE_EXPLORE_FORMSET_GUID \\r
+ { \\r
+ 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \\r
+ }\r
+\r
+#define FORM_MAIN_ID 0x1001\r
+#define FORM_BOOT_ADD_ID 0x1002\r
+#define FORM_BOOT_DEL_ID 0x1003\r
+#define FORM_BOOT_CHG_ID 0x1004\r
+#define FORM_DRV_ADD_ID 0x1005\r
+#define FORM_DRV_DEL_ID 0x1006\r
+#define FORM_DRV_CHG_ID 0x1007\r
+#define FORM_CON_MAIN_ID 0x1008\r
+#define FORM_CON_IN_ID 0x1009\r
+#define FORM_CON_OUT_ID 0x100A\r
+#define FORM_CON_ERR_ID 0x100B\r
+#define FORM_FILE_SEEK_ID 0x100C\r
+#define FORM_FILE_NEW_SEEK_ID 0x100D\r
+#define FORM_DRV_ADD_FILE_ID 0x100E\r
+#define FORM_DRV_ADD_HANDLE_ID 0x100F\r
+#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010\r
+#define FORM_BOOT_NEXT_ID 0x1011\r
+#define FORM_TIME_OUT_ID 0x1012\r
+#define FORM_RESET 0x1013\r
+#define FORM_BOOT_SETUP_ID 0x1014\r
+#define FORM_DRIVER_SETUP_ID 0x1015\r
+#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016\r
+#define FORM_CON_COM_ID 0x1017\r
+#define FORM_CON_COM_SETUP_ID 0x1018\r
+#define FORM_SET_FD_ORDER_ID 0x1019\r
+#define FORM_SET_HD_ORDER_ID 0x101A\r
+#define FORM_SET_CD_ORDER_ID 0x101B\r
+#define FORM_SET_NET_ORDER_ID 0x101C\r
+#define FORM_SET_BEV_ORDER_ID 0x101D\r
+#define FORM_FILE_EXPLORER_ID 0x101E\r
+#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F\r
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020\r
+#define FORM_CON_MODE_ID 0x1021\r
+\r
+#define MAXIMUM_FORM_ID 0x10FF\r
+\r
+#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101\r
+#define KEY_VALUE_COM_SET_DATA_BITS 0x1102\r
+#define KEY_VALUE_COM_SET_STOP_BITS 0x1103\r
+#define KEY_VALUE_COM_SET_PARITY 0x1104\r
+#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105\r
+#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106\r
+#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107\r
+#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108\r
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109\r
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A\r
+#define KEY_VALUE_SAVE_AND_EXIT 0x110B\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C\r
+#define KEY_VALUE_BOOT_FROM_FILE 0x110D\r
+\r
+#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF\r
+\r
+//\r
+// Varstore ID defined for Buffer Stoarge\r
+//\r
+#define VARSTORE_ID_BOOT_MAINT 0x1000\r
+#define VARSTORE_ID_FILE_EXPLORER 0x1001\r
+\r
+///\r
+/// This is the structure that will be used to store the\r
+/// question's current value. Use it at initialize time to\r
+/// set default value for each question. When using at run\r
+/// time, this map is returned by the callback function,\r
+/// so dynamically changing the question's value will be\r
+/// possible through this mechanism\r
+///\r
+typedef struct {\r
+ //\r
+ // Three questions displayed at the main page\r
+ // for Timeout, BootNext Variables respectively\r
+ //\r
+ UINT16 BootTimeOut;\r
+ UINT16 BootNext;\r
+\r
+ //\r
+ // This is the COM1 Attributes value storage\r
+ //\r
+ UINT8 COM1BaudRate;\r
+ UINT8 COM1DataRate;\r
+ UINT8 COM1StopBits;\r
+ UINT8 COM1Parity;\r
+ UINT8 COM1TerminalType;\r
+\r
+ //\r
+ // This is the COM2 Attributes value storage\r
+ //\r
+ UINT8 COM2BaudRate;\r
+ UINT8 COM2DataRate;\r
+ UINT8 COM2StopBits;\r
+ UINT8 COM2Parity;\r
+ UINT8 COM2TerminalType;\r
+\r
+ //\r
+ // Driver Option Add Handle page storage\r
+ //\r
+ UINT16 DriverAddHandleDesc[100];\r
+ UINT16 DriverAddHandleOptionalData[100];\r
+ UINT8 DriverAddActive;\r
+ UINT8 DriverAddForceReconnect;\r
+\r
+ //\r
+ // Console Input/Output/Errorout using COM port check storage\r
+ //\r
+ UINT8 ConsoleInputCOM1;\r
+ UINT8 ConsoleInputCOM2;\r
+ UINT8 ConsoleOutputCOM1;\r
+ UINT8 ConsoleOutputCOM2;\r
+ UINT8 ConsoleErrorCOM1;\r
+ UINT8 ConsoleErrorCOM2;\r
+\r
+ //\r
+ // At most 100 input/output/errorout device for console storage\r
+ //\r
+ UINT8 ConsoleCheck[100];\r
+\r
+ //\r
+ // Boot or Driver Option Order storage\r
+ //\r
+ UINT8 OptionOrder[100];\r
+ UINT8 DriverOptionToBeDeleted[100];\r
+\r
+ //\r
+ // Boot Option Delete storage\r
+ //\r
+ UINT8 BootOptionDel[100];\r
+ UINT8 DriverOptionDel[100];\r
+\r
+ //\r
+ // This is the Terminal Attributes value storage\r
+ //\r
+ UINT8 COMBaudRate;\r
+ UINT8 COMDataRate;\r
+ UINT8 COMStopBits;\r
+ UINT8 COMParity;\r
+ UINT8 COMTerminalType;\r
+\r
+ //\r
+ // Legacy Device Order Selection Storage\r
+ //\r
+ UINT8 LegacyFD[100];\r
+ UINT8 LegacyHD[100];\r
+ UINT8 LegacyCD[100];\r
+ UINT8 LegacyNET[100];\r
+ UINT8 LegacyBEV[100];\r
+\r
+ //\r
+ // We use DisableMap array to record the enable/disable state of each boot device\r
+ // It should be taken as a bit array, from left to right there are totally 256 bits\r
+ // the most left one stands for BBS table item 0, and the most right one stands for item 256\r
+ // If the bit is 1, it means the boot device has been disabled.\r
+ //\r
+ UINT8 DisableMap[32];\r
+\r
+ //\r
+ // Console Output Text Mode\r
+ //\r
+ UINT16 ConsoleOutMode;\r
+\r
+ //\r
+ // UINT16 PadArea[10];\r
+ //\r
+} BMM_FAKE_NV_DATA;\r
+\r
+//\r
+// Key used by File Explorer forms\r
+//\r
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001\r
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003\r
+\r
+///\r
+/// This is the data structure used by File Explorer formset\r
+///\r
+typedef struct {\r
+ UINT16 DescriptionData[75];\r
+ UINT16 OptionalData[127];\r
+ UINT8 Active;\r
+ UINT8 ForceReconnect;\r
+} FILE_EXPLORER_NV_DATA;\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+Dynamically update the pages.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+\r
+/**\r
+ Refresh the global UpdateData structure.\r
+\r
+**/\r
+VOID\r
+RefreshUpdateData (\r
+ VOID\r
+ )\r
+{\r
+ gUpdateData.Offset = 0;\r
+}\r
+\r
+/**\r
+ Add a "Go back to main page" tag in front of the form when there are no\r
+ "Apply changes" and "Discard changes" tags in the end of the form.\r
+ \r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdatePageStart (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ RefreshUpdateData ();\r
+\r
+ if (!(CallbackData->BmmAskSaveOrNot)) {\r
+ //\r
+ // Add a "Go back to main page" tag in front of the form when there are no\r
+ // "Apply changes" and "Discard changes" tags in the end of the form.\r
+ //\r
+ CreateGotoOpCode (\r
+ FORM_MAIN_ID,\r
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+ 0,\r
+ FORM_MAIN_ID,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Create the "Apply changes" and "Discard changes" tags. And\r
+ ensure user can return to the main page.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdatePageEnd (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ //\r
+ // Create the "Apply changes" and "Discard changes" tags.\r
+ //\r
+ if (CallbackData->BmmAskSaveOrNot) {\r
+ CreateSubTitleOpCode (\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ 0,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_MAIN_ID,\r
+ STRING_TOKEN (STR_SAVE_AND_EXIT),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ KEY_VALUE_SAVE_AND_EXIT,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ //\r
+ // Ensure user can return to the main page.\r
+ //\r
+ CreateGotoOpCode (\r
+ FORM_MAIN_ID,\r
+ STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ KEY_VALUE_NO_SAVE_AND_EXIT,\r
+ &gUpdateData\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ CallbackData->BmmHiiHandle,\r
+ &mBootMaintGuid,\r
+ CallbackData->BmmCurrentPageId,\r
+ CallbackData->BmmCurrentPageId,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+}\r
+\r
+/**\r
+ Clean up the dynamic opcode at label and form specified by both LabelId. \r
+\r
+ @param LabelId It is both the Form ID and Label ID for opcode deletion.\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+CleanUpPage (\r
+ IN UINT16 LabelId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ RefreshUpdateData ();\r
+\r
+ //\r
+ // Remove all op-codes from dynamic page\r
+ //\r
+ IfrLibUpdateForm (\r
+ CallbackData->BmmHiiHandle,\r
+ &mBootMaintGuid,\r
+ LabelId,\r
+ LabelId,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+}\r
+\r
+/**\r
+ Boot a file selected by user at File Expoloer of BMM.\r
+\r
+ @param FileContext The file context data, which contains the device path\r
+ of the file to be boot from.\r
+\r
+ @retval EFI_SUCCESS The function completed successfull.\r
+ @return Other value if the boot from the file fails.\r
+\r
+**/\r
+EFI_STATUS\r
+BootThisFile (\r
+ IN BM_FILE_CONTEXT *FileContext\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ BDS_COMMON_OPTION *Option;\r
+\r
+ Option = (BDS_COMMON_OPTION *) AllocatePool (sizeof (BDS_COMMON_OPTION));\r
+ ASSERT (Option != NULL);\r
+ Option->Description = FileContext->FileName;\r
+ Option->DevicePath = FileContext->DevicePath;\r
+ Option->LoadOptionsSize = 0;\r
+ Option->LoadOptions = NULL;\r
+\r
+ //\r
+ // Since current no boot from removable media directly is allowed */\r
+ //\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+ ExitDataSize = 0;\r
+\r
+ Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Create a list of Goto Opcode for all terminal devices logged\r
+ by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.\r
+\r
+ @param CallbackData The BMM context data.\r
+**/\r
+VOID\r
+UpdateConCOMPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+\r
+ CreateGotoOpCode (\r
+ FORM_CON_COM_SETUP_ID,\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (TERMINAL_OPTION_OFFSET + Index),\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Create a lit of boot option from global BootOptionMenu. It\r
+ allow user to delete the boot option.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateBootDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0])));\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (NewLoadContext->IsLegacy) {\r
+ continue;\r
+ }\r
+\r
+ NewLoadContext->Deleted = FALSE;\r
+ CallbackData->BmmFakeNvData.BootOptionDel[Index] = 0x00;\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Create a lit of driver option from global DriverMenu.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
+\r
+ CreateGotoOpCode (\r
+ FORM_DRV_ADD_HANDLE_DESC_ID,\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (HANDLE_OPTION_OFFSET + Index),\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Create a lit of driver option from global DriverOptionMenu. It\r
+ allow user to delete the driver option.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateDrvDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);\r
+ \r
+ ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0])));\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = FALSE;\r
+ CallbackData->BmmFakeNvData.DriverOptionDel[Index] = 0x00;\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Prepare the page to allow user to add description for \r
+ a Driver Option.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+ CallbackData->BmmFakeNvData.DriverAddActive = 0x01;\r
+ CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00;\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+ NewMenuEntry = CallbackData->MenuEntry;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ CreateSubTitleOpCode (\r
+ NewMenuEntry->DisplayStringToken,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateStringOpCode (\r
+ (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ DRV_ADD_HANDLE_DESC_VAR_OFFSET,\r
+ STRING_TOKEN (STR_LOAD_OPTION_DESC),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ 0,\r
+ 0,\r
+ 6,\r
+ 75,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ DRV_ADD_RECON_VAR_OFFSET,\r
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateStringOpCode (\r
+ (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ DRIVER_ADD_OPTION_VAR_OFFSET,\r
+ STRING_TOKEN (STR_OPTIONAL_DATA),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ 0,\r
+ 0,\r
+ 6,\r
+ 75,\r
+ &gUpdateData\r
+ );\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Update console page.\r
+\r
+ @param UpdatePageId The form ID to be updated.\r
+ @param ConsoleMenu The console menu list.\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateConsolePage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BM_MENU_OPTION *ConsoleMenu,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ UINT16 Index;\r
+ UINT16 Index2;\r
+ UINT8 CheckFlags;\r
+ \r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ ASSERT (ConsoleMenu->MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.ConsoleCheck) / sizeof (CallbackData->BmmFakeNvData.ConsoleCheck[0])));\r
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ CheckFlags = 0;\r
+ if (NewConsoleContext->IsActive) {\r
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+ } else {\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+ }\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ CheckFlags,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {\r
+ CheckFlags = 0;\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+ ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+ ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))\r
+ ) {\r
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+ } else {\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+ }\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ CheckFlags,\r
+ &gUpdateData\r
+ );\r
+\r
+ Index++;\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Update the page's NV Map if user has changed the order\r
+ a list. This list can be Boot Order or Driver Order.\r
+\r
+ @param UpdatePageId The form ID to be updated.\r
+ @param OptionMenu The new list.\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateOrderPage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BM_MENU_OPTION *OptionMenu,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 Index;\r
+ IFR_OPTION *IfrOptionList;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+ ZeroMem (CallbackData->BmmFakeNvData.OptionOrder, 100);\r
+\r
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);\r
+ if (IfrOptionList == NULL) {\r
+ return ;\r
+ }\r
+ \r
+ ASSERT (OptionMenu->MenuNumber <= (sizeof (IfrOptionList) / sizeof (IfrOptionList[0])));\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+ IfrOptionList[Index].Value.u8 = (UINT8) (NewMenuEntry->OptionNumber + 1);\r
+ IfrOptionList[Index].Flags = 0;\r
+ CallbackData->BmmFakeNvData.OptionOrder[Index] = IfrOptionList[Index].Value.u8;\r
+ }\r
+\r
+ if (OptionMenu->MenuNumber > 0) {\r
+ CreateOrderedListOpCode (\r
+ (EFI_QUESTION_ID) OPTION_ORDER_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ OPTION_ORDER_VAR_OFFSET,\r
+ STRING_TOKEN (STR_CHANGE_ORDER),\r
+ STRING_TOKEN (STR_CHANGE_ORDER),\r
+ 0,\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ 100,\r
+ IfrOptionList,\r
+ OptionMenu->MenuNumber,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ FreePool (IfrOptionList);\r
+\r
+ UpdatePageEnd (CallbackData);\r
+\r
+ CopyMem (\r
+ CallbackData->BmmOldFakeNVData.OptionOrder,\r
+ CallbackData->BmmFakeNvData.OptionOrder,\r
+ 100\r
+ );\r
+}\r
+\r
+/**\r
+ Create the dynamic page to allow user to set\r
+ the "BootNext" value.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateBootNextPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ IFR_OPTION *IfrOptionList;\r
+ UINTN NumberOfOptions;\r
+ UINT16 Index;\r
+\r
+ IfrOptionList = NULL;\r
+ NumberOfOptions = BootOptionMenu.MenuNumber;\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+ if (NumberOfOptions > 0) {\r
+ IfrOptionList = AllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));\r
+\r
+ ASSERT (IfrOptionList);\r
+\r
+ CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);\r
+\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (NewLoadContext->IsBootNext) {\r
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ CallbackData->BmmFakeNvData.BootNext = Index;\r
+ } else {\r
+ IfrOptionList[Index].Flags = 0;\r
+ }\r
+\r
+ IfrOptionList[Index].Value.u16 = Index;\r
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+ }\r
+\r
+ IfrOptionList[Index].Value.u16 = Index;\r
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_NONE);\r
+ IfrOptionList[Index].Flags = 0;\r
+ if (CallbackData->BmmFakeNvData.BootNext == Index) {\r
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ BOOT_NEXT_VAR_OFFSET,\r
+ STRING_TOKEN (STR_BOOT_NEXT),\r
+ STRING_TOKEN (STR_BOOT_NEXT_HELP),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_2,\r
+ IfrOptionList,\r
+ (UINTN) (NumberOfOptions + 1),\r
+ &gUpdateData\r
+ );\r
+\r
+ FreePool (IfrOptionList);\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Create the dynamic page to allow user to set the "TimeOut" value.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateTimeOutPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINT16 BootTimeOut;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ BootTimeOut = BdsLibGetTimeout ();\r
+\r
+ CreateNumericOpCode (\r
+ (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ BOOT_TIME_OUT_VAR_OFFSET,\r
+ STRING_TOKEN (STR_NUM_AUTO_BOOT),\r
+ STRING_TOKEN (STR_HLP_AUTO_BOOT),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,\r
+ 0,\r
+ 65535,\r
+ 0,\r
+ BootTimeOut,\r
+ &gUpdateData\r
+ );\r
+\r
+ CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Refresh the text mode page.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateConModePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN Mode;\r
+ UINTN Index;\r
+ UINTN Col;\r
+ UINTN Row;\r
+ CHAR16 RowString[50];\r
+ CHAR16 ModeString[50];\r
+ UINTN MaxMode;\r
+ UINTN ValidMode;\r
+ EFI_STRING_ID *ModeToken;\r
+ IFR_OPTION *IfrOptionList;\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
+\r
+ ConOut = gST->ConOut;\r
+ Index = 0;\r
+ ValidMode = 0;\r
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ //\r
+ // Check valid mode\r
+ //\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ ValidMode++;\r
+ }\r
+\r
+ if (ValidMode == 0) {\r
+ return;\r
+ }\r
+\r
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * ValidMode);\r
+ ASSERT(IfrOptionList != NULL);\r
+\r
+ ModeToken = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);\r
+ ASSERT(ModeToken != NULL);\r
+\r
+ //\r
+ // Determin which mode should be the first entry in menu\r
+ //\r
+ GetConsoleOutMode (CallbackData);\r
+\r
+ //\r
+ // Build text mode options\r
+ //\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Build mode string Column x Row\r
+ //\r
+ UnicodeValueToString (ModeString, 0, Col, 0);\r
+ ASSERT ((StrLen (ModeString) + 1) < (sizeof (ModeString) / sizeof (ModeString[0])));\r
+ StrCat (ModeString, L" x ");\r
+ UnicodeValueToString (RowString, 0, Row, 0);\r
+ ASSERT ((StrLen (ModeString) + StrLen(RowString)) < (sizeof (ModeString) / sizeof (ModeString[0])));\r
+ StrCat (ModeString, RowString);\r
+\r
+ HiiLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString);\r
+\r
+ IfrOptionList[Index].StringToken = ModeToken[Index];\r
+ IfrOptionList[Index].Value.u16 = (UINT16) Mode;\r
+ if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {\r
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ } else {\r
+ IfrOptionList[Index].Flags = 0;\r
+ }\r
+ Index++;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ CON_MODE_VAR_OFFSET,\r
+ STRING_TOKEN (STR_CON_MODE_SETUP),\r
+ STRING_TOKEN (STR_CON_MODE_SETUP),\r
+ EFI_IFR_FLAG_RESET_REQUIRED,\r
+ EFI_IFR_NUMERIC_SIZE_2,\r
+ IfrOptionList,\r
+ ValidMode,\r
+ &gUpdateData\r
+ );\r
+ FreePool (IfrOptionList);\r
+ FreePool (ModeToken);\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,\r
+ Parity, Stop Bits, Terminal Type.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateTerminalPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINT8 Index;\r
+ UINT8 CheckFlags;\r
+ IFR_OPTION *IfrOptionList;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (\r
+ &TerminalMenu,\r
+ CallbackData->CurrentTerminal\r
+ );\r
+\r
+ if (NewMenuEntry == NULL) {\r
+ return ;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 19);\r
+ if (IfrOptionList == NULL) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ NewTerminalContext->BaudRateIndex = Index;\r
+ CallbackData->BmmFakeNvData.COMBaudRate = NewTerminalContext->BaudRateIndex;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = BaudRateList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_BAUD_RATE_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_BAUD_RATE),\r
+ STRING_TOKEN (STR_COM_BAUD_RATE),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 19,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) {\r
+ CheckFlags = 0;\r
+\r
+ if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {\r
+ NewTerminalContext->DataBitsIndex = Index;\r
+ CallbackData->BmmFakeNvData.COMDataRate = NewTerminalContext->DataBitsIndex;\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = DataBitsList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_DATA_RATE_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_DATA_BITS),\r
+ STRING_TOKEN (STR_COM_DATA_BITS),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 4,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->Parity == ParityList[Index].Value) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ NewTerminalContext->ParityIndex = (UINT8) Index;\r
+ CallbackData->BmmFakeNvData.COMParity = NewTerminalContext->ParityIndex;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = ParityList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_PARITY_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_PARITY),\r
+ STRING_TOKEN (STR_COM_PARITY),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 5,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ NewTerminalContext->StopBitsIndex = (UINT8) Index;\r
+ CallbackData->BmmFakeNvData.COMStopBits = NewTerminalContext->StopBitsIndex;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = StopBitsList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_STOP_BITS_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_STOP_BITS),\r
+ STRING_TOKEN (STR_COM_STOP_BITS),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 3,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < 4; Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->TerminalType == Index) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = (EFI_STRING_ID) TerminalType[Index];\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_TERMINAL_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+ STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 4,\r
+ &gUpdateData\r
+ );\r
+\r
+ FreePool (IfrOptionList);\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Dispatch the correct update page function to call based on\r
+ the UpdatePageId.\r
+\r
+ @param UpdatePageId The form ID.\r
+ @param CallbackData The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdatePageBody (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ CleanUpPage (UpdatePageId, CallbackData);\r
+ switch (UpdatePageId) {\r
+ case FORM_CON_IN_ID:\r
+ UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_CON_OUT_ID:\r
+ UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_CON_ERR_ID:\r
+ UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_BOOT_CHG_ID:\r
+ UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_DRV_CHG_ID:\r
+ UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Get the index number (#### in Boot####) for the boot option pointed to a BBS legacy device type\r
+ specified by DeviceType.\r
+\r
+ @param DeviceType The legacy device type. It can be floppy, network, harddisk, cdrom,\r
+ etc.\r
+ @param OptionIndex Returns the index number (#### in Boot####).\r
+ @param OptionSize Return the size of the Boot### variable.\r
+\r
+**/\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+ IN UINTN DeviceType,\r
+ OUT UINTN *OptionIndex,\r
+ OUT UINTN *OptionSize\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ VOID *OptionBuffer;\r
+ UINTN OrderSize;\r
+ UINTN Index;\r
+ UINT16 *OrderBuffer;\r
+ CHAR16 StrTemp[100];\r
+ UINT16 FilePathSize;\r
+ UINT8 *Ptr;\r
+ UINT8 *OptionalData;\r
+\r
+ //\r
+ // Get Boot Option number from the size of BootOrder\r
+ //\r
+ OrderBuffer = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &OrderSize\r
+ );\r
+ \r
+ if (OrderBuffer == NULL) {\r
+ return NULL;\r
+ }\r
+ \r
+ for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);\r
+ OptionBuffer = BdsLibGetVariableAndSize (\r
+ StrTemp,\r
+ &gEfiGlobalVariableGuid,\r
+ OptionSize\r
+ );\r
+ if (NULL == OptionBuffer) {\r
+ continue;\r
+ }\r
+\r
+ Ptr = (UINT8 *) OptionBuffer;\r
+ Ptr += sizeof (UINT32);\r
+\r
+ FilePathSize = *(UINT16 *) Ptr;\r
+ Ptr += sizeof (UINT16);\r
+\r
+ Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+ //\r
+ // Now Ptr point to Device Path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ Ptr += FilePathSize;\r
+\r
+ //\r
+ // Now Ptr point to Optional Data\r
+ //\r
+ OptionalData = Ptr;\r
+\r
+ if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&\r
+ (BBS_DEVICE_PATH == DevicePath->Type) &&\r
+ (BBS_BBS_DP == DevicePath->SubType)\r
+ ) {\r
+ *OptionIndex = OrderBuffer[Index];\r
+ FreePool (OrderBuffer);\r
+ return OptionBuffer;\r
+ } else {\r
+ FreePool (OptionBuffer);\r
+ }\r
+ }\r
+\r
+ FreePool (OrderBuffer);\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Create a dynamic page so that Legacy Device boot order\r
+ can be set for specified device type.\r
+\r
+ @param UpdatePageId The form ID. It also spefies the legacy device type.\r
+ @param CallbackData The BMM context data.\r
+\r
+\r
+**/\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+ BM_MENU_OPTION *OptionMenu;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ IFR_OPTION *IfrOptionList;\r
+ EFI_STRING_ID StrRef;\r
+ EFI_STRING_ID StrRefHelp;\r
+ BBS_TYPE BbsType;\r
+ UINTN VarSize;\r
+ UINTN Pos;\r
+ UINTN Bit;\r
+ UINT16 Index;\r
+ UINT16 Key;\r
+ CHAR16 String[100];\r
+ CHAR16 *TypeStr;\r
+ CHAR16 *TypeStrHelp;\r
+ UINT16 VarDevOrder;\r
+ UINT8 *VarData;\r
+ UINT8 *LegacyOrder;\r
+ UINT8 *OldData;\r
+ UINT8 *DisMap;\r
+\r
+ OptionMenu = NULL;\r
+ Key = 0;\r
+ StrRef = 0;\r
+ StrRefHelp = 0;\r
+ TypeStr = NULL;\r
+ TypeStrHelp = NULL;\r
+ BbsType = BBS_FLOPPY;\r
+ LegacyOrder = NULL;\r
+ OldData = NULL;\r
+ DisMap = NULL;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+ UpdatePageStart (CallbackData);\r
+\r
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+\r
+ SetMem (DisMap, 32, 0);\r
+ //\r
+ // Create oneof option list\r
+ //\r
+ switch (UpdatePageId) {\r
+ case FORM_SET_FD_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+ Key = (UINT16) LEGACY_FD_QUESTION_ID;\r
+ TypeStr = STR_FLOPPY;\r
+ TypeStrHelp = STR_FLOPPY_HELP;\r
+ BbsType = BBS_FLOPPY;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyFD;\r
+ break;\r
+\r
+ case FORM_SET_HD_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+ Key = (UINT16) LEGACY_HD_QUESTION_ID;\r
+ TypeStr = STR_HARDDISK;\r
+ TypeStrHelp = STR_HARDDISK_HELP;\r
+ BbsType = BBS_HARDDISK;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyHD;\r
+ break;\r
+\r
+ case FORM_SET_CD_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+ Key = (UINT16) LEGACY_CD_QUESTION_ID;\r
+ TypeStr = STR_CDROM;\r
+ TypeStrHelp = STR_CDROM_HELP;\r
+ BbsType = BBS_CDROM;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyCD;\r
+ break;\r
+\r
+ case FORM_SET_NET_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+ Key = (UINT16) LEGACY_NET_QUESTION_ID;\r
+ TypeStr = STR_NET;\r
+ TypeStrHelp = STR_NET_HELP;\r
+ BbsType = BBS_EMBED_NETWORK;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyNET;\r
+ break;\r
+\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+ Key = (UINT16) LEGACY_BEV_QUESTION_ID;\r
+ TypeStr = STR_BEV;\r
+ TypeStrHelp = STR_BEV_HELP;\r
+ BbsType = BBS_BEV_DEVICE;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
+ break;\r
+\r
+ default:\r
+ DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));\r
+ return;\r
+ }\r
+\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+ IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));\r
+ if (NULL == IfrOptionList) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+ IfrOptionList[Index].Flags = 0;\r
+ if (0 == Index) {\r
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+ }\r
+\r
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+ IfrOptionList[Index].Value.u8 = (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;\r
+ }\r
+ //\r
+ // for item "Disabled"\r
+ //\r
+ IfrOptionList[Index].Flags = 0;\r
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);\r
+ IfrOptionList[Index].Value.u8 = 0xFF;\r
+\r
+ //\r
+ // Get Device Order from variable\r
+ //\r
+ VarData = BdsLibGetVariableAndSize (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ &VarSize\r
+ );\r
+\r
+ if (NULL != VarData) {\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+ while (VarData < VarData + VarSize) {\r
+ if (DevOrder->BbsType == BbsType) {\r
+ break;\r
+ }\r
+\r
+ VarData += sizeof (BBS_TYPE);\r
+ VarData += *(UINT16 *) VarData;\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+ }\r
+ //\r
+ // Create oneof tag here for FD/HD/CD #1 #2\r
+ //\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ //\r
+ // Create the string for oneof tag\r
+ //\r
+ UnicodeSPrint (String, sizeof (String), TypeStr, Index);\r
+ StrRef = 0;\r
+ HiiLibNewString (CallbackData->BmmHiiHandle, &StrRef, String);\r
+\r
+ UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);\r
+ StrRefHelp = 0;\r
+ HiiLibNewString (CallbackData->BmmHiiHandle, &StrRefHelp, String);\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) (Key + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),\r
+ StrRef,\r
+ StrRefHelp,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ OptionMenu->MenuNumber + 1,\r
+ &gUpdateData\r
+ );\r
+\r
+ VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));\r
+\r
+ if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
+ LegacyOrder[Index] = 0xFF;\r
+ Pos = (VarDevOrder & 0xFF) / 8;\r
+ Bit = 7 - ((VarDevOrder & 0xFF) % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+ } else {\r
+ LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);\r
+ }\r
+ }\r
+ }\r
+\r
+ CopyMem (OldData, LegacyOrder, 100);\r
+\r
+ if (IfrOptionList != NULL) {\r
+ FreePool (IfrOptionList);\r
+ IfrOptionList = NULL;\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+ Dispatch the display to the next page based on NewPageId.\r
+\r
+ @param Private The BMM context data.\r
+ @param NewPageId The original page ID.\r
+\r
+**/\r
+VOID\r
+UpdatePageId (\r
+ BMM_CALLBACK_DATA *Private,\r
+ UINT16 NewPageId\r
+ )\r
+{\r
+ if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {\r
+ //\r
+ // If we select a handle to add driver option, advance to the add handle description page.\r
+ //\r
+ NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;\r
+ } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {\r
+ //\r
+ // Return to main page after "Save Changes" or "Discard Changes".\r
+ //\r
+ NewPageId = FORM_MAIN_ID;\r
+ } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {\r
+ NewPageId = FORM_CON_COM_SETUP_ID;\r
+ }\r
+\r
+ if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {\r
+ Private->BmmPreviousPageId = Private->BmmCurrentPageId;\r
+ Private->BmmCurrentPageId = NewPageId;\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ Variable operation that will be used by bootmaint\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootMaint.h"\r
+\r
+/**\r
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+ After deleting this boot option, call Var_ChangeBootOrder to\r
+ make sure BootOrder is in valid state.\r
+\r
+ @retval EFI_SUCCESS If all boot load option EFI Variables corresponding to \r
+ BM_LOAD_CONTEXT marked for deletion is deleted.\r
+ @retval EFI_NOT_FOUND If can not find the boot option want to be deleted.\r
+ @return Others If failed to update the "BootOrder" variable after deletion. \r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+ VOID\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 BootString[10];\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2 = 0;\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (!NewLoadContext->Deleted) {\r
+ continue;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ BootString,\r
+ sizeof (BootString),\r
+ L"Boot%04x",\r
+ NewMenuEntry->OptionNumber\r
+ );\r
+\r
+ EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
+ Index2++;\r
+ //\r
+ // If current Load Option is the same as BootNext,\r
+ // must delete BootNext in order to make sure\r
+ // there will be no panic on next boot\r
+ //\r
+ if (NewLoadContext->IsBootNext) {\r
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ RemoveEntryList (&NewMenuEntry->Link);\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+ NewMenuEntry = NULL;\r
+ }\r
+\r
+ BootOptionMenu.MenuNumber -= Index2;\r
+\r
+ Status = Var_ChangeBootOrder ();\r
+ return Status;\r
+}\r
+\r
+/**\r
+ After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+ Since some are missing but in BootOrder, while some are present but are\r
+ not reflected by BootOrder. Then a function rebuild BootOrder from\r
+ scratch by content from BootOptionMenu is needed.\r
+\r
+\r
+ \r
+\r
+ @retval EFI_SUCCESS The boot order is updated successfully.\r
+ @return EFI_STATUS other than EFI_SUCCESS if failed to\r
+ Set the "BootOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+ VOID\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *BootOrderList;\r
+ UINT16 *BootOrderListPtr;\r
+ UINTN BootOrderListSize;\r
+ UINTN Index;\r
+\r
+ BootOrderList = NULL;\r
+ BootOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether BootOrder is present in current configuration\r
+ //\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ //\r
+ // If exists, delete it to hold new BootOrder\r
+ //\r
+ if (BootOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ FreePool (BootOrderList);\r
+ BootOrderList = NULL;\r
+ }\r
+ //\r
+ // Maybe here should be some check method to ensure that\r
+ // no new added boot options will be added\r
+ // but the setup engine now will give only one callback\r
+ // that is to say, user are granted only one chance to\r
+ // decide whether the boot option will be added or not\r
+ // there should be no indictor to show whether this\r
+ // is a "new" boot option\r
+ //\r
+ BootOrderListSize = BootOptionMenu.MenuNumber;\r
+\r
+ if (BootOrderListSize > 0) {\r
+ BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
+ ASSERT (BootOrderList != NULL);\r
+ BootOrderListPtr = BootOrderList;\r
+\r
+ //\r
+ // Get all current used Boot#### from BootOptionMenu.\r
+ // OptionNumber in each BM_LOAD_OPTION is really its\r
+ // #### value.\r
+ //\r
+ for (Index = 0; Index < BootOrderListSize; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
+ BootOrderList++;\r
+ }\r
+\r
+ BootOrderList = BootOrderListPtr;\r
+\r
+ //\r
+ // After building the BootOrderList, write it back\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderListSize * sizeof (UINT16),\r
+ BootOrderList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+ After deleting this Driver option, call Var_ChangeDriverOrder to\r
+ make sure DriverOrder is in valid state.\r
+\r
+ @retval EFI_SUCCESS Load Option is successfully updated.\r
+ @retval EFI_NOT_FOUND Fail to find the driver option want to be deleted.\r
+ @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI\r
+ Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+ VOID\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 DriverString[12];\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2 = 0;\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (!NewLoadContext->Deleted) {\r
+ continue;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ DriverString,\r
+ sizeof (DriverString),\r
+ L"Driver%04x",\r
+ NewMenuEntry->OptionNumber\r
+ );\r
+\r
+ EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
+ Index2++;\r
+\r
+ RemoveEntryList (&NewMenuEntry->Link);\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+ NewMenuEntry = NULL;\r
+ }\r
+\r
+ DriverOptionMenu.MenuNumber -= Index2;\r
+\r
+ Status = Var_ChangeDriverOrder ();\r
+ return Status;\r
+}\r
+\r
+/**\r
+ After any operation on Driver####, there will be a discrepancy in\r
+ DriverOrder. Since some are missing but in DriverOrder, while some\r
+ are present but are not reflected by DriverOrder. Then a function\r
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
+ needed.\r
+\r
+ @retval EFI_SUCCESS The driver order is updated successfully.\r
+ @return EFI_STATUS other than EFI_SUCCESS if failed to\r
+ Set the "DriverOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *DriverOrderList;\r
+ UINT16 *DriverOrderListPtr;\r
+ UINTN DriverOrderListSize;\r
+ UINTN Index;\r
+\r
+ DriverOrderList = NULL;\r
+ DriverOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether DriverOrder is present in current configuration\r
+ //\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+\r
+ //\r
+ // If exists, delete it to hold new DriverOrder\r
+ //\r
+ if (DriverOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+ FreePool (DriverOrderList);\r
+ DriverOrderList = NULL;\r
+ }\r
+\r
+ DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
+\r
+ if (DriverOrderListSize > 0) {\r
+ DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
+ ASSERT (DriverOrderList != NULL);\r
+ DriverOrderListPtr = DriverOrderList;\r
+\r
+ //\r
+ // Get all current used Driver#### from DriverOptionMenu.\r
+ // OptionNumber in each BM_LOAD_OPTION is really its\r
+ // #### value.\r
+ //\r
+ for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+ *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
+ DriverOrderList++;\r
+ }\r
+\r
+ DriverOrderList = DriverOrderListPtr;\r
+\r
+ //\r
+ // After building the DriverOrderList, write it back\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ DriverOrderListSize * sizeof (UINT16),\r
+ DriverOrderList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update the device path of "ConOut", "ConIn" and "ErrOut" \r
+ based on the new BaudRate, Data Bits, parity and Stop Bits\r
+ set.\r
+\r
+**/\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+ VOID\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;\r
+ EFI_STATUS Status;\r
+\r
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+ if (OutDevicePath != NULL) {\r
+ ChangeVariableDevicePath (OutDevicePath);\r
+ Status = gRT->SetVariable (\r
+ L"ConOut",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (OutDevicePath),\r
+ OutDevicePath\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+\r
+ if (InpDevicePath != NULL) {\r
+ ChangeVariableDevicePath (InpDevicePath);\r
+ Status = gRT->SetVariable (\r
+ L"ConIn",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (InpDevicePath),\r
+ InpDevicePath\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+\r
+ if (ErrDevicePath != NULL) {\r
+ ChangeVariableDevicePath (ErrDevicePath);\r
+ Status = gRT->SetVariable (\r
+ L"ErrOut",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (ErrDevicePath),\r
+ ErrDevicePath\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+}\r
+\r
+/**\r
+ This function delete and build multi-instance device path for\r
+ specified type of console device.\r
+\r
+ This function clear the EFI variable defined by ConsoleName and\r
+ gEfiGlobalVariableGuid. It then build the multi-instance device\r
+ path by appending the device path of the Console (In/Out/Err) instance \r
+ in ConsoleMenu. Then it scan all corresponding console device by\r
+ scanning Terminal (built from device supporting Serial I/O instances)\r
+ devices in TerminalMenu. At last, it save a EFI variable specifed\r
+ by ConsoleName and gEfiGlobalVariableGuid.\r
+\r
+ @param ConsoleName The name for the console device type. They are\r
+ usually "ConIn", "ConOut" and "ErrOut".\r
+ @param ConsoleMenu The console memu which is a list of console devices.\r
+ @param UpdatePageId The flag specifying which type of console device\r
+ to be processed.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleOption (\r
+ IN UINT16 *ConsoleName,\r
+ IN BM_MENU_OPTION *ConsoleMenu,\r
+ IN UINT16 UpdatePageId\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ EFI_STATUS Status;\r
+ VENDOR_DEVICE_PATH Vendor;\r
+ EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
+ UINTN Index;\r
+\r
+ ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+ if (ConDevicePath != NULL) {\r
+ EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+ FreePool (ConDevicePath);\r
+ ConDevicePath = NULL;\r
+ };\r
+\r
+ //\r
+ // First add all console input device from console input menu\r
+ //\r
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (NewConsoleContext->IsActive) {\r
+ ConDevicePath = AppendDevicePathInstance (\r
+ ConDevicePath,\r
+ NewConsoleContext->DevicePath\r
+ );\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+ ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+ ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))\r
+ ) {\r
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Vendor.Header.SubType = MSG_VENDOR_DP;\r
+ \r
+ ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0])));\r
+ CopyMem (\r
+ &Vendor.Guid,\r
+ &TerminalTypeGuid[NewTerminalContext->TerminalType],\r
+ sizeof (EFI_GUID)\r
+ );\r
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+ TerminalDevicePath = AppendDevicePathNode (\r
+ NewTerminalContext->DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+ );\r
+ ASSERT (TerminalDevicePath != NULL);\r
+ ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
+ ConDevicePath = AppendDevicePathInstance (\r
+ ConDevicePath,\r
+ TerminalDevicePath\r
+ );\r
+ }\r
+ }\r
+\r
+ if (ConDevicePath != NULL) {\r
+ Status = gRT->SetVariable (\r
+ ConsoleName,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (ConDevicePath),\r
+ ConDevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ This function delete and build multi-instance device path ConIn\r
+ console device.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+ VOID\r
+ )\r
+{\r
+ return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
+}\r
+\r
+/**\r
+ This function delete and build multi-instance device path ConOut\r
+ console device.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+ VOID\r
+ )\r
+{\r
+ return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
+}\r
+\r
+/**\r
+ This function delete and build multi-instance device path ErrOut\r
+ console device.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. \r
+**/\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+ VOID\r
+ )\r
+{\r
+ return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
+}\r
+\r
+/**\r
+ This function create a currently loaded Drive Option from \r
+ the BMM. It then appends this Driver Option to the end of \r
+ the "DriverOrder" list. It append this Driver Opotion to the end\r
+ of DriverOptionMenu.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param HiiHandle The HII handle associated with the BMM formset.\r
+ @param DescriptionData The description of this driver option.\r
+ @param OptionalData The optional load option.\r
+ @param ForceReconnect If to force reconnect.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+ @retval EFI_SUCCESS If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN UINT16 *DescriptionData,\r
+ IN UINT16 *OptionalData,\r
+ IN UINT8 ForceReconnect\r
+ )\r
+{\r
+ UINT16 Index;\r
+ UINT16 *DriverOrderList;\r
+ UINT16 *NewDriverOrderList;\r
+ UINT16 DriverString[12];\r
+ UINTN DriverOrderListSize;\r
+ VOID *Buffer;\r
+ UINTN BufferSize;\r
+ UINT8 *Ptr;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BOOLEAN OptionalDataExist;\r
+ EFI_STATUS Status;\r
+\r
+ OptionalDataExist = FALSE;\r
+\r
+ Index = BOpt_GetDriverOptionNumber ();\r
+ UnicodeSPrint (\r
+ DriverString,\r
+ sizeof (DriverString),\r
+ L"Driver%04x",\r
+ Index\r
+ );\r
+\r
+ if (*DescriptionData == 0x0000) {\r
+ StrCpy (DescriptionData, DriverString);\r
+ }\r
+\r
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);\r
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ if (*OptionalData != 0x0000) {\r
+ OptionalDataExist = TRUE;\r
+ BufferSize += StrSize (OptionalData);\r
+ }\r
+\r
+ Buffer = AllocateZeroPool (BufferSize);\r
+ if (NULL == Buffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ FreePool (Buffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->LoadOptionSize = BufferSize;\r
+ Ptr = (UINT8 *) Buffer;\r
+ NewLoadContext->LoadOption = Ptr;\r
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+ NewLoadContext->IsActive = TRUE;\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ Ptr += sizeof (UINT32);\r
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+\r
+ Ptr += sizeof (UINT16);\r
+ CopyMem (\r
+ Ptr,\r
+ DescriptionData,\r
+ StrSize (DescriptionData)\r
+ );\r
+\r
+ NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (VOID *) Ptr,\r
+ StrSize (DescriptionData)\r
+ );\r
+\r
+ Ptr += StrSize (DescriptionData);\r
+ CopyMem (\r
+ Ptr,\r
+ CallbackData->LoadContext->FilePathList,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (VOID *) Ptr,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->OptionNumber = Index;\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionStrDepository\r
+ );\r
+ HiiLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionHelpStrDepository\r
+ );\r
+ HiiLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+ if (OptionalDataExist) {\r
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ OptionalData,\r
+ StrSize (OptionalData)\r
+ );\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ DriverString,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
+ ASSERT (NewDriverOrderList != NULL);\r
+ CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
+ NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
+ if (DriverOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ DriverOrderListSize + sizeof (UINT16),\r
+ NewDriverOrderList\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (DriverOrderList != NULL) {\r
+ FreePool (DriverOrderList);\r
+ }\r
+ DriverOrderList = NULL;\r
+ FreePool (NewDriverOrderList);\r
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+ DriverOptionMenu.MenuNumber++;\r
+\r
+ *DescriptionData = 0x0000;\r
+ *OptionalData = 0x0000;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function create a currently loaded Boot Option from \r
+ the BMM. It then appends this Boot Option to the end of \r
+ the "BootOrder" list. It also append this Boot Opotion to the end\r
+ of BootOptionMenu.\r
+\r
+ @param CallbackData The BMM context data.\r
+ @param NvRamMap The file explorer formset internal state.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+ @retval EFI_SUCCESS If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN FILE_EXPLORER_NV_DATA *NvRamMap\r
+ )\r
+{\r
+ UINT16 *BootOrderList;\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT16 BootString[10];\r
+ VOID *Buffer;\r
+ UINTN BufferSize;\r
+ UINT8 *Ptr;\r
+ UINT16 Index;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BOOLEAN OptionalDataExist;\r
+ EFI_STATUS Status;\r
+\r
+ OptionalDataExist = FALSE;\r
+\r
+ Index = BOpt_GetBootOptionNumber () ;\r
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
+\r
+ if (NvRamMap->DescriptionData[0] == 0x0000) {\r
+ StrCpy (NvRamMap->DescriptionData, BootString);\r
+ }\r
+\r
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);\r
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ if (NvRamMap->OptionalData[0] != 0x0000) {\r
+ OptionalDataExist = TRUE;\r
+ BufferSize += StrSize (NvRamMap->OptionalData);\r
+ }\r
+\r
+ Buffer = AllocateZeroPool (BufferSize);\r
+ if (NULL == Buffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->LoadOptionSize = BufferSize;\r
+ Ptr = (UINT8 *) Buffer;\r
+ NewLoadContext->LoadOption = Ptr;\r
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+ NewLoadContext->IsActive = TRUE;\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ Ptr += sizeof (UINT32);\r
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+ Ptr += sizeof (UINT16);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ NvRamMap->DescriptionData,\r
+ StrSize (NvRamMap->DescriptionData)\r
+ );\r
+\r
+ NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (VOID *) Ptr,\r
+ StrSize (NvRamMap->DescriptionData)\r
+ );\r
+\r
+ Ptr += StrSize (NvRamMap->DescriptionData);\r
+ CopyMem (\r
+ Ptr,\r
+ CallbackData->LoadContext->FilePathList,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (VOID *) Ptr,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->OptionNumber = Index;\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionStrDepository\r
+ );\r
+ HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionHelpStrDepository\r
+ );\r
+ HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+ if (OptionalDataExist) {\r
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ BootString,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
+ ASSERT (NewBootOrderList != NULL);\r
+ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
+ NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
+\r
+ if (BootOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ FreePool (BootOrderList);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderListSize + sizeof (UINT16),\r
+ NewBootOrderList\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ FreePool (NewBootOrderList);\r
+ NewBootOrderList = NULL;\r
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+ BootOptionMenu.MenuNumber++;\r
+\r
+ NvRamMap->DescriptionData[0] = 0x0000;\r
+ NvRamMap->OptionalData[0] = 0x0000;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function update the "BootNext" EFI Variable. If there is \r
+ no "BootNex" specified in BMM, this EFI Variable is deleted.\r
+ It also update the BMM context data specified the "BootNext"\r
+ vaule.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @return The EFI variable can be saved. See gRT->SetVariable \r
+ for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
+ UINT16 Index;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+ CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ ASSERT (NULL != NewMenuEntry);\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->IsBootNext = FALSE;\r
+ }\r
+\r
+ if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (\r
+ &BootOptionMenu,\r
+ CurrentFakeNVMap->BootNext\r
+ );\r
+ ASSERT (NewMenuEntry != NULL);\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ Status = gRT->SetVariable (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ sizeof (UINT16),\r
+ &NewMenuEntry->OptionNumber\r
+ );\r
+ NewLoadContext->IsBootNext = TRUE;\r
+ CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function update the "BootOrder" EFI Variable based on\r
+ BMM Formset's NV map. It then refresh BootOptionMenu\r
+ with the new "BootOrder" list.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Index;\r
+ UINT16 *BootOrderList;\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BootOrderListSize;\r
+\r
+ BootOrderList = NULL;\r
+ BootOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether BootOrder is present in current configuration\r
+ //\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ NewBootOrderList = AllocateZeroPool (BootOrderListSize);\r
+ if (NewBootOrderList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // If exists, delete it to hold new BootOrder\r
+ //\r
+ if (BootOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ FreePool (BootOrderList);\r
+ }\r
+\r
+ ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.OptionOrder) / sizeof (CallbackData->BmmFakeNvData.OptionOrder[0])));\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderListSize,\r
+ NewBootOrderList\r
+ );\r
+ FreePool (NewBootOrderList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_FreeMenu (&BootOptionMenu);\r
+ BOpt_GetBootOptions (CallbackData);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ This function update the "DriverOrder" EFI Variable based on\r
+ BMM Formset's NV map. It then refresh DriverOptionMenu\r
+ with the new "DriverOrder" list.\r
+\r
+ @param CallbackData The BMM context data.\r
+\r
+ @retval EFI_SUCCESS The function complete successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to complete the function.\r
+ @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Index;\r
+ UINT16 *DriverOrderList;\r
+ UINT16 *NewDriverOrderList;\r
+ UINTN DriverOrderListSize;\r
+\r
+ DriverOrderList = NULL;\r
+ DriverOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether DriverOrder is present in current configuration\r
+ //\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+\r
+ NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
+\r
+ if (NewDriverOrderList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // If exists, delete it to hold new DriverOrder\r
+ //\r
+ if (DriverOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+ FreePool (DriverOrderList);\r
+ }\r
+\r
+ ASSERT (DriverOrderListSize <= (sizeof (CallbackData->BmmFakeNvData.OptionOrder) / sizeof (CallbackData->BmmFakeNvData.OptionOrder[0])));\r
+ for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+ NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ DriverOrderListSize,\r
+ NewDriverOrderList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_FreeMenu (&DriverOptionMenu);\r
+ BOpt_GetDriverOptions (CallbackData);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable\r
+ is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
+ is also updated.\r
+\r
+ @param CallbackData The context data for BMM.\r
+\r
+ @return EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ VOID *BootOptionVar;\r
+ CHAR16 VarName[100];\r
+ UINTN OptionSize;\r
+ UINT8 *Ptr;\r
+ EFI_STATUS Status;\r
+ CHAR16 DescString[100];\r
+ CHAR8 DescAsciiString[100];\r
+ UINTN NewOptionSize;\r
+ UINT8 *NewOptionPtr;\r
+ UINT8 *TempPtr;\r
+ UINT32 *Attribute;\r
+ BM_MENU_OPTION *OptionMenu;\r
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;\r
+ UINT8 *LegacyDev;\r
+ UINT8 *VarData;\r
+ UINTN VarSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+ UINT8 *OriginalPtr;\r
+ UINT8 *DisMap;\r
+ UINTN Pos;\r
+ UINTN Bit;\r
+ UINT16 *NewOrder;\r
+ UINT16 Tmp;\r
+\r
+ LegacyDeviceContext = NULL;\r
+ DisMap = NULL;\r
+ NewOrder = NULL;\r
+\r
+ if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;\r
+ CallbackData->BbsType = BBS_FLOPPY;\r
+ } else {\r
+ if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;\r
+ CallbackData->BbsType = BBS_HARDDISK;\r
+ } else {\r
+ if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;\r
+ CallbackData->BbsType = BBS_CDROM;\r
+ } else {\r
+ if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;\r
+ CallbackData->BbsType = BBS_EMBED_NETWORK;\r
+ } else {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;\r
+ CallbackData->BbsType = BBS_BEV_DEVICE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Find the first device's context\r
+ // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
+ // because we just use it to fill the desc string, and user can not see the string in UI\r
+ //\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+ LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
+ DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Update the Variable "LegacyDevOrder"\r
+ //\r
+ VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ &VarSize\r
+ );\r
+\r
+ if (VarData == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ OriginalPtr = VarData;\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+\r
+ while (VarData < VarData + VarSize) {\r
+ if (DevOrder->BbsType == CallbackData->BbsType) {\r
+ break;\r
+ }\r
+\r
+ VarData += sizeof (BBS_TYPE);\r
+ VarData += *(UINT16 *) VarData;\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+ }\r
+\r
+ if (VarData >= VarData + VarSize) {\r
+ FreePool (OriginalPtr);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
+ if (NewOrder == NULL) {\r
+ FreePool (VarData);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ if (0xFF == LegacyDev[Index]) {\r
+ break;\r
+ }\r
+\r
+ NewOrder[Index] = LegacyDev[Index];\r
+ }\r
+ //\r
+ // Only the enable/disable state of each boot device with same device type can be changed,\r
+ // so we can count on the index information in DevOrder.\r
+ // DisMap bit array is the only reliable source to check a device's en/dis state,\r
+ // so we use DisMap to set en/dis state of each item in NewOrder array\r
+ //\r
+ for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
+ Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
+ Tmp &= 0xFF;\r
+ Pos = Tmp / 8;\r
+ Bit = 7 - (Tmp % 8);\r
+ if ((DisMap[Pos] & (1 << Bit)) != 0) {\r
+ NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
+ Index++;\r
+ }\r
+ }\r
+\r
+ CopyMem (\r
+ (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
+ NewOrder,\r
+ DevOrder->Length - sizeof (UINT16)\r
+ );\r
+ FreePool (NewOrder);\r
+\r
+ Status = gRT->SetVariable (\r
+ VAR_LEGACY_DEV_ORDER,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ VarSize,\r
+ OriginalPtr\r
+ );\r
+\r
+ FreePool (OriginalPtr);\r
+\r
+ //\r
+ // Update Optional Data of Boot####\r
+ //\r
+ BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
+\r
+ if (BootOptionVar != NULL) {\r
+ CopyMem (\r
+ DescString,\r
+ LegacyDeviceContext->Description,\r
+ StrSize (LegacyDeviceContext->Description)\r
+ );\r
+\r
+ UnicodeStrToAsciiStr((CONST CHAR16*)&DescString, (CHAR8 *)&DescAsciiString);\r
+\r
+ NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +\r
+ sizeof (BBS_BBS_DEVICE_PATH);\r
+ NewOptionSize += AsciiStrLen (DescAsciiString) +\r
+ END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);\r
+\r
+ UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
+\r
+ Ptr = BootOptionVar;\r
+\r
+ Attribute = (UINT32 *) Ptr;\r
+ *Attribute |= LOAD_OPTION_ACTIVE;\r
+ if (LegacyDev[0] == 0xFF) {\r
+ //\r
+ // Disable this legacy boot option\r
+ //\r
+ *Attribute &= ~LOAD_OPTION_ACTIVE;\r
+ }\r
+\r
+ Ptr += sizeof (UINT32);\r
+\r
+ Ptr += sizeof (UINT16);\r
+ Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+ NewOptionPtr = AllocateZeroPool (NewOptionSize);\r
+ if (NewOptionPtr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TempPtr = NewOptionPtr;\r
+\r
+ //\r
+ // Attribute\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ BootOptionVar,\r
+ sizeof (UINT32)\r
+ );\r
+\r
+ TempPtr += sizeof (UINT32);\r
+\r
+ //\r
+ // BBS device path Length\r
+ //\r
+ *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +\r
+ AsciiStrLen (DescAsciiString) +\r
+ END_DEVICE_PATH_LENGTH);\r
+\r
+ TempPtr += sizeof (UINT16);\r
+\r
+ //\r
+ // Description string\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ DescString,\r
+ StrSize (DescString)\r
+ );\r
+\r
+ TempPtr += StrSize (DescString);\r
+\r
+ //\r
+ // BBS device path\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ Ptr,\r
+ sizeof (BBS_BBS_DEVICE_PATH)\r
+ );\r
+\r
+ CopyMem (\r
+ ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,\r
+ DescAsciiString,\r
+ AsciiStrSize (DescAsciiString)\r
+ );\r
+\r
+ SetDevicePathNodeLength (\r
+ (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,\r
+ sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)\r
+ );\r
+\r
+ TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);\r
+\r
+ //\r
+ // End node\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ EndDevicePath,\r
+ END_DEVICE_PATH_LENGTH\r
+ );\r
+ TempPtr += END_DEVICE_PATH_LENGTH;\r
+\r
+ //\r
+ // Now TempPtr point to optional data, i.e. Bbs Table\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ LegacyDeviceContext->BbsTable,\r
+ sizeof (BBS_TABLE)\r
+ );\r
+\r
+ //\r
+ // Now TempPtr point to BBS index\r
+ //\r
+ TempPtr += sizeof (BBS_TABLE);\r
+ *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
+\r
+ Status = gRT->SetVariable (\r
+ VarName,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ NewOptionSize,\r
+ NewOptionPtr\r
+ );\r
+\r
+ FreePool (NewOptionPtr);\r
+ FreePool (BootOptionVar);\r
+ }\r
+\r
+ BOpt_GetBootOptions (CallbackData);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Update the Text Mode of Console.\r
+\r
+ @param CallbackData The context data for BMM.\r
+\r
+ @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
+ @return Other value if the Text Mode of Console is not updated.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Mode;\r
+ CONSOLE_OUT_MODE ModeInfo;\r
+\r
+ Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
+\r
+ Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
+ if (EFI_ERROR(Status)) {\r
+ ModeInfo.Column = 80;\r
+ ModeInfo.Row = 25;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ VAR_CON_OUT_MODE,\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (CONSOLE_OUT_MODE),\r
+ &ModeInfo\r
+ );\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ The platform boot manager reference implementation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BootManager.h"\r
+\r
+UINT16 mKeyInput;\r
+EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
+LIST_ENTRY *mBootOptionsList;\r
+BDS_COMMON_OPTION *gOption;\r
+\r
+BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {\r
+ BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+ NULL,\r
+ NULL,\r
+ {\r
+ FakeExtractConfig,\r
+ FakeRouteConfig,\r
+ BootManagerCallback\r
+ }\r
+};\r
+\r
+/**\r
+ This call back funtion is registered with Boot Manager formset.\r
+ When user selects a boot option, this call back function will\r
+ be triggered. The boot option is saved for later processing.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ BDS_COMMON_OPTION *Option;\r
+ LIST_ENTRY *Link;\r
+ UINT16 KeyCount;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the key count\r
+ //\r
+ KeyCount = 0;\r
+\r
+ for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ KeyCount++;\r
+\r
+ gOption = Option;\r
+\r
+ //\r
+ // Is this device the one chosen?\r
+ //\r
+ if (KeyCount == QuestionId) {\r
+ //\r
+ // Assigning the returned Key to a global allows the original routine to know what was chosen\r
+ //\r
+ mKeyInput = QuestionId;\r
+\r
+ //\r
+ // Request to exit SendForm(), so that we could boot the selected option\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Registers HII packages for the Boot Manger to HII Database.\r
+ It also registers the browser call back function.\r
+\r
+ @return Status of HiiLibCreateHiiDriverHandle() and gHiiDatabase->NewPackageList()\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBootManager (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gBootManagerPrivate.DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gBootManagerPrivate.ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = HiiLibPreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gBootManagerPrivate.DriverHandle,\r
+ &gBootManagerPrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This funtion invokees Boot Manager. If all devices have not a chance to be connected,\r
+ the connect all will be triggered. It then enumerate all boot options. If \r
+ a boot option from the Boot Manager page is selected, Boot Manager will boot\r
+ from this boot option.\r
+ \r
+**/\r
+VOID\r
+CallBootManager (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BDS_COMMON_OPTION *Option;\r
+ LIST_ENTRY *Link;\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ CHAR16 *ExitData;\r
+ UINTN ExitDataSize;\r
+ EFI_STRING_ID Token;\r
+ EFI_INPUT_KEY Key;\r
+ LIST_ENTRY BdsBootOptionList;\r
+ CHAR16 *HelpString;\r
+ EFI_STRING_ID HelpToken;\r
+ UINT16 *TempStr;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ UINTN TempSize;\r
+\r
+ gOption = NULL;\r
+ InitializeListHead (&BdsBootOptionList);\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+ //\r
+ // BugBug: Here we can not remove the legacy refresh macro, so we need\r
+ // get the boot order every time from "BootOrder" variable.\r
+ // Recreate the boot option list base on the BootOrder variable\r
+ //\r
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+ mBootOptionsList = &BdsBootOptionList;\r
+\r
+ HiiHandle = gBootManagerPrivate.HiiHandle;\r
+\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData.BufferSize = 0x1000;\r
+ UpdateData.Offset = 0;\r
+ UpdateData.Data = AllocateZeroPool (0x1000);\r
+ ASSERT (UpdateData.Data != NULL);\r
+\r
+ mKeyInput = 0;\r
+\r
+ for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ //\r
+ // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
+ //\r
+ mKeyInput++;\r
+\r
+ //\r
+ // Don't display the boot option marked as LOAD_OPTION_HIDDEN\r
+ //\r
+ if (Option->Attribute & LOAD_OPTION_HIDDEN) {\r
+ continue;\r
+ }\r
+\r
+ HiiLibNewString (HiiHandle, &Token, Option->Description);\r
+\r
+ TempStr = DevicePathToStr (Option->DevicePath);\r
+ TempSize = StrSize (TempStr);\r
+ HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
+ ASSERT (HelpString != NULL);\r
+ StrCat (HelpString, L"Device Path : ");\r
+ StrCat (HelpString, TempStr);\r
+\r
+ HiiLibNewString (HiiHandle, &HelpToken, HelpString);\r
+\r
+ CreateActionOpCode (\r
+ mKeyInput,\r
+ Token,\r
+ HelpToken,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &UpdateData\r
+ );\r
+ }\r
+\r
+ IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mBootManagerGuid,\r
+ BOOT_MANAGER_FORM_ID,\r
+ LABEL_BOOT_OPTION,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+ FreePool (UpdateData.Data);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ if (gOption == NULL) {\r
+ return ;\r
+ }\r
+\r
+ //\r
+ //Will leave browser, check any reset required change is applied? if yes, reset system\r
+ //\r
+ SetupResetReminder ();\r
+\r
+ //\r
+ // parse the selected option\r
+ //\r
+ Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+ PlatformBdsBootSuccess (gOption);\r
+ } else {\r
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
+ gST->ConOut->OutputString (\r
+ gST->ConOut,\r
+ GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
+ );\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ The platform boot manager reference implement\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_BOOT_MANAGER_H_\r
+#define _EFI_BOOT_MANAGER_H_\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define BOOT_MANAGER_FORMSET_GUID \\r
+ { \\r
+ 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \\r
+ }\r
+\r
+#define BOOT_MANAGER_FORM_ID 0x1000\r
+\r
+#define LABEL_BOOT_OPTION 0x00\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 BootManagerVfrBin[];\r
+\r
+#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('B', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ //\r
+ // HII relative handles\r
+ //\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+\r
+ //\r
+ // Produced protocols\r
+ //\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+} BOOT_MANAGER_CALLBACK_DATA;\r
+\r
+/**\r
+ This call back funtion is registered with Boot Manager formset.\r
+ When user selects a boot option, this call back function will\r
+ be triggered. The boot option is saved for later processing.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ );\r
+\r
+/**\r
+\r
+ Registers HII packages for the Boot Manger to HII Database.\r
+ It also registers the browser call back function.\r
+\r
+ @return Status of HiiLibCreateHiiDriverHandle() and gHiiDatabase->NewPackageList()\r
+**/\r
+EFI_STATUS\r
+InitializeBootManager (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This funtion invokees Boot Manager. If all devices have not a chance to be connected,\r
+ the connect all will be triggered. It then enumerate all boot options. If \r
+ a boot option from the Boot Manager page is selected, Boot Manager will boot\r
+ from this boot option.\r
+ \r
+**/\r
+VOID\r
+CallBootManager (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+///** @file\r
+// \r
+// Browser formset.\r
+// \r
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+// \r
+//**/\r
+\r
+#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }\r
+\r
+#define BOOT_MANAGER_FORM_ID 0x1000\r
+\r
+#define LABEL_BOOT_OPTION 0x00\r
+#define LABEL_BOOT_OPTION_END 0x01\r
+\r
+#define BOOT_MANAGER_CLASS 0x00\r
+#define BOOT_MANAGER_SUBCLASS 0x00\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_BM_BANNER),\r
+ help = STRING_TOKEN(STR_LAST_STRING),\r
+ class = BOOT_MANAGER_CLASS,\r
+ subclass = BOOT_MANAGER_SUBCLASS,\r
+\r
+ form formid = BOOT_MANAGER_FORM_ID,\r
+ title = STRING_TOKEN(STR_BM_BANNER);\r
+\r
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+ subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER);\r
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+\r
+ //\r
+ // This is where we will dynamically add choices for the Boot Manager\r
+ //\r
+ label LABEL_BOOT_OPTION;\r
+ label LABEL_BOOT_OPTION_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+ subtitle text = STRING_TOKEN(STR_HELP_FOOTER);\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/** @file\r
+ BDS routines to handle capsules.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "Bds.h"\r
+\r
+/**\r
+ This function locks the block \r
+\r
+ @param CpuIo A instance of EFI_CPU_IO_PROTOCOL. \r
+ @param Base The base address flash region to be locked.\r
+\r
+**/\r
+VOID\r
+BdsLockFv (\r
+ IN EFI_CPU_IO_PROTOCOL *CpuIo,\r
+ IN EFI_PHYSICAL_ADDRESS Base\r
+ )\r
+{\r
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ UINT8 Data;\r
+ UINT32 BlockLength;\r
+ UINTN Index;\r
+\r
+ BaseAddress = Base - 0x400000 + 2;\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));\r
+ BlockMap = &(FvHeader->BlockMap[0]);\r
+\r
+ while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {\r
+ BlockLength = BlockMap->Length;\r
+ for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
+ CpuIo->Mem.Read (\r
+ CpuIo,\r
+ EfiCpuIoWidthUint8,\r
+ BaseAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+ Data = (UINT8) (Data | 0x3);\r
+ CpuIo->Mem.Write (\r
+ CpuIo,\r
+ EfiCpuIoWidthUint8,\r
+ BaseAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+ BaseAddress += BlockLength;\r
+ }\r
+\r
+ BlockMap++;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ This routine is called to see if there are any capsules we need to process.\r
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the\r
+ capsule HOBS and produce firmware volumes for them via the DXE service.\r
+ Then call the dispatcher to dispatch drivers from them. Finally, check\r
+ the status of the updates.\r
+\r
+ This function should be called by BDS in case we need to do some\r
+ sort of processing even if there is no capsule to process. We\r
+ need to do this if an earlier update went away and we need to\r
+ clear the capsule variable so on the next reset PEI does not see it and\r
+ think there is a capsule available.\r
+\r
+ @param BootMode the current boot mode\r
+\r
+ @retval EFI_INVALID_PARAMETER boot mode is not correct for an update\r
+ @retval EFI_SUCCESS There is no error when processing capsule\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessCapsules (\r
+ EFI_BOOT_MODE BootMode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_HOB_POINTERS HobPointer;\r
+ EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ UINT32 Size;\r
+ UINT32 CapsuleNumber;\r
+ UINT32 CapsuleTotalNumber;\r
+ EFI_CAPSULE_TABLE *CapsuleTable;\r
+ UINT32 Index;\r
+ UINT32 CacheIndex;\r
+ UINT32 CacheNumber;\r
+ VOID **CapsulePtr;\r
+ VOID **CapsulePtrCache;\r
+ EFI_GUID *CapsuleGuidCache; \r
+ CAPSULE_HOB_INFO *CapsuleHobInfo;\r
+\r
+ CapsuleNumber = 0;\r
+ CapsuleTotalNumber = 0;\r
+ CacheIndex = 0;\r
+ CacheNumber = 0;\r
+ CapsulePtr = NULL;\r
+ CapsulePtrCache = NULL;\r
+ CapsuleGuidCache = NULL;\r
+\r
+ //\r
+ // We don't do anything else if the boot mode is not flash-update\r
+ //\r
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ Status = EFI_SUCCESS;\r
+ //\r
+ // Find all capsule images from hob\r
+ //\r
+ HobPointer.Raw = GetHobList ();\r
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+ CapsuleTotalNumber ++;\r
+\r
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+ }\r
+ \r
+ if (CapsuleTotalNumber == 0) {\r
+ //\r
+ // We didn't find a hob, so had no errors.\r
+ //\r
+ PlatformBdsLockNonUpdatableFlash ();\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ //\r
+ // Init temp Capsule Data table.\r
+ //\r
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+ ASSERT (CapsulePtr != NULL);\r
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+ ASSERT (CapsulePtrCache != NULL);\r
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);\r
+ ASSERT (CapsuleGuidCache != NULL);\r
+ \r
+ //\r
+ // Find all capsule images from hob\r
+ //\r
+ HobPointer.Raw = GetHobList ();\r
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+ CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);\r
+ CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);\r
+\r
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+ }\r
+\r
+ //\r
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
+ //capsuleTable to configure table with EFI_CAPSULE_GUID\r
+ //\r
+\r
+ //\r
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
+ // System to have information persist across a system reset. EFI System Table must \r
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents\r
+ // searching for this type capsule will look in EFI System Table and search for the \r
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes\r
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table. \r
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an \r
+ // array for later sorting capsules by CapsuleGuid.\r
+ //\r
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+ //\r
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as \r
+ // an additional one.\r
+ //\r
+ CacheIndex = 0;\r
+ while (CacheIndex < CacheNumber) {\r
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {\r
+ break;\r
+ }\r
+ CacheIndex++;\r
+ }\r
+ if (CacheIndex == CacheNumber) {\r
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules\r
+ // whose guid is the same as it, and malloc memory for an array which preceding\r
+ // with UINT32. The array fills with entry point of capsules that have the same\r
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install\r
+ // this array into EFI System Table, so that agents searching for this type capsule\r
+ // will look in EFI System Table and search for the capsule's Guid and associated\r
+ // pointer to retrieve the data.\r
+ //\r
+ CacheIndex = 0;\r
+ while (CacheIndex < CacheNumber) {\r
+ CapsuleNumber = 0; \r
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
+ //\r
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
+ //\r
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
+ }\r
+ }\r
+ }\r
+ if (CapsuleNumber != 0) {\r
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*); \r
+ CapsuleTable = AllocateRuntimePool (Size);\r
+ ASSERT (CapsuleTable != NULL);\r
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;\r
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ CacheIndex++;\r
+ }\r
+\r
+ //\r
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are\r
+ // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash \r
+ // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional\r
+ // type capsule transaction could be extended. It depends on platform policy.\r
+ //\r
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
+ //\r
+ // Call capsule library to process capsule image.\r
+ //\r
+ ProcessCapsuleImage (CapsuleHeader);\r
+ }\r
+ }\r
+\r
+ PlatformBdsLockNonUpdatableFlash ();\r
+ \r
+ //\r
+ // Free the allocated temp memory space.\r
+ //\r
+ FreePool (CapsuleGuidCache);\r
+ FreePool (CapsulePtrCache);\r
+ FreePool (CapsulePtr);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ The platform device manager reference implementation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DeviceManager.h"\r
+\r
+DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {\r
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+ NULL,\r
+ NULL,\r
+ {\r
+ FakeExtractConfig,\r
+ FakeRouteConfig,\r
+ DeviceManagerCallback\r
+ }\r
+};\r
+\r
+EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
+\r
+DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {\r
+ { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }\r
+};\r
+\r
+#define MENU_ITEM_NUM \\r
+ (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))\r
+\r
+/**\r
+ This function is invoked if user selected a iteractive opcode from Device Manager's\r
+ Formset. The decision by user is saved to gCallbackKey for later processing. If\r
+ user set VBIOS, the new value is saved to EFI variable.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ DEVICE_MANAGER_CALLBACK_DATA *PrivateData;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+ switch (QuestionId) {\r
+ case DEVICE_MANAGER_KEY_VBIOS:\r
+ PrivateData->VideoBios = Value->u8;\r
+ gRT->SetVariable (\r
+ L"VBIOS",\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT8),\r
+ &PrivateData->VideoBios\r
+ );\r
+\r
+ //\r
+ // Tell browser not to ask for confirmation of changes,\r
+ // since we have already applied.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // The key corresponds the Handle Index which was requested to be displayed\r
+ //\r
+ gCallbackKey = QuestionId;\r
+\r
+ //\r
+ // Request to exit SendForm(), so as to switch to selected form\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ This function registers HII packages to HII database.\r
+\r
+ @retval EFI_SUCCESS This function complete successfully.\r
+ @return Other value if failed to register HII packages.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gDeviceManagerPrivate.DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gDeviceManagerPrivate.ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gDeviceManagerPrivate.DriverHandle,\r
+ &gDeviceManagerPrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Call the browser and display the device manager to allow user\r
+ to configure the platform.\r
+\r
+ This function create the dynamic content for device manager. It includes\r
+ section header for all class of devices, one-of opcode to set VBIOS.\r
+ \r
+ @retval EFI_SUCCESS Operation is successful.\r
+ @return Other values if failed to clean up the dynamic content from HII\r
+ database.\r
+\r
+**/\r
+EFI_STATUS\r
+CallDeviceManager (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Count;\r
+ UINTN Index;\r
+ CHAR16 *String;\r
+ UINTN StringLength;\r
+ EFI_HII_UPDATE_DATA UpdateData[MENU_ITEM_NUM];\r
+ EFI_STRING_ID Token;\r
+ EFI_STRING_ID TokenHelp;\r
+ IFR_OPTION *IfrOptionList;\r
+ UINT8 *VideoOption;\r
+ UINTN VideoOptionSize;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN HandleBufferLength;\r
+ UINTN NumberOfHiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ UINT16 FormSetClass;\r
+ EFI_STRING_ID FormSetTitle;\r
+ EFI_STRING_ID FormSetHelp;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ IfrOptionList = NULL;\r
+ VideoOption = NULL;\r
+ HiiHandles = NULL;\r
+ HandleBufferLength = 0;\r
+\r
+ Status = EFI_SUCCESS;\r
+ gCallbackKey = 0;\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+\r
+ //\r
+ // Create Subtitle OpCodes\r
+ //\r
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData[Index].BufferSize = 0x1000;\r
+ UpdateData[Index].Offset = 0;\r
+ UpdateData[Index].Data = AllocatePool (0x1000);\r
+ ASSERT (UpdateData[Index].Data != NULL);\r
+\r
+ CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1, &UpdateData[Index]);\r
+ }\r
+\r
+ //\r
+ // Get all the Hii handles\r
+ //\r
+ Status = HiiLibGetHiiHandles (&HandleBufferLength, &HiiHandles);\r
+ ASSERT_EFI_ERROR (Status && (HiiHandles != NULL));\r
+\r
+ HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
+\r
+ StringLength = 0x1000;\r
+ String = AllocateZeroPool (StringLength);\r
+ ASSERT (String != NULL);\r
+\r
+ //\r
+ // Search for formset of each class type\r
+ //\r
+ NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+ for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+ IfrLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);\r
+\r
+ if (FormSetClass == EFI_NON_DEVICE_CLASS) {\r
+ continue;\r
+ }\r
+\r
+ Token = 0;\r
+ *String = 0;\r
+ StringLength = 0x1000;\r
+ HiiLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);\r
+ HiiLibNewString (HiiHandle, &Token, String);\r
+\r
+ TokenHelp = 0;\r
+ *String = 0;\r
+ StringLength = 0x1000;\r
+ HiiLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);\r
+ HiiLibNewString (HiiHandle, &TokenHelp, String);\r
+\r
+ for (Count = 0; Count < MENU_ITEM_NUM; Count++) {\r
+ if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {\r
+ CreateActionOpCode (\r
+ (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),\r
+ Token,\r
+ TokenHelp,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &UpdateData[Count]\r
+ );\r
+ }\r
+ }\r
+ }\r
+ FreePool (String);\r
+\r
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+ //\r
+ // Add End Opcode for Subtitle\r
+ //\r
+ CreateEndOpCode (&UpdateData[Index]);\r
+\r
+ IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mDeviceManagerGuid,\r
+ DEVICE_MANAGER_FORM_ID,\r
+ mDeviceManagerMenuItemTable[Index].Class,\r
+ FALSE,\r
+ &UpdateData[Index]\r
+ );\r
+ }\r
+\r
+ //\r
+ // Add oneof for video BIOS selection\r
+ //\r
+ VideoOption = BdsLibGetVariableAndSize (\r
+ L"VBIOS",\r
+ &gEfiGenericPlatformVariableGuid,\r
+ &VideoOptionSize\r
+ );\r
+ if (VideoOption == NULL) {\r
+ gDeviceManagerPrivate.VideoBios = 0;\r
+ } else {\r
+ gDeviceManagerPrivate.VideoBios = VideoOption[0];\r
+ FreePool (VideoOption);\r
+ }\r
+\r
+ ASSERT (gDeviceManagerPrivate.VideoBios <= 1);\r
+\r
+ IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
+ ASSERT (IfrOptionList != NULL);\r
+ IfrOptionList[0].Flags = 0;\r
+ IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI);\r
+ IfrOptionList[0].Value.u8 = 0;\r
+ IfrOptionList[1].Flags = 0;\r
+ IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP);\r
+ IfrOptionList[1].Value.u8 = 1;\r
+ IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+\r
+ UpdateData[0].Offset = 0;\r
+ CreateOneOfOpCode (\r
+ DEVICE_MANAGER_KEY_VBIOS,\r
+ 0,\r
+ 0,\r
+ STRING_TOKEN (STR_ONE_OF_VBIOS),\r
+ STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 2,\r
+ &UpdateData[0]\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mDeviceManagerGuid,\r
+ DEVICE_MANAGER_FORM_ID,\r
+ LABEL_VBIOS,\r
+ FALSE,\r
+ &UpdateData[0]\r
+ );\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ //\r
+ // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
+ // a target to display\r
+ //\r
+ if (gCallbackKey != 0) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ //\r
+ // Force return to Device Manager\r
+ //\r
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+ }\r
+\r
+ //\r
+ // Cleanup dynamic created strings in HII database by reinstall the packagelist\r
+ //\r
+ gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
+ PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gDeviceManagerPrivate.DriverHandle,\r
+ &gDeviceManagerPrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+ FreePool (UpdateData[Index].Data);\r
+ }\r
+ FreePool (HiiHandles);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ The platform device manager reference implement\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DEVICE_MANAGER_H_\r
+#define _DEVICE_MANAGER_H_\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define DEVICE_MANAGER_FORMSET_GUID \\r
+ { \\r
+ 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \\r
+ }\r
+\r
+#define LABEL_VBIOS 0x0040\r
+\r
+#define DEVICE_MANAGER_FORM_ID 0x1000\r
+\r
+#define DEVICE_KEY_OFFSET 0x1000\r
+#define DEVICE_MANAGER_KEY_VBIOS 0x2000\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 DeviceManagerVfrBin[];\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('D', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ ///\r
+ /// HII relative handles\r
+ ///\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+\r
+ ///\r
+ /// Produced protocols\r
+ ///\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+\r
+ ///\r
+ /// Configuration data\r
+ ///\r
+ UINT8 VideoBios;\r
+} DEVICE_MANAGER_CALLBACK_DATA;\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ DEVICE_MANAGER_CALLBACK_DATA, \\r
+ ConfigAccess, \\r
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \\r
+ )\r
+typedef struct {\r
+ EFI_STRING_ID StringId;\r
+ UINT16 Class;\r
+} DEVICE_MANAGER_MENU_ITEM;\r
+\r
+/**\r
+ This function is invoked if user selected a iteractive opcode from Device Manager's\r
+ Formset. The decision by user is saved to gCallbackKey for later processing. If\r
+ user set VBIOS, the new value is saved to EFI variable.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ );\r
+\r
+/**\r
+\r
+ This function registers HII packages to HII database.\r
+\r
+ @retval EFI_SUCCESS This function complete successfully.\r
+ @return Other value if failed to register HII packages.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+ VOID\r
+ );\r
+\r
+/**\r
+\r
+ Call the browser and display the device manager to allow user\r
+ to configure the platform.\r
+\r
+ This function create the dynamic content for device manager. It includes\r
+ section header for all class of devices, one-of opcode to set VBIOS.\r
+ \r
+ @retval EFI_SUCCESS Operation is successful.\r
+ @retval Other values if failed to clean up the dynamic content from HII\r
+ database.\r
+\r
+**/\r
+EFI_STATUS\r
+CallDeviceManager (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+///** @file\r
+// \r
+// Device Manager formset.\r
+// \r
+// Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+// \r
+//**/\r
+\r
+#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }\r
+\r
+#define EFI_DISK_DEVICE_CLASS 0x0001\r
+#define EFI_VIDEO_DEVICE_CLASS 0x0002\r
+#define EFI_NETWORK_DEVICE_CLASS 0x0004\r
+#define EFI_INPUT_DEVICE_CLASS 0x0008\r
+#define EFI_ON_BOARD_DEVICE_CLASS 0x0010\r
+#define EFI_OTHER_DEVICE_CLASS 0x0020\r
+#define LABEL_VBIOS 0x0040\r
+\r
+#define LABEL_END 0xffff\r
+\r
+#define DEVICE_MANAGER_CLASS 0x0000\r
+#define FRONT_PAGE_SUBCLASS 0x0003\r
+\r
+#define DEVICE_MANAGER_FORM_ID 0x1000\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),\r
+ help = STRING_TOKEN(STR_EMPTY_STRING),\r
+ class = DEVICE_MANAGER_CLASS,\r
+ subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+ form formid = DEVICE_MANAGER_FORM_ID,\r
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);\r
+\r
+ //\r
+ // This is where devices get added to the device manager hierarchy\r
+ //\r
+ label EFI_DISK_DEVICE_CLASS;\r
+// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size\r
+\r
+ label EFI_VIDEO_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_NETWORK_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_INPUT_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_ON_BOARD_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_OTHER_DEVICE_CLASS;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+\r
+ label LABEL_VBIOS;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+ subtitle text = STRING_TOKEN(STR_EXIT_STRING);\r
+\r
+ endform;\r
+endformset;\r
+\r
--- /dev/null
+/** @file\r
+ FrontPage routines to handle the callbacks and browser calls\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_GUID mFrontPageGuid = FRONT_PAGE_FORMSET_GUID;\r
+\r
+BOOLEAN gConnectAllHappened = FALSE;\r
+UINTN gCallbackKey;\r
+\r
+EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL *gHiiString;\r
+EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = {\r
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ {\r
+ FakeExtractConfig,\r
+ FakeRouteConfig,\r
+ FrontPageCallback\r
+ }\r
+};\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
+ @param Progress On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results is filled with the requested values.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
+ @param Progress A pointer to a string filled in with the offset of the most\r
+ recent '&' before the first failing name/value pair (or the\r
+ beginning of the string if the failure is in the first\r
+ name/value pair) or the terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The Results is processed successfully.\r
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
+ @retval EFI_DEVICE_ERROR The variable could not be saved.\r
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ CHAR8 *LanguageString;\r
+ CHAR8 *LangCode;\r
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];\r
+ CHAR8 OldLang[ISO_639_2_ENTRY_SIZE];\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ gCallbackKey = QuestionId;\r
+\r
+ //\r
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+ // describe to their customers in documentation how to find their setup information (namely\r
+ // under the device manager and specific buckets)\r
+ //\r
+ switch (QuestionId) {\r
+ case FRONT_PAGE_KEY_CONTINUE:\r
+ //\r
+ // This is the continue - clear the screen and return an error to get out of FrontPage loop\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_LANGUAGE:\r
+ //\r
+ // Collect the languages from what our current Language support is based on our VFR\r
+ //\r
+ LanguageString = HiiLibGetSupportedLanguages (gFrontPagePrivate.HiiHandle);\r
+ ASSERT (LanguageString != NULL);\r
+\r
+ Index = 0;\r
+ LangCode = LanguageString;\r
+ while (*LangCode != 0) {\r
+ HiiLibGetNextLanguage (&LangCode, Lang);\r
+\r
+ if (Index == Value->u8) {\r
+ break;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"PlatformLang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrSize (Lang),\r
+ Lang\r
+ );\r
+\r
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+ //\r
+ // Set UEFI deprecated variable "Lang" for backwards compatibility\r
+ //\r
+ Status = ConvertRfc3066LanguageToIso639Language (Lang, OldLang);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gRT->SetVariable (\r
+ L"Lang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ ISO_639_2_ENTRY_SIZE,\r
+ OldLang\r
+ );\r
+ }\r
+ }\r
+\r
+ FreePool (LanguageString);\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+ //\r
+ // Boot Manager\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+ //\r
+ // Device Manager\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+ //\r
+ // Boot Maintenance Manager\r
+ //\r
+ break;\r
+\r
+ default:\r
+ gCallbackKey = 0;\r
+ break;\r
+ }\r
+\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialize HII information for the FrontPage\r
+\r
+\r
+ @param InitializeHiiData TRUE if HII elements need to be initialized.\r
+\r
+ @retval EFI_SUCCESS The operation is successful.\r
+ @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+ IN BOOLEAN InitializeHiiData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ IFR_OPTION *OptionList;\r
+ CHAR8 *LanguageString;\r
+ CHAR8 *LangCode;\r
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];\r
+ CHAR8 CurrentLang[RFC_3066_ENTRY_SIZE];\r
+ UINTN OptionCount;\r
+ EFI_STRING_ID Token;\r
+ CHAR16 *StringBuffer;\r
+ UINTN BufferSize;\r
+ UINTN Index;\r
+ EFI_HII_HANDLE HiiHandle;\r
+\r
+ if (InitializeHiiData) {\r
+ //\r
+ // Initialize the Device Manager\r
+ //\r
+ InitializeDeviceManager ();\r
+\r
+ //\r
+ // Initialize the Device Manager\r
+ //\r
+ InitializeBootManager ();\r
+\r
+ gCallbackKey = 0;\r
+\r
+ //\r
+ // Locate Hii relative protocols\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gHiiString);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &gHiiConfigRouting);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&gFrontPagePrivate.DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gFrontPagePrivate.DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gFrontPagePrivate.ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = HiiLibPreparePackageList (2, &mFrontPageGuid, FrontPageVfrBin, BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gFrontPagePrivate.DriverHandle,\r
+ &gFrontPagePrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get current language setting\r
+ //\r
+ GetCurrentLanguage (CurrentLang);\r
+\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData.BufferSize = 0x1000;\r
+ UpdateData.Data = AllocateZeroPool (0x1000);\r
+ ASSERT (UpdateData.Data != NULL);\r
+\r
+ OptionList = AllocateZeroPool (0x1000);\r
+ ASSERT (OptionList != NULL);\r
+\r
+ //\r
+ // Collect the languages from what our current Language support is based on our VFR\r
+ //\r
+ HiiHandle = gFrontPagePrivate.HiiHandle;\r
+ LanguageString = HiiLibGetSupportedLanguages (HiiHandle);\r
+ ASSERT (LanguageString != NULL);\r
+\r
+ OptionCount = 0;\r
+ LangCode = LanguageString;\r
+ while (*LangCode != 0) {\r
+ HiiLibGetNextLanguage (&LangCode, Lang);\r
+\r
+ if (gFrontPagePrivate.LanguageToken == NULL) {\r
+ //\r
+ // Get Language Name from String Package. The StringId of Printable Language\r
+ // Name is always 1 which is generated by StringGather Tool.\r
+ //\r
+ BufferSize = 0x100;\r
+ StringBuffer = AllocatePool (BufferSize);\r
+ Status = gHiiString->GetString (\r
+ gHiiString,\r
+ Lang,\r
+ HiiHandle,\r
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+ StringBuffer,\r
+ &BufferSize,\r
+ NULL\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (StringBuffer);\r
+ StringBuffer = AllocatePool (BufferSize);\r
+ Status = gHiiString->GetString (\r
+ gHiiString,\r
+ Lang,\r
+ HiiHandle,\r
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+ StringBuffer,\r
+ &BufferSize,\r
+ NULL\r
+ );\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Token = 0;\r
+ Status = HiiLibNewString (HiiHandle, &Token, StringBuffer);\r
+ FreePool (StringBuffer);\r
+ } else {\r
+ Token = gFrontPagePrivate.LanguageToken[OptionCount];\r
+ }\r
+\r
+ if (AsciiStrCmp (Lang, CurrentLang) == 0) {\r
+ OptionList[OptionCount].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ } else {\r
+ OptionList[OptionCount].Flags = 0;\r
+ }\r
+ OptionList[OptionCount].StringToken = Token;\r
+ OptionList[OptionCount].Value.u8 = (UINT8) OptionCount;\r
+\r
+ OptionCount++;\r
+ }\r
+\r
+ FreePool (LanguageString);\r
+\r
+ UpdateData.Offset = 0;\r
+ CreateOneOfOpCode (\r
+ FRONT_PAGE_KEY_LANGUAGE,\r
+ 0,\r
+ 0,\r
+ STRING_TOKEN (STR_LANGUAGE_SELECT),\r
+ STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ OptionList,\r
+ OptionCount,\r
+ &UpdateData\r
+ );\r
+\r
+ Status = IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mFrontPageGuid,\r
+ FRONT_PAGE_FORM_ID,\r
+ LABEL_SELECT_LANGUAGE,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ //\r
+ // Save the string Id for each language\r
+ //\r
+ gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));\r
+ ASSERT (gFrontPagePrivate.LanguageToken != NULL);\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ gFrontPagePrivate.LanguageToken[Index] = OptionList[Index].StringToken;\r
+ }\r
+\r
+ FreePool (UpdateData.Data);\r
+ FreePool (OptionList);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Call the browser and display the front page\r
+\r
+ @return Status code that will be returned by\r
+ EFI_FORM_BROWSER2_PROTOCOL.SendForm ().\r
+\r
+**/\r
+EFI_STATUS\r
+CallFrontPage (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+\r
+ //\r
+ // Begin waiting for USER INPUT\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)\r
+ );\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &gFrontPagePrivate.HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ //\r
+ // Check whether user change any option setting which needs a reset to be effective\r
+ //\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Acquire the string associated with the ProducerGuid and return it.\r
+\r
+\r
+ @param ProducerGuid The Guid to search the HII database for\r
+ @param Token The token value of the string to extract\r
+ @param String The string that is extracted\r
+\r
+ @retval EFI_SUCCESS The function returns EFI_SUCCESS always.\r
+\r
+**/\r
+EFI_STATUS\r
+GetProducerString (\r
+ IN EFI_GUID *ProducerGuid,\r
+ IN EFI_STRING_ID Token,\r
+ OUT CHAR16 **String\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = HiiLibGetStringFromToken (ProducerGuid, Token, String);\r
+ if (EFI_ERROR (Status)) {\r
+ *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Convert Processor Frequency Data to a string\r
+\r
+ @param ProcessorFrequency The frequency data to process\r
+ @param String The string that is created\r
+\r
+**/\r
+VOID\r
+ConvertProcessorToString (\r
+ IN EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,\r
+ OUT CHAR16 **String\r
+ )\r
+{\r
+ CHAR16 *StringBuffer;\r
+ UINTN Index;\r
+ UINT32 FreqMhz;\r
+\r
+ if (ProcessorFrequency->Exponent >= 6) {\r
+ FreqMhz = ProcessorFrequency->Value;\r
+ for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {\r
+ FreqMhz *= 10;\r
+ }\r
+ } else {\r
+ FreqMhz = 0;\r
+ }\r
+\r
+ StringBuffer = AllocateZeroPool (0x20);\r
+ ASSERT (StringBuffer != NULL);\r
+ Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);\r
+ StrCat (StringBuffer, L".");\r
+ UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);\r
+ StrCat (StringBuffer, L" GHz");\r
+\r
+ *String = (CHAR16 *) StringBuffer;\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Convert Memory Size to a string.\r
+\r
+ @param MemorySize The size of the memory to process\r
+ @param String The string that is created\r
+\r
+**/\r
+VOID\r
+ConvertMemorySizeToString (\r
+ IN UINT32 MemorySize,\r
+ OUT CHAR16 **String\r
+ )\r
+{\r
+ CHAR16 *StringBuffer;\r
+\r
+ StringBuffer = AllocateZeroPool (0x20);\r
+ ASSERT (StringBuffer != NULL);\r
+ UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);\r
+ StrCat (StringBuffer, L" MB RAM");\r
+\r
+ *String = (CHAR16 *) StringBuffer;\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Update the banner information for the Front Page based on DataHub information.\r
+\r
+**/\r
+VOID\r
+UpdateFrontPageStrings (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING_ID TokenToUpdate;\r
+ CHAR16 *NewString;\r
+ UINT64 MonotonicCount;\r
+ EFI_DATA_HUB_PROTOCOL *DataHub;\r
+ EFI_DATA_RECORD_HEADER *Record;\r
+ EFI_SUBCLASS_TYPE1_HEADER *DataHeader;\r
+ EFI_MISC_BIOS_VENDOR_DATA *BiosVendor;\r
+ EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;\r
+ EFI_PROCESSOR_VERSION_DATA *ProcessorVersion;\r
+ EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;\r
+ EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray;\r
+ BOOLEAN Find[5];\r
+\r
+ ZeroMem (Find, sizeof (Find));\r
+\r
+ //\r
+ // Update Front Page strings\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDataHubProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DataHub\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ MonotonicCount = 0;\r
+ Record = NULL;\r
+ do {\r
+ Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
+ DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+ (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)\r
+ ) {\r
+ BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);\r
+ GetProducerString (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);\r
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[0] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+ (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)\r
+ ) {\r
+ SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);\r
+ GetProducerString (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);\r
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[1] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+ (DataHeader->RecordType == ProcessorVersionRecordType)\r
+ ) {\r
+ ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);\r
+ GetProducerString (&Record->ProducerName, *ProcessorVersion, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);\r
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[2] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+ (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)\r
+ ) {\r
+ ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);\r
+ ConvertProcessorToString (ProcessorFrequency, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);\r
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[3] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMemorySubClassGuid) &&\r
+ (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)\r
+ ) {\r
+ MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);\r
+ ConvertMemorySizeToString (\r
+ (UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20)),\r
+ &NewString\r
+ );\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);\r
+ HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[4] = TRUE;\r
+ }\r
+ }\r
+ } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Function waits for a given event to fire, or for an optional timeout to expire.\r
+\r
+ @param Event The event to wait for\r
+ @param Timeout An optional timeout value in 100 ns units.\r
+\r
+ @retval EFI_SUCCESS Event fired before Timeout expired.\r
+ @retval EFI_TIME_OUT Timout expired before Event fired..\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForSingleEvent (\r
+ IN EFI_EVENT Event,\r
+ IN UINT64 Timeout OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_EVENT TimerEvent;\r
+ EFI_EVENT WaitList[2];\r
+\r
+ if (Timeout != 0) {\r
+ //\r
+ // Create a timer event\r
+ //\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set the timer event\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ Timeout\r
+ );\r
+\r
+ //\r
+ // Wait for the original event or the timer\r
+ //\r
+ WaitList[0] = Event;\r
+ WaitList[1] = TimerEvent;\r
+ Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+ gBS->CloseEvent (TimerEvent);\r
+\r
+ //\r
+ // If the timer expired, change the return to timed out\r
+ //\r
+ if (!EFI_ERROR (Status) && Index == 1) {\r
+ Status = EFI_TIMEOUT;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // No timeout... just wait on the event\r
+ //\r
+ Status = gBS->WaitForEvent (1, &Event, &Index);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ ASSERT (Index == 0);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Function show progress bar to wait for user input.\r
+\r
+\r
+ @param TimeoutDefault The fault time out value before the system continue to boot.\r
+\r
+ @retval EFI_SUCCESS User pressed some key except "Enter"\r
+ @retval EFI_TIME_OUT Timout expired or user press "Enter"\r
+\r
+**/\r
+EFI_STATUS\r
+ShowProgress (\r
+ IN UINT16 TimeoutDefault\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *TmpStr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ EFI_INPUT_KEY Key;\r
+ UINT16 TimeoutRemain;\r
+\r
+ if (TimeoutDefault == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));\r
+ \r
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+ //\r
+ // Clear the progress status bar first\r
+ //\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);\r
+ }\r
+\r
+ TimeoutRemain = TimeoutDefault;\r
+ while (TimeoutRemain != 0) {\r
+ DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));\r
+ \r
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);\r
+ if (Status != EFI_TIMEOUT) {\r
+ break;\r
+ }\r
+ TimeoutRemain--;\r
+\r
+ //\r
+ // Show progress\r
+ //\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),\r
+ 0\r
+ );\r
+ }\r
+ }\r
+ gBS->FreePool (TmpStr);\r
+\r
+ //\r
+ // Timeout expired\r
+ //\r
+ if (TimeoutRemain == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ //\r
+ // User pressed some key\r
+ //\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ //\r
+ // User pressed enter, equivalent to select "continue"\r
+ //\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function is the main entry of the platform setup entry.\r
+ The function will present the main menu of the system setup,\r
+ this is the platform reference part and can be customize.\r
+\r
+\r
+ @param TimeoutDefault The fault time out value before the system\r
+ continue to boot.\r
+ @param ConnectAllHappened The indicater to check if the connect all have\r
+ already happended.\r
+\r
+**/\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+ IN UINT16 TimeoutDefault,\r
+ IN BOOLEAN ConnectAllHappened\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+\r
+ PERF_START (0, "BdsTimeOut", "BDS", 0);\r
+ //\r
+ // Indicate if we need connect all in the platform setup\r
+ //\r
+ if (ConnectAllHappened) {\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+\r
+ if (TimeoutDefault != 0xffff) {\r
+ Status = ShowProgress (TimeoutDefault);\r
+\r
+ //\r
+ // Ensure screen is clear when switch Console from Graphics mode to Text mode\r
+ //\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Timeout or user press enter to continue\r
+ //\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ do {\r
+\r
+ InitializeFrontPage (FALSE);\r
+\r
+ //\r
+ // Update Front Page strings\r
+ //\r
+ UpdateFrontPageStrings ();\r
+\r
+ gCallbackKey = 0;\r
+ Status = CallFrontPage ();\r
+\r
+ //\r
+ // If gCallbackKey is greater than 1 and less or equal to 5,\r
+ // it will lauch configuration utilities.\r
+ // 2 = set language\r
+ // 3 = boot manager\r
+ // 4 = device manager\r
+ // 5 = boot maintainenance manager\r
+ //\r
+ if (gCallbackKey != 0) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)\r
+ );\r
+ }\r
+ //\r
+ // Based on the key that was set, we can determine what to do\r
+ //\r
+ switch (gCallbackKey) {\r
+ //\r
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+ // describe to their customers in documentation how to find their setup information (namely\r
+ // under the device manager and specific buckets)\r
+ //\r
+ // These entries consist of the Continue, Select language, Boot Manager, and Device Manager\r
+ //\r
+ case FRONT_PAGE_KEY_CONTINUE:\r
+ //\r
+ // User hit continue\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_LANGUAGE:\r
+ //\r
+ // User made a language setting change - display front page again\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+ //\r
+ // User chose to run the Boot Manager\r
+ //\r
+ CallBootManager ();\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+ //\r
+ // Display the Device Manager\r
+ //\r
+ do {\r
+ CallDeviceManager();\r
+ } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+ //\r
+ // Display the Boot Maintenance Manager\r
+ //\r
+ BdsStartBootMaint ();\r
+ break;\r
+ }\r
+\r
+ } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));\r
+\r
+ //\r
+ //Will leave browser, check any reset required change is applied? if yes, reset system\r
+ //\r
+ SetupResetReminder ();\r
+\r
+Exit:\r
+ //\r
+ // Automatically load current entry\r
+ // Note: The following lines of code only execute when Auto boot\r
+ // takes affect\r
+ //\r
+ PERF_END (0, "BdsTimeOut", "BDS", 0);\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+\r
+}\r
--- /dev/null
+/** @file\r
+ FrontPage routines to handle the callbacks and browser calls\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _FRONT_PAGE_H_\r
+#define _FRONT_PAGE_H_\r
+\r
+#include "DeviceMngr/DeviceManager.h"\r
+#include "BootMaint/BootMaint.h"\r
+#include "BootMngr/BootManager.h"\r
+#include "String.h"\r
+\r
+#define ONE_SECOND 10000000\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define FRONT_PAGE_FORM_ID 0x1000\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE 0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE 0x1000\r
+\r
+#define FRONT_PAGE_FORMSET_GUID \\r
+ { \\r
+ 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe} \\r
+ }\r
+\r
+#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('F', 'P', 'C', 'B')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ //\r
+ // HII relative handles\r
+ //\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_STRING_ID *LanguageToken;\r
+\r
+ //\r
+ // Produced protocols\r
+ //\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+} FRONT_PAGE_CALLBACK_DATA;\r
+\r
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ FRONT_PAGE_CALLBACK_DATA, \\r
+ ConfigAccess, \\r
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE \\r
+ )\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 FrontPageVfrBin[];\r
+\r
+extern EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;\r
+extern EFI_HII_STRING_PROTOCOL *gHiiString;\r
+extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;\r
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+extern UINTN gCallbackKey;\r
+extern BOOLEAN gConnectAllHappened;\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+\r
+ @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Request - A null-terminated Unicode string in <ConfigRequest> format.\r
+ @param Progress - On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ @param Results - A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results is filled with the requested values.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ );\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+\r
+ @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Configuration - A null-terminated Unicode string in <ConfigResp> format.\r
+ @param Progress - A pointer to a string filled in with the offset of the most\r
+ recent '&' before the first failing name/value pair (or the\r
+ beginning of the string if the failure is in the first\r
+ name/value pair) or the terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The Results is processed successfully.\r
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ );\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+\r
+ @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action - Specifies the type of action taken by the browser.\r
+ @param QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type - The type of value for the question.\r
+ @param Value - A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
+ @retval EFI_DEVICE_ERROR The variable could not be saved.\r
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ );\r
+\r
+/**\r
+ Initialize HII information for the FrontPage\r
+\r
+\r
+ @param InitializeHiiData TRUE if HII elements need to be initialized.\r
+\r
+ @retval EFI_SUCCESS The operation is successful.\r
+ @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+ IN BOOLEAN InitializeHiiData\r
+ );\r
+\r
+/**\r
+ Acquire the string associated with the ProducerGuid and return it.\r
+\r
+\r
+ @param ProducerGuid - The Guid to search the HII database for\r
+ @param Token - The token value of the string to extract\r
+ @param String - The string that is extracted\r
+\r
+ @retval EFI_SUCCESS The function returns EFI_SUCCESS always.\r
+\r
+**/\r
+EFI_STATUS\r
+GetProducerString (\r
+ IN EFI_GUID *ProducerGuid,\r
+ IN EFI_STRING_ID Token,\r
+ OUT CHAR16 **String\r
+ );\r
+\r
+/**\r
+ Compare two EFI_TIME data.\r
+\r
+\r
+ @param FirstTime - A pointer to the first EFI_TIME data.\r
+ @param SecondTime - A pointer to the second EFI_TIME data.\r
+\r
+ @retval TRUE The FirstTime is not later than the SecondTime.\r
+ @retval FALSE The FirstTime is later than the SecondTime.\r
+\r
+**/\r
+BOOLEAN\r
+TimeCompare (\r
+ IN EFI_TIME *FirstTime,\r
+ IN EFI_TIME *SecondTime\r
+ );\r
+\r
+/**\r
+ This function is the main entry of the platform setup entry.\r
+ The function will present the main menu of the system setup,\r
+ this is the platform reference part and can be customize.\r
+\r
+\r
+ @param TimeoutDefault - The fault time out value before the system\r
+ continue to boot.\r
+ @param ConnectAllHappened - The indicater to check if the connect all have\r
+ already happended.\r
+\r
+**/\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+ IN UINT16 TimeoutDefault,\r
+ IN BOOLEAN ConnectAllHappened\r
+ );\r
+\r
+#endif // _FRONT_PAGE_H_\r
+\r
--- /dev/null
+///** @file\r
+// \r
+// Browser formset.\r
+// \r
+// Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// \r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+// \r
+//**/\r
+\r
+#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }\r
+\r
+#define FRONT_PAGE_CLASS 0x0000\r
+#define FRONT_PAGE_SUBCLASS 0x0002\r
+\r
+#define FRONT_PAGE_FORM_ID 0x1000\r
+\r
+#define FRONT_PAGE_ITEM_ONE 0x0001\r
+#define FRONT_PAGE_ITEM_TWO 0x0002\r
+#define FRONT_PAGE_ITEM_THREE 0x0003\r
+#define FRONT_PAGE_ITEM_FOUR 0x0004\r
+#define FRONT_PAGE_ITEM_FIVE 0x0005\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE 0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE 0x1000\r
+#define LABEL_TIMEOUT 0x2000\r
+#define LABEL_END 0xffff\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ class = FRONT_PAGE_CLASS,\r
+ subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+ form formid = FRONT_PAGE_FORM_ID,\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE);\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),\r
+ line 0,\r
+ align left;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),\r
+ line 1,\r
+ align left;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),\r
+ line 1,\r
+ align right;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),\r
+ line 2,\r
+ align left;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),\r
+ line 2,\r
+ align right;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),\r
+// line 0,\r
+// align left;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),\r
+// line 0,\r
+// align right;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),\r
+// line 1,\r
+// align left;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),\r
+// line 1,\r
+// align right;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),\r
+// line 2,\r
+// align left;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),\r
+// line 3,\r
+// align left;\r
+\r
+ goto FRONT_PAGE_ITEM_ONE,\r
+ prompt = STRING_TOKEN(STR_CONTINUE_PROMPT),\r
+ help = STRING_TOKEN(STR_CONTINUE_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_CONTINUE;\r
+\r
+ label LABEL_SELECT_LANGUAGE;\r
+ //\r
+ // This is where we will dynamically add a OneOf type op-code to select\r
+ // Languages from the currently available choices\r
+ //\r
+ label LABEL_END;\r
+\r
+ goto FRONT_PAGE_ITEM_THREE,\r
+ prompt = STRING_TOKEN(STR_BOOT_MANAGER),\r
+ help = STRING_TOKEN(STR_BOOT_MANAGER_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_BOOT_MANAGER;\r
+\r
+ goto FRONT_PAGE_ITEM_FOUR,\r
+ prompt = STRING_TOKEN(STR_DEVICE_MANAGER),\r
+ help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+\r
+ goto FRONT_PAGE_ITEM_FIVE,\r
+ prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER),\r
+ help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_BOOT_MAINTAIN;\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/** @file\r
+ Provides a way for 3rd party applications to register themselves for launch by the\r
+ Boot Manager based on hot key\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Hotkey.h"\r
+\r
+\r
+LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
+BOOLEAN mHotkeyCallbackPending = FALSE;\r
+EFI_EVENT mHotkeyEvent;\r
+VOID *mHotkeyRegistration;\r
+\r
+\r
+/**\r
+ Check if the Key Option is valid or not.\r
+\r
+ @param KeyOption The Hot Key Option to be checked.\r
+\r
+ @retval TRUE The Hot Key Option is valid.\r
+ @retval FALSE The Hot Key Option is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+IsKeyOptionValid (\r
+ IN EFI_KEY_OPTION *KeyOption\r
+)\r
+{\r
+ UINT16 BootOptionName[10];\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOptionSize;\r
+ UINT32 Crc;\r
+\r
+ //\r
+ // Check whether corresponding Boot Option exist\r
+ //\r
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+\r
+ if (BootOptionVar == NULL || BootOptionSize == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check CRC for Boot Option\r
+ //\r
+ gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);\r
+ FreePool (BootOptionVar);\r
+\r
+ return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);\r
+}\r
+\r
+/**\r
+ Create Key#### for the given hotkey.\r
+\r
+ @param KeyOption The Hot Key Option to be added.\r
+ @param KeyOptionNumber The key option number for Key#### (optional).\r
+\r
+ @retval EFI_SUCCESS Register hotkey successfully.\r
+ @retval EFI_INVALID_PARAMETER The hotkey option is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterHotkey (\r
+ IN EFI_KEY_OPTION *KeyOption,\r
+ OUT UINT16 *KeyOptionNumber\r
+)\r
+{\r
+ UINT16 KeyOptionName[10];\r
+ UINT16 *KeyOrder;\r
+ UINTN KeyOrderSize;\r
+ UINT16 *NewKeyOrder;\r
+ UINTN Index;\r
+ UINT16 MaxOptionNumber;\r
+ UINT16 RegisterOptionNumber;\r
+ EFI_KEY_OPTION *TempOption;\r
+ UINTN TempOptionSize;\r
+ EFI_STATUS Status;\r
+ UINTN KeyOptionSize;\r
+ BOOLEAN UpdateBootOption;\r
+\r
+ //\r
+ // Validate the given key option\r
+ //\r
+ if (!IsKeyOptionValid (KeyOption)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) * sizeof (EFI_INPUT_KEY);\r
+ UpdateBootOption = FALSE;\r
+\r
+ //\r
+ // check whether HotKey conflict with keys used by Setup Browser\r
+ //\r
+ KeyOrder = BdsLibGetVariableAndSize (\r
+ VAR_KEY_ORDER,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOrderSize\r
+ );\r
+ if (KeyOrder == NULL) {\r
+ KeyOrderSize = 0;\r
+ }\r
+\r
+ //\r
+ // Find free key option number\r
+ //\r
+ MaxOptionNumber = 0;\r
+ TempOption = NULL;\r
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+ if (MaxOptionNumber < KeyOrder[Index]) {\r
+ MaxOptionNumber = KeyOrder[Index];\r
+ }\r
+\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+ TempOption = BdsLibGetVariableAndSize (\r
+ KeyOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &TempOptionSize\r
+ );\r
+\r
+ if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
+ //\r
+ // Got the option, so just return\r
+ //\r
+ FreePool (TempOption);\r
+ FreePool (KeyOrder);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {\r
+ if (GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) == 0 ||\r
+ CompareMem (\r
+ ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
+ ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
+ KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
+ ) == 0) {\r
+ //\r
+ // Hotkey is the same but BootOption changed, need update\r
+ //\r
+ UpdateBootOption = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (TempOption);\r
+ }\r
+\r
+ if (UpdateBootOption) {\r
+ RegisterOptionNumber = KeyOrder[Index];\r
+ FreePool (TempOption);\r
+ } else {\r
+ RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
+ }\r
+\r
+ if (KeyOptionNumber != NULL) {\r
+ *KeyOptionNumber = RegisterOptionNumber;\r
+ }\r
+\r
+ //\r
+ // Create variable Key####\r
+ //\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
+ Status = gRT->SetVariable (\r
+ KeyOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ KeyOptionSize,\r
+ KeyOption\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (KeyOrder);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Update the key order variable - "KeyOrder"\r
+ //\r
+ if (!UpdateBootOption) {\r
+ Index = KeyOrderSize / sizeof (UINT16);\r
+ KeyOrderSize += sizeof (UINT16);\r
+ }\r
+\r
+ NewKeyOrder = AllocatePool (KeyOrderSize);\r
+ if (NewKeyOrder == NULL) {\r
+ FreePool (KeyOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (KeyOrder != NULL) {\r
+ CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
+ }\r
+\r
+ NewKeyOrder[Index] = RegisterOptionNumber;\r
+\r
+ Status = gRT->SetVariable (\r
+ VAR_KEY_ORDER,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ KeyOrderSize,\r
+ NewKeyOrder\r
+ );\r
+\r
+ FreePool (KeyOrder);\r
+ FreePool (NewKeyOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ Delete Key#### for the given Key Option number.\r
+\r
+ @param KeyOptionNumber Key option number for Key####\r
+\r
+ @retval EFI_SUCCESS Unregister hotkey successfully.\r
+ @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
+\r
+**/\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+ IN UINT16 KeyOptionNumber\r
+)\r
+{\r
+ UINT16 KeyOption[10];\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN Index2Del;\r
+ UINT16 *KeyOrder;\r
+ UINTN KeyOrderSize;\r
+\r
+ //\r
+ // Delete variable Key####\r
+ //\r
+ UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
+ gRT->SetVariable (\r
+ KeyOption,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Adjust key order array\r
+ //\r
+ KeyOrder = BdsLibGetVariableAndSize (\r
+ VAR_KEY_ORDER,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOrderSize\r
+ );\r
+ if (KeyOrder == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Index2Del = 0;\r
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+ if (KeyOrder[Index] == KeyOptionNumber) {\r
+ Index2Del = Index;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != KeyOrderSize / sizeof (UINT16)) {\r
+ //\r
+ // KeyOptionNumber found in "KeyOrder", delete it\r
+ //\r
+ for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
+ KeyOrder[Index] = KeyOrder[Index + 1];\r
+ }\r
+\r
+ KeyOrderSize -= sizeof (UINT16);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ VAR_KEY_ORDER,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ KeyOrderSize,\r
+ KeyOrder\r
+ );\r
+\r
+ FreePool (KeyOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This is the common notification function for HotKeys, it will be registered\r
+ with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
+\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke\r
+ information for the key that was pressed.\r
+\r
+ @retval EFI_SUCCESS KeyData is successfully processed.\r
+ @return EFI_NOT_FOUND Fail to find boot option variable.\r
+**/\r
+EFI_STATUS\r
+HotkeyCallback (\r
+ IN EFI_KEY_DATA *KeyData\r
+)\r
+{\r
+ BOOLEAN HotkeyCatched;\r
+ LIST_ENTRY BootLists;\r
+ LIST_ENTRY *Link;\r
+ BDS_HOTKEY_OPTION *Hotkey;\r
+ UINT16 Buffer[10];\r
+ BDS_COMMON_OPTION *BootOption;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ EFI_STATUS Status;\r
+ EFI_KEY_DATA *HotkeyData;\r
+\r
+ if (mHotkeyCallbackPending) {\r
+ //\r
+ // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
+ // the current Boot#### load option returned\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Link = GetFirstNode (&mHotkeyList);\r
+\r
+ while (!IsNull (&mHotkeyList, Link)) {\r
+ HotkeyCatched = FALSE;\r
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+ //\r
+ // Is this Key Stroke we are waiting for?\r
+ //\r
+ ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
+ HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
+ if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
+ (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
+ ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {\r
+ //\r
+ // Receive an expecting key stroke\r
+ //\r
+ if (Hotkey->CodeCount > 1) {\r
+ //\r
+ // For hotkey of key combination, transit to next waiting state\r
+ //\r
+ Hotkey->WaitingKey++;\r
+\r
+ if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
+ //\r
+ // Received the whole key stroke sequence\r
+ //\r
+ HotkeyCatched = TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // For hotkey of single key stroke\r
+ //\r
+ HotkeyCatched = TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // Receive an unexpected key stroke, reset to initial waiting state\r
+ //\r
+ Hotkey->WaitingKey = 0;\r
+ }\r
+\r
+ if (HotkeyCatched) {\r
+ //\r
+ // Reset to initial waiting state\r
+ //\r
+ Hotkey->WaitingKey = 0;\r
+\r
+ //\r
+ // Launch its BootOption\r
+ //\r
+ InitializeListHead (&BootLists);\r
+\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+ if (BootOption == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+\r
+ //\r
+ // Clear the screen before launch this BootOption\r
+ //\r
+ gST->ConOut->Reset (gST->ConOut, FALSE);\r
+\r
+ mHotkeyCallbackPending = TRUE;\r
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ mHotkeyCallbackPending = FALSE;\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Call platform action to indicate the boot fail\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+ } else {\r
+ //\r
+ // Call platform action to indicate the boot success\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+ PlatformBdsBootSuccess (BootOption);\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&mHotkeyList, Link);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
+\r
+ @param SimpleTextInEx Simple Text Input Ex protocol instance\r
+\r
+ @retval EFI_SUCCESS Register hotkey notification function successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
+\r
+**/\r
+EFI_STATUS\r
+HotkeyRegisterNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
+)\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BDS_HOTKEY_OPTION *Hotkey;\r
+\r
+ //\r
+ // Register notification function for each hotkey\r
+ //\r
+ Link = GetFirstNode (&mHotkeyList);\r
+\r
+ while (!IsNull (&mHotkeyList, Link)) {\r
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+ Index = 0;\r
+ do {\r
+ Status = SimpleTextInEx->RegisterKeyNotify (\r
+ SimpleTextInEx,\r
+ &Hotkey->KeyData[Index],\r
+ HotkeyCallback,\r
+ &Hotkey->NotifyHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // some of the hotkey registry failed\r
+ //\r
+ return Status;\r
+ }\r
+ Index ++;\r
+ } while (Index < Hotkey->CodeCount);\r
+\r
+ Link = GetNextNode (&mHotkeyList, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Callback function for SimpleTextInEx protocol install events\r
+\r
+ @param Event the event that is signaled.\r
+ @param Context not used here.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HotkeyEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ EFI_HANDLE Handle;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
+\r
+ while (TRUE) {\r
+ BufferSize = sizeof (EFI_HANDLE);\r
+ Status = gBS->LocateHandle (\r
+ ByRegisterNotify,\r
+ NULL,\r
+ mHotkeyRegistration,\r
+ &BufferSize,\r
+ &Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no more notification events exist\r
+ //\r
+ return ;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &SimpleTextInEx\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ HotkeyRegisterNotify (SimpleTextInEx);\r
+ }\r
+}\r
+\r
+/**\r
+ Insert Key Option to hotkey list.\r
+\r
+ @param KeyOption The Hot Key Option to be added to hotkey list.\r
+\r
+ @retval EFI_SUCCESS Add to hotkey list success.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
+**/\r
+EFI_STATUS\r
+HotkeyInsertList (\r
+ IN EFI_KEY_OPTION *KeyOption\r
+)\r
+{\r
+ BDS_HOTKEY_OPTION *HotkeyLeft;\r
+ BDS_HOTKEY_OPTION *HotkeyRight;\r
+ UINTN Index;\r
+ UINT32 KeyOptions;\r
+ UINT32 KeyShiftStateLeft;\r
+ UINT32 KeyShiftStateRight;\r
+ EFI_INPUT_KEY *InputKey;\r
+ EFI_KEY_DATA *KeyData;\r
+\r
+ HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
+ if (HotkeyLeft == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
+ HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
+\r
+ KeyOptions = KeyOption->KeyData.PackedValue;\r
+\r
+ HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);\r
+\r
+ //\r
+ // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
+ //\r
+ KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |\r
+ ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |\r
+ ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |\r
+ ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |\r
+ ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |\r
+ EFI_SHIFT_STATE_VALID;\r
+\r
+ KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
+\r
+ InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
+\r
+ Index = 0;\r
+ KeyData = &HotkeyLeft->KeyData[0];\r
+ do {\r
+ //\r
+ // If Key CodeCount is 0, then only KeyData[0] is used;\r
+ // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
+ //\r
+ KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
+ KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
+ KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
+\r
+ Index++;\r
+ KeyData++;\r
+ } while (Index < HotkeyLeft->CodeCount);\r
+ InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
+\r
+ if (KeyShiftStateLeft != KeyShiftStateRight) {\r
+ //\r
+ // Need an extra hotkey for shift key on right\r
+ //\r
+ HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
+ if (HotkeyRight == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Index = 0;\r
+ KeyData = &HotkeyRight->KeyData[0];\r
+ do {\r
+ //\r
+ // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
+ // only need to update KeyState.KeyShiftState\r
+ //\r
+ KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
+\r
+ Index++;\r
+ KeyData++;\r
+ } while (Index < HotkeyRight->CodeCount);\r
+ InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+ @retval EFI_SUCCESS Hotkey services successfully initialized.\r
+ @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
+**/\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 BootOptionSupport;\r
+ UINT16 *KeyOrder;\r
+ UINTN KeyOrderSize;\r
+ UINTN Index;\r
+ UINT16 KeyOptionName[8];\r
+ UINTN KeyOptionSize;\r
+ EFI_KEY_OPTION *KeyOption;\r
+\r
+ //\r
+ // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
+ //\r
+ BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
+ Status = gRT->SetVariable (\r
+ L"BootOptionSupport",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT32),\r
+ &BootOptionSupport\r
+ );\r
+\r
+ //\r
+ // Get valid Key Option List from private EFI variable "KeyOrder"\r
+ //\r
+ KeyOrder = BdsLibGetVariableAndSize (\r
+ VAR_KEY_ORDER,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOrderSize\r
+ );\r
+\r
+ if (KeyOrder == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+ KeyOption = BdsLibGetVariableAndSize (\r
+ KeyOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOptionSize\r
+ );\r
+\r
+ if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
+ UnregisterHotkey (KeyOrder[Index]);\r
+ } else {\r
+ HotkeyInsertList (KeyOption);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Register Protocol notify for Hotkey service\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ HotkeyEvent,\r
+ NULL,\r
+ &mHotkeyEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register for protocol notifications on this event\r
+ //\r
+ Status = gBS->RegisterProtocolNotify (\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ mHotkeyEvent,\r
+ &mHotkeyRegistration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Provides a way for 3rd party applications to register themselves for launch by the\r
+ Boot Manager based on hot key\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _HOTKEY_H_\r
+#define _HOTKEY_H_\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+#define GET_KEY_CODE_COUNT(KeyOptions) (((KeyOptions) & EFI_KEY_CODE_COUNT) >> 8)\r
+\r
+#define BDS_HOTKEY_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'K', 'O')\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_HANDLE NotifyHandle;\r
+ UINT16 BootOptionNumber;\r
+ UINT8 CodeCount;\r
+ UINT8 WaitingKey;\r
+ EFI_KEY_DATA KeyData[3];\r
+} BDS_HOTKEY_OPTION;\r
+\r
+#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE)\r
+\r
+#define VAR_KEY_ORDER L"KeyOrder"\r
+\r
+/**\r
+\r
+ Create Key#### for the given hotkey.\r
+\r
+\r
+ @param KeyOption - The Hot Key Option to be added.\r
+ @param KeyOptionNumber - The key option number for Key#### (optional).\r
+\r
+ @retval EFI_SUCCESS Register hotkey successfully.\r
+ @retval EFI_INVALID_PARAMETER The hotkey option is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterHotkey (\r
+ IN EFI_KEY_OPTION *KeyOption,\r
+ OUT UINT16 *KeyOptionNumber\r
+ );\r
+\r
+/**\r
+\r
+ Delete Key#### for the given Key Option number.\r
+\r
+\r
+ @param KeyOptionNumber - Key option number for Key####\r
+\r
+ @retval EFI_SUCCESS Unregister hotkey successfully.\r
+ @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
+\r
+**/\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+ IN UINT16 KeyOptionNumber\r
+ );\r
+\r
+\r
+/**\r
+\r
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+\r
+ @param VOID\r
+\r
+ @retval EFI_SUCCESS Hotkey services successfully initialized.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Set the level of support for Hardware Error Record Persistence that is\r
+ implemented by the platform.\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HwErrRecSupport.h"\r
+\r
+/**\r
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+ level of support for Hardware Error Record Persistence that is implemented\r
+ by the platform.\r
+\r
+\r
+ @param HwErrRecSupportLevel\r
+ zero value: Indicates that the platform implements no support for\r
+ Hardware Error Record Persistence.\r
+ non-zero value: Indicates that the platform implements Hardware Error\r
+ Record Persistence.\r
+\r
+**/\r
+VOID\r
+InitializeHwErrRecSupport (\r
+ IN UINT16 HwErrRecSupportLevel\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gRT->SetVariable (\r
+ L"HwErrRecSupport",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (UINT16),\r
+ &HwErrRecSupportLevel\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HwErrRecSupport: Can not set the variable\n"));\r
+ }\r
+\r
+}\r
--- /dev/null
+/** @file\r
+ Set the level of support for Hardware Error Record Persistence that is\r
+ implemented by the platform.\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _HW_ERR_REC_SUPPORT_H_\r
+#define _HW_ERR_REC_SUPPORT_H_\r
+\r
+#include "Bds.h"\r
+\r
+/**\r
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+ level of support for Hardware Error Record Persistence that is implemented\r
+ by the platform.\r
+\r
+\r
+ @param HwErrRecSupportLevel\r
+ zero value - Indicates that the platform implements no support for\r
+ Hardware Error Record Persistence.\r
+ non-zero value - Indicates that the platform implements Hardware Error\r
+ Record Persistence.\r
+\r
+**/\r
+VOID\r
+InitializeHwErrRecSupport (\r
+ IN UINT16 HwErrRecSupportLevel\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Language settings\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+#define NARROW_GLYPH_NUMBER 8\r
+#define WIDE_GLYPH_NUMBER 75\r
+\r
+EFI_GUID mFontPackageGuid = {\r
+ 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc}\r
+};\r
+\r
+typedef struct {\r
+ ///\r
+ /// This 4-bytes total array length is required by HiiLibPreparePackageList()\r
+ ///\r
+ UINT32 Length;\r
+\r
+ //\r
+ // This is the Font package definition\r
+ //\r
+ EFI_HII_PACKAGE_HEADER Header;\r
+ UINT16 NumberOfNarrowGlyphs;\r
+ UINT16 NumberOfWideGlyphs;\r
+ EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER];\r
+ EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER];\r
+} FONT_PACK_BIN;\r
+\r
+FONT_PACK_BIN mFontBin = {\r
+ sizeof (FONT_PACK_BIN),\r
+ {\r
+ sizeof (FONT_PACK_BIN) - sizeof (UINT32),\r
+ EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+ },\r
+ NARROW_GLYPH_NUMBER,\r
+ 0,\r
+ { // Narrow Glyphs\r
+ {\r
+ 0x05d0,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x4E,\r
+ 0x6E,\r
+ 0x62,\r
+ 0x32,\r
+ 0x32,\r
+ 0x3C,\r
+ 0x68,\r
+ 0x4C,\r
+ 0x4C,\r
+ 0x46,\r
+ 0x76,\r
+ 0x72,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d1,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x78,\r
+ 0x7C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x7E,\r
+ 0x7E,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d2,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x78,\r
+ 0x7C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x1C,\r
+ 0x3E,\r
+ 0x66,\r
+ 0x66,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d3,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x7E,\r
+ 0x7E,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d4,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x7C,\r
+ 0x7E,\r
+ 0x06,\r
+ 0x06,\r
+ 0x06,\r
+ 0x06,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d5,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x3C,\r
+ 0x3C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d6,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x38,\r
+ 0x38,\r
+ 0x1E,\r
+ 0x1E,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x0000,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+/**\r
+ Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver.\r
+\r
+**/\r
+VOID\r
+ExportFonts (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
+ PackageList = HiiLibPreparePackageList (1, &mFontPackageGuid, &mFontBin);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, DriverHandle, &HiiHandle);\r
+ FreePool (PackageList);\r
+}\r
+\r
+/**\r
+ Determine the current language that will be used\r
+ based on language related EFI Variables.\r
+\r
+ @param LangCodesSettingRequired - If required to set LangCode variable\r
+\r
+**/\r
+VOID\r
+InitializeLanguage (\r
+ BOOLEAN LangCodesSettingRequired\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ CHAR8 *Lang;\r
+ CHAR8 LangCode[ISO_639_2_ENTRY_SIZE];\r
+ CHAR8 *LangCodes;\r
+ CHAR8 *PlatformLang;\r
+ CHAR8 *PlatformLangCodes;\r
+ UINTN Index;\r
+ BOOLEAN Invalid;\r
+\r
+ ExportFonts ();\r
+\r
+ LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);\r
+ if (LangCodesSettingRequired) {\r
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+ //\r
+ // UEFI 2.1 depricated this variable so we support turning it off\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"LangCodes",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrLen (LangCodes),\r
+ LangCodes\r
+ );\r
+ }\r
+\r
+\r
+ PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);\r
+ Status = gRT->SetVariable (\r
+ L"PlatformLangCodes",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrSize (PlatformLangCodes),\r
+ PlatformLangCodes\r
+ );\r
+ }\r
+\r
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+ //\r
+ // UEFI 2.1 depricated this variable so we support turning it off\r
+ //\r
+\r
+ //\r
+ // Find current LangCode from Lang NV Variable\r
+ //\r
+ Size = ISO_639_2_ENTRY_SIZE;\r
+ Status = gRT->GetVariable (\r
+ L"Lang",\r
+ &gEfiGlobalVariableGuid,\r
+ NULL,\r
+ &Size,\r
+ &LangCode\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_NOT_FOUND;\r
+ for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {\r
+ if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // If we cannot get language code from Lang variable,\r
+ // or LangCode cannot be found from language table,\r
+ // set the mDefaultLangCode to Lang variable.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);\r
+ Status = gRT->SetVariable (\r
+ L"Lang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ ISO_639_2_ENTRY_SIZE,\r
+ Lang\r
+ );\r
+ }\r
+ }\r
+\r
+ Invalid = FALSE;\r
+ PlatformLang = BdsLibGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);\r
+ if (PlatformLang != NULL) {\r
+ //\r
+ // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD\r
+ // Set Invalid based on state of PlatformLang.\r
+ //\r
+\r
+ FreePool (PlatformLang);\r
+ } else {\r
+ // No valid variable is set\r
+ Invalid = TRUE;\r
+ }\r
+\r
+ if (Invalid) {\r
+ PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);\r
+ Status = gRT->SetVariable (\r
+ L"PlatformLang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrSize (PlatformLang),\r
+ PlatformLang\r
+ );\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ Language setting\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LANGUAGE_H_\r
+#define _LANGUAGE_H_\r
+\r
+#include "String.h"\r
+\r
+/**\r
+ Determine the current language that will be used\r
+ based on language related EFI Variables.\r
+\r
+ @param LangCodesSettingRequired If required to set LangCode variable\r
+\r
+**/\r
+VOID\r
+InitializeLanguage (\r
+ BOOLEAN LangCodesSettingRequired\r
+ );\r
+\r
+#endif // _LANGUAGE_H_\r
--- /dev/null
+/** @file\r
+ Perform the platform memory test\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+/**\r
+\r
+ Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+\r
+ @param TitleForeground Foreground color for Title.\r
+ @param TitleBackground Background color for Title.\r
+ @param Title Title above progress bar.\r
+ @param ProgressColor Progress bar color.\r
+ @param Progress Progress (0-100)\r
+ @param PreviousValue The previous value of the progress.\r
+\r
+ @retval EFI_STATUS Success update the progress bar\r
+\r
+**/\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ IN CHAR16 *Title,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ IN UINTN Progress,\r
+ IN UINTN PreviousValue\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ UINT32 SizeOfX;\r
+ UINT32 SizeOfY;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINTN BlockHeight;\r
+ UINTN BlockWidth;\r
+ UINTN BlockNum;\r
+ UINTN PosX;\r
+ UINTN PosY;\r
+ UINTN Index;\r
+\r
+ if (Progress > 100) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UgaDraw = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID **) &GraphicsOutput\r
+ );\r
+ if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ GraphicsOutput = NULL;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ (VOID **) &UgaDraw\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SizeOfX = 0;\r
+ SizeOfY = 0;\r
+ if (GraphicsOutput != NULL) {\r
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+ } else if (UgaDraw != NULL) {\r
+ Status = UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &SizeOfX,\r
+ &SizeOfY,\r
+ &ColorDepth,\r
+ &RefreshRate\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ BlockWidth = SizeOfX / 100;\r
+ BlockHeight = SizeOfY / 50;\r
+\r
+ BlockNum = Progress;\r
+\r
+ PosX = 0;\r
+ PosY = SizeOfY * 48 / 50;\r
+\r
+ if (BlockNum == 0) {\r
+ //\r
+ // Clear progress area\r
+ //\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &Color,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - EFI_GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &Color,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - EFI_GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ //\r
+ // Show progress by drawing blocks\r
+ //\r
+ for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+ PosX = Index * BlockWidth;\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &ProgressColor,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &ProgressColor,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ PrintXY (\r
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
+ PosY - EFI_GLYPH_HEIGHT - 1,\r
+ &TitleForeground,\r
+ &TitleBackground,\r
+ Title\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+ Perform the memory test base on the memory test intensive level,\r
+ and update the memory resource.\r
+\r
+\r
+ @param Level The memory test intensive level.\r
+\r
+ @retval EFI_STATUS Success test all the system memory and update\r
+ the memory resource\r
+\r
+**/\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+ IN EXTENDMEM_COVERAGE_LEVEL Level\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS KeyStatus;\r
+ EFI_STATUS InitStatus;\r
+ EFI_STATUS ReturnStatus;\r
+ BOOLEAN RequireSoftECCInit;\r
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
+ UINT64 TestedMemorySize;\r
+ UINT64 TotalMemorySize;\r
+ UINTN TestPercent;\r
+ UINT64 PreviousValue;\r
+ BOOLEAN ErrorOut;\r
+ BOOLEAN TestAbort;\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 StrPercent[16];\r
+ CHAR16 *StrTotalMemory;\r
+ CHAR16 *Pos;\r
+ CHAR16 *TmpStr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINT8 Value;\r
+ UINTN DataSize;\r
+ UINT32 Attributes;\r
+ UINT32 TempData;\r
+\r
+ ReturnStatus = EFI_SUCCESS;\r
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ Pos = AllocatePool (128);\r
+\r
+ if (Pos == NULL) {\r
+ return ReturnStatus;\r
+ }\r
+\r
+ StrTotalMemory = Pos;\r
+\r
+ TestedMemorySize = 0;\r
+ TotalMemorySize = 0;\r
+ PreviousValue = 0;\r
+ ErrorOut = FALSE;\r
+ TestAbort = FALSE;\r
+\r
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+ RequireSoftECCInit = FALSE;\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGenericMemTestProtocolGuid,\r
+ NULL,\r
+ (VOID **) &GenMemoryTest\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Pos);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ InitStatus = GenMemoryTest->MemoryTestInit (\r
+ GenMemoryTest,\r
+ Level,\r
+ &RequireSoftECCInit\r
+ );\r
+ if (InitStatus == EFI_NO_MEDIA) {\r
+ //\r
+ // The PEI codes also have the relevant memory test code to check the memory,\r
+ // it can select to test some range of the memory or all of them. If PEI code\r
+ // checks all the memory, this BDS memory test will has no not-test memory to\r
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
+ // "MemoryTestInit". So it does not need to test memory again, just return.\r
+ //\r
+ FreePool (Pos);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
+\r
+ if (TmpStr != NULL) {\r
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ do {\r
+ Status = GenMemoryTest->PerformMemoryTest (\r
+ GenMemoryTest,\r
+ &TestedMemorySize,\r
+ &TotalMemorySize,\r
+ &ErrorOut,\r
+ TestAbort\r
+ );\r
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
+ if (TmpStr != NULL) {\r
+ PrintXY (10, 10, NULL, NULL, TmpStr);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ ASSERT (0);\r
+ }\r
+\r
+ TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
+ TestPercent = (UINTN) DivU64x32 (\r
+ DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
+ TempData\r
+ );\r
+ if (TestPercent != PreviousValue) {\r
+ UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
+ if (TmpStr != NULL) {\r
+ BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ TestPercent,\r
+ (UINTN) PreviousValue\r
+ );\r
+ FreePool (TmpStr);\r
+ }\r
+ }\r
+\r
+ PreviousValue = TestPercent;\r
+\r
+ KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {\r
+ if (!RequireSoftECCInit) {\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ 100,\r
+ (UINTN) PreviousValue\r
+ );\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+ gST->ConOut->OutputString (gST->ConOut, L"100");\r
+ Status = GenMemoryTest->Finished (GenMemoryTest);\r
+ goto Done;\r
+ }\r
+\r
+ TestAbort = TRUE;\r
+ }\r
+ } while (Status != EFI_NOT_FOUND);\r
+\r
+ Status = GenMemoryTest->Finished (GenMemoryTest);\r
+\r
+Done:\r
+ UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
+ if (StrTotalMemory[0] == L',') {\r
+ StrTotalMemory++;\r
+ }\r
+\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
+ if (TmpStr != NULL) {\r
+ StrCat (StrTotalMemory, TmpStr);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+ gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ StrTotalMemory,\r
+ Color,\r
+ 100,\r
+ (UINTN) PreviousValue\r
+ );\r
+\r
+ FreePool (Pos);\r
+\r
+ DataSize = sizeof (Value);\r
+ Status = gRT->GetVariable (\r
+ L"BootState",\r
+ &gEfiBootStateGuid,\r
+ &Attributes,\r
+ &DataSize,\r
+ &Value\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Value = 1;\r
+ gRT->SetVariable (\r
+ L"BootState",\r
+ &gEfiBootStateGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (Value),\r
+ &Value\r
+ );\r
+ }\r
+\r
+ return ReturnStatus;\r
+}\r
--- /dev/null
+/** @file\r
+ String support\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_HII_HANDLE gStringPackHandle;\r
+\r
+EFI_GUID mBdsStringPackGuid = {\r
+ 0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a}\r
+};\r
+\r
+/**\r
+ Initialize HII global accessor for string support\r
+\r
+ @retval EFI_SUCCESS String support initialize success.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ PackageList = HiiLibPreparePackageList (1, &mBdsStringPackGuid, &BdsDxeStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ DriverHandle,\r
+ &gStringPackHandle\r
+ );\r
+\r
+ FreePool (PackageList);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get string by string id from HII Interface\r
+\r
+\r
+ @param Id String ID.\r
+\r
+ @retval CHAR16 * String from ID.\r
+ @retval NULL If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+GetStringById (\r
+ IN EFI_STRING_ID Id\r
+ )\r
+{\r
+ CHAR16 *String;\r
+\r
+ String = NULL;\r
+ HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);\r
+\r
+ return String;\r
+}\r
--- /dev/null
+/** @file\r
+ String support\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _STRING_H_\r
+#define _STRING_H_\r
+\r
+#include "Bds.h"\r
+\r
+extern EFI_HII_HANDLE gStringPackHandle;\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+\r
+extern UINT8 BdsDxeStrings[];\r
+\r
+//\r
+// String Definition Guid for BDS Platform\r
+//\r
+#define EFI_BDS_PLATFORM_GUID \\r
+ { \\r
+ 0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \\r
+ }\r
+\r
+/**\r
+ Get string by string id from HII Interface\r
+\r
+\r
+ @param Id String ID.\r
+\r
+ @retval CHAR16 * String from ID.\r
+ @retval NULL If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+GetStringById (\r
+ IN EFI_STRING_ID Id\r
+ );\r
+\r
+/**\r
+ Initialize HII global accessor for string support\r
+\r
+ @retval EFI_SUCCESS String support initialize success.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Call the browser and display the front page\r
+\r
+ @return Status code that will be returned by\r
+ EFI_FORM_BROWSER2_PROTOCOL.SendForm ().\r
+\r
+**/\r
+EFI_STATUS\r
+CallFrontPage (\r
+ VOID\r
+ );\r
+\r
+#endif // _STRING_H_\r