Modify the feature of BMC set boot option as switching generic BDS. Break BMC SetBoot option out into BmcConfigBootLib.
Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ming Huang huangming23@huawei.com Signed-off-by: Heyi Guo heyi.guo@linaro.org Reviewed-by: Leif Lindholm leif.lindholm@linaro.org Reviewed-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- Platform/Hisilicon/D03/D03.dsc | 1 + Platform/Hisilicon/D05/D05.dsc | 1 + Silicon/Hisilicon/HisiPkg.dec | 1 + Silicon/Hisilicon/Include/Library/BmcConfigBootLib.h | 31 ++ Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.c | 466 ++++++++++++++++++++ Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.inf | 51 +++ Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c | 7 + Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 1 + 8 files changed, 559 insertions(+)
diff --git a/Platform/Hisilicon/D03/D03.dsc b/Platform/Hisilicon/D03/D03.dsc index 5fbe1f9..e1e3b14 100644 --- a/Platform/Hisilicon/D03/D03.dsc +++ b/Platform/Hisilicon/D03/D03.dsc @@ -68,6 +68,7 @@ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf PlatformBdsLib|Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf + BmcConfigBootLib|Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.inf UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf diff --git a/Platform/Hisilicon/D05/D05.dsc b/Platform/Hisilicon/D05/D05.dsc index 4d630da..ac7da04 100644 --- a/Platform/Hisilicon/D05/D05.dsc +++ b/Platform/Hisilicon/D05/D05.dsc @@ -84,6 +84,7 @@ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf PlatformBdsLib|Silicon/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf + BmcConfigBootLib|Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.inf UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf diff --git a/Silicon/Hisilicon/HisiPkg.dec b/Silicon/Hisilicon/HisiPkg.dec index 398d0a7..889a181 100644 --- a/Silicon/Hisilicon/HisiPkg.dec +++ b/Silicon/Hisilicon/HisiPkg.dec @@ -43,6 +43,7 @@
gHisiEfiMemoryMapGuid = {0xf8870015, 0x6994, 0x4b98, {0x95, 0xa2, 0xbd, 0x56, 0xda, 0x91, 0xc0, 0x7f}} gVersionInfoHobGuid = {0xe13a14c, 0x859c, 0x4f22, {0x82, 0xbd, 0x18, 0xe, 0xe1, 0x42, 0x12, 0xbf}} + gOemBootVariableGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99, 0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8}}
[LibraryClasses] PlatformSysCtrlLib|Include/Library/PlatformSysCtrlLib.h diff --git a/Silicon/Hisilicon/Include/Library/BmcConfigBootLib.h b/Silicon/Hisilicon/Include/Library/BmcConfigBootLib.h new file mode 100644 index 0000000..d937234 --- /dev/null +++ b/Silicon/Hisilicon/Include/Library/BmcConfigBootLib.h @@ -0,0 +1,31 @@ +/** @file +* +* Copyright (c) 2017, Hisilicon Limited. All rights reserved. +* Copyright (c) 2017, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef _BMC_CONFIG_BOOT_LIB_H_ +#define _BMC_CONFIG_BOOT_LIB_H_ + +VOID +EFIAPI +RestoreBootOrder ( + VOID + ); + +VOID +EFIAPI +HandleBmcBootType ( + VOID + ); + +#endif diff --git a/Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.c b/Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.c new file mode 100644 index 0000000..08a9c9c --- /dev/null +++ b/Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.c @@ -0,0 +1,466 @@ +/** @file +* +* Copyright (c) 2017, Hisilicon Limited. All rights reserved. +* Copyright (c) 2017, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/IpmiCmdLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Library/UefiBootManagerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Guid/GlobalVariable.h> +#include <Protocol/DevicePathToText.h> + + +STATIC +UINT16 +EFIAPI +GetBBSTypeFromFileSysPath ( + IN CHAR16 *UsbPathTxt, + IN CHAR16 *FileSysPathTxt, + IN EFI_DEVICE_PATH_PROTOCOL *FileSysPath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + + if (StrnCmp (UsbPathTxt, FileSysPathTxt, StrLen (UsbPathTxt)) == 0) { + Node = FileSysPath; + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (Node) == MEDIA_CDROM_DP)) { + return BBS_TYPE_CDROM; + } + Node = NextDevicePathNode (Node); + } + } + + return BBS_TYPE_UNKNOWN; +} + +STATIC +UINT16 +EFIAPI +GetBBSTypeFromUsbPath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *UsbPath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *FileSystemHandles; + UINTN NumberFileSystemHandles; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *FileSysPath; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + CHAR16 *UsbPathTxt; + CHAR16 *FileSysPathTxt; + UINT16 Result; + + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevPathToText); + ASSERT_EFI_ERROR(Status); + + Result = BBS_TYPE_UNKNOWN; + UsbPathTxt = DevPathToText->ConvertDevicePathToText (UsbPath, TRUE, TRUE); + if (UsbPathTxt == NULL) { + return Result; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberFileSystemHandles, + &FileSystemHandles + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Locate SimpleFileSystemProtocol error(%r)\n", Status)); + FreePool (UsbPathTxt); + return BBS_TYPE_UNKNOWN; + } + + for (Index = 0; Index < NumberFileSystemHandles; Index++) { + FileSysPath = DevicePathFromHandle (FileSystemHandles[Index]); + FileSysPathTxt = DevPathToText->ConvertDevicePathToText (FileSysPath, TRUE, TRUE); + + if (FileSysPathTxt == NULL) { + continue; + } + + Result = GetBBSTypeFromFileSysPath (UsbPathTxt, FileSysPathTxt, FileSysPath); + FreePool (FileSysPathTxt); + + if (Result != BBS_TYPE_UNKNOWN) { + break; + } + } + + if (NumberFileSystemHandles != 0) { + FreePool (FileSystemHandles); + } + + FreePool (UsbPathTxt); + + return Result; +} + +STATIC +UINT16 +EFIAPI +GetBBSTypeFromMessagingDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *Node + ) +{ + VENDOR_DEVICE_PATH *Vendor; + UINT16 Result; + + Result = BBS_TYPE_UNKNOWN; + + switch (DevicePathSubType (Node)) { + case MSG_MAC_ADDR_DP: + Result = BBS_TYPE_EMBEDDED_NETWORK; + break; + + case MSG_USB_DP: + Result = GetBBSTypeFromUsbPath (DevicePath); + if (Result == BBS_TYPE_UNKNOWN) { + Result = BBS_TYPE_USB; + } + break; + + case MSG_SATA_DP: + Result = BBS_TYPE_HARDDRIVE; + break; + + case MSG_VENDOR_DP: + Vendor = (VENDOR_DEVICE_PATH *) (Node); + if (&Vendor->Guid != NULL) { + if (CompareGuid (&Vendor->Guid, &((EFI_GUID) DEVICE_PATH_MESSAGING_SAS))) { + Result = BBS_TYPE_HARDDRIVE; + } + } + break; + + default: + Result = BBS_TYPE_UNKNOWN; + break; + } + + return Result; +} + +STATIC +UINT16 +EFIAPI +GetBBSTypeByDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + UINT16 Result; + + Result = BBS_TYPE_UNKNOWN; + if (DevicePath == NULL) { + return Result; + } + + Node = DevicePath; + while (!IsDevicePathEnd (Node)) { + switch (DevicePathType (Node)) { + case MEDIA_DEVICE_PATH: + if (DevicePathSubType (Node) == MEDIA_CDROM_DP) { + Result = BBS_TYPE_CDROM; + } + break; + + case MESSAGING_DEVICE_PATH: + Result = GetBBSTypeFromMessagingDevicePath (DevicePath, Node); + break; + + default: + Result = BBS_TYPE_UNKNOWN; + break; + } + + if (Result != BBS_TYPE_UNKNOWN) { + break; + } + + Node = NextDevicePathNode (Node); + } + + return Result; +} + +STATIC +EFI_STATUS +EFIAPI +GetBmcBootOptionsSetting ( + OUT IPMI_GET_BOOT_OPTION *BmcBootOpt + ) +{ + EFI_STATUS Status; + + Status = IpmiCmdGetSysBootOptions (BmcBootOpt); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Get iBMC BootOpts %r!\n", Status)); + return Status; + } + + if (BmcBootOpt->BootFlagsValid != BOOT_OPTION_BOOT_FLAG_VALID) { + return EFI_NOT_FOUND; + } + + if (BmcBootOpt->Persistent) { + BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_VALID; + } else { + BmcBootOpt->BootFlagsValid = BOOT_OPTION_BOOT_FLAG_INVALID; + } + + Status = IpmiCmdSetSysBootOptions (BmcBootOpt); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Set iBMC BootOpts %r!\n", Status)); + } + + return Status; +} + +VOID +EFIAPI +RestoreBootOrder ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 *BootOrder; + UINTN BootOrderSize; + + GetVariable2 ( + L"BootOrderBackup", + &gOemBootVariableGuid, + (VOID **) &BootOrder, + &BootOrderSize + ); + if (BootOrder == NULL) { + return ; + } + + Print (L"\nRestore BootOrder(%d).\n", BootOrderSize / sizeof (UINT16)); + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SetVariable BootOrder %r!\n", Status)); + } + + Status = gRT->SetVariable ( + L"BootOrderBackup", + &gOemBootVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status)); + } + + FreePool (BootOrder); +} + + +STATIC +VOID +EFIAPI +RestoreBootOrderOnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // restore BootOrder variable in normal condition. + RestoreBootOrder (); +} + +STATIC +VOID +EFIAPI +UpdateBootOrder ( + IN UINT16 *NewOrder, + IN UINT16 *BootOrder, + IN UINTN BootOrderSize + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gRT->SetVariable ( + L"BootOrderBackup", + &gOemBootVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Set BootOrderBackup Variable:%r!\n", Status)); + return; + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + NewOrder + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Set BootOrder Variable:%r!\n", Status)); + return; + } + + // Register notify function to restore BootOrder variable on ReadyToBoot Event. + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RestoreBootOrderOnReadyToBoot, + NULL, + &gEfiEventReadyToBootGuid, + &Event + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Create ready to boot event %r!\n", Status)); + } +} + +STATIC +VOID +EFIAPI +SetBootOrder ( + IN UINT16 BootType + ) +{ + EFI_STATUS Status; + UINT16 *NewOrder; + UINT16 *RemainBoots; + UINT16 *BootOrder; + UINTN BootOrderSize; + EFI_BOOT_MANAGER_LOAD_OPTION Option; + CHAR16 OptionName[sizeof ("Boot####")]; + UINTN Index; + UINTN SelectCnt; + UINTN RemainCnt; + + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSize); + if (BootOrder == NULL) { + return ; + } + + NewOrder = AllocatePool (BootOrderSize); + RemainBoots = AllocatePool (BootOrderSize); + if ((NewOrder == NULL) || (RemainBoots == NULL)) { + DEBUG ((DEBUG_ERROR, "Out of resources.")); + goto Exit; + } + + SelectCnt = 0; + RemainCnt = 0; + + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder[Index]); + Status = EfiBootManagerVariableToLoadOption (OptionName, &Option); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index])); + continue; + } + + if (GetBBSTypeByDevicePath (Option.FilePath) == BootType) { + NewOrder[SelectCnt++] = BootOrder[Index]; + } else { + RemainBoots[RemainCnt++] = BootOrder[Index]; + } + } + + if (SelectCnt != 0) { + // append RemainBoots to NewOrder + for (Index = 0; Index < RemainCnt; Index++) { + NewOrder[SelectCnt + Index] = RemainBoots[Index]; + } + + if (CompareMem (NewOrder, BootOrder, BootOrderSize) != 0) { + UpdateBootOrder (NewOrder, BootOrder, BootOrderSize); + } + } + +Exit: + FreePool (BootOrder); + if (NewOrder != NULL) { + FreePool (NewOrder); + } + if (RemainBoots != NULL) { + FreePool (RemainBoots); + } +} + +VOID +EFIAPI +HandleBmcBootType ( + VOID + ) +{ + EFI_STATUS Status; + IPMI_GET_BOOT_OPTION BmcBootOpt; + UINT16 BootType; + + Status = GetBmcBootOptionsSetting (&BmcBootOpt); + if (EFI_ERROR (Status)) { + return; + } + + Print (L"Boot Type from BMC is %x\n", BmcBootOpt.BootDeviceSelector); + + switch (BmcBootOpt.BootDeviceSelector) { + case ForcePxe: + BootType = BBS_TYPE_EMBEDDED_NETWORK; + break; + + case ForcePrimaryRemovableMedia: + BootType = BBS_TYPE_USB; + break; + + case ForceDefaultHardDisk: + BootType = BBS_TYPE_HARDDRIVE; + break; + + case ForceDefaultCD: + BootType = BBS_TYPE_CDROM; + break; + + default: + return; + } + + SetBootOrder (BootType); +} + diff --git a/Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.inf b/Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.inf new file mode 100644 index 0000000..b603523 --- /dev/null +++ b/Silicon/Hisilicon/Library/BmcConfigBootLib/BmcConfigBootLib.inf @@ -0,0 +1,51 @@ +#/** @file +# +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2015, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = BmcConfigBootLib + FILE_GUID = f174d192-7208-46c1-b9d1-65b2db06ad3b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BmcConfigBootLib + +[Sources.common] + BmcConfigBootLib.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + IpmiCmdLib + PcdLib + PrintLib + UefiBootManagerLib + +[Guids] + gEfiEventReadyToBootGuid + gOemBootVariableGuid + +[Protocols] + gEfiDevicePathToTextProtocolGuid ## CONSUMES + gEfiSimpleFileSystemProtocolGuid ## CONSUMES + +[Depex] + gEfiDevicePathToTextProtocolGuid diff --git a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c index 15df3ba..7dd5ba6 100644 --- a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c +++ b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c @@ -17,6 +17,7 @@
#include <IndustryStandard/Pci22.h> #include <Library/BootLogoLib.h> +#include <Library/BmcConfigBootLib.h> #include <Library/DevicePathLib.h> #include <Library/PcdLib.h> #include <Library/UefiBootManagerLib.h> @@ -502,6 +503,10 @@ PlatformBootManagerBeforeConsole ( Status = EsrtManagement->SyncEsrtFmp (); }
+ // restore BootOrder variable if previous BMC boot override attempt + // left it in a modified state + RestoreBootOrder (); + UpdateMemory ();
// @@ -601,6 +606,8 @@ PlatformBootManagerAfterConsole ( PlatformRegisterFvBootOption ( PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE ); + + HandleBmcBootType (); }
/** diff --git a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index 27ef64b..7a53bef 100644 --- a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -42,6 +42,7 @@ BaseLib BaseMemoryLib BootLogoLib + BmcConfigBootLib DebugLib DevicePathLib DxeServicesLib