//***************************************************************************** // Copyright (c) 2012 - 2021, Hefei LCFC Information Technology Co.Ltd. // And/or its affiliates. All rights reserved. // Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL. // Use is subject to license terms. //****************************************************************************** /*++ Abstract: This application is used for battery related function control and test, which will communicate with BIOS by WMI, BIOS bypass command to EC to implement the function. History: Date Name Version Change Notes 2021.03.04 Steven Wang V1.00 Initial release. Module Name: LfcBatteryCtrlTool.cpp */ #include "stdafx.h" //#define _WIN32_DCOM #include using namespace std; #include #include #include // for wcstombs #include // for towlower #include // for wchar_t #include #include #include #include // used for check single option bool LibCheckOption(std::vector ¶m, const std::string &opt, bool exist = true); // option has one followed param bool LibCheckOneParameter(std::vector ¶m, const std::string &opt, std::string &val, bool exist = true); IWbemServices *pSvc = NULL; #pragma comment(lib, "wbemuuid.lib") ULONG returnvalue; VOID HeaderMsg(VOID) { printf("======================================================================\n"); printf("Name : Battery Control Tool \n"); printf("Version : 1.00 \n"); printf("Date : %s\n", __DATE__); printf("Author : LCFC RDC SSHF - BIOS Team \n"); printf("Copyright (c) 2012 - 2021, Hefei LCFC Information Technology Co.Ltd. \n"); printf("======================================================================\n\n"); } // exist true, this option must exist, if not exist, return false. bool LibCheckOption(std::vector ¶m, const std::string &opt, bool exist) { auto i = std::find(param.begin(), param.end(), opt); if (i == param.end()) { if (exist) return false; return true; } param.erase(i); return true; } // if no one followed param, false bool LibCheckOneParameter(std::vector ¶m, const std::string &opt, std::string &val, bool exist) { auto i = std::find(param.begin(), param.end(), opt); if (i == param.end()) { if (exist) return false; return true; } if ((i + 1) == param.end()) return false; val = *(i + 1); param.erase(i + 1); param.erase(i); return true; } int WmiMethodUlong (ULONG valIn) { HRESULT hres; ULONG result = FALSE; CComPtr pClassObj = NULL; CComPtr pInClass = NULL; CComPtr pInParam = NULL; CComPtr ppiWmiOutUlong = NULL; //====================================================== // SetULong "UINT32" type input parameter preparation //====================================================== //Step0: 初始化 VARIANT; VARIANT arrVarInArg; VariantInit(&arrVarInArg); //Step1: 封装到VARIANT内: //@@BUGBUG: The data type should be VT_UI4(uint32), but here we must use int32 // or will cause LfcWmiEcControlUlong put input parameter failed! error=0x80041005 // WBEM_E_TYPE_MISMATCH V_VT(&arrVarInArg) = VT_I4; V_I4(&arrVarInArg) = valIn; //Input ulong parameter //====================================================== // Exectute LfcWmiEcControlUlong Method //====================================================== //Step1: Get Lfc_Tools_Wmi_Service object hres = pSvc->GetObject(L"Lfc_Tools_Wmi_Service", 0, NULL, &pClassObj, NULL); if (FAILED(hres)) { printf("Failed to get Lfc_Tools_Wmi_Service object: %x\n", hres); goto ErrorExit; } //Step2: Get LfcWmiEcControlUlong method from Lfc_Tools_Wmi_Service class hres = pClassObj->GetMethod(L"LfcWmiEcControlUlong", 0, &pInClass, NULL); if (WBEM_S_NO_ERROR == hres) { //printf("WMI:Get LfcWmiEcControlUlong method successfully\n"); if (pInClass != NULL) { //create instance copy if(WBEM_S_NO_ERROR == (hres=pInClass->SpawnInstance(0, &pInParam)) ) { //Step3: Put parameter to LfcWmiEcControlUlong input parameter hres = pInParam->Put(L"parameter", 0, &arrVarInArg, 0); if (WBEM_S_NO_ERROR != hres) { printf("WMI:ExecMethodWMI LfcWmiEcControlUlong put input parameter failed! error=0x%x\n", hres); goto ErrorExit; // Put failed, check the properties and their types // WBEM_E_TYPE_MISMATCH } } } //Step4: Everything is ok, now execute the "LfcWmiEcControlUlong" method hres = pSvc->ExecMethod(L"Lfc_Tools_Wmi_Service.InstanceName='ACPI\\PNP0C14\\WM00_0'",L"LfcWmiEcControlUlong",0, NULL, pInParam, &ppiWmiOutUlong, NULL); if (WBEM_S_NO_ERROR != hres) { printf("WMI:ExecMethodWMI LfcWmiEcControlUlong Fail! error=0x%x\n", hres); goto ErrorExit; } //Great! Method run successfully. result = TRUE; VARIANT ReturnVar; VariantInit(&ReturnVar); hres = ppiWmiOutUlong->Get(L"return", 0, &ReturnVar, NULL,0); if (WBEM_S_NO_ERROR != hres) { printf("WMI:ExecMethodWMI Get return of LfcWmiEcControlUlong failed! error=0x%x\n", hres); VariantClear(&ReturnVar); } returnvalue= V_I4(&ReturnVar); printf("Return value = 0X%lX\n", returnvalue); if((returnvalue == 0x00)||(returnvalue == 0xFA)){ //0xFA: unsupport EC command result = FALSE; } if((valIn == 0x01030601)||(valIn == 0x02040601)){//fan speed maybe is 0 result = TRUE; } } else { printf("WMI:Get LfcWmiEcControlUlong method failed error=0x%x\n", hres); goto ErrorExit; } // Cleanup // ======== ErrorExit: VariantClear(&arrVarInArg); if (pClassObj) { pClassObj.Release(); pClassObj = NULL; } if (pInClass) { pInClass.Release(); pInClass = NULL; } if (pInParam) { pInParam.Release(); pInParam = NULL; } if (ppiWmiOutUlong) { ppiWmiOutUlong.Release(); ppiWmiOutUlong = NULL; } if (result == TRUE) { return TRUE; } else { return FALSE; } } VOID DisplayHelp () { printf("\ -help or -? :This help screen\n\ -command 0xBBAA :This is manual EC command, only for 0xEF command\n\ the data BB is extend data, the AA is the main data\n\ -shipmode -en :enter battery ship mode\n\ -covsmode -en :enter battery coversation mode\n\ -covsmode -dis :exit battery coversation mode \n\ -covsmode -check :check battery coversation mode status\n\ -bfudata -clear :Clear battery first use data \n\ -bfudata -check :check battery first use data status\n\ -powerled -on :set power led on\n\ -chargeled -on :set charge led on \n\ -dischargeled -on :set discharge led on \n\ -numlockled -on :set number lock led on \n\ -fnlockled -on :set FN lock led on \n\ -capslockled -on :set caps lock led on \n\ -kbblled -on :set keyboard backlight led on \n\ -fp1led -on :set fingerprint 1 led on \n\ -fp2led -on :set fingerprint 2 led on \n\ -allledoff -on :disable all led\n\ -allledback -on :return the LED control right back to EC\n\ -cputemp -get :get the CPU temperature\n\ -gputemp -get :get the GPU temperature\n\ -setfan1speed dd :set the fan1 speed, dd is a decimal number, the fan speed will be set to dd*100rpm \n\ -setfan2speed dd :set the fan2 speed, dd is a decimal number, the fan speed will be set to dd*100rpm \n\ -fan1speed -get :get the fan1 speed \n\ -fan2speed -get :get the fan2 speed \n\ -fanauto -set :set the fan speed to auto speed\n\ \n"); } int _tmain(int argc, _TCHAR* argv[]) { std::vector paraIn; HeaderMsg(); //display help message if(argc -1 == 1){ string string3 = argv[1]; if((string3.compare("-help") == 0)||(string3.compare("-?") == 0)||(string3.compare("/?") == 0)||(string3.compare("/help") == 0)){ DisplayHelp (); return TRUE; } } if((argc -1 == 0)){ DisplayHelp (); return TRUE; } if (argc != 3) { printf("Input parameter error!\n\n"); return FALSE; } for (int i = 0; i < argc; i++) { paraIn.push_back(std::string(argv[i])); } HRESULT hres; //Get current time time_t now = time(0); // 把 now 转换为字符串形式 char* dt = ctime(&now); printf("Current time is %s\n", dt); // Step 1: -------------------------------------------------- // Initialize COM. ------------------------------------------ hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { printf("Failed to initialize COM library. Error code = 0x%x\n", hres); return FALSE; // Program has failed. } // Step 2: -------------------------------------------------- // Set general COM security levels -------------------------- hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { printf("Failed to initialize security. Error code = 0x%x\n",hres); CoUninitialize(); return FALSE; // Program has failed. } // Step 3: --------------------------------------------------- // Obtain the initial locator to WMI ------------------------- IWbemLocator *pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc); if (FAILED(hres)) { printf("Failed to create IWbemLocator object.Err code = 0x%x\n", hres); CoUninitialize(); return FALSE; // Program has failed. } // Step 4: ----------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method // Connect to the root\cimv2 namespace with // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\WMI"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (for example, Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if (FAILED(hres)) { printf("Could not connect. Error code = 0x%x\n",hres); pLoc->Release(); CoUninitialize(); return FALSE; // Program has failed. } // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { printf("Could not set proxy blanket. Error code = 0x%x\n",hres); pSvc->Release(); pLoc->Release(); CoUninitialize(); return FALSE; // Program has failed. } string string1 = argv[1]; string string2 = argv[2]; //printf("Argument 1 is %s.\n", argv[1]); //printf("Argument 2 is %s.\n", argv[2]); //Byte0: SMI main function (Low byte) //Byte1: Item //Byte2: Action //Byte3: Payload (High byte) //Ship mode if(string1.compare("-shipmode") == 0){ if(string2.compare("-en") == 0){ printf("Enter ship mode start ...\n"); if(WmiMethodUlong(0x00010101) == TRUE) { printf("Enter ship mode success...\n\n"); } } else { printf("Ship mode don't support %s command\n\n", argv[2]); } } //conversation mode if(string1.compare("-covsmode") == 0){ if(string2.compare("-en") == 0){ printf("Enter conversation mode start ...\n"); if(WmiMethodUlong(0x00010201) == TRUE) { printf("Enter conversation mode success...\n\n"); } } else if(string2.compare("-dis") == 0){ printf("Exit conversation mode start ...\n"); if(WmiMethodUlong(0x00000201) == TRUE) { printf("Exit conversation mode success...\n\n"); } } else if(string2.compare("-check") == 0){ printf("check conversation mode start ...\n"); if(WmiMethodUlong(0x00020201) == TRUE) { printf("Already in conversation mode...\n\n"); }else{ printf("Not in conversation mode...\n\n"); } }else { printf("Input wrong parameter!\n\n"); } } //first use data if(string1.compare("-bfudata") == 0){ if(string2.compare("-clear") == 0){ printf("Clear first use data start ...\n"); if(WmiMethodUlong(0x00010301) == TRUE) { printf("Clear first use data success...\n\n"); } } else if(string2.compare("-check") == 0){ printf("check first use data start ...\n"); if(WmiMethodUlong(0x00000301) == TRUE) { printf("First use data not set...\n\n"); } else { printf("First use data already setting...\n\n"); } } else { printf("Input wrong parameter!\n\n"); } } //manual command if(string1.compare("-command") == 0){ ULONG EcCommand = strtol (argv[2],NULL,16); //get argv2 to 16hex if(EcCommand > 0xffff){ printf ("Input wrong data!\n"); goto ExitService; } //printf ("data1 is: %x\n", EcCommand); EcCommand = EcCommand << 16; //printf ("data2 is: %x\n", EcCommand); EcCommand = EcCommand | 0x0000EF01; //printf ("data is: %x\n", EcCommand); //WmiMethodUlong(EcCommand); if(WmiMethodUlong(EcCommand) == TRUE){ printf("The command 0x%08X success...\n\n", EcCommand); } else { printf("Unsupport command...\n\n"); } } // Led command if(string1.compare("-powerled") == 0){ if(string2.compare("-on") == 0){ printf("enable power led on start ...\n"); if(WmiMethodUlong(0x00010401) == TRUE){ printf("enable power led on success ...\n"); }else { printf("enable power led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-chargeled") == 0){ if(string2.compare("-on") == 0){ printf("charge led on start ...\n"); if(WmiMethodUlong(0x00020401) == TRUE){ printf("enable charge led on success ...\n"); }else { printf("enable charge led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-dischargeled") == 0){ if(string2.compare("-on") == 0){ printf("dischargeled led on start ...\n"); if(WmiMethodUlong(0x00030401) == TRUE){ printf("enable dischargeled led on success ...\n"); }else { printf("enable dischargeled led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-numlockled") == 0){ if(string2.compare("-on") == 0){ printf("numlockled led on start ...\n"); if(WmiMethodUlong(0x00040401) == TRUE){ printf("enable numlockled led on success ...\n"); }else { printf("enable numlockled led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-capslockled") == 0){ if(string2.compare("-on") == 0){ printf("capslockled led on start ...\n"); if(WmiMethodUlong(0x00050401) == TRUE){ printf("enable capslockled led on success ...\n"); }else { printf("enable capslockled led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-kbblled") == 0){ if(string2.compare("-on") == 0){ printf("keyboard backlight led on start ...\n"); if(WmiMethodUlong(0x00060401) == TRUE){ printf("enable keyboard backlight led on success ...\n"); }else { printf("enable keyboard backlight led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-fp1led") == 0){ if(string2.compare("-on") == 0){ printf("fingerprint 1 led on start ...\n"); if(WmiMethodUlong(0x00070401) == TRUE){ printf("enable fingerprint 1 led on success ...\n"); }else { printf("enable fingerprint 1 led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-fp2led") == 0){ if(string2.compare("-on") == 0){ printf("fingerprint 2 led on start ...\n"); if(WmiMethodUlong(0x00080401) == TRUE){ printf("enable fingerprint 2 led on success ...\n"); }else { printf("enable fingerprint 2 led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-fnlockled") == 0){ if(string2.compare("-on") == 0){ printf("Fn lock led on start ...\n"); if(WmiMethodUlong(0x00090401) == TRUE){ printf("Fn lock led on success ...\n"); }else { printf("Fn lock led on fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-allledoff") == 0){ if(string2.compare("-on") == 0){ printf("All led off start ...\n"); if(WmiMethodUlong(0x000A0401) == TRUE){ printf("All led off success ...\n"); }else { printf("All led off fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-allledback") == 0){ if(string2.compare("-on") == 0){ printf("All led control right back to EC start ...\n"); if(WmiMethodUlong(0x000B0401) == TRUE){ printf("All led control right back to EC success ...\n"); }else { printf("All led control right back to EC fail ...\n"); } } else { printf("Input wrong parameter!\n\n"); } } //get the CPU/GPU temp if(string1.compare("-cputemp") == 0){ if(string2.compare("-get") == 0){ if(WmiMethodUlong(0x01010501) == TRUE){ printf("current CPU temperature is %d degree\n", returnvalue); }else { printf("Get CPU temperature fail ...\n"); } }else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-gputemp") == 0){ if(string2.compare("-get") == 0){ if(WmiMethodUlong(0x02020501) == TRUE){ printf("current GPU temperature is %d degree\n", returnvalue); }else { printf("Get GPU temperature fail ...\n"); } }else { printf("Input wrong parameter!\n\n"); } } //get/set fan speed if(string1.compare("-setfan1speed") == 0){ ULONG EcCommand = strtol (argv[2],NULL,10); //get argv2 to 10d if(EcCommand > 0xff){ printf ("Input wrong data,the max value is 255, the speed is value*100RPM\n"); goto ExitService; } //printf ("data1 is: %d\n", EcCommand); //change the input value from dec to hex int val1 = EcCommand/16; //取商数 int val2 = EcCommand%16; //取余数 val1 = val1<<28; val2 = val2<<24; val1 = val1+val2; //printf ("data2 is: %x\n", EcCommand); val1 = val1 | 0x00010601; //printf ("data1 is: %x\n", val1); //printf ("data is: %x\n", EcCommand); if(WmiMethodUlong(val1) == TRUE){ printf("set the fan1 speed to %d*100rpm success...\n\n", strtol (argv[2],NULL,10)); } else { printf("Unsupport command...\n\n"); } } if(string1.compare("-setfan2speed") == 0){ ULONG EcCommand = strtol (argv[2],NULL,10); //get argv2 to 10dec if(EcCommand > 0xff){ printf ("Input wrong data,the max value is 255, the speed is value*100RPM\n"); goto ExitService; } //printf ("data1 is: %x\n", EcCommand); //change the input value from dec to hex int val1 = EcCommand/16; //取商数 int val2 = EcCommand%16; //取余数 val1 = val1<<28; val2 = val2<<24; val1 = val1+val2; //printf ("data2 is: %x\n", EcCommand); val1 = val1 | 0x00020601; //printf ("data is: %x\n", EcCommand); if(WmiMethodUlong(val1) == TRUE){ printf("set the fan2 speed to %d*100 rpm success...\n\n", strtol (argv[2],NULL,10)); } else { printf("Unsupport command...\n\n"); } } if(string1.compare("-fan1speed") == 0){ if(string2.compare("-get") == 0){ if(WmiMethodUlong(0x01030601) == TRUE){ returnvalue = returnvalue*100; printf("the fan1 speed is %d rpm\n", returnvalue); }else { printf("get fan1 speed fail ...\n"); } }else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-fan2speed") == 0){ if(string2.compare("-get") == 0){ if(WmiMethodUlong(0x02040601) == TRUE){ returnvalue = returnvalue*100; printf("the fan2 speed is %d rpm\n", returnvalue); }else { printf("get fan2 speed fail ...\n"); } }else { printf("Input wrong parameter!\n\n"); } } if(string1.compare("-fanauto") == 0){ if(string2.compare("-set") == 0){ if(WmiMethodUlong(0x00050601) == TRUE){ printf("return the fan speed to auto\n"); }else { printf("return the fan speed to auto fail ...\n"); } }else { printf("Input wrong parameter!\n\n"); } } /* if (LibCheckOption(paraIn, "-shipmode")) { printf("Enter shipmode start ...\n"); //Byte0: SMI main function (Low byte) //Byte1: Item //Byte2: Action //Byte3: Payload (High byte) if(WmiMethodUlong(0x00010101) == TRUE) { printf("Enter shipmode success...\n"); } } */ ExitService: pSvc->Release(); pLoc->Release(); CoUninitialize(); return TRUE; }