/**@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 //[-end-200831-IB17800089-add]// //[-start-191111-IB10189001-removed]// // #include //[-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]//