494 lines
20 KiB
C
494 lines
20 KiB
C
/** @file
|
|
Dxe Telemetry HwErrRec Lib implementation.
|
|
|
|
Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
**/
|
|
#include "DxeTelemetryAcpiLib.h"
|
|
#include "DxeTelemetryHwErrRec.h"
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mIsFirstCall = TRUE;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 *mMotherBoardHealthRecBuffer = NULL;
|
|
|
|
/**
|
|
|
|
Clear all the Telemetry HwErrRec entries on flash.
|
|
|
|
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
|
defined by the Attributes.
|
|
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
|
|
DataSize exceeds the maximum allowed.
|
|
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
|
|
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
|
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
|
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
|
|
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
|
|
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set,
|
|
but the AuthInfo does NOT pass the validation check carried out by the firmware.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ClearAllTelemetryHwErrRec (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT32 OffsetOfList;
|
|
CHAR16 VarName[TELEMETRY_HW_ERR_REC_VAR_NAME_LEN];
|
|
EFI_STATUS Status;
|
|
UINT8 *VariableData;
|
|
EFI_GUID SectionType;
|
|
BOOLEAN IsDriverHealth;
|
|
|
|
Index = 0;
|
|
OffsetOfList = 0;
|
|
Status = EFI_SUCCESS;
|
|
VariableData = NULL;
|
|
IsDriverHealth = FALSE;
|
|
|
|
DEBUG ((EFI_D_INFO, "ClearAllTelemetryHwErrRec entered\n"));
|
|
|
|
for (Index = 0; Index <= MAX_UINT16; Index++) {
|
|
UnicodeSPrint (VarName, sizeof(VarName), L"%s%04X", TELEMETRY_HW_ERR_REC_VAR_NAME, Index);
|
|
DEBUG ((EFI_D_INFO,"Variablesearch = %s\n",VarName));
|
|
|
|
Status = GetVariable2 (VarName, &gEfiHardwareErrorVariableGuid, (VOID **) &VariableData, NULL);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
//
|
|
// There is no this HwErrRec Variable
|
|
//
|
|
break;
|
|
} else if (EFI_ERROR (Status) || (VariableData == NULL)) {
|
|
DEBUG ((EFI_D_ERROR, "Failed to get HwErrRecVariable data. Status = %r\n", Status));
|
|
return Status;
|
|
}
|
|
CopyGuid (&SectionType, &((EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD *) VariableData)->SectionDescriptor.SectionType);
|
|
//
|
|
// Clear variable when the variable SectionType is belong to mDriverHealthSupportList.
|
|
//
|
|
for (OffsetOfList = 0; mDriverHealthSupportList[OffsetOfList] != NULL; OffsetOfList++ ) {
|
|
if (CompareGuid (&SectionType, mDriverHealthSupportList[OffsetOfList])) {
|
|
IsDriverHealth = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (IsDriverHealth == TRUE) {
|
|
Status = gRT->SetVariable (
|
|
VarName,
|
|
&gEfiHardwareErrorVariableGuid,
|
|
EFI_VARIABLE_NON_VOLATILE |
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
|
EFI_VARIABLE_RUNTIME_ACCESS |
|
|
EFI_VARIABLE_HARDWARE_ERROR_RECORD,
|
|
0,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, " Clear HwErrRec has an issue...\n"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (Status == EFI_NOT_FOUND) {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
DEBUG ((EFI_D_INFO, "ClearAllTelemetryHwErrRec exit...\n"));
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
This routine accepts the pointer to a UINT16 number. It will iterate through each HwErrRecXXXX and stops
|
|
after 0xFFFF iterations or spotted a slot that returns EFI_NOT_FOUND.
|
|
|
|
@param[out] NextVariable The pointer to output result holder
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
|
@retval EFI_INVALID_PARAMETER NextVariable is NULL.
|
|
@retval EFI_NOT_READY gRT or gRt->GetVariable fuction is NULL.
|
|
@retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result.
|
|
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
|
@retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
TelemetryFindNextAvailableSlot (
|
|
OUT UINT16 *NextVariable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 Index;
|
|
UINTN VariableSize;
|
|
CHAR16 VarName[TELEMETRY_HW_ERR_REC_VAR_NAME_LEN];
|
|
|
|
Status = EFI_SUCCESS;
|
|
Index = 0;
|
|
VariableSize = 0;
|
|
|
|
if (NextVariable == NULL) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ((gRT == NULL) || (gRT->GetVariable == NULL)) {
|
|
Status = EFI_NOT_READY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
for (Index = 0; Index <= MAX_UINT16; Index++) {
|
|
VariableSize = 0;
|
|
UnicodeSPrint (VarName, sizeof(VarName), L"%s%04X", TELEMETRY_HW_ERR_REC_VAR_NAME, Index);
|
|
Status = gRT->GetVariable (
|
|
VarName,
|
|
&gEfiHardwareErrorVariableGuid,
|
|
NULL,
|
|
&VariableSize,
|
|
NULL
|
|
);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Translate result corresponds to this specific function
|
|
//
|
|
if (Status == EFI_NOT_FOUND) {
|
|
*NextVariable = Index;
|
|
Status = EFI_SUCCESS;
|
|
} else if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Cleanup:
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Init HwErr Header data.
|
|
|
|
@param[in out] HwErrRecData Point to the guid buffer of EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_INVALID_PARAMETER HwErrRecData is NULL.
|
|
**/
|
|
EFI_STATUS
|
|
InitHwErrHeader(
|
|
IN OUT EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD *HwErrRecData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_TIME Time;
|
|
EFI_GUID UUID;
|
|
EFI_GUID ZeroGuid;
|
|
UINT8 Thousand;
|
|
UINT8 Hundred;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
if (HwErrRecData == NULL) {
|
|
DEBUG ((EFI_D_ERROR, "InitHwErrHeader : Invalid Parameter.\n"));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
ZeroMem (HwErrRecData, sizeof (EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD));
|
|
ZeroMem (&Time, sizeof (EFI_TIME));
|
|
ZeroMem (&UUID, sizeof (EFI_GUID));
|
|
ZeroMem (&ZeroGuid, sizeof (EFI_GUID));
|
|
|
|
//
|
|
// SignatureStart is CPER
|
|
//
|
|
HwErrRecData->Header.SignatureStart = ERROR_RECORD_HEADER_SIGNATURE_START;
|
|
HwErrRecData->Header.Revision = ERROR_RECORD_HEADER_REVISION;
|
|
HwErrRecData->Header.SignatureEnd = ERROR_RECORD_HEADER_SIGNATURE_END;
|
|
HwErrRecData->Header.SectionCount = ERROR_RECORD_HEADER_SIGNATURE_COUNT;
|
|
HwErrRecData->Header.ErrorSeverity = ERROR_RECORD_HEADER_ERRORSEVERITY;
|
|
HwErrRecData->Header.ValidationBits = ERROR_RECORD_HEADER_VALIDATIONBITS;
|
|
//
|
|
// get time
|
|
//
|
|
Status = gRT->GetTime (&Time, NULL);
|
|
if (EFI_ERROR (Status) || (Time.Year < 1970)) {
|
|
DEBUG ((EFI_D_ERROR, "Get Time failed.\n"));
|
|
}
|
|
HwErrRecData->Header.TimeStamp.Seconds = Time.Second;
|
|
HwErrRecData->Header.TimeStamp.Minutes = Time.Minute;
|
|
HwErrRecData->Header.TimeStamp.Hours = Time.Hour;
|
|
HwErrRecData->Header.TimeStamp.Flag = 0;
|
|
HwErrRecData->Header.TimeStamp.Day = Time.Day;
|
|
HwErrRecData->Header.TimeStamp.Month = Time.Month;
|
|
HwErrRecData->Header.TimeStamp.Year = (UINT8) (Time.Year % 100);
|
|
Thousand = (UINT8) ((Time.Year / 1000) %10);
|
|
Hundred = (UINT8) ((Time.Year / 100) %10);
|
|
HwErrRecData->Header.TimeStamp.Century = Thousand * 10 + Hundred + 1;
|
|
|
|
//
|
|
// get uuid from the smbios table
|
|
//
|
|
Status = NetLibGetSystemGuid (&UUID);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "Failed to read system GUID from the smbios table! Status = %r\n", Status));
|
|
ZeroMem (&UUID, sizeof (EFI_GUID));
|
|
}
|
|
|
|
CopyGuid (&HwErrRecData->Header.PlatformID, &UUID);
|
|
CopyGuid (&HwErrRecData->Header.CreatorID, &UUID);
|
|
CopyGuid (&HwErrRecData->Header.PartitionID, &ZeroGuid);
|
|
HwErrRecData->Header.NotificationType = gEfiEventNotificationTypeBootGuid;
|
|
HwErrRecData->Header.Flags = ERROR_RECORD_HEADER_FLAGS;
|
|
|
|
HwErrRecData->SectionDescriptor.SectionOffset = sizeof (EFI_COMMON_ERROR_RECORD_HEADER) + sizeof (EFI_ERROR_SECTION_DESCRIPTOR);
|
|
HwErrRecData->SectionDescriptor.Revision = ERROR_RECORD_SECTION_DESCRIPTOR_REVISION;
|
|
HwErrRecData->SectionDescriptor.SecValidMask = ERROR_RECORD_SECTION_DESCRIPTOR_SECVALIDMASK;
|
|
HwErrRecData->SectionDescriptor.SectionFlags = ERROR_RECORD_SECTION_DESCRIPTOR_SECTIONFLAGS;
|
|
HwErrRecData->SectionDescriptor.Severity = ERROR_RECORD_SECTION_DESCRIPTOR_SEVERITY;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
This function set DriverHealth HwErrRec Variable.
|
|
If the current variable size is greater than the MaximumVariableSize
|
|
current HwErrRec Variable will not be created.
|
|
|
|
@param[IN] AcpiPhatTablePointer A pointer to the EFI_ACPI_DESCRIPTION_HEADER instance.
|
|
|
|
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
|
defined by the Attributes.
|
|
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
|
|
DataSize exceeds the maximum allowed.
|
|
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
|
|
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
|
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
|
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
|
|
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
|
|
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set,
|
|
but the AuthInfo does NOT pass the validation check carried out by the firmware.
|
|
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetDriverHealthHwErrRecVariable (
|
|
IN EFI_ACPI_DESCRIPTION_HEADER *AcpiPhatTablePointer
|
|
)
|
|
{
|
|
EFI_ACPI_PLATFORM_TELEMETRY_RECORD_HEADER *AcpiTelemetryHeader;
|
|
UINTN BufferSize;
|
|
EFI_GUID ComponentID;
|
|
EFI_STATUS Status;
|
|
UINT8 *PhatPointer;
|
|
UINT8 *HealthRecord;
|
|
UINTN TotalRecordLength;
|
|
UINTN TelemetryDataLength;
|
|
EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD HwErrRecData;
|
|
UINT8 *DriverHealthRecData;
|
|
UINT32 DevicePathOffset;
|
|
CHAR16 VariableName[TELEMETRY_HW_ERR_REC_VAR_NAME_LEN];
|
|
UINT16 NextVariable;
|
|
UINT64 MaximumVariableStorageSize;
|
|
UINT64 RemainingVariableStorageSize;
|
|
UINT64 MaximumVariableSize;
|
|
EFI_TELEMETRY_HEALTH_RECORD SectionRecord;
|
|
|
|
BufferSize = 0;
|
|
TotalRecordLength = 0;
|
|
DriverHealthRecData = NULL;
|
|
AcpiTelemetryHeader = NULL;
|
|
|
|
if (AcpiPhatTablePointer == NULL) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
ZeroMem (&SectionRecord, sizeof (EFI_TELEMETRY_HEALTH_RECORD));
|
|
|
|
Status = InitHwErrHeader (&HwErrRecData);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "Failed to initialize the data of HwErrRec header. Status = %r\n", Status));
|
|
goto Done;
|
|
}
|
|
|
|
if (AcpiPhatTablePointer->Length > sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
|
|
TelemetryDataLength = AcpiPhatTablePointer->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER);
|
|
if (TelemetryDataLength < sizeof (EFI_ACPI_PLATFORM_TELEMETRY_RECORD_HEADER)) {
|
|
DEBUG ((EFI_D_ERROR, "PHAT table is not existed or corrupted \n"));
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
} else {
|
|
DEBUG ((EFI_D_ERROR, "PHAT table is not existed or corrupted \n"));
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
PhatPointer = (UINT8 *) AcpiPhatTablePointer + sizeof (EFI_ACPI_DESCRIPTION_HEADER);
|
|
for (TotalRecordLength = 0; TotalRecordLength < TelemetryDataLength - sizeof (EFI_ACPI_PLATFORM_TELEMETRY_RECORD_HEADER);
|
|
PhatPointer += AcpiTelemetryHeader->RecordLength, TotalRecordLength += AcpiTelemetryHeader->RecordLength) {
|
|
AcpiTelemetryHeader = (EFI_ACPI_PLATFORM_TELEMETRY_RECORD_HEADER *) PhatPointer;
|
|
|
|
if (AcpiTelemetryHeader->RecordLength <= sizeof (EFI_ACPI_PLATFORM_TELEMETRY_RECORD_HEADER)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
//
|
|
// Check Telemetry data RecordType.
|
|
//
|
|
if (AcpiTelemetryHeader->RecordType != FirmwareHealthDataRecord) {
|
|
continue;
|
|
}
|
|
//
|
|
// found driver health records
|
|
//
|
|
HealthRecord = (UINT8 *) AcpiTelemetryHeader;
|
|
//
|
|
// skip EFI_ACPI_PLATFORM_TELEMETRY_RECORD_HEADER, Reserved and AmHealthy
|
|
//
|
|
CopyGuid (&ComponentID, &((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->DeviceSignature);
|
|
//
|
|
// Pre-allocate Buffer for MotherBoard Record When the function is first call.
|
|
//
|
|
if ((mIsFirstCall == TRUE) && ((CompareGuid (&ComponentID, &gAdapterInfoMotherBoardHealthGuid)))) {
|
|
mMotherBoardHealthRecBuffer = AllocateZeroPool (sizeof (EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD) +
|
|
((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->DeviceSpecificDataOffset);
|
|
if (mMotherBoardHealthRecBuffer == NULL) {
|
|
DEBUG ((EFI_D_ERROR, "Failed to process SetDriverHealthHwErrRecVariable due to lack of resources!\n"));
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Done;
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
// check if it's Unhealthy Data records.
|
|
//
|
|
if (((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->AmHealthy != TelemetryUnhealthy) {
|
|
continue;
|
|
}
|
|
//
|
|
// Get the the maximum size of an individual EFI variable in current system
|
|
//
|
|
Status = gRT->QueryVariableInfo (
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD,
|
|
&MaximumVariableStorageSize,
|
|
&RemainingVariableStorageSize,
|
|
&MaximumVariableSize
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
goto Done;
|
|
}
|
|
|
|
DevicePathOffset = ((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->DeviceSpecificDataOffset;
|
|
CopyGuid (&HwErrRecData.SectionDescriptor.SectionType, &ComponentID);
|
|
HwErrRecData.SectionDescriptor.SectionLength = DevicePathOffset;
|
|
BufferSize = sizeof (EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD) + DevicePathOffset;
|
|
if (BufferSize > MaximumVariableSize) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
HwErrRecData.Header.RecordLength = (UINT32) BufferSize;
|
|
//
|
|
// Skip other devices when the function is not called for the first time.
|
|
//
|
|
if (mIsFirstCall == FALSE) {
|
|
if (CompareGuid (&ComponentID, &gAdapterInfoMotherBoardHealthGuid)) {
|
|
//
|
|
// DriverHealthRecData Point to pre-allocated buffer.
|
|
//
|
|
DriverHealthRecData = mMotherBoardHealthRecBuffer;
|
|
} else {
|
|
continue;
|
|
}
|
|
} else {
|
|
DriverHealthRecData = AllocateZeroPool (BufferSize);
|
|
}
|
|
if (DriverHealthRecData == NULL) {
|
|
DEBUG ((EFI_D_ERROR, "Failed to process SetDriverHealthHwErrRecVariable due to lack of resources!\n"));
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Done;
|
|
}
|
|
|
|
// telemetry HwErrCper record header
|
|
// ------------------------------------------------------------|
|
|
// | field | Byte Length | Byte offset |
|
|
// |------------------------------------------------------------|
|
|
// | Record Length | 2 | 0 |
|
|
// |------------------------------------------------------------|
|
|
// | Revision | 1 | 2 |
|
|
// |------------------------------------------------------------|
|
|
// | Reserved | 4 | 3 |
|
|
// |------------------------------------------------------------|
|
|
// | AmHealthy | 1 | 7 |
|
|
// -------------------------------------------------------------|
|
|
// | DeviceSignature | 16 | 8 |
|
|
// -------------------------------------------------------------|
|
|
// | DeviceSpecificDataOffset | 4 | 24 |
|
|
// -------------------------------------------------------------|
|
|
//
|
|
SectionRecord.RecordLength = ((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->Header.RecordLength;
|
|
SectionRecord.Revision = ((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->Header.Revision;
|
|
SectionRecord.Reserved = 0;
|
|
SectionRecord.AmHealthy = ((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->AmHealthy;
|
|
SectionRecord.DeviceSignature = ((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->DeviceSignature;
|
|
SectionRecord.DeviceSpecificDataOffset = ((EFI_ACPI_TELEMETRY_HEALTH_DATA_RECORD_STRUCTURE *) AcpiTelemetryHeader)->DeviceSpecificDataOffset;
|
|
//
|
|
// Find next HwErrRec Variable name.
|
|
//
|
|
Status = TelemetryFindNextAvailableSlot (&NextVariable);
|
|
if (Status != EFI_SUCCESS) {
|
|
goto Done;
|
|
}
|
|
UnicodeSPrint (VariableName, sizeof(VariableName), L"%s%04X", TELEMETRY_HW_ERR_REC_VAR_NAME, NextVariable );
|
|
HwErrRecData.Header.RecordID = NextVariable;
|
|
//
|
|
// Copy telemetry HwErr record data to the buffer.
|
|
//
|
|
CopyMem (DriverHealthRecData, (UINT8 *) &HwErrRecData, sizeof (EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD));
|
|
//
|
|
// Copy telemetry HwErrCper record header to the buffer.
|
|
//
|
|
CopyMem (DriverHealthRecData + sizeof (EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD),
|
|
(UINT8 *) &SectionRecord, sizeof (EFI_TELEMETRY_HEALTH_RECORD));
|
|
//
|
|
// Copy device path to the buffer.
|
|
//
|
|
CopyMem (DriverHealthRecData + sizeof (EFI_DRIVERHEALTH_HARDWARE_ERROR_RECORD) + sizeof (EFI_TELEMETRY_HEALTH_RECORD),
|
|
HealthRecord + sizeof (EFI_TELEMETRY_HEALTH_RECORD), DevicePathOffset - sizeof (EFI_TELEMETRY_HEALTH_RECORD)); // lijie error
|
|
//
|
|
// Set DriverHealth HwErrRec Variable.
|
|
//
|
|
Status = gRT->SetVariable (
|
|
VariableName,
|
|
&gEfiHardwareErrorVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD,
|
|
BufferSize,
|
|
DriverHealthRecData
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "Failed to set the DriverHealthRecData Health record into a HwErrRec#### variable. Status = %r\n", Status));
|
|
goto Done;
|
|
}
|
|
|
|
if (DriverHealthRecData != NULL) {
|
|
FreePool (DriverHealthRecData);
|
|
DriverHealthRecData = NULL;
|
|
}
|
|
}
|
|
Done:
|
|
if (DriverHealthRecData != NULL) {
|
|
FreePool (DriverHealthRecData);
|
|
}
|
|
mIsFirstCall = FALSE;
|
|
|
|
return Status;
|
|
}
|