diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-07-06 18:04:32 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-07-06 18:04:32 +0200 |
commit | a7f89980e5b3f4b9a74c70dbc5ffe8aabd28be28 (patch) | |
tree | 41c4deec1fdfbafd7821b4ca7a9772ac0abd92f5 /util/ipmims.cpp |
Imported Upstream version 2.9.3upstream/2.9.3
Diffstat (limited to 'util/ipmims.cpp')
-rw-r--r-- | util/ipmims.cpp | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/util/ipmims.cpp b/util/ipmims.cpp new file mode 100644 index 0000000..2ba0611 --- /dev/null +++ b/util/ipmims.cpp @@ -0,0 +1,638 @@ +/*M* +// $Workfile: ipmims.cpp $ +// $Revision: 1.0 $ +// $Modtime: 08 Sep 2008 13:31:14 $ +// $Author: arcress at users.sourceforge.net $ +// +// This implements support for the Microsoft Windows 2003 R2 IPMI driver. +// Note that this should be compiled with /TP (as C++). +// +// 09/08/08 ARCress - created. +// 04/27/11 Jay Krell - fixed WIN64-unsafe logic +// 09/30/13 ARCress - fixed Win2012 x64 SafeArrayDestroy fault +// + *M*/ +/*----------------------------------------------------------------------* +The BSD License + +Copyright (c) 2008, Intel Corporation +Copyright (c) 2009 Kontron America, Inc. +Copyright (c) 2013 Andy Cress <arcress at users.sourceforge.net> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a.. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b.. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + c.. Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *----------------------------------------------------------------------*/ + +#ifdef WIN32 +/* Microsoft IPMI drver is only valid in Windows */ +#define _WIN32_DCOM +#pragma once +#include <windows.h> +#include <stdio.h> +#include <iostream> //deprecated iostream.h +#include <Objbase.h> //ole32.lib +#include <comutil.h> +#include <Wbemcli.h> + +#ifdef ALONE +#define uchar unsigned char +#define ushort unsigned short +#define ulong unsigned long +#else +#include "ipmicmd.h" +extern "C" { extern ipmi_cmd_t ipmi_cmds[NCMDS]; } +#endif +static char fmsopen = 0; +static char fdebugms = 0; +static IWbemLocator *pLoc = 0; +static IWbemServices *pSvc = 0; +static IWbemClassObject* pClass = NULL; +static IEnumWbemClassObject* pEnumerator = NULL; +static IWbemClassObject* pInstance = NULL; +static VARIANT varPath; +#define NVAR 32 +/* Wbem error return codes, returned by WMI */ +#ifdef RES_ALL +#define NRES 82 +#else +#define NRES 10 +#endif +static struct { char *desc; int val; } res_list[NRES] = { +{"WBEM_E_FAILED", 0x80041001 }, +{"WBEM_E_NOT_FOUND", 0x80041002 }, +{"WBEM_E_ACCESS_DENIED", 0x80041003 }, +{"WBEM_E_PROVIDER_FAILURE", 0x80041004 }, +{"WBEM_E_TYPE_MISMATCH", 0x80041005 }, +{"WBEM_E_OUT_OF_MEMORY", 0x80041006 }, +{"WBEM_E_INVALID_CONTEXT", 0x80041007 }, +{"WBEM_E_INVALID_PARAMETER", 0x80041008 }, +{"WBEM_E_NOT_AVAILABLE", 0x80041009 }, +{"WBEM_E_CRITICAL_ERROR", 0x8004100A } +#ifdef RES_ALL +, +{"WBEM_E_CRITICAL_ERROR", 0x8004100A } , +{"WBEM_E_INVALID_STREAM", 0x8004100B }, +{"WBEM_E_NOT_SUPPORTED", 0x8004100C }, +{"WBEM_E_INVALID_SUPERCLASS", 0x8004100D }, +{"WBEM_E_INVALID_NAMESPACE", 0x8004100E }, +{"WBEM_E_INVALID_OBJECT", 0x8004100F }, +{"WBEM_E_INVALID_CLASS", 0x80041010 }, +{"WBEM_E_PROVIDER_NOT_FOUND", 0x80041011 }, +{"WBEM_E_INVALID_PROVIDER_REGISTRATION", 0x80041012 }, +{"WBEM_E_PROVIDER_LOAD_FAILURE", 0x80041013 }, +{"WBEM_E_INITIALIZATION_FAILURE", 0x80041014 }, +{"WBEM_E_TRANSPORT_FAILURE", 0x80041015 }, +{"WBEM_E_INVALID_OPERATION", 0x80041016 }, +{"WBEM_E_INVALID_QUERY", 0x80041017 }, +{"WBEM_E_INVALID_QUERY_TYPE", 0x80041018 }, +{"WBEM_E_ALREADY_EXISTS", 0x80041019 }, +{"WBEM_E_OVERRIDE_NOT_ALLOWED", 0x8004101A }, +{"WBEM_E_PROPAGATED_QUALIFIER", 0x8004101B }, +{"WBEM_E_PROPAGATED_PROPERTY", 0x8004101C }, +{"WBEM_E_UNEXPECTED", 0x8004101D }, +{"WBEM_E_ILLEGAL_OPERATION", 0x8004101E }, +{"WBEM_E_CANNOT_BE_KEY", 0x8004101F }, +{"WBEM_E_INCOMPLETE_CLASS", 0x80041020 }, +{"WBEM_E_INVALID_SYNTAX", 0x80041021 }, +{"WBEM_E_NONDECORATED_OBJECT", 0x80041022 }, +{"WBEM_E_READ_ONLY", 0x80041023 }, +{"WBEM_E_PROVIDER_NOT_CAPABLE", 0x80041024 }, +{"WBEM_E_CLASS_HAS_CHILDREN", 0x80041025 }, +{"WBEM_E_CLASS_HAS_INSTANCES", 0x80041026 }, +{"WBEM_E_QUERY_NOT_IMPLEMENTED", 0x80041027 }, +{"WBEM_E_ILLEGAL_NULL", 0x80041028 }, +{"WBEM_E_INVALID_QUALIFIER_TYPE", 0x80041029 }, +{"WBEM_E_INVALID_PROPERTY_TYPE", 0x8004102A }, +{"WBEM_E_VALUE_OUT_OF_RANGE", 0x8004102B }, +{"WBEM_E_CANNOT_BE_SINGLETON", 0x8004102C }, +{"WBEM_E_INVALID_CIM_TYPE", 0x8004102D }, +{"WBEM_E_INVALID_METHOD", 0x8004102E }, +{"WBEM_E_INVALID_METHOD_PARAMETERS", 0x8004102F }, +{"WBEM_E_SYSTEM_PROPERTY", 0x80041030 }, +{"WBEM_E_INVALID_PROPERTY", 0x80041031 }, +{"WBEM_E_CALL_CANCELLED", 0x80041032 }, +{"WBEM_E_SHUTTING_DOWN", 0x80041033 }, +{"WBEM_E_PROPAGATED_METHOD", 0x80041034 }, +{"WBEM_E_UNSUPPORTED_PARAMETER", 0x80041035 }, +{"WBEM_E_MISSING_PARAMETER_ID", 0x80041036 }, +{"WBEM_E_INVALID_PARAMETER_ID", 0x80041037 }, +{"WBEM_E_NONCONSECUTIVE_PARAMETER_IDS", 0x80041038 }, +{"WBEM_E_PARAMETER_ID_ON_RETVAL", 0x80041039 }, +{"WBEM_E_INVALID_OBJECT_PATH", 0x8004103A }, +{"WBEM_E_OUT_OF_DISK_SPACE", 0x8004103B }, +{"WBEM_E_BUFFER_TOO_SMALL", 0x8004103C }, +{"WBEM_E_UNSUPPORTED_PUT_EXTENSION", 0x8004103D }, +{"WBEM_E_UNKNOWN_OBJECT_TYPE", 0x8004103E }, +{"WBEM_E_UNKNOWN_PACKET_TYPE", 0x8004103F }, +{"WBEM_E_MARSHAL_VERSION_MISMATCH", 0x80041040 }, +{"WBEM_E_MARSHAL_INVALID_SIGNATURE", 0x80041041 }, +{"WBEM_E_INVALID_QUALIFIER", 0x80041042 }, +{"WBEM_E_INVALID_DUPLICATE_PARAMETER", 0x80041043 }, +{"WBEM_E_TOO_MUCH_DATA", 0x80041044 }, +{"WBEM_E_SERVER_TOO_BUSY", 0x80041045 }, +{"WBEM_E_INVALID_FLAVOR", 0x80041046 }, +{"WBEM_E_CIRCULAR_REFERENCE", 0x80041047 }, +{"WBEM_E_UNSUPPORTED_CLASS_UPDATE", 0x80041048 }, +{"WBEM_E_CANNOT_CHANGE_KEY_INHERITANCE", 0x80041049 }, +{"WBEM_E_CANNOT_CHANGE_INDEX_INHERITANCE", 0x80041050 }, +{"WBEM_E_TOO_MANY_PROPERTIES", 0x80041051 }, +{"WBEM_E_UPDATE_TYPE_MISMATCH", 0x80041052 }, +{"WBEM_E_UPDATE_OVERRIDE_NOT_ALLOWED", 0x80041053 }, +{"WBEM_E_UPDATE_PROPAGATED_METHOD", 0x80041054 }, +{"WBEM_E_METHOD_NOT_IMPLEMENTED", 0x80041055 }, +{"WBEM_E_METHOD_DISABLED", 0x80041056 }, +{"WBEMESS_E_REGISTRATION_TOO_BROAD", 0x80042001 }, +{"WBEMESS_E_REGISTRATION_TOO_PRECISE", 0x80042002 } +#endif +}; + +/* + * Microsoft_IPMI methods: + * void RequestResponse( + * [in] uint8 Command, + * [out] uint8 CompletionCode, + * [in] uint8 Lun, + * [in] uint8 NetworkFunction, + * [in] uint8 RequestData[], + * [out] uint32 ResponseDataSize, + * [in] uint32 RequestDataSize, + * [in] uint8 ResponderAddress, + * [out] uint8 ResponseData + * ); + * + * void SMS_Attention( + * [out] boolean AttentionSet, + * [out] uint8 StatusRegisterValue + * ); + */ + +static void cleanup_wmi(void) +{ + VariantClear(&varPath); + if (pInstance != NULL) pInstance->Release(); + if (pEnumerator != NULL) pEnumerator->Release(); + if (pClass != NULL) pClass->Release(); + if (pSvc != 0) pSvc->Release(); + if (pLoc != 0) pLoc->Release(); + CoUninitialize(); +} + +static void dumpbuf(uchar *p, int len, char fwrap) +{ + int i; + for (i = 0; i < len; i++) { + if (fwrap) { + if ((i % 16) == 0) printf("\n%04x: ",i); + } + printf(" %02x",p[i]); + } + printf("\n"); + return; +} + +static char *res_str(HRESULT res) +{ + char *pstr = ""; + int i; + for (i = 0; i < NRES; i++) { + if (res_list[i].val == res) { + pstr = &res_list[i].desc[0]; + break; + } + } + return (pstr); +} + +extern "C" { + +int ipmi_open_ms(char fdebugcmd) +{ + int bRet = -1; + HRESULT hres; + ULONG dwCount = NULL; + + fdebugms = fdebugcmd; + // Initialize COM. + hres = CoInitializeEx(0, COINIT_MULTITHREADED); + if (FAILED(hres)) { + if (fdebugcmd) printf("ipmi_open_ms: CoInitializeEx error\n"); + return bRet; + } + + // Obtain the initial locator to Windows Management + // on a particular host computer. + hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID *) &pLoc); + if (FAILED(hres)) { + CoUninitialize(); + if (fdebugcmd) printf("ipmi_open_ms: CreateInstance(WbemLoc) error\n"); + return bRet; + } + + + // 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"), NULL, NULL, 0, + NULL, 0, 0, &pSvc ); + if (FAILED(hres)) { + pLoc->Release(); + CoUninitialize(); + if (fdebugcmd) printf("ipmi_open_ms: ConnectServer error\n"); + return bRet; + } + + // Set the IWbemServices proxy so that impersonation + // of the user (client) occurs. + hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, + NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, EOAC_NONE ); + if (FAILED(hres)) { + if (fdebugcmd) printf("ipmi_open_ms: Cannot SetProxyBlanket\n"); + cleanup_wmi(); + return bRet; // Program has failed. + } + + hres = pSvc->GetObject( L"Microsoft_IPMI", 0, NULL, &pClass, NULL); + if (FAILED(hres)) { + cleanup_wmi(); + if (fdebugcmd) + printf("ipmi_open_ms: cannot open microsoft_ipmi driver (ipmidrv.sys)\n"); + return bRet; + } + + hres = pSvc->CreateInstanceEnum( L"microsoft_ipmi", 0, NULL, &pEnumerator); + if (FAILED(hres)) { + cleanup_wmi(); + if (fdebugcmd) + printf("ipmi_open_ms: cannot open microsoft_ipmi Enum\n"); + return bRet; + } + + hres = pEnumerator->Next( WBEM_INFINITE, 1, &pInstance, &dwCount); + if (FAILED(hres)) { + if (fdebugcmd) + printf("ipmi_open_ms: Cannot get microsoft_ipmi instance\n"); + cleanup_wmi(); + return bRet; + } + VariantInit(&varPath); + hres = pInstance->Get(_bstr_t(L"__RelPath"), 0, &varPath, NULL, 0); + if (FAILED(hres)) { + if (fdebugcmd) + printf("ipmi_open_ms: Cannot get instance Path %s\n","__RelPath"); + cleanup_wmi(); + return bRet; + } else { /*success*/ + if (fdebugcmd) + printf("ipmi_open_ms: ObjectPath: %ls\n",V_BSTR(&varPath)); + // usually L"Microsoft_IPMI.InstanceName=\"Root\\SYSTEM\\0003_0\"", + fmsopen = 1; + bRet = 0; + } + + return bRet; +} + +int ipmi_close_ms(void) +{ + int bRet = -1; + if (fmsopen) { + cleanup_wmi(); + fmsopen = 0; + bRet = 0; + } + return bRet; +} + +int ipmi_cmdraw_ms(uchar cmd, uchar netfn, uchar lun, uchar sa, + uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, + uchar *pcc, char fdebugcmd) +{ + int bRet; + HRESULT hres; + IWbemClassObject* pInParams = NULL; /*class definition*/ + IWbemClassObject* pInReq = NULL; /*instance*/ + IWbemClassObject* pOutResp = NULL; + VARIANT varCmd, varNetfn, varLun, varSa, varSize, varData; + SAFEARRAY* psa = NULL; + long i; + uchar *p; + + fdebugms = fdebugcmd; + if (!fmsopen) { + bRet = ipmi_open_ms(fdebugcmd); + if (bRet != 0) return(bRet); + } + bRet = -1; + + + hres = pClass->GetMethod(L"RequestResponse",0,&pInParams,NULL); + if (FAILED(hres)) { + if (fdebugcmd) + printf("ipmi_cmdraw_ms: Cannot get RequestResponse method\n"); + return (bRet); + } + +#ifdef WDM_FIXED + /* see http://support.microsoft.com/kb/951242 for WDM bug info */ + hres = pInParams->SpawnInstance(0,&pInReq); + if (FAILED(hres)) { + if (fdebugcmd) + printf("ipmi_cmdraw_ms: Cannot get RequestResponse instance\n"); + return (bRet); + } + // also substitute pInReq for pInParams below if this gets fixed. +#endif + + VariantInit(&varCmd); + varCmd.vt = VT_UI1; + varCmd.bVal = cmd; + hres = pInParams->Put(_bstr_t(L"Command"), 0, &varCmd, 0); + // VariantClear(&varCmd); + if (FAILED(hres)) goto MSRET; + + VariantInit(&varNetfn); + varNetfn.vt = VT_UI1; + varNetfn.bVal = netfn; + hres = pInParams->Put(_bstr_t(L"NetworkFunction"), 0, &varNetfn, 0); + // VariantClear(&varNetfn); + if (FAILED(hres)) goto MSRET; + + VariantInit(&varLun); + varLun.vt = VT_UI1; + varLun.bVal = lun; + hres = pInParams->Put(_bstr_t(L"Lun"), 0, &varLun, 0); + // VariantClear(&varLun); + if (FAILED(hres)) goto MSRET; + + VariantInit(&varSa); + varSa.vt = VT_UI1; + varSa.bVal = sa; + hres = pInParams->Put(_bstr_t(L"ResponderAddress"), 0, &varSa, 0); + // VariantClear(&varSa); + if (FAILED(hres)) goto MSRET; + + VariantInit(&varSize); + varSize.vt = VT_I4; + varSize.lVal = sdata; + hres = pInParams->Put(_bstr_t(L"RequestDataSize"), 0, &varSize, 0); + // VariantClear(&varSize); + if (FAILED(hres)) goto MSRET; + + SAFEARRAYBOUND rgsabound[1]; + rgsabound[0].cElements = sdata; + rgsabound[0].lLbound = 0; + psa = SafeArrayCreate(VT_UI1,1,rgsabound); + if(!psa) { + printf("ipmi_cmdraw_ms: SafeArrayCreate failed\n"); + goto MSRET; + } +#ifdef SHOULD_WORK_BUT_NO + /* The SafeArrayPutElement does not put the data in the right + * place, so skip this and copy the raw data below. */ + VARIANT tvar; + if (fdebugcmd && sdata > 0) + { printf("psa1(%p):",psa); dumpbuf((uchar *)psa,42,1); } + + for(i =0; i< sdata; i++) + { + VariantInit(&tvar); + tvar.vt = VT_UI1; + tvar.bVal = pdata[i]; + hres = SafeArrayPutElement(psa, &i, &tvar); + // VariantClear(&tvar); + if (FAILED(hres)) { + printf("ipmi_cmdraw_ms: SafeArrayPutElement(%d) failed\n",i); + goto MSRET; + } + } /*end for*/ + if (fdebugcmd && sdata > 0) + { printf("psa2(%p):",psa); dumpbuf((uchar *)psa,42,1); } +#endif + + /* Copy the real RequestData into psa */ + memcpy(psa->pvData,pdata,sdata); + + VariantInit(&varData); + varData.vt = VT_ARRAY | VT_UI1; + varData.parray = psa; + hres = pInParams->Put(_bstr_t(L"RequestData"), 0, &varData, 0); + // VariantClear(&varData); + if (FAILED(hres)) { + printf("Put(RequestData) error %x\n",hres); + goto MSRET; + } + +#ifdef TEST_METHODS + IWbemClassObject* pOutSms = NULL; + if (fdebugcmd) printf("ipmi_cmdraw_ms: calling SMS_Attention(%ls)\n", + V_BSTR(&varPath)); + hres = pSvc->ExecMethod( V_BSTR(&varPath), _bstr_t(L"SMS_Attention"), + 0, NULL, NULL, &pOutSms, NULL); + if (FAILED(hres)) { + printf("ipmi_cmdraw_ms: SMS_Attention method error %x\n",hres); + goto MSRET; + } + if (fdebugcmd) printf("ipmi_cmdraw_ms: SMS_Attention method ok\n"); + /* This does work, without input parameters */ + pOutSms->Release(); +#endif + + hres = pSvc->ExecMethod( V_BSTR(&varPath), _bstr_t(L"RequestResponse"), + 0, NULL, pInParams, &pOutResp, NULL); + if (fdebugcmd) { + printf("ipmi_cmdraw_ms(cmd=%x,netfn=%x,lun=%x,sa=%x,sdata=%d)" + " RequestResponse ret=%x\n", cmd,netfn,lun,sa,sdata,hres); + if (sdata > 0) { + printf("ipmi_cmdraw_ms: req data(%d):",sdata); + dumpbuf(pdata,sdata,0); + } + } + if (FAILED(hres)) { + printf("ipmi_cmdraw_ms: RequestResponse error %x %s\n", + hres,res_str(hres)); +#ifdef EXTRA_DESC + /* This does not usually add any meaning for IPMI. */ + BSTR desc; + IErrorInfo *pIErrorInfo; + GetErrorInfo(0,&pIErrorInfo); + pIErrorInfo->GetDescription(&desc); + printf("ipmi_cmdraw_ms: ErrorInfoDescr: %ls\n",desc); + SysFreeString(desc); +#endif + bRet = -1; + /*fall through for cleanup and return*/ + } + else { /*successful, get ccode and response data */ + VARIANT varByte, varRSz, varRData; + VariantInit(&varByte); + VariantInit(&varRSz); + VariantInit(&varRData); + long rlen; + + hres = pOutResp->Get(_bstr_t(L"CompletionCode"),0, &varByte, NULL, 0); + if (FAILED(hres)) goto MSRET; + if (fdebugcmd) printf("ipmi_cmdraw_ms: CompletionCode %x returned\n", + V_UI1(&varByte) ); + *pcc = V_UI1(&varByte); + + hres = pOutResp->Get(_bstr_t(L"ResponseDataSize"),0, &varRSz, NULL, 0); + if (FAILED(hres)) goto MSRET; + rlen = V_I4(&varRSz); + if (rlen > 1) rlen--; /*skip cc*/ + if (rlen > *sresp) { + if (fdebugcmd) printf("ResponseData truncated from %d to %d\n", + rlen,*sresp); + rlen = *sresp; /*truncate*/ + } + *sresp = (int)rlen; + + hres = pOutResp->Get(_bstr_t(L"ResponseData"),0, &varRData, NULL,0); + if (FAILED(hres)) { /*ignore failure */ + if (fdebugcmd) printf("Get ResponseData error %x\n",hres); + } else { /* success */ +#ifdef SHOULD_WORK_BUT_NO + uchar *pa; + p = (uchar*)varRData.parray->pvData; + pa = (uchar*)varRData.parray; + printf("pa=%p, pa+12=%p p=%p\n",pa,(pa+12),p); + if (fdebugcmd) { + printf("Data.vt = %04x, Data.parray(%p):", + varRData.vt, varRData.parray); + // 0x2011 means VT_ARRAY | VT_UI1 + dumpbuf((uchar *)varRData.parray,40,1); + } + /* The SafeArrayGetElement does not get the data from the right + * place, so skip this and copy the raw data below. */ + VARIANT rgvar[NVAR]; + if (rlen > NVAR) *pcc = 0xEE; + for (i = 0; i <= rlen; i++) + VariantInit(&rgvar[i]); + /* copy the response data from varRData to presp */ + for( i = 0; i <= rlen; i++) + { + hres = SafeArrayGetElement(varRData.parray, &i, &rgvar[i]); + if (FAILED(hres)) { + if (fdebugcmd) + printf("ipmi_cmdraw_ms: SafeArrayGetElement(%d) failed\n",i); + break; + } + if (fdebugcmd) { + printf("Data[%d] vt=%02x val=%02x, rgvar(%p):",i, + rgvar[i].vt, V_UI1(&rgvar[i]),&rgvar[i]); + dumpbuf((uchar *)&rgvar[i],12,0); + } + /* skip the completion code */ + // if (i > 0) presp[i-1] = V_UI1(&rgvar[i]); + } /*end for*/ +#endif + /* + * parray from a GetDeviceId response: + * 0015CEE0: 01 00 80 00 01 00 00 00 00 00 00 00 00 cf 15 00 + * 0015CEF0: 10 00 00 00 00 00 00 00 03 00 06 00 95 01 08 00 + * ^- datalen=0x10 + * 0015CF00: 00 20 01 00 19 02 9f 57 01 ... + * ^- start of data (cc=00, ...) + */ + /* Copy the real ResponseData into presp. */ + p = (uchar*)varRData.parray->pvData; + for( i = 0; i <= rlen; i++) { + /* skip the completion code */ + if (i > 0) presp[i-1] = p[i]; + } + if (fdebugcmd) { + printf("ipmi_cmdraw_ms: resp data(%d):",rlen+1); + dumpbuf(p,rlen+1,0); + } + } + bRet = 0; + } + +MSRET: +#define CLEAN_OK 1 +#ifdef CLEAN_OK + /* VariantClear(&var*) should be done by pInParams->Release() */ + if (psa != NULL) SafeArrayDestroy(psa); + if (pInParams != NULL) pInParams->Release(); + if (pOutResp != NULL) pOutResp->Release(); +#endif + return(bRet); +} + +#ifndef ALONE +int ipmi_cmd_ms(ushort cmd, uchar *pdata, int sdata, + uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) +{ + int bRet = -1; + int i; + + fdebugms = fdebugcmd; + for (i = 0; i < NCMDS; i++) { + if (ipmi_cmds[i].cmdtyp == cmd) break; + } + if (i >= NCMDS) { + printf("ipmi_cmd_ms: Unknown command %04x\n",cmd); + return(-1); + } + if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */ + + bRet = ipmi_cmdraw_ms((uchar)cmd,ipmi_cmds[i].netfn,ipmi_cmds[i].lun, + ipmi_cmds[i].sa, ipmi_cmds[i].bus, + pdata,sdata,presp,sresp,pcc,fdebugcmd); + return (bRet); +} +#endif + +} /* end C */ + +#ifdef TEST_BIN +int main(int argc, char **argv) +{ + uchar rdata[40]; + int i, rv; + int rlen = 0; + uchar cc; + + fdebugms = 1; + rlen = sizeof(rdata); + rv = ipmi_cmdraw_ms(0x01, 0x06, 0, 0x20, 0, /*get_device_id*/ + NULL, 0, rdata, &rlen, &cc, fdebugms); + printf("ipmi_cmdraw_ms ret=%d, cc=%02x\n",rv,cc); + if (rv == 0) { + printf(" ** Return Code: %2.2X\n", cc); + printf(" ** Data[%d]:",rlen); + for (i=0; i < rlen; i++) + printf(" %2.2X", rdata[i]); + printf("\n"); + } + ipmi_close_ms(); + return 0; +} +#endif + + +#endif +/* endif WIN32 */ + +/* end ipmims.cpp */ |