449 lines
16 KiB
C
449 lines
16 KiB
C
/** @file
|
|
This file implements Gop firmware version information driver.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2019 - 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 "GopFirmwareVersion.h"
|
|
|
|
#include <PiDxe.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Protocol/AdapterInformation.h>
|
|
|
|
#include <Library/IoLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DevicePathLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Guid/EventGroup.h>
|
|
|
|
#include <Protocol/GopComponentName2.h>
|
|
|
|
/**
|
|
Convert FVI GOP Version by transfer revison from CHAR16 to UINT
|
|
|
|
@attention This function may receive untrusted input.
|
|
DriverVersion is external input, so this function will validate its data structure within this buffer before use.
|
|
|
|
@param[in] DriverVersion A pointer to the GOP driver version instance.
|
|
|
|
@retval The Converted Gop Verison
|
|
**/
|
|
UINT64
|
|
ConvertFviGopVersion (
|
|
CHAR16 *DriverVersion
|
|
)
|
|
{
|
|
UINT32 Version[3];
|
|
CHAR16 TempStr;
|
|
UINT32 Index;
|
|
UINT32 VersionIndex;
|
|
UINTN StringSize;
|
|
UINT64 VersionReturn;
|
|
|
|
Index = 0;
|
|
VersionIndex = 0;
|
|
StringSize = 0;
|
|
VersionReturn = GOP_VERSION;
|
|
|
|
ZeroMem (Version, sizeof (Version));
|
|
|
|
if (DriverVersion != NULL) {
|
|
if (StrSize (DriverVersion) > GOP_STR_LEN) {
|
|
StringSize = GOP_STR_LEN;
|
|
} else {
|
|
StringSize = StrSize (DriverVersion);
|
|
}
|
|
for (Index = 0; Index <= StringSize; Index++) {
|
|
TempStr = DriverVersion[Index];
|
|
if (TempStr == '.') {
|
|
VersionIndex++;
|
|
} else if ((TempStr <= '9') && (TempStr >= '0')) {
|
|
if (VersionIndex >= 3) {
|
|
break;
|
|
}
|
|
Version[VersionIndex] *= 0x10;
|
|
Version[VersionIndex] += ((UINT32)(TempStr) - '0');
|
|
}
|
|
}
|
|
VersionReturn = ((UINT8) Version[0]) << VERSION_MINOR_VERSION_SHIFT
|
|
| ((UINT8) Version[1]) << VERSION_REVISION_SHIFT
|
|
| ((UINT16) Version[2]) << VERSION_BUILD_NUM_SHIFT;
|
|
}
|
|
|
|
return VersionReturn;
|
|
}
|
|
|
|
/**
|
|
Update FVI GOP Version, the GOP version depends on the
|
|
GOP_COMPONENT_NAME2_PROTOCOL_GUID and transfer the Revision the CHAR16 to UINT.
|
|
|
|
@param[out] GopTelemetryVersionData A pointer to the array of Gop Version Record Data
|
|
@param[out] TelemetryVersionDataCount A pointer to the count of Gop Version Record Data
|
|
|
|
@retval EFI_SUCCESS The list of undi version record data was returned in GopTelemetryVersionData.
|
|
The count of undi version record data was returned in TelemetryVersionDataCount.
|
|
@retval EFI_INVALID_PARAMETER GopTelemetryVersionData is NULL
|
|
@retval EFI_INVALID_PARAMETER TelemetryVersionDataCount is NULL
|
|
@retval EFI_OUT_OF_RESOURCES Allocate buffer fails
|
|
@retval EFI_NOT_FOUND No handles has protocol gGopComponentName2ProtocolGuid
|
|
**/
|
|
EFI_STATUS
|
|
UpdateGopInfo (
|
|
OUT TELEMETRY_VERSION_RECORD_DATA **GopTelemetryVersionData,
|
|
OUT UINTN *TelemetryVersionDataCount
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN VersionDataIndex;
|
|
TELEMETRY_VERSION_RECORD_DATA *VersionData;
|
|
CHAR16 *DriverVersion;
|
|
GOP_COMPONENT_NAME2_PROTOCOL *GopComponentName2Protocol;
|
|
UINT64 Version;
|
|
|
|
if ((GopTelemetryVersionData == NULL) || (TelemetryVersionDataCount == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
VersionData = NULL;
|
|
VersionDataIndex = 0;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gGopComponentName2ProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "UpdateGopInfo: gBS->LocateHandleBuffer %r\n.", Status));
|
|
return Status;
|
|
}
|
|
DEBUG ((EFI_D_ERROR, "HandleCount : %d\n", HandleCount));
|
|
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gGopComponentName2ProtocolGuid,
|
|
(VOID *) &GopComponentName2Protocol
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Get Gop Version from GopComponentName2Protocol, then convert.
|
|
//
|
|
Status = GopComponentName2Protocol->GetDriverVersion (
|
|
GopComponentName2Protocol,
|
|
"en-US",
|
|
&DriverVersion
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Version = ConvertFviGopVersion (DriverVersion);
|
|
} else {
|
|
Version = GOP_VERSION;
|
|
}
|
|
|
|
//
|
|
// Reallocate when more than one Gop Driver detected.
|
|
//
|
|
if (VersionDataIndex > 0) {
|
|
VersionData = ReallocatePool (
|
|
sizeof (TELEMETRY_VERSION_RECORD_DATA) * VersionDataIndex,
|
|
sizeof (TELEMETRY_VERSION_RECORD_DATA) * (VersionDataIndex + 1),
|
|
VersionData
|
|
);
|
|
} else {
|
|
VersionData = AllocateZeroPool (sizeof (TELEMETRY_VERSION_RECORD_DATA));
|
|
}
|
|
if (VersionData == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
VersionData[VersionDataIndex].Version = Version;
|
|
VersionData[VersionDataIndex].ComponentName = GOP_VERSION_STRING;
|
|
CopyGuid (&VersionData[VersionDataIndex].ComponentID, &(EFI_GUID) GOP_VERSION_COMPONENT_ID);
|
|
|
|
VersionDataIndex++;
|
|
}
|
|
|
|
DEBUG ((EFI_D_INFO, "Gop FVI: Found %d gop driver FVI\n", VersionDataIndex));
|
|
*TelemetryVersionDataCount = VersionDataIndex;
|
|
*GopTelemetryVersionData = VersionData;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Get a list of supported information types for this instance of the protocol.
|
|
|
|
This function returns a list of InformationType GUIDs that are supported on an
|
|
adapter with this instance of EFI_ADAPTER_INFORMATION_PROTOCOL. The list is returned
|
|
in InfoTypesBuffer, and the number of GUID pointers in InfoTypesBuffer is returned in
|
|
InfoTypesBufferCount.
|
|
|
|
@param[in] This A pointer to the EFI_ADAPTER_INFORMATION_PROTOCOL instance.
|
|
@param[out] InfoTypesBuffer A pointer to the array of InformationType GUIDs that are supported
|
|
by This.
|
|
@param[out] InfoTypesBufferCount A pointer to the number of GUIDs present in InfoTypesBuffer.
|
|
|
|
@retval EFI_SUCCESS The list of information type GUIDs that are supported on this adapter was
|
|
returned in InfoTypesBuffer. The number of information type GUIDs was
|
|
returned in InfoTypesBufferCount.
|
|
@retval EFI_INVALID_PARAMETER This is NULL.
|
|
@retval EFI_INVALID_PARAMETER InfoTypesBuffer is NULL.
|
|
@retval EFI_INVALID_PARAMETER InfoTypesBufferCount is NULL.
|
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GopAipGetSupportedTypes (
|
|
IN EFI_ADAPTER_INFORMATION_PROTOCOL *This,
|
|
OUT EFI_GUID **InfoTypesBuffer,
|
|
OUT UINTN *InfoTypesBufferCount
|
|
)
|
|
{
|
|
if ((This == NULL) || (InfoTypesBuffer == NULL) || (InfoTypesBufferCount == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*InfoTypesBuffer = AllocateCopyPool (sizeof (gAdapterInfoTelemetryVersionRecordGuid), &gAdapterInfoTelemetryVersionRecordGuid);
|
|
if (*InfoTypesBuffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*InfoTypesBufferCount = 1;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Returns the current state information for the adapter.
|
|
|
|
This function returns information of type InformationType from the adapter.
|
|
If an adapter does not support the requested informational type, then
|
|
EFI_UNSUPPORTED is returned.
|
|
|
|
@param[in] This A pointer to the EFI_ADAPTER_INFORMATION_PROTOCOL instance.
|
|
@param[in] InformationType A pointer to an EFI_GUID that defines the contents of InformationBlock.
|
|
@param[out] InformationBlock The service returns a pointer to the buffer with the InformationBlock
|
|
structure which contains details about the data specific to InformationType.
|
|
@param[out] InformationBlockSize The driver returns the size of the InformationBlock in bytes.
|
|
|
|
@retval EFI_SUCCESS The InformationType information was retrieved.
|
|
@retval EFI_UNSUPPORTED The InformationType is not known.
|
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
|
@retval EFI_INVALID_PARAMETER This is NULL.
|
|
@retval EFI_INVALID_PARAMETER InformationBlock is NULL.
|
|
@retval EFI_INVALID_PARAMETER InformationBlockSize is NULL.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GopFviAipGetInfo (
|
|
IN EFI_ADAPTER_INFORMATION_PROTOCOL *This,
|
|
IN EFI_GUID *InformationType,
|
|
OUT VOID **InformationBlock,
|
|
OUT UINTN *InformationBlockSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TELEMETRY_VERSION_RECORD_DATA *GopTelemetryVersionData;
|
|
UINTN TelemetryVersionDataCount;
|
|
|
|
if ((This == NULL) || (InformationBlock == NULL) || (InformationBlockSize == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
if (!CompareGuid (InformationType, &gAdapterInfoTelemetryVersionRecordGuid)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = UpdateGopInfo (&GopTelemetryVersionData, &TelemetryVersionDataCount);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "GopFviAipGetInfo: UpdateGopInfo() return : %r\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
Status = CreateTelemetryFviBlock (
|
|
GopTelemetryVersionData,
|
|
TelemetryVersionDataCount,
|
|
(EFI_AIP_TELEMETRY_VERSION_DATA**) InformationBlock,
|
|
InformationBlockSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "GopFviAipGetInfo: CreateTelemetryFviBlock() return : %r\n", Status));
|
|
goto Exit;
|
|
}
|
|
|
|
if (*InformationBlock == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
FreePool (GopTelemetryVersionData);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Sets state information for an adapter.
|
|
|
|
This function sends information of type InformationType for an adapter.
|
|
If an adapter does not support the requested information type, then EFI_UNSUPPORTED
|
|
is returned.
|
|
|
|
@param[in] This A pointer to the EFI_ADAPTER_INFORMATION_PROTOCOL instance.
|
|
@param[in] InformationType A pointer to an EFI_GUID that defines the contents of InformationBlock.
|
|
@param[in] InformationBlock A pointer to the InformationBlock structure which contains details
|
|
about the data specific to InformationType.
|
|
@param[in] InformationBlockSize The size of the InformationBlock in bytes.
|
|
|
|
@retval EFI_SUCCESS The information was received and interpreted successfully.
|
|
@retval EFI_UNSUPPORTED The InformationType is not known.
|
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
|
@retval EFI_INVALID_PARAMETER This is NULL.
|
|
@retval EFI_INVALID_PARAMETER InformationBlock is NULL.
|
|
@retval EFI_WRITE_PROTECTED The InformationType cannot be modified using EFI_ADAPTER_INFO_SET_INFO().
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GopFviAipSetInfo (
|
|
IN EFI_ADAPTER_INFORMATION_PROTOCOL *This,
|
|
IN EFI_GUID *InformationType,
|
|
IN VOID *InformationBlock,
|
|
IN UINTN InformationBlockSize
|
|
)
|
|
{
|
|
|
|
if ((This == NULL) || (InformationBlock == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!CompareGuid (InformationType, &gAdapterInfoTelemetryVersionRecordGuid)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get GOP Version - To get the GOP version depends on the
|
|
GOP_COMPONENT_NAME2_PROTOCOL_GUID and transfer the Revision the CHAR16 to UINT.
|
|
|
|
@param[in] Event The Event this notify function registered to.
|
|
@param[in] Context Pointer to the context data registered to the Event.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InitializeGetGopVersionCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *ProtocolPointer;
|
|
EFI_ADAPTER_INFORMATION_PROTOCOL *AdapterInfo;
|
|
EFI_HANDLE Handle;
|
|
|
|
AdapterInfo = NULL;
|
|
Handle = NULL;
|
|
|
|
Status = gBS->LocateProtocol (&gGopComponentName2ProtocolGuid, NULL, (VOID **) &ProtocolPointer);
|
|
if (EFI_SUCCESS != Status) {
|
|
return;
|
|
}
|
|
|
|
gBS->CloseEvent (Event);
|
|
|
|
AdapterInfo = AllocateZeroPool (sizeof (EFI_ADAPTER_INFORMATION_PROTOCOL));
|
|
if (AdapterInfo == NULL) {
|
|
DEBUG ((EFI_D_ERROR, "EFI_OUT_OF_RESOURCES to Allocate EFI_ADAPTER_INFORMATION_PROTOCOL. \n"));
|
|
return;
|
|
}
|
|
|
|
AdapterInfo->GetInformation = GopFviAipGetInfo;
|
|
AdapterInfo->SetInformation = GopFviAipSetInfo;
|
|
AdapterInfo->GetSupportedTypes = GopAipGetSupportedTypes;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Handle,
|
|
&gEfiAdapterInformationProtocolGuid,
|
|
AdapterInfo,
|
|
NULL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "GOP FVI: faild to install AIP protocol, %r.\n", Status));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
This is driver entry point to register the notification event.
|
|
|
|
@param[in] ImageHandle A handle for the image that is initializing this driver
|
|
@param[in] SystemTable A pointer to the EFI system table
|
|
|
|
@retval EFI_SUCCESS The initialization finished successfully.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GopFirmwareVersionDxe (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
VOID *Registration;
|
|
|
|
//
|
|
// Get the GOP driver version.
|
|
//
|
|
EfiCreateProtocolNotifyEvent (
|
|
&gGopComponentName2ProtocolGuid,
|
|
TPL_CALLBACK,
|
|
InitializeGetGopVersionCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|