/** @file\r
BDS Lib functions which relate with create or process the boot option.\r
\r
-Copyright (c) 2004 - 2009, Intel Corporation. <BR>\r
+Copyright (c) 2004 - 2010, 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
**/\r
\r
#include "InternalBdsLib.h"\r
+#include "String.h"\r
\r
BOOLEAN mEnumBootDevice = FALSE;\r
+EFI_HII_HANDLE gBdsLibStringPackHandle = NULL;\r
\r
///\r
/// This GUID is used for an EFI Variable that stores the front device pathes\r
///\r
EFI_GUID mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };\r
\r
+///\r
+/// This GUID is used for register UNI string.\r
+///\r
+EFI_GUID mBdsLibStringPackGuid = { 0x3b4d9b23, 0x95ac, 0x44f6, { 0x9f, 0xcd, 0xe, 0x95, 0x94, 0x58, 0x6c, 0x72 } };\r
+\r
+///\r
+/// This GUID is used for Set/Get platform language into/from variable at last time enumeration to ensure the enumeration will\r
+/// only execute once.\r
+///\r
+EFI_GUID mBdsLibLastLangGuid = { 0xe8c545b, 0xa2ee, 0x470d, { 0x8e, 0x26, 0xbd, 0xa1, 0xa1, 0x3c, 0xa, 0xa3 } };\r
+\r
+/**\r
+ The constructor function register UNI strings into imageHandle.\r
+ \r
+ It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. \r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+ \r
+ @retval EFI_SUCCESS The constructor successfully added string package.\r
+ @retval Other value The constructor can't add string package.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenericBdsLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+\r
+ gBdsLibStringPackHandle = HiiAddPackages (\r
+ &mBdsLibStringPackGuid,\r
+ &ImageHandle,\r
+ GenericBdsLibStrings,\r
+ NULL\r
+ );\r
+\r
+ ASSERT (gBdsLibStringPackHandle != NULL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
\r
\r
/**\r
EFI_DEVICE_PATH_PROTOCOL *WorkingDevicePath;\r
EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;\r
LIST_ENTRY TempBootLists;\r
- EFI_SECURITY_ARCH_PROTOCOL *SecurityProtocol;\r
\r
//\r
// Record the performance data for End of BDS\r
DevicePath = Option->DevicePath;\r
}\r
\r
- //\r
- // Measure GPT Table by SAP protocol.\r
- //\r
- Status = gBS->LocateProtocol (\r
- &gEfiSecurityArchProtocolGuid,\r
- NULL,\r
- (VOID**) &SecurityProtocol\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = SecurityProtocol->FileAuthenticationState (SecurityProtocol, 0, DevicePath);\r
- }\r
-\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
+ DEBUG_CODE_BEGIN();\r
\r
+ if (Option->Description == NULL) {\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting from unknown device path\n"));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
+ }\r
+ \r
+ DEBUG_CODE_END();\r
+ \r
Status = gBS->LoadImage (\r
TRUE,\r
mBdsImageHandle,\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
+ // If we didn't find an image directly, we need to try as if it is a removable device boot option\r
// and load the image according to the default boot behavior for removable device.\r
//\r
if (EFI_ERROR (Status)) {\r
\r
TempNewDevicePath = CachedDevicePath;\r
CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
- FreePool(TempNewDevicePath);\r
+ if (TempNewDevicePath != NULL) {\r
+ FreePool(TempNewDevicePath);\r
+ }\r
} else {\r
TempNewDevicePath = CachedDevicePath;\r
CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
}\r
}\r
\r
- FreePool (CachedDevicePath);\r
+ if (CachedDevicePath != NULL) {\r
+ FreePool (CachedDevicePath);\r
+ }\r
if (BlockIoBuffer != NULL) {\r
FreePool (BlockIoBuffer);\r
}\r
EFI_HANDLE *BlockIoHandles;\r
EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
UINTN Index;\r
- UINTN NumberSimpleNetworkHandles;\r
- EFI_HANDLE *SimpleNetworkHandles;\r
+ UINTN NumOfLoadFileHandles;\r
+ EFI_HANDLE *LoadFileHandles;\r
UINTN FvHandleCount;\r
EFI_HANDLE *FvHandleBuffer;\r
EFI_FV_FILETYPE Type;\r
UINTN NumberFileSystemHandles;\r
BOOLEAN NeedDelete;\r
EFI_IMAGE_DOS_HEADER DosHeader;\r
+ CHAR8 *PlatLang;\r
+ CHAR8 *LastLang;\r
EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
\r
UsbNumber = 0;\r
MiscNumber = 0;\r
ScsiNumber = 0;\r
+ PlatLang = NULL;\r
+ LastLang = NULL;\r
ZeroMem (Buffer, sizeof (Buffer));\r
\r
//\r
// device from the boot order variable\r
//\r
if (mEnumBootDevice) {\r
- Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
- return Status;\r
+ LastLang = GetVariable (L"LastEnumLang", &mBdsLibLastLangGuid);\r
+ PlatLang = GetEfiGlobalVariable (L"PlatformLang");\r
+ if (LastLang == PlatLang) {\r
+ Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+ return Status;\r
+ } else {\r
+ Status = gRT->SetVariable (\r
+ L"LastEnumLang",\r
+ &mBdsLibLastLangGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (PlatLang),\r
+ PlatLang\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
}\r
\r
//\r
\r
switch (DevicePathType) {\r
case BDS_EFI_ACPI_FLOPPY_BOOT:\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", FloppyNumber);\r
+ if (FloppyNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)));\r
+ }\r
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
FloppyNumber++;\r
break;\r
//\r
case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
case BDS_EFI_MESSAGE_SATA_BOOT:\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", CdromNumber);\r
+ if (CdromNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)));\r
+ }\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer));\r
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
CdromNumber++;\r
break;\r
\r
case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", UsbNumber);\r
+ if (UsbNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)));\r
+ }\r
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
UsbNumber++;\r
break;\r
\r
case BDS_EFI_MESSAGE_SCSI_BOOT:\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", ScsiNumber);\r
+ if (ScsiNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)));\r
+ }\r
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
ScsiNumber++;\r
break;\r
\r
case BDS_EFI_MESSAGE_MISC_BOOT:\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", MiscNumber);\r
+ if (MiscNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)));\r
+ }\r
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
MiscNumber++;\r
break;\r
//\r
BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
} else {\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);\r
+ if (NonBlockNumber != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)));\r
+ }\r
BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);\r
NonBlockNumber++;\r
}\r
//\r
// Parse Network Boot Device\r
//\r
+ NumOfLoadFileHandles = 0;\r
+ //\r
+ // Search Load File protocol for PXE boot option.\r
+ //\r
gBS->LocateHandleBuffer (\r
ByProtocol,\r
- &gEfiSimpleNetworkProtocolGuid,\r
+ &gEfiLoadFileProtocolGuid,\r
NULL,\r
- &NumberSimpleNetworkHandles,\r
- &SimpleNetworkHandles\r
+ &NumOfLoadFileHandles,\r
+ &LoadFileHandles\r
);\r
\r
- for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {\r
- UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", Index);\r
- BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);\r
+ for (Index = 0; Index < NumOfLoadFileHandles; Index++) {\r
+ if (Index != 0) {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)), Index);\r
+ } else {\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)));\r
+ }\r
+ BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer);\r
}\r
\r
- if (NumberSimpleNetworkHandles != 0) {\r
- FreePool (SimpleNetworkHandles);\r
+ if (NumOfLoadFileHandles != 0) {\r
+ FreePool (LoadFileHandles);\r
}\r
\r
//\r
EFI_HANDLE Handle;\r
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
BOOLEAN MediaPresent;\r
+ UINT32 InterruptStatus;\r
\r
MediaPresent = FALSE;\r
\r
UpdatedDevicePath = DevicePath;\r
- Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ //\r
+ // Locate Load File Protocol for PXE boot option first\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
if (EFI_ERROR (Status)) {\r
//\r
// Device not present so see if we need to connect it\r
//\r
// This one should work after we did the connect\r
//\r
- Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
}\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Failed to open SNP from this handle, try to get SNP from parent handle\r
+ //\r
+ UpdatedDevicePath = DevicePathFromHandle (Handle);\r
+ if (UpdatedDevicePath != NULL) {\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // SNP handle found, get SNP from it\r
+ //\r
+ Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **) &Snp);\r
+ }\r
+ }\r
+ }\r
+\r
if (!EFI_ERROR (Status)) {\r
if (Snp->Mode->MediaPresentSupported) {\r
if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
+ //\r
+ // Invoke Snp->GetStatus() to refresh the media status\r
+ //\r
+ Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
+\r
//\r
// In case some one else is using the SNP check to see if it's connected\r
//\r
ACPI_HID_DEVICE_PATH *Acpi;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
-\r
+ UINT32 BootType;\r
\r
if (NULL == DevicePath) {\r
return BDS_EFI_UNSUPPORT;\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
+ // skip it\r
//\r
LastDeviceNode = NextDevicePathNode (LastDeviceNode);\r
}\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
- } else if (DevicePathSubType(TempDevicePath) == MSG_SATA_DP) {\r
- return BDS_EFI_MESSAGE_SATA_BOOT;\r
- } else if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {\r
- return BDS_EFI_MESSAGE_MAC_BOOT;\r
+ switch (DevicePathSubType (TempDevicePath)) {\r
+ case MSG_ATAPI_DP:\r
+ BootType = BDS_EFI_MESSAGE_ATAPI_BOOT;\r
+ break;\r
+\r
+ case MSG_USB_DP:\r
+ BootType = BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
+ break;\r
+\r
+ case MSG_SCSI_DP:\r
+ BootType = BDS_EFI_MESSAGE_SCSI_BOOT;\r
+ break;\r
+\r
+ case MSG_SATA_DP:\r
+ BootType = BDS_EFI_MESSAGE_SATA_BOOT;\r
+ break;\r
+\r
+ case MSG_MAC_ADDR_DP:\r
+ case MSG_VLAN_DP:\r
+ case MSG_IPv4_DP:\r
+ case MSG_IPv6_DP:\r
+ BootType = BDS_EFI_MESSAGE_MAC_BOOT;\r
+ break;\r
+\r
+ default:\r
+ BootType = BDS_EFI_MESSAGE_MISC_BOOT;\r
+ break;\r
}\r
- return BDS_EFI_MESSAGE_MISC_BOOT;\r
+ return BootType;\r
+\r
default:\r
break;\r
}\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
+ // Check if it's a valid boot option for network boot device.\r
+ // Check if there is EfiLoadFileProtocol installed. \r
+ // If yes, that means there is a boot option for network.\r
//\r
Status = gBS->LocateDevicePath (\r
- &gEfiSimpleNetworkProtocolGuid,\r
+ &gEfiLoadFileProtocolGuid,\r
&TempDevicePath,\r
&Handle\r
);\r
TempDevicePath = DevPath;\r
BdsLibConnectDevicePath (TempDevicePath);\r
Status = gBS->LocateDevicePath (\r
- &gEfiSimpleNetworkProtocolGuid,\r
+ &gEfiLoadFileProtocolGuid,\r
&TempDevicePath,\r
&Handle\r
);\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
+ if (!IsDevicePathEnd (TempDevicePath)) {\r
+ //\r
+ // LoadFile protocol is not installed on handle with exactly the same DevPath\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
if (CheckMedia) {\r
//\r
// Test if it is ready to boot now\r
}\r
} else {\r
return TRUE;\r
- }\r
+ } \r
}\r
\r
//\r