alder_lake_bios/Intel/AlderLake/AlderLakePlatSamplePkg/Features/Amt/AmtPetAlertDxe/AmtPetAlert.c

1020 lines
31 KiB
C

/**@file
BAE Pet Alert Implementation
;******************************************************************************
;* Copyright (c) 2018 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
@copyright
INTEL CONFIDENTIAL
Copyright 2011 - 2020 Intel Corporation.
The source code contained or described herein and all documents related to the
source code ("Material") are owned by Intel Corporation or its suppliers or
licensors. Title to the Material remains with Intel Corporation or its suppliers
and licensors. The Material may contain trade secrets and proprietary and
confidential information of Intel Corporation and its suppliers and licensors,
and is protected by worldwide copyright and trade secret laws and treaty
provisions. No part of the Material may be used, copied, reproduced, modified,
published, uploaded, posted, transmitted, distributed, or disclosed in any way
without Intel's prior express written permission.
No license under any patent, copyright, trade secret or other intellectual
property right is granted to or conferred upon you by disclosure or delivery
of the Materials, either expressly, by implication, inducement, estoppel or
otherwise. Any license under such intellectual property rights must be
express and approved by Intel in writing.
Unless otherwise agreed by Intel in writing, you may not remove or alter
this notice or any other notice embedded in Materials by Intel or
Intel's suppliers or licensors in any way.
This file contains a 'Sample Driver' and is licensed as such under the terms
of your license agreement with Intel or your vendor. This file may be modified
by the user, subject to the additional terms of the license agreement.
@par Specification Reference:
**/
#include "AmtPetAlert.h"
//[-start-200831-IB17800089-add]//
#include <Library/GenericBdsLib.h>
//[-end-200831-IB17800089-add]//
//[-start-191111-IB10189001-removed]//
// #include <Library/DxePlatformBootManagerLib.h>
//[-end-191111-IB10189001-removed]//
// Example 1: 16 10 0F 6F 02 68 08 FF FF 22 00 40 13 XX XX XX
PET_ALERT mPetAlertWithoutChange = {
{
ASF_MESSAGE_COMMAND_MESSAGE +
(ASF_MESSAGE_BYTE_COUNT_MAP (PET_ALERT) << 8) +
(ASF_MESSAGE_SUBCOMMAND_NORETRANSMIT << 16) +
(ASF_VERSION << 24)
},
ASF_EVENT_SENSOR_TYPE_SYS_FW_ERR_PROG,
ASF_EVENT_TYPE_SENSOR_SPECIFIC,
ASF_EVENT_OFFSET_SYS_FW_PROGRESS,
ASF_EVENT_SOURCE_TYPE_ASF10,
ASF_EVENT_SEVERITY_CODE_NONCRITICAL,
ASF_SENSOR_DEVICE,
ASF_SENSOR_NUMBER,
ASF_ENTITY_BIOS,
ASF_ENTITY_INSTANCE_UNSPECIFIED,
ASF_BAE_EVENT_DATA1,
ASF_FP_BOOT_OS,
0x00,
0x00,
0x00
};
// Example 2: 15 10 0F 6F 02 68 10 FF FF 22 00 AA 13 03 03 02
PET_ALERT mPetAlertWithChange = {
{
ASF_MESSAGE_COMMAND_MESSAGE +
(ASF_MESSAGE_BYTE_COUNT_MAP (PET_ALERT) << 8) +
(ASF_MESSAGE_SUBCOMMAND_RETRANSMIT << 16) +
(ASF_VERSION << 24)
},
ASF_EVENT_SENSOR_TYPE_SYS_FW_ERR_PROG,
ASF_EVENT_TYPE_SENSOR_SPECIFIC,
ASF_EVENT_OFFSET_SYS_FW_PROGRESS,
ASF_EVENT_SOURCE_TYPE_ASF10,
ASF_EVENT_SEVERITY_CODE_CRITICAL,
ASF_SENSOR_DEVICE,
ASF_SENSOR_NUMBER,
ASF_ENTITY_BIOS,
ASF_ENTITY_INSTANCE_UNSPECIFIED,
ASF_BAE_EVENT_DATA1_EVENT_DATA_SET_BY_OEM,
ASF_FP_BOOT_OS,
0x00,
0x00,
0x00
};
//[-start-180502-IB11270199-add]//
CHAR16 *
DevicePathToStr (
IN EFI_DEVICE_PATH_PROTOCOL *DevPath
);
BOOLEAN
IsItPartitionsDevicePath(
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
);
EFI_STATUS
ExpandPartitionsDevPath (
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption,
OUT EFI_DEVICE_PATH_PROTOCOL **BootDevicePath
);
BOOLEAN
DevPathContainsPartition (
IN HARDDRIVE_DEVICE_PATH *ParitionDevPath,
IN EFI_DEVICE_PATH_PROTOCOL *FullDevPath
);
//[-end-180502-IB11270199-add]//
/**
Entry point for AMT PET Alert initialization.
@param[in] ImageHandle Pointer to the loaded image protocol for this driver
@param[in] SystemTable Pointer to the EFI System Table
@retval EFI_SUCCESS PET Alert driver initialized successfully.
**/
EFI_STATUS
EFIAPI
InitializeAmtPetAlert (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EVENT ReadyToBootEvent;
//
// Register Ready to Boot Event for AMT Wrapper
//
Status = EfiCreateEventReadyToBootEx (
TPL_CALLBACK,
AmtPetAlertReadyToBoot,
(VOID *) &ImageHandle,
&ReadyToBootEvent
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Switches the endianess of every 16-bit integer.
@param[in, out] Data The address of data
@param[in] Size Size of data
**/
VOID
SwapEntries (
IN OUT CHAR8 *Data,
IN UINT16 Size
)
{
UINT16 Index;
CHAR8 Temp8;
for (Index = 0; (Index + 1) < Size; Index += 2) {
Temp8 = Data[Index];
Data[Index] = Data[Index + 1];
Data[Index + 1] = Temp8;
}
}
/**
Send BAE PET message
@param[in] BaePetAlert BAE PET message
@retval EFI_SUCCESS Message packet sent.
@retval EFI_NOT_READY HECI is not ready for communication
**/
EFI_STATUS
SendBaeMessage (
IN PET_ALERT BaePetAlert
)
{
EFI_STATUS Status;
HECI_PROTOCOL *Heci;
UINT32 MeStatus;
Status = gBS->LocateProtocol (&gHeciProtocolGuid, NULL, (VOID **) &Heci);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Heci->GetMeStatus (&MeStatus);
ASSERT_EFI_ERROR (Status);
//
// Only send ASF Push Progress code when ME is ready. Ignore FW Init Status.
//
if (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY) {
Status = Heci->SendMsg (
HECI1_DEVICE,
(UINT32 *) &BaePetAlert,
sizeof (PET_ALERT),
BIOS_ASF_HOST_ADDR,
HECI_ASF_MESSAGE_ADDR
);
}
return Status;
}
/**
Send BAE PET message
@param[in] DeviceType PET Alert device type
@param[in] HarddriveTag Hard drive nanme
@retval EFI_SUCCESS The function completed successfully.
@return EFI_NOT_FOUND PetAlertCfg variable not found.
**/
EFI_STATUS
PetAlert (
IN UINT8 DeviceType,
IN CHAR8 *HarddriveTag
)
{
PET_ALERT_CFG PetAlertCfgVar;
UINTN VarSize;
UINTN UpdateFlag;
EFI_STATUS Status;
PET_ALERT PetAlertMsg;
UpdateFlag = 0;
PetAlertMsg = mPetAlertWithoutChange;
if (HarddriveTag == NULL) {
HarddriveTag = "";
}
VarSize = sizeof (PetAlertCfgVar);
Status = gRT->GetVariable (
L"PetAlertCfg",
&gPlatformGlobalVariableGuid,
NULL,
&VarSize,
&PetAlertCfgVar
);
if (EFI_ERROR (Status)) {
UpdateFlag = 1;
PetAlertCfgVar.BootQueue[0] = DeviceType;
PetAlertCfgVar.BootQueue[1] = DeviceType;
PetAlertCfgVar.BootQueue[2] = DeviceType;
AsciiStrCpyS ((CHAR8 *) PetAlertCfgVar.BootHarddriveTag, sizeof (PetAlertCfgVar.BootHarddriveTag) / sizeof (CHAR8), HarddriveTag);
}
DEBUG ((DEBUG_INFO, "PetAlert HDD ModelSerialNumber = %a\n", PetAlertCfgVar.BootHarddriveTag));
if ((DeviceType != BAE_HDD_DEVICE) ||
((DeviceType == BAE_HDD_DEVICE) && AsciiStrCmp (HarddriveTag, (CHAR8 *) PetAlertCfgVar.BootHarddriveTag))) {
//
// If booting from a network/removable device or from a different HDD send expanded BAE message
//
UpdateFlag = 1;
PetAlertMsg = mPetAlertWithChange;
PetAlertMsg.EventData5 = PetAlertCfgVar.BootQueue[2] = PetAlertCfgVar.BootQueue[1];
PetAlertMsg.EventData4 = PetAlertCfgVar.BootQueue[1] = PetAlertCfgVar.BootQueue[0];
PetAlertMsg.EventData3 = PetAlertCfgVar.BootQueue[0] = DeviceType;
}
SendBaeMessage (PetAlertMsg);
if (UpdateFlag) {
AsciiStrCpyS ((CHAR8 *) PetAlertCfgVar.BootHarddriveTag, sizeof (PetAlertCfgVar.BootHarddriveTag) / sizeof (CHAR8), HarddriveTag);
VarSize = sizeof (PetAlertCfgVar);
Status = gRT->SetVariable (
L"PetAlertCfg",
&gPlatformGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
VarSize,
&PetAlertCfgVar
);
ASSERT_EFI_ERROR (Status);
}
return Status;
}
/**
Compare two device paths up to a size of Boot Option's Device Path
@param[in] BootOptionDp Device path acquired from BootXXXX EFI variable
@param[in] FileSysDp Device path acquired through EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Handles buffer
@retval TRUE Both device paths point to the same device
@retval FALSE Device paths point to different devices
**/
BOOLEAN
CompareDevicePaths (
IN EFI_DEVICE_PATH_PROTOCOL *BootOptionDp,
IN EFI_DEVICE_PATH_PROTOCOL *FileSysDp
)
{
UINTN BootOptionDpSize;
UINTN FileSysDpSize;
if (BootOptionDp == NULL || FileSysDp == NULL) {
return FALSE;
}
BootOptionDpSize = GetDevicePathSize (BootOptionDp) - END_DEVICE_PATH_LENGTH;
FileSysDpSize = GetDevicePathSize (FileSysDp) - END_DEVICE_PATH_LENGTH;
if ((BootOptionDpSize <= FileSysDpSize) && (CompareMem (FileSysDp, BootOptionDp, BootOptionDpSize) == 0)) {
return TRUE;
}
return FALSE;
}
/**
Get EFI device path through EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Handles buffer. Acquired path must
point to the same device as argument DevicePath passed to the function.
@param[in] DevicePath Device path acquired from BootXXXX EFI variable
@retval EFI_DEVICE_PATH_PROTOCOL Device path for booting
**/
EFI_DEVICE_PATH_PROTOCOL *
GetFullBootDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
UINTN HandleNum;
EFI_HANDLE *HandleBuf;
UINTN Index;
//[-start-181129-IB15410203-add]//
if (IS_USB_SHORT_FORM_DEVICE_PATH (DevicePath)) {
return BdsLibExpandUsbShortFormDevPath (DevicePath);
}
//[-end-181129-IB15410203-add]//
ReturnDevicePath = NULL;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
&HandleNum,
&HandleBuf
);
if ((EFI_ERROR (Status)) || (HandleBuf == NULL)) {
return NULL;
}
for (Index = 0; Index < HandleNum; Index++) {
TempDevicePath = DevicePathFromHandle (HandleBuf[Index]);
if (CompareDevicePaths (DevicePath, TempDevicePath)) {
ReturnDevicePath = DuplicateDevicePath (TempDevicePath);
break;
}
}
return ReturnDevicePath;
}
UINT8
GetDeviceType (
IN EFI_DEVICE_PATH_PROTOCOL *DevPath
)
{
UINT8 DeviceType;
DeviceType = BAE_EMPTY_QUEUE;
//[-start-181129-IB15410203-modify]//
while (!IsDevicePathEnd (DevPath)) {
if ((DevicePathType (DevPath) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevPath) == MSG_USB_DP ||
DevicePathSubType (DevPath) == MSG_USB_WWID_DP)) {
//
// If device connected through USB, we automatically treat it as removable
//
DeviceType = BAE_REMOVABLE_DEVICE;
break;
} else if (DevicePathType (DevPath) == MEDIA_DEVICE_PATH) {
if (DevicePathSubType (DevPath) == MEDIA_HARDDRIVE_DP) {
DeviceType = BAE_HDD_DEVICE;
break;
} else if (DevicePathSubType (DevPath) == MEDIA_CDROM_DP) {
DeviceType = BAE_REMOVABLE_DEVICE;
break;
} else if (DevicePathSubType (DevPath) == MEDIA_FILEPATH_DP) {
DeviceType = BAE_NETWORK_DEVICE;
break;
}
}
DevPath = NextDevicePathNode(DevPath);
}
//[-end-181129-IB15410203-modify]//
return DeviceType;
}
/**
Cleans off leading and trailing spaces.
@param[in, out] String Pointer to the string to trim them off.
**/
VOID
TrimSpace (
IN OUT CHAR8 *String
)
{
UINTN Index;
if ((String == NULL) || (AsciiStrLen (String) == 0)) {
return;
}
//
// Remove any spaces at the beginning of the String.
//
Index = 0;
while ((String [Index] == ' ') && (AsciiStrLen (String) > Index)) {
Index++;
}
if (Index > 0) {
CopyMem (String, String + Index, AsciiStrLen (String) - Index);
String [AsciiStrLen (String) - Index] = '\0';
}
//
// Remove any spaces at the end of the String.
//
for (Index = AsciiStrLen (String) - 1; (String [Index] == ' ') && (Index > 0); Index--);
if (Index != AsciiStrLen (String) - 1) {
String [Index + 1] = '\0';
}
return;
}
///
///@todo: File a request to add NVME related command to core
///
/**
Get Nvme device identify data.
@param[in] NvmeDevice The pointer to the NVME_PASS_THRU_DEVICE data structure.
@param[in] NamespaceId NamespaceId for an NVM Express namespace present on the NVM Express controller
@param[in] IdentifyStructure Specifies the information to be returned to host.
@param[out] Buffer The buffer used to store the identify controller data.
@return EFI_SUCCESS Successfully get the identify controller data.
@return EFI_DEVICE_ERROR Fail to get the identify controller data.
**/
EFI_STATUS
NvmeIdentifyCommand (
IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *NvmeDevice,
IN UINT32 NamespaceId,
IN UINT32 IdentifyStructure,
OUT VOID *Buffer
)
{
EFI_STATUS Status;
EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
EFI_NVM_EXPRESS_COMMAND Command;
EFI_NVM_EXPRESS_COMPLETION Completion;
ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
DEBUG ((DEBUG_INFO, "Sending Identify Command with Cns = %d\n", IdentifyStructure));
Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
Command.Nsid = NamespaceId;
CommandPacket.NvmeCmd = &Command;
CommandPacket.NvmeCompletion = &Completion;
CommandPacket.TransferBuffer = Buffer;
CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA);
CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
CommandPacket.QueueType = NVME_ADMIN_QUEUE;
//
// Set bit 0 (Cns bit) to 0 to identify a namespace / 1 to identify a controller
//
Command.Cdw10 = IdentifyStructure;
Command.Flags = CDW10_VALID;
Status = NvmeDevice->PassThru (NvmeDevice, NamespaceId, &CommandPacket, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Identify Command Status=%r\n", Status));
}
return Status;
}
EFI_STATUS
GetModelSerialNumberFromNVMePassThru (
IN EFI_HANDLE Handle,
OUT CHAR8 *ModelSerialNumber,
IN UINTN ModelSerialNumberSize
)
{
EFI_STATUS Status;
CHAR8 ModelNumber[42];
CHAR8 SerialNumber[22];
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *NvmePassthruProtocol;
UINT32 NamespaceId;
NVME_ADMIN_CONTROLLER_DATA ControllerData;
Status = EFI_NOT_FOUND;
DevicePath = NULL;
NvmePassthruProtocol = NULL;
Status = gBS->HandleProtocol (
Handle,
&gEfiDevicePathProtocolGuid,
(VOID **) &DevicePath
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->LocateDevicePath (
&gEfiNvmExpressPassThruProtocolGuid,
&DevicePath,
&Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (
Handle,
&gEfiNvmExpressPassThruProtocolGuid,
(VOID**)&NvmePassthruProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
NamespaceId = NVME_ALL_NAMESPACES;
Status = NvmePassthruProtocol->GetNextNamespace (NvmePassthruProtocol, &NamespaceId);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Due to the fact that RAID Driver expects other value of NamespaceId parameter than AHCI driver,
// need to send the Identify Controller command twice - once with the NamespaceId retrieved
// using GetNextNamespace. If it fails we need to set NamespaceId = 0.
//
ZeroMem (&ControllerData, sizeof (NVME_ADMIN_CONTROLLER_DATA));
Status = NvmeIdentifyCommand (NvmePassthruProtocol, NamespaceId, NVME_IDENTIFY_CONTROLLER_STRUCT, (VOID *) &ControllerData);
if (EFI_ERROR (Status)) {
Status = NvmeIdentifyCommand (NvmePassthruProtocol, NVME_CONTROLLER_ID, NVME_IDENTIFY_CONTROLLER_STRUCT, (VOID *) &ControllerData);
if (EFI_ERROR (Status)) {
return Status;
}
}
CopyMem (SerialNumber, ControllerData.Sn, 20);
SerialNumber[20] = '\0';
TrimSpace (SerialNumber);
CopyMem (ModelNumber, ControllerData.Mn, 40);
ModelNumber[40] = '\0';
TrimSpace (ModelNumber);
AsciiStrCpyS (ModelSerialNumber, ModelSerialNumberSize, ModelNumber);
AsciiStrCatS (ModelSerialNumber, ModelSerialNumberSize, "_");
AsciiStrCatS (ModelSerialNumber, ModelSerialNumberSize, SerialNumber);
return Status;
}
EFI_STATUS
GetModelSerialNumber (
IN EFI_HANDLE Handle,
OUT CHAR8 *ModelSerialNumber,
IN UINTN ModelSerialNumberSize
)
{
EFI_STATUS Status;
EFI_DISK_INFO_PROTOCOL *DiskInfo;
EFI_ATAPI_IDENTIFY_DATA *IdentifyDriveInfo;
UINT32 BufferSize;
UINT16 ModelNameLength;
CHAR8 *ModelNumber;
UINT16 SerialNumberLength;
CHAR8 *SerialNumber;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
IdentifyDriveInfo = NULL;
ModelNameLength = 0;
ModelNumber = NULL;
SerialNumberLength = 0;
SerialNumber = NULL;
DevicePath = NULL;
Status = EFI_NOT_FOUND;
AsciiStrCpyS (ModelSerialNumber, ModelSerialNumberSize, "");
Status = GetModelSerialNumberFromNVMePassThru (Handle, ModelSerialNumber, ModelSerialNumberSize);
if (!EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (
Handle,
&gEfiDevicePathProtocolGuid,
(VOID **) &DevicePath
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->LocateDevicePath (
&gEfiDiskInfoProtocolGuid,
&DevicePath,
&Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (
Handle,
&gEfiDiskInfoProtocolGuid,
(VOID **) &DiskInfo
);
if (EFI_ERROR (Status)) {
return Status;
}
IdentifyDriveInfo = AllocatePool (sizeof(EFI_ATAPI_IDENTIFY_DATA));
if (IdentifyDriveInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
SetMem (IdentifyDriveInfo, sizeof (EFI_ATAPI_IDENTIFY_DATA), 0);
BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA);
Status = DiskInfo->Identify (
DiskInfo,
IdentifyDriveInfo,
&BufferSize
);
if (EFI_ERROR (Status)) {
FreePool (IdentifyDriveInfo);
return Status;
}
SerialNumberLength = sizeof (IdentifyDriveInfo->SerialNo) / sizeof (CHAR8);
SerialNumber = AllocateZeroPool ((SerialNumberLength + 1) * sizeof (CHAR8));
if (SerialNumber == NULL) {
FreePool (IdentifyDriveInfo);
return EFI_OUT_OF_RESOURCES;
}
CopyMem (SerialNumber, IdentifyDriveInfo->SerialNo, SerialNumberLength);
SwapEntries (SerialNumber, SerialNumberLength);
SerialNumber [SerialNumberLength] = '\0';
TrimSpace (SerialNumber);
ModelNameLength = sizeof (IdentifyDriveInfo->ModelName) / sizeof (CHAR8);
ModelNumber = AllocateZeroPool ((ModelNameLength + 1) * sizeof (CHAR8));
if (ModelNumber == NULL) {
FreePool (IdentifyDriveInfo);
FreePool (SerialNumber);
return EFI_OUT_OF_RESOURCES;
}
CopyMem (ModelNumber, IdentifyDriveInfo->ModelName, ModelNameLength);
SwapEntries (ModelNumber, ModelNameLength);
ModelNumber [ModelNameLength] = '\0';
TrimSpace (ModelNumber);
AsciiStrCpyS (ModelSerialNumber, ModelSerialNumberSize, ModelNumber);
AsciiStrCatS (ModelSerialNumber, ModelSerialNumberSize, "_");
AsciiStrCatS (ModelSerialNumber, ModelSerialNumberSize, SerialNumber);
FreePool (IdentifyDriveInfo);
FreePool (SerialNumber);
FreePool (ModelNumber);
return EFI_SUCCESS;
}
EFI_STATUS
GetModelSerialNumberFromBbs (
IN UINT8 DeviceType,
OUT CHAR8 *ModelSerialNumber,
IN UINTN ModelSerialNumberSize
)
{
return EFI_NOT_FOUND;
}
/**
Ready to Boot Event notification handler.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
**/
VOID
EFIAPI
AmtPetAlertReadyToBoot (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT16 BootCurrent;
UINTN VarSize;
CHAR16 BootXXXX[16];
EFI_DEVICE_PATH_PROTOCOL *BootDevicePath;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
UINT8 DeviceType;
CHAR8 ModelSerialNumber[64];
EFI_HANDLE BootDeviceHandle;
EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
UINTN ModelSerialNumberSize;
ME_BIOS_PAYLOAD_HOB *MbpHob;
gBS->CloseEvent (Event);
MbpHob = NULL;
MbpHob = GetFirstGuidHob (&gMeBiosPayloadHobGuid);
if (MbpHob == NULL || MbpHob->MeBiosPayload.FwFeaturesState.FwFeatures.Fields.Amt == 0 ||
MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.Amt == 0) {
return;
}
DEBUG ((DEBUG_INFO, "Send BAE message in ReadyToBoot event\n"));
ModelSerialNumberSize = sizeof (ModelSerialNumber) / sizeof (CHAR8);
AsciiStrCpyS (ModelSerialNumber, ModelSerialNumberSize, "");
BootDeviceHandle = 0;
DeviceType = 0;
BootDevicePath = NULL;
//
// Get current boot option from NVRAM variables
//
VarSize = sizeof (UINT16);
Status = gRT->GetVariable (
L"BootCurrent",
&gEfiGlobalVariableGuid,
NULL,
&VarSize,
&BootCurrent
);
if (EFI_ERROR (Status)) {
return;
}
UnicodeSPrint (BootXXXX, sizeof(BootXXXX), L"Boot%04X", BootCurrent);
Status = EfiBootManagerVariableToLoadOption (BootXXXX, &BootOption);
if (EFI_ERROR (Status)) {
return;
}
//[-start-181129-IB15410203-modify]//
if (((BBS_BBS_DEVICE_PATH *)BootOption.FilePath)->Header.Type == BBS_DEVICE_PATH) {
BootDevicePath = DuplicateDevicePath (BootOption.FilePath);
} else if (IsItPartitionsDevicePath (&BootOption)) {
Status = ExpandPartitionsDevPath (&BootOption, &BootDevicePath);
} else if (DevicePathType (BootOption.FilePath) == MESSAGING_DEVICE_PATH &&
DevicePathSubType (BootOption.FilePath) == MSG_USB_WWID_DP) {
BootDevicePath = DuplicateDevicePath (BootOption.FilePath);
} else {
//
// For EFI boot get full device path from EFI_SIMPLE_FILE_SYSTEM
//
BootDevicePath = GetFullBootDevicePath (BootOption.FilePath);
}
//[-end-181129-IB15410203-modify]//
EfiBootManagerFreeLoadOption (&BootOption);
if (BootDevicePath == NULL) {
return;
}
DeviceType = GetDeviceType (BootDevicePath);
//
// Get model serial number if device is HDD
//
if (DeviceType == BAE_HDD_DEVICE) {
TempDevicePath = BootDevicePath;
Status = gBS->LocateDevicePath (
&gEfiSimpleFileSystemProtocolGuid,
&TempDevicePath,
&BootDeviceHandle
);
if (EFI_ERROR (Status)) {
FreePool (BootDevicePath);
return;
}
GetModelSerialNumber (BootDeviceHandle, ModelSerialNumber, ModelSerialNumberSize);
}
FreePool (BootDevicePath);
Status = PetAlert (DeviceType, ModelSerialNumber);
return;
}
//[-start-180502-IB11270199-modify]//
/**
Checks whenever a given load option starts with a partition device path
@param[in] LoadOption Pointer to load option to test
@retval TRUE
@retval FALSE
**/
BOOLEAN
IsItPartitionsDevicePath(
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
)
{
return DevicePathType (LoadOption->FilePath) == MEDIA_DEVICE_PATH &&
(DevicePathSubType (LoadOption->FilePath) == MEDIA_HARDDRIVE_DP);
}
/**
Tries to expand the given partitions device path to start with physical HDD
device path
@param[in] LoadOption pointer to an Efi Boot Manager boot option
@param[out] BootDevicePath indirect pointer to retrieved device path
@retval EFI_SUCCESS Function found
**/
EFI_STATUS
ExpandPartitionsDevPath (
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption,
OUT EFI_DEVICE_PATH_PROTOCOL **BootDevicePath
)
{
EFI_STATUS Status;
UINTN BlockIoHandleCount;
EFI_HANDLE *BlockIoBuffer;
EFI_DEVICE_PATH_PROTOCOL *PartitionDevPath;
EFI_DEVICE_PATH *BlockIoDevicePath;
UINT32 Index;
DEBUG ((DEBUG_INFO, "Expand partitions device path\n"));
*BootDevicePath = NULL;
PartitionDevPath = LoadOption->FilePath;
DEBUG_CODE (
CHAR16 *DevPathStr;
DevPathStr = DevicePathToStr(PartitionDevPath);
DEBUG ((DEBUG_INFO, "Partition dev path : %s\n", DevPathStr));
FreePool (DevPathStr);
);
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
if (EFI_ERROR (Status) || BlockIoHandleCount == 0 || BlockIoBuffer == NULL) {
return EFI_NOT_FOUND;
}
for (Index=0; Index < BlockIoHandleCount; Index++) {
Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);
if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {
continue;
}
DEBUG_CODE (
CHAR16 *DevPathStr;
DevPathStr = DevicePathToStr(BlockIoDevicePath);
DEBUG ((DEBUG_INFO, "Checking dev path : %s\n", DevPathStr));
FreePool (DevPathStr);
);
if (DevPathContainsPartition((HARDDRIVE_DEVICE_PATH*) PartitionDevPath, BlockIoDevicePath)) {
*BootDevicePath = DuplicateDevicePath(BlockIoDevicePath);
break;
}
}
if (*BootDevicePath == NULL) {
Status = EFI_NOT_FOUND;
}
if (BlockIoBuffer != NULL) {
FreePool (BlockIoBuffer);
}
return Status;
}
/**
Check whether there is a instance in BlockIoDevicePath, which contain multi device path
instances, has the same partition node with HardDriveDevicePath device path
@param BlockIoDevicePath Multi device path instances which need to check
@param HardDriveDevicePath A device path which starts with a hard drive media
device path.
@retval TRUE There is a matched device path instance.
@retval FALSE There is no matched device path instance.
**/
BOOLEAN
DevPathContainsPartition (
IN HARDDRIVE_DEVICE_PATH *ParitionDevPath,
IN EFI_DEVICE_PATH_PROTOCOL *FullDevPath
)
{
HARDDRIVE_DEVICE_PATH *PartitionToCompare;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
BOOLEAN Match;
DEBUG ((DEBUG_INFO , "Device Path Contains Partition\n"));
if ((FullDevPath == NULL) || (ParitionDevPath == NULL)) {
return FALSE;
}
//
// find the partition device path node
//
DevicePath = (EFI_DEVICE_PATH_PROTOCOL*)FullDevPath;
PartitionToCompare = NULL;
while (!IsDevicePathEnd (DevicePath)) {
if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {
PartitionToCompare = (HARDDRIVE_DEVICE_PATH *) DevicePath;
break;
}
DevicePath = NextDevicePathNode (DevicePath);
}
if (PartitionToCompare == NULL) {
return FALSE;
}
DEBUG_CODE(
CHAR16 *PartitionToCompareStr;
CHAR16 *PartitionStr;
PartitionToCompareStr = DevicePathToStr ((EFI_DEVICE_PATH_PROTOCOL*)PartitionToCompare);
PartitionStr = DevicePathToStr ((EFI_DEVICE_PATH_PROTOCOL*)ParitionDevPath);
DEBUG ((DEBUG_INFO, "\t\tpartition : \"%s\"\n\t\tpartitionToCompare: \"%s\"\n", PartitionStr, PartitionToCompareStr));
FreePool (PartitionStr);
FreePool (PartitionToCompareStr);
);
//
// Check for the match
//
Match = FALSE;
if ((PartitionToCompare->MBRType == ParitionDevPath->MBRType) &&
(PartitionToCompare->SignatureType == ParitionDevPath->SignatureType)) {
switch (PartitionToCompare->SignatureType) {
case SIGNATURE_TYPE_GUID:
Match = CompareGuid (
(EFI_GUID *)PartitionToCompare->Signature,
(EFI_GUID *)ParitionDevPath->Signature
);
DEBUG ((
DEBUG_INFO, "GUID Signature\n\t\tpartition %016X%016X\n"
"\t\tpartitionToCompare: %016X%016X\n",
(UINT64*) ((VOID*)&ParitionDevPath->Signature[0]),
(UINT64*) ((VOID*)&ParitionDevPath->Signature[1]),
(UINT64*) ((VOID*)&PartitionToCompare->Signature[0]),
(UINT64*) ((VOID*)&PartitionToCompare->Signature[1])
));
break;
case SIGNATURE_TYPE_MBR:
Match = (
(BOOLEAN)(*((UINT32 *)(&(PartitionToCompare->Signature[0]))) ==
ReadUnaligned32((UINT32 *)(&(ParitionDevPath->Signature[0]))))
);
DEBUG ((
DEBUG_INFO,
"MBR signature type:\n\tpartition %08X\n\tpartitionToCompare %08X\n",
ReadUnaligned32((UINT32 *)(&(ParitionDevPath->Signature[0]))),
*((UINT32 *)(&(PartitionToCompare->Signature[0])))
));
break;
default:
Match = FALSE;
break;
}
}
if (Match) {
DEBUG ((DEBUG_INFO, "Partition is contained inside dev path.\n"));
} else {
DEBUG ((DEBUG_INFO, "Partition is not contained inside dev path.\n"));
}
return Match;
}
//[-end-180502-IB11270199-modify]//