alder_lake_bios/Intel/AlderLake/AlderLakePlatSamplePkg/Features/Me/MeSmbiosUpdateConfigDxe/MeSmbiosUpdateConfig.c

601 lines
18 KiB
C

/** @file
This is the driver which installs protocol for updating ME SMBIOS tables.
@copyright
INTEL CONFIDENTIAL
Copyright 2019 - 2021 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 <IndustryStandard/Pci30.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PciSegmentLib.h>
#include <Library/GbeLib.h>
#include <Library/HobLib.h>
#include <Library/PchPciBdfLib.h>
#include <Library/PcdLib.h>
#include <Protocol/MeSmbiosUpdateProtocol.h>
#include <Protocol/OneClickRecoveryProtocol.h>
#include <Protocol/TrustedDeviceSetupMainProtocol.h>
#include <Protocol/MebxConfigProtocol.h>
#include <Register/PchRegs.h>
#include <Register/Msr.h>
#include <Register/Cpuid.h>
#include <Register/PchRegsLpc.h>
#include <MeBiosPayloadHob.h>
#include <Uefi.h>
#include <MebxData.h>
#include <MeSmbios.h>
#include <SetupVariable.h>
#include <OemSetup.h>
#if FixedPcdGetBool(PcdRemotePlatformEraseSupport) == 1
#include <RemotePlatformErase.h>
#endif
EFI_STATUS
EFIAPI
UpdateSmbios130 (
VOID
);
EFI_STATUS
EFIAPI
UpdateSmbios131 (
VOID
);
ME_SMBIOS_TABLES_UPDATE_PROTOCOL mMeSmbiosTablesUpdate = {
UpdateSmbios130,
UpdateSmbios131,
};
/**
Returns the SMBIOS table with the specified type.
@param[in] Type The type of the SMBIOS table which is searched.
@param[out] Record If the functions finishes with success, then it will point the found SMBIOS Record.
@retval EFI_SUCCESS Record was found.
@retval EFI_INVALID_PARAMETER Table pointer is NULL.
@retval EFI_NOT_FOUND Record cannot be found.
**/
EFI_STATUS
GetSmbiosTable (
IN SMBIOS_TYPE Type,
OUT EFI_SMBIOS_TABLE_HEADER **Table
)
{
EFI_STATUS Status;
EFI_SMBIOS_HANDLE SmbiosHandle;
EFI_SMBIOS_PROTOCOL *Smbios;
EFI_SMBIOS_TABLE_HEADER *Record;
if (Table == NULL) {
return EFI_INVALID_PARAMETER;
}
*Table = NULL;
Status = gBS->LocateProtocol (
&gEfiSmbiosProtocolGuid,
NULL,
(VOID**) &Smbios
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return Status;
}
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
do {
Status = Smbios->GetNext (
Smbios,
&SmbiosHandle,
NULL,
&Record,
NULL
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
} while (Record->Type != Type);
*Table = Record;
return EFI_SUCCESS;
}
/**
This function updates SMBIOS type 130 OemCapabilities1 field.
@param[out] SmbiosTableType130Data SMBIOS type 130 data
@param[in] MbpHob ME BIOS Payload Hob
**/
VOID
UpdateManageabilityData (
OUT SMBIOS_TABLE_TYPE130 *SmbiosTableType130Data,
IN ME_BIOS_PAYLOAD_HOB *MbpHob
)
{
EFI_STATUS Status;
UINTN MebxDataSize;
MEBX_DATA MebxData;
MEBX_CONFIG_PROTOCOL *MebxConfigProtocol;
if (MbpHob == NULL) {
DEBUG ((DEBUG_ERROR, "%a: No MBP HOB available\n", __FUNCTION__));
return;
}
ZeroMem (&MebxData, sizeof (MEBX_DATA));
Status = gBS->LocateProtocol (&gMebxConfigProtocolGuid, NULL, (VOID**) &MebxConfigProtocol);
if (!EFI_ERROR (Status)) {
MebxDataSize = sizeof (MEBX_DATA);
Status = MebxConfigProtocol->GetMebxConfig (&MebxDataSize, (VOID*) &MebxData);
DEBUG ((DEBUG_INFO, "MebxConfigProtocol->GetMebxConfig %r\n", Status));
if (EFI_ERROR (Status)) {
ZeroMem (&MebxData, sizeof (MEBX_DATA));
}
}
SmbiosTableType130Data->AmtSupported = (UINT8) MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.Amt;
if (SmbiosTableType130Data->AmtSupported) {
SmbiosTableType130Data->AmtEnabled = (UINT8) MbpHob->MeBiosPayload.FwFeaturesState.FwFeatures.Fields.Amt;
}
if (SmbiosTableType130Data->AmtSupported) {
//
// if vPro or ISM supported, LAN is always enabled and SRoU/Sol depend on enabled/disabled state in MEBX
//
SmbiosTableType130Data->NetworkEnabled = 1;
SmbiosTableType130Data->SrouEnabled = MebxData.AmtSrou;
SmbiosTableType130Data->SolEnabled = MebxData.AmtSol;
}
if (MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.KVM) {
SmbiosTableType130Data->KvmEnabled = (UINT8) MbpHob->MeBiosPayload.FwFeaturesState.FwFeatures.Fields.KVM;
}
}
/**
This function updates SMBIOS type 130 OemCapabilities1 field.
@param[out] OemCapabilities1 OemCapabilities1
@param[in] MeSetup ME Setup Configuration
**/
VOID
UpdateOemCapabilities1 (
OUT UINT8 *OemCapabilities1,
IN ME_SETUP MeSetup
)
{
*OemCapabilities1 |= (((!!MeSetup.BiosReflash) << OEM_CAPS_1_BIOS_REFLASH_BIT_OFFSET) |
((!!MeSetup.BiosSetup) << OEM_CAPS_1_BIOS_SETUP_BIT_OFFSET ) |
((!!MeSetup.BiosPause) << OEM_CAPS_1_BIOS_PAUSE_BIT_OFFSET )
);
}
/**
This function updates SMBIOS type 130 OemCapabilities2 field.
@param[out] OemCapabilities2 OemCapabilities2
**/
VOID
UpdateOemCapabilities2 (
OUT UINT8 *OemCapabilities2
)
{
*OemCapabilities2 |= OEM_CAPS_2_TERMINAL_EMULATION_VT100PLUS;
}
/**
This function updates SMBIOS type 130 OemCapabilities3 field.
@param[out] OemCapabilities3 OemCapabilities3
@param[in] MeSetup ME Setup Configuration
@param[in] MbpHob ME BIOS Payload Hob
**/
VOID
UpdateOemCapabilities3 (
OUT UINT8 *OemCapabilities3,
IN ME_SETUP MeSetup,
IN ME_BIOS_PAYLOAD_HOB *MbpHob
)
{
BOOLEAN FullMngSupport;
if ((MbpHob != NULL) && (!!MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.FullMng)) {
FullMngSupport = TRUE;
} else {
FullMngSupport = FALSE;
}
*OemCapabilities3 |= (((!!MeSetup.SecureBootExposureToFw) << OEM_CAPS_3_BIOS_SECURE_BOOT_BIT_OFFSET) |
( FullMngSupport << OEM_CAPS_3_SECURE_ERASE_BIT_OFFSET )
);
}
/**
This function updates SMBIOS type 130 OemCapabilities4 field.
@param[out] OemCapabilities4 OemCapabilities4
@param[in] MeSetup ME Setup Configuration
@param[in] MbpHob ME BIOS Payload Hob
**/
VOID
UpdateOemCapabilities4 (
OUT UINT8 *OemCapabilities4,
IN ME_SETUP MeSetup,
IN ME_BIOS_PAYLOAD_HOB *MbpHob
)
{
EFI_STATUS Status;
ONE_CLICK_RECOVERY_PROTOCOL *OneClickRecovery;
ONE_CLICK_RECOVERY_CAP OcrCap;
if (MbpHob == NULL) {
DEBUG ((DEBUG_ERROR, "%a: No MBP HOB available\n", __FUNCTION__));
return;
}
//
// Supported in full or standard manageability
//
if (!!MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.Amt) {
*OemCapabilities4 |= (!!MeSetup.vProTbtDock) << OEM_CAPS_4_VPRO_TBT_DOCK_BIT_OFFSET;
}
//
// Supported in full manageability
//
if (!!MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.FullMng) {
Status = gBS->LocateProtocol (&gOneClickRecoveryProtocolGuid, NULL, (VOID **) &OneClickRecovery);
if (EFI_ERROR (Status)) {
return;
}
OcrCap = OneClickRecovery->OcrCap ();
*OemCapabilities4 |= (((!!OcrCap.Bits.OcrBootHttps) << OEM_CAPS_4_OCR_HTTPS_BOOT_BIT_OFFSET ) |
((!!OcrCap.Bits.OcrBootPba) << OEM_CAPS_4_OCR_PBA_BOOT_BIT_OFFSET ) |
((!!OcrCap.Bits.OcrBootWinRe) << OEM_CAPS_4_OCR_WINRE_BOOT_BIT_OFFSET ) |
((!!OcrCap.Bits.OcrAmtDisSecBoot) << OEM_CAPS_4_OCR_AMT_DIS_SEC_BOOT_BIT_OFFSET) |
((!!OcrCap.Bits.OcrWifiProfile) << OEM_CAPS_4_OCR_WIFI_PROFILE_BIT_OFFSET )
);
}
}
/**
Updates SMBIOS 130 table with Remote Platform Erase Capabilities
@param[out] RpeCapabilities RpeCapabilities
@param[in] MbpHob ME BIOS Payload Hob
**/
VOID
UpdateRpeCapabilities (
OUT UINT32 *RpeCapabilities,
IN ME_BIOS_PAYLOAD_HOB *MbpHob
)
{
#if FixedPcdGetBool(PcdRemotePlatformEraseSupport) == 1
if ((MbpHob != NULL) && (!!MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.FullMng)) {
*RpeCapabilities |= RPE_CAPABILITY_SUPPORT;
}
#endif
}
/**
This function makes boot time changes to the content of the SMBIOS type 130.
@retval EFI_SUCCESS Record was updated successfully.
@retval EFI_NOT_FOUND HECI protocol or SMBIOS type 130 record cannot be found.
**/
EFI_STATUS
EFIAPI
UpdateSmbios130 (
VOID
)
{
EFI_STATUS Status;
EFI_SMBIOS_TABLE_HEADER *Record;
ME_SETUP MeSetup;
UINTN VariableSize;
SMBIOS_TABLE_TYPE130 *SmbiosTableType130Data;
ME_BIOS_PAYLOAD_HOB *MbpHob;
DEBUG ((DEBUG_INFO, "%a() entry \n", __FUNCTION__));
Status = GetSmbiosTable (MESMBIOS_TYPE_130, &Record);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
SmbiosTableType130Data = (SMBIOS_TABLE_TYPE130*) Record;
MbpHob = GetFirstGuidHob (&gMeBiosPayloadHobGuid);
VariableSize = sizeof (ME_SETUP);
Status = gRT->GetVariable (
L"MeSetup",
&gMeSetupVariableGuid,
NULL,
&VariableSize,
&MeSetup
);
if (EFI_ERROR (Status)) {
ZeroMem (&MeSetup, sizeof (ME_SETUP));
}
UpdateManageabilityData (SmbiosTableType130Data, MbpHob);
UpdateOemCapabilities1 (&SmbiosTableType130Data->OemCapabilities1, MeSetup);
UpdateOemCapabilities2 (&SmbiosTableType130Data->OemCapabilities2);
UpdateOemCapabilities3 (&SmbiosTableType130Data->OemCapabilities3, MeSetup, MbpHob);
UpdateOemCapabilities4 (&SmbiosTableType130Data->OemCapabilities4, MeSetup, MbpHob);
UpdateRpeCapabilities (&SmbiosTableType130Data->RpeCapabilities, MbpHob);
return EFI_SUCCESS;
}
/**
Updates CPU capabilities.
@param[out] CpuCapabilities Cpu Capabilities
**/
VOID
UpdateCpuCapabilities (
OUT CPU_CAP *CpuCapabilities
)
{
MSR_IA32_FEATURE_CONTROL_REGISTER Ia32FeatureControlMsr;
CPUID_VERSION_INFO_ECX Ecx;
Ia32FeatureControlMsr.Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
CpuCapabilities->VMXState = Ia32FeatureControlMsr.Bits.EnableVmxOutsideSmx;
CpuCapabilities->VTxEnabled = CpuCapabilities->VMXState;
CpuCapabilities->SMXState = Ia32FeatureControlMsr.Bits.EnableVmxInsideSmx;
CpuCapabilities->LtTxtEnabled = CpuCapabilities->SMXState;
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &Ecx.Uint32, NULL);
CpuCapabilities->LtTxtCap = Ecx.Bits.SMX;
CpuCapabilities->VTxCap = Ecx.Bits.VMX;
}
/**
Updates MEBx version. Deprecated
@param[out] MebxVersion Legacy MEBx version
**/
VOID
UpdateMebxVersion (
OUT MEBX_VER *MebxVersion
)
{
EFI_STATUS Status;
MEBX_PROTOCOL *MebxProtocol;
Status = gBS->LocateProtocol (&gMebxProtocolGuid, NULL, (VOID**) &MebxProtocol);
if (!EFI_ERROR (Status)) {
MebxVersion->Major = MebxProtocol->MebxVersion.Major;
MebxVersion->Minor = MebxProtocol->MebxVersion.Minor;
MebxVersion->Hotfix = MebxProtocol->MebxVersion.Hotfix;
MebxVersion->Build = MebxProtocol->MebxVersion.Build;
}
}
/**
Updates PCH capabilities.
@param[out] PchCapabilities PCH Capabilities
**/
VOID
UpdatePchCapabilities (
OUT PCH_CAP *PchCapabilities
)
{
PchCapabilities->FunctionNumber = LpcFuncNumber ();
PchCapabilities->DeviceNumber = LpcDevNumber ();
PchCapabilities->BusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
PchCapabilities->DeviceID = PciSegmentRead16 (LpcPciCfgBase () + PCI_DEVICE_ID_OFFSET);
}
/**
Updates ME platform capabilites from the MBP.
@param[out] MeCapabilities ME Capabilities
**/
VOID
UpdateMeCapabilities (
OUT ME_CAP *MeCapabilities
)
{
ME_BIOS_PAYLOAD_HOB *MbpHob;
MbpHob = NULL;
//
// Get Mbp Data HOB
//
MbpHob = GetFirstGuidHob (&gMeBiosPayloadHobGuid);
if (MbpHob == NULL) {
DEBUG ((DEBUG_ERROR, "HeciGetMeFwInfo: No MBP Data Protocol available\n"));
return;
}
MeCapabilities->MeEnabled = 1;
MeCapabilities->IntelAmtEnabled = MbpHob->MeBiosPayload.FwFeaturesState.FwFeatures.Fields.FullMng;
MeCapabilities->IntelKVM = MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.KVM;
MeCapabilities->IntelKVMEnabled = MbpHob->MeBiosPayload.FwFeaturesState.FwFeatures.Fields.KVM;
switch (MbpHob->MeBiosPayload.FwPlatType.RuleData.Fields.PlatformBrand) {
case IntelAmtBrand:
MeCapabilities->IntelAmtFw = 1;
MeCapabilities->LocalWakeupTimer = 1;
break;
case IntelStandardManageabilityBrand:
MeCapabilities->IntelAmtFwStandard = 1;
break;
}
MeCapabilities->MeMajorVer = MbpHob->MeBiosPayload.FwVersionName.MajorVersion;
MeCapabilities->MeMinorVer = MbpHob->MeBiosPayload.FwVersionName.MinorVersion;
MeCapabilities->MeBuildNo = MbpHob->MeBiosPayload.FwVersionName.BuildVersion;
MeCapabilities->MeHotFixNo = MbpHob->MeBiosPayload.FwVersionName.HotfixVersion;
}
/**
Updates Network device.
@param[out] NetworkDevice Network Device
**/
VOID
UpdateNetworkDevice (
OUT NETWORK_DEV *NetworkDevice
)
{
NetworkDevice->FunctionNumber = GbeFuncNumber (); // [2:0] PCI Device Function Number of Wired LAN
NetworkDevice->DeviceNumber = GbeDevNumber (); // [7:3] PCI Device Device Number of Wired LAN
NetworkDevice->BusNumber = DEFAULT_PCI_BUS_NUMBER_PCH; // [15:8] PCI Device Bus Number of Wired LAN
NetworkDevice->DeviceID = PciSegmentRead16 (GbePciCfgBase () + PCI_DEVICE_ID_OFFSET);
}
/**
Updates BIOS capabilities.
@param[out] BiosCapabilities BIOS Capabilities
**/
VOID
UpdateBiosCapabilities (
OUT BIOS_CAP *BiosCapabilities
)
{
EFI_STATUS Status;
SETUP_CPU_FEATURES SetupCpuFeatures;
SETUP_VOLATILE_DATA SetupVolatileData;
UINTN VariableSize;
TRUSTED_DEVICE_SETUP_PROTOCOL *TrustedDeviceSetupProtocol;
VariableSize = sizeof (SETUP_CPU_FEATURES);
Status = gRT->GetVariable (
L"SetupCpuFeatures",
&gSetupVariableGuid,
NULL,
&VariableSize,
&SetupCpuFeatures
);
if (!EFI_ERROR (Status)) {
BiosCapabilities->VTxSupport = !!SetupCpuFeatures.VTAvailable;
BiosCapabilities->TxtSupport = !!SetupCpuFeatures.TXTAvailable;
}
Status = gBS->LocateProtocol (&gTrustedDeviceSetupMainProtocolGuid, NULL, (VOID**) &TrustedDeviceSetupProtocol);
if (!EFI_ERROR (Status)) {
TrustedDeviceSetupProtocol->SmbiosTrustedDeviceSetupCapabilities ((VOID *) BiosCapabilities);
}
VariableSize = sizeof (SETUP_VOLATILE_DATA);
Status = gRT->GetVariable (
L"SetupVolatileData",
&gSetupVariableGuid,
NULL,
&VariableSize,
&SetupVolatileData
);
if (!EFI_ERROR (Status)) {
BiosCapabilities->VTdSupport = !!SetupVolatileData.VTdAvailable;
}
}
/**
This function makes boot time changes to the content of the SMBIOS type 131.
@retval EFI_SUCCESS Record was updated successfully.
@retval EFI_NOT_FOUND HECI protocol or SMBIOS type 131 record cannot be found.
**/
EFI_STATUS
EFIAPI
UpdateSmbios131 (
VOID
)
{
EFI_STATUS Status;
EFI_SMBIOS_TABLE_HEADER *Record;
SMBIOS_TABLE_TYPE131 *SmbiosTableType131Data;
DEBUG ((DEBUG_INFO, "%a() entry \n", __FUNCTION__));
Status = GetSmbiosTable (MESMBIOS_TYPE_131, &Record);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
SmbiosTableType131Data = (SMBIOS_TABLE_TYPE131*) Record;
UpdateCpuCapabilities (&SmbiosTableType131Data->CpuCapabilities);
UpdateMebxVersion (&SmbiosTableType131Data->MebxVersion);
UpdatePchCapabilities (&SmbiosTableType131Data->PchCapabilities);
UpdateMeCapabilities (&SmbiosTableType131Data->MeCapabilities);
UpdateNetworkDevice (&SmbiosTableType131Data->NetworkDevice);
UpdateBiosCapabilities (&SmbiosTableType131Data->BiosCapabilities);
return EFI_SUCCESS;
}
/**
This is the standard EFI driver entrypoint to install protocol to update ME SMBIOS tables from silicon package.
@param[in] ImageHandle Handle for the image of this driver
@param[in] SystemTable Pointer to the EFI System Table
@retval EFI_SUCCESS The protocol interface was installed.
@retval EFI_OUT_OF_RESOURCES Space for a new handle could not be allocated.
@retval EFI_INVALID_PARAMETER Handle or Protocol is NULL.
**/
EFI_STATUS
EFIAPI
MeSmbiosUpdateConfigEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gMeSmbiosTablesUpdateProtocolGuid,
EFI_NATIVE_INTERFACE,
&mMeSmbiosTablesUpdate
);
ASSERT_EFI_ERROR (Status);
return Status;
}