From adb40e53a1023fa181120c1f761a5fc094f253a6 Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Thu, 12 May 2005 04:13:32 +0000 Subject: [PATCH] add oem commands --- ipmitool/include/ipmitool/Makefile.am | 2 +- ipmitool/include/ipmitool/ipmi_sunoem.h | 57 ++ ipmitool/lib/Makefile.am | 2 +- ipmitool/lib/ipmi_sunoem.c | 786 ++++++++++++++++++++++++ ipmitool/src/ipmitool.c | 2 + 5 files changed, 847 insertions(+), 2 deletions(-) create mode 100644 ipmitool/include/ipmitool/ipmi_sunoem.h create mode 100644 ipmitool/lib/ipmi_sunoem.c diff --git a/ipmitool/include/ipmitool/Makefile.am b/ipmitool/include/ipmitool/Makefile.am index b35e352..5125b56 100644 --- a/ipmitool/include/ipmitool/Makefile.am +++ b/ipmitool/include/ipmitool/Makefile.am @@ -39,5 +39,5 @@ noinst_HEADERS = log.h bswap.h helper.h ipmi.h ipmi_intf.h \ ipmi_sdr.h ipmi_sel.h ipmi_sol.h ipmi_mc.h ipmi_raw.h \ ipmi_channel.h ipmi_sensor.h ipmi_event.h ipmi_session.h \ ipmi_strings.h ipmi_constants.h ipmi_user.h ipmi_pef.h \ - ipmi_oem.h ipmi_isol.h ipmi_main.h + ipmi_oem.h ipmi_isol.h ipmi_sunoem.h ipmi_main.h diff --git a/ipmitool/include/ipmitool/ipmi_sunoem.h b/ipmitool/include/ipmitool/ipmi_sunoem.h new file mode 100644 index 0000000..6a94f40 --- /dev/null +++ b/ipmitool/include/ipmitool/ipmi_sunoem.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003 Sun Microsystems, 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: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +#ifndef IPMI_SUNOEM_H +#define IPMI_SUNOEM_H + +#if HAVE_CONFIG_H +# include +#endif +#include + +#define IPMI_NETFN_SUNOEM 0x2e + +#define IPMI_SUNOEM_SET_SSH_KEY 0x01 +#define IPMI_SUNOEM_DEL_SSH_KEY 0x02 +#define IPMI_SUNOEM_GET_HEALTH_STATUS 0x10 +#define IPMI_SUNOEM_SET_FAN_SPEED 0x20 +#define IPMI_SUNOEM_LED_GET 0x21 +#define IPMI_SUNOEM_LED_SET 0x22 + +int ipmi_sunoem_main(struct ipmi_intf *, int, char **); + +#endif /*IPMI_SUNOEM_H*/ + diff --git a/ipmitool/lib/Makefile.am b/ipmitool/lib/Makefile.am index 0372989..e99bb91 100644 --- a/ipmitool/lib/Makefile.am +++ b/ipmitool/lib/Makefile.am @@ -40,7 +40,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \ ipmi_lanp.c ipmi_fru.c ipmi_chassis.c ipmi_mc.c log.c \ dimm_spd.c ipmi_sensor.c ipmi_channel.c ipmi_event.c \ ipmi_session.c ipmi_strings.c ipmi_user.c ipmi_raw.c \ - ipmi_oem.c ipmi_isol.c ipmi_main.c + ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_main.c libipmitool_la_LDFLAGS = -export-dynamic libipmitool_la_LIBADD = -lm libipmitool_la_DEPENDENCIES = diff --git a/ipmitool/lib/ipmi_sunoem.c b/ipmitool/lib/ipmi_sunoem.c new file mode 100644 index 0000000..241d1d9 --- /dev/null +++ b/ipmitool/lib/ipmi_sunoem.c @@ -0,0 +1,786 @@ +/* + * Copyright (c) 2005 Sun Microsystems, 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: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct valstr sunoem_led_type_vals[] = { + { 0, "OK2RM" }, + { 1, "SERVICE" }, + { 2, "ACT" }, + { 3, "LOCATE" }, + { 0, NULL }, +}; + +static const struct valstr sunoem_led_mode_vals[] = { + { 0, "OFF" }, + { 1, "ON" }, + { 2, "STANDBY_BLINK" }, + { 3, "SLOW_BLINK" }, + { 4, "FAST_BLINK" }, + { 0, NULL }, +}; + +static void +ipmi_sunoem_usage(void) +{ + lprintf(LOG_NOTICE, "usage: sunoem [option...]"); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " fan speed <0-100>"); + lprintf(LOG_NOTICE, " Set system fan speed (PWM duty cycle)"); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " sshkey set "); + lprintf(LOG_NOTICE, " Set ssh key for a userid into authorized_keys,"); + lprintf(LOG_NOTICE, " view users with 'user list' command."); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " sshkey del "); + lprintf(LOG_NOTICE, " Delete ssh key for userid from authorized_keys,"); + lprintf(LOG_NOTICE, " view users with 'user list' command."); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " led get [ledtype]"); + lprintf(LOG_NOTICE, " Read status of LED found in Generic Device Locator."); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " led set [ledtype]"); + lprintf(LOG_NOTICE, " Set mode of LED found in Generic Device Locator."); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " Use 'sdr list generic' command to get list of Generic"); + lprintf(LOG_NOTICE, " Devices that are controllable LEDs."); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " Optional SIS LED Type:"); + lprintf(LOG_NOTICE, " OK2RM OK to Remove"); + lprintf(LOG_NOTICE, " SERVICE Service Required"); + lprintf(LOG_NOTICE, " ACT Activity"); + lprintf(LOG_NOTICE, " LOCATE Locate"); + lprintf(LOG_NOTICE, ""); + lprintf(LOG_NOTICE, " Required SIS LED Mode:"); + lprintf(LOG_NOTICE, " OFF Off"); + lprintf(LOG_NOTICE, " ON Steady On"); + lprintf(LOG_NOTICE, " STANDBY_BLINK 100ms on 2900ms off blink rate"); + lprintf(LOG_NOTICE, " SLOW_BLINK 1HZ blink rate"); + lprintf(LOG_NOTICE, " FAST_BLINK 4HZ blink rate"); + lprintf(LOG_NOTICE, ""); +} + +/* + * IPMI Request Data: 1 byte + * + * [byte 0] FanSpeed Fan speed as percentage + */ +static int +ipmi_sunoem_fan_speed(struct ipmi_intf * intf, uint8_t speed) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + /* + * sunoem fan speed + */ + + if (speed > 100) { + lprintf(LOG_NOTICE, "Invalid fan speed: %d", speed); + return -1; + } + + req.msg.netfn = IPMI_NETFN_SUNOEM; + req.msg.cmd = IPMI_SUNOEM_SET_FAN_SPEED; + req.msg.data = &speed; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed"); + return -1; + } + else if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + printf("Set Fan speed to %d%%\n", speed); + + return 0; +} + +static void +__sdr_list_empty(struct sdr_record_list * head) +{ + struct sdr_record_list * e, * f; + for (e = head; e != NULL; e = f) { + f = e->next; + free(e); + } + head = NULL; +} + +static struct ipmi_rs * +sunoem_led_get(struct ipmi_intf * intf, + struct sdr_record_generic_locator * dev, + int ledtype) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t rqdata[5]; + + if (dev == NULL) + return NULL; + + rqdata[0] = dev->dev_slave_addr; + rqdata[1] = ledtype; + rqdata[2] = dev->dev_access_addr; + rqdata[3] = dev->oem; + rqdata[4] = 0; + + req.msg.netfn = IPMI_NETFN_SUNOEM; + req.msg.cmd = IPMI_SUNOEM_LED_GET; + req.msg.data = rqdata; + req.msg.data_len = 5; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Sun OEM Get LED command failed"); + return NULL; + } + else if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Sun OEM Get LED command failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return NULL; + } + + return rsp; +} + +static struct ipmi_rs * +sunoem_led_set(struct ipmi_intf * intf, + struct sdr_record_generic_locator * dev, + int ledtype, int ledmode) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t rqdata[7]; + + if (dev == NULL) + return NULL; + + rqdata[0] = dev->dev_slave_addr; + rqdata[1] = ledtype; + rqdata[2] = dev->dev_access_addr; + rqdata[3] = dev->oem; + rqdata[4] = ledmode; + rqdata[5] = 0; + rqdata[6] = 0; + + req.msg.netfn = IPMI_NETFN_SUNOEM; + req.msg.cmd = IPMI_SUNOEM_LED_SET; + req.msg.data = rqdata; + req.msg.data_len = 7; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Sun OEM Set LED command failed"); + return NULL; + } + else if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return NULL; + } + + return rsp; +} + +static void +sunoem_led_get_byentity(struct ipmi_intf * intf, uint8_t entity_id, + uint8_t entity_inst, int ledtype) +{ + struct ipmi_rs * rsp; + struct sdr_record_list *elist, *e; + struct entity_id entity; + + if (entity_id == 0) + return; + + /* lookup sdrs with this entity */ + memset(&entity, 0, sizeof(struct entity_id)); + entity.id = entity_id; + entity.instance = entity_inst; + + elist = ipmi_sdr_find_sdr_byentity(intf, &entity); + + /* for each generic sensor set its led state */ + for (e = elist; e != NULL; e = e->next) { + if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) + continue; + rsp = sunoem_led_get(intf, e->record.genloc, ledtype); + if (rsp && rsp->data_len == 1) { + printf("LED %s is %s\n", + e->record.genloc->id_string, + val2str(rsp->data[0], sunoem_led_mode_vals)); + } + } + + __sdr_list_empty(elist); +} + +static void +sunoem_led_set_byentity(struct ipmi_intf * intf, uint8_t entity_id, + uint8_t entity_inst, int ledtype, int ledmode) +{ + struct ipmi_rs * rsp; + struct sdr_record_list *elist, *e; + struct entity_id entity; + + if (entity_id == 0) + return; + + /* lookup sdrs with this entity */ + memset(&entity, 0, sizeof(struct entity_id)); + entity.id = entity_id; + entity.instance = entity_inst; + + elist = ipmi_sdr_find_sdr_byentity(intf, &entity); + + /* for each generic sensor set its led state */ + for (e = elist; e != NULL; e = e->next) { + if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) + continue; + rsp = sunoem_led_set(intf, e->record.genloc, ledtype, ledmode); + if (rsp && rsp->data_len == 0) { + printf("Set LED %s to %s\n", + e->record.genloc->id_string, + val2str(ledmode, sunoem_led_mode_vals)); + } + } + + __sdr_list_empty(elist); +} + +/* + * IPMI Request Data: 5 bytes + * + * [byte 0] devAddr Value from the "Device Slave Address" field in + * LED's Generic Device Locator record in the SDR + * [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE + * [byte 2] ctrlrAddr Controller address; value from the "Device + * Access Address" field, 0x20 if the LED is local + * [byte 3] hwInfo The OEM field from the SDR record + * [byte 4] force 1 = directly access the device + * 0 = go thru its controller + * Ignored if LED is local + */ +static int +ipmi_sunoem_led_get(struct ipmi_intf * intf, int argc, char ** argv) +{ + struct ipmi_rs * rsp; + struct sdr_record_list *sdr; + struct sdr_record_list *alist, *a; + struct sdr_record_entity_assoc *assoc; + int ledtype = 0; + int i; + + /* + * sunoem led get [type] + */ + + if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { + lprintf(LOG_NOTICE, "usage: sunoem led get [type]"); + return 0; + } + + if (argc > 1) { + ledtype = str2val(argv[1], sunoem_led_type_vals); + } + + if (strncasecmp(argv[0], "all", 3) == 0) { + /* do all generic sensors */ + alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR); + for (a = alist; a != NULL; a = a->next) { + if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) + continue; + if (a->record.genloc->entity.logical) + continue; + rsp = sunoem_led_get(intf, a->record.genloc, ledtype); + if (rsp && rsp->data_len == 1) { + printf("LED %s is %s\n", + a->record.genloc->id_string, + val2str(rsp->data[0], sunoem_led_mode_vals)); + } + } + __sdr_list_empty(alist); + return 0; + } + + /* look up generic device locator record in SDR */ + sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]); + + if (sdr == NULL) { + lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]); + return -1; + } + + if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) { + lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type); + return -1; + } + + if (!sdr->record.genloc->entity.logical) { + /* + * handle physical entity + */ + rsp = sunoem_led_get(intf, sdr->record.genloc, ledtype); + if (rsp && rsp->data_len == 1) { + printf("LED %s is %s\n", + sdr->record.genloc->id_string, + val2str(rsp->data[0], sunoem_led_mode_vals)); + } + return 0; + } + + /* + * handle logical entity for LED grouping + */ + + lprintf(LOG_NOTICE, "LED %s is logical device", argv[0]); + + /* get entity assoc records */ + alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC); + for (a = alist; a != NULL; a = a->next) { + if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC) + continue; + assoc = a->record.entassoc; + if (assoc == NULL) + continue; + + /* check that the entity id/instance matches our generic record */ + if (assoc->entity.id != sdr->record.genloc->entity.id || + assoc->entity.instance != sdr->record.genloc->entity.instance) + continue; + + if (assoc->flags.isrange) { + /* + * handle ranged entity associations + * + * the test for non-zero entity id is handled in + * sunoem_led_get_byentity() + */ + + /* first range set - id 1 and 2 must be equal */ + if (assoc->entity_id_1 == assoc->entity_id_2) + for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++) + sunoem_led_get_byentity(intf, assoc->entity_id_1, i, ledtype); + + /* second range set - id 3 and 4 must be equal */ + if (assoc->entity_id_3 == assoc->entity_id_4) + for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++) + sunoem_led_get_byentity(intf, assoc->entity_id_3, i, ledtype); + } + else { + /* + * handle entity list + */ + sunoem_led_get_byentity(intf, assoc->entity_id_1, + assoc->entity_inst_1, ledtype); + sunoem_led_get_byentity(intf, assoc->entity_id_2, + assoc->entity_inst_2, ledtype); + sunoem_led_get_byentity(intf, assoc->entity_id_3, + assoc->entity_inst_3, ledtype); + sunoem_led_get_byentity(intf, assoc->entity_id_4, + assoc->entity_inst_4, ledtype); + } + } + + __sdr_list_empty(alist); + + return 0; +} + +/* + * IPMI Request Data: 7 bytes + * + * [byte 0] devAddr Value from the "Device Slave Address" field in + * LED's Generic Device Locator record in the SDR + * [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE + * [byte 2] ctrlrAddr Controller address; value from the "Device + * Access Address" field, 0x20 if the LED is local + * [byte 3] hwInfo The OEM field from the SDR record + * [byte 4] mode LED Mode: OFF, ON, STANDBY_BLINK, SLOW_BLINK, FAST_BLINK + * [byte 5] force TRUE - directly access the device + * FALSE - go thru its controller + * Ignored if LED is local + * [byte 6] role Used by BMC for authorization purposes + * + * + * IPMI Response Data: 1 byte + * + * [byte 0] mode LED Mode: OFF, ON, STANDBY_BLINK, SLOW_BLINK, FAST_BLINK + */ + +static int +ipmi_sunoem_led_set(struct ipmi_intf * intf, int argc, char ** argv) +{ + struct ipmi_rs * rsp; + struct sdr_record_list *sdr; + struct sdr_record_list *alist, *a; + struct sdr_record_entity_assoc *assoc; + int ledmode; + int ledtype = 0; + int i; + + /* + * sunoem led set [type] + */ + + if (argc < 2 || strncmp(argv[0], "help", 4) == 0) { + ipmi_sunoem_usage(); + return 0; + } + + ledmode = str2val(argv[1], sunoem_led_mode_vals); + if (ledmode < 0) { + lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]); + return -1; + } + + if (argc > 3) { + ledtype = str2val(argv[2], sunoem_led_type_vals); + if (ledtype < 0) + ledtype = 0; + } + + if (strncasecmp(argv[0], "all", 3) == 0) { + /* do all generic sensors */ + alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR); + for (a = alist; a != NULL; a = a->next) { + if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) + continue; + if (a->record.genloc->entity.logical) + continue; + rsp = sunoem_led_set(intf, a->record.genloc, ledtype, ledmode); + if (rsp && rsp->ccode == 0) { + printf("Set LED %s to %s\n", + a->record.genloc->id_string, + val2str(ledmode, sunoem_led_mode_vals)); + } + } + __sdr_list_empty(alist); + return 0; + } + + /* look up generic device locator records in SDR */ + sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]); + + if (sdr == NULL) { + lprintf(LOG_ERR, "No Sensor Data Record found for %s", + argv[0]); + return -1; + } + + if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) { + lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type); + return -1; + } + + if (!sdr->record.genloc->entity.logical) { + /* + * handle physical entity + */ + rsp = sunoem_led_set(intf, sdr->record.genloc, ledtype, ledmode); + if (rsp && rsp->ccode == 0) { + printf("Set LED %s to %s\n", argv[0], + val2str(ledmode, sunoem_led_mode_vals)); + } + return 0; + } + + /* + * handle logical entity for LED grouping + */ + + lprintf(LOG_NOTICE, "LED %s is logical device", argv[0]); + + /* get entity assoc records */ + alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC); + for (a = alist; a != NULL; a = a->next) { + if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC) + continue; + assoc = a->record.entassoc; + if (assoc == NULL) + continue; + + /* check that the entity id/instance matches our generic record */ + if (assoc->entity.id != sdr->record.genloc->entity.id || + assoc->entity.instance != sdr->record.genloc->entity.instance) + continue; + + if (assoc->flags.isrange) { + /* + * handle ranged entity associations + * + * the test for non-zero entity id is handled in + * sunoem_led_get_byentity() + */ + + /* first range set - id 1 and 2 must be equal */ + if (assoc->entity_id_1 == assoc->entity_id_2) + for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++) + sunoem_led_set_byentity(intf, assoc->entity_id_1, i, ledtype, ledmode); + + /* second range set - id 3 and 4 must be equal */ + if (assoc->entity_id_3 == assoc->entity_id_4) + for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++) + sunoem_led_set_byentity(intf, assoc->entity_id_3, i, ledtype, ledmode); + } + else { + /* + * handle entity list + */ + sunoem_led_set_byentity(intf, assoc->entity_id_1, + assoc->entity_inst_1, ledtype, ledmode); + sunoem_led_set_byentity(intf, assoc->entity_id_2, + assoc->entity_inst_2, ledtype, ledmode); + sunoem_led_set_byentity(intf, assoc->entity_id_3, + assoc->entity_inst_3, ledtype, ledmode); + sunoem_led_set_byentity(intf, assoc->entity_id_4, + assoc->entity_inst_4, ledtype, ledmode); + } + } + + __sdr_list_empty(alist); + + return 0; +} + +static int +ipmi_sunoem_sshkey_del(struct ipmi_intf * intf, uint8_t uid) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(struct ipmi_rq)); + req.msg.netfn = IPMI_NETFN_SUNOEM; + req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY; + req.msg.data = &uid; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to delete ssh key for UID %d", uid); + return -1; + } + else if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid, + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + printf("Deleted SSH key for user id %d\n", uid); + return 0; +} + +#define SSHKEY_BLOCK_SIZE 64 +static int +ipmi_sunoem_sshkey_set(struct ipmi_intf * intf, uint8_t uid, char * ifile) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + FILE * fp; + int count; + uint16_t i_size, r, size; + uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3]; + + if (ifile == NULL) { + lprintf(LOG_ERR, "Invalid or misisng input filename"); + return -1; + } + + fp = ipmi_open_file_read(ifile); + if (fp == NULL) { + lprintf(LOG_ERR, "Unable to open file %s for reading", ifile); + return -1; + } + + printf("Setting SSH key for user id %d...", uid); + + memset(&req, 0, sizeof(struct ipmi_rq)); + req.msg.netfn = IPMI_NETFN_SUNOEM; + req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY; + req.msg.data = wbuf; + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + for (r = 0; r < size; r += i_size) { + i_size = size - r; + if (i_size > SSHKEY_BLOCK_SIZE) + i_size = SSHKEY_BLOCK_SIZE; + + memset(wbuf, 0, SSHKEY_BLOCK_SIZE); + fseek(fp, r, SEEK_SET); + count = fread(wbuf+3, 1, i_size, fp); + if (count != i_size) { + lprintf(LOG_ERR, "Unable to read %d bytes from file %s", i_size, ifile); + fclose(fp); + return -1; + } + + printf("."); + fflush(stdout); + + wbuf[0] = uid; + if ((r + SSHKEY_BLOCK_SIZE) >= size) + wbuf[1] = 0xff; + else + wbuf[1] = (uint8_t)(r / SSHKEY_BLOCK_SIZE); + wbuf[2] = i_size; + req.msg.data_len = i_size + 3; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to set ssh key for UID %d", uid); + break; + } + } + + printf("done\n"); + + fclose(fp); + return 0; +} + + +int +ipmi_sunoem_main(struct ipmi_intf * intf, int argc, char ** argv) +{ + int rc = 0; + + if (argc == 0 || strncmp(argv[0], "help", 4) == 0) { + ipmi_sunoem_usage(); + return 0; + } + + if (strncmp(argv[0], "fan", 3) == 0) { + uint8_t pct; + if (argc < 2) { + ipmi_sunoem_usage(); + return -1; + } + else if (strncmp(argv[1], "speed", 5) == 0) { + if (argc < 3) { + ipmi_sunoem_usage(); + return -1; + } + pct = (uint8_t)strtol(argv[2], NULL, 0); + rc = ipmi_sunoem_fan_speed(intf, pct); + } + else { + ipmi_sunoem_usage(); + return -1; + } + } + + if (strncmp(argv[0], "led", 3) == 0) { + if (argc < 2) { + ipmi_sunoem_usage(); + return -1; + } + if (strncmp(argv[1], "get", 3) == 0) { + if (argc < 3) { + ipmi_sunoem_usage(); + return -1; + } + rc = ipmi_sunoem_led_get(intf, argc-2, &(argv[2])); + } + else if (strncmp(argv[1], "set", 3) == 0) { + if (argc < 4) { + ipmi_sunoem_usage(); + return -1; + } + rc = ipmi_sunoem_led_set(intf, argc-2, &(argv[2])); + } + else { + ipmi_sunoem_usage(); + return -1; + } + } + + if (strncmp(argv[0], "sshkey", 6) == 0) { + if (argc < 2) { + ipmi_sunoem_usage(); + return -1; + } + else if (strncmp(argv[1], "del", 3) == 0) { + uint8_t uid; + if (argc < 3) { + ipmi_sunoem_usage(); + return -1; + } + uid = (uint8_t)strtoul(argv[2], NULL, 0); + rc = ipmi_sunoem_sshkey_del(intf, uid); + } + else if (strncmp(argv[1], "set", 3) == 0) { + uint8_t uid; + if (argc < 4) { + ipmi_sunoem_usage(); + return -1; + } + uid = (uint8_t)strtoul(argv[2], NULL, 0); + rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]); + } + } + + return rc; +} diff --git a/ipmitool/src/ipmitool.c b/ipmitool/src/ipmitool.c index b3447ab..4746095 100644 --- a/ipmitool/src/ipmitool.c +++ b/ipmitool/src/ipmitool.c @@ -57,6 +57,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H # include @@ -90,6 +91,7 @@ struct ipmi_cmd ipmitool_cmd_list[] = { { ipmi_user_main, "user", "Configure Management Controller users" }, { ipmi_channel_main, "channel", "Configure Management Controller channels" }, { ipmi_session_main, "session", "Print session information" }, + { ipmi_sunoem_main, "sunoem", "OEM Commands for Sun servers" }, #ifdef HAVE_READLINE { ipmi_shell_main, "shell", "Launch interactive IPMI shell" }, #endif