/* * idcmi.c * Data Center Manageability Interface (DCMI) command support * * Change history: * 11/17/2011 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2011 Kontron America, Inc. 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 Kontron 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. *M*/ #ifdef WIN32 #include #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "isensor.h" #include "idcmi.h" #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil dcmi"; #else static char * progver = "3.08"; static char * progname = "idcmi"; #endif extern char fdebug; /*from ipmicmd.c*/ static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static uchar dcmi_ver = 0x00; /* 0x10, 0x11, or 0x15 */ static uchar fpwm = 0; /* =1 if Power Management supported */ static uchar do_sensors = 0; static uchar set_asset = 0; static uchar set_mcid = 0; static char *asset_new = NULL; static char *mcid_new = NULL; static int asset_len = 0; static int mcid_len = 0; static char mc_id[64]; static char asset[64]; #ifdef NOT /* see idcmi.h */ #define NETFN_DCMI 0x2C #define CMD_DCMI_GET_CAPAB 0x01 #define CMD_DCMI_GET_POWREAD 0x02 #define CMD_DCMI_GET_POWLIMIT 0x03 #define CMD_DCMI_SET_POWLIMIT 0x04 #define CMD_DCMI_ACT_POWLIMIT 0x05 #define CMD_DCMI_GET_ASSETTAG 0x06 #define CMD_DCMI_GET_SENSORINF 0x07 #define CMD_DCMI_SET_ASSETTAG 0x08 #define CMD_DCMI_GET_MCIDSTR 0x09 #define CMD_DCMI_SET_MCIDSTR 0x0A /* for DCMI 1.5 only */ #define CMD_DCMI_SET_THERMLIM 0x0B #define CMD_DCMI_GET_THERMLIM 0x0C #define CMD_DCMI_GET_TEMPRDNGS 0x10 #define CMD_DCMI_SET_CONFIG 0x12 #define CMD_DCMI_GET_CONFIG 0x13 #endif static int dcmi_usage(void) { printf("Usage: %s [-admsx -NUPREFTVY] \n", progname); printf(" -a Set DCMI Asset Tag to this string\n"); printf(" -d Set DCMI MC ID to this string\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -s Get DCMI sensor info\n"); printf(" -x Display extra debug messages\n"); print_lan_opt_usage(1); printf("where is one of:\n"); printf(" info Get DCMI Capabilities, MC ID, asset tag (default)\n"); printf(" power [get] Get Power reading & limit\n"); printf(" power set_limit Set Power limit\n"); printf(" power set_action Set Power limit exception action\n"); printf(" (action = no_action | power_off | log_sel)\n"); printf(" power set_correction Set Power limit correction time (in ms)\n"); printf(" power set_sample Set Power limit sampling period (in sec)\n"); printf(" power activate Activate Power limit\n"); printf(" power deactivate Deactivate Power limit\n"); printf(" thermal Get/Set DCMI Thermal parameters\n"); printf(" config Get/Set DCMI Configuration parameters\n"); printf(" help Show this help message\n"); return(ERR_USAGE); } static int dcmi_get_capab(int param, uchar *pdata, int sdata) { uchar idata[4]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = (uchar)param; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_CAPAB, NETFN_DCMI, g_sa, g_bus, g_lun, idata,2, rdata, &rlen, &cc, fdebug); if ((rv != 0) || (cc != 0)) { if (fdebug) printf("dcmi_get_capab(%d): rv = %d, ccode %02x\n",param,rv,cc); if (rv == 0) rv = cc; return(rv); } /* if here, success */ if (fdebug) { /*show raw response*/ printf("dcmi_get_capab(%d): rlen = %d\n",param,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rlen > sdata) { if (fdebug) printf("dcmi_get_capab(%d): data truncated from %d to %d\n", param,rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); return(rv); } static int dcmi_get_power_read(int param, uchar *pdata, int sdata) { uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = (uchar)param; /*mode 1 or 2*/ idata[2] = 0x00; idata[3] = 0x00; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_POWREAD, NETFN_DCMI, g_sa, g_bus, g_lun, idata,4, rdata, &rlen, &cc, fdebug); if (rv == 0) rv = cc; if (fdebug) { /*show raw response*/ printf("dcmi_get_power_read(%d): rv = %d rlen = %d\n",param,rv,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rv == 0) { /* if here, success */ if (rlen > sdata) { if (fdebug) printf("dcmi_get_power_read(%d): data truncated from %d to %d\n", param,rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); } return(rv); } static int dcmi_get_power_limit( uchar *pdata, int sdata) { uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = 0x00; idata[2] = 0x00; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_POWLIMIT, NETFN_DCMI, g_sa, g_bus, g_lun, idata,3, rdata, &rlen, &cc, fdebug); if (rv == 0) rv = cc; if (fdebug) { /*show raw response*/ printf("dcmi_get_power_limit: rv = %d rlen = %d\n",rv,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rv == 0) { /* if here, success */ if (rlen > sdata) { if (fdebug) printf("dcmi_get_power_limit: data truncated from %d to %d\n", rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); } return(rv); } static int dcmi_set_power_limit(int param,int value, uchar *pow, int spow) { int rv = 0; uchar idata[32]; uchar rdata[32]; int rlen; uchar cc; if (spow > 15) spow = 15; memcpy(idata,pow,spow); switch(param) { case CORRECTION_TIME: idata[10]=(uchar)((value >> 24) & 0xff); idata[9] =(uchar)((value >> 16) & 0xff); idata[8] =(uchar)((value >> 8) & 0xff); idata[7] =(uchar)((value) & 0xff); break; case EXCEPTION_ACTION: idata[4] = (uchar)(value & 0xff); break; case POWER_LIMIT: idata[5] = (uchar)(value & 0xff); idata[6] = (uchar)((value >> 8) & 0xff); break; case SAMPLE_PERIOD: idata[14] = (uchar)((value >> 8) & 0xff); idata[13] = (uchar)(value & 0xff); break; default: return ERR_BAD_PARAM; break; } rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_SET_POWLIMIT, NETFN_DCMI, g_sa, g_bus, g_lun, idata,15, rdata, &rlen,&cc, fdebug); if (fdebug) printf("dcmi_set_power_limit(%d,%d): rv = %d cc = %x\n", param,value,rv,cc); if (rv == 0) rv = cc; return (rv); } static int dcmi_power_limit_activate ( int yes) { int rv; uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; if (yes < 0) return (ERR_BAD_PARAM); if (yes > 1) return (ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = yes; idata[2] = 0x00; idata[3] = 0x00; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_ACT_POWLIMIT, NETFN_DCMI, g_sa, g_bus, g_lun, idata,4, rdata, &rlen, &cc, fdebug); if (fdebug) printf("dcmi_power_limit_activate(%d): rv = %d cc = %x\n",yes,rv,cc); if (rv == 0) rv = cc; return(rv); } void dcmi_show_power_read(int parm, uchar *cdata, int sdata) { int i; ulong sample_period; time_t t = 0; uchar state; if (fdebug) { /*++++*/ printf("dcmi_show_power_read(%d,%p,%d) called\n",parm,cdata,sdata); for (i = 0; i < sdata; i++) printf("%02x ",cdata[i]); printf("\n"); } if (sdata < 18) { printf("power_read data length %d is too short\n",sdata); return; } if (cdata[0] != 0xDC) { printf("power_read: invalid first data byte (0x%02x)\n",cdata[0]); return; } memcpy(&t,&cdata[9],4); sample_period = cdata[13]; sample_period += (cdata[14] << 8); sample_period += (cdata[15] << 16); sample_period += (cdata[16] << 24); state = cdata[17]; switch(parm) { case 1: /* Mode 1 - System Power Statistics */ printf(" Current Power: %d Watts\n",cdata[1]+(cdata[2]<<8)); printf(" Min Power over sample duration: %d Watts\n",cdata[3]+(cdata[4]<<8)); printf(" Max Power over sample duration: %d Watts\n",cdata[5]+(cdata[6]<<8)); printf(" Avg Power over sample duration: %d Watts\n",cdata[7]+(cdata[8]<<8)); printf(" Timestamp: %s\n",ctime(&t)); printf(" Sampling period: %lu ms\n",sample_period); printf(" Power reading state is: %s\n",(state&0x40)? "active":"not active"); break; case 2: /* Mode 2 - Enhanced System Power Statistics */ printf("Enhanced Power Mode 2 decoding not yet implemented\n"); /* TODO */ // break; default: for (i = 0; i < sdata; i++) printf("%02x ",cdata[i]); printf("\n"); break; } } void dcmi_show_power_limit(uchar *cdata, int sdata, int rv) { ulong correction_time; char *pstr; correction_time = cdata[6]; correction_time += (cdata[7] << 8); correction_time += (cdata[8] << 16); correction_time += (ulong)(cdata[9] << 24); if (rv == 0) pstr = "(active)"; else if (rv == 0x80) pstr = "(inactive)"; else pstr = "(error)"; printf(" Exception Action: "); if (cdata[3] & 0x01) printf("Hard Power off\n"); else if ((cdata[3] & 0x11) == 0x11) printf("SEL logging\n"); else printf("OEM defined\n"); printf(" Power Limit: %d Watts %s\n",cdata[4]+(cdata[5]<<8), pstr); printf(" Correction Time: %lu ms\n", correction_time); printf(" Sampling period: %d sec\n", cdata[12]+(cdata[13]<<8)); } static int dcmi_get_sensorinf(uchar styp, uchar snum, uchar offset, uchar *pdata, int sdata) { uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = styp; /*sensor type, 0x01 = Temperature*/ idata[2] = snum; /*sensor number */ idata[3] = 0x00; /*Entity Instance, 0 = all instances*/ idata[4] = offset; /*Entity Instance start/offset */ rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_SENSORINF, NETFN_DCMI, g_sa, g_bus, g_lun, idata,5, rdata, &rlen, &cc, fdebug); if (rv == 0) rv = cc; if (fdebug) { /*show raw response*/ printf("dcmi_get_sensorinf(%d): rlen = %d\n",snum,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rv == 0) { /* if here, success */ if (rlen > sdata) { if (fdebug) printf("dcmi_get_sensorinf(%d): data truncated from %d to %d\n", snum,rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); } return(rv); } static char *entstr(int i) { char *pstr = NULL; switch(i) { case 0: pstr = "Inlet"; break; case 1: pstr = "CPU"; break; case 2: default: pstr = "Baseboard"; break; } return(pstr); } static int dcmi_get_sensors(int styp) { int i, j, n, r, recs; uchar offset, id; uchar dbuf[20]; uchar s1; int rv; uchar *sdrs = NULL; uchar sdr[128]; offset = 0; r = 1; n = 8; s1 = 0x40; /*0x40,0x41,0x42*/ rv = get_sdr_cache(&sdrs); printf("---Sensors---\n"); for (i = 0; i < 3; i++) { rv = dcmi_get_sensorinf(styp,s1+i,offset,dbuf,sizeof(dbuf)); if (rv != 0) break; n = dbuf[1]; recs = dbuf[2]; printf(" %d %s temp sensors: \tn_returned=%d\n",n,entstr(i),recs); for (r = 0; r < n; r += recs) { recs = dbuf[2]; if (recs == 0) break; for (j = 0; j < r; j++) { id = (dbuf[4 + (2*j)] << 8) + dbuf[3 + (2*j)]; if (fdebug) printf("j=%d id=%x \n",j,id); /* get the sensor info for each record id */ rv = find_sdr_next(sdr,sdrs,(id-1)); ShowSDR("",sdr); } offset += recs; rv = dcmi_get_sensorinf(1,s1+i,offset,dbuf,sizeof(dbuf)); if (rv != 0) break; } } if (rv != 0) printf("dcmi_get_sensors(%d,%d) error %d\n",styp,i,rv); free_sdr_cache(sdrs); return(rv); } static int dcmi_get_asset_tag(char *pdata, int sdata, int *dlen) { uchar idata[4]; uchar rdata[32]; int rlen; uchar cc; int n, rv = -1; int sz_chunk = 16; int sz_all; if (pdata == NULL || sdata < 16) return(ERR_BAD_PARAM); memset(pdata,0,sdata); sz_all = sdata; for (n = 0; (n < sdata && n < sz_all); n += sz_chunk) { idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_ASSETTAG, NETFN_DCMI, g_sa, g_bus, g_lun, idata,3, rdata, &rlen, &cc, fdebug); if (fdebug) printf("dcmi_get_asset(%d): rv=%d ccode=%02x rlen=%d\n", n,rv,cc,rlen); if (rv == 0) rv = cc; if (rv == 0) { /* if here, success */ if (n == 0) sz_all = rdata[1]; if ((rlen - 2) < sz_chunk) sz_chunk = rlen - 2; if ((n + sz_chunk) > sdata) { if (fdebug) printf("dcmi_get_asset(%d): data truncated from %d to %d\n", n,(n+sz_chunk),sdata); sz_chunk = (sdata - n); } memcpy(&pdata[n],&rdata[2],sz_chunk); } else break; } /*end-for loop*/ pdata[n] = 0; /*stringify*/ if (dlen != NULL) *dlen = n; return(rv); } static int dcmi_get_mc_id(char *pdata, int sdata, int *dlen) { uchar idata[4]; uchar rdata[32]; int rlen; uchar cc; int n, rv = -1; int sz_chunk = 16; int sz_all; if (pdata == NULL || sdata < 16) return(ERR_BAD_PARAM); memset(pdata,0,sdata); sz_all = sdata; for (n = 0; (n < sdata && n < sz_all); n += sz_chunk) { idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_MCIDSTR, NETFN_DCMI, g_sa, g_bus, g_lun, idata,3, rdata, &rlen, &cc, fdebug); if (fdebug) printf("dcmi_get_mc_id(%d): rv=%d ccode=%02x rlen=%d\n", n,rv,cc,rlen); if (rv == 0) rv = cc; if (rv == 0) { /* if here, success */ if (n == 0) sz_all = rdata[1]; if ((rlen - 2) < sz_chunk) sz_chunk = rlen - 2; if ((n + sz_chunk) > sdata) { if (fdebug) printf("dcmi_get_mc_id(%d): data truncated from %d to %d\n", n,(n+sz_chunk),sdata); sz_chunk = (sdata - n); } memcpy(&pdata[n],&rdata[2],sz_chunk); } else break; } /*end-for loop*/ pdata[n] = 0; /*stringify*/ if (dlen != NULL) *dlen = n; return(rv); } static int dcmi_set_asset_tag(char *pdata, int sdata) { int rv = -1; uchar idata[32]; uchar rdata[8]; uchar cc; int ilen, rlen, n; int sz_chunk = 16; if (pdata == NULL || sdata < 2) return(ERR_BAD_PARAM); for (n = 0; (n < sdata); n += sz_chunk) { idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ memset(&idata[3],0x20,sz_chunk); ilen = 3 + sz_chunk; if ((n + sz_chunk) > sdata) sz_chunk = sdata - n; memcpy(&idata[3],&pdata[n],sz_chunk); rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_SET_ASSETTAG, NETFN_DCMI, g_sa, g_bus, g_lun, idata,ilen, rdata, &rlen, &cc, fdebug); if (rv == 0) { if (fdebug) printf("dcmi_set_asset_tag(%d,%d,%d) cc=%x resp: %02x %02x %02x\n", sdata,n,sz_chunk,cc,rdata[0],rdata[1],rdata[2]); rv = cc; } if (rv != 0) break; } return(rv); } static int dcmi_set_mc_id(char *pdata, int sdata) { int rv = -1; uchar idata[32]; uchar rdata[8]; uchar cc; int ilen, rlen, n; int sz_chunk = 16; if (pdata == NULL || sdata < 2) return(ERR_BAD_PARAM); for (n = 0; (n < sdata); n += sz_chunk) { if ((n + sz_chunk) > sdata) sz_chunk = sdata - n; idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ memset(&idata[3],0x20,sz_chunk); ilen = 3 + sz_chunk; if ((n + sz_chunk) > sdata) sz_chunk = sdata - n; memcpy(&idata[3],&pdata[n],sz_chunk); rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_SET_MCIDSTR, NETFN_DCMI, g_sa, g_bus, g_lun, idata,ilen, rdata, &rlen, &cc, fdebug); if (rv == 0) { if (fdebug) printf("dcmi_set_mc_id(%d,%d,%d) resp: %02x %02x %02x\n", sdata,n,sz_chunk,rdata[0], rdata[1], rdata[2]); rv = cc; } if (rv != 0) break; } return(rv); } static int dcmi_show_asset_tag(void) { int rv = -1; rv = dcmi_get_asset_tag(asset,sizeof(asset),&asset_len); if (rv == 0) printf("DCMI Asset Tag: \t%s\n",asset); return(rv); } static int dcmi_show_mc_id(void) { int rv = -1; rv = dcmi_get_mc_id(mc_id,sizeof(mc_id),&mcid_len); if (rv == 0) printf("DCMI Mgt Controller ID: \t%s\n",mc_id); return(rv); } static char *supported[2] = { "Unsupported", "Supported" }; void dcmi_show_capab(int parm, uchar *cdata, int sdata) { char mystr[64] = ""; int i, j, k, n, f; switch(parm) { case 1: printf("DCMI Version: \t%d.%d\n",cdata[1],cdata[2]); dcmi_ver = ((cdata[1] & 0x0f) << 4) + (cdata[2] & 0x0f); if (cdata[5] & 0x01) { fpwm = 1; } else { fpwm = 0; } printf("DCMI Power Management: \t%s\n",supported[fpwm]); if (cdata[6] & 0x01) f = 1; else f = 0; printf("DCMI System Interface Access:\t%s\n",supported[f]); if (cdata[6] & 0x02) f = 1; else f = 0; printf("DCMI Serial TMode Access:\t%s\n",supported[f]); if (cdata[6] & 0x02) f = 1; else f = 0; printf("DCMI Secondary LAN Channel:\t%s\n",supported[f]); break; case 2: mystr[0] = 0; if (cdata[5] & 0x80) strcat(mystr,"Overwrite "); else strcat(mystr,"NoOverwrite "); if (cdata[5] & 0x40) strcat(mystr,"FlushAll "); if (cdata[5] & 0x20) strcat(mystr,"FlushRec"); printf("DCMI SEL Management: \t%s\n",mystr); n = ((cdata[5] & 0x0F) << 8) + cdata[4]; printf("DCMI SEL num entries: \t%d\n",n); i = cdata[8]; printf("DCMI Temperature Polling: \t%d sec\n",i); break; case 3: n = ((cdata[4] & 0xFE) >> 1); printf("DCMI PWM Slave_Address: \t%02x\n",n); n = ((cdata[5] & 0xF0) >> 4); printf("DCMI PWM Channel: \t%02x\n",n); printf("DCMI PWM Dev_Rev: \t%02x\n",(cdata[5] & 0x0F)); break; case 4: printf("DCMI LanPlus primary chan:\t%02x\n",cdata[4]); printf("DCMI LanPlus secondary chan:\t%02x\n",cdata[5]); printf("DCMI Serial channel: \t%02x\n",cdata[6]); break; case 5: n = cdata[4]; if (n > (5 + sdata)) n = sdata - 5; /*truncate*/ for (i = 0; i < n; i++) { j = (cdata[5+i] & 0x0f); k = ((cdata[5+i] & 0xf0) >> 4); switch(k) { case 3: strcpy(mystr,"days"); break; case 2: strcpy(mystr,"hrs"); break; case 1: strcpy(mystr,"min"); break; case 0: default: strcpy(mystr,"sec"); break; } printf("DCMI Power Stats Duration(%d):\t%d %s\n",i,j,mystr); } break; default: printf("DCMI(%d) data: %02x %02x %02x %02x %02x %02x %02x %02x\n", parm,cdata[1],cdata[2],cdata[3],cdata[4], cdata[5], cdata[6], cdata[7], cdata[8]); break; } } static int dcmi_show_all_capab(void) { int rv = -1; int i; uchar cdata[32]; for (i = 1; i <= 5; i++) { /* only read power stats(5) when power management is supported */ if (i == 5 && fpwm == 0) continue; rv = dcmi_get_capab(i, cdata, sizeof(cdata)); if (rv != 0) { if (i == 1 && rv == CC_DCMI_INVALID_COMMAND) { /*0xC1 on first*/ printf("DCMI not supported on this platform\n"); break; } else if (i == 5 && rv == CC_DCMI_RECORD_NOT_PRESENT) /*0xCB*/ rv = 0; /*optional, ignore this error*/ /*else just dont show the param*/ } else dcmi_show_capab(i,cdata,sizeof(cdata)); } /*end-for dcmi_capab loop */ return(rv); } #ifdef METACOMMAND int i_dcmi(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; int c, i; char *s1; uchar cdata[32]; uchar powdata[32]; printf("%s ver %s\n", progname,progver); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"a:d:m:p:sT:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'a': set_asset = 1; asset_new = optarg; break; case 'd': set_mcid = 1; mcid_new = optarg; break; case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 's': do_sensors = 1; break; case 'x': fdebug = 1; break; /* debug messages */ case 'p': /* port */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': return(dcmi_usage()); break; } for (i = 0; i < optind; i++) { argv++; argc--; } if ((argc > 0) && strcmp(argv[0], "help") == 0) { return(dcmi_usage()); } rv = ipmi_getdeviceid( cdata, sizeof(cdata),fdebug); if (rv == 0) { uchar ipmi_maj, ipmi_min; ipmi_maj = cdata[4] & 0x0f; ipmi_min = cdata[4] >> 4; show_devid( cdata[2], cdata[3], ipmi_maj, ipmi_min); } else goto do_exit; if (set_asset) { rv = dcmi_get_asset_tag(asset,sizeof(asset),&asset_len); memset(asset,' ',asset_len); /*fill with spaces*/ asset_len = strlen_(asset_new); if (asset_len >= sizeof(asset)) asset_len = sizeof(asset) - 1; memcpy(asset,asset_new,asset_len); asset[asset_len] = 0; rv = dcmi_set_asset_tag(asset, asset_len); printf("Set DCMI Asset Tag to %s, ret = %d\n",asset_new,rv); } if (set_mcid) { rv = dcmi_get_mc_id(mc_id,sizeof(mc_id),&mcid_len); memset(mc_id,' ',mcid_len); /*fill with spaces*/ mcid_len = strlen_(mcid_new); if (mcid_len >= sizeof(mc_id)) mcid_len = sizeof(mc_id) - 1; memcpy(mc_id,mcid_new,mcid_len); mc_id[mcid_len] = 0; rv = dcmi_set_mc_id(mcid_new, mcid_len); printf("Set DCMI MC ID to %s, ret = %d\n",mcid_new,rv); } if ( (argc == 0) || (strcmp(argv[0], "info") == 0) ) { rv = dcmi_show_all_capab(); if (rv == 0) { rv = dcmi_show_mc_id(); rv = dcmi_show_asset_tag(); if (do_sensors) rv = dcmi_get_sensors(1); /*temp sensors*/ rv = 0; /*ignore errors for optional features*/ } } else { rv = dcmi_get_capab(1, cdata, sizeof(cdata)); if (rv == 0) dcmi_show_capab(1,cdata,sizeof(cdata)); else if (rv == CC_DCMI_INVALID_COMMAND) /*0xC1 on first*/ printf("DCMI not supported on this platform\n"); if (strncmp(argv[0], "power",5) == 0) { if (fpwm == 0) { /*not supported in capab */ printf("DCMI Power functions not supported on this platform.\n"); rv = LAN_ERR_NOTSUPPORT; } else { rv = dcmi_get_power_read(1, cdata, sizeof(cdata)); if (rv == 0) { dcmi_show_power_read(1,cdata,sizeof(cdata)); rv = dcmi_get_power_limit(powdata, sizeof(powdata)); if (rv == 0) dcmi_show_power_limit(powdata,sizeof(powdata),rv); else if (rv == 0x80) { dcmi_show_power_limit(powdata,sizeof(powdata),rv); rv = 0; } } if (argc < 2) ; /*just get, done above*/ else if (strncmp(argv[1],"get",3) == 0) ; /*done above*/ else if (strncmp(argv[1],"set_limit",9) == 0) { if (argc < 3) return(dcmi_usage()); i = atoi(argv[2]); { /*let range checking be done by DCMI*/ rv = dcmi_set_power_limit (POWER_LIMIT, i, powdata,16); switch(rv) { case 0: printf("DCMI Power limit applied successfully.\n"); break; case 0x84: printf("Power limit out of range\n"); break; case 0x85: printf("Correction time out of range\n"); break; case 0x89: printf("Statistics reporting period out of range\n"); break; default: printf("DCMI Power Limit Set error %d\n",rv); break; } if (rv == 0) { rv = dcmi_power_limit_activate(1); printf ("DCMI Power Limit Activate returned %d\n",rv); } } } else if (strncmp(argv[1],"activate",8) == 0) { rv = dcmi_power_limit_activate(1); if (rv == 0) printf ("DCMI Power Limit Activated.\n"); else printf("DCMI Power Limit Activate error %d\n",rv); } else if (strncmp(argv[1],"deactivate",10) == 0) { rv = dcmi_power_limit_activate(0); if (rv == 0) printf("DCMI Power Limit Deactivated.\n"); else printf("DCMI Power Limit Deactivate error %d\n",rv); } else if (strcmp(argv[1],"set_action")==0) { if (argc < 3) return(dcmi_usage()); else if (strcmp(argv[2],"no_action") == 0) rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x00, powdata,16); else if (strcmp(argv[2],"log_sel") == 0) rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x11, powdata,16); else if (strcmp(argv[2],"power_off") == 0) rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x01, powdata,16); else return(dcmi_usage()); if (rv == 0) printf("exception action set successfully.\n"); else printf("set_exception action error %d\n",rv); } else if (strcmp(argv[1],"set_sample")==0) { if (argc < 3) return(dcmi_usage()); i = atoi(argv[2]); if (i != 0) { rv = dcmi_set_power_limit (SAMPLE_PERIOD,i,powdata,16); if (rv == 0x00) printf("sample period set successfully\n"); else if (rv == 0x89) printf("sample period %d out of range\n",i); else printf("set_sample period error %d\n",rv); } else { printf("invalid sample period %d\n",i); rv = ERR_USAGE; } } else if (strcmp(argv[1],"set_correction")==0) { if (argc < 3) return(dcmi_usage()); i = atoi(argv[2]); if (i != 0) { rv = dcmi_set_power_limit(CORRECTION_TIME,i,powdata,16); if (rv == 0x00) printf("correction time set successfully\n"); else if (rv == 0x85) printf("correction time %d out of range\n",i); else { dcmi_usage(); rv = ERR_USAGE; } } else { printf("correction time %d invalid\n",i); rv = ERR_USAGE; } } else { printf("invalid subfunction %s\n",argv[1]); rv = ERR_USAGE; } } /* endif power functions supported */ } else if (strcmp(argv[0], "thermal") == 0) { if (dcmi_ver < 0x15) { /*not supported in DCMI < 1.5 */ printf("DCMI 1.5 Thermal functions not supported on this platform.\n"); rv = LAN_ERR_NOTSUPPORT; } else { rv = dcmi_get_sensors(1); /*temp sensors*/ /* These are DCMI 1.5 commands */ // #define CMD_DCMI_SET_THERMLIM 0x0B // #define CMD_DCMI_GET_THERMLIM 0x0C // #define CMD_DCMI_GET_TEMPRDNGS 0x10 /* TODO: implement these 3 DCMI thermal commands */ printf("DCMI 1.5 Thermal functions not yet implemented\n"); rv = ERR_USAGE; } } else if (strcmp(argv[0], "config") == 0) { if (dcmi_ver < 0x15) { /*not supported in DCMI < 1.5 */ printf("DCMI 1.5 Config functions not supported on this platform.\n"); rv = LAN_ERR_NOTSUPPORT; } else { /* These are DCMI 1.5 commands */ // #define CMD_DCMI_SET_CONFIG 0x12 // #define CMD_DCMI_GET_CONFIG 0x13 /* TODO: implement these 2 DCMI config commands */ printf("DCMI 1.5 Config get/set functions not yet implemented\n"); rv = ERR_USAGE; } } else { return(dcmi_usage()); } } /*else not info command*/ do_exit: ipmi_close_(); return rv; } /* end idcmi.c */