/** @file ;****************************************************************************** ;* Copyright (c) 2018, 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 "WmiSetupUnderOsSmm.h" /** WMI set boot order. @param ParameterValue A pointer to the parameter value. @param BootOrder A pointer to boot order. @param L05BootOrderCount Count of L05 boot order. @param L05WmiBootDescription A pointer to the L05 WMI boot description. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS WmiSetBootOrder ( CHAR8 *ParameterValue, UINT16 *BootOrder, UINT16 L05BootOrderCount, L05_WMI_BOOT_DESCRIPTION *L05WmiBootDescription ) { EFI_STATUS Status; UINT16 *TempBootOrder; UINTN BufferOffset; UINTN TempBufferOffset; UINTN Index; UINTN Index2; UINTN BootOrderIndex; UINTN BootOrderCheckSum; UINTN BootOrderCheckSumCount; UINTN VerifyBootOrderCheckSum; UINTN ValueSize; CHAR8 *Ipv4NetworkStr = WMI_L05_PXE_IPV4_STRING; CHAR8 *Ipv6NetworkStr = WMI_L05_PXE_IPV6_STRING; BOOLEAN FindNewNetworkOption; UINTN NewNetworkOptionShift; UINTN NewNetworkOptionIndex; // // Initialization // Status = EFI_SUCCESS; BufferOffset = 0; TempBufferOffset = 0; BootOrderIndex = 0; BootOrderCheckSum = 0; BootOrderCheckSumCount = 0; VerifyBootOrderCheckSum = 0; ValueSize = AsciiStrSize (ParameterValue); FindNewNetworkOption = FALSE; NewNetworkOptionShift = FALSE; NewNetworkOptionIndex = 0; // // Allocate resources // TempBootOrder = AllocateRuntimeZeroPool (sizeof (UINT16) * L05BootOrderCount); if (TempBootOrder == NULL) { return EFI_OUT_OF_RESOURCES; } // // Find Network Option index & set Network Option shift // for (Index = 0; Index < L05BootOrderCount; Index++) { if ((CompareMem (Ipv4NetworkStr, L05WmiBootDescription[Index].BootDescription, AsciiStrSize (Ipv4NetworkStr) - sizeof (CHAR8)) == 0x0) || (CompareMem (Ipv6NetworkStr, L05WmiBootDescription[Index].BootDescription, AsciiStrSize (Ipv6NetworkStr) - sizeof (CHAR8)) == 0x0)) { NewNetworkOptionShift = 1; NewNetworkOptionIndex = Index; break; } } // // Part Boot Order section // for (BufferOffset = 0; BufferOffset < ValueSize; BufferOffset++) { if ((ParameterValue[BufferOffset] != ':') &&(ParameterValue[BufferOffset] != 0)) { continue; } ParameterValue[BufferOffset] = 0; // // Get Boot Order index for setting // Index = AsciiStrDecimalToUintn (&ParameterValue[TempBufferOffset]); // // Count Boot Order value check sum // BootOrderCheckSum += Index; BootOrderCheckSumCount++; // // Transform for index of array // Index--; // // Index shift for merge PXE // Index += (Index > NewNetworkOptionIndex ? NewNetworkOptionShift : 0); // // Check Index is valid // if (Index >= L05BootOrderCount) { Status = EFI_INVALID_PARAMETER; break; } // // Check is NewNetwork Option // if ((CompareMem (Ipv4NetworkStr, L05WmiBootDescription[Index].BootDescription, AsciiStrSize (Ipv4NetworkStr) - sizeof (CHAR8)) == 0x0) || (CompareMem (Ipv6NetworkStr, L05WmiBootDescription[Index].BootDescription, AsciiStrSize (Ipv6NetworkStr) - sizeof (CHAR8)) == 0x0)) { FindNewNetworkOption = TRUE; } // // Sorting Boot Order // for (Index2 = 0; Index2 < (FindNewNetworkOption ? (UINTN) 2 : (UINTN) 1); Index2++) { TempBootOrder[BootOrderIndex] = L05WmiBootDescription[Index + Index2].BootOption; BootOrderIndex++; } TempBufferOffset = BufferOffset; TempBufferOffset++; FindNewNetworkOption = FALSE; Status = EFI_SUCCESS; } // // Check Set BootOrder count is correct // if (BootOrderIndex != L05BootOrderCount) { Status = EFI_INVALID_PARAMETER; } // // Check Set BootOrder value is correct, not repeat. // VerifyBootOrderCheckSum = ((1 + BootOrderCheckSumCount) * BootOrderCheckSumCount) / 2; if (VerifyBootOrderCheckSum != BootOrderCheckSum) { Status = EFI_INVALID_PARAMETER; } if (EFI_ERROR (Status)) { FreePool (TempBootOrder); return Status; } // // When Boot Order change will set Boot Order. // if (CompareMem (BootOrder, TempBootOrder, (sizeof (UINT16) * L05BootOrderCount)) != 0) { CopyMem (BootOrder, TempBootOrder, (sizeof (UINT16) * L05BootOrderCount)); } // // Free resources // FreePool (TempBootOrder); return Status; } /** Set setup value. @param SelectStrListIndex Select string list index. @param ConfigValue A pointer to the config value. @retval EFI_SUCCESS Set setup value successfully. @retval EFI_NO_MAPPING Can't find select value. **/ EFI_STATUS SetSetupValue ( UINTN SelectStrListIndex, CHAR8 *ConfigValue ) { EFI_STATUS Status; UINTN Index; // // Initialization // Status = EFI_SUCCESS; // // Get select value // for (Index = 0; Index < mWmiSelectStrListMap[SelectStrListIndex].SelectStrCount; Index++) { if (AsciiStrCmp (ConfigValue, mWmiSelectStrListMap[SelectStrListIndex].SelectStrList[Index]) == 0) { // // Set select value, when select value different with L05WmiSetupItem. // if (*mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].L05WmiSetupItem != Index) { *mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].L05WmiSetupItem = (UINT8) Index; } break; } } // // Check set config value is valid // if (Index >= mWmiSelectStrListMap[SelectStrListIndex].SelectStrCount) { Status = EFI_NO_MAPPING; } return Status; } /** Extend check for set BIOS setting. @param WmiSetBiosSettingParameter A pointer to the WMI set BIOS setting parameter. @retval EFI_SUCCESS Extend check is successfully. @retval EFI_ACCESS_DENIED Extend check is denied. **/ EFI_STATUS SetBiosSettingExtendCheck ( WMI_SET_BIOS_SETTING_PARAMETER *WmiSetBiosSettingParameter ) { EFI_STATUS Status; Status = EFI_SUCCESS; // // [Lenovo BIOS Setup Design Guide V2.5] // [Configuration] // BIOS Back Flash - WMI Enable Only. // Disable is also avilable when BIOS Administrator password is installed. // if (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == BiosBackFlashType) { if (mAdminPasswordExist) { return EFI_SUCCESS; } if (AsciiStrCmp (WmiSetBiosSettingParameter->Value, "Disable") == 0) { return EFI_ACCESS_DENIED; } } // // [Lenovo BIOS Setup Design Guide V2.7] // [Security] // Device Guard - WMI // when administrator password is installed. // if (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == DeviceGuardType) { if (mAdminPasswordExist) { return EFI_SUCCESS; } else { return EFI_ACCESS_DENIED; } } // // Unselectable for Device Guard // If "Device Guard" is Enabled, below items should be gray out. // if ((mL05WmiSetupItem.L05DeviceGuard == L05_WMI_SETUP_ITEM_ENABLE) && ((mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == IntelVtType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == IntelVtdType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == AmdVType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == SecureBootType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == BootModeType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == EfiBootOrderType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == LegacyBootOrderType) || (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == OsOptimizedDefaultsType))) { return EFI_ACCESS_DENIED; } // // [Lenovo BIOS Setup Design Guide V2.5] // [Security] // Intel (R) SGX Control - If the system is in "Software Controlled(Enabled)" or "Enabled" state, // the request of "Disabled" or "Software Controlled" are rejected. // if (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == IntelSgxType) { // // Allow Intel (R) SGX set to "Enable". // if (AsciiStrCmp (WmiSetBiosSettingParameter->Value, "Enable") == 0) { return EFI_SUCCESS; } // // Not allowed setting when Intel (R) SGX is in "Enable" state. // if (*mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].L05WmiSetupItem == 1) { // mIntelSgxStrList[1]: Enable return EFI_ACCESS_DENIED; } // // Allow Intel (R) SGX set to "Software Controlled(Enabled)". // if ((mIsSgxFeatureCtrlSet) && (AsciiStrCmp (WmiSetBiosSettingParameter->Value, "Software Controlled") == 0)) { return EFI_SUCCESS; } // // Not allowed setting when Intel (R) SGX is in "Software Controlled(Enabled)" state. // if ((mIsSgxFeatureCtrlSet) && (*mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].L05WmiSetupItem == 0)) { // mIntelSgxStrList[0]: Software Controlled return EFI_ACCESS_DENIED; } return EFI_SUCCESS; } // // [Lenovo BIOS Setup Design Guide V2.5] // [Security] // Secure Boot - WMI Enable Only. // if (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType == SecureBootType) { if (AsciiStrCmp (WmiSetBiosSettingParameter->Value, "Disable") == 0) { return EFI_ACCESS_DENIED; } } return Status; } /** Extend setting for switch config type. @param None. @retval EFI_SUCCESS This function execute successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS SwitchConfigExtendSetting ( VOID ) { EFI_STATUS Status; Status = EFI_SUCCESS; // // Extend setting for switch config type // switch (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType) { case DeviceGuardType: // // Intel - Set "Intel Virtualization Technology, Intel VT-d Feature" to Enabled. // AMD - Set "AMD V (TM) Technology" to Enabled. // Common - Set "Secure Boot and Os Optimized Defaults" to Enabled. // Set "Boot Mode" to UEFI. // if (mL05WmiSetupItem.L05DeviceGuard == L05_WMI_SETUP_ITEM_ENABLE) { mL05WmiSetupItem.L05IntelVt = L05_WMI_SETUP_ITEM_ENABLE; mL05WmiSetupItem.L05IntelVtd = L05_WMI_SETUP_ITEM_ENABLE; mL05WmiSetupItem.L05SecureBoot = L05_WMI_SETUP_ITEM_ENABLE; mL05WmiSetupItem.L05OsOptimizedDefault = L05_WMI_SETUP_ITEM_ENABLE; mL05WmiSetupItem.L05BootMode = L05_WMI_BOOT_MODE_UEFI; } break; } return Status; } /** WMI Method for Set BIOS setting - Mapping to WMI class : Lenovo_SetBiosSetting Mapping to ASL method : WMA1 @param None @retval EFI_SUCCESS This function execute successfully. @retval EFI_ACCESS_DENIED WMI input password is invalid. @retval Others An unexpected error occurred. **/ EFI_STATUS EFIAPI WmiSetBiosSettingA1 ( VOID ) { EFI_STATUS Status; UINTN BufferOffset; UINTN TempBufferOffset; CHAR8 SelectStr[L05_WMI_BUFFER_MAX_SIZE]; UINT16 SelectStrLen; UINTN SelectStrListIndex; UINTN SectionCount; WMI_SET_BIOS_SETTING_PARAMETER WmiSetBiosSettingParameter; WMI_CHECK_PASSWORD_PARAMETER WmiCheckPasswordParameter; // // Initialization // Status = EFI_SUCCESS; BufferOffset = 0; ZeroMem (&WmiSetBiosSettingParameter, sizeof (WMI_SET_BIOS_SETTING_PARAMETER)); ZeroMem (&WmiCheckPasswordParameter, sizeof (WMI_CHECK_PASSWORD_PARAMETER)); // // Analyze WMI input buffer // Status = AnalyzeWmiInputBuffer (SelectStr, &SelectStrLen, &mL05GlobalNVSArea->L05WmiItem, &SelectStrListIndex); if (EFI_ERROR (Status)) { return Status; } // // Check L05 WMI Setup Item is Valid // if (*mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].L05WmiSetupItemValid == FALSE) { return EFI_UNSUPPORTED; } // // Check SCU access level is Read Only // if (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ScuAccessLevel == ReadOnly) { return EFI_UNSUPPORTED; } // // Part section // SectionCount = 0; TempBufferOffset = 0; for (BufferOffset = 0; BufferOffset < mL05GlobalNVSArea->L05WmiBufferLen; BufferOffset++) { if ((mL05GlobalNVSArea->L05WmiBuffer[BufferOffset] != ',') &&(mL05GlobalNVSArea->L05WmiBuffer[BufferOffset] != ';')) { continue; } mL05GlobalNVSArea->L05WmiBuffer[BufferOffset] = 0; switch (SectionCount) { case SetBiosSettingItem: WmiSetBiosSettingParameter.Item = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset]; break; case SetBiosSettingValue: WmiSetBiosSettingParameter.Value = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset]; break; case SetBiosSettingPassword: WmiCheckPasswordParameter.Password = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset]; break; case SetBiosSettingPasswordEncoding: WmiCheckPasswordParameter.PasswordEncodingStr = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset]; break; case SetBiosSettingPasswordLanguage: WmiCheckPasswordParameter.PasswordLanguageStr = &mL05GlobalNVSArea->L05WmiBuffer[TempBufferOffset]; break; } TempBufferOffset = BufferOffset; TempBufferOffset++; SectionCount++; } switch (SectionCount) { case SetBiosSettingWithoutPassword: // // [Lenovo BIOS Setup using WMI Deployment Guide - Third Edition (February 2016)] // Password Authentication: // If a supervisor password is already set, you must specify that supervisor password before you can change any // BIOS settings. // if (mAdminPasswordExist) { Status = EFI_ACCESS_DENIED; return Status; } case SetBiosSettingWithPassword: // // When admin password exist need to check password // if (mAdminPasswordExist) { Status = WmiCheckAdminPassword ( WmiCheckPasswordParameter.Password, WmiCheckPasswordParameter.PasswordEncodingStr, WmiCheckPasswordParameter.PasswordLanguageStr ); if (EFI_ERROR (Status)) { return Status; } } // // Extend check for set BIOS setting. // Status = SetBiosSettingExtendCheck (&WmiSetBiosSettingParameter); if (EFI_ERROR (Status)) { return Status; } if (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType < SwitchConfigTypeMax) { // // Switch config type to get config value // Status = GetConfigValue (); if (EFI_ERROR (Status)) { return Status; } // // Set setup value // Status = SetSetupValue (SelectStrListIndex, WmiSetBiosSettingParameter.Value); if (EFI_ERROR (Status)) { return Status; } // // Extend setting for switch config type. // Status = SwitchConfigExtendSetting (); if (EFI_ERROR (Status)) { return Status; } } else { // // Special type to set config value // Status = EFI_INVALID_PARAMETER; switch (mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].ConfigDataType) { case ClearUserPasswordType: case ClearIntelPttKeyType: case ClearAmdPspKeyType: case ResetToSetupModeType: case RestoreFactoryKeysType: *mWmiBiosConfigEnumMap[mL05GlobalNVSArea->L05WmiItem].L05WmiSetupItem = TRUE; Status = EFI_SUCCESS; break; case EfiBootOrderType: Status = WmiSetBootOrder ( WmiSetBiosSettingParameter.Value, mL05WmiSetupItem.L05EfiBootOrder, mL05WmiSetupItem.L05EfiBootOrderCount, mL05WmiSetupItem.L05WmiEfiBootDescription ); break; case LegacyBootOrderType: Status = WmiSetBootOrder ( WmiSetBiosSettingParameter.Value, mL05WmiSetupItem.L05LegacyBootOrder, mL05WmiSetupItem.L05LegacyBootOrderCount, mL05WmiSetupItem.L05WmiLegacyBootDescription ); break; default: return EFI_UNSUPPORTED; } } break; default: Status = EFI_UNSUPPORTED; } if (EFI_ERROR (Status)) { return Status; } // // Clean WMI buffer // ZeroMem (mL05GlobalNVSArea->L05WmiBuffer, L05_WMI_BUFFER_MAX_SIZE); return Status; }