alder_lake_bios/Oem/L05/FeatureCommon/InsydeL05ModulePkg/MacAddressPassThroughDxe/MacAddressPassThroughDxe.c

637 lines
18 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 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.
;*
;******************************************************************************
*/
#include "MacAddressPassThroughDxe.h"
/**
Compares two Mac Address.
This function compares MacAddr1 to MacAddr2. If the MacAddrs are identical then TRUE is returned.
If there are any bit differences in the two MacAddrs, then FALSE is returned.
@param MacAddr1 A pointer to EFI_MAC_ADDRESS.
@param MacAddr2 A pointer to EFI_MAC_ADDRESS.
@retval TRUE MacAddr1 and MacAddr2 are identical.
@retval FALSE MacAddr1 and MacAddr2 are not identical.
**/
BOOLEAN
CompareMacAddress (
IN EFI_MAC_ADDRESS *MacAddr1,
IN EFI_MAC_ADDRESS *MacAddr2,
IN UINTN Length
)
{
UINTN Index;
for (Index = 0; Index < Length; Index++) {
if (MacAddr1->Addr[Index] != MacAddr2->Addr[Index]) {
return FALSE;
}
}
return TRUE;
}
/**
Update DSDT MAC Name Space.
[Lenovo Dock BIOS Writer's Guide (BWG) V0.3]
2.2 Implement Guidance
Put Name(with proper value in ACPI DSDT to notify overridden MAC to network driver.
2.2.2 Flowchart
Put Namme(MACA,"_AUXMAX_#xXXXXXXXXXXX#") in ACPI DSDT table,
where xxxxxXxXXXXX means Onboard LAN MAC.
@param MacAddress A pointer to EFI_MAC_ADDRESS.
@retval EFI_SUCCESS The operation completed successfully.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
UpdateDsdtMacNameSpace (
EFI_MAC_ADDRESS *MacAddress
)
{
EFI_STATUS Status;
EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
INTN Index;
EFI_ACPI_DESCRIPTION_HEADER *Table;
EFI_ACPI_TABLE_VERSION Version;
UINTN Handle;
UINT8 *CurrPtr;
UINT32 *Signature;
UINT8 *DsdtPointer;
AcpiSupport = NULL;
Index = 0;
Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (VOID **) &AcpiSupport);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Search for DSDT table
//
while (1) {
Status = AcpiSupport->GetAcpiTable (AcpiSupport, Index, (VOID **) &Table, &Version, &Handle);
if (Status == EFI_NOT_FOUND) {
break;
}
//
// Updates once the table found
//
if (Table->Signature == EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
//
// Point to the beginning of the DSDT table
//
CurrPtr = (UINT8 *) Table;
if (CurrPtr == NULL) {
return EFI_NOT_FOUND;
}
//
// Loop through the ASL looking for values that we must fix up.
//
for (DsdtPointer = CurrPtr; DsdtPointer < (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
//
// Get a pointer to compare for signature
//
Signature = (UINT32 *) DsdtPointer;
//
// Check if this is the signature we are looking for
//
if ((*Signature) == SIGNATURE_32 ('M', 'A', 'C', 'A')) { //MACA
//
// Look for Name Encoding
//
if (*(DsdtPointer - 1) != AML_NAME_OP || *(DsdtPointer + 4) != AML_STRING_PREFIX) {
continue;
}
//
// Update MAC Name Space string
//
AsciiSPrint (
(DsdtPointer + 5),
AsciiStrSize (DsdtPointer + 5),
MACA_NAME_STRING,
MacAddress->Addr[0],
MacAddress->Addr[1],
MacAddress->Addr[2],
MacAddress->Addr[3],
MacAddress->Addr[4],
MacAddress->Addr[5]
);
//
// Update DSDT table
//
Status = AcpiSupport->SetAcpiTable (AcpiSupport, Table, TRUE, Version, &Handle);
gBS->FreePool (Table);
return Status;
}
}
}
gBS->FreePool (Table);
Index++;
}
return EFI_NOT_FOUND;
}
/**
Update DSDT MAC Name Space Callback.
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context.
@retval None
**/
VOID
UpdateDsdtMacNameSpaceCallback (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
)
{
EFI_STATUS Status;
SYSTEM_CONFIGURATION *SetupVariable;
L05_MAC_ADDRESS_DATA *ModifyMacAddrData;
UINTN ModifyMacAddrVarSize;
SetupVariable = NULL;
ModifyMacAddrData = NULL;
SetupVariable = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
Status = CommonGetVariableDataAndSize (
L05_MAC_ADDRESS_PASS_THROUGH_VARIABLE_NAME,
&gH2OBdsCpNetworkUpdateMacAddrGuid,
&ModifyMacAddrVarSize,
(VOID **) &ModifyMacAddrData
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Get MAC address pass through variable fail\n"));
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
return;
}
switch (SetupVariable->L05MacAddressPassThrough) {
case SELECT_NATIVE_MAC_ADDRESS:
DEBUG ((DEBUG_INFO, "Mac Address Pass Through Feature is disable\n"));
break;
case SELECT_INTERNAL_MAC_ADDRESS:
if (ModifyMacAddrData->InternalMacExisted == TRUE) {
//
// Update DSDT Mac Name Space to Internal Mac address
//
Status = UpdateDsdtMacNameSpace (&ModifyMacAddrData->InternalMacAddrrss);
DEBUG ((DEBUG_INFO, "UpdateDsdtMacNameSpace Status: %r\n", Status));
}
break;
case SELECT_SECOND_MAC_ADDRESS:
if (ModifyMacAddrData->SecondMacExisted == TRUE) {
//
// Update DSDT Mac Name Space to Internal Mac address
//
Status = UpdateDsdtMacNameSpace (&ModifyMacAddrData->SecondMacAddrrss);
DEBUG ((DEBUG_INFO, "UpdateDsdtMacNameSpace Status: %r\n", Status));
}
break;
}
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
if (ModifyMacAddrData != NULL) {
FreePool (ModifyMacAddrData);
}
}
/**
Check is need update On-Board Lan MAC Address.
@param ModifyMacAddrData A pointer to the L05_MAC_ADDRESS_DATA.
@retval TRUE On-Board Lan MAC Address is need update.
@retval FALSE On-Board Lan MAC Address is not need update.
**/
BOOLEAN
IsNeedUpdateOnBoardLanMacAddress (
IN OUT L05_MAC_ADDRESS_DATA *ModifyMacAddrData
)
{
EFI_STATUS Status;
UINTN Index;
EFI_HANDLE *DeviceHandleBuffer;
UINTN DeviceHandleCount;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
MAC_ADDR_DEVICE_PATH *MacAddrDevicePath;
DeviceHandleBuffer = NULL;
DeviceHandleCount = 0;
//
// Find On-Board Lan Mac Address
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleNetworkProtocolGuid,
NULL,
&DeviceHandleCount,
&DeviceHandleBuffer
);
if (EFI_ERROR (Status)) {
DeviceHandleCount = 0;
DEBUG ((DEBUG_INFO, "There is No network device on the platform\n"));
}
for (Index = 0; Index < DeviceHandleCount; Index ++) {
Status = gBS->HandleProtocol (
DeviceHandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
(VOID **) &TempDevicePath
);
if (EFI_ERROR (Status)) {
continue;
}
MacAddrDevicePath = NULL;
while (!IsDevicePathEndType (TempDevicePath)) {
if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (TempDevicePath) == MSG_MAC_ADDR_DP)) {
MacAddrDevicePath = (MAC_ADDR_DEVICE_PATH *) TempDevicePath;
break;
}
TempDevicePath = NextDevicePathNode (TempDevicePath);
}
if (MacAddrDevicePath == NULL) {
continue;
}
if (MacAddrDevicePath->IfType == 0x00) {
//
// Internal Mac Address is existed.
//
ModifyMacAddrData->InternalMacExisted = TRUE;
if (!CompareMacAddress (&ModifyMacAddrData->InternalMacAddrrss, &MacAddrDevicePath->MacAddress, sizeof (EFI_MAC_ADDRESS))) {
CopyMem (&ModifyMacAddrData->InternalMacAddrrss, &MacAddrDevicePath->MacAddress, sizeof (EFI_MAC_ADDRESS));
return TRUE;
}
return FALSE;
}
}
if (ModifyMacAddrData->InternalMacExisted == TRUE) {
ModifyMacAddrData->InternalMacExisted = FALSE;
ZeroMem (&ModifyMacAddrData->InternalMacAddrrss, sizeof (EFI_MAC_ADDRESS));
return TRUE;
}
return FALSE;
}
/**
Check is need update Second MAC Address.
@param ModifyMacAddrData A pointer to the L05_MAC_ADDRESS_DATA.
@retval TRUE Second MAC Address is need update.
@retval FALSE Second MAC Address is not need update.
**/
BOOLEAN
IsNeedUpdateSecondMacAddress (
IN OUT L05_MAC_ADDRESS_DATA *ModifyMacAddrData
)
{
EFI_STATUS Status;
EFI_MAC_ADDRESS *SecondMacAddress;
SecondMacAddress = AllocateZeroPool (sizeof (EFI_MAC_ADDRESS));
Status = OemSvcUpdateSecondMacAddress (SecondMacAddress);
if (Status == EFI_MEDIA_CHANGED) {
ModifyMacAddrData->SecondMacExisted = TRUE;
if (!CompareMacAddress (&ModifyMacAddrData->SecondMacAddrrss, SecondMacAddress, sizeof (EFI_MAC_ADDRESS))) {
CopyMem (&ModifyMacAddrData->SecondMacAddrrss, SecondMacAddress, sizeof (EFI_MAC_ADDRESS));
FreePool (SecondMacAddress);
return TRUE;
}
FreePool (SecondMacAddress);
return FALSE;
}
FreePool (SecondMacAddress);
if (ModifyMacAddrData->SecondMacExisted == TRUE) {
ModifyMacAddrData->SecondMacExisted = FALSE;
ZeroMem (&ModifyMacAddrData->SecondMacAddrrss, sizeof (EFI_MAC_ADDRESS));
return TRUE;
}
return FALSE;
}
/**
Update MAC Address Variable Callback.
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context.
@retval None
**/
VOID
EFIAPI
UpdateMacAddressVariableCallback (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
)
{
EFI_STATUS Status;
SYSTEM_CONFIGURATION *SetupVariable;
L05_MAC_ADDRESS_DATA *ModifyMacAddrData;
UINTN ModifyMacAddrVarSize;
BOOLEAN IsNeedToUpdateVariable;
SetupVariable = NULL;
ModifyMacAddrData = NULL;
SetupVariable = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
Status = CommonGetVariableDataAndSize (
L05_MAC_ADDRESS_PASS_THROUGH_VARIABLE_NAME,
&gH2OBdsCpNetworkUpdateMacAddrGuid,
&ModifyMacAddrVarSize,
(VOID **) &ModifyMacAddrData
);
if (EFI_ERROR (Status)) {
//
// Initial MAC_ADDRESS_VARIABLE data
//
ModifyMacAddrVarSize = sizeof (L05_MAC_ADDRESS_DATA);
ModifyMacAddrData = AllocateZeroPool (ModifyMacAddrVarSize);
}
IsNeedToUpdateVariable = FALSE;
IsNeedToUpdateVariable |= IsNeedUpdateOnBoardLanMacAddress (ModifyMacAddrData);
IsNeedToUpdateVariable |= IsNeedUpdateSecondMacAddress (ModifyMacAddrData);
if (IsNeedToUpdateVariable) {
//
// Set Variable "MAC_ADDRESS_VARIABLE" if need.
//
Status = CommonSetVariable (
L05_MAC_ADDRESS_PASS_THROUGH_VARIABLE_NAME,
&gH2OBdsCpNetworkUpdateMacAddrGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
ModifyMacAddrVarSize,
ModifyMacAddrData
);
}
FreePool (SetupVariable);
FreePool (ModifyMacAddrData);
return;
}
/**
Update MAC Address Callback.
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context.
@retval None
**/
VOID
UpdateMacAddressCallback (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
)
{
EFI_STATUS Status;
H2O_BDS_CP_NETWORK_UPDATE_MAC_ADDR_DATA *BdsNetworkUpdateMacAddrData;
EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
MAC_ADDR_DEVICE_PATH *MacAddrDevicePath;
SYSTEM_CONFIGURATION *SetupVariable;
L05_MAC_ADDRESS_DATA *ModifyMacAddrData;
UINTN ModifyMacAddrVarSize;
SetupVariable = NULL;
ModifyMacAddrData = NULL;
SetupVariable = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
if (SetupVariable->L05MacAddressPassThrough == SELECT_NATIVE_MAC_ADDRESS) {
DEBUG ((DEBUG_INFO, "Mac Address Pass Through Feature is disable\n"));
goto ON_EXIT;
}
Status = CommonGetVariableDataAndSize (
L05_MAC_ADDRESS_PASS_THROUGH_VARIABLE_NAME,
&gH2OBdsCpNetworkUpdateMacAddrGuid,
&ModifyMacAddrVarSize,
(VOID **) &ModifyMacAddrData
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Get MAC address pass through variable fail\n"));
goto ON_EXIT;
}
//
// Find out the modify MAC address
//
Status = H2OCpLookup (Handle, (VOID **) &BdsNetworkUpdateMacAddrData, &gH2OBdsCpNetworkUpdateMacAddrGuid);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Checkpoint Data Not Found: %x (%r)\n", Handle, Status));
DEBUG ((DEBUG_ERROR, " %a\n", __FUNCTION__));
goto ON_EXIT;
}
//
// Check UNDI device to get MAC address.
//
Status = gBS->HandleProtocol (BdsNetworkUpdateMacAddrData->NicHandle, &gEfiDevicePathProtocolGuid, (VOID **) &UndiDevicePath);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "DevicePath not found in Handle: %x (%r)\n", Handle, Status));
goto ON_EXIT;
}
MacAddrDevicePath = NULL;
TempDevicePath = UndiDevicePath;
while (!IsDevicePathEndType (TempDevicePath)) {
if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (TempDevicePath) == MSG_MAC_ADDR_DP)) {
MacAddrDevicePath = (MAC_ADDR_DEVICE_PATH *) TempDevicePath;
break;
}
TempDevicePath = NextDevicePathNode (TempDevicePath);
}
if (MacAddrDevicePath == NULL) {
DEBUG ((DEBUG_ERROR, "MAC DevicePath not found in DevicePath: %x (%r)\n", UndiDevicePath, Status));
goto ON_EXIT;
}
if (MacAddrDevicePath->IfType == 0x00) {
DEBUG ((DEBUG_ERROR, "Don't override On-board Lan Mac address\n"));
goto ON_EXIT;
}
switch (SetupVariable->L05MacAddressPassThrough) {
case SELECT_INTERNAL_MAC_ADDRESS:
if (ModifyMacAddrData->InternalMacExisted == TRUE) {
BdsNetworkUpdateMacAddrData->Status = H2O_CP_TASK_UPDATE;
CopyMem (&BdsNetworkUpdateMacAddrData->NicMacAddr, &ModifyMacAddrData->InternalMacAddrrss, sizeof (EFI_MAC_ADDRESS));
}
break;
case SELECT_SECOND_MAC_ADDRESS:
if (ModifyMacAddrData->SecondMacExisted == TRUE) {
BdsNetworkUpdateMacAddrData->Status = H2O_CP_TASK_UPDATE;
CopyMem (&BdsNetworkUpdateMacAddrData->NicMacAddr, &ModifyMacAddrData->SecondMacAddrrss, sizeof (EFI_MAC_ADDRESS));
}
break;
}
ON_EXIT:
if (SetupVariable != NULL) {
FreePool (SetupVariable);
}
if (ModifyMacAddrData != NULL) {
FreePool (ModifyMacAddrData);
}
return;
}
/**
This function is sample to update MAC addresses.
Modify addresses defined in variable ModifyMacAddrVarString:gH2OBdsCpNetworkUpdateMacAddrGuid
@param ImageHandle The firmware allocated handle for the UEFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
EFIAPI
MacAddressPassThroughDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
H2O_CP_HANDLE CpHandle;
Status = EFI_SUCCESS;
if (FeaturePcdGet (PcdH2OBdsCpReadyToBootBeforeSupported)) {
Status = H2OCpRegisterHandler (
&gH2OBdsCpReadyToBootBeforeGuid,
UpdateDsdtMacNameSpaceCallback,
H2O_CP_LOW,
&CpHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpReadyToBootBeforeGuid, Status));
return Status;
}
DEBUG ((EFI_D_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpReadyToBootBeforeGuid, Status));
}
if (FeaturePcdGet (PcdH2OBdsCpConnectAllAfterSupported)) {
Status = H2OCpRegisterHandler (
&gH2OBdsCpConnectAllAfterGuid,
UpdateMacAddressVariableCallback,
H2O_CP_LOW,
&CpHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpConnectAllAfterGuid, Status));
return Status;
}
DEBUG ((EFI_D_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpConnectAllAfterGuid, Status));
}
if (FeaturePcdGet (PcdH2OBdsCpNetworkUpdateMacAddrSupported)) {
Status = H2OCpRegisterHandler (
&gH2OBdsCpNetworkUpdateMacAddrGuid,
UpdateMacAddressCallback,
H2O_CP_LOW,
&CpHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpNetworkUpdateMacAddrGuid, Status));
return Status;
}
DEBUG ((EFI_D_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpNetworkUpdateMacAddrGuid, Status));
}
return Status;
}