406 lines
15 KiB
C
406 lines
15 KiB
C
/** @file
|
|
This file implements undi 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 "UndiFirmwareVersion.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/BaseLib.h>
|
|
#include <Library/DevicePathLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Guid/EventGroup.h>
|
|
|
|
#include <Protocol/LoadedImage.h>
|
|
#include <Protocol/GopComponentName2.h>
|
|
|
|
/**
|
|
Update UNDI Version Value.
|
|
|
|
@param[out] UndiTelemetryVersionData A pointer to the array of Undi Version Record Data
|
|
@param[out] TelemetryVersionDataCount A pointer to the count of Undi Version Record Data
|
|
|
|
@retval EFI_SUCCESS The list of undi version record data was returned in UndiTelemetryVersionData.
|
|
The count of undi version record data was returned in TelemetryVersionDataCount.
|
|
If count is zero, then return NULL in data.
|
|
@retval EFI_INVALID_PARAMETER UndiTelemetryVersionData is NULL
|
|
@retval EFI_INVALID_PARAMETER TelemetryVersionDataCount is NULL
|
|
@retval EFI_OUT_OF_RESOURCES Allocate buffer fails.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateUndiInfo (
|
|
OUT TELEMETRY_VERSION_RECORD_DATA **UndiTelemetryVersionData,
|
|
OUT UINTN *TelemetryVersionDataCount
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN DriverImageHandleCount;
|
|
EFI_HANDLE *DriverImageHandleBuffer;
|
|
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
|
EFI_GUID *NameGuid;
|
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
|
|
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
|
|
UINT32 RetVal;
|
|
UINTN VersionDataIndex;
|
|
TELEMETRY_VERSION_RECORD_DATA *VersionData;
|
|
|
|
if ((UndiTelemetryVersionData == NULL) || (TelemetryVersionDataCount == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DriverImageHandleCount = 0;
|
|
VersionDataIndex = 0;
|
|
VersionData = NULL;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiLoadedImageProtocolGuid,
|
|
NULL,
|
|
&DriverImageHandleCount,
|
|
&DriverImageHandleBuffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
for (Index = 0; Index < DriverImageHandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
DriverImageHandleBuffer[Index],
|
|
&gEfiLoadedImageProtocolGuid,
|
|
(VOID *) &LoadedImage
|
|
);
|
|
if (LoadedImage->FilePath == NULL) {
|
|
continue;
|
|
}
|
|
|
|
TempDevicePath = LoadedImage->FilePath;
|
|
LastDeviceNode = TempDevicePath;
|
|
while (!IsDevicePathEnd (TempDevicePath)) {
|
|
LastDeviceNode = TempDevicePath;
|
|
TempDevicePath = NextDevicePathNode (TempDevicePath);
|
|
}
|
|
NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (
|
|
(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
|
|
);
|
|
if ((NameGuid != NULL) && (CompareGuid (NameGuid, &gUndiDriverImageGuid))) {
|
|
Status = gBS->HandleProtocol(
|
|
DriverImageHandleBuffer[Index],
|
|
&gEfiDriverBindingProtocolGuid,
|
|
(VOID *) &DriverBinding
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
RetVal = DriverBinding->Version;
|
|
} else {
|
|
RetVal = (UINT32) -1;
|
|
}
|
|
|
|
//
|
|
// Reallocate when more than one Undi 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 = (UINT64) ((RetVal >> 24) & 0x000000FF) << VERSION_MINOR_VERSION_SHIFT
|
|
| (UINT64) ((RetVal >> 16) & 0x000000FF) << VERSION_REVISION_SHIFT
|
|
| (UINT64) (RetVal & 0x0000FFFF) << VERSION_BUILD_NUM_SHIFT;
|
|
VersionData[VersionDataIndex].ComponentName = UNDI_VERSION_STRING;
|
|
CopyGuid (&VersionData[VersionDataIndex].ComponentID, &(EFI_GUID) UNDI_VERSION_COMPONENT_ID);
|
|
|
|
VersionDataIndex++;
|
|
}
|
|
}
|
|
|
|
DEBUG ((EFI_D_INFO, "Undi FVI: Found %d undi driver FVI\n", VersionDataIndex));
|
|
*TelemetryVersionDataCount = VersionDataIndex;
|
|
*UndiTelemetryVersionData = 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
|
|
UndiAipGetSupportedTypes (
|
|
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
|
|
UndiFviAipGetInfo (
|
|
IN EFI_ADAPTER_INFORMATION_PROTOCOL *This,
|
|
IN EFI_GUID *InformationType,
|
|
OUT VOID **InformationBlock,
|
|
OUT UINTN *InformationBlockSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TELEMETRY_VERSION_RECORD_DATA *UndiTelemetryVersionData;
|
|
UINTN TelemetryVersionDataCount;
|
|
|
|
if ((This == NULL) || (InformationBlock == NULL) || (InformationBlockSize == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
if (!CompareGuid (InformationType, &gAdapterInfoTelemetryVersionRecordGuid)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
//
|
|
// update UNDI Version
|
|
//
|
|
Status = UpdateUndiInfo (&UndiTelemetryVersionData, &TelemetryVersionDataCount);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "UndiFviAipGetInfo: UpdateUndiInfo() return : %r.\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
Status = CreateTelemetryFviBlock (
|
|
UndiTelemetryVersionData,
|
|
TelemetryVersionDataCount,
|
|
(EFI_AIP_TELEMETRY_VERSION_DATA**) InformationBlock,
|
|
InformationBlockSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "UndiFviAipGetInfo: CreateTelemetryFviBlock() return : %r.\n", Status));
|
|
goto Exit;
|
|
}
|
|
|
|
if (*InformationBlock == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
if (UndiTelemetryVersionData != NULL){
|
|
FreePool (UndiTelemetryVersionData);
|
|
}
|
|
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
|
|
UndiFviAipSetInfo (
|
|
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 UNDI version.
|
|
|
|
@param[in] Event The Event this notify function registered to.
|
|
@param[in] Context Pointer to the context data registered to the Event.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InitializeGetUndiVersionCallback (
|
|
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 (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **) &ProtocolPointer);
|
|
DEBUG ((EFI_D_ERROR, "GetUndiVersion() : gBS->LocateProtocol returns %r.\n", Status));
|
|
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 = UndiFviAipGetInfo;
|
|
AdapterInfo->SetInformation = UndiFviAipSetInfo;
|
|
AdapterInfo->GetSupportedTypes = UndiAipGetSupportedTypes;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Handle,
|
|
&gEfiAdapterInformationProtocolGuid,
|
|
AdapterInfo,
|
|
NULL
|
|
);
|
|
|
|
DEBUG ((EFI_D_ERROR, "GetUndiVersion() : gBS->InstallMultipleProtocolInterfaces returns %r\n", Status));
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "UNDI 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
|
|
UndiFirmwareVersionDxe (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
VOID *Registration;
|
|
|
|
//
|
|
// Get the UNDI driver version.
|
|
//
|
|
EfiCreateProtocolNotifyEvent (
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
TPL_CALLBACK,
|
|
InitializeGetUndiVersionCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|