/** @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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if FixedPcdGetBool(PcdRemotePlatformEraseSupport) == 1 #include #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; }