/* * bmc_transport.c * * MontaVista IPMI code for emulating a MC. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2012 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Modified BSD Licence * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. */ #include "bmc.h" #include #include #include #include static void handle_ipmi_set_lan_config_parms(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char lchan; channel_t *chan; if (msg->len < 3) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } lchan = msg->data[0]; if (lchan == 0xe) lchan = msg->channel; else if (lchan >= IPMI_MAX_CHANNELS) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (!mc->channels[lchan]) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } chan = mc->channels[lchan]; if (!chan->set_lan_parms) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } chan->set_lan_parms(chan, msg, rdata, rdata_len); } static void handle_ipmi_get_lan_config_parms(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char lchan; channel_t *chan; if (msg->len < 4) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } lchan = msg->data[0]; if (lchan == 0xe) lchan = msg->channel; else if (lchan >= IPMI_MAX_CHANNELS) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (!mc->channels[lchan]) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } chan = mc->channels[lchan]; if (!chan->get_lan_parms) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } chan->get_lan_parms(chan, msg, rdata, rdata_len); } static void handle_set_sol_config_parms(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char err = 0; unsigned char val; int write_config = 0; ipmi_sol_t *sol = &mc->sol; if (!mc->sol.configured) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (msg->len < 3) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } /* * There is a channel in this message, but as far as I can tell, * it is completely without point. The data is generic to the * management controller. So just ignore it. */ switch (msg->data[1]) { case 0: switch (msg->data[2] & 0x3) { case 0: if (sol->set_in_progress) { /* Rollback */ memcpy(&mc->sol.solparm, &mc->sol.solparm_rollback, sizeof(solparm_t)); write_config = 1; } break; case 1: if (sol->set_in_progress) err = 0x81; /* Another user is writing. */ else { /* Save rollback data */ memcpy(&mc->sol.solparm_rollback, &mc->sol.solparm, sizeof(solparm_t)); sol->set_in_progress = 1; } break; case 2: sol->set_in_progress = 0; break; case 3: err = IPMI_INVALID_DATA_FIELD_CC; } break; case 1: sol->solparm.enabled = msg->data[2] & 1; write_config = 1; break; case 5: val = msg->data[2] & 0xf; if ((val < 6) || (val > 0xa)) { err = IPMI_INVALID_DATA_FIELD_CC; } else { sol->solparm.bitrate_nonv = val; write_config = 1; } break; case 6: val = msg->data[2] & 0xf; if ((val < 6) || (val > 0xa)) { err = IPMI_INVALID_DATA_FIELD_CC; } else { sol->solparm.bitrate = val; if (sol->update_bitrate) sol->update_bitrate(mc); } break; default: err = 0x80; /* Parm not supported */ } if (write_config) write_sol_config(mc); rdata[0] = err; *rdata_len = 1; } static void handle_get_sol_config_parms(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { ipmi_sol_t *sol = &mc->sol; unsigned char databyte = 0; if (!mc->sol.configured) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (msg->len < 4) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } /* * There is a channel in this message, but as far as I can tell, * it is completely without point. The data is generic to the * management controller. So just ignore it. */ switch (msg->data[1]) { case 0: databyte = sol->set_in_progress; break; case 1: databyte = sol->solparm.enabled; break; case 5: databyte = sol->solparm.bitrate_nonv; break; case 6: databyte = sol->solparm.bitrate; break; default: rdata[0] = 0x80; /* Parm not supported */ *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = 0x11; rdata[2] = databyte; *rdata_len = 3; } cmd_handler_f transport_netfn_handlers[256] = { [IPMI_SET_LAN_CONFIG_PARMS_CMD] = handle_ipmi_set_lan_config_parms, [IPMI_GET_LAN_CONFIG_PARMS_CMD] = handle_ipmi_get_lan_config_parms, [IPMI_SET_SOL_CONFIGURATION_PARAMETERS] = handle_set_sol_config_parms, [IPMI_GET_SOL_CONFIGURATION_PARAMETERS] = handle_get_sol_config_parms };