alder_lake_bios/Lcfc/LfcPkg/LfcWmi/Tools/LfcBatteryCtrlTool/LfcBatteryCtrlTool.cpp

742 lines
23 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//*****************************************************************************
// 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 <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#include <stdlib.h> // for wcstombs
#include <wctype.h> // for towlower
#include <wchar.h> // for wchar_t
#include <string>
#include <vector>
#include <sstream>
#include <ctime>
// used for check single option
bool LibCheckOption(std::vector<std::string> &param, const std::string &opt, bool exist = true);
// option has one followed param
bool LibCheckOneParameter(std::vector<std::string> &param, 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<std::string> &param, 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<std::string> &param, 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<IWbemClassObject> pClassObj = NULL;
CComPtr<IWbemClassObject> pInClass = NULL;
CComPtr<IWbemClassObject> pInParam = NULL;
CComPtr<IWbemClassObject> ppiWmiOutUlong = NULL;
//======================================================
// SetULong "UINT32" type input parameter preparation
//======================================================
//Step0: <20><>ʼ<EFBFBD><CABC> VARIANT;
VARIANT arrVarInArg;
VariantInit(&arrVarInArg);
//Step1: <20><>װ<EFBFBD><D7B0>VARIANT<4E>ڣ<EFBFBD>
//@@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<std::string> 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);
// <20><> now ת<><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ʽ
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; //ȡ<><C8A1><EFBFBD><EFBFBD>
int val2 = EcCommand%16; //ȡ<><C8A1><EFBFBD><EFBFBD>
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; //ȡ<><C8A1><EFBFBD><EFBFBD>
int val2 = EcCommand%16; //ȡ<><C8A1><EFBFBD><EFBFBD>
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;
}