Message ID | 1495162486-34455-1-git-send-email-chenhui.sun@linaro.org |
---|---|
State | New |
Headers | show |
On Fri, May 19, 2017 at 10:54:46AM +0800, Chenhui Sun wrote: > From: Chenhui Sun <chenhui.sun@linaro.com> > > Support the feature that BIOS get boot option from BMC and > put it in the first boot order. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: huangming <huangming23@huawei.com> > Signed-off-by: Heyi Guo <guoheyi@huawei.com> > Signed-off-by: Yi Li <Phoenix.liyi@huawei.com> > Signed-off-by: Chenhui Sun <sunchenhui@huawei.com> Thanks, this one looks good. Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org> > --- > Chips/Hisilicon/Include/Library/IpmiCmdLib.h | 94 +++++ > .../Library/PlatformIntelBdsLib/IntelBdsPlatform.c | 437 +++++++++++++++++++++ > .../PlatformIntelBdsLib/PlatformIntelBdsLib.inf | 4 + > 3 files changed, 535 insertions(+) > create mode 100644 Chips/Hisilicon/Include/Library/IpmiCmdLib.h > > diff --git a/Chips/Hisilicon/Include/Library/IpmiCmdLib.h b/Chips/Hisilicon/Include/Library/IpmiCmdLib.h > new file mode 100644 > index 0000000..8868b76 > --- /dev/null > +++ b/Chips/Hisilicon/Include/Library/IpmiCmdLib.h > @@ -0,0 +1,94 @@ > +/** @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 _IPMI_CMD_LIB_H_ > +#define _IPMI_CMD_LIB_H_ > + > +#define BOOT_OPTION_BOOT_FLAG_VALID 1 > +#define BOOT_OPTION_BOOT_FLAG_INVALID 0 > + > +typedef enum { > + NoOverride = 0x0, > + ForcePxe, > + ForceDefaultHardDisk, > + ForceDefaultHardDiskSafeMode, > + ForceDefaultDiagnosticPartition, > + ForceDefaultCD, > + ForceSetupUtility, > + ForceRemoteRemovableMedia, > + ForceRemoteCD, > + ForcePrimaryRemoteMedia, > + ForceRemoteHardDisk = 0xB, > + ForcePrimaryRemovableMedia = 0xF > +} BOOT_DEVICE_SELECTOR; > + > +// > +// Get System Boot Option data structure > +// > +typedef struct { > + UINT8 ParameterVersion :4; > + UINT8 Reserved1 :4; > + UINT8 ParameterSelector :7; > + UINT8 ParameterValid :1; > + // > + // Boot Flags Data 1 > + // > + UINT8 Reserved2 :5; > + UINT8 BiosBootType :1; > + UINT8 Persistent :1; > + UINT8 BootFlagsValid :1; > + // > + // Boot Flags Data 2 > + // > + UINT8 LockResetBtn :1; > + UINT8 ScreenBlank :1; > + UINT8 BootDeviceSelector :4; > + UINT8 LockKeyboard :1; > + UINT8 ClearCmos :1; > + // > + // Boot Flags Data 3 > + // > + UINT8 ConsoleRedirectionControl :2; > + UINT8 LockSleepBtn :1; > + UINT8 UserPasswordByPass :1; > + UINT8 Reserved3 :1; > + UINT8 FirmwareVerbosity :2; > + UINT8 LockPowerBtn :1; > + // > + // Boot Flags Data 4 > + // > + UINT8 MuxControlOverride :3; > + UINT8 ShareModeOverride :1; > + UINT8 Reserved4 :4; > + // > + // Boot Flags Data 5 > + // > + UINT8 DeviceInstanceSelector :5; > + UINT8 Reserved5 :3; > +} IPMI_GET_BOOT_OPTION; > + > +EFI_STATUS > +EFIAPI > +IpmiCmdSetSysBootOptions ( > + OUT IPMI_GET_BOOT_OPTION *BootOption > + ); > + > +EFI_STATUS > +EFIAPI > +IpmiCmdGetSysBootOptions ( > + IN IPMI_GET_BOOT_OPTION *BootOption > + ); > + > +#endif > diff --git a/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c b/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c > index efefeb6..dc23e46 100644 > --- a/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c > +++ b/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c > @@ -21,16 +21,23 @@ > > #include <IndustryStandard/Pci22.h> > #include <Library/DevicePathLib.h> > +#include <Library/GenericBdsLib.h> > +#include <Library/IpmiCmdLib.h> > #include <Library/PcdLib.h> > #include <Library/PlatformBdsLib.h> > +#include <Library/PrintLib.h> > #include <Library/UefiLib.h> > #include <Protocol/DevicePath.h> > +#include <Protocol/DevicePathToText.h> > #include <Protocol/GraphicsOutput.h> > #include <Protocol/PciIo.h> > #include <Protocol/PciRootBridgeIo.h> > +#include <Guid/GlobalVariable.h> > > #include "IntelBdsPlatform.h" > > +GUID gOemBootVaraibleGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99, > + 0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8} }; > > //3CEF354A-3B7A-4519-AD70-72A134698311 > GUID gEblFileGuid = {0x3CEF354A, 0x3B7A, 0x4519, {0xAD, 0x70, > @@ -142,6 +149,431 @@ STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { > } > }; > > +STATIC > +UINT16 > +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 > +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); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Locate DevicePathToTextPro %r\n", Status)); > + return BBS_TYPE_UNKNOWN; > + } > + > + 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 > +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 > +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 > +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; > +} > + > +STATIC > +VOID > +RestoreBootOrder ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + UINT16 *BootOrder; > + UINTN BootOrderSize; > + > + GetVariable2 (L"BootOrderBackup", &gOemBootVaraibleGuid, (VOID **) &BootOrder, &BootOrderSize); > + if (BootOrder == NULL) { > + return ; > + } > + > + Print (L"Restore 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", > + &gOemBootVaraibleGuid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, > + 0, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status)); > + } > + > + FreePool (BootOrder); > + > + return; > +} > + > + > +VOID > +RestoreBootOrderOnReadyToBoot ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + // restore BootOrder variable in normal condition. > + RestoreBootOrder (); > +} > + > +STATIC > +VOID > +UpdateBootOrder ( > + IN UINT16 *NewOrder, > + IN UINT16 *BootOrder, > + IN UINTN BootOrderSize > + ) > +{ > + EFI_STATUS Status; > + EFI_EVENT Event; > + > + Status = gRT->SetVariable ( > + L"BootOrderBackup", > + &gOemBootVaraibleGuid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, > + BootOrderSize, > + BootOrder > + ); > + if (EFI_ERROR (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)) { > + 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)); > + } > + > + return; > +} > + > +STATIC > +VOID > +SetBootOrder ( > + IN UINT16 BootType > + ) > +{ > + UINT16 *NewOrder; > + UINT16 *RemainBoots; > + UINT16 *BootOrder; > + UINTN BootOrderSize; > + CHAR16 OptionName[sizeof ("Boot####")]; > + UINTN Index; > + LIST_ENTRY BootOptionList; > + BDS_COMMON_OPTION *Option; > + UINTN SelectCnt; > + UINTN RemainCnt; > + > + InitializeListHead (&BootOptionList); > + > + 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]); > + Option = BdsLibVariableToOption (&BootOptionList, OptionName); > + if (Option == NULL) { > + DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index])); > + continue; > + } > + > + if (GetBBSTypeByDevicePath (Option->DevicePath) == 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); > + } > + > + return ; > +} > + > +STATIC > +VOID > +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); > +} > > // > // BDS Platform Functions > @@ -159,6 +591,10 @@ PlatformBdsInit ( > { > //Signal EndofDxe Event > EfiEventGroupSignal(&gEfiEndOfDxeEventGroupGuid); > + > + // restore BootOrder variable if previous BMC boot override attempt > + // left it in a modified state > + RestoreBootOrder (); > } > > > @@ -473,6 +909,7 @@ PlatformBdsPolicyBehavior ( > Print (L"Press Enter to boot OS immediately.\n"); > Print (L"Press any other key in %d seconds to stop automatical booting...\n", PcdGet16(PcdPlatformBootTimeOut)); > PlatformBdsEnterFrontPage (PcdGet16(PcdPlatformBootTimeOut), TRUE); > + HandleBmcBootType (); > } > > /** > diff --git a/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf b/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf > index baceb57..41ceb89 100644 > --- a/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf > +++ b/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf > @@ -42,6 +42,7 @@ > IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec > MdeModulePkg/MdeModulePkg.dec > MdePkg/MdePkg.dec > + OpenPlatformPkg/Chips/Hisilicon/HisiPkg.dec > > [LibraryClasses] > BaseLib > @@ -49,6 +50,7 @@ > DebugLib > DevicePathLib > GenericBdsLib > + IpmiCmdLib > MemoryAllocationLib > PcdLib > PrintLib > @@ -68,12 +70,14 @@ > > [Guids] > gEfiEndOfDxeEventGroupGuid > + gEfiEventReadyToBootGuid > gEfiFileInfoGuid > gEfiFileSystemInfoGuid > gEfiFileSystemVolumeLabelInfoIdGuid > > [Protocols] > gEfiDevicePathProtocolGuid > + gEfiDevicePathToTextProtocolGuid > gEfiGraphicsOutputProtocolGuid > gEfiLoadedImageProtocolGuid > gEfiPciRootBridgeIoProtocolGuid > -- > 1.9.1 >
Thanks Leif, I also put these three patches(include thed03/d05 ipmi patch) on ssh://git@git.linaro.org/people/heyi.guo/OpenPlatformPkg.git, branch: rp-17.04-07. Thanks and Regards, Chenhui Sun 在 2017/5/19 18:29, Leif Lindholm 写道: > On Fri, May 19, 2017 at 10:54:46AM +0800, Chenhui Sun wrote: >> From: Chenhui Sun <chenhui.sun@linaro.com> >> >> Support the feature that BIOS get boot option from BMC and >> put it in the first boot order. >> >> Contributed-under: TianoCore Contribution Agreement 1.0 >> Signed-off-by: huangming <huangming23@huawei.com> >> Signed-off-by: Heyi Guo <guoheyi@huawei.com> >> Signed-off-by: Yi Li <Phoenix.liyi@huawei.com> >> Signed-off-by: Chenhui Sun <sunchenhui@huawei.com> > Thanks, this one looks good. > > Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org> > >> --- >> Chips/Hisilicon/Include/Library/IpmiCmdLib.h | 94 +++++ >> .../Library/PlatformIntelBdsLib/IntelBdsPlatform.c | 437 +++++++++++++++++++++ >> .../PlatformIntelBdsLib/PlatformIntelBdsLib.inf | 4 + >> 3 files changed, 535 insertions(+) >> create mode 100644 Chips/Hisilicon/Include/Library/IpmiCmdLib.h >> >> diff --git a/Chips/Hisilicon/Include/Library/IpmiCmdLib.h b/Chips/Hisilicon/Include/Library/IpmiCmdLib.h >> new file mode 100644 >> index 0000000..8868b76 >> --- /dev/null >> +++ b/Chips/Hisilicon/Include/Library/IpmiCmdLib.h >> @@ -0,0 +1,94 @@ >> +/** @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 _IPMI_CMD_LIB_H_ >> +#define _IPMI_CMD_LIB_H_ >> + >> +#define BOOT_OPTION_BOOT_FLAG_VALID 1 >> +#define BOOT_OPTION_BOOT_FLAG_INVALID 0 >> + >> +typedef enum { >> + NoOverride = 0x0, >> + ForcePxe, >> + ForceDefaultHardDisk, >> + ForceDefaultHardDiskSafeMode, >> + ForceDefaultDiagnosticPartition, >> + ForceDefaultCD, >> + ForceSetupUtility, >> + ForceRemoteRemovableMedia, >> + ForceRemoteCD, >> + ForcePrimaryRemoteMedia, >> + ForceRemoteHardDisk = 0xB, >> + ForcePrimaryRemovableMedia = 0xF >> +} BOOT_DEVICE_SELECTOR; >> + >> +// >> +// Get System Boot Option data structure >> +// >> +typedef struct { >> + UINT8 ParameterVersion :4; >> + UINT8 Reserved1 :4; >> + UINT8 ParameterSelector :7; >> + UINT8 ParameterValid :1; >> + // >> + // Boot Flags Data 1 >> + // >> + UINT8 Reserved2 :5; >> + UINT8 BiosBootType :1; >> + UINT8 Persistent :1; >> + UINT8 BootFlagsValid :1; >> + // >> + // Boot Flags Data 2 >> + // >> + UINT8 LockResetBtn :1; >> + UINT8 ScreenBlank :1; >> + UINT8 BootDeviceSelector :4; >> + UINT8 LockKeyboard :1; >> + UINT8 ClearCmos :1; >> + // >> + // Boot Flags Data 3 >> + // >> + UINT8 ConsoleRedirectionControl :2; >> + UINT8 LockSleepBtn :1; >> + UINT8 UserPasswordByPass :1; >> + UINT8 Reserved3 :1; >> + UINT8 FirmwareVerbosity :2; >> + UINT8 LockPowerBtn :1; >> + // >> + // Boot Flags Data 4 >> + // >> + UINT8 MuxControlOverride :3; >> + UINT8 ShareModeOverride :1; >> + UINT8 Reserved4 :4; >> + // >> + // Boot Flags Data 5 >> + // >> + UINT8 DeviceInstanceSelector :5; >> + UINT8 Reserved5 :3; >> +} IPMI_GET_BOOT_OPTION; >> + >> +EFI_STATUS >> +EFIAPI >> +IpmiCmdSetSysBootOptions ( >> + OUT IPMI_GET_BOOT_OPTION *BootOption >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +IpmiCmdGetSysBootOptions ( >> + IN IPMI_GET_BOOT_OPTION *BootOption >> + ); >> + >> +#endif >> diff --git a/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c b/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c >> index efefeb6..dc23e46 100644 >> --- a/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c >> +++ b/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c >> @@ -21,16 +21,23 @@ >> >> #include <IndustryStandard/Pci22.h> >> #include <Library/DevicePathLib.h> >> +#include <Library/GenericBdsLib.h> >> +#include <Library/IpmiCmdLib.h> >> #include <Library/PcdLib.h> >> #include <Library/PlatformBdsLib.h> >> +#include <Library/PrintLib.h> >> #include <Library/UefiLib.h> >> #include <Protocol/DevicePath.h> >> +#include <Protocol/DevicePathToText.h> >> #include <Protocol/GraphicsOutput.h> >> #include <Protocol/PciIo.h> >> #include <Protocol/PciRootBridgeIo.h> >> +#include <Guid/GlobalVariable.h> >> >> #include "IntelBdsPlatform.h" >> >> +GUID gOemBootVaraibleGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99, >> + 0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8} }; >> >> //3CEF354A-3B7A-4519-AD70-72A134698311 >> GUID gEblFileGuid = {0x3CEF354A, 0x3B7A, 0x4519, {0xAD, 0x70, >> @@ -142,6 +149,431 @@ STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { >> } >> }; >> >> +STATIC >> +UINT16 >> +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 >> +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); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Locate DevicePathToTextPro %r\n", Status)); >> + return BBS_TYPE_UNKNOWN; >> + } >> + >> + 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 >> +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 >> +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 >> +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; >> +} >> + >> +STATIC >> +VOID >> +RestoreBootOrder ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT16 *BootOrder; >> + UINTN BootOrderSize; >> + >> + GetVariable2 (L"BootOrderBackup", &gOemBootVaraibleGuid, (VOID **) &BootOrder, &BootOrderSize); >> + if (BootOrder == NULL) { >> + return ; >> + } >> + >> + Print (L"Restore 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", >> + &gOemBootVaraibleGuid, >> + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, >> + 0, >> + NULL >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status)); >> + } >> + >> + FreePool (BootOrder); >> + >> + return; >> +} >> + >> + >> +VOID >> +RestoreBootOrderOnReadyToBoot ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + // restore BootOrder variable in normal condition. >> + RestoreBootOrder (); >> +} >> + >> +STATIC >> +VOID >> +UpdateBootOrder ( >> + IN UINT16 *NewOrder, >> + IN UINT16 *BootOrder, >> + IN UINTN BootOrderSize >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_EVENT Event; >> + >> + Status = gRT->SetVariable ( >> + L"BootOrderBackup", >> + &gOemBootVaraibleGuid, >> + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, >> + BootOrderSize, >> + BootOrder >> + ); >> + if (EFI_ERROR (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)) { >> + 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)); >> + } >> + >> + return; >> +} >> + >> +STATIC >> +VOID >> +SetBootOrder ( >> + IN UINT16 BootType >> + ) >> +{ >> + UINT16 *NewOrder; >> + UINT16 *RemainBoots; >> + UINT16 *BootOrder; >> + UINTN BootOrderSize; >> + CHAR16 OptionName[sizeof ("Boot####")]; >> + UINTN Index; >> + LIST_ENTRY BootOptionList; >> + BDS_COMMON_OPTION *Option; >> + UINTN SelectCnt; >> + UINTN RemainCnt; >> + >> + InitializeListHead (&BootOptionList); >> + >> + 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]); >> + Option = BdsLibVariableToOption (&BootOptionList, OptionName); >> + if (Option == NULL) { >> + DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index])); >> + continue; >> + } >> + >> + if (GetBBSTypeByDevicePath (Option->DevicePath) == 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); >> + } >> + >> + return ; >> +} >> + >> +STATIC >> +VOID >> +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); >> +} >> >> // >> // BDS Platform Functions >> @@ -159,6 +591,10 @@ PlatformBdsInit ( >> { >> //Signal EndofDxe Event >> EfiEventGroupSignal(&gEfiEndOfDxeEventGroupGuid); >> + >> + // restore BootOrder variable if previous BMC boot override attempt >> + // left it in a modified state >> + RestoreBootOrder (); >> } >> >> >> @@ -473,6 +909,7 @@ PlatformBdsPolicyBehavior ( >> Print (L"Press Enter to boot OS immediately.\n"); >> Print (L"Press any other key in %d seconds to stop automatical booting...\n", PcdGet16(PcdPlatformBootTimeOut)); >> PlatformBdsEnterFrontPage (PcdGet16(PcdPlatformBootTimeOut), TRUE); >> + HandleBmcBootType (); >> } >> >> /** >> diff --git a/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf b/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf >> index baceb57..41ceb89 100644 >> --- a/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf >> +++ b/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf >> @@ -42,6 +42,7 @@ >> IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec >> MdeModulePkg/MdeModulePkg.dec >> MdePkg/MdePkg.dec >> + OpenPlatformPkg/Chips/Hisilicon/HisiPkg.dec >> >> [LibraryClasses] >> BaseLib >> @@ -49,6 +50,7 @@ >> DebugLib >> DevicePathLib >> GenericBdsLib >> + IpmiCmdLib >> MemoryAllocationLib >> PcdLib >> PrintLib >> @@ -68,12 +70,14 @@ >> >> [Guids] >> gEfiEndOfDxeEventGroupGuid >> + gEfiEventReadyToBootGuid >> gEfiFileInfoGuid >> gEfiFileSystemInfoGuid >> gEfiFileSystemVolumeLabelInfoIdGuid >> >> [Protocols] >> gEfiDevicePathProtocolGuid >> + gEfiDevicePathToTextProtocolGuid >> gEfiGraphicsOutputProtocolGuid >> gEfiLoadedImageProtocolGuid >> gEfiPciRootBridgeIoProtocolGuid >> -- >> 1.9.1 >>
diff --git a/Chips/Hisilicon/Include/Library/IpmiCmdLib.h b/Chips/Hisilicon/Include/Library/IpmiCmdLib.h new file mode 100644 index 0000000..8868b76 --- /dev/null +++ b/Chips/Hisilicon/Include/Library/IpmiCmdLib.h @@ -0,0 +1,94 @@ +/** @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 _IPMI_CMD_LIB_H_ +#define _IPMI_CMD_LIB_H_ + +#define BOOT_OPTION_BOOT_FLAG_VALID 1 +#define BOOT_OPTION_BOOT_FLAG_INVALID 0 + +typedef enum { + NoOverride = 0x0, + ForcePxe, + ForceDefaultHardDisk, + ForceDefaultHardDiskSafeMode, + ForceDefaultDiagnosticPartition, + ForceDefaultCD, + ForceSetupUtility, + ForceRemoteRemovableMedia, + ForceRemoteCD, + ForcePrimaryRemoteMedia, + ForceRemoteHardDisk = 0xB, + ForcePrimaryRemovableMedia = 0xF +} BOOT_DEVICE_SELECTOR; + +// +// Get System Boot Option data structure +// +typedef struct { + UINT8 ParameterVersion :4; + UINT8 Reserved1 :4; + UINT8 ParameterSelector :7; + UINT8 ParameterValid :1; + // + // Boot Flags Data 1 + // + UINT8 Reserved2 :5; + UINT8 BiosBootType :1; + UINT8 Persistent :1; + UINT8 BootFlagsValid :1; + // + // Boot Flags Data 2 + // + UINT8 LockResetBtn :1; + UINT8 ScreenBlank :1; + UINT8 BootDeviceSelector :4; + UINT8 LockKeyboard :1; + UINT8 ClearCmos :1; + // + // Boot Flags Data 3 + // + UINT8 ConsoleRedirectionControl :2; + UINT8 LockSleepBtn :1; + UINT8 UserPasswordByPass :1; + UINT8 Reserved3 :1; + UINT8 FirmwareVerbosity :2; + UINT8 LockPowerBtn :1; + // + // Boot Flags Data 4 + // + UINT8 MuxControlOverride :3; + UINT8 ShareModeOverride :1; + UINT8 Reserved4 :4; + // + // Boot Flags Data 5 + // + UINT8 DeviceInstanceSelector :5; + UINT8 Reserved5 :3; +} IPMI_GET_BOOT_OPTION; + +EFI_STATUS +EFIAPI +IpmiCmdSetSysBootOptions ( + OUT IPMI_GET_BOOT_OPTION *BootOption + ); + +EFI_STATUS +EFIAPI +IpmiCmdGetSysBootOptions ( + IN IPMI_GET_BOOT_OPTION *BootOption + ); + +#endif diff --git a/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c b/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c index efefeb6..dc23e46 100644 --- a/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c +++ b/Chips/Hisilicon/Library/PlatformIntelBdsLib/IntelBdsPlatform.c @@ -21,16 +21,23 @@ #include <IndustryStandard/Pci22.h> #include <Library/DevicePathLib.h> +#include <Library/GenericBdsLib.h> +#include <Library/IpmiCmdLib.h> #include <Library/PcdLib.h> #include <Library/PlatformBdsLib.h> +#include <Library/PrintLib.h> #include <Library/UefiLib.h> #include <Protocol/DevicePath.h> +#include <Protocol/DevicePathToText.h> #include <Protocol/GraphicsOutput.h> #include <Protocol/PciIo.h> #include <Protocol/PciRootBridgeIo.h> +#include <Guid/GlobalVariable.h> #include "IntelBdsPlatform.h" +GUID gOemBootVaraibleGuid = {0xb7784577, 0x5aaf, 0x4557, {0xa1, 0x99, + 0xd4, 0xa4, 0x2f, 0x45, 0x06, 0xf8} }; //3CEF354A-3B7A-4519-AD70-72A134698311 GUID gEblFileGuid = {0x3CEF354A, 0x3B7A, 0x4519, {0xAD, 0x70, @@ -142,6 +149,431 @@ STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { } }; +STATIC +UINT16 +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 +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); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Locate DevicePathToTextPro %r\n", Status)); + return BBS_TYPE_UNKNOWN; + } + + 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 +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 +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 +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; +} + +STATIC +VOID +RestoreBootOrder ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 *BootOrder; + UINTN BootOrderSize; + + GetVariable2 (L"BootOrderBackup", &gOemBootVaraibleGuid, (VOID **) &BootOrder, &BootOrderSize); + if (BootOrder == NULL) { + return ; + } + + Print (L"Restore 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", + &gOemBootVaraibleGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SetVariable BootOrderBackup %r!\n", Status)); + } + + FreePool (BootOrder); + + return; +} + + +VOID +RestoreBootOrderOnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // restore BootOrder variable in normal condition. + RestoreBootOrder (); +} + +STATIC +VOID +UpdateBootOrder ( + IN UINT16 *NewOrder, + IN UINT16 *BootOrder, + IN UINTN BootOrderSize + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gRT->SetVariable ( + L"BootOrderBackup", + &gOemBootVaraibleGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + BootOrderSize, + BootOrder + ); + if (EFI_ERROR (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)) { + 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)); + } + + return; +} + +STATIC +VOID +SetBootOrder ( + IN UINT16 BootType + ) +{ + UINT16 *NewOrder; + UINT16 *RemainBoots; + UINT16 *BootOrder; + UINTN BootOrderSize; + CHAR16 OptionName[sizeof ("Boot####")]; + UINTN Index; + LIST_ENTRY BootOptionList; + BDS_COMMON_OPTION *Option; + UINTN SelectCnt; + UINTN RemainCnt; + + InitializeListHead (&BootOptionList); + + 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]); + Option = BdsLibVariableToOption (&BootOptionList, OptionName); + if (Option == NULL) { + DEBUG ((DEBUG_ERROR, "Boot%04x is invalid option!\n", BootOrder[Index])); + continue; + } + + if (GetBBSTypeByDevicePath (Option->DevicePath) == 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); + } + + return ; +} + +STATIC +VOID +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); +} // // BDS Platform Functions @@ -159,6 +591,10 @@ PlatformBdsInit ( { //Signal EndofDxe Event EfiEventGroupSignal(&gEfiEndOfDxeEventGroupGuid); + + // restore BootOrder variable if previous BMC boot override attempt + // left it in a modified state + RestoreBootOrder (); } @@ -473,6 +909,7 @@ PlatformBdsPolicyBehavior ( Print (L"Press Enter to boot OS immediately.\n"); Print (L"Press any other key in %d seconds to stop automatical booting...\n", PcdGet16(PcdPlatformBootTimeOut)); PlatformBdsEnterFrontPage (PcdGet16(PcdPlatformBootTimeOut), TRUE); + HandleBmcBootType (); } /** diff --git a/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf b/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf index baceb57..41ceb89 100644 --- a/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf +++ b/Chips/Hisilicon/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf @@ -42,6 +42,7 @@ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec MdeModulePkg/MdeModulePkg.dec MdePkg/MdePkg.dec + OpenPlatformPkg/Chips/Hisilicon/HisiPkg.dec [LibraryClasses] BaseLib @@ -49,6 +50,7 @@ DebugLib DevicePathLib GenericBdsLib + IpmiCmdLib MemoryAllocationLib PcdLib PrintLib @@ -68,12 +70,14 @@ [Guids] gEfiEndOfDxeEventGroupGuid + gEfiEventReadyToBootGuid gEfiFileInfoGuid gEfiFileSystemInfoGuid gEfiFileSystemVolumeLabelInfoIdGuid [Protocols] gEfiDevicePathProtocolGuid + gEfiDevicePathToTextProtocolGuid gEfiGraphicsOutputProtocolGuid gEfiLoadedImageProtocolGuid gEfiPciRootBridgeIoProtocolGuid