OpenIPMI-2.0.33/0000775000175000017500000000000014261607642010172 500000000000000OpenIPMI-2.0.33/TODO0000644000175000017500000000222112002623311010553 00000000000000Add domain statistics to the GUI. Look at integrating ASF info OpenIPMI. Add handling of event data for sensors that have defined event data information specific to that sensor type. Add a way to be notified if children or parents are added to an entity. Add sensor SDRs back into the main SDR repository (if they can from there). Add controls for the GUIDs (system and device) and for the various chassis-related commands. Add the ability to add/remove connections in domains and IP addresses for LAN connections. Firmware firewall configuration xRC4 support Serial port support Various chassis controls (identify, front panel enables, power restore policy, power cycle interval, restart cause) Boot option configuration Implement set channel security keys command Implement a way to get the channel cipher suites for an MC Implement direct serial port interface, including the ability to have disconnected operation. Implement payload control Dynamic address setting for IPMI LAN Settable sensor support (errata E372) Channel forwarding (errata E379) System Info support (errata E381) Suspend BMC ARPs command handling Get IP/UDP/RMCP statistics OpenIPMI-2.0.33/ipmi.sysconf0000644000175000017500000000437012002623311012436 00000000000000## Path: Hardware/IPMI ## Description: Enable standard hardware interfaces (KCS, BT, SMIC) ## Type: yesno ## Default: "yes" ## Config: ipmi # Enable standard hardware interfaces (KCS, BT, SMIC) # You probably want this enabled. IPMI_SI=yes ## Path: Hardware/IPMI ## Description: Enable /dev/ipmi0 interface, used by ipmitool, ipmicmd, ## Type: yesno ## Default: "yes" ## Config: ipmi # Enable /dev/ipmi0 interface, used by ipmitool, ipmicmd, # and other userspace IPMI-using applications. # You probably want this enabled. DEV_IPMI=yes ## Path: Hardware/IPMI ## Description: Enable IPMI_WATCHDOG if you want the IPMI watchdog ## Type: yesno ## Default: "no" ## Config: ipmi # Enable IPMI_WATCHDOG if you want the IPMI watchdog # to reboot the system if it hangs IPMI_WATCHDOG=no ## Path: Hardware/IPMI ## Description: Watchdog options - modinfo ipmi_watchdog for details ## Type: string ## Default: "timeout=60" ## Config: ipmi # Watchdog options - modinfo ipmi_watchdog for details # watchdog timeout value in seconds # as there is no userspace ping application that runs during shutdown, # be sure to give it enough time for any device drivers to # do their cleanup (e.g. megaraid cache flushes) # without the watchdog triggering prematurely IPMI_WATCHDOG_OPTIONS="timeout=60" ## Path: Hardware/IPMI ## Description: Enable IPMI_POWEROFF if you want the IPMI poweroff module to be loaded. ## Type: yesno ## Default: "no" ## Config: ipmi # Enable IPMI_POWEROFF if you want the IPMI # poweroff module to be loaded. IPMI_POWEROFF=no ## Path: Hardware/IPMI ## Description: Enable IPMI_POWERCYCLE if you want the system to be power-cycled on reboot ## Type: yesno ## Default: "no" ## Config: ipmi # Enable IPMI_POWERCYCLE if you want the system to be power-cycled (power # down, delay briefly, power on) rather than power off, on systems # that support such. IPMI_POWEROFF=yes is also required. IPMI_POWERCYCLE=no ## Path: Hardware/IPMI ## Description: Enable "legacy" interfaces for applications ## Type: yesno ## Default: "no" ## Config: ipmi # Enable "legacy" interfaces for applications # Intel IMB driver interface IPMI_IMB=no OpenIPMI-2.0.33/FAQ0000644000175000017500000003364712002623311010435 00000000000000 1) Questions about the driver 1.1) I'm trying to do a send message command, but it fails. Why can't I do this? You know too much about IPMI :-). OpenIPMI does all this work for you. To send a message out on IPMB, you set up an IPMB address and send the message to that address (without all that nasty send message stuff). It's much easier. Try it, you'll like it. 1.2) I *really* want to do a send message command. How do I do it? Sorry, you can't. It's not that I have it out for you, it has to do with the technical details of IPMI. If you have multiple users of an IPMI system, you have to have a central mechanism to manage information. You have sequence numbers that have to be assigned and managed; if the same applications used the same sequence numbers then chaos would ensue. Since the OpenIPMI driver allows multiple users (and has users both inside and outside the kernel) it can't allow users to directly do send message commands. 2) Questions about the library. 2.1) Why is ipmi_ui so ugly? Well, ipmi_ui is a test program that I wrote for my own purposes. I'll try to clean it up in the future and make it into something useful, and it's certainly ugly, but it's primarily for my testing. In general, it has been replace with the ipmish command, which provides a much more consistent interface to the system. It is much more consistent and is well documented. It is perhaps not quite as nice for interactive use. 2.2) What if I just want to send some IPMI commands. Then "ipmicmd" is the tools for you. It can connect to a system interface or to a LAN connection and let you directly enter commands. 2.3) I'm trying to write a little program that comes up and queries a few things. Can I use the OpenIPMI library to do that? Yes, you can. In the ipmi_open_domain() command, you can turn on and off the things you want, so you can trim down the startup process to speed it up. 2.4) Why can't I just perform an operation and immediately get the results? Why all these callbacks? Read the documenation for details. The OpenHPI interface (http://openhpi.sourceforce.net) is expected to sit on top of the OpenIPMI library and provide an interface more like that. Plus, you can write your own wrappers to do it. It's not possible to write event-driven wrappers on top of a non-event-driven interface. 2.5) Can I have multiple OpenIPMI session from different programs to the same interface? Certainly. I do it all the time :-) The main problem is the System Event Log (SEL). Somebody has to delete items from the SEL. You have a couple of options... If you don't care about the SEL, then set the SEL rescan time to zero with ipmi_domain_set_sel_rescan_time() or disable it with the startup options. This will turn off the SEL completely. If you do care about SELs on multiple programs, you will have to develop a protocol between all the users. You have to have a way to let all the listeners get all the SELs, but still delete items from the SEL in a timely manner. I recommend that you set the SEL rescan time to a value, and for every event receive wait double that value before deleting it. OpenIPMI will correctly handle multiple things deleting items from the SEL. 2.6) Can you open more than one IPMI session from OpenIPMI? Certainly. You can create as many connections and domains as you like, the library has no limitiation. 2.7) I have an xyz computer, does OpenIPMI support it? That depends on a lot of things. Does the box have IPMI? Most systems do not, it's currently mostly on high-end system. If the system does have IPMI, OpenIPMI will probably support it. It may not support the full function of your system though. Output devices are not defined by the IPMI spec, so they are all OEM and require custom code to control them. Sensors that do not appear in an SDR repository will not be supported without custom code. Any things custom to the system will probably not be supported. 2.8) What interfaces does OpenIPMI support? OpenIPMI currently supports system interfaces through the OpenIPMI device driver and LAN interfaces. It does not support serial interfaces or any type of callback devices. 2.9) Does OpenIPMI support ICMB? Not currently, although it shouldn't be hard to add. 2.10) How do I learn more about IPMI? Not much information currently exists. The OpenIPMI web site has a pointer to the specs and the documentation that comes with IPMI, but the spec is very hard to read and the documentation is really more marketing level. The documentation that comes with OpenIPMI provides a more gentle introduction to IPMI (you should certainly read it before you read the spec) but it's more focused on OpenIPMI, not IPMI proper. Someone needs to write a book (and it's not going to be me). 2.11) What does OpenIPMI do? OpenIPMI attempts to handle a lot of the difficult parts of IPMI for the user; as much as it can without making too many policy decisions for the user. For instance, it: * Fetches all the SDRs and translates them into sensors and entity information. * Manages access to the SEL. * Handles the interface, which is especially hard for LAN connections. * Handles fetching FRU information for entities. * Lets you deal directly with sensors and entities. * Periodically scans all the information it manages to see if it has changed. * Decodes incoming events, correlates them with sensors, translates raw values into useful values, and delivers them with the sensor object. * Allows OEM code to plug in to fix up things and present non-standard devices through standard interfaces. Basically, the user just has to start up the connection and wait for things to happen. As OpenIPMI finds things, it will report them and the user can take action. It is designed to remove the low-level details from the user's concern and only present the things the user is really interested in handling. 2.12) I don't like the way OpenIPMI does x. You may disagree with implementation decisions I have made and that's fine. You can make suggestions, submit patches, and work with me on this. Or you may write your own IPMI library. Or you may pillage OpenIPMI to get what you want. Like Linus holds final say on what goes into his distribution of Linux, I hold final say on what goes into my distribution of OpenIPMI. But that doesn't mean you can't do your own work on it. 2.13) Why did you write OpenIPMI? OpenIPMI was originally written to support a customer who needed an interface for their IPMI platform. It was also designed with HPI in mind, for something to implement as the base to an HPI library. 2.14) I just want to use pieces of OpenIPMI, can I? Well, it's open source. But unfortunately, OpenIPMI is not terribly modular as a whole. Certain parts (the interface code, for instance) can be used stand-alone. But SDRs, MC, SELs, domains, sensors, etc. all know about each other. It's somewhat inescapable, really, the concepts are intertwined. It would be fairly easy to take any individual piece of the code (the sdr.c code, for instance) and change it to work in a different system, but you would have to change the code to do that. 2.15) Why is the OpenIPMI interface the way it is (bad, good, ugly, elegent, simple, obtuse, etc)? My basic philosophy of API design is: 1) Users should only have to deal with the objects they really care about. You should distill the interface down to what the user really cares about. Think about it from the user's point of view and implement what they want. 2) Users (especially me) have a hard time dealing with large numbers of types. Distill the types down to the essentials. Don't overload types with information that doesn't belong in them, either. Essentials are essentials; don't go beyond them, though. 3) Interfaces should be designed with extensibility in mind. All types should be opaque pointers so that the internal representation and implementation can change without the binary or logical interface changing. If you make an exception on this, it better be for a really good reason. 4) Use the basic types of the language as much as possible. It's better to have more functions than types. I'm very picky about this. I have seen too many bad APIs; ones based on the implementation, not the needs of the user. 2.16) My IPMI system has some broken information in it. Can I fix it in OpenIPMI? Sure. You can write OEM code that ties in to when objects are added to the system and fix them up as necessary. The details of this are beyond the scope of the FAQ, but you can look in lib/oem_*.c for examples. 2.17) It takes a long time to find all the information about a system on IPMB. What's the deal? Unfortunately, the base library can't really know what exists or where it should exist, so it has to scan everything on the bus. You can write an OEM plugin or scan the addresses you are interested in by hand. If you don't care about the information, as of version 1.4.4 you can skip those steps via options to the ipmi_open_domain() function or the startup parms to ipmish or the Perl interface. 2.18) I want to know when OpenIPMI is done finding everything in the system. Unfortunately, there is no concept of "done" in IPMI. IPMI allows a dynamic environment with elements of the system coming and going. You need to re-think your philosophy here and design software that can dynamically manage elements of the system coming and going. OpenIPMI will tell you when it finds things, and then you can manage them. But bowing to popular demand, though, the 1.4 version of OpenIPMI adds a "done" callback to the ipmi_open_domain function that lets you know when OpenIPMI has finished the first pass of everything (SDRs, SELs, FRUs, IPMB scan). There is no guarantee that it found everything in the first pass, and you should handle dynamically adding things later. 2.19) How do I build the Perl interface? The Perl interface uses swig 1.3.22 or later, which is available from http://www.swig.org. That must be installed and in your path to build the Perl interface. You must also have the development libraries for Perl installed, of course. 2.20) How do I catch SNMP traps with OpenIPMI? Although OpenIPMI has infrastructure to handle traps, it does not catch them for you. You have to provide the software to catch the traps and then you can tell OpenIPMI about them. The ui/basic_ui.c code has some example SNMP trap code using the netsmp and ucsdsnmp libraries. 2.21) Why does it take a long time to get events from OpenIPMI? The standard interface to the event log is polled, and the polling time is 5 seconds by default. You can change the polling time if you don't care about the additional load. A system interface (SMI) does have an immediate event receive capability; when an event comes in it goes into the system log and into a queue. OpenIPMI does nt enable tis by default, you must enable it yourself with a "Set BMC Global Enables Command". LAN interfaces may be capable of sending SNMP traps when an event comes in. This is through the Platform Event Traps and is fairly complicated. OpenIPMI provides a way to configure this more easily, but you still have to know what you are doing. See question 2.20 for how to handle these traps. 2.22) What crypto does OpenIPMI implement/use? OpenIPMI implements MD2 and MD5. It's questionable whether those are crypto algorithms or not, but I'm including them just to be sure. For the IPMI 2.0 RMCP+ algorithms, OpenIPMI requires the OpenSSL package. OpenIPMI will work without OpenSSL, but then it will not be able to use the advanced encryption algorithms. The algorithms used by OpenIPMI are: HMAC-SHA1 (96 bit) and HMAC-MD5 (128 bit) for authentication and integrity. AES-CBC (128 bit) is the only option for encryption. In the future, RC4 (40 bit and 128 bit) may be implemented per the spec. The OpenIPMI authentication/encryption framework is pluggable and users could write their own algorithms if they wish. 2.23) How do I interpret the OpenIPMI numeric error values? Nothing should really be printing these values except for logs and tracing. However, a lot of these come out from sample applications. However, I'll go over a little to make tracing and the like easier. The top 8 bits of an error are the error type (basically where the error came from). The rest of the value is the error itself; make sure to use the proper IPMI_xxx_ERR_VAL() to extract it. The error types are: * 00 - An OS error or an error from OpenIPMI itself. These are standard errno values and can be decoded with strerror() and friends. * 01 - An error from the remote management controller (An IPMI error). You can look these up in the IPMI manual. * 02 - RMCP+ error. These are in the IPMI LAN section of the IPMI manual. * 03 - SoL (Serial Over LAN) errors. These are in the SoL section of the IPMI manual. You can convert any of these errors to a human-readable (currently English only) string using ipmi_err_get_string(). See include/OpenIPMI/ipmi_err.h for more details on these things. OpenIPMI-2.0.33/lanserv/0000775000175000017500000000000014261607642011644 500000000000000OpenIPMI-2.0.33/lanserv/TODO0000664000175000017500000000022214002617260012236 00000000000000 * The depends= that is part of the polled file sensor really needs to be part of the main sensor structure, or at least the polled structure. OpenIPMI-2.0.33/lanserv/serial_ipmi.c0000664000175000017500000007440714002617260014227 00000000000000/* * serial_ipmi.c * * MontaVista IPMI LAN server serial port interface. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include #include #define EVENT_BUFFER_GLOBAL_ENABLE (1 << 2) #define EVENT_LOG_GLOBAL_ENABLE (1 << 3) #define SUPPORTED_GLOBAL_ENABLES (EVENT_BUFFER_GLOBAL_ENABLE | \ EVENT_LOG_GLOBAL_ENABLE) static void raw_send(serserv_data_t *si, unsigned char *data, unsigned int len) { if (si->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(si->sysinfo, data, len, "Raw serial send:"); si->send_out(si, data, len); } static unsigned char hex2char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static int fromhex(unsigned char c) { if (isdigit(c)) return c - '0'; else if (isxdigit(c)) return tolower(c) - 'a' + 10; else return -1; } static int unformat_ipmb_msg(msg_t *msg, unsigned char *msgd, unsigned int len, serserv_data_t *si) { if (len < 7) { fprintf(stderr, "Message too short\n"); return -1; } if (ipmb_checksum(msgd, len, 0) != 0) { fprintf(stderr, "Message checksum failure\n"); return -1; } len--; msg->rs_addr = msgd[0]; msg->netfn = msgd[1] >> 2; msg->rs_lun = msgd[1] & 3; msg->rq_addr = msgd[3]; msg->rq_seq = msgd[4] >> 2; msg->rq_lun = msgd[4] & 3; msg->cmd = msgd[5]; msg->len = len - 6; msg->data = msgd + 6; msg->src_addr = NULL; msg->src_len = 0; return 0; } static void format_ipmb_rsp(msg_t *msg, unsigned char *msgd, unsigned int *msgd_len, serserv_data_t *mi) { msgd[0] = msg->rs_addr; msgd[1] = (msg->netfn << 2) | msg->rs_lun; msgd[2] = -ipmb_checksum(msgd, 2, 0); msgd[3] = msg->rq_addr; msgd[4] = (msg->rq_seq << 2) | msg->rq_lun; msgd[5] = msg->cmd; memcpy(msgd + 6, msg->data, msg->len); *msgd_len = msg->len + 6; msgd[*msgd_len] = -ipmb_checksum(msgd + 3, (*msgd_len) - 3, 0); (*msgd_len)++; } static void handle_attn(channel_t *chan, int val, int irq) { serserv_data_t *si = chan->chan_info; if (val && si->do_attn) raw_send(si, si->attn_chars, si->attn_chars_len); } /*********************************************************************** * * Radisys ASCII codec. * ***********************************************************************/ #define RA_MAX_CHARS_SIZE (((IPMI_SIM_MAX_MSG_LENGTH + 1) * 3) + 4) struct ra_data { unsigned char recv_chars[RA_MAX_CHARS_SIZE]; unsigned int recv_chars_len; int recv_chars_too_many; }; static void ra_format_msg(const unsigned char *msg, unsigned int msg_len, serserv_data_t *si) { unsigned int i; unsigned int len; unsigned char c[RA_MAX_CHARS_SIZE]; len = 0; for (i = 0; i < msg_len; i++) { c[len] = hex2char[msg[i] >> 4]; len++; c[len] = hex2char[msg[i] & 0xf]; len++; } c[len] = 0x0d; len++; raw_send(si, c, len); } static int ra_ipmb_handler(channel_t *chan, msg_t *msg) { serserv_data_t *si = chan->chan_info; ra_format_msg(msg->data, msg->len, si); free(msg); return 1; } /* * Called when the '0x0d' is seen. */ static int ra_unformat_msg(unsigned char *r, unsigned int len, serserv_data_t *si) { unsigned char real_o[IPMI_SIM_MAX_MSG_LENGTH + 1]; unsigned char *o = real_o + 1; msg_t msg; unsigned int p = 0; unsigned int i = 0; int rv; if (si->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(si->sysinfo, r, len, "Raw serial receive:"); while (p < len) { rv = fromhex(r[p]); if (rv < 0) return rv; o[i] = rv << 4; p++; if (p >= len) return -1; rv = fromhex(r[p]); if (rv < 0) return rv; o[i] |= rv; p++; i++; } if (i < 1) return -1; memset(&msg, 0, sizeof(msg)); if ((o[0] == si->sysinfo->bmc_ipmb) || (o[0] == 1)) { rv = unformat_ipmb_msg(&msg, o, i, si); if (rv) return rv; } else { msg.rs_addr = 1; msg.netfn = IPMI_APP_NETFN; msg.rs_lun = 0; msg.rq_addr = 1; msg.rq_seq = 0; msg.rq_lun = 0; msg.cmd = IPMI_SEND_MSG_CMD; msg.len = i + 1; msg.data = real_o; real_o[0] = 0; } channel_smi_send(&si->channel, &msg); return 0; } static void ra_handle_char(unsigned char ch, serserv_data_t *si) { struct ra_data *info = si->codec_info; unsigned int len = info->recv_chars_len; unsigned char *r; int rv; if (ch == 0x0d) { /* End of command, handle it. */ if (info->recv_chars_too_many) { /* Input data overrun. */ fprintf(stderr, "Data overrun\n"); info->recv_chars_too_many = 0; info->recv_chars_len = 0; return; } rv = ra_unformat_msg(info->recv_chars, info->recv_chars_len, si); info->recv_chars_too_many = 0; info->recv_chars_len = 0; if (rv) { /* Bad input data. */ fprintf(stderr, "Bad input data\n"); return; } return; } if (info->recv_chars_too_many) return; r = info->recv_chars; if (len >= sizeof(info->recv_chars)) { info->recv_chars_too_many = 1; } else if ((len > 0) && isspace(r[len-1]) && isspace(ch)) { /* Ignore multiple spaces together. */ } else { r[len] = ch; info->recv_chars_len++; } } static void ra_send(msg_t *omsg, serserv_data_t *si) { unsigned char msg[IPMI_SIM_MAX_MSG_LENGTH + 7]; unsigned int msg_len; if (omsg->netfn == IPMI_APP_NETFN && omsg->cmd == IPMI_SEND_MSG_CMD) return; /* These are dummies, ignore them. */ format_ipmb_rsp(omsg, msg, &msg_len, si); ra_format_msg(msg, msg_len, si); } int ra_setup(serserv_data_t *si) { struct ra_data *info; info = malloc(sizeof(*info)); if (!info) return -1; info->recv_chars_len = 0; info->recv_chars_too_many = 0; si->codec_info = info; si->channel.recv_in_q = ra_ipmb_handler; return 0; } /*********************************************************************** * * Direct Mode codec. * ***********************************************************************/ #define DM_START_CHAR 0xA0 #define DM_STOP_CHAR 0xA5 #define DM_PACKET_HANDSHAKE 0xA6 #define DM_DATA_ESCAPE_CHAR 0xAA struct dm_data { unsigned char recv_msg[IPMI_SIM_MAX_MSG_LENGTH + 4]; unsigned int recv_msg_len; int recv_msg_too_many; int in_recv_msg; int in_escape; }; static void dm_handle_msg(unsigned char *imsg, unsigned int len, serserv_data_t *si) { int rv; msg_t msg; if (si->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(si->sysinfo, imsg, len, "Raw serial receive:"); memset(&msg, 0, sizeof(msg)); rv = unformat_ipmb_msg(&msg, imsg, len, si); if (rv) return; channel_smi_send(&si->channel, &msg); } static void dm_handle_char(unsigned char ch, serserv_data_t *si) { struct dm_data *info = si->codec_info; unsigned int len = info->recv_msg_len; unsigned char c; switch (ch) { case DM_START_CHAR: if (info->in_recv_msg) fprintf(stderr, "Msg started in the middle of another\n"); info->in_recv_msg = 1; info->recv_msg_len = 0; info->recv_msg_too_many = 0; info->in_escape = 0; break; case DM_STOP_CHAR: if (!info->in_recv_msg) fprintf(stderr, "Empty message\n"); else if (info->in_escape) { info->in_recv_msg = 0; fprintf(stderr, "Message ended in escape\n"); } else if (info->recv_msg_too_many) { fprintf(stderr, "Message too long\n"); info->in_recv_msg = 0; } else { dm_handle_msg(info->recv_msg, info->recv_msg_len, si); info->in_recv_msg = 0; } info->in_escape = 0; c = DM_PACKET_HANDSHAKE; raw_send(si, &c, 1); break; case DM_PACKET_HANDSHAKE: info->in_escape = 0; break; case DM_DATA_ESCAPE_CHAR: if (!info->recv_msg_too_many) info->in_escape = 1; break; default: if (!info->in_recv_msg) /* Ignore characters outside of messages. */ break; if (info->in_escape) { info->in_escape = 0; switch (ch) { case 0xB0: ch = DM_START_CHAR; break; case 0xB5: ch = DM_STOP_CHAR; break; case 0xB6: ch = DM_PACKET_HANDSHAKE; break; case 0xBA: ch = DM_DATA_ESCAPE_CHAR; break; case 0x3B: ch = 0x1b; break; default: fprintf(stderr, "Invalid escape char: 0x%x\n", ch); info->recv_msg_too_many = 1; return; } } if (!info->recv_msg_too_many) { if (len >= sizeof(info->recv_msg)) { info->recv_msg_too_many = 1; break; } info->recv_msg[len] = ch; info->recv_msg_len++; } break; } } static void dm_send(msg_t *imsg, serserv_data_t *si) { unsigned int i; unsigned int len = 0; unsigned char c[(IPMI_SIM_MAX_MSG_LENGTH + 7) * 2]; unsigned char msg[IPMI_SIM_MAX_MSG_LENGTH + 7]; unsigned int msg_len; format_ipmb_rsp(imsg, msg, &msg_len, si); c[len++] = 0xA0; for (i = 0; i < msg_len; i++) { switch (msg[i]) { case 0xA0: c[len++] = 0xAA; c[len++] = 0xB0; break; case 0xA5: c[len++] = 0xAA; c[len++] = 0xB5; break; case 0xA6: c[len++] = 0xAA; c[len++] = 0xB6; break; case 0xAA: c[len++] = 0xAA; c[len++] = 0xBA; break; case 0x1B: c[len++] = 0xAA; c[len++] = 0x3B; break; default: c[len++] = msg[i]; } } c[len++] = 0xA5; raw_send(si, c, len); } static int dm_setup(serserv_data_t *si) { struct dm_data *info; info = malloc(sizeof(*info)); if (!info) return -1; memset(info, 0, sizeof(*info)); si->channel.set_atn = handle_attn; si->codec_info = info; return 0; } /*********************************************************************** * * Terminal Mode codec. * ***********************************************************************/ #define TM_MAX_CHARS_SIZE (((IPMI_SIM_MAX_MSG_LENGTH + 1) * 3) + 4) struct tm_data { unsigned char recv_chars[TM_MAX_CHARS_SIZE]; unsigned int recv_chars_len; int recv_chars_too_many; }; static void tm_send(msg_t *msg, serserv_data_t *si) { unsigned int i; unsigned int len; unsigned char c[TM_MAX_CHARS_SIZE]; unsigned char t; len = 0; c[len] = '['; len++; t = msg->netfn << 2 | msg->rs_lun; c[len] = hex2char[t >> 4]; len++; c[len] = hex2char[t & 0xf]; len++; /* * Insert the sequence number and bridge bits. Bridge bits * are always zero. */ t = msg->rq_seq << 2; c[len] = hex2char[t >> 4]; len++; c[len] = hex2char[t & 0xf]; len++; c[len] = hex2char[msg->cmd >> 4]; len++; c[len] = hex2char[msg->cmd & 0xf]; len++; /* Now the rest of the message. */ for (i = 0; ; ) { c[len] = hex2char[msg->data[i] >> 4]; len++; c[len] = hex2char[msg->data[i] & 0xf]; len++; i++; if (i == msg->len) break; c[len] = ' '; len++; } c[len] = ']'; len++; c[len] = 0x0a; len++; raw_send(si, c, len); } /* * Called when the ']' is seen, the leading '[' is removed, too. We * get this with a leading space and no more than one space between * items. */ static int tm_unformat_msg(unsigned char *r, unsigned int len, serserv_data_t *si) { unsigned char o[IPMI_SIM_MAX_MSG_LENGTH]; msg_t msg; unsigned int p = 0; unsigned int i = 0; int rv; if (si->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(si->sysinfo, r, len, "Raw serial receive:"); #define SKIP_SPACE if (isspace(r[p])) p++ #define ENSURE_MORE if (p >= len) return -1 SKIP_SPACE; while (p < len) { if (i >= sizeof(o)) return -1; ENSURE_MORE; rv = fromhex(r[p]); if (rv < 0) return rv; o[i] = rv << 4; p++; ENSURE_MORE; rv = fromhex(r[p]); if (rv < 0) return rv; o[i] |= rv; p++; i++; SKIP_SPACE; } if (i < 3) return -1; memset(&msg, 0, sizeof(msg)); msg.netfn = o[0] >> 2; msg.rq_lun = o[0] & 3; msg.rq_seq = o[1] >> 2; msg.cmd = o[2]; msg.data = o + 3; msg.len = i - 3; msg.src_addr = NULL; msg.src_len = 0; channel_smi_send(&si->channel, &msg); return 0; #undef SKIP_SPACE #undef ENSURE_MORE } static void tm_handle_char(unsigned char ch, serserv_data_t *si) { struct tm_data *info = si->codec_info; unsigned int len = info->recv_chars_len; unsigned char *r; int rv; if (ch == '[') { /* * Start of a command. Note that if a command is * already in progress (len != 0) we abort it. */ if (len != 0) fprintf(stderr, "Msg started in the middle of another\n"); /* Convert the leading '[' to a space, that's innocuous. */ info->recv_chars[0] = ' '; info->recv_chars_len = 1; info->recv_chars_too_many = 0; return; } if (len == 0) /* Ignore everything outside [ ]. */ return; if (ch == ']') { /* End of command, handle it. */ if (info->recv_chars_too_many) { /* Input data overrun. */ fprintf(stderr, "Data overrun\n"); info->recv_chars_too_many = 0; info->recv_chars_len = 0; return; } rv = tm_unformat_msg(info->recv_chars, info->recv_chars_len, si); info->recv_chars_too_many = 0; info->recv_chars_len = 0; if (rv) { /* Bad input data. */ fprintf(stderr, "Bad input data\n"); return; } return; } if (info->recv_chars_too_many) return; r = info->recv_chars; if (len >= sizeof(info->recv_chars)) { info->recv_chars_too_many = 1; } else if ((len > 0) && isspace(r[len-1]) && isspace(ch)) { /* Ignore multiple spaces together. */ } else { r[len] = ch; info->recv_chars_len++; } } static int tm_setup(serserv_data_t *si) { struct tm_data *info; info = malloc(sizeof(*info)); if (!info) return -1; info->recv_chars_len = 0; info->recv_chars_too_many = 0; si->channel.set_atn = handle_attn; si->codec_info = info; return 0; } /*********************************************************************** * * VM Mode codec. * ***********************************************************************/ /* * This protocol has an end-of-message marker, everything from the * beginning or the last end of message is a new message (or command). * Messages are normal IPMI messages with the following header: * * seq * netfn << 2 | lun * cmd * data.... * checksum * * The sequence is return in the response as-is. * Commands are special things to alert the other end of things like * attn, requests for reset/nmi/etc. */ #define VM_MSG_CHAR 0xA0 /* Marks end of message */ #define VM_CMD_CHAR 0xA1 /* Marks end of a command */ #define VM_ESCAPE_CHAR 0xAA /* Set bit 4 from the next byte to 0 */ #define VM_PROTOCOL_VERSION 1 #define VM_CMD_VERSION 0xff /* A version number byte follows */ #define VM_CMD_NOATTN 0x00 #define VM_CMD_ATTN 0x01 #define VM_CMD_ATTN_IRQ 0x02 #define VM_CMD_POWEROFF 0x03 #define VM_CMD_RESET 0x04 #define VM_CMD_ENABLE_IRQ 0x05 /* Enable/disable the messaging irq */ #define VM_CMD_DISABLE_IRQ 0x06 #define VM_CMD_SEND_NMI 0x07 #define VM_CMD_CAPABILITIES 0x08 #define VM_CAPABILITIES_POWER 0x01 #define VM_CAPABILITIES_RESET 0x02 #define VM_CAPABILITIES_IRQ 0x04 #define VM_CAPABILITIES_NMI 0x08 #define VM_CAPABILITIES_ATTN 0x10 #define VM_CAPABILITIES_GRACEFUL_SHUTDOWN 0x20 #define VM_CMD_GRACEFUL_SHUTDOWN 0x09 struct vm_data { unsigned char recv_msg[IPMI_SIM_MAX_MSG_LENGTH + 4]; unsigned int recv_msg_len; int recv_msg_too_many; int in_escape; int attn_works; }; static void vm_handle_msg(unsigned char *imsg, unsigned int len, serserv_data_t *si) { msg_t msg; if (si->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(si->sysinfo, imsg, len, "Raw serial receive:"); if (len < 4) { fprintf(stderr, "Message too short\n"); return; } if (ipmb_checksum(imsg, len, 0) != 0) { fprintf(stderr, "Message checksum failure\n"); return; } len--; memset(&msg, 0, sizeof(msg)); msg.rq_seq = imsg[0]; msg.netfn = imsg[1] >> 2; msg.rs_lun = imsg[1] & 0x3; msg.cmd = imsg[2]; msg.len = len - 3; msg.data = imsg + 3; channel_smi_send(&si->channel, &msg); } static void vm_handle_cmd(unsigned char *imsg, unsigned int len, serserv_data_t *si) { struct vm_data *info = si->codec_info; if (si->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(si->sysinfo, imsg, len, "Raw serial cmd:"); if (len < 1) return; switch (imsg[0]) { case VM_CMD_VERSION: /* We only support one version for now. */ break; case VM_CMD_CAPABILITIES: if (len < 2) return; if (imsg[1] & VM_CAPABILITIES_POWER) si->channel.hw_capabilities |= (1 << HW_OP_POWERON); if (imsg[1] & VM_CAPABILITIES_GRACEFUL_SHUTDOWN) si->channel.hw_capabilities |= (1 << HW_OP_GRACEFUL_SHUTDOWN); if (imsg[1] & VM_CAPABILITIES_RESET) si->channel.hw_capabilities |= (1 << HW_OP_RESET); if (imsg[1] & VM_CAPABILITIES_IRQ) si->channel.hw_capabilities |= (1 << HW_OP_IRQ_ENABLE); if (imsg[1] & VM_CAPABILITIES_NMI) si->channel.hw_capabilities |= (1 << HW_OP_SEND_NMI); if (imsg[1] & VM_CAPABILITIES_ATTN) info->attn_works = 1; break; case VM_CMD_RESET: /* The remote end reset, report it. */ if (si->sysinfo->target_reset) si->sysinfo->target_reset(si->sysinfo); break; } } static void vm_handle_char(unsigned char ch, serserv_data_t *si) { struct vm_data *info = si->codec_info; unsigned int len = info->recv_msg_len; switch (ch) { case VM_MSG_CHAR: case VM_CMD_CHAR: if (info->in_escape) { fprintf(stderr, "Message ended in escape\n"); } else if (info->recv_msg_too_many) { fprintf(stderr, "Message too long\n"); } else if (info->recv_msg_len == 0) { /* Nothing to do */ } else if (ch == VM_MSG_CHAR) { vm_handle_msg(info->recv_msg, info->recv_msg_len, si); } else if (ch == VM_CMD_CHAR) { vm_handle_cmd(info->recv_msg, info->recv_msg_len, si); } info->in_escape = 0; info->recv_msg_len = 0; info->recv_msg_too_many = 0; break; case VM_ESCAPE_CHAR: if (!info->recv_msg_too_many) info->in_escape = 1; break; default: if (info->in_escape) { info->in_escape = 0; ch &= ~0x10; } if (!info->recv_msg_too_many) { if (len >= sizeof(info->recv_msg)) { info->recv_msg_too_many = 1; break; } info->recv_msg[len] = ch; info->recv_msg_len++; } break; } } static void vm_add_char(unsigned char ch, unsigned char *c, unsigned int *pos) { switch (ch) { case VM_MSG_CHAR: case VM_CMD_CHAR: case VM_ESCAPE_CHAR: c[(*pos)++] = VM_ESCAPE_CHAR; c[(*pos)++] = ch | 0x10; break; default: c[(*pos)++] = ch; } } static void vm_send(msg_t *imsg, serserv_data_t *si) { unsigned int i; unsigned int len = 0; unsigned char c[(IPMI_SIM_MAX_MSG_LENGTH + 7) * 2]; unsigned char csum; unsigned char ch; ch = imsg->rq_seq; vm_add_char(ch, c, &len); csum = ipmb_checksum(&ch, 1, 0); ch = (imsg->netfn << 2) | imsg->rs_lun; vm_add_char(ch, c, &len); csum = ipmb_checksum(&ch, 1, csum); vm_add_char(imsg->cmd, c, &len); csum = ipmb_checksum(&imsg->cmd, 1, csum); for (i = 0; i < imsg->len; i++) vm_add_char(imsg->data[i], c, &len); vm_add_char(-ipmb_checksum(imsg->data, imsg->len, csum), c, &len); c[len++] = VM_MSG_CHAR; raw_send(si, c, len); } static void vm_set_attn(channel_t *chan, int val, int irq) { serserv_data_t *si = chan->chan_info; unsigned int len = 0; unsigned char c[3]; if (!val) vm_add_char(VM_CMD_NOATTN, c, &len); else if (irq) vm_add_char(VM_CMD_ATTN_IRQ, c, &len); else vm_add_char(VM_CMD_ATTN, c, &len); c[len++] = VM_CMD_CHAR; raw_send(si, c, len); } static int vm_hw_op(channel_t *chan, unsigned int op) { serserv_data_t *si = chan->chan_info; unsigned int len = 0; unsigned char c[3]; switch(op) { case HW_OP_RESET: vm_add_char(VM_CMD_RESET, c, &len); break; case HW_OP_POWERON: if (chan->start_cmd) chan->start_cmd(chan); return 0; case HW_OP_POWEROFF: if (si->connected) vm_add_char(VM_CMD_POWEROFF, c, &len); if (chan->stop_cmd) chan->stop_cmd(chan, !si->connected); break; case HW_OP_GRACEFUL_SHUTDOWN: if (si->connected) vm_add_char(VM_CMD_GRACEFUL_SHUTDOWN, c, &len); break; case HW_OP_SEND_NMI: vm_add_char(VM_CMD_SEND_NMI, c, &len); break; case HW_OP_IRQ_ENABLE: vm_add_char(VM_CMD_ENABLE_IRQ, c, &len); break; case HW_OP_IRQ_DISABLE: vm_add_char(VM_CMD_DISABLE_IRQ, c, &len); break; case HW_OP_CHECK_POWER: return si->connected; break; default: return 0; } c[len++] = VM_CMD_CHAR; raw_send(si, c, len); return 0; } static void vm_connected(serserv_data_t *si) { unsigned int len = 0; unsigned char c[5]; vm_add_char(VM_CMD_VERSION, c, &len); vm_add_char(VM_PROTOCOL_VERSION, c, &len); c[len++] = VM_CMD_CHAR; raw_send(si, c, len); si->connected = 1; if (si->sysinfo->resend_atn) si->sysinfo->resend_atn(&si->channel); } static void vm_disconnected(serserv_data_t *si) { si->connected = 0; } static int vm_setup(serserv_data_t *si) { struct vm_data *info; info = malloc(sizeof(*info)); if (!info) return -1; memset(info, 0, sizeof(*info)); si->codec_info = info; si->channel.hw_op = vm_hw_op; si->channel.set_atn = vm_set_attn; si->channel.hw_capabilities = (1 << HW_OP_POWERON); return 0; } /*********************************************************************** * * codec structure * ***********************************************************************/ static ser_codec_t codecs[] = { { "TerminalMode", tm_handle_char, tm_send, tm_setup }, { "Direct", dm_handle_char, dm_send, dm_setup }, { "RadisysAscii", ra_handle_char, ra_send, ra_setup }, { "VM", vm_handle_char, vm_send, vm_setup, vm_connected, vm_disconnected }, { NULL } }; static ser_codec_t * ser_lookup_codec(const char *name) { unsigned int i; for (i = 0; codecs[i].name; i++) { if (strcmp(codecs[i].name, name) == 0) return &codecs[i]; } return NULL; } #define PP_GET_SERIAL_INTF_CMD 0x01 #define PP_SET_SERIAL_INTF_CMD 0x02 static unsigned char pp_oem_chars[] = { 0x00, 0x40, 0x0a }; static int pp_oem_handler(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { serserv_data_t *ser = chan->chan_info; if (msg->netfn != IPMI_OEM_GROUP_NETFN) return 0; if ((msg->len < 3) || (memcmp(msg->data, pp_oem_chars, 3) != 0)) return 0; switch (msg->cmd) { case PP_GET_SERIAL_INTF_CMD: rdata[0] = 0; memcpy(rdata + 1, pp_oem_chars, 3); rdata[4] = 0; if (msg->data[3] == 1) rdata[4] |= ser->echo; *rdata_len = 5; return 1; case PP_SET_SERIAL_INTF_CMD: if (msg->len < 5) rdata[0] = 0xcc; else if (msg->data[3] == 1) { ser->echo = msg->data[4] & 1; rdata[0] = 0; } memcpy(rdata + 1, pp_oem_chars, 3); *rdata_len = 4; return 1; } return 0; } static void pp_oem_init(serserv_data_t *ser) { ser->echo = 1; ser->channel.oem_intf_recv_handler = pp_oem_handler; } #define RA_CONTROLLER_OEM_NETFN 0x3e #define RA_GET_IPMB_ADDR_CMD 0x12 static int ra_oem_handler(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { serserv_data_t *ser = chan->chan_info; if (msg->netfn == RA_CONTROLLER_OEM_NETFN) { switch (msg->cmd) { case RA_GET_IPMB_ADDR_CMD: rdata[0] = 0; rdata[1] = ser->my_ipmb; *rdata_len = 2; return 1; } } else if (msg->netfn == IPMI_APP_NETFN) { switch (msg->cmd) { case IPMI_GET_MSG_FLAGS_CMD: /* No message flag support. */ rdata[0] = 0xc1; *rdata_len = 1; return 1; } } return 0; } static void ra_oem_init(serserv_data_t *ser) { ser->channel.oem_intf_recv_handler = ra_oem_handler; } static ser_oem_handler_t oem_handlers[] = { { "PigeonPoint", pp_oem_handler, pp_oem_init }, { "Radisys", ra_oem_handler, ra_oem_init }, { NULL } }; static ser_oem_handler_t * ser_lookup_oem(const char *name) { unsigned int i; for (i = 0; oem_handlers[i].name; i++) { if (strcmp(oem_handlers[i].name, name) == 0) return &oem_handlers[i]; } return NULL; } static void ser_return_rsp(channel_t *chan, msg_t *imsg, rsp_msg_t *rsp) { serserv_data_t *ser = chan->chan_info; msg_t msg; if (!ser->connected) return; msg.netfn = rsp->netfn; msg.cmd = rsp->cmd; msg.data = rsp->data; msg.len = rsp->data_len; msg.rq_lun = imsg->rs_lun; msg.rq_addr = imsg->rs_addr; msg.rs_lun = imsg->rq_lun; msg.rs_addr = imsg->rq_addr; msg.rq_seq = imsg->rq_seq; ser->codec->send(&msg, ser); } void serserv_handle_data(serserv_data_t *ser, uint8_t *data, unsigned int len) { unsigned int i; for (i = 0; i < len; i++) ser->codec->handle_char(data[i], ser); } int serserv_init(serserv_data_t *ser) { ser->channel.return_rsp = ser_return_rsp; ser->codec->setup(ser); if (ser->oem) ser->oem->init(ser); chan_init(&ser->channel); return 0; } int serserv_read_config(char **tokptr, sys_data_t *sys, const char **errstr) { serserv_data_t *ser; const char *tok, *tok2; char *endp; int err; unsigned int chan_num; ser = malloc(sizeof(*ser)); if (!ser) { *errstr = "Out of memory"; return -1; } memset(ser, 0, sizeof(*ser)); tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *errstr = "No channel given"; goto out_err; } ser->channel.session_support = IPMI_CHANNEL_SESSION_LESS; ser->channel.medium_type = IPMI_CHANNEL_MEDIUM_RS232; if (strcmp(tok, "kcs") == 0) { chan_num = 15; ser->channel.protocol_type = IPMI_CHANNEL_PROTOCOL_KCS; } else if (strcmp(tok, "bt") == 0) { chan_num = 15; ser->channel.protocol_type = IPMI_CHANNEL_PROTOCOL_BT_v15; } else if (strcmp(tok, "smic") == 0) { chan_num = 15; ser->channel.protocol_type = IPMI_CHANNEL_PROTOCOL_SMIC; } else { chan_num = strtoul(tok, &endp, 0); if (*endp != '\0') { *errstr = "Channel not a valid number"; goto out_err; } ser->channel.protocol_type = IPMI_CHANNEL_PROTOCOL_TMODE; } if (chan_num != 15) { *errstr = "Only BMC channel (channel 15, or kcs/bt/smic) is" " supported for serial"; goto out_err; } if (sys->chan_set[chan_num]) { *errstr = "System channel already defined"; goto out_err; } ser->channel.channel_num = chan_num; err = get_sock_addr(tokptr, &ser->addr.addr, &ser->addr.addr_len, NULL, SOCK_STREAM, errstr); if (err) goto out_err; for (tok = mystrtok(NULL, " \t\n", tokptr); tok; tok = mystrtok(NULL, " \t\n", tokptr)) { if (strcmp(tok, "connect") == 0) { ser->do_connect = 1; continue; } tok2 = mystrtok(NULL, " \t\n", tokptr); if (strcmp(tok, "codec") == 0) { if (!tok2) { *errstr = "Missing parameter for codec"; return -1; } ser->codec = ser_lookup_codec(tok2); if (!ser->codec) { *errstr = "Invalid codec"; return -1; } } else if (strcmp(tok, "oem") == 0) { if (!tok2) { *errstr = "Missing parameter for oem"; return -1; } ser->oem = ser_lookup_oem(tok2); if (!ser->oem) { *errstr = "Invalid oem setting"; return -1; } } else if (strcmp(tok, "attn") == 0) { unsigned int pos = 0; char *tokptr2 = NULL; if (!tok2) { *errstr = "Missing parameter for attn"; return -1; } ser->do_attn = 1; tok2 = mystrtok((char *) tok2, ",", &tokptr2); while (tok2) { if (pos >= sizeof(ser->attn_chars)) { *errstr = "Too many attn characters"; return -1; } ser->attn_chars[pos] = strtoul(tok2, &endp, 0); if (*endp != '\0') { *errstr = "Invalid attn value"; return -1; } pos++; tok2 = mystrtok(NULL, ",", &tokptr2); } ser->attn_chars_len = pos; } else if (strcmp(tok, "ipmb") == 0) { char *endp; ser->my_ipmb = strtoul(tok2, &endp, 0); if (*endp != '\0') { *errstr = "Invalid IPMB address"; return -1; } } else { *errstr = "Invalid setting, not connect, codec, oem, attn, or ipmb"; return -1; } } if (!ser->codec) { *errstr = "codec not specified"; goto out_err; } ser->sysinfo = sys; ser->channel.chan_info = ser; sys->chan_set[chan_num] = &ser->channel; return 0; out_err: free(ser); return -1; } OpenIPMI-2.0.33/lanserv/bmc_picmg.c0000664000175000017500000007213713576426563013673 00000000000000/* * bmc_picmg.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 #include #include int ipmi_mc_set_power(lmc_data_t *mc, unsigned char power, int gen_event) { lmc_data_t *dest_mc; unsigned char data[13]; int rv; if (mc->power_value == power) return 0; mc->power_value = power; if ((mc->event_receiver == 0) || (!gen_event)) return 0; rv = ipmi_emu_get_mc_by_addr(mc->emu, mc->event_receiver, &dest_mc); if (rv) return 0; /* Timestamp is ignored. */ data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = 0x20; /* These come from 0x20. */ data[5] = 0; data[6] = 0x01; /* Version 1. */ data[7] = 0; data[8] = 0x40; /* IPMB of the device being powered. */ data[9] = 0; data[10] = power; data[11] = 0; data[12] = 0; mc_new_event(dest_mc, 0xc0, data); return 0; } static void handle_set_power(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (check_msg_length(msg, 1, rdata, rdata_len)) return; ipmi_mc_set_power(mc, msg->data[0], 1); rdata[0] = 0; *rdata_len = 1; } static void handle_get_power(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { rdata[0] = 0; rdata[1] = mc->power_value; *rdata_len = 2; } static void handle_set_hs_led(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (check_msg_length(msg, 1, rdata, rdata_len)) return; mc->leds[0].color = msg->data[0]; printf("Setting hotswap LED to %d\n", msg->data[0]); rdata[0] = 0; *rdata_len = 1; } static void handle_get_hs_led(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { rdata[0] = 0; rdata[1] = mc->leds[0].color; *rdata_len = 2; } cmd_handler_f oem0_netfn_handlers[256] = { [0x01] = handle_set_power, [0x02] = handle_get_power, [0x03] = handle_set_hs_led, [0x04] = handle_get_hs_led }; static void handle_picmg_get_properties(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; rdata[2] = 0x22; /* Version 2.2 */ rdata[3] = 0; /* Only have one FRU. */ rdata[4] = 0; /* As defined by spec. */ *rdata_len = 5; } static void handle_picmg_get_address_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { atca_site_t *sites = mc->emu->atca_sites; unsigned char hw_addr = mc->ipmb >> 1; unsigned char devid = 0; int i; if (msg->len == 3) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (msg->len >= 2) devid = msg->data[1]; if (msg->len >= 4) { switch (msg->data[2]) { case 0: hw_addr = msg->data[3]; break; case 1: hw_addr = msg->data[3] >> 1; break; case 3: if (msg->len < 5) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } for (i=0; i<128; i++) { if (sites[i].valid && (sites[i].site_type == msg->data[4]) && (sites[i].site_number == msg->data[3])) { break; } } if (i == 128) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } hw_addr = i; break; default: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } } if ((hw_addr >= 128) || (!sites[hw_addr].valid) || (devid > 0)) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; rdata[2] = hw_addr; rdata[3] = hw_addr << 1; rdata[4] = 0xff; rdata[5] = devid; rdata[6] = sites[hw_addr].site_number; rdata[7] = sites[hw_addr].site_type; *rdata_len = 8; } static void handle_picmg_cmd_fru_control(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (check_msg_length(msg, 3, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } if (msg->data[2] >= 4) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } /* Nothing to reset. */ printf("Fru control set to %d\n", msg->data[2]); rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; *rdata_len = 2; } static void handle_picmg_cmd_get_fru_led_properties(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (check_msg_length(msg, 2, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; if (mc->num_leds <= 2) { mc->num_leds = 2; rdata[2] = 0x03; /* We support the first 2 LEDs. */ rdata[3] = 0x00; } else if (mc->num_leds == 3) { rdata[2] = 0x07; /* We support the first 3 LEDs. */ rdata[3] = 0x00; } else { rdata[2] = 0xf; /* We support the first 4 LEDs. */ rdata[3] = mc->num_leds = 4; /* How many more do we support? */ } *rdata_len = 4; } static void handle_picmg_cmd_get_led_color_capabilities(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned int led; if (check_msg_length(msg, 3, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } led = msg->data[2]; if (led >= mc->num_leds) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; rdata[2] = mc->leds[led].color_sup; rdata[3] = mc->leds[led].def_loc_cnt_color; rdata[4] = mc->leds[led].def_override_color; *rdata_len = 5; } void picmg_led_set(lmc_data_t *mc, sensor_t *sensor) { printf("ATCA hot-swap state is %d\n", sensor->value); switch (sensor->value) { case 0: case 3: case 4: /* off */ mc->leds[0].def_off_dur = 0; mc->leds[0].def_on_dur = 0; break; case 1: /* on */ mc->leds[0].def_off_dur = 0xff; mc->leds[0].def_on_dur = 0; break; case 2: /* long blink */ mc->leds[0].def_off_dur = 10; mc->leds[0].def_on_dur = 90; break; case 5: case 6: /* short blink */ mc->leds[0].def_off_dur = 90; mc->leds[0].def_on_dur = 10; break; case 7: /* Nothing to do */ break; } if (mc->leds[0].loc_cnt) { mc->leds[0].off_dur = mc->leds[0].def_off_dur; mc->leds[0].on_dur = mc->leds[0].def_on_dur; printf("Setting ATCA LED %d to %s %x %x %x\n", 0, mc->leds[0].loc_cnt ? "local_control" : "override", mc->leds[0].off_dur, mc->leds[0].on_dur, mc->leds[0].color); } } static void handle_picmg_cmd_set_fru_led_state(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned int led; if (check_msg_length(msg, 3, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } led = msg->data[2]; if (led >= mc->num_leds) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } switch (msg->data[3]) { case 0xfc: /* Local control */ if (!mc->leds[led].loc_cnt_sup) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } mc->leds[led].loc_cnt = 1; mc->leds[led].off_dur = mc->leds[led].def_off_dur; mc->leds[led].on_dur = mc->leds[led].def_on_dur; mc->leds[led].color = mc->leds[led].def_loc_cnt_color; break; case 0xfb: case 0xfd: case 0xfe: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; default: /* Override mode */ mc->leds[led].loc_cnt = 0; mc->leds[led].off_dur = msg->data[3]; mc->leds[led].on_dur = msg->data[4]; if (msg->data[5] == 0xf) mc->leds[led].color = mc->leds[led].def_override_color; else if (msg->data[5] != 0xe) /* 0xe is don't change. */ mc->leds[led].color = msg->data[5]; } printf("Setting ATCA LED %d to %s %x %x %x\n", led, mc->leds[led].loc_cnt ? "local_control" : "override", mc->leds[led].off_dur, mc->leds[led].on_dur, mc->leds[led].color); rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; *rdata_len = 2; } static void handle_picmg_cmd_get_fru_led_state(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned int led; if (check_msg_length(msg, 3, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } led = msg->data[2]; if (led >= mc->num_leds) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; rdata[2] = 0x00; if (mc->leds[led].loc_cnt_sup) rdata[2] |= 0x01; /* Local control support */ if (mc->leds[led].loc_cnt) { rdata[3] = mc->leds[led].off_dur; rdata[4] = mc->leds[led].on_dur; rdata[5] = mc->leds[led].color; *rdata_len = 6; } else { rdata[2] |= 0x02; /* override state. */ rdata[3] = mc->leds[led].def_off_dur; rdata[4] = mc->leds[led].def_on_dur; rdata[5] = mc->leds[led].def_loc_cnt_color; rdata[6] = mc->leds[led].off_dur; rdata[7] = mc->leds[led].on_dur; rdata[8] = mc->leds[led].color; *rdata_len = 9; } } static void handle_picmg_cmd_get_shelf_address_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_shelf_address_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_ipmb_state(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_fru_activation_policy(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_get_fru_activation_policy(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_fru_activation(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int op; sensor_t *hssens; if (check_msg_length(msg, 3, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } if (! mc->hs_sensor) { handle_invalid_cmd(mc, rdata, rdata_len); return; } op = msg->data[2]; if (op >= 2) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } hssens = mc->hs_sensor; switch (op) { case 0: if (bit_set(hssens->event_status, 3) || bit_set(hssens->event_status, 4) || bit_set(hssens->event_status, 5)) { /* Transition to m6. */ ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num, 6, 1); /* Transition to m1. */ ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num, 1, 1); } break; case 1: if (bit_set(hssens->event_status, 2)) { /* Transition to m3. */ ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num, 3, 1); /* Transition to m4. */ ipmi_mc_sensor_set_bit_clr_rest(mc, hssens->lun, hssens->num, 4, 1); } } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; *rdata_len = 2; } static void handle_picmg_cmd_get_device_locator_record(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_port_state(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_get_port_state(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_compute_power_properties(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_power_level(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_get_power_level(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_renegotiate_power(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_get_fan_speed_properties(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_fan_level(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_get_fan_level(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_bused_resource(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_ipmb_link_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_shelf_power_allocation(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (check_msg_length(msg, 2, rdata, rdata_len)) return; if (msg->data[1] > 1) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; ipmi_set_uint16(rdata+2, 0); if (msg->data[1] == 0) { ipmi_set_uint16(rdata+4, 105); ipmi_set_uint16(rdata+6, 227); *rdata_len = 8; } else { ipmi_set_uint16(rdata+4, 227); *rdata_len = 6; } } static void handle_picmg_cmd_shelf_manager_ipmb_address(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_set_fan_policy(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_get_fan_policy(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_picmg_cmd_fru_control_capabilities(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (check_msg_length(msg, 2, rdata, rdata_len)) return; if (msg->data[1] != 0) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; rdata[2] = 0x0e; *rdata_len = 3; } static void handle_picmg_cmd_fru_inventory_device_lock_control(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { emu_data_t *emu = mc->emu; uint16_t lock_id; fru_data_t *fru; if (mc->ipmb != 0x20) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 5, rdata, rdata_len)) return; if (msg->data[1] != 254) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; switch (msg->data[2]) { case 0: rdata[2] = 0; rdata[3] = 0; ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp); *rdata_len = 8; break; case 1: if (emu->atca_fru_inv_locked) { rdata[0] = 0x81; *rdata_len = 1; break; } fru = find_fru(mc, 254); if (!fru || fru->length == 0) { rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC; *rdata_len = 1; break; } emu->temp_fru_inv_data = malloc(fru->length); if (!emu->temp_fru_inv_data) { rdata[0] = IPMI_OUT_OF_SPACE_CC; *rdata_len = 1; break; } emu->temp_fru_inv_data_len = fru->length; memcpy(emu->temp_fru_inv_data, fru->data, emu->temp_fru_inv_data_len); emu->atca_fru_inv_locked = 1; emu->atca_fru_inv_curr_lock_id++; ipmi_set_uint16(rdata+2, emu->atca_fru_inv_curr_lock_id); ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp); *rdata_len = 8; emu->atca_fru_inv_lock_timeout = 20; break; case 2: lock_id = ipmi_get_uint16(msg->data+3); if (!emu->atca_fru_inv_locked || (lock_id != emu->atca_fru_inv_curr_lock_id)) { rdata[0] = 0x81; *rdata_len = 1; break; } emu->atca_fru_inv_locked = 0; rdata[2] = 0; rdata[3] = 0; ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp); *rdata_len = 8; free(emu->temp_fru_inv_data); emu->temp_fru_inv_data = NULL; break; case 3: lock_id = ipmi_get_uint16(msg->data+3); if (!emu->atca_fru_inv_locked || (lock_id != emu->atca_fru_inv_curr_lock_id)) { rdata[0] = 0x81; *rdata_len = 1; break; } emu->atca_fru_inv_locked = 0; rdata[2] = 0; rdata[3] = 0; ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp); *rdata_len = 8; emu->atca_fru_inv_curr_timestamp++; /* FIXME - validate data. */ fru = find_fru(mc, 254); if (!fru || fru->length == 0) { rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC; *rdata_len = 1; break; } memcpy(fru->data, emu->temp_fru_inv_data, emu->temp_fru_inv_data_len); free(emu->temp_fru_inv_data); emu->temp_fru_inv_data = NULL; break; default: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; break; } } static void handle_picmg_cmd_fru_inventory_device_write(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { emu_data_t *emu = mc->emu; uint16_t lock_id; unsigned int offset; unsigned int count; if (mc->ipmb != 0x20) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (msg->data[1] != 254) { rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC; *rdata_len = 1; return; } lock_id = ipmi_get_uint16(msg->data+2); if (!emu->atca_fru_inv_locked || (lock_id != emu->atca_fru_inv_curr_lock_id)) { rdata[0] = 0x80; *rdata_len = 1; return; } /* Reset the timer. */ emu->atca_fru_inv_lock_timeout = 20; offset = ipmi_get_uint16(msg->data+4); count = msg->len - 6; if (offset >= emu->temp_fru_inv_data_len) { rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC; *rdata_len = 1; return; } if ((offset+count) > emu->temp_fru_inv_data_len) { /* Too much data to put into FRU. */ rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; *rdata_len = 1; return; } memcpy(emu->temp_fru_inv_data+offset, msg->data+6, count); rdata[0] = 0; rdata[1] = IPMI_PICMG_GRP_EXT; rdata[2] = count; *rdata_len = 3; } static void handle_picmg_cmd_get_shelf_manager_ip_addresses(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { emu_data_t *emu = mc->emu; unsigned int addr; unsigned int count; emu_addr_t *ap = NULL; int i; if (check_msg_length(msg, 2, rdata, rdata_len)) return; addr = msg->data[1]; for (count=0, i=0; iaddr[i].valid) { if (count == addr) ap = &(emu->addr[i]); count++; } } if (addr >= count) { rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC; *rdata_len = 1; return; } rdata[0] = 0; ipmi_set_uint32(rdata+1, emu->last_addr_change_time.tv_sec); rdata[5] = count; rdata[6] = 0x03; rdata[7] = addr - 1; rdata[8] = 20; rdata[9] = ap->addr_type; if (addr == 0) rdata[9] |= 0x80; memcpy(rdata+10, ap->addr_data, ap->addr_len); *rdata_len = 10 + ap->addr_len; } void handle_picmg_msg(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data); int ipmi_emu_atca_enable(emu_data_t *emu) { emu->atca_mode = 1; ipmi_emu_register_group_extension_handler(IPMI_PICMG_GRP_EXT, handle_picmg_msg, NULL); return 0; } int ipmi_emu_atca_set_site(emu_data_t *emu, unsigned char hw_address, unsigned char site_type, unsigned char site_number) { if (hw_address >= 128) return EINVAL; emu->atca_sites[hw_address].valid = 1; emu->atca_sites[hw_address].hw_address = hw_address; emu->atca_sites[hw_address].site_type = site_type; emu->atca_sites[hw_address].site_number = site_number; return 0; } void handle_picmg_msg(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { switch(msg->cmd) { case IPMI_PICMG_CMD_GET_PROPERTIES: handle_picmg_get_properties(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_ADDRESS_INFO: handle_picmg_get_address_info(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_FRU_CONTROL: handle_picmg_cmd_fru_control(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_FRU_LED_PROPERTIES: handle_picmg_cmd_get_fru_led_properties(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_LED_COLOR_CAPABILITIES: handle_picmg_cmd_get_led_color_capabilities(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_FRU_LED_STATE: handle_picmg_cmd_set_fru_led_state(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_FRU_LED_STATE: handle_picmg_cmd_get_fru_led_state(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_SHELF_ADDRESS_INFO: handle_picmg_cmd_get_shelf_address_info(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_SHELF_ADDRESS_INFO: handle_picmg_cmd_set_shelf_address_info(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_IPMB_STATE: handle_picmg_cmd_set_ipmb_state(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_FRU_ACTIVATION_POLICY: handle_picmg_cmd_set_fru_activation_policy(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_FRU_ACTIVATION_POLICY: handle_picmg_cmd_get_fru_activation_policy(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_FRU_ACTIVATION: handle_picmg_cmd_set_fru_activation(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_DEVICE_LOCATOR_RECORD: handle_picmg_cmd_get_device_locator_record(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_PORT_STATE: handle_picmg_cmd_set_port_state(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_PORT_STATE: handle_picmg_cmd_get_port_state(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_COMPUTE_POWER_PROPERTIES: handle_picmg_cmd_compute_power_properties(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_POWER_LEVEL: handle_picmg_cmd_set_power_level(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_POWER_LEVEL: handle_picmg_cmd_get_power_level(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_RENEGOTIATE_POWER: handle_picmg_cmd_renegotiate_power(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_FAN_SPEED_PROPERTIES: handle_picmg_cmd_get_fan_speed_properties(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_FAN_LEVEL: handle_picmg_cmd_set_fan_level(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_FAN_LEVEL: handle_picmg_cmd_get_fan_level(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_BUSED_RESOURCE: handle_picmg_cmd_bused_resource(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_IPMB_LINK_INFO: handle_picmg_cmd_ipmb_link_info(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SHELF_POWER_ALLOCATION: handle_picmg_cmd_shelf_power_allocation(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SHELF_MANAGER_IPMB_ADDRESS: handle_picmg_cmd_shelf_manager_ipmb_address(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_SET_FAN_POLICY: handle_picmg_cmd_set_fan_policy(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_FAN_POLICY: handle_picmg_cmd_get_fan_policy(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_FRU_CONTROL_CAPABILITIES: handle_picmg_cmd_fru_control_capabilities(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_FRU_INVENTORY_DEVICE_LOCK_CONTROL: handle_picmg_cmd_fru_inventory_device_lock_control(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_FRU_INVENTORY_DEVICE_WRITE: handle_picmg_cmd_fru_inventory_device_write(mc, msg, rdata, rdata_len, NULL); break; case IPMI_PICMG_CMD_GET_SHELF_MANAGER_IP_ADDRESSES: handle_picmg_cmd_get_shelf_manager_ip_addresses(mc, msg, rdata, rdata_len, NULL); break; default: handle_invalid_cmd(mc, rdata, rdata_len); break; } } OpenIPMI-2.0.33/lanserv/bmc_app.c0000664000175000017500000006776313160062145013342 00000000000000/* * bmc_app.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 #include #include #include static void handle_get_device_id(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { memset(rdata, 0, 12); rdata[1] = mc->device_id; rdata[2] = ((mc->has_device_sdrs << 0x7) | (mc->device_revision & 0xf)); rdata[3] = mc->major_fw_rev & 0x7f; rdata[4] = mc->minor_fw_rev; rdata[5] = 0x02; rdata[6] = mc->device_support; memcpy(rdata+7, mc->mfg_id, 3); memcpy(rdata+10, mc->product_id, 2); memcpy(rdata+12, mc->aux_fw_rev, 4); *rdata_len = 16; } void ipmi_mc_set_dev_revision(lmc_data_t *mc, unsigned char dev_revision) { mc->device_revision = dev_revision; } void ipmi_mc_set_fw_revision(lmc_data_t *mc, unsigned char fw_revision_major, unsigned char fw_revision_minor) { mc->major_fw_rev = fw_revision_major; mc->minor_fw_rev = fw_revision_minor; } void ipmi_mc_set_aux_fw_revision(lmc_data_t *mc, unsigned char aux_fw_revision[4]) { memcpy(mc->aux_fw_rev, aux_fw_revision, 4); } void ipmi_mc_setfw_versions() { } /* Returns tenths of a second (deciseconds). */ static long diff_timeval_dc(struct timeval *tv1, struct timeval *tv2) { long rv; rv = (tv1->tv_sec - tv2->tv_sec) * 10; rv += (tv1->tv_usec - tv2->tv_usec + 50000) / 100000; return rv; } static void add_timeval(struct timeval *tv1, struct timeval *tv2) { tv1->tv_sec += tv2->tv_sec; tv1->tv_usec += tv2->tv_usec; while (tv1->tv_usec >= 1000000) { tv1->tv_usec -= 1000000; tv1->tv_sec += 1; } while (tv1->tv_usec <= 0) { tv1->tv_usec += 1000000; tv1->tv_sec -= 1; } } static void sub_timeval(struct timeval *tv1, struct timeval *tv2) { tv1->tv_sec -= tv2->tv_sec; tv1->tv_usec -= tv2->tv_usec; while (tv1->tv_usec >= 1000000) { tv1->tv_usec -= 1000000; tv1->tv_sec += 1; } while (tv1->tv_usec <= 0) { tv1->tv_usec += 1000000; tv1->tv_sec -= 1; } } static void handle_get_watchdog_timer(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { long v = 0; static struct timeval zero_tv = {0, 0}; if (!mc->watchdog_timer) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (mc->watchdog_running) { struct timeval now; mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &now); v = diff_timeval_dc(&mc->watchdog_expiry, &now); if (v < 0) v = 0; } rdata[0] = 0; rdata[1] = mc->watchdog_use; rdata[2] = mc->watchdog_action; rdata[3] = mc->watchdog_pretimeout; rdata[4] = mc->watchdog_expired; ipmi_set_uint16(rdata + 7, v); v = diff_timeval_dc(&mc->watchdog_time, &zero_tv); ipmi_set_uint16(rdata + 5, v); *rdata_len = 7; } void watchdog_timeout(void *cb_data) { lmc_data_t *mc = cb_data; channel_t *bchan = mc->channels[15]; sensor_t *sens = mc->sensors[0][WATCHDOG_SENSOR_NUM]; if (!mc->watchdog_running) goto out; if( !sens ) { // NOTE(noelbk): The watchdog sensor should have been defined // earlier, but don't SEGFAULT if it isn't goto out; } if (! mc->watchdog_preaction_ran) { struct timeval tv, now; switch (IPMI_MC_WATCHDOG_GET_PRE_ACTION(mc)) { case IPMI_MC_WATCHDOG_PRE_NMI: mc->msg_flags |= IPMI_MC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK; bchan->hw_op(bchan, HW_OP_SEND_NMI); set_sensor_bit(mc, sens, 8, 1, 0xc8, (2 << 4) | 0xf, 0xff, 1); break; case IPMI_MC_WATCHDOG_PRE_MSG_INT: mc->msg_flags |= IPMI_MC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK; if (bchan->set_atn && !IPMI_MC_MSG_FLAG_EVT_BUF_FULL_SET(mc)) bchan->set_atn(bchan, 1, IPMI_MC_MSG_INTS_ON(mc)); set_sensor_bit(mc, sens, 8, 1, 0xc8, (3 << 4) | 0xf, 0xff, 1); break; default: goto do_full_expiry; } mc->watchdog_preaction_ran = 1; /* Issued the pretimeout, do the rest of the timeout now. */ mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &now); tv = mc->watchdog_expiry; sub_timeval(&tv, &now); if (tv.tv_sec == 0) { tv.tv_sec = 0; tv.tv_usec = 0; } mc->sysinfo->start_timer(mc->watchdog_timer, &tv); goto out; } do_full_expiry: mc->watchdog_running = 0; /* Stop the watchdog on a timeout */ mc->watchdog_expired |= (1 << IPMI_MC_WATCHDOG_GET_USE(mc)); switch (IPMI_MC_WATCHDOG_GET_ACTION(mc)) { case IPMI_MC_WATCHDOG_ACTION_NONE: set_sensor_bit(mc, sens, 0, 1, 0xc0, mc->watchdog_use & 0xf, 0xff, 1); break; case IPMI_MC_WATCHDOG_ACTION_RESET: set_sensor_bit(mc, sens, 1, 1, 0xc1, mc->watchdog_use & 0xf, 0xff, 1); bchan->hw_op(bchan, HW_OP_RESET); break; case IPMI_MC_WATCHDOG_ACTION_POWER_DOWN: set_sensor_bit(mc, sens, 2, 1, 0xc2, mc->watchdog_use & 0xf, 0xff, 1); bchan->hw_op(bchan, HW_OP_POWEROFF); if (bchan->stop_cmd) bchan->stop_cmd(bchan, 0); break; case IPMI_MC_WATCHDOG_ACTION_POWER_CYCLE: set_sensor_bit(mc, sens, 3, 1, 0xc3, mc->watchdog_use & 0xf, 0xff, 1); bchan->hw_op(bchan, HW_OP_POWEROFF); if (bchan->stop_cmd) bchan->stop_cmd(bchan, 0); start_poweron_timer(mc); break; } out: return; } static void do_watchdog_reset(lmc_data_t *mc) { struct timeval tv; if (IPMI_MC_WATCHDOG_GET_ACTION(mc) == IPMI_MC_WATCHDOG_ACTION_NONE) { mc->watchdog_running = 0; return; } mc->watchdog_preaction_ran = 0; /* Timeout is in tenths of a second, offset is in seconds */ mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &mc->watchdog_expiry); add_timeval(&mc->watchdog_expiry, &mc->watchdog_time); tv = mc->watchdog_time; if (IPMI_MC_WATCHDOG_GET_PRE_ACTION(mc) != IPMI_MC_WATCHDOG_PRE_NONE) { tv.tv_sec -= mc->watchdog_pretimeout; if (tv.tv_sec < 0) { tv.tv_sec = 0; tv.tv_usec = 0; } } mc->watchdog_running = 1; mc->sysinfo->start_timer(mc->watchdog_timer, &tv); } static void handle_set_watchdog_timer(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned int val; channel_t *bchan; if (!mc->watchdog_timer) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; val = msg->data[0] & 0x7; /* Validate use */ if (val == 0 || val > 5) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; bchan = mc->channels[15]; val = msg->data[1] & 0x7; /* Validate action */ switch (val) { case IPMI_MC_WATCHDOG_ACTION_NONE: break; case IPMI_MC_WATCHDOG_ACTION_RESET: rdata[0] = !HW_OP_CAN_RESET(bchan); break; case IPMI_MC_WATCHDOG_ACTION_POWER_DOWN: case IPMI_MC_WATCHDOG_ACTION_POWER_CYCLE: rdata[0] = !HW_OP_CAN_POWER(bchan); break; default: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; } if (rdata[0]) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } val = (msg->data[1] >> 4) & 0x7; /* Validate preaction */ switch (val) { case IPMI_MC_WATCHDOG_PRE_MSG_INT: case IPMI_MC_WATCHDOG_PRE_NONE: break; case IPMI_MC_WATCHDOG_PRE_NMI: if (!HW_OP_CAN_NMI(bchan)) { /* NMI not supported. */ rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } default: /* We don't support PRE_SMI */ rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } mc->watchdog_initialized = 1; mc->watchdog_use = msg->data[0] & IPMI_MC_WATCHDOG_USE_MASK; mc->watchdog_action = msg->data[1] & IPMI_MC_WATCHDOG_ACTION_MASK; mc->watchdog_pretimeout = msg->data[2]; mc->watchdog_expired &= ~msg->data[3]; val = msg->data[4] | (((uint16_t) msg->data[5]) << 8); mc->watchdog_time.tv_sec = val / 10; mc->watchdog_time.tv_usec = (val % 10) * 100000; if (mc->watchdog_running & IPMI_MC_WATCHDOG_GET_DONT_STOP(mc)) do_watchdog_reset(mc); else mc->watchdog_running = 0; } static void handle_reset_watchdog_timer(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!mc->watchdog_timer) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (!mc->watchdog_initialized) { rdata[0] = 0x80; *rdata_len = 1; return; } do_watchdog_reset(mc); rdata[0] = 0x00; *rdata_len = 1; } static void handle_get_channel_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char lchan; unsigned char medium_type; unsigned char protocol_type; unsigned char session_support; unsigned char active_sessions; if (msg->len < 1) { 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]) { if (lchan == 0) { /* The IPMB channel is always there. */ medium_type = IPMI_CHANNEL_MEDIUM_IPMB; protocol_type = IPMI_CHANNEL_PROTOCOL_IPMB; session_support = IPMI_CHANNEL_SESSION_LESS; active_sessions = 0; } else { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } } else { medium_type = mc->channels[lchan]->medium_type; protocol_type = mc->channels[lchan]->protocol_type; session_support = mc->channels[lchan]->session_support; active_sessions = mc->channels[lchan]->active_sessions; } rdata[0] = 0; rdata[1] = lchan; rdata[2] = medium_type; rdata[3] = protocol_type; rdata[4] = (session_support << 6) | active_sessions; rdata[5] = 0xf2; rdata[6] = 0x1b; rdata[7] = 0x00; rdata[8] = 0x00; rdata[9] = 0x00; *rdata_len = 10; } static void handle_get_channel_access(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char lchan; channel_t *chan; uint8_t upd; if (msg->len < 2) { 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]) { if (lchan == 0) { rdata[0] = 0; rdata[1] = 0; rdata[2] = 0; *rdata_len = 3; return; } rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } chan = mc->channels[lchan]; upd = (msg->data[1] >> 6) & 0x3; rdata[0] = 0; if (upd == 2) { rdata[1] = ((chan->PEF_alerting << 5) | 0x2); rdata[2] = chan->privilege_limit; *rdata_len = 3; } else if (upd == 1) { rdata[1] = ((chan->PEF_alerting_nonv << 5) | 0x2); rdata[2] = chan->privilege_limit_nonv; *rdata_len = 3; } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } } static void handle_set_global_enables(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char old_evint = IPMI_MC_EVBUF_FULL_INT_ENABLED(mc); unsigned char old_int = IPMI_MC_MSG_INTS_ON(mc); channel_t *bchan; if (check_msg_length(msg, 1, rdata, rdata_len)) return; rdata[0] = 0; *rdata_len = 1; mc->global_enables = msg->data[0]; bchan = mc->channels[15]; if (!bchan || !bchan->set_atn) return; if (!old_int && IPMI_MC_MSG_INTS_ON(mc) && HW_OP_CAN_IRQ(bchan)) bchan->hw_op(bchan, HW_OP_IRQ_ENABLE); else if (old_int && !IPMI_MC_MSG_INTS_ON(mc) && HW_OP_CAN_IRQ(bchan)) bchan->hw_op(bchan, HW_OP_IRQ_DISABLE); if ((!old_evint && IPMI_MC_EVBUF_FULL_INT_ENABLED(mc) && mc->ev_in_q) || (old_int && !IPMI_MC_MSG_INTS_ON(mc) && mc->channels[15]->recv_q_tail)) bchan->set_atn(bchan, 1, IPMI_MC_EVBUF_FULL_INT_ENABLED(mc)); } static void handle_get_global_enables(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { rdata[0] = 0; rdata[1] = mc->global_enables; *rdata_len = 2; } static void cleanup_ascii_16(uint8_t *c) { int i; i = 0; while ((i < 16) && (*c != 0)) { c++; i++; } while (i < 16) { *c = 0; c++; i++; } } static void set_users_changed(lmc_data_t *mc) { mc->users_changed = 1; mc->emu->users_changed = 1; } static void handle_set_user_access(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint8_t user; uint8_t priv; uint8_t newv; int changed = 0; if (msg->len < 3) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } user = msg->data[1] & 0x3f; if (user == 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } priv = msg->data[2] & 0xf; /* Allow privilege level F as the "no access" privilege */ if (((priv == 0) || (priv > 4)) && (priv != 0xf)) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (msg->data[0] & 0x80) { newv = (msg->data[0] >> 4) & 1; if (newv != mc->users[user].valid) { mc->users[user].valid = newv; changed = 1; } newv = (msg->data[0] >> 5) & 1; if (newv != mc->users[user].link_auth) { mc->users[user].link_auth = newv; changed = 1; } newv = (msg->data[0] >> 6) & 1; if (newv != mc->users[user].cb_only) { mc->users[user].cb_only = newv; changed = 1; } } if (priv != mc->users[user].privilege) { mc->users[user].privilege = priv; changed = 1; } if (msg->len >= 4) { /* Got the session limit byte. */ newv = msg->data[3] & 0xf; if (newv != mc->users[user].max_sessions) { mc->users[user].max_sessions = newv; changed = 1; } } if (changed) set_users_changed(mc); rdata[0] = 0; *rdata_len = 1; } static void handle_get_user_access(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int i; uint8_t user; if (msg->len < 2) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } user = msg->data[1] & 0x3f; if (user == 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = MAX_USERS; /* Number of enabled users. */ rdata[2] = 0; for (i=1; i<=MAX_USERS; i++) { if (mc->users[i].valid) rdata[2]++; } /* Only fixed user name is user 1. */ rdata[3] = mc->users[1].valid; rdata[4] = ((mc->users[user].valid << 4) | (mc->users[user].link_auth << 5) | (mc->users[user].cb_only << 6) | mc->users[user].privilege); *rdata_len = 5; } static void handle_set_user_name(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint8_t user; if (msg->len < 17) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } user = msg->data[0] & 0x3f; if (user <= 1) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } memcpy(mc->users[user].username, msg->data+1, 16); cleanup_ascii_16(mc->users[user].username); set_users_changed(mc); rdata[0] = 0; *rdata_len = 1; } static void handle_get_user_name(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint8_t user; if (msg->len < 1) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } user = msg->data[0] & 0x3f; if ((user <= 1) || (user > MAX_USERS)) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; memcpy(rdata+1, mc->users[user].username, 16); *rdata_len = 17; } static void handle_set_user_password(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint8_t user; uint8_t op; if (msg->len < 2) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } user = msg->data[0] & 0x3f; if (user == 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } op = msg->data[1] & 0x3; if (op == 0) { mc->users[user].valid = 0; } else if (op == 1) { mc->users[user].valid = 1; } else { if (msg->len < 18) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (op == 2) { memcpy(mc->users[user].pw, msg->data+2, 16); } else { /* Nothing to do for test password, we accept anything. */ } } set_users_changed(mc); rdata[0] = 0; *rdata_len = 1; } static void handle_set_channel_access(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->sysinfo || !mc->channels[lchan]) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } if (!mc->sysinfo || !mc->channels[lchan]) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } chan = mc->channels[lchan]; if (!chan->set_chan_access) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } chan->set_chan_access(chan, msg, rdata, rdata_len); } static void handle_read_event_msg_buffer(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *chan = mc->channels[15]; if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (!mc->ev_in_q) { rdata[0] = 0x80; *rdata_len = 1; return; } rdata[0] = 0; memcpy(rdata + 1, mc->evq, 16); *rdata_len = 17; mc->ev_in_q = 0; mc->msg_flags &= ~IPMI_MC_MSG_FLAG_EVT_BUF_FULL; if (chan->set_atn) chan->set_atn(chan, !!mc->msg_flags, IPMI_MC_EVBUF_FULL_INT_ENABLED(mc)); } static void handle_get_msg_flags(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { rdata[0] = 0; rdata[1] = mc->msg_flags; *rdata_len = 2; } static void handle_clear_msg_flags(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *chan = mc->channels[15]; if (check_msg_length(msg, 1, rdata, rdata_len)) return; mc->msg_flags &= ~msg->data[0]; if (msg->data[0] & IPMI_MC_MSG_FLAG_EVT_BUF_FULL) mc->ev_in_q = 0; if (msg->data[0] & IPMI_MC_MSG_FLAG_RCV_MSG_QUEUE) { while (chan->recv_q_head) { msg_t *qmsg = chan->recv_q_head; chan->recv_q_head = qmsg->next; free(qmsg); } chan->recv_q_tail = NULL; } if (chan->set_atn) chan->set_atn(chan, !!mc->msg_flags, IPMI_MC_MSG_INTS_ON(mc)); rdata[0] = 0; *rdata_len = 1; } static void handle_get_msg(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { msg_t *qmsg; channel_t *chan = mc->channels[15]; if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } qmsg = chan->recv_q_head; if (!qmsg) { rdata[0] = 0x80; *rdata_len = 1; return; } if (qmsg->len + 2 > *rdata_len) { rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; *rdata_len = 1; return; } chan->recv_q_head = qmsg->next; if (!qmsg->next) { chan->recv_q_tail = NULL; mc->msg_flags &= ~IPMI_MC_MSG_FLAG_RCV_MSG_QUEUE; if (chan->set_atn) chan->set_atn(chan, !!mc->msg_flags, IPMI_MC_MSG_INTS_ON(mc)); } rdata[0] = 0; rdata[1] = 0; /* Always channel 0 for now, FIXME - privilege level? */ /* * Note that we chop off the first byte because the destination * address is not in the get message response. */ memcpy(rdata + 2, qmsg->data + 1, qmsg->len + 1); *rdata_len = qmsg->len - 1 + 2; free(qmsg); } static void handle_get_payload_activation_status(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *channel = mc->channels[msg->channel]; if (!mc->sol.configured || !channel->set_associated_mc) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (msg->len < 1) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } rdata[0] = 0; *rdata_len = 4; if ((msg->data[0] & 0xf) == IPMI_RMCPP_PAYLOAD_TYPE_SOL) { rdata[1] = 1; /* Only one SOL session at a time */ rdata[2] = mc->sol.active; rdata[3] = 0; } else { rdata[1] = 0; rdata[2] = 0; rdata[3] = 0; } } static void handle_get_payload_instance_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *channel = mc->channels[msg->channel]; if (msg->len < 2) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!mc->sol.configured || !channel->set_associated_mc) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if ((msg->data[0] & 0xf) != IPMI_RMCPP_PAYLOAD_TYPE_SOL) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (msg->data[1] != 1) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; ipmi_set_uint32(rdata + 1, mc->sol.session_id); rdata[5] = 1; memset(rdata + 6, 0, 7); *rdata_len = 13; } static void handle_get_channel_payload_support(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *channel; if (msg->len < 1) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } channel = mc->channels[msg->data[0] & 0xf]; rdata[0] = 0; rdata[1] = ((1 << 1) | ((mc->sol.configured && channel->set_associated_mc) << 2)); memset(rdata + 2, 0, 7); *rdata_len = 9; } static void handle_activate_payload(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *channel = msg->orig_channel; if (!mc->sol.configured || !channel->set_associated_mc) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (msg->len < 6) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if ((msg->data[0] & 0xf) != IPMI_RMCPP_PAYLOAD_TYPE_SOL) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if ((msg->data[0] & 0xf) != IPMI_RMCPP_PAYLOAD_TYPE_SOL) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } ipmi_sol_activate(mc, channel, msg, rdata, rdata_len); } static void handle_deactivate_payload(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { channel_t *channel = msg->orig_channel; if (!mc->sol.configured || !channel->set_associated_mc) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } if (msg->len < 6) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if ((msg->data[0] & 0xf) != IPMI_RMCPP_PAYLOAD_TYPE_SOL) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if ((msg->data[0] & 0xf) != IPMI_RMCPP_PAYLOAD_TYPE_SOL) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } ipmi_sol_deactivate(mc, channel, msg, rdata, rdata_len); } cmd_handler_f app_netfn_handlers[256] = { [IPMI_GET_DEVICE_ID_CMD] = handle_get_device_id, [IPMI_GET_WATCHDOG_TIMER_CMD] = handle_get_watchdog_timer, [IPMI_SET_WATCHDOG_TIMER_CMD] = handle_set_watchdog_timer, [IPMI_RESET_WATCHDOG_TIMER_CMD] = handle_reset_watchdog_timer, [IPMI_GET_CHANNEL_INFO_CMD] = handle_get_channel_info, [IPMI_GET_CHANNEL_ACCESS_CMD] = handle_get_channel_access, [IPMI_SET_BMC_GLOBAL_ENABLES_CMD] = handle_set_global_enables, [IPMI_GET_BMC_GLOBAL_ENABLES_CMD] = handle_get_global_enables, [IPMI_SET_USER_ACCESS_CMD] = handle_set_user_access, [IPMI_GET_USER_ACCESS_CMD] = handle_get_user_access, [IPMI_SET_USER_NAME_CMD] = handle_set_user_name, [IPMI_GET_USER_NAME_CMD] = handle_get_user_name, [IPMI_SET_USER_PASSWORD_CMD] = handle_set_user_password, [IPMI_SET_CHANNEL_ACCESS_CMD] = handle_set_channel_access, [IPMI_READ_EVENT_MSG_BUFFER_CMD] = handle_read_event_msg_buffer, [IPMI_GET_MSG_CMD] = handle_get_msg, [IPMI_GET_MSG_FLAGS_CMD] = handle_get_msg_flags, [IPMI_CLEAR_MSG_FLAGS_CMD] = handle_clear_msg_flags, [IPMI_GET_PAYLOAD_ACTIVATION_STATUS_CMD] = handle_get_payload_activation_status, [IPMI_GET_PAYLOAD_INSTANCE_INFO_CMD] = handle_get_payload_instance_info, [IPMI_GET_CHANNEL_PAYLOAD_SUPPORT_CMD] = handle_get_channel_payload_support, [IPMI_ACTIVATE_PAYLOAD_CMD] = handle_activate_payload, [IPMI_DEACTIVATE_PAYLOAD_CMD] = handle_deactivate_payload }; OpenIPMI-2.0.33/lanserv/sdrcomp/0000775000175000017500000000000014261607642013313 500000000000000OpenIPMI-2.0.33/lanserv/sdrcomp/Makefile.in0000664000175000017500000005536214261607634015314 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = sdrcomp$(EXEEXT) noinst_PROGRAMS = sdrcomp_build$(EXEEXT) subdir = lanserv/sdrcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/ax_config_feature.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_pkg_swig.m4 \ $(top_srcdir)/m4/ax_prog_python_version.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_sdrcomp_OBJECTS = sdrcomp.$(OBJEXT) sdrcomp_OBJECTS = $(am_sdrcomp_OBJECTS) sdrcomp_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = sdrcomp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(sdrcomp_LDFLAGS) $(LDFLAGS) -o $@ am_sdrcomp_build_OBJECTS = sdrcomp.$(OBJEXT) sdrcomp_build_OBJECTS = $(am_sdrcomp_build_OBJECTS) sdrcomp_build_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/sdrcomp.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(sdrcomp_SOURCES) $(sdrcomp_build_SOURCES) DIST_SOURCES = $(sdrcomp_SOURCES) $(sdrcomp_build_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BIBTEX = @BIBTEX@ BUILD_CC = @BUILD_CC@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DIA = @DIA@ DIA_FILTER_NAME = @DIA_FILTER_NAME@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPDF = @DVIPDF@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDBM_LIB = @GDBM_LIB@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_DIR = @GLIB_DIR@ GLIB_LIB = @GLIB_LIB@ GLIB_LIBS = @GLIB_LIBS@ GLIB_PKGCONF = @GLIB_PKGCONF@ GLIB_SO = @GLIB_SO@ GLIB_TARGET = @GLIB_TARGET@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MARVELL_BMC_DIR = @MARVELL_BMC_DIR@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENIPMI_SWIG_LIBS = @OPENIPMI_SWIG_LIBS@ OPENIPMI_SWIG_SO = @OPENIPMI_SWIG_SO@ OPENIPMI_VERSION_EXTRA = @OPENIPMI_VERSION_EXTRA@ OPENIPMI_VERSION_MAJOR = @OPENIPMI_VERSION_MAJOR@ OPENIPMI_VERSION_MINOR = @OPENIPMI_VERSION_MINOR@ OPENIPMI_VERSION_RELEASE = @OPENIPMI_VERSION_RELEASE@ OPENSSLINCS = @OPENSSLINCS@ OPENSSLLIBS = @OPENSSLLIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL_CFLAGS = @PERL_CFLAGS@ PERL_DIR = @PERL_DIR@ PERL_HAS_POSIX_THREADS = @PERL_HAS_POSIX_THREADS@ PERL_INSTALL_DIR = @PERL_INSTALL_DIR@ PERL_POSIX_LIB = @PERL_POSIX_LIB@ PERL_POSIX_SO = @PERL_POSIX_SO@ POPTLIBS = @POPTLIBS@ PYTHON = @PYTHON@ PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ PYTHON_DIR = @PYTHON_DIR@ PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ PYTHON_GUI_DIR = @PYTHON_GUI_DIR@ PYTHON_HAS_POSIX_THREADS = @PYTHON_HAS_POSIX_THREADS@ PYTHON_INSTALL_DIR = @PYTHON_INSTALL_DIR@ PYTHON_INSTALL_LIB_DIR = @PYTHON_INSTALL_LIB_DIR@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM_SITE_PKG = @PYTHON_PLATFORM_SITE_PKG@ PYTHON_POSIX_LIB = @PYTHON_POSIX_LIB@ PYTHON_POSIX_SO = @PYTHON_POSIX_SO@ PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ PYTHON_SWIG_FLAGS = @PYTHON_SWIG_FLAGS@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ RT_LIB = @RT_LIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMPLIBS = @SNMPLIBS@ SOCKETLIB = @SOCKETLIB@ STRIP = @STRIP@ SWIG = @SWIG@ SWIG_DIR = @SWIG_DIR@ SWIG_LIB = @SWIG_LIB@ TCL_CFLAGS = @TCL_CFLAGS@ TCL_DIR = @TCL_DIR@ TCL_LIB = @TCL_LIB@ TCL_LIBS = @TCL_LIBS@ TCL_PKGCONF = @TCL_PKGCONF@ TCL_SO = @TCL_SO@ TCL_TARGET = @TCL_TARGET@ TERM_LIBS = @TERM_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ diaprog = @diaprog@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ perlprog = @perlprog@ pkgprog = @pkgprog@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include \ -I$(top_srcdir)/lanserv -I$(top_srcdir)/utils AM_CPPFLAGS = -DSTATEDIR='"$(localstatedir)"' # sdrcomp.c #includes persist.c and string.c sdrcomp_DEPENDENCIES = $(top_srcdir)/lanserv/persist.c \ $(top_srcdir)/utils/string.c sdrcomp_SOURCES = sdrcomp.c sdrcomp_LDFLAGS = -lm # Build host version of the program sdrcomp_build_SOURCES = sdrcomp.c BUILD_SDRCOMP_DEPS = $(top_srcdir)/lanserv/persist.c \ $(top_srcdir)/utils/string.c BUILD_SDRCOMP_SRCS = $(top_srcdir)/$(subdir)/sdrcomp.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lanserv/sdrcomp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lanserv/sdrcomp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list sdrcomp$(EXEEXT): $(sdrcomp_OBJECTS) $(sdrcomp_DEPENDENCIES) $(EXTRA_sdrcomp_DEPENDENCIES) @rm -f sdrcomp$(EXEEXT) $(AM_V_CCLD)$(sdrcomp_LINK) $(sdrcomp_OBJECTS) $(sdrcomp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdrcomp.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/sdrcomp.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/sdrcomp.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile sdrcomp_build$(EXEEXT): $(BUILD_SDRCOMP_SRCS) $(BUILD_SDRCOMP_DEPS) $(BUILD_CC) -o $@ $(BUILD_SDRCOMP_SRCS) $(AM_CFLAGS) -lm # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: OpenIPMI-2.0.33/lanserv/sdrcomp/Makefile.am0000664000175000017500000000133213067176003015261 00000000000000 AM_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include \ -I$(top_srcdir)/lanserv -I$(top_srcdir)/utils AM_CPPFLAGS = -DSTATEDIR='"$(localstatedir)"' bin_PROGRAMS = sdrcomp noinst_PROGRAMS = sdrcomp_build # sdrcomp.c #includes persist.c and string.c sdrcomp_DEPENDENCIES = $(top_srcdir)/lanserv/persist.c \ $(top_srcdir)/utils/string.c sdrcomp_SOURCES = sdrcomp.c sdrcomp_LDFLAGS = -lm # Build host version of the program sdrcomp_build_SOURCES = sdrcomp.c BUILD_SDRCOMP_DEPS = $(top_srcdir)/lanserv/persist.c \ $(top_srcdir)/utils/string.c BUILD_SDRCOMP_SRCS = $(top_srcdir)/$(subdir)/sdrcomp.c sdrcomp_build$(EXEEXT): $(BUILD_SDRCOMP_SRCS) $(BUILD_SDRCOMP_DEPS) $(BUILD_CC) -o $@ $(BUILD_SDRCOMP_SRCS) $(AM_CFLAGS) -lm OpenIPMI-2.0.33/lanserv/sdrcomp/sdrcomp.c0000664000175000017500000015713214002617260015045 00000000000000/* * sdrcomp.c * * MontaVista IPMI SDR compiler * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 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. */ #include #include #include #include #include #include #include #include #include /* Primarily to get string handling routines */ #include #include "persist.c" #include "string.c" #define MAX_SDR_LINE 256 static FILE *outfile; static char *outfname = NULL; static int ascii_encoding_8_bit = 0; static void out_err(int err) { if (outfname) { unlink(outfname); } exit(err); } struct sdr_field_name { char *name; int val; }; struct sdr_field { char *name; /* SBITS means signed bits, the highest bit is a sign bit, 2s complement */ enum { SDR_BITS, SDR_SBITS, SDR_MULTIBITS, SDR_MULTISBITS, SDR_MULTIBITS2, SDR_STRING, SDR_BOOLBIT, SDR_THRESH, SDR_THRESHREL } type; /* * IMPORTANT: pos is offset + 1, the values given in the IPMI spec. * It is not zero-based. */ uint16_t pos; uint8_t bitoff; uint8_t bitsize; uint8_t required; uint16_t default_val; struct sdr_field_name *strvals; }; static struct sdr_field_name entity_id_fields[] = { { "unspecified", 0 }, { "other", 1 }, { "unknown", 2 }, { "processor", 3 }, { "disk_or_disk_bay", 4 }, { "peripheral_bay", 5 }, { "system_management_module", 6 }, { "system_board", 7 }, { "memory_module", 8 }, { "processor_module", 9 }, { "power_supply", 10 }, { "add-in_card", 11 }, { "front_panel_board", 12 }, { "back_panel_board", 13 }, { "power_system_board", 14 }, { "drive_backplane", 15 }, { "system_internal_expansion_board", 16 }, { "other_system_board", 17 }, { "processor_board", 18 }, { "power_unit", 19 }, { "power_module", 20 }, { "power_management", 21 }, { "chassis_back_panel_board", 22 }, { "system_chassis", 23 }, { "sub-chassis", 24 }, { "Other_chassis_board", 25 }, { "Disk_Drive_Bay", 26 }, { "Peripheral_Bay", 27 }, { "Device_Bay", 28 }, { "fan_cooling_device", 29 }, { "cooling_unit", 30 }, { "cable_interconnect", 31 }, { "memory_device", 32 }, { "system_management_software", 33 }, { "bios", 34 }, { "operating_system", 35 }, { "system_bus", 36 }, { "group", 37 }, { "remote_management_communication_device", 38 }, { "external_environment", 39 }, { "battery", 40 }, { "processing_blade", 41 }, { "connectivity_switch", 42 }, { "processor/memory_module", 43 }, { "i/o_module", 44 }, { "processor/_io_module", 45 }, { "management_controller_firmware", 46 }, { "ipmi_channel", 47 }, { "pci_bus", 48 }, { "pci_express_bus", 49 }, { "scsi_bus", 50 }, { "sata_/_sas_bus", 51 }, { "processor_/_front-side_bus", 52 }, { "picmg_front", 0xa0 }, { "picmg_rtm", 0xc0 }, { "picmg_amc", 0xc1 }, { NULL } }; static struct sdr_field_name sensor_type_fields[] = { { "Temperature", 1 }, { "Voltage", 2 }, { "Current", 3 }, { "Fan", 4 }, { "Physical_Security", 5 }, { "Platform_Security_Violation_Attempt", 6 }, { "Processor", 7 }, { "Power_Supply", 8 }, { "Power_Unit", 9 }, { "Cooling_Device", 10 }, { "Other_Units_Based_Sensor", 11 }, { "Memory", 12 }, { "Drive_Slot", 13 }, { "POST_Memory_Resize", 14 }, { "System_Firmware_Progress", 15 }, { "Event_Logging_Disabled", 16 }, { "Watchdog_1", 17 }, { "System_Event", 18 }, { "Critical_Interrupt", 19 }, { "Button_Switch", 20 }, { "Module_Board", 21 }, { "Microcontroller_Coprocessor", 22 }, { "Add_In_Card", 23 }, { "Chassis", 24 }, { "Chip_Set", 25 }, { "Other_Fru", 26 }, { "Cable_Interconnect", 27 }, { "Terminator", 28 }, { "System_Boot_Initiated", 29 }, { "Boot_Error", 30 }, { "OS_Boot", 31 }, { "OS_Critical_Stop", 32 }, { "Slot_Connector", 33 }, { "System_ACPI_Power_State", 34 }, { "Watchdog_2", 35 }, { "Platform_Alert", 36 }, { "Entity_Presence", 37 }, { "Monitor_ASIC_IC", 38 }, { "LAN", 39 }, { "Management_Subsystem_Health", 40 }, { "Battery", 41 }, { "Session_Audit", 42 }, { "Version_Change", 43 }, { "FRU_State", 44 }, { "picmg_FruHotSwap", 0xF0 }, { "picmg_IPMB0", 0xF1 }, { "picmg_ModuleHotSwap", 0xF2 }, { NULL } }; static struct sdr_field_name sensor_access_fields[] = { { "no", 0 }, { "readable", 1 }, { "settable", 2 }, { "fixed", 3 }, { NULL } }; static struct sdr_field_name sensor_event_msg_ctrl_fields[] = { { "per_state", 0 }, { "entire_sensor", 1 }, { "global", 2 }, { "no", 3 }, { NULL } }; static struct sdr_field_name analog_data_format_fields[] = { { "unsigned", 0 }, { "1s_complement", 1 }, { "2s_complement", 2 }, { "no", 3 }, { NULL } }; static struct sdr_field_name rate_unit_fields[] = { { "none", 0 }, { "per_us", 1 }, { "per_ms", 2 }, { "per_s", 3 }, { "per_min", 4 }, { "per_hour", 5 }, { "per_day", 6 }, { NULL } }; static struct sdr_field_name modifier_unit_fields[] = { { "none", 0 }, { "multiply", 1 }, { "divide", 2 }, { NULL } }; static struct sdr_field_name base_unit_fields[] = { { "unspecified", 0 }, { "degrees_C", 1 }, { "degrees_F", 2 }, { "degrees_K", 3 }, { "Volts", 4 }, { "Amps", 5 }, { "Watts", 6 }, { "Joules", 7 }, { "Coulombs", 8 }, { "VA", 9 }, { "Nits", 10 }, { "lumen", 11 }, { "lux", 12 }, { "Candela", 13 }, { "kPa", 14 }, { "PSI", 15 }, { "Newton", 16 }, { "CFM", 17 }, { "RPM", 18 }, { "Hz", 19 }, { "microsecond", 20 }, { "millisecond", 21 }, { "second", 22 }, { "minute", 23 }, { "hour", 24 }, { "day", 25 }, { "week", 26 }, { "mil", 27 }, { "inches", 28 }, { "feet", 29 }, { "cu_in", 30 }, { "cu_feet", 31 }, { "mm", 32 }, { "cm", 33 }, { "m", 34 }, { "cu_cm", 35 }, { "cu_m", 36 }, { "liters", 37 }, { "fluid_ounce", 38 }, { "radians", 39 }, { "steradians", 40 }, { "revolutions", 41 }, { "cycles", 42 }, { "gravities", 43 }, { "ounce", 44 }, { "pound", 45 }, { "ft-lb", 46 }, { "oz-in", 47 }, { "gauss", 48 }, { "gilberts", 49 }, { "henry", 50 }, { "millihenry", 51 }, { "farad", 52 }, { "microfarad", 53 }, { "ohms", 54 }, { "siemens", 55 }, { "mole", 56 }, { "becquerel", 57 }, { "PPM", 58 }, { "reserved", 59 }, { "Decibels", 60 }, { "DbA", 61 }, { "DbC", 62 }, { "gray", 63 }, { "sievert", 64 }, { "color_temp_deg_K", 65 }, { "bit", 66 }, { "kilobit", 67 }, { "megabit", 68 }, { "gigabit", 69 }, { "byte", 70 }, { "kilobyte", 71 }, { "megabyte", 72 }, { "gigabyte", 73 }, { "word", 74 }, { "dword", 75 }, { "qword", 76 }, { "line", 77 }, { "hit", 78 }, { "miss", 79 }, { "retry", 80 }, { "reset", 81 }, { "overrun_overflow", 82 }, { "underrun", 83 }, { "collision", 84 }, { "packets", 85 }, { "messages", 86 }, { "characters", 87 }, { "error", 88 }, { "correctable_error", 89 }, { "uncorrectable_error", 90 }, { NULL } }; static struct sdr_field_name linearization_fields[] = { { "linear", 0 }, { "ln", 1 }, { "log10", 2 }, { "log2", 3 }, { "e", 4 }, { "exp10", 5 }, { "exp2", 6 }, { "1/x", 7 }, { "sqr(x)", 9 }, { "cube(x)", 10 }, { "sqrt(x)", 11 }, { "cube-1(x)", 12 }, { "non-linear", 0x70 }, { NULL } }; static struct sdr_field_name sensor_direction_fields[] = { { "n/a", 0 }, { "input", 1 }, { "output", 2 }, { NULL } }; static struct sdr_field type1[] = { { "sensor_owner_id", SDR_BITS, 6, 0, 8, .required = 1 }, { "channel_number", SDR_BITS, 7, 4, 4, .required = 1 }, { "sensor_owner_lun", SDR_BITS, 7, 0, 2, .required = 1 }, { "sensor_number", SDR_BITS, 8, 0, 8, .required = 1 }, { "entity_id", SDR_BITS, 9, 0, 8, .required = 1, .strvals = entity_id_fields }, { "logical_entity", SDR_BOOLBIT, 10, 7, 1 }, { "entity_instance", SDR_BITS, 10, 0, 8, .required = 1 }, { "init_scanning", SDR_BOOLBIT, 11, 6, 1 }, { "init_events", SDR_BOOLBIT, 11, 5, 1 }, { "init_thresholds", SDR_BOOLBIT, 11, 4, 1 }, { "init_hysteresis", SDR_BOOLBIT, 11, 3, 1 }, { "init_sensor_type", SDR_BOOLBIT, 11, 2, 1 }, { "default_event_gen_on", SDR_BOOLBIT, 11, 1, 1 }, { "default_sensor_scan_on", SDR_BOOLBIT, 11, 0, 1 }, { "ignore_if_no_entity", SDR_BOOLBIT, 12, 7, 1 }, { "sensor_auto_rearm", SDR_BOOLBIT, 12, 6, 1 }, { "sensor_hysteresis", SDR_BITS, 12, 4, 2, .strvals = sensor_access_fields }, { "sensor_threshold_access",SDR_BITS, 12, 2, 2, .strvals = sensor_access_fields }, { "sensor_event_msg_ctrl", SDR_BITS, 12, 0, 2, .strvals = sensor_event_msg_ctrl_fields }, { "sensor_type", SDR_BITS, 13, 0, 8, .required = 1, .strvals = sensor_type_fields }, { "event_reading_type_code",SDR_BITS, 14, 0, 8, .required = 1 }, { "assert_event14", SDR_BOOLBIT, 16, 6, 1 }, { "assert_event13", SDR_BOOLBIT, 16, 5, 1 }, { "assert_event12", SDR_BOOLBIT, 16, 4, 1 }, { "assert_event11", SDR_BOOLBIT, 16, 3, 1 }, { "assert_event10", SDR_BOOLBIT, 16, 2, 1 }, { "assert_event9", SDR_BOOLBIT, 16, 1, 1 }, { "assert_event8", SDR_BOOLBIT, 16, 0, 1 }, { "assert_event7", SDR_BOOLBIT, 15, 7, 1 }, { "assert_event6", SDR_BOOLBIT, 15, 6, 1 }, { "assert_event5", SDR_BOOLBIT, 15, 5, 1 }, { "assert_event4", SDR_BOOLBIT, 15, 4, 1 }, { "assert_event3", SDR_BOOLBIT, 15, 3, 1 }, { "assert_event2", SDR_BOOLBIT, 15, 2, 1 }, { "assert_event1", SDR_BOOLBIT, 15, 1, 1 }, { "assert_event0", SDR_BOOLBIT, 15, 0, 1 }, { "return_lnr", SDR_BOOLBIT, 16, 6, 1 }, { "return_lc", SDR_BOOLBIT, 16, 5, 1 }, { "return_lnc", SDR_BOOLBIT, 16, 4, 1 }, { "assert_unrgh", SDR_BOOLBIT, 16, 3, 1 }, { "assert_unrgl", SDR_BOOLBIT, 16, 2, 1 }, { "assert_ucgh", SDR_BOOLBIT, 16, 1, 1 }, { "assert_ucgl", SDR_BOOLBIT, 16, 0, 1 }, { "assert_uncgh", SDR_BOOLBIT, 15, 7, 1 }, { "assert_uncgl", SDR_BOOLBIT, 15, 6, 1 }, { "assert_lnrgh", SDR_BOOLBIT, 15, 5, 1 }, { "assert_lnrgl", SDR_BOOLBIT, 15, 4, 1 }, { "assert_lcgh", SDR_BOOLBIT, 15, 3, 1 }, { "assert_lcgl", SDR_BOOLBIT, 15, 2, 1 }, { "assert_lncgh", SDR_BOOLBIT, 15, 1, 1 }, { "assert_lncgl", SDR_BOOLBIT, 15, 0, 1 }, { "deassert_event14", SDR_BOOLBIT, 18, 6, 1 }, { "deassert_event13", SDR_BOOLBIT, 18, 5, 1 }, { "deassert_event12", SDR_BOOLBIT, 18, 4, 1 }, { "deassert_event11", SDR_BOOLBIT, 18, 3, 1 }, { "deassert_event10", SDR_BOOLBIT, 18, 2, 1 }, { "deassert_event9", SDR_BOOLBIT, 18, 1, 1 }, { "deassert_event8", SDR_BOOLBIT, 18, 0, 1 }, { "deassert_event7", SDR_BOOLBIT, 17, 7, 1 }, { "deassert_event6", SDR_BOOLBIT, 17, 6, 1 }, { "deassert_event5", SDR_BOOLBIT, 17, 5, 1 }, { "deassert_event4", SDR_BOOLBIT, 17, 4, 1 }, { "deassert_event3", SDR_BOOLBIT, 17, 3, 1 }, { "deassert_event2", SDR_BOOLBIT, 17, 2, 1 }, { "deassert_event1", SDR_BOOLBIT, 17, 1, 1 }, { "deassert_event0", SDR_BOOLBIT, 17, 0, 1 }, { "return_unr", SDR_BOOLBIT, 18, 6, 1 }, { "return_uc", SDR_BOOLBIT, 18, 5, 1 }, { "return_unc", SDR_BOOLBIT, 18, 4, 1 }, { "deassert_unrgh", SDR_BOOLBIT, 18, 3, 1 }, { "deassert_unrgl", SDR_BOOLBIT, 18, 2, 1 }, { "deassert_ucgh", SDR_BOOLBIT, 18, 1, 1 }, { "deassert_ucgl", SDR_BOOLBIT, 18, 0, 1 }, { "deassert_uncgh", SDR_BOOLBIT, 17, 7, 1 }, { "deassert_uncgl", SDR_BOOLBIT, 17, 6, 1 }, { "deassert_lnrgh", SDR_BOOLBIT, 17, 5, 1 }, { "deassert_lnrgl", SDR_BOOLBIT, 17, 4, 1 }, { "deassert_lcgh", SDR_BOOLBIT, 17, 3, 1 }, { "deassert_lcgl", SDR_BOOLBIT, 17, 2, 1 }, { "deassert_lncgh", SDR_BOOLBIT, 17, 1, 1 }, { "deassert_lncgl", SDR_BOOLBIT, 17, 0, 1 }, { "event14_state_ret", SDR_BOOLBIT, 20, 6, 1 }, { "event13_state_ret", SDR_BOOLBIT, 20, 5, 1 }, { "event12_state_ret", SDR_BOOLBIT, 20, 4, 1 }, { "event11_state_ret", SDR_BOOLBIT, 20, 3, 1 }, { "event10_state_ret", SDR_BOOLBIT, 20, 2, 1 }, { "event9_state_ret", SDR_BOOLBIT, 20, 1, 1 }, { "event8_state_ret", SDR_BOOLBIT, 20, 0, 1 }, { "event7_state_ret", SDR_BOOLBIT, 19, 7, 1 }, { "event6_state_ret", SDR_BOOLBIT, 19, 6, 1 }, { "event5_state_ret", SDR_BOOLBIT, 19, 5, 1 }, { "event4_state_ret", SDR_BOOLBIT, 19, 4, 1 }, { "event3_state_ret", SDR_BOOLBIT, 19, 3, 1 }, { "event2_state_ret", SDR_BOOLBIT, 19, 2, 1 }, { "event1_state_ret", SDR_BOOLBIT, 19, 1, 1 }, { "event0_state_ret", SDR_BOOLBIT, 19, 0, 1 }, { "unr_thrsh_settable", SDR_BOOLBIT, 20, 5, 1 }, { "uc_thrsh_settable", SDR_BOOLBIT, 20, 4, 1 }, { "unc_thrsh_settable", SDR_BOOLBIT, 20, 3, 1 }, { "lnr_thrsh_settable", SDR_BOOLBIT, 20, 2, 1 }, { "lc_thrsh_settable", SDR_BOOLBIT, 20, 1, 1 }, { "lnc_thrsh_settable", SDR_BOOLBIT, 20, 0, 1 }, { "unr_thrsh_readable", SDR_BOOLBIT, 19, 5, 1 }, { "uc_thrsh_readable", SDR_BOOLBIT, 19, 4, 1 }, { "unc_thrsh_readable", SDR_BOOLBIT, 19, 3, 1 }, { "lnr_thrsh_readable", SDR_BOOLBIT, 19, 2, 1 }, { "lc_thrsh_readable", SDR_BOOLBIT, 19, 1, 1 }, { "lnc_thrsh_readable", SDR_BOOLBIT, 19, 0, 1 }, { "analog_data_format", SDR_BITS, 21, 6, 2, .strvals = analog_data_format_fields }, { "rate_unit", SDR_BITS, 21, 3, 3, .strvals = rate_unit_fields }, { "modifier_unit", SDR_BITS, 21, 1, 2, .strvals = modifier_unit_fields }, { "percentage", SDR_BOOLBIT, 21, 0, 1 }, { "base_unit", SDR_BITS, 22, 0, 8, .strvals = base_unit_fields }, { "modifier_unit_code", SDR_BITS, 23, 0, 8, .strvals = base_unit_fields }, { "linearization", SDR_BITS, 24, 0, 7, .strvals = linearization_fields }, { "m", SDR_MULTISBITS, 25, 0, 8 }, { "m", SDR_MULTIBITS2, 26, 6, 2 }, { "tolerance", SDR_BITS, 26, 0, 6 }, { "b", SDR_MULTISBITS, 27, 0, 8 }, { "b", SDR_MULTIBITS2, 28, 6, 2 }, { "accuracy", SDR_MULTISBITS, 28, 0, 6 }, { "accuracy", SDR_MULTIBITS2, 29, 4, 4 }, { "accuracy_exp", SDR_BITS, 29, 2, 2 }, { "sensor_direction", SDR_BITS, 29, 0, 2, .strvals = sensor_direction_fields }, { "r_exp", SDR_SBITS, 30, 4, 4 }, { "b_exp", SDR_SBITS, 30, 0, 4 }, { "normal_min_specified", SDR_BOOLBIT, 31, 2, 1 }, { "normal_max_specified", SDR_BOOLBIT, 31, 1, 1 }, { "nominal_specified", SDR_BOOLBIT, 31, 0, 1 }, { "nominal_reading", SDR_BITS, 32, 0, 8 }, { "nominal_freading", SDR_THRESH, 32, 0, 8 }, { "normal_maximum", SDR_BITS, 33, 0, 8 }, { "normal_fmaximum", SDR_THRESH, 33, 0, 8 }, { "normal_minimum", SDR_BITS, 34, 0, 8 }, { "normal_fminimum", SDR_THRESH, 34, 0, 8 }, { "sensor_maximum", SDR_BITS, 35, 0, 8 }, { "sensor_minimum", SDR_BITS, 36, 0, 8 }, { "unr_thresh", SDR_BITS, 37, 0, 8 }, { "uc_thresh", SDR_BITS, 38, 0, 8 }, { "unc_thresh", SDR_BITS, 39, 0, 8 }, { "lnr_thresh", SDR_BITS, 40, 0, 8 }, { "lc_thresh", SDR_BITS, 41, 0, 8 }, { "lnc_thresh", SDR_BITS, 42, 0, 8 }, { "unr_fthresh", SDR_THRESH, 37, 0, 8 }, { "uc_fthresh", SDR_THRESH, 38, 0, 8 }, { "unc_fthresh", SDR_THRESH, 39, 0, 8 }, { "lnr_fthresh", SDR_THRESH, 40, 0, 8 }, { "lc_fthresh", SDR_THRESH, 41, 0, 8 }, { "lnc_fthresh", SDR_THRESH, 42, 0, 8 }, { "positive_hysteresis", SDR_BITS, 43, 0, 8 }, { "positive_fhysteresis", SDR_THRESHREL, 43, 0, 8 }, { "negative_hysteresis", SDR_BITS, 44, 0, 8 }, { "negative_fhysteresis", SDR_THRESHREL, 44, 0, 8 }, { "oem", SDR_BITS, 47, 0, 8 }, { "id_string", SDR_STRING, 48, 0, 8, .required = 1 }, }; #define TYPE1_LEN (sizeof(type1) / sizeof(struct sdr_field)) static struct sdr_field_name id_string_modifier_fields[] = { { "numeric", 0 }, { "alpha", 1 }, { NULL } }; static struct sdr_field type2[] = { { "sensor_owner_id", SDR_BITS, 6, 0, 8, .required = 1 }, { "channel_number", SDR_BITS, 7, 4, 4, .required = 1 }, { "sensor_owner_lun", SDR_BITS, 7, 0, 2, .required = 1 }, { "sensor_number", SDR_BITS, 8, 0, 8, .required = 1 }, { "entity_id", SDR_BITS, 9, 0, 8, .required = 1, .strvals = entity_id_fields }, { "logical_entity", SDR_BOOLBIT, 10, 7, 1 }, { "entity_instance", SDR_BITS, 10, 0, 8, .required = 1 }, { "init_scanning", SDR_BOOLBIT, 11, 6, 1 }, { "init_events", SDR_BOOLBIT, 11, 5, 1 }, { "init_thresholds", SDR_BOOLBIT, 11, 4, 1 }, { "init_systeresis", SDR_BOOLBIT, 11, 3, 1 }, { "init_sensor_type", SDR_BOOLBIT, 11, 2, 1 }, { "default_event_gen_on", SDR_BOOLBIT, 11, 1, 1 }, { "default_sensor_scan_on", SDR_BOOLBIT, 11, 0, 1 }, { "ignore_if_no_entity", SDR_BOOLBIT, 12, 7, 1 }, { "sensor_auto_rearm", SDR_BOOLBIT, 12, 6, 1 }, { "sensor_hysteresis", SDR_BITS, 12, 4, 2, .strvals = sensor_access_fields }, { "sensor_threshold_access",SDR_BITS, 12, 2, 2, .strvals = sensor_access_fields }, { "sensor_event_msg_ctrl", SDR_BITS, 12, 0, 2, .strvals = sensor_event_msg_ctrl_fields }, { "sensor_type", SDR_BITS, 13, 0, 8, .required = 1, .strvals = sensor_type_fields }, { "event_reading_type_code",SDR_BITS, 14, 0, 8, .required = 1 }, { "assert_event14", SDR_BOOLBIT, 16, 6, 1 }, { "assert_event13", SDR_BOOLBIT, 16, 5, 1 }, { "assert_event12", SDR_BOOLBIT, 16, 4, 1 }, { "assert_event11", SDR_BOOLBIT, 16, 3, 1 }, { "assert_event10", SDR_BOOLBIT, 16, 2, 1 }, { "assert_event9", SDR_BOOLBIT, 16, 1, 1 }, { "assert_event8", SDR_BOOLBIT, 16, 0, 1 }, { "assert_event7", SDR_BOOLBIT, 15, 7, 1 }, { "assert_event6", SDR_BOOLBIT, 15, 6, 1 }, { "assert_event5", SDR_BOOLBIT, 15, 5, 1 }, { "assert_event4", SDR_BOOLBIT, 15, 4, 1 }, { "assert_event3", SDR_BOOLBIT, 15, 3, 1 }, { "assert_event2", SDR_BOOLBIT, 15, 2, 1 }, { "assert_event1", SDR_BOOLBIT, 15, 1, 1 }, { "assert_event0", SDR_BOOLBIT, 15, 0, 1 }, { "assert_lnr", SDR_BOOLBIT, 16, 6, 1 }, { "assert_lc", SDR_BOOLBIT, 16, 5, 1 }, { "assert_lnc", SDR_BOOLBIT, 16, 4, 1 }, { "assert_unrgh", SDR_BOOLBIT, 16, 3, 1 }, { "assert_unrgl", SDR_BOOLBIT, 16, 2, 1 }, { "assert_ucgh", SDR_BOOLBIT, 16, 1, 1 }, { "assert_ucgl", SDR_BOOLBIT, 16, 0, 1 }, { "assert_uncgh", SDR_BOOLBIT, 15, 7, 1 }, { "assert_uncgl", SDR_BOOLBIT, 15, 6, 1 }, { "assert_lnrgh", SDR_BOOLBIT, 15, 5, 1 }, { "assert_lnrgl", SDR_BOOLBIT, 15, 4, 1 }, { "assert_lcgh", SDR_BOOLBIT, 15, 3, 1 }, { "assert_lcgl", SDR_BOOLBIT, 15, 2, 1 }, { "assert_lncgh", SDR_BOOLBIT, 15, 1, 1 }, { "assert_lncgl", SDR_BOOLBIT, 15, 0, 1 }, { "deassert_event14", SDR_BOOLBIT, 18, 6, 1 }, { "deassert_event13", SDR_BOOLBIT, 18, 5, 1 }, { "deassert_event12", SDR_BOOLBIT, 18, 4, 1 }, { "deassert_event11", SDR_BOOLBIT, 18, 3, 1 }, { "deassert_event10", SDR_BOOLBIT, 18, 2, 1 }, { "deassert_event9", SDR_BOOLBIT, 18, 1, 1 }, { "deassert_event8", SDR_BOOLBIT, 18, 0, 1 }, { "deassert_event7", SDR_BOOLBIT, 17, 7, 1 }, { "deassert_event6", SDR_BOOLBIT, 17, 6, 1 }, { "deassert_event5", SDR_BOOLBIT, 17, 5, 1 }, { "deassert_event4", SDR_BOOLBIT, 17, 4, 1 }, { "deassert_event3", SDR_BOOLBIT, 17, 3, 1 }, { "deassert_event2", SDR_BOOLBIT, 17, 2, 1 }, { "deassert_event1", SDR_BOOLBIT, 17, 1, 1 }, { "deassert_event0", SDR_BOOLBIT, 17, 0, 1 }, { "deassert_lnr", SDR_BOOLBIT, 18, 6, 1 }, { "deassert_lc", SDR_BOOLBIT, 18, 5, 1 }, { "deassert_lnc", SDR_BOOLBIT, 18, 4, 1 }, { "deassert_unrgh", SDR_BOOLBIT, 18, 3, 1 }, { "deassert_unrgl", SDR_BOOLBIT, 18, 2, 1 }, { "deassert_ucgh", SDR_BOOLBIT, 18, 1, 1 }, { "deassert_ucgl", SDR_BOOLBIT, 18, 0, 1 }, { "deassert_uncgh", SDR_BOOLBIT, 17, 7, 1 }, { "deassert_uncgl", SDR_BOOLBIT, 17, 6, 1 }, { "deassert_lnrgh", SDR_BOOLBIT, 17, 5, 1 }, { "deassert_lnrgl", SDR_BOOLBIT, 17, 4, 1 }, { "deassert_lcgh", SDR_BOOLBIT, 17, 3, 1 }, { "deassert_lcgl", SDR_BOOLBIT, 17, 2, 1 }, { "deassert_lncgh", SDR_BOOLBIT, 17, 1, 1 }, { "deassert_lncgl", SDR_BOOLBIT, 17, 0, 1 }, { "event14_state_ret", SDR_BOOLBIT, 20, 6, 1 }, { "event13_state_ret", SDR_BOOLBIT, 20, 5, 1 }, { "event12_state_ret", SDR_BOOLBIT, 20, 4, 1 }, { "event11_state_ret", SDR_BOOLBIT, 20, 3, 1 }, { "event10_state_ret", SDR_BOOLBIT, 20, 2, 1 }, { "event9_state_ret", SDR_BOOLBIT, 20, 1, 1 }, { "event8_state_ret", SDR_BOOLBIT, 20, 0, 1 }, { "event7_state_ret", SDR_BOOLBIT, 19, 7, 1 }, { "event6_state_ret", SDR_BOOLBIT, 19, 6, 1 }, { "event5_state_ret", SDR_BOOLBIT, 19, 5, 1 }, { "event4_state_ret", SDR_BOOLBIT, 19, 4, 1 }, { "event3_state_ret", SDR_BOOLBIT, 19, 3, 1 }, { "event2_state_ret", SDR_BOOLBIT, 19, 2, 1 }, { "event1_state_ret", SDR_BOOLBIT, 19, 1, 1 }, { "event0_state_ret", SDR_BOOLBIT, 19, 0, 1 }, { "unr_thrsh_settable", SDR_BOOLBIT, 20, 5, 1 }, { "uc_thrsh_settable", SDR_BOOLBIT, 20, 4, 1 }, { "unc_thrsh_settable", SDR_BOOLBIT, 20, 3, 1 }, { "lnr_thrsh_settable", SDR_BOOLBIT, 20, 2, 1 }, { "lc_thrsh_settable", SDR_BOOLBIT, 20, 1, 1 }, { "lnc_thrsh_settable", SDR_BOOLBIT, 20, 0, 1 }, { "unr_thrsh_readable", SDR_BOOLBIT, 19, 5, 1 }, { "uc_thrsh_readable", SDR_BOOLBIT, 19, 4, 1 }, { "unc_thrsh_readable", SDR_BOOLBIT, 19, 3, 1 }, { "lnr_thrsh_readable", SDR_BOOLBIT, 19, 2, 1 }, { "lc_thrsh_readable", SDR_BOOLBIT, 19, 1, 1 }, { "lnc_thrsh_readable", SDR_BOOLBIT, 19, 0, 1 }, { "", SDR_BITS, 21, 6, 2, .default_val = 3 }, { "rate_unit", SDR_BITS, 21, 3, 3, .strvals = rate_unit_fields }, { "modifier_unit", SDR_BITS, 21, 1, 2, .strvals = modifier_unit_fields }, { "percentage", SDR_BOOLBIT, 21, 0, 1 }, { "base_unit", SDR_BITS, 22, 0, 8 }, { "modifier_unit_code", SDR_BITS, 23, 0, 8 }, { "sensor_direction", SDR_BITS, 24, 6, 2, .strvals = sensor_direction_fields }, { "id_string_modifier", SDR_BITS, 24, 4, 2, .strvals = id_string_modifier_fields }, { "share_count", SDR_BITS, 24, 0, 4 }, { "entity_instance_incr", SDR_BOOLBIT, 25, 7, 1 }, { "instance_modifier_off", SDR_BITS, 25, 0, 7 }, { "positive_hysteresis", SDR_BITS, 26, 0, 8 }, { "negative_hysteresis", SDR_BITS, 27, 0, 8 }, { "oem", SDR_BITS, 31, 0, 8 }, { "id_string", SDR_STRING, 32, 0, 8, .required = 1 }, }; #define TYPE2_LEN (sizeof(type2) / sizeof(struct sdr_field)) static struct sdr_field type3[] = { { "sensor_owner_id", SDR_BITS, 6, 0, 8, .required = 1 }, { "channel_number", SDR_BITS, 7, 4, 4, .required = 1 }, { "sensor_owner_lun", SDR_BITS, 7, 0, 2, .required = 1 }, { "sensor_number", SDR_BITS, 8, 0, 8, .required = 1 }, { "entity_id", SDR_BITS, 9, 0, 8, .required = 1, .strvals = entity_id_fields }, { "logical_entity", SDR_BOOLBIT, 10, 7, 1 }, { "entity_instance", SDR_BITS, 10, 0, 8, .required = 1 }, { "sensor_type", SDR_BITS, 11, 0, 8, .required = 1, .strvals = sensor_type_fields }, { "event_reading_type_code",SDR_BITS, 12, 0, 8, .required = 1 }, { "sensor_direction", SDR_BITS, 13, 6, 2, .strvals = sensor_direction_fields }, { "id_string_modifier", SDR_BITS, 13, 4, 2, .strvals = id_string_modifier_fields }, { "share_count", SDR_BITS, 13, 0, 4 }, { "entity_instance_incr", SDR_BOOLBIT, 14, 7, 1 }, { "instance_modifier_off", SDR_BITS, 14, 0, 7 }, { "oem", SDR_BITS, 16, 0, 8 }, { "id_string", SDR_STRING, 17, 0, 8, .required = 1 }, }; #define TYPE3_LEN (sizeof(type3) / sizeof(struct sdr_field)) static struct sdr_field type8[] = { { "container_entity_id", SDR_BITS, 6, 0, 8, .required = 1, .strvals = entity_id_fields }, { "container_entity_inst", SDR_BITS, 7, 0, 8, .required = 1 }, { "entities_are_range", SDR_BOOLBIT, 8, 7, 1 }, { "linked_ears", SDR_BOOLBIT, 8, 6, 1 }, { "presence_sensor_always_there",SDR_BOOLBIT, 8, 5, 1 }, { "entity_1_id", SDR_BITS, 9, 0, 8, .required = 1, .strvals = entity_id_fields }, { "entity_1_inst", SDR_BITS, 10, 0, 8, .required = 1 }, { "entity_2_id", SDR_BITS, 11, 0, 8, .strvals = entity_id_fields }, { "entity_2_inst", SDR_BITS, 12, 0, 8 }, { "entity_3_id", SDR_BITS, 13, 0, 8, .strvals = entity_id_fields }, { "entity_3_inst", SDR_BITS, 14, 0, 8 }, { "entity_4_id", SDR_BITS, 15, 0, 8, .strvals = entity_id_fields }, { "entity_4_inst", SDR_BITS, 16, 0, 8 }, }; #define TYPE8_LEN (sizeof(type8) / sizeof(struct sdr_field)) static struct sdr_field type9[] = { { "container_entity_id", SDR_BITS, 6, 0, 8, .required = 1, .strvals = entity_id_fields }, { "container_entity_inst", SDR_BITS, 7, 4, 4, .required = 1 }, { "container_entity_dev_addr", SDR_BITS, 8, 0, 8, .required = 1 }, { "container_entity_dev_chan", SDR_BITS, 9, 0, 8, .required = 1 }, { "entities_are_range", SDR_BOOLBIT, 10, 7, 1 }, { "linked_ears", SDR_BOOLBIT, 10, 6, 1 }, { "presence_sensor_always_there",SDR_BOOLBIT, 10, 5, 1 }, { "entity_1_dev_addr", SDR_BITS, 11, 0, 8, .required = 1 }, { "entity_1_dev_chan", SDR_BITS, 12, 0, 8, .required = 1 }, { "entity_1_id", SDR_BITS, 13, 0, 8, .required = 1, .strvals = entity_id_fields }, { "entity_1_inst", SDR_BITS, 14, 0, 8, .required = 1 }, { "entity_2_dev_addr", SDR_BITS, 15, 0, 8 }, { "entity_2_dev_chan", SDR_BITS, 16, 0, 8 }, { "entity_2_id", SDR_BITS, 17, 0, 8, .strvals = entity_id_fields }, { "entity_2_inst", SDR_BITS, 18, 0, 8 }, { "entity_3_dev_addr", SDR_BITS, 19, 0, 8 }, { "entity_3_dev_chan", SDR_BITS, 20, 0, 8 }, { "entity_3_id", SDR_BITS, 21, 0, 8, .strvals = entity_id_fields }, { "entity_3_inst", SDR_BITS, 22, 0, 8 }, { "entity_4_dev_addr", SDR_BITS, 23, 0, 8 }, { "entity_4_dev_chan", SDR_BITS, 24, 0, 8 }, { "entity_4_id", SDR_BITS, 25, 0, 8, .strvals = entity_id_fields }, { "entity_4_inst", SDR_BITS, 26, 0, 8 }, }; #define TYPE9_LEN (sizeof(type9) / sizeof(struct sdr_field)) static struct sdr_field type16[] = { { "device_access_address", SDR_BITS, 6, 0, 8, .required = 1 }, { "device_slave_address", SDR_BITS, 7, 0, 8, .required = 1 }, { "channel_number", SDR_BITS, 8, 5, 3 }, { "lun", SDR_BITS, 8, 3, 2 }, { "private_bus_id", SDR_BITS, 8, 0, 3 }, { "address_span", SDR_BITS, 9, 0, 3 }, { "device_type", SDR_BITS, 11, 0, 8, .required = 1 }, { "device_type_modifier", SDR_BITS, 12, 0, 8, .required = 1 }, { "entity_id", SDR_BITS, 13, 0, 8, .required = 1, .strvals = entity_id_fields }, { "entity_instance", SDR_BITS, 14, 0, 8, .required = 1 }, { "oem", SDR_BITS, 15, 0, 8 }, { "id_string", SDR_STRING, 16, 0, 8, .required = 1 }, }; #define TYPE16_LEN (sizeof(type16) / sizeof(struct sdr_field)) static struct sdr_field type17[] = { { "device_access_address", SDR_BITS, 6, 0, 8, .required = 1 }, { "fru_device_address", SDR_BITS, 7, 0, 8, .required = 1 }, { "logical_fru", SDR_BOOLBIT, 8, 7, 1 }, { "lun", SDR_BITS, 8, 3, 2 }, { "private_bus_id", SDR_BITS, 8, 0, 3 }, { "channel_number", SDR_BITS, 9, 4, 4 }, { "device_type", SDR_BITS, 11, 0, 8, .required = 1 }, { "device_type_modifier", SDR_BITS, 12, 0, 8, .required = 1 }, { "fru_entity_id", SDR_BITS, 13, 0, 8, .required = 1, .strvals = entity_id_fields }, { "fru_entity_instance", SDR_BITS, 14, 0, 8, .required = 1 }, { "oem", SDR_BITS, 15, 0, 8 }, { "id_string", SDR_STRING, 16, 0, 8, .required = 1 }, }; #define TYPE17_LEN (sizeof(type17) / sizeof(struct sdr_field)) static struct sdr_field_name gen_events_modifier_fields[] = { { "enable_event_msg_gen", 0 }, { "disable_event_msg_gen", 1 }, { "do_not_init", 2 }, { NULL } }; static struct sdr_field type18[] = { { "device_slave_address", SDR_BITS, 6, 0, 8, .required = 1 }, { "device_channel_number", SDR_BITS, 7, 0, 4, .required = 1 }, { "ACPI_sys_power_state", SDR_BOOLBIT, 8, 7, 1 }, { "ACPI_dev_power_state", SDR_BOOLBIT, 8, 6, 1 }, { "static_controller", SDR_BOOLBIT, 8, 5, 1 }, { "controller_logs_init", SDR_BOOLBIT, 8, 3, 1 }, { "log_init", SDR_BOOLBIT, 8, 2, 1 }, { "gen_events", SDR_BITS, 8, 0, 2, .strvals = gen_events_modifier_fields }, { "chassis", SDR_BOOLBIT, 9, 7, 1 }, { "bridge", SDR_BOOLBIT, 9, 6, 1 }, { "ipmb_event_gen", SDR_BOOLBIT, 9, 5, 1 }, { "ipmb_event_recv", SDR_BOOLBIT, 9, 4, 1 }, { "fru_inventory", SDR_BOOLBIT, 9, 3, 1 }, { "sel", SDR_BOOLBIT, 9, 2, 1 }, { "sdr", SDR_BOOLBIT, 9, 1, 1 }, { "sensor", SDR_BOOLBIT, 9, 0, 1 }, { "entity_id", SDR_BITS, 13, 0, 8, .required = 1, .strvals = entity_id_fields }, { "entity_instance", SDR_BITS, 14, 0, 8, .required = 1 }, { "oem", SDR_BITS, 15, 0, 8 }, { "id_string", SDR_STRING, 16, 0, 8, .required = 1 }, }; #define TYPE18_LEN (sizeof(type18) / sizeof(struct sdr_field)) struct variable { char *name; char *value; struct variable *next; } *vars; int add_variable(const char *name, const char *value) { struct variable *var = vars, *last = NULL; while (var) { if (strcmp(name, var->name) == 0) break; last = var; var = var->next; } if (var) { free(var->value); } else { var = malloc(sizeof(*var)); if (!var) { fprintf(stderr, "Out of memory\n"); return ENOMEM; } var->name = strdup(name); if (!var->name) { fprintf(stderr, "Out of memory\n"); free(var); return ENOMEM; } var->next = NULL; if (last) last->next = var; else vars = var; } var->value = strdup(value); if (!var->value) { fprintf(stderr, "Out of memory\n"); return ENOMEM; } return 0; } const char *find_var(const char *name) { struct variable *var = vars; while (var) { if (strcmp(name, var->name) == 0) break; var = var->next; } if (!var) { fprintf(stderr, "Unknown variable named %s\n", name); return NULL; } return var->value; } /* * To parse more complex expressions, we really need to know what the * save state is. So we, unfortunately, have to create our own * version of strtok so we know what it is. */ const char * mystrtok(char *str, const char *delim, char **next) { char *pos; char *curr; if (str) curr = str; else curr = *next; /* Skip initial delimiters. */ for (;;) { const char *c = delim; if (*curr == '\0') { *next = curr; return NULL; } while (*c != '\0') { if (*c == *curr) break; c++; } if (*c == '\0') break; curr++; } pos = curr; /* Now collect until there is a delimiter. */ for (;;) { const char *c = delim; if (*curr == '\0') { *next = curr; goto out; } while (*c != '\0') { if (*c == *curr) { *curr = '\0'; *next = curr + 1; goto out; } c++; } curr++; } out: if (*pos == '$') return find_var(pos + 1); else return pos; } int isquote(char c) { return c == '\'' || c == '"'; } int get_delim_str(char **rtokptr, char **rval, char **err) { char *tokptr = *rtokptr; char endc; char *rv = NULL; while (isspace(*tokptr)) tokptr++; if (*tokptr == '\0') { *err = "missing string value"; return -1; } for (;;) { const char *val; if (*tokptr == '$') { char oldc; tokptr++; val = tokptr; while (*tokptr && *tokptr != '$' && !isspace(*tokptr) && !isquote(*tokptr)) { tokptr++; } oldc = *tokptr; *tokptr = '\0'; val = find_var(val); if (!val) { if (rv) free(rv); *err = "variable not found"; return -1; } *tokptr = oldc; } else if (isquote(*tokptr)) { endc = *tokptr; tokptr++; val = tokptr; while (*tokptr != endc) { if (*tokptr == '\0') { if (rv) free(rv); *err = "End of line in string"; return -1; } tokptr++; } *tokptr = '\0'; tokptr++; } else { if (rv) free(rv); *err = "string value must start with '\"' or '''"; return -1; } if (rv) { char *newrv = malloc(strlen(rv) + strlen(val) + 1); if (!newrv) { if (rv) free(rv); *err = "Out of memory copying string"; return -1; } strcpy(newrv, rv); strcat(newrv, val); free(rv); rv = newrv; } else { rv = strdup(val); if (!rv) { *err = "Out of memory copying string"; return -1; } } if (*tokptr == '\0' || isspace(*tokptr)) break; } *rtokptr = tokptr; *rval = rv; return 0; } int get_bool(char **tokptr, unsigned int *rval, char **err) { const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No boolean value given"; return -1; } if (strcasecmp(tok, "true") == 0) *rval = 1; else if (strcasecmp(tok, "false") == 0) *rval = 0; else if (strcasecmp(tok, "on") == 0) *rval = 1; else if (strcasecmp(tok, "off") == 0) *rval = 0; else if (strcasecmp(tok, "yes") == 0) *rval = 1; else if (strcasecmp(tok, "no") == 0) *rval = 0; else if (strcasecmp(tok, "1") == 0) *rval = 1; else if (strcasecmp(tok, "0") == 0) *rval = 0; else { *err = "Invalid boolean value, must be 'true', 'on', 'false', or 'off'"; return -1; } return 0; } int get_uint(char **tokptr, unsigned int *rval, char **err, const char *start) { char *end; const char *tok; if (start) tok = start; else { tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No integer value given"; return -1; } } *rval = strtoul(tok, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } tok = mystrtok(NULL, " \t\n", tokptr); if (tok) { const char *tok2 = mystrtok(NULL, " \t\n", tokptr); unsigned int val2; if (!tok2) { *err = "No value after operator"; return -1; } val2 = strtoul(tok2, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } if (strlen(tok) > 1) { *err = "Invalid operator"; return -1; } switch (*tok) { case '+': *rval += val2; break; case '-': *rval -= val2; break; default: *err = "Invalid operator"; return -1; } } return 0; } int get_int(char **tokptr, int *rval, char **err) { char *end; const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No integer value given"; return -1; } *rval = strtol(tok, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } tok = mystrtok(NULL, " \t\n", tokptr); if (tok) { const char *tok2 = mystrtok(NULL, " \t\n", tokptr); int val2; if (!tok2) { *err = "No value after operator"; return -1; } val2 = strtol(tok2, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } if (strlen(tok) > 1) { *err = "Invalid operator"; return -1; } switch (*tok) { case '+': *rval += val2; break; case '-': *rval -= val2; break; default: *err = "Invalid operator"; return -1; } } return 0; } int get_float(char **tokptr, double *rval, char **err) { char *end; const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No floating point value given"; return -1; } *rval = strtod(tok, &end); if (*end != '\0') { *err = "Invalid floating point value"; return -1; } return 0; } static int get_uint_str(struct sdr_field *t, char **tokptr, unsigned int *rval, char **err) { const char *tok = mystrtok(NULL, " \t\n", tokptr); if (t->strvals) { struct sdr_field_name *s = t->strvals; while (s->name) { if (strcmp(s->name, tok) == 0) { *rval = s->val; return 0; } s++; } } return get_uint(tokptr, rval, err, tok); } static int store_sdr_bits(struct sdr_field *t, unsigned char *sdr, unsigned int len, unsigned int bits, char **errstr) { if (t->pos > len) { *errstr = "Internal error: position out of range"; return -1; } sdr[t->pos - 1] |= (bits & ((1 << t->bitsize) - 1)) << t->bitoff; return 0; } static unsigned int get_sdr_bits(unsigned char *sdr, unsigned int pos, unsigned int bitoff, unsigned int len) { return (sdr[pos - 1] >> bitoff) & ((1 << len) - 1); } int get_sdr_type(int type, struct sdr_field **t, unsigned int *tlen, unsigned int *sdr_len, char **errstr) { switch (type) { case 1: *t = type1; *tlen = TYPE1_LEN; *sdr_len = 48; break; case 2: *t = type2; *tlen = TYPE2_LEN; *sdr_len = 32; break; case 3: *t = type3; *tlen = TYPE3_LEN; *sdr_len = 17; break; case 8: *t = type8; *tlen = TYPE8_LEN; *sdr_len = 16; break; case 9: *t = type9; *tlen = TYPE9_LEN; *sdr_len = 32; break; case 16: *t = type16; *tlen = TYPE16_LEN; *sdr_len = 16; break; case 17: *t = type17; *tlen = TYPE17_LEN; *sdr_len = 16; break; case 18: *t = type18; *tlen = TYPE18_LEN; *sdr_len = 16; break; default: if (errstr) *errstr = "Unknown SDR type, supported types are 1, 2, 3, 8, 9," " 16 (0x10) and 17 (0x11)"; return -1; } return 0; } int ipmi_compile_sdr(FILE *f, unsigned int type, unsigned char **retbuf, unsigned int *retlen, char **errstr, char **errstr2, unsigned int *line) { unsigned int i, j, tlen; struct sdr_field *t; char *requireds, *sets; char buf[MAX_SDR_LINE]; int err = -1; char *tokptr; unsigned char *sdr = NULL; unsigned int sdr_len; *errstr2 = NULL; if (get_sdr_type(type, &t, &tlen, &sdr_len, errstr)) return -1; requireds = malloc(tlen * sizeof(char)); if (!requireds) { *errstr = "Out of memory"; return -1; } sets = malloc(tlen * sizeof(char)); if (!sets) { free(requireds); *errstr = "Out of memory"; return -1; } sdr = malloc(sdr_len); if (!sdr) { err = -1; *errstr = "Out of memory"; goto out_err; } memset(sdr, 0, sdr_len); for (i = 0; i < tlen; i++) { requireds[i] = t[i].required; sets[i] = 0; if (t[i].default_val) store_sdr_bits(&t[i], sdr, sdr_len, t[i].default_val, errstr); } for (;;) { const char *tok; char *s = fgets(buf, sizeof(buf), f); if (s == NULL) { err = -1; *errstr = "Unexpected end of file"; goto out_err; } (*line)++; tok = mystrtok(buf, " \t\n", &tokptr); if (!tok || (tok[0] == '#')) continue; if (strcmp(tok, "endsdr") == 0) break; for (i = 0; i < tlen; i++) { if (strcmp(tok, t[i].name) == 0) { break; } } if (i == tlen) { err = -1; *errstr = "unknown SDR field"; goto out_err; } if (sets[i]) { err = -1; *errstr = "Field already set in this SDR"; *errstr2 = t[i].name; goto out_err; } sets[i] = 1; requireds[i] = 0; switch (t[i].type) { case SDR_BITS: { unsigned int uval, umax; err = get_uint_str(&t[i], &tokptr, &uval, errstr); if (err) goto out_err; umax = (1 << t[i].bitsize) - 1; if (uval > umax) { err = -1; *errstr = "Value too large for bit size"; goto out_err; } err = store_sdr_bits(&t[i], sdr, sdr_len, uval, errstr); if (err) goto out_err; break; } case SDR_SBITS: { int sval, smin, smax; err = get_int(&tokptr, &sval, errstr); if (err) goto out_err; smax = (1 << (t[i].bitsize - 1)) - 1; smin = -smax - 1; if (sval > smax || sval < smin) { err = -1; *errstr = "Value out of range for bit size"; goto out_err; } err = store_sdr_bits(&t[i], sdr, sdr_len, (unsigned int) sval, errstr); if (err) goto out_err; break; } case SDR_BOOLBIT: { unsigned int uval; err = get_bool(&tokptr, &uval, errstr); if (err) goto out_err; err = store_sdr_bits(&t[i], sdr, sdr_len, uval, errstr); if (err) goto out_err; break; } case SDR_MULTIBITS: case SDR_MULTISBITS: { unsigned int uval, totalbits; totalbits = t[i].bitsize; for (j = i + 1; t[j].type == SDR_MULTIBITS2; j++) totalbits += t[j].bitsize; if (t[i].type == SDR_MULTISBITS) { int sval, smin, smax; err = get_int(&tokptr, &sval, errstr); if (err) goto out_err; smax = 1 << (totalbits - 1); smin = -smax - 1; if (sval > smax || sval < smin) { err = -1; *errstr = "Value out of range for bit size"; goto out_err; } uval = (unsigned int) sval; } else { unsigned int umax; err = get_uint_str(&t[i], &tokptr, &uval, errstr); if (err) goto out_err; umax = 1 << totalbits; if (uval > umax) { err = -1; *errstr = "Value too large for bit size"; goto out_err; } } err = store_sdr_bits(&t[i], sdr, sdr_len, uval, errstr); if (err) goto out_err; for (j = i + 1; t[j].type == SDR_MULTIBITS2; j++) { uval >>= t[j - 1].bitsize; err = store_sdr_bits(&t[j], sdr, sdr_len, uval, errstr); if (err) goto out_err; } break; } case SDR_STRING: { unsigned char str[IPMI_MAX_STR_LEN]; char *sval; unsigned int out_len = sizeof(str); err = get_delim_str(&tokptr, &sval, errstr); if (err) goto out_err; if (!ascii_encoding_8_bit) ipmi_set_device_string2(sval, IPMI_ASCII_STR, strlen(sval), str, 0, &out_len, IPMI_STRING_OPTION_NONE); else ipmi_set_device_string2(sval, IPMI_ASCII_STR, strlen(sval), str, 0, &out_len, IPMI_STRING_OPTION_8BIT_ONLY); free(sval); if (out_len > 1) { unsigned char *newsdr = realloc(sdr, sdr_len + out_len - 1); if (!newsdr) { err = -1; *errstr = "Out of memory"; goto out_err; } sdr = newsdr; sdr_len += out_len - 1; } memcpy(sdr + t[i].pos - 1, str, out_len); break; } case SDR_MULTIBITS2: /* Should never happen */ *errstr = "Internal error: multibits2 showed up"; goto out_err; break; case SDR_THRESH: case SDR_THRESHREL: { double fval, fx; int m, b, r_exp, b_exp; err = get_float(&tokptr, &fval, errstr); if (err) goto out_err; m = get_sdr_bits(sdr, 25, 0, 8); m |= get_sdr_bits(sdr, 26, 6, 2) << 8; if (m & (1 << 9)) m |= (~0U << 10); b = get_sdr_bits(sdr, 27, 0, 8); b |= get_sdr_bits(sdr, 28, 6, 2) << 8; if (b & (1 << 9)) b |= (~0U << 10); r_exp = get_sdr_bits(sdr, 30, 4, 4); if (r_exp & (1 << 3)) r_exp |= (~0U << 4); b_exp = get_sdr_bits(sdr, 30, 0, 4); if (b_exp & (1 << 3)) b_exp |= (~0U << 4); if (t[i].type == SDR_THRESHREL) /* * A threshold value, like hysteresis. It's not * an absolute value, it's a relative value, so we * leave "b" out of the equation. Note that this * only works for linear equations. */ fx = (((fval / pow(10, r_exp))) / ((double) m)); else fx = (((fval / pow(10, r_exp)) - ((double) b) * pow(10, b_exp)) / ((double) m)); /* * We always round here. This means that a threshold * may be set that is on the "wrong side" of the * threshold, and the trigger may too sensitive. Or * perhaps insensitive. Of course, that can happen * without rounding, too. There appears to be no easy * way to second-guess the user of this program and, * given a floating point value, figure out the proper * integer value they want. Instead, they are expected * to give a floating point value that will evaluate * very closely to the integer they want. Rounding * should handle the issue of getting it right on the * integer value the user wants and avoid issues with * floating point imprecision. */ fx = round(fx); if (fx < 0.0 || fx > 255.0) { err = -1; *errstr = "Value out of range type"; goto out_err; } err = store_sdr_bits(&t[i], sdr, sdr_len, (unsigned int) fx, errstr); if (err) goto out_err; break; } } } for (i = 0; i < tlen; i++) { if (requireds[i]) { err = -1; *errstr = "Missing required field:"; *errstr2 = t[i].name; goto out_err; } } free(requireds); free(sets); sdr[2] = 0x51; sdr[3] = type; sdr[4] = sdr_len - 5; *retbuf = sdr; *retlen = sdr_len; return 0; out_err: free(requireds); free(sets); if (sdr) free(sdr); return err; } struct includes { const char *dirname; struct includes *next; }; static struct includes *includes; static void add_include_dir(const char *dirname) { struct includes *n, *p; n = malloc(sizeof(*n)); if (!n) { fprintf(stderr, "Out of memory allocating include dir\n"); exit(1); } n->dirname = dirname; n->next = NULL; if (!includes) { includes = n; return; } p = includes; while (p->next) p = p->next; p->next = n; } static FILE * open_include(const char *filename, unsigned int line, const char *name) { FILE *f; struct includes *n; int namelen; f = fopen(name, "r"); if (f) return f; namelen = strlen(name); for (n = includes; n; n = n->next) { char *s = malloc(namelen + strlen(n->dirname) + 2); sprintf(s, "%s/%s", n->dirname, name); f = fopen(s, "r"); if (f) return f; free(s); } fprintf(stderr, "%s:%3d: Unable to open included file %s\n", filename, line, name); out_err(1); return NULL; } static void compile_file(const char *filename, FILE *f, persist_t *p, int outraw, unsigned int *sdrnum) { char buf[MAX_SDR_LINE]; char *s; unsigned int line = 0; while ((s = fgets(buf, sizeof(buf), f))) { int err; unsigned int sdrtype; char *errstr, *errstr2; unsigned char *sdr; unsigned int sdrlen; char *tokptr; const char *tok; line++; tok = mystrtok(buf, " \t\n", &tokptr); if (!tok || (tok[0] == '#')) continue; if (strcmp(tok, "sdr") == 0) { tok = mystrtok(NULL, " \n\t", &tokptr); if (!tok || strcmp(tok, "type") != 0) { fprintf(stderr, "%s:%3d: Invalid input, expecting \"sdr type \"\n", filename, line); out_err(1); } err = get_uint(&tokptr, &sdrtype, &errstr, NULL); if (err) { fprintf(stderr, "%s:%3d: Invalid input, expecting \"sdr type \":" " %s\n", filename, line, errstr); out_err(1); } err = ipmi_compile_sdr(f, sdrtype, &sdr, &sdrlen, &errstr, &errstr2, &line); if (err) { if (errstr2) fprintf(stderr, "%s:%3d: %s: %s\n", filename, line, errstr, errstr2); else fprintf(stderr, "%s:%3d: %s\n", filename, line, errstr); out_err(1); } sdr[0] = *sdrnum & 0xff; sdr[1] = (*sdrnum >> 8) & 0xff; if (outraw) { fwrite(sdr, sdrlen, 1, outfile); } else { err = add_persist_data(p, sdr, sdrlen, "%d", *sdrnum); if (err) { fprintf(stderr, "Out of memory\n"); out_err(1); } } (*sdrnum)++; free(sdr); } else if (strcmp(tok, "define") == 0) { const char *name; char *value; name = mystrtok(NULL, " \n\t", &tokptr); if (!name) { fprintf(stderr, "%s:%3d: Invalid input, expecting variable name\n", filename, line); out_err(1); } err = get_delim_str(&tokptr, &value, &errstr); if (err) { fprintf(stderr, "%s:%3d: Invalid value, expecting quote delimited" " string: %s\n", filename, line, errstr); out_err(1); } err = add_variable(name, value); if (err) { free(value); out_err(1); } } else if (strcmp(tok, "include") == 0) { char *nfilename; FILE *f2; err = get_delim_str(&tokptr, &nfilename, &errstr); if (err) { fprintf(stderr, "%s:%3d: Invalid filename, expecting quote delimited" " string: %s\n", filename, line, errstr); out_err(1); } f2 = open_include(filename, line, nfilename); compile_file(nfilename, f2, p, outraw, sdrnum); fclose(f2); } else { fprintf(stderr, "%s:%3d: Invalid input," " expecting \"sdr type \"\n", filename, line); out_err(1); } } } static int extract_bits(uint8_t *sdr, struct sdr_field *t) { unsigned int v; /* * Note that the pos is the IPMI 1's based offset, not a zero * based offset. So we subtract 1 to get the array position. */ v = sdr[t->pos - 1]; v >>= t->bitoff; v &= (1 << t->bitsize) - 1; return v; } static int sign_extend(int v, int bitsize) { if (v & (1 << (bitsize - 1))) { /* Negative */ v &= ~(1 << (bitsize - 1)); v = -v - 1; } return v; } static void dump_val(struct sdr_field *t, int v) { struct sdr_field_name *n = t->strvals; if (n) { while (n->name) { if (v == n->val) { fprintf(outfile, "%s\n", n->name); return; } n++; } } fprintf(outfile, "%d\n", v); } static void dump_int(uint8_t *sdr, struct sdr_field *t, int is_signed) { int v = extract_bits(sdr, t); if (is_signed) v = sign_extend(v, t->bitsize); dump_val(t, v); } static void dump_multibits(uint8_t *sdr, struct sdr_field *t, int is_signed) { int v = extract_bits(sdr, t); int shift = t->bitsize; t++; while (t->type == SDR_MULTIBITS2) { v |= extract_bits(sdr, t) << shift; shift += t->bitsize; t++; } if (is_signed) v = sign_extend(v, t->bitsize); dump_val(t, v); } static void dump_thresh(uint8_t *sdr, struct sdr_field *t, int is_rel) { int v = extract_bits(sdr, t); int m, b, r_exp, b_exp, is_signed; double fx; is_signed = get_sdr_bits(sdr, 21, 6, 2); if (is_signed) v = sign_extend(v, t->bitsize); m = get_sdr_bits(sdr, 25, 0, 8); m |= get_sdr_bits(sdr, 26, 6, 2) << 8; if (m & (1 << 9)) m |= (~0U << 10); b = get_sdr_bits(sdr, 27, 0, 8); b |= get_sdr_bits(sdr, 28, 6, 2) << 8; if (b & (1 << 9)) b |= (~0U << 10); r_exp = get_sdr_bits(sdr, 30, 4, 4); if (r_exp & (1 << 3)) r_exp |= (~0U << 4); b_exp = get_sdr_bits(sdr, 30, 0, 4); if (b_exp & (1 << 3)) b_exp |= (~0U << 4); fx = ((double) m) * ((double) v); if (!is_rel) fx += ((double) b) * pow(10, b_exp); fx *= pow(10, r_exp); fprintf(outfile, "%f\n", fx); } static void dump_string(uint8_t *sdr, struct sdr_field *t, unsigned int sdr_len) { unsigned char *sptr = ((unsigned char *) sdr) + t->pos - 1; char str[IPMI_MAX_STR_LEN + 1]; unsigned int out_len; enum ipmi_str_type_e stype; int err; err = ipmi_get_device_string(&sptr, sdr_len + 5 - t->pos + 1, str, IPMI_STR_SDR_SEMANTICS, 0, &stype, sizeof(str), &out_len); if (err) { fprintf(stderr, "Warning: Invalid SDR string, search for **INVALID**" " in output\n"); fprintf(outfile, "**INVALID**\n"); return; } str[out_len] = '\0'; fprintf(outfile, "%s\n", str); } static void dump_sdr_field(uint8_t *sdr, struct sdr_field *t, unsigned int len) { if (t->type == SDR_MULTIBITS2) return; fprintf(outfile, "\t%s\t", t->name); switch(t->type) { case SDR_BITS: case SDR_SBITS: dump_int(sdr, t, t->type == SDR_SBITS); break; case SDR_BOOLBIT: if (sdr[t->pos] & (1 << t->bitoff)) fprintf(outfile, "true\n"); else fprintf(outfile, "false\n"); break; case SDR_MULTIBITS: case SDR_MULTISBITS: dump_multibits(sdr, t, t->type == SDR_MULTISBITS); break; case SDR_MULTIBITS2: break; case SDR_THRESH: case SDR_THRESHREL: dump_thresh(sdr, t, t->type == SDR_THRESHREL); break; case SDR_STRING: dump_string(sdr, t, len); break; } } static void decompile_file(FILE *f) { uint8_t sdr[261]; size_t l; int recnum = 0; struct sdr_field *t; unsigned int tlen, sdr_len; size_t offset = 0; unsigned int i; l = fread(sdr, 5, 1, f); while (l == 1) { uint16_t recid = sdr[0] | sdr[1] << 8; int badtype = 0; if (sdr[2] != 0x51) { fprintf(stderr, "SDR %d offset %ld: Unknown SDR version: 0x%x\n", recnum, offset, sdr[2]); } fprintf(outfile, "# Record id: %d\n", recid); fprintf(outfile, "# Record num: %d\n", recnum); if (get_sdr_type(sdr[3], &t, &tlen, &sdr_len, NULL)) { fprintf(outfile, "# unknown type: %d\n", sdr[3]); badtype = 1; } else if (sdr[4] < sdr_len - 5) { fprintf(stderr, "SDR %d offset %ld type %d: not long enough: %d," " expected %d\n", recnum, offset, sdr[3], sdr[4], sdr_len - 5); exit(1); } l = fread(sdr + 5, sdr[4], 1, f); if (l != 1) { if (ferror(f)) { fprintf(stderr, "Error reading file: %s\n", strerror(errno)); exit(1); } else { fprintf(stderr, "End of file in the middle of" " record %d offset %ld\n", recnum, offset); exit(1); } } if (!badtype) { fprintf(outfile, "sdr %d\n", sdr[3]); for (i = 0; i < tlen; i++) dump_sdr_field(sdr, t + i, sdr[4]); fprintf(outfile, "endsdr\n\n"); } offset += sdr[4] + 5; l = fread(sdr, 5, 1, f); recnum++; } if (ferror(f)) { fprintf(stderr, "Error reading file: %s\n", strerror(errno)); exit(1); } } static char *progname; static void help(void) { fprintf(stderr, "%s [-r] [-8] [-o ] [-d] \n", progname); exit(1); } int main(int argc, char *argv[]) { FILE *f; persist_t *p = NULL; unsigned int sdrnum = 1; int argn; int outraw = 0; int decompile = 0; progname = argv[0]; outfile = stdout; for (argn = 1; argn < argc; argn++) { if (argv[argn][0] != '-') break; if (strcmp(argv[argn], "--") == 0) break; if (strcmp(argv[argn], "-r") == 0) { outraw = 1; } else if (strcmp(argv[argn], "-8") == 0) { ascii_encoding_8_bit = 1; } else if (strcmp(argv[argn], "-d") == 0) { decompile = 1; } else if (strcmp(argv[argn], "-I") == 0) { argn++; if (argn == argc) { fprintf(stderr, "No value supplied for -I\n"); exit(1); } add_include_dir(argv[argn]); } else if (strcmp(argv[argn], "-o") == 0) { argn++; if (argn == argc) { fprintf(stderr, "No value supplied for -o\n"); exit(1); } outfname = argv[argn]; } else { fprintf(stderr, "Invalid option: %s\n", argv[argn]); exit(1); } } if ((argc - argn) < 1) { fprintf(stderr, "No input file given\n"); help(); } f = fopen(argv[argn], "r"); if (!f) { fprintf(stderr, "Unable to open input file %s\n", argv[argn]); exit(1); } argn++; if (argn < argc) { fprintf(stderr, "Extra arguments at end: %s\n", argv[argn]); exit(1); } if (!outraw && !decompile) { p = alloc_persist(""); if (!p) { fprintf(stderr, "Out of memory\n"); exit(1); } } if (outfname) { outfile = fopen(outfname, "w"); if (!outfile) { fprintf(stderr, "Unable to open output file %s: %s\n", outfname, strerror(errno)); exit(1); } } if (decompile) decompile_file(f); else compile_file(argv[argn - 1], f, p, outraw, &sdrnum); fclose(f); if (!outraw && !decompile) { add_persist_int(p, time(NULL), "last_add_time"); write_persist_file(p, outfile); free_persist(p); } return 0; } OpenIPMI-2.0.33/lanserv/ipmi_sim.c0000664000175000017500000011320214002617260013523 00000000000000/* * ipmi_sim.c * * MontaVista IPMI code for creating a LAN interface, emulated system * interfaces, and a full BMC emulator. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005,2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Option parsing made easy */ #include #include #include #include #include #if HAVE_SYSLOG #include #endif #include #include #include #include #include #include #include "emu.h" #include #include #include #include #include "ipmi_sim.h" #define MAX_ADDR 4 #define BASE_CONF_STR SYSCONFDIR "/ipmi" static char *config_file = BASE_CONF_STR "/lan.conf"; static const char *statedir = STATEDIR; static char *command_string = NULL; static char *command_file = NULL; static int debug = 0; static int nostdio = 0; /* * Keep track of open sockets so we can close them on exec(). */ typedef struct isim_fd { int fd; struct isim_fd *next; } isim_fd_t; static isim_fd_t *isim_fds = NULL; static void isim_add_fd(int fd) { isim_fd_t *n = malloc(sizeof(*n)); if (!n) { fprintf(stderr, "Unable to add fd to list, out of memory\n"); exit(1); } n->fd = fd; n->next = isim_fds; isim_fds = n; } static void isim_close_fds(void) { isim_fd_t *n = isim_fds; while(n) { close(n->fd); n = n->next; } } static void shutdown_handler(int sig); typedef struct misc_data misc_data_t; typedef struct console_info_s { char buffer[1024]; unsigned int pos; int telnet; int echo; int shutdown_on_close; misc_data_t *data; int outfd; os_hnd_fd_id_t *conid; unsigned int tn_pos; unsigned char tn_buf[4]; emu_out_t out; struct console_info_s *prev; struct console_info_s *next; } console_info_t; struct misc_data { sys_data_t *sys; emu_data_t *emu; os_handler_t *os_hnd; os_handler_waiter_factory_t *waiter_factory; os_hnd_timer_id_t *timer; console_info_t *consoles; }; static misc_data_t *global_misc_data; static void * balloc(sys_data_t *sys, int size) { return malloc(size); } static void bfree(sys_data_t *sys, void *data) { return free(data); } typedef struct sim_addr_s { struct sockaddr_storage addr; socklen_t addr_len; int xmit_fd; } sim_addr_t; static int smi_send(channel_t *chan, msg_t *msg) { misc_data_t *data = chan->oem.user_data; unsigned char msgd[36]; unsigned int msgd_len = sizeof(msgd); ipmi_emu_handle_msg(data->emu, chan->mc, msg, msgd, &msgd_len); ipmi_handle_smi_rsp(chan, msg, msgd, msgd_len); return 0; } static int gen_rand(lanserv_data_t *lan, void *data, int len) { return gen_random(data, len); } static int sys_gen_rand(sys_data_t *lan, void *data, int len) { return gen_random(data, len); } static void lan_send(lanserv_data_t *lan, struct iovec *data, int vecs, void *addr, int addr_len) { struct msghdr msg; sim_addr_t *l = addr; int rv; /* When we send messages to ourself, we set the address to NULL so it won't be used. */ if (!l) return; memset(&msg, 0, sizeof(msg)); msg.msg_name = &(l->addr); msg.msg_namelen = l->addr_len; msg.msg_iov = data; msg.msg_iovlen = vecs; rv = sendmsg(l->xmit_fd, &msg, 0); if (rv) { /* FIXME - log an error. */ } } static void lan_data_ready(int lan_fd, void *cb_data, os_hnd_fd_id_t *id) { lanserv_data_t *lan = cb_data; int len; sim_addr_t l; unsigned char msgd[256]; l.addr_len = sizeof(l.addr); len = recvfrom(lan_fd, msgd, sizeof(msgd), 0, (struct sockaddr *) &(l.addr), &(l.addr_len)); if (len < 0) { if (errno != EINTR) { perror("Error receiving message"); exit(1); } goto out; } l.xmit_fd = lan_fd; if (lan->sysinfo->debug & DEBUG_RAW_MSG) { debug_log_raw_msg(lan->sysinfo, (void *) &l.addr, l.addr_len, "Raw LAN receive from:"); debug_log_raw_msg(lan->sysinfo, msgd, len, " Receive message:"); } if (len < 4) goto out; if (msgd[0] != 6) goto out; /* Invalid version */ /* Check the message class. */ switch (msgd[3]) { case 6: handle_asf(lan, msgd, len, &l, sizeof(l)); break; case 7: ipmi_handle_lan_msg(lan, msgd, len, &l, sizeof(l)); break; } out: return; } static int open_lan_fd(struct sockaddr *addr, socklen_t addr_len) { int fd; int rv; int opt; fd = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); if (fd == -1) { perror("Unable to create socket"); exit(1); } opt = 1; rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (rv == -1) { fprintf(stderr, "Unable to set SO_REUSEADDR: %s\n", strerror(errno)); exit(1); } rv = bind(fd, addr, addr_len); if (rv == -1) { fprintf(stderr, "Unable to bind to LAN port: %s\n", strerror(errno)); exit(1); } isim_add_fd(fd); return fd; } static int lan_channel_init(void *info, channel_t *chan) { misc_data_t *data = info; lanserv_data_t *lan = chan->chan_info; int err; int lan_fd; os_hnd_fd_id_t *fd_id; unsigned char addr_data[6]; lan->user_info = data; lan->send_out = lan_send; lan->gen_rand = gen_rand; err = ipmi_lan_init(lan); if (err) { fprintf(stderr, "Unable to init lan: 0x%x\n", err); exit(1); } if (lan->guid) { lmc_data_t *sys = ipmi_emu_get_bmc_mc(data->emu); if (sys) ipmi_emu_set_mc_guid(sys, lan->guid, 0); } if (lan->lan_addr_set) { lan_fd = open_lan_fd(&lan->lan_addr.addr.s_ipsock.s_addr0, lan->lan_addr.addr_len); if (lan_fd == -1) { fprintf(stderr, "Unable to open LAN address\n"); exit(1); } memcpy(addr_data, &lan->lan_addr.addr.s_ipsock.s_addr4.sin_addr.s_addr, 4); memcpy(addr_data + 4, &lan->lan_addr.addr.s_ipsock.s_addr4.sin_port, 2); ipmi_emu_set_addr(data->emu, 0, 0, addr_data, 6); err = data->os_hnd->add_fd_to_wait_for(data->os_hnd, lan_fd, lan_data_ready, lan, NULL, &fd_id); if (err) { fprintf(stderr, "Unable to add socket wait: 0x%x\n", err); exit(1); } } return err; } static void ser_send(serserv_data_t *ser, unsigned char *data, unsigned int data_len) { int rv; if (ser->con_fd == -1) /* Not connected */ return; rv = write(ser->con_fd, data, data_len); if (rv) { /* FIXME - log an error. */ } } static void ser_data_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { serserv_data_t *ser = cb_data; int len; unsigned char msgd[256]; len = recv(fd, msgd, sizeof(msgd), 0); if (len <= 0) { if ((len < 0) && (errno == EINTR)) return; if (ser->codec->disconnected) ser->codec->disconnected(ser); ser->os_hnd->remove_fd_to_wait_for(ser->os_hnd, id); close_socket(fd); ser->con_fd = -1; return; } serserv_handle_data(ser, msgd, len); } static void ser_bind_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { serserv_data_t *ser = cb_data; int rv; int err; os_hnd_fd_id_t *fd_id; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); int val = 1; rv = accept(fd, (struct sockaddr *) &addr, &addr_len); if (rv < 0) { perror("Error from accept"); exit(1); } if (ser->con_fd >= 0) { close_socket(rv); return; } setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(rv, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(val)); ser->con_fd = rv; err = ser->os_hnd->add_fd_to_wait_for(ser->os_hnd, ser->con_fd, ser_data_ready, ser, NULL, &fd_id); if (err) { fprintf(stderr, "Unable to add serial socket wait: 0x%x\n", err); ser->con_fd = -1; close_socket(rv); } else { if (ser->codec->connected) ser->codec->connected(ser); } } static int ser_channel_init(void *info, channel_t *chan) { misc_data_t *data = info; serserv_data_t *ser = chan->chan_info; int err; int fd; struct sockaddr *addr = &ser->addr.addr.s_ipsock.s_addr0; os_hnd_fd_id_t *fd_id; int val; ser->os_hnd = data->os_hnd; ser->user_info = data; ser->send_out = ser_send; err = serserv_init(ser); if (err) { fprintf(stderr, "Unable to init serial: 0x%x\n", err); exit(1); } fd = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { perror("Unable to create socket"); exit(1); } if (ser->do_connect) { err = connect(fd, addr, ser->addr.addr_len); if (err == -1) { fprintf(stderr, "Unable to connect to serial TCP port: %s\n", strerror(errno)); exit(1); } ser->con_fd = fd; ser->bind_fd = -1; err = data->os_hnd->add_fd_to_wait_for(data->os_hnd, ser->con_fd, ser_data_ready, ser, NULL, &fd_id); if (err) { fprintf(stderr, "Unable to add serial socket wait: 0x%x\n", err); exit(1); } } else { int opt = 1; err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (err == -1) { fprintf(stderr, "Unable to set SO_REUSEADDR on serial TCP: %s\n", strerror(errno)); exit(1); } err = bind(fd, addr, ser->addr.addr_len); if (err == -1) { fprintf(stderr, "Unable to bind to serial TCP port: %s\n", strerror(errno)); exit(1); } ser->bind_fd = fd; ser->con_fd = -1; err = listen(fd, 1); if (err == -1) { fprintf(stderr, "Unable to listen to serial TCP port: %s\n", strerror(errno)); exit(1); } val = 1; err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); if (err == -1) { fprintf(stderr, "Unable to set SO_REUSEADDR on socket: %s\n", strerror(errno)); exit(1); } err = data->os_hnd->add_fd_to_wait_for(data->os_hnd, ser->bind_fd, ser_bind_ready, ser, NULL, &fd_id); if (err) { fprintf(stderr, "Unable to add serial socket wait: 0x%x\n", err); exit(1); } } if (!err) isim_add_fd(fd); return err; } static int ipmb_open(char *ipmi_dev) { int ipmi_fd; if (!ipmi_dev) { fprintf(stderr, "ipmi_dev is not specified\n"); return -1; } ipmi_fd = open(ipmi_dev, O_RDWR); if (ipmi_fd == -1) fprintf(stderr, "Could not open ipmi device\n"); return ipmi_fd; } static void ipmb_data_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { ipmbserv_data_t *ipmb = cb_data; unsigned int len; unsigned char msgd[256]; len = read(fd, msgd, sizeof(msgd)); if (ipmb->sysinfo->debug & DEBUG_MSG) printf(">ipmb_data_ready size %d\n", len); if (len <= 0) { if ((len < 0) && (errno == EINTR)) return; ipmb->os_hnd->remove_fd_to_wait_for(ipmb->os_hnd, id); close(fd); ipmb->fd = -1; return; } ipmbserv_handle_data(ipmb, msgd, len); } static void ipmb_send(ipmbserv_data_t *ipmb, unsigned char *data, unsigned int data_len) { int rv; if (ipmb->fd == -1) /* Not connected */ return; rv = write(ipmb->fd, data, data_len); if (rv) { /* FIXME - log an error. */ } } static int ipmb_channel_init(void *info, channel_t *chan) { misc_data_t *data = info; ipmbserv_data_t *ipmb = chan->chan_info; int err; os_hnd_fd_id_t *fd_id; ipmb->os_hnd = data->os_hnd; ipmb->user_info = data; ipmb->send_out = ipmb_send; err = ipmbserv_init(ipmb); if (err) { fprintf(stderr, "Unable to init ipmb: 0x%x\n", err); exit(1); } ipmb->fd = ipmb_open(ipmb->ipmbdev); if (ipmb->fd == -1){ fprintf(stderr, "Unable to open ipmi device file: 0x%x\n", err); exit(1); } err = data->os_hnd->add_fd_to_wait_for(data->os_hnd, ipmb->fd, ipmb_data_ready, ipmb, NULL, &fd_id); if (err) { close(ipmb->fd); ipmb->fd = -1; fprintf(stderr, "Unable to open ipmi device file: 0x%x\n", err); exit(1); } isim_add_fd(ipmb->fd); return 0; } static void isim_log(sys_data_t *sys, int logtype, msg_t *msg, const char *format, va_list ap, int len) { misc_data_t *data = sys->info; char *str; console_info_t *con; if (msg) { char dummy; int pos; unsigned int i; #define mformat " channel=%d netfn=0x%x cmd=0x%x rs_addr=0x%x rs_lun=0x%x" \ " rq_addr=0x%x\n rq_lun=0x%x rq_seq=0x%x\n" len += snprintf(&dummy, 0, mformat, msg->channel, msg->netfn, msg->cmd, msg->rs_addr, msg->rs_lun, msg->rq_addr, msg->rq_lun, msg->rq_seq); len += 3 * msg->len + 3; str = malloc(len); if (!str) return; pos = vsprintf(str, format, ap); str[pos++] = '\n'; pos += sprintf(str + pos, mformat, msg->channel, msg->netfn, msg->cmd, msg->rs_addr, msg->rs_lun, msg->rq_addr, msg->rq_lun, msg->rq_seq); #undef mformat for (i = 0; i < msg->len; i++) pos += sprintf(str + pos, " %2.2x", msg->data[i]); } else { str = malloc(len + 1); if (!str) return; vsprintf(str, format, ap); } con = data->consoles; while (con) { con->out.eprintf(&con->out, "%s", str); con->out.eprintf(&con->out, "\n"); con = con->next; } #if HAVE_SYSLOG if (logtype == DEBUG) syslog(LOG_DEBUG, "%s", str); else syslog(LOG_NOTICE, "%s", str); #endif free(str); } static void sim_log(sys_data_t *sys, int logtype, msg_t *msg, const char *format, ...) { va_list ap; char dummy; int len; va_start(ap, format); len = vsnprintf(&dummy, 1, format, ap); va_end(ap); va_start(ap, format); isim_log(sys, logtype, msg, format, ap, len); va_end(ap); } static void sim_chan_log(channel_t *chan, int logtype, msg_t *msg, const char *format, ...) { va_list ap; char dummy; int len; va_start(ap, format); len = vsnprintf(&dummy, 1, format, ap); va_end(ap); va_start(ap, format); isim_log(global_misc_data->sys, logtype, msg, format, ap, len); va_end(ap); } static struct poptOption poptOpts[]= { { "config-file", 'c', POPT_ARG_STRING, &config_file, 'c', "configuration file", "" }, { "command-string", 'x', POPT_ARG_STRING, &command_string, 'x', "command string", "" }, { "command-file", 'f', POPT_ARG_STRING, &command_file, 'f', "command file", "" }, { "state-dir", 's', POPT_ARG_STRING, &statedir, 's', "state directory", "" }, { "debug", 'd', POPT_ARG_NONE, NULL, 'd', "debug", "" }, { "version", 'v', POPT_ARG_NONE, NULL, 'v', "version", "" }, { "nostdio", 'n', POPT_ARG_NONE, NULL, 'n', "nostdio", "" }, { "nopersist", 'p', POPT_ARG_NONE, NULL, 'p', "nopersist", "" }, POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; static void emu_printf(emu_out_t *out, char *format, ...) { console_info_t *info = out->data; va_list ap; char buffer[500]; int start = 0; int pos; va_start(ap, format); vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); for (pos = 0; buffer[pos]; pos++) { if (buffer[pos] == '\n') { (void) write(info->outfd, buffer + start, pos - start + 1); (void) write(info->outfd, "\r", 1); start = pos + 1; } } if (pos != start) (void) write(info->outfd, buffer + start, pos - start); } static void dummy_printf(emu_out_t *out, char *format, ...) { } #define TN_IAC 255 #define TN_WILL 251 #define TN_WONT 252 #define TN_DO 253 #define TN_DONT 254 #define TN_OPT_SUPPRESS_GO_AHEAD 3 #define TN_OPT_ECHO 1 static unsigned char handle_telnet(console_info_t *info, unsigned char c) { info->tn_buf[info->tn_pos++] = c; if ((info->tn_pos == 2) && (info->tn_buf[1] == TN_IAC)) /* Double IAC, just send it on. */ return TN_IAC; if ((info->tn_pos == 2) && (info->tn_buf[1] < 250)) /* Ignore 1-byte commands */ goto cmd_done; if ((info->tn_pos == 3) && (info->tn_buf[1] != 250)) { /* Two byte commands */ switch (info->tn_buf[1]) { case TN_WILL: goto send_dont; case TN_WONT: break; case TN_DO: if ((info->tn_buf[2] == TN_OPT_ECHO) || (info->tn_buf[2] == TN_OPT_SUPPRESS_GO_AHEAD)) break; goto send_wont; } goto cmd_done; } if (info->tn_pos < 4) return 0; /* * We are in a suboption, which we ignore. Just look for * IAC 240 for the end. Use tn_buf[2] to track the last * character we got. */ if ((info->tn_buf[2] == TN_IAC) && (info->tn_buf[3] == 240)) goto cmd_done; info->tn_buf[2] = info->tn_buf[3]; info->tn_pos--; send_wont: info->tn_buf[1] = TN_WONT; (void) write(info->outfd, info->tn_buf, 3); goto cmd_done; send_dont: info->tn_buf[1] = TN_DONT; (void) write(info->outfd, info->tn_buf, 3); goto cmd_done; cmd_done: info->tn_pos = 0; return 0; } static int handle_user_char(console_info_t *info, unsigned char c) { if (info->tn_pos) c = handle_telnet(info, c); if (!c) return 0; switch(c) { case TN_IAC: if (info->telnet) { info->tn_buf[0] = c; info->tn_pos = 1; } else goto handle_char; break; case 8: case 0x7f: if (info->pos > 0) { info->pos--; if (info->echo) (void) write(info->outfd, "\b \b", 3); } break; case 4: if (info->pos == 0) { if (info->echo) (void) write(info->outfd, "\n", 1); return 1; } break; case 10: case 13: if (info->echo) { (void) write(info->outfd, "\n", 1); if (info->telnet) (void) write(info->outfd, "\r", 1); } info->buffer[info->pos] = '\0'; if (strcmp(info->buffer, "noecho") == 0) { info->echo = 0; } else { ipmi_emu_cmd(&info->out, info->data->emu, info->buffer); } (void) write(info->outfd, "> ", 2); info->pos = 0; break; handle_char: default: if (info->pos >= sizeof(info->buffer)-1) { char *msg = "\nCommand is too long, max of %d characters\n"; (void) write(info->outfd, msg, strlen(msg)); } else { info->buffer[info->pos] = c; info->pos++; if (info->echo) (void) write(info->outfd, &c, 1); } } return 0; } static void user_data_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { console_info_t *info = cb_data; unsigned char rc[50]; unsigned char *c = rc; int count; count = read(fd, rc, sizeof(rc)); if (count == 0) goto closeit; while (count > 0) { if (handle_user_char(info, *c)) goto closeit; c++; count--; } return; closeit: if (info->shutdown_on_close) { ipmi_emu_shutdown(info->data->emu); return; } info->data->os_hnd->remove_fd_to_wait_for(info->data->os_hnd, info->conid); close(fd); if (info->prev) info->prev->next = info->next; else info->data->consoles = info->next; if (info->next) info->next->prev = info->prev; free(info); } static void console_bind_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { misc_data_t *misc = cb_data; console_info_t *newcon; int rv; int err; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); int val = 1; static unsigned char telnet_init_seq[] = { TN_IAC, TN_WILL, TN_OPT_SUPPRESS_GO_AHEAD, TN_IAC, TN_WILL, TN_OPT_ECHO, TN_IAC, TN_DONT, TN_OPT_ECHO, }; rv = accept(fd, (struct sockaddr *) &addr, &addr_len); if (rv < 0) { perror("Error from accept"); exit(1); } newcon = malloc(sizeof(*newcon)); if (!newcon) { char *msg = "Out of memory\n"; err = write(rv, msg, strlen(msg)); close_socket(rv); return; } newcon->data = misc; newcon->outfd = rv; newcon->pos = 0; newcon->echo = 1; newcon->shutdown_on_close = 0; newcon->telnet = 1; newcon->tn_pos = 0; newcon->out.eprintf = emu_printf; newcon->out.data = newcon; setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(rv, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(val)); err = misc->os_hnd->add_fd_to_wait_for(misc->os_hnd, rv, user_data_ready, newcon, NULL, &newcon->conid); if (err) { char *msg = "Unable to add socket wait\n"; err = write(rv, msg, strlen(msg)); close_socket(rv); free(newcon); return; } newcon->next = misc->consoles; if (newcon->next) newcon->next->prev = newcon; newcon->prev = NULL; misc->consoles = newcon; err = write(rv, telnet_init_seq, sizeof(telnet_init_seq)); err = write(rv, "> ", 2); } struct termios old_termios; int old_flags; static void init_term(void) { struct termios new_termios; tcgetattr(0, &old_termios); new_termios = old_termios; new_termios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); new_termios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); new_termios.c_cc[VTIME] = 0; new_termios.c_cc[VMIN] = 0; tcsetattr(0, TCSADRAIN, &new_termios); } void ipmi_emu_shutdown(emu_data_t *emu) { misc_data_t *data = ipmi_emu_get_user_data(emu); console_info_t *con; if (data->sys->console_fd != -1) close(data->sys->console_fd); con = data->consoles; while (con) { data->os_hnd->remove_fd_to_wait_for(data->os_hnd, con->conid); close(con->outfd); con = con->next; } if (!nostdio) tcsetattr(0, TCSADRAIN, &old_termios); fcntl(0, F_SETFL, old_flags); tcdrain(0); shutdown_handler(0); exit(0); } /* Sleep and don't take any user input. */ static void sleeper(emu_data_t *emu, struct timeval *time) { misc_data_t *data = ipmi_emu_get_user_data(emu); os_handler_waiter_t *waiter; waiter = os_handler_alloc_waiter(data->waiter_factory); if (!waiter) { fprintf(stderr, "Unable to allocate waiter\n"); exit(1); } os_handler_waiter_wait(waiter, time); os_handler_waiter_release(waiter); } struct ipmi_io_s { os_hnd_fd_id_t *id; misc_data_t *data; void (*read_cb)(int fd, void *cb_data); void (*write_cb)(int fd, void *cb_data); void (*except_cb)(int fd, void *cb_data); void *cb_data; }; static void io_read_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { ipmi_io_t *io = cb_data; io->read_cb(fd, io->cb_data); } static void io_write_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { ipmi_io_t *io = cb_data; io->write_cb(fd, io->cb_data); } static void io_except_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { ipmi_io_t *io = cb_data; io->except_cb(fd, io->cb_data); } static void ipmi_io_set_hnds(ipmi_io_t *io, void (*write_hnd)(int fd, void *cb_data), void (*except_hnd)(int fd, void *cb_data)) { io->write_cb = write_hnd; io->except_cb = except_hnd; } static void ipmi_io_set_enables(ipmi_io_t *io, int read, int write, int except) { io->data->os_hnd->set_fd_enables(io->data->os_hnd, io->id, read, write, except); } static int ipmi_add_io_hnd(sys_data_t *sys, int fd, void (*read_hnd)(int fd, void *cb_data), void *cb_data, ipmi_io_t **rio) { ipmi_io_t *io; misc_data_t *data = sys->info; int err; io = malloc(sizeof(*io)); if (!io) return ENOMEM; io->data = data; io->read_cb = read_hnd; io->cb_data = cb_data; err = data->os_hnd->add_fd_to_wait_for(data->os_hnd, fd, io_read_ready, io, NULL, &io->id); if (err) { free(io); return err; } data->os_hnd->set_fd_handlers(data->os_hnd, io->id, io_write_ready, io_except_ready); *rio = io; return 0; } static void ipmi_remove_io_hnd(ipmi_io_t *io) { io->data->os_hnd->remove_fd_to_wait_for(io->data->os_hnd, io->id); } struct ipmi_timer_s { os_hnd_timer_id_t *id; misc_data_t *data; void (*cb)(void *cb_data); void *cb_data; }; static int ipmi_alloc_timer(sys_data_t *sys, void (*cb)(void *cb_data), void *cb_data, ipmi_timer_t **rtimer) { misc_data_t *data = sys->info; ipmi_timer_t *timer; int err; timer = malloc(sizeof(ipmi_timer_t)); if (!timer) return ENOMEM; timer->cb = cb; timer->cb_data = cb_data; timer->data = data; err = data->os_hnd->alloc_timer(data->os_hnd, &timer->id); if (err) { free(timer); return err; } *rtimer = timer; return 0; } static void timer_cb(void *cb_data, os_hnd_timer_id_t *id) { ipmi_timer_t *timer = cb_data; timer->cb(timer->cb_data); } static int ipmi_start_timer(ipmi_timer_t *timer, struct timeval *timeout) { return timer->data->os_hnd->start_timer(timer->data->os_hnd, timer->id, timeout, timer_cb, timer); } static int ipmi_stop_timer(ipmi_timer_t *timer) { return timer->data->os_hnd->stop_timer(timer->data->os_hnd, timer->id); } static void ipmi_free_timer(ipmi_timer_t *timer) { timer->data->os_hnd->free_timer(timer->data->os_hnd, timer->id); } static ipmi_tick_handler_t *tick_handlers; static void is_register_tick_handler(ipmi_tick_handler_t *handler) { handler->next = tick_handlers; tick_handlers = handler; } static void tick(void *cb_data, os_hnd_timer_id_t *id) { misc_data_t *data = cb_data; struct timeval tv; int err; ipmi_tick_handler_t *h; h = tick_handlers; while(h) { h->handler(h->info, 1); h = h->next; } ipmi_emu_tick(data->emu, 1); tv.tv_sec = 1; tv.tv_usec = 0; err = data->os_hnd->start_timer(data->os_hnd, data->timer, &tv, tick, data); if (err) { fprintf(stderr, "Unable to start timer: 0x%x\n", err); exit(1); } } static void * ialloc(channel_t *chan, int size) { return malloc(size); } static void ifree(channel_t *chan, void *data) { return free(data); } static int sigpipeh[2] = {-1, -1}; static void handle_sigchld(int sig) { unsigned char c = 1; (void) write(sigpipeh[1], &c, 1); } static ipmi_child_quit_t *child_quit_handlers; void ipmi_register_child_quit_handler(ipmi_child_quit_t *handler) { handler->next = child_quit_handlers; child_quit_handlers = handler; } static void sigchld_ready(int fd, void *cb_data, os_hnd_fd_id_t *id) { char buf; int rv; int status; ipmi_child_quit_t *h; rv = read(sigpipeh[0], &buf, 1); rv = waitpid(-1, &status, WNOHANG); if (rv == -1) return; h = child_quit_handlers; while (h) { h->handler(h->info, rv); h = h->next; } } static ipmi_shutdown_t *shutdown_handlers; void ipmi_register_shutdown_handler(ipmi_shutdown_t *handler) { handler->next = shutdown_handlers; shutdown_handlers = handler; } static int shutdown_sigs[] = { SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTERM, SIGBUS, 0 }; static void shutdown_handler(int sig) { ipmi_shutdown_t *h = shutdown_handlers; while (h) { h->handler(h->info, sig); h = h->next; } if (sig) raise(sig); } void ipmi_do_start_cmd(startcmd_t *startcmd) { pid_t pid; char *cmd; cmd = malloc(strlen(startcmd->startcmd) + 6); if (!cmd) return; strcpy(cmd, "exec "); strcpy(cmd + 5, startcmd->startcmd); pid = fork(); if (pid == -1) { free(cmd); return; } if (pid == 0) { char *args[4] = { "/bin/sh", "-c", cmd, NULL }; isim_close_fds(); execvp(args[0], args); exit(1); } startcmd->vmpid = pid; free(cmd); } void ipmi_do_kill(startcmd_t *startcmd, int noblock) { if (noblock) kill(startcmd->vmpid, SIGKILL); else kill(startcmd->vmpid, SIGTERM); } static int ipmi_get_monotonic_time(sys_data_t *sys, struct timeval *tv) { misc_data_t *data = sys->info; os_handler_t *os_hnd = data->os_hnd; return os_hnd->get_monotonic_time(os_hnd, tv); } static int ipmi_get_real_time(sys_data_t *sys, struct timeval *tv) { misc_data_t *data = sys->info; os_handler_t *os_hnd = data->os_hnd; return os_hnd->get_real_time(os_hnd, tv); } int main(int argc, const char *argv[]) { sys_data_t sysinfo; misc_data_t data; int err, rv = 1; int i; poptContext poptCtx; struct timeval tv; console_info_t stdio_console; struct sigaction act; os_hnd_fd_id_t *conid; lmc_data_t *mc; int print_version = 0; poptCtx = poptGetContext(argv[0], argc, argv, poptOpts, 0); while ((i = poptGetNextOpt(poptCtx)) >= 0) { switch (i) { case 'd': debug++; break; case 'n': nostdio = 1; break; case 'v': print_version = 1; break; case 'p': persist_enable = 0; break; } } poptFreeContext(poptCtx); printf("IPMI Simulator version %s\n", PVERSION); global_misc_data = &data; data.os_hnd = ipmi_posix_setup_os_handler(); if (!data.os_hnd) { fprintf(stderr, "Unable to allocate OS handler\n"); exit(1); } err = os_handler_alloc_waiter_factory(data.os_hnd, 0, 0, &data.waiter_factory); if (err) { fprintf(stderr, "Unable to allocate waiter factory: 0x%x\n", err); exit(1); } err = data.os_hnd->alloc_timer(data.os_hnd, &data.timer); if (err) { fprintf(stderr, "Unable to allocate timer: 0x%x\n", err); exit(1); } sysinfo_init(&sysinfo); sysinfo.info = &data; sysinfo.alloc = balloc; sysinfo.free = bfree; sysinfo.get_monotonic_time = ipmi_get_monotonic_time; sysinfo.get_real_time = ipmi_get_real_time; sysinfo.alloc_timer = ipmi_alloc_timer; sysinfo.start_timer = ipmi_start_timer; sysinfo.stop_timer = ipmi_stop_timer; sysinfo.free_timer = ipmi_free_timer; sysinfo.add_io_hnd = ipmi_add_io_hnd; sysinfo.io_set_hnds = ipmi_io_set_hnds; sysinfo.io_set_enables = ipmi_io_set_enables; sysinfo.remove_io_hnd = ipmi_remove_io_hnd; sysinfo.gen_rand = sys_gen_rand; sysinfo.debug = debug; sysinfo.log = sim_log; sysinfo.csmi_send = smi_send; sysinfo.clog = sim_chan_log; sysinfo.calloc = ialloc; sysinfo.cfree = ifree; sysinfo.lan_channel_init = lan_channel_init; sysinfo.ser_channel_init = ser_channel_init; sysinfo.ipmb_channel_init = ipmb_channel_init; sysinfo.mc_alloc_unconfigured = is_mc_alloc_unconfigured; sysinfo.resend_atn = is_resend_atn; sysinfo.mc_get_ipmb = is_mc_get_ipmb; sysinfo.mc_get_channelset = is_mc_get_channelset; sysinfo.mc_get_sol = is_mc_get_sol; sysinfo.mc_get_startcmdinfo = is_mc_get_startcmdinfo; sysinfo.mc_get_users = is_mc_get_users; sysinfo.mc_users_changed = is_mc_users_changed; sysinfo.mc_get_pef = is_mc_get_pef; sysinfo.mc_get_next_recv_q = is_mc_get_next_recv_q; sysinfo.sol_read_config = is_sol_read_config; sysinfo.set_chassis_control_prog = is_set_chassis_control_prog; sysinfo.register_tick_handler = is_register_tick_handler; data.sys = &sysinfo; err = pipe(sigpipeh); if (err) { perror("Creating signal handling pipe"); exit(1); } act.sa_handler = handle_sigchld; sigemptyset(&act.sa_mask); act.sa_flags = 0; err = sigaction(SIGCHLD, &act, NULL); if (err) { perror("setting up sigchld sigaction"); exit(1); } err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, sigpipeh[0], sigchld_ready, &data, NULL, &conid); if (err) { fprintf(stderr, "Unable to sigchld pipe wait: 0x%x\n", err); exit(1); } data.emu = ipmi_emu_alloc(&data, sleeper, &sysinfo); /* Set this up for console I/O, even if we don't use it. */ stdio_console.data = &data; stdio_console.outfd = 1; stdio_console.pos = 0; stdio_console.echo = 1; stdio_console.shutdown_on_close = 1; stdio_console.telnet = 0; stdio_console.tn_pos = 0; if (nostdio) { stdio_console.out.eprintf = dummy_printf; stdio_console.out.data = &stdio_console; } else { stdio_console.out.eprintf = emu_printf; stdio_console.out.data = &stdio_console; } stdio_console.next = NULL; stdio_console.prev = NULL; data.consoles = &stdio_console; err = is_mc_alloc_unconfigured(&sysinfo, 0x20, &mc); if (err) { if (err == ENOMEM) fprintf(stderr, "Out of memory allocation BMC MC\n"); exit(1); } sysinfo.mc = mc; sysinfo.chan_set = is_mc_get_channelset(mc); sysinfo.startcmd = is_mc_get_startcmdinfo(mc); sysinfo.cpef = is_mc_get_pef(mc); sysinfo.cusers = is_mc_get_users(mc); sysinfo.sol = is_mc_get_sol(mc); if (read_config(&sysinfo, config_file, print_version)) exit(1); if (print_version) exit(0); if (!sysinfo.name) { fprintf(stderr, "name not set in config file\n"); exit(1); } err = persist_init("ipmi_sim", sysinfo.name, statedir); if (err) { fprintf(stderr, "Unable to initialize persistence: %s\n", strerror(err)); exit(1); } read_persist_users(&sysinfo); err = sol_init(&sysinfo); if (err) { fprintf(stderr, "Unable to initialize SOL: %s\n", strerror(err)); goto out; } err = read_sol_config(&sysinfo); if (err) { fprintf(stderr, "Unable to read SOL configs: %s\n", strerror(err)); goto out; } err = load_dynamic_libs(&sysinfo, 0); if (err) goto out; if (!command_file) { FILE *tf; command_file = malloc(strlen(BASE_CONF_STR) + 6 + strlen(sysinfo.name)); if (!command_file) { fprintf(stderr, "Out of memory\n"); goto out; } strcpy(command_file, BASE_CONF_STR); strcat(command_file, "/"); strcat(command_file, sysinfo.name); strcat(command_file, ".emu"); tf = fopen(command_file, "r"); if (!tf) { free(command_file); command_file = NULL; } else { fclose(tf); } } if (command_file) read_command_file(&stdio_console.out, data.emu, command_file); if (command_string) ipmi_emu_cmd(&stdio_console.out, data.emu, command_string); if (!sysinfo.bmc_ipmb || !sysinfo.ipmb_addrs[sysinfo.bmc_ipmb]) { sysinfo.log(&sysinfo, SETUP_ERROR, NULL, "No bmc_ipmb specified or configured."); goto out; } sysinfo.console_fd = -1; if (sysinfo.console_addr_len) { int nfd; int val; nfd = socket(sysinfo.console_addr.s_ipsock.s_addr0.sa_family, SOCK_STREAM, IPPROTO_TCP); if (nfd == -1) { perror("Console socket open"); goto out; } err = bind(nfd, (struct sockaddr *) &sysinfo.console_addr, sysinfo.console_addr_len); if (err) { perror("bind to console socket"); goto out; } err = listen(nfd, 1); if (err == -1) { perror("listen to console socket"); goto out; } val = 1; err = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); if (err) { perror("console setsockopt reuseaddr"); goto out; } sysinfo.console_fd = nfd; err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, nfd, console_bind_ready, &data, NULL, &conid); if (err) { fprintf(stderr, "Unable to add console wait: 0x%x\n", err); goto out; } else { isim_add_fd(nfd); } } if (!nostdio) { init_term(); err = write(1, "> ", 2); err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, 0, user_data_ready, &stdio_console, NULL, &stdio_console.conid); if (err) { fprintf(stderr, "Unable to add input wait: 0x%x\n", err); goto out; } } post_init_dynamic_libs(&sysinfo); act.sa_handler = shutdown_handler; act.sa_flags = SA_RESETHAND; for (i = 0; shutdown_sigs[i]; i++) { err = sigaction(shutdown_sigs[i], &act, NULL); if (err) { fprintf(stderr, "Unable to register shutdown signal %d: %s\n", shutdown_sigs[i], strerror(errno)); } } tv.tv_sec = 1; tv.tv_usec = 0; err = data.os_hnd->start_timer(data.os_hnd, data.timer, &tv, tick, &data); if (err) { fprintf(stderr, "Unable to start timer: 0x%x\n", err); goto out; } data.os_hnd->operation_loop(data.os_hnd); rv = 0; out: shutdown_handler(0); exit(rv); } OpenIPMI-2.0.33/lanserv/lanserv.c0000664000175000017500000005050114002617260013371 00000000000000/* * lanserv.c * * MontaVista IPMI code for creating a LAN interface to an SMI interface. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2002,2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Option parsing made easy */ #include #include #include #include #if HAVE_SYSLOG #include #endif #include #include #include #include #include #include /* Stolen from ipmi_mc.h can't include that and linux/ipmi.h */ #define IPMI_CHANNEL_MEDIUM_8023_LAN 4 #include static int daemonize = 1; #define MAX_ADDR 4 static void lanserv_log(sys_data_t *sys, int logtype, msg_t *msg, const char *format, ...); typedef struct misc_data { int smi_fd; sys_data_t *sys; os_handler_t *os_hnd; os_handler_waiter_factory_t *waiter_factory; os_hnd_timer_id_t *timer; unsigned char bmc_ipmb; } misc_data_t; static void * balloc(sys_data_t *sys, int size) { return malloc(size); } static void bfree(sys_data_t *sys, void *data) { return free(data); } typedef struct lanserv_addr_s { sockaddr_ip_t addr; socklen_t addr_len; int xmit_fd; } lanserv_addr_t; static void lan_send(lanserv_data_t *lan, struct iovec *data, int vecs, void *addr, int addr_len) { struct msghdr msg; lanserv_addr_t *l = addr; int rv; msg.msg_name = &(l->addr); msg.msg_namelen = l->addr_len; msg.msg_iov = data; msg.msg_iovlen = vecs; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; rv = sendmsg(l->xmit_fd, &msg, 0); if (rv) { /* FIXME - log an error. */ } } static void ipmb_addr_change_dev(channel_t *chan, unsigned char addr) { unsigned int slave_addr = addr; int rv; misc_data_t *info = chan->oem.user_data; info->bmc_ipmb = addr; rv = ioctl(info->smi_fd, IPMICTL_SET_MY_ADDRESS_CMD, &slave_addr); if (rv) { chan->log(chan, OS_ERROR, NULL, "Error setting IPMB address: 0x%x", errno); } } static int smi_send_dev(channel_t *chan, msg_t *msg) { struct ipmi_req req; char addr_data[sizeof(struct ipmi_addr)]; struct ipmi_addr *addr = (struct ipmi_addr *) addr_data; misc_data_t *info = chan->oem.user_data; int rv; if (info->sys->debug & DEBUG_MSG) { info->sys->log(info->sys, DEBUG, msg, "msg: netfn = 0x%2.2x cmd=%2.2x", msg->netfn, msg->cmd); } req.addr = (unsigned char *) addr; if (msg->cmd == IPMI_SEND_MSG_CMD) { struct ipmi_ipmb_addr *ipmb = (void *) addr; int pos; /* Send message has special handling */ if (msg->len < 8) return EMSGSIZE; ipmb->addr_type = IPMI_IPMB_ADDR_TYPE; ipmb->channel = msg->data[0] & 0xf; pos = 1; if (msg->data[pos] == 0) { ipmb->addr_type = IPMI_IPMB_BROADCAST_ADDR_TYPE; pos++; if (msg->len < 9) return EMSGSIZE; } ipmb->slave_addr = msg->data[pos]; ipmb->lun = msg->data[pos+1] & 0x3; req.addr_len = sizeof(*ipmb); req.msg.netfn = msg->data[pos+1] >> 2; req.msg.cmd = msg->data[pos+5]; req.msg.data = msg->data+pos+6; req.msg.data_len = msg->len-(pos + 7); /* Subtract last checksum, too */ } else { /* Normal message to the BMC. */ struct ipmi_system_interface_addr *si = (void *) addr; si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; si->channel = 0xf; si->lun = msg->rs_lun; req.addr_len = sizeof(*si); req.msg.netfn = msg->netfn; req.msg.cmd = msg->cmd; req.msg.data = msg->data; req.msg.data_len = msg->len; } req.msgid = (long) msg; rv = ioctl(info->smi_fd, IPMICTL_SEND_COMMAND, &req); if (rv == -1) { free(msg); return errno; } else return 0; } static int gen_rand(lanserv_data_t *lan, void *data, int len) { return gen_random(data, len); } static void handle_msg_ipmi_dev(int smi_fd, void *cb_data, os_hnd_fd_id_t *id) { misc_data_t *info = cb_data; struct ipmi_recv rsp; char addr_data[sizeof(struct ipmi_addr)]; struct ipmi_addr *addr = (struct ipmi_addr *) addr_data; unsigned char data[IPMI_MAX_MSG_LENGTH+8]; unsigned char rdata[IPMI_MAX_MSG_LENGTH]; int rv; msg_t *msg; rsp.addr = (unsigned char *) addr; rsp.addr_len = sizeof(struct ipmi_addr); rsp.msg.data = rdata; rsp.msg.data_len = sizeof(rdata); rv = ioctl(smi_fd, IPMICTL_RECEIVE_MSG_TRUNC, &rsp); if (rv == -1) { if (errno == EINTR) return; /* Try again later. */ if (errno == EMSGSIZE) { rdata[0] = IPMI_REQUEST_DATA_TRUNCATED_CC; rsp.msg.data_len = sizeof(rdata); } else { lanserv_log(NULL, DEBUG, NULL, "Error receiving message: %s\n", strerror(errno)); return; } } msg = (msg_t *) rsp.msgid; if (rdata[0] == IPMI_TIMEOUT_CC) { /* Ignore timeouts, we let the LAN code do the timeouts. */ free(msg); return; } /* We only handle responses. */ if (rsp.recv_type != IPMI_RESPONSE_RECV_TYPE) { free(msg); return; } if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) { /* Nothing to do. */ } else if (addr->addr_type == IPMI_IPMB_ADDR_TYPE) { struct ipmi_ipmb_addr *ipmb = (void *) addr; data[0] = 0; /* return code. */ data[1] = info->bmc_ipmb; data[2] = (rsp.msg.netfn << 2) | 2; data[3] = -ipmb_checksum(data+1, 2, 0); data[4] = ipmb->slave_addr; data[5] = (msg->data[4] & 0xfc) | ipmb->lun; data[6] = rsp.msg.cmd; memcpy(data+7, rsp.msg.data, rsp.msg.data_len); rsp.msg.data = data; rsp.msg.data_len += 8; data[rsp.msg.data_len-1] = -ipmb_checksum(data+1, rsp.msg.data_len-2, 0); } else { lanserv_log(NULL, DEBUG, NULL, "Error!\n"); return; } ipmi_handle_smi_rsp(info->sys->chan_set[msg->channel], msg, rsp.msg.data, rsp.msg.data_len); } static void lan_data_ready(int lan_fd, void *cb_data, os_hnd_fd_id_t *id) { lanserv_data_t *lan = cb_data; int len; lanserv_addr_t l; unsigned char data[256]; l.addr_len = sizeof(l.addr); len = recvfrom(lan_fd, data, sizeof(data), 0, (struct sockaddr *)&(l.addr), &(l.addr_len)); if (len < 0) { if (errno != EINTR) { perror("Error receiving message"); exit(1); } return; } l.xmit_fd = lan_fd; if (lan->sysinfo->debug & DEBUG_RAW_MSG) { debug_log_raw_msg(lan->sysinfo, (void *) &l.addr, l.addr_len, "Raw LAN receive from:"); debug_log_raw_msg(lan->sysinfo, data, len, " Receive message:"); } if (len < 4) return; if (data[0] != 6) return; /* Invalid version */ /* Check the message class. */ switch (data[3]) { case 6: handle_asf(lan, data, len, &l, sizeof(l)); break; case 7: ipmi_handle_lan_msg(lan, data, len, &l, sizeof(l)); break; } } static int ipmi_open(char *ipmi_dev) { int ipmi_fd; if (ipmi_dev) { ipmi_fd = open(ipmi_dev, O_RDWR); } else { ipmi_fd = open("/dev/ipmidev/0", O_RDWR); if (ipmi_fd == -1) { ipmi_fd = open("/dev/ipmi0", O_RDWR); } } if (ipmi_fd == -1) { perror("Could not open ipmi device /dev/ipmidev/0 or /dev/ipmi0"); } else { /* Set the timing parameters for the connection to no retries and 1 second timeout. The LAN connection will retry, there is no reason for us to. If this fails, oh well, the kernel doesn't support it. It's not the end of the world. */ struct ipmi_timing_parms parms; int rv; parms.retries = 0; parms.retry_time_ms = 1000; rv = ioctl(ipmi_fd, IPMICTL_SET_TIMING_PARMS_CMD, &parms); if (rv == -1) perror("Could not set timing parms"); } return ipmi_fd; } static int open_lan_fd(struct sockaddr *addr, socklen_t addr_len) { int fd; int rv; fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd == -1) { perror("Unable to create socket"); exit(1); } rv = bind(fd, addr, addr_len); if (rv == -1) { fprintf(stderr, "Unable to bind to LAN port: %s\n", strerror(errno)); exit(1); } return fd; } static void ilanserv_log(sys_data_t *sys, int logtype, msg_t *msg, const char *format, va_list ap, int len) { if (msg) { char *str, dummy; int pos; unsigned int i; #define mformat " channel=%d netfn=0x%x cmd=0x%x rs_addr=0x%x rs_lun=0x%x" \ " rq_addr=0x%x\n rq_lun=0x%x rq_seq=0x%x\n" len += snprintf(&dummy, 0, mformat, msg->channel, msg->netfn, msg->cmd, msg->rs_addr, msg->rs_lun, msg->rq_addr, msg->rq_lun, msg->rq_seq); len += 3 * msg->len + 3; str = malloc(len); if (!str) goto print_no_msg; pos = vsprintf(str, format, ap); str[pos++] = '\n'; pos += sprintf(str + pos, mformat, msg->channel, msg->netfn, msg->cmd, msg->rs_addr, msg->rs_lun, msg->rq_addr, msg->rq_lun, msg->rq_seq); #undef mformat for (i = 0; i < msg->len; i++) pos += sprintf(str + pos, " %2.2x", msg->data[i]); if (!daemonize || (logtype == DEBUG)) printf("%s\n", str); #if HAVE_SYSLOG if (logtype != DEBUG) syslog(LOG_NOTICE, "%s", str); #endif free(str); return; } print_no_msg: if (!daemonize || (logtype == DEBUG)) { vprintf(format, ap); printf("\n"); } #if HAVE_SYSLOG if (logtype != DEBUG) vsyslog(LOG_NOTICE, format, ap); #endif } static void lanserv_log(sys_data_t *sys, int logtype, msg_t *msg, const char *format, ...) { va_list ap; char dummy; int len; va_start(ap, format); len = vsnprintf(&dummy, 1, format, ap); va_end(ap); va_start(ap, format); ilanserv_log(sys, logtype, msg, format, ap, len); va_end(ap); } static void lanserv_chan_log(channel_t *sys, int logtype, msg_t *msg, const char *format, ...) { va_list ap; char dummy; int len; va_start(ap, format); len = vsnprintf(&dummy, 1, format, ap); va_end(ap); va_start(ap, format); ilanserv_log(NULL, logtype, msg, format, ap, len); va_end(ap); } static char *config_file = "/etc/ipmi/lan.conf"; static char *ipmi_dev = NULL; static struct poptOption poptOpts[]= { { "config-file", 'c', POPT_ARG_STRING, &config_file, 'c', "configuration file", "" }, { "ipmi-dev", 'i', POPT_ARG_STRING, &ipmi_dev, 'i', "IPMI device", "" }, { "debug", 'd', POPT_ARG_NONE, NULL, 'd', "debug", "" }, { "daemonize", 'n', POPT_ARG_NONE, NULL, 'n', "daemonize", "" }, POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; void init_oem_force(void); static ipmi_tick_handler_t *tick_handlers; static void ls_register_tick_handler(ipmi_tick_handler_t *handler) { handler->next = tick_handlers; tick_handlers = handler; } static void tick(void *cb_data, os_hnd_timer_id_t *id) { misc_data_t *data = cb_data; struct timeval tv; int err; ipmi_tick_handler_t *h; h = tick_handlers; while(h) { h->handler(h->info, 1); h = h->next; } tv.tv_sec = 1; tv.tv_usec = 0; err = data->os_hnd->start_timer(data->os_hnd, data->timer, &tv, tick, data); if (err) { fprintf(stderr, "Unable to start timer: 0x%x\n", err); exit(1); } } static void * ialloc(channel_t *chan, int size) { return malloc(size); } static void ifree(channel_t *chan, void *data) { return free(data); } void sys_start_cmd(sys_data_t *sys) { } static msg_t * ls_mc_get_next_recv_q(channel_t *chan) { return NULL; } static void ls_set_chassis_control_prog(lmc_data_t *mc, const char *prog) { } static int ls_mc_alloc_unconfigured(sys_data_t *sys, unsigned char ipmb, lmc_data_t **rmc) { *rmc = (lmc_data_t *) sys; return 0; } static channel_t ** ls_mc_get_channelset(lmc_data_t *mc) { sys_data_t *sys = (sys_data_t *) mc; return sys->chan_set; } static int ls_sol_read_config(char **tokptr, sys_data_t *sys, const char **err) { *err = "SOL not supported in lanserv"; return -1; } ipmi_sol_t * ls_mc_get_sol(lmc_data_t *mc) { return NULL; } startcmd_t * ls_mc_get_startcmdinfo(lmc_data_t *mc) { return NULL; } static user_t musers[MAX_USERS + 1]; static unsigned char ls_mc_get_ipmb(lmc_data_t *mc) { return 0x20; } int ls_mc_users_changed(lmc_data_t *mc) { return 0; } static user_t * ls_mc_get_users(lmc_data_t *mc) { return musers; } static pef_data_t mpef; static pef_data_t * ls_mc_get_pef(lmc_data_t *mc) { return &mpef; } void ipmi_do_start_cmd(startcmd_t *startcmd) { pid_t pid; char *cmd; cmd = malloc(strlen(startcmd->startcmd) + 6); if (!cmd) return; strcpy(cmd, "exec "); strcpy(cmd + 5, startcmd->startcmd); pid = fork(); if (pid == -1) { free(cmd); return; } if (pid == 0) { char *args[4] = { "/bin/sh", "-c", cmd, NULL }; execvp(args[0], args); exit(1); } startcmd->vmpid = pid; free(cmd); } void ipmi_do_kill(startcmd_t *startcmd, int noblock) { if (noblock) kill(startcmd->vmpid, SIGKILL); else kill(startcmd->vmpid, SIGTERM); } static int ipmi_get_monotonic_time(sys_data_t *sys, struct timeval *tv) { misc_data_t *data = sys->info; os_handler_t *os_hnd = data->os_hnd; return os_hnd->get_monotonic_time(os_hnd, tv); } static int ipmi_get_real_time(sys_data_t *sys, struct timeval *tv) { misc_data_t *data = sys->info; os_handler_t *os_hnd = data->os_hnd; return os_hnd->get_real_time(os_hnd, tv); } int main(int argc, const char *argv[]) { sys_data_t sysinfo; misc_data_t data; int o; unsigned int i; int err; poptContext poptCtx; struct timeval tv; int lan_fd; os_hnd_fd_id_t *fd_id; unsigned int debug = 0; channel_t *channels[16]; #if HAVE_SYSLOG openlog(argv[0], LOG_CONS, LOG_DAEMON); #endif poptCtx = poptGetContext(argv[0], argc, argv, poptOpts, 0); while ((o = poptGetNextOpt(poptCtx)) >= 0) { switch (o) { case 'd': debug++; break; case 'n': daemonize = 0; break; } } poptFreeContext(poptCtx); data.bmc_ipmb = 0x20; data.sys = &sysinfo; data.os_hnd = ipmi_posix_setup_os_handler(); if (!data.os_hnd) { fprintf(stderr, "Unable to allocate OS handler\n"); exit(1); } err = os_handler_alloc_waiter_factory(data.os_hnd, 0, 0, &data.waiter_factory); if (err) { fprintf(stderr, "Unable to allocate waiter factory: 0x%x\n", err); exit(1); } err = data.os_hnd->alloc_timer(data.os_hnd, &data.timer); if (err) { fprintf(stderr, "Unable to allocate timer: 0x%x\n", err); exit(1); } /* Call the OEM init code. */ init_oem_force(); sysinfo_init(&sysinfo); sysinfo.alloc = balloc; sysinfo.free = bfree; sysinfo.log = lanserv_log; sysinfo.debug = debug; sysinfo.get_monotonic_time = ipmi_get_monotonic_time; sysinfo.get_real_time = ipmi_get_real_time; memset(channels, 0, sizeof(channels)); sysinfo.chan_set = channels; sysinfo.mc_alloc_unconfigured = ls_mc_alloc_unconfigured; sysinfo.mc_get_ipmb = ls_mc_get_ipmb; sysinfo.mc_get_channelset = ls_mc_get_channelset; sysinfo.mc_get_sol = ls_mc_get_sol; sysinfo.mc_get_startcmdinfo = ls_mc_get_startcmdinfo; sysinfo.mc_get_users = ls_mc_get_users; sysinfo.mc_users_changed = ls_mc_users_changed; sysinfo.mc_get_pef = ls_mc_get_pef; sysinfo.mc_get_next_recv_q = ls_mc_get_next_recv_q; sysinfo.sol_read_config = ls_sol_read_config; sysinfo.set_chassis_control_prog = ls_set_chassis_control_prog; sysinfo.register_tick_handler = ls_register_tick_handler; if (read_config(&sysinfo, config_file, 0)) exit(1); data.smi_fd = ipmi_open(ipmi_dev); if (data.smi_fd == -1) exit(1); err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, data.smi_fd, handle_msg_ipmi_dev, &data, NULL, &fd_id); if (err) { fprintf(stderr, "Unable to add input wait: 0x%x\n", err); exit(1); } for (i = 0; i < IPMI_MAX_CHANNELS; i++) { channel_t *chan = channels[i]; if (!chan) continue; chan->smi_send = smi_send_dev; chan->oem.user_data = &data; chan->oem.ipmb_addr_change = ipmb_addr_change_dev; chan->alloc = ialloc; chan->free = ifree; chan->log = lanserv_chan_log; if (chan->medium_type == IPMI_CHANNEL_MEDIUM_8023_LAN) { lanserv_data_t *lan = chan->chan_info; lan->user_info = &data; lan->send_out = lan_send; lan->gen_rand = gen_rand; err = ipmi_lan_init(lan); if (err) { fprintf(stderr, "Unable to init lan: 0x%x\n", err); exit(1); } if (!lan->lan_addr_set) { struct sockaddr_in *ipaddr = (void *) &lan->lan_addr.addr; ipaddr->sin_family = AF_INET; ipaddr->sin_port = htons(623); ipaddr->sin_addr.s_addr = INADDR_ANY; lan->lan_addr.addr_len = sizeof(*ipaddr); lan->lan_addr_set = 1; } lan_fd = open_lan_fd(&lan->lan_addr.addr.s_ipsock.s_addr0, lan->lan_addr.addr_len); if (lan_fd == -1) { fprintf(stderr, "Unable to open LAN address %d\n", i+1); exit(1); } err = data.os_hnd->add_fd_to_wait_for(data.os_hnd, lan_fd, lan_data_ready, lan, NULL, &fd_id); if (err) { fprintf(stderr, "Unable to add socket wait: 0x%x\n", err); exit(1); } } else chan_init(chan); } if (daemonize) { int pid; if ((pid = fork()) > 0) { exit(0); } else if (pid < 0) { lanserv_log(NULL, LAN_ERR, NULL, "Error forking first fork"); exit(1); } else { /* setsid() is necessary if we really want to demonize */ setsid(); /* Second fork to really deamonize me. */ if ((pid = fork()) > 0) { exit(0); } else if (pid < 0) { lanserv_log(NULL, LAN_ERR, NULL, "Error forking second fork"); exit(1); } } } lanserv_log(NULL, LAN_ERR, NULL, "%s startup", argv[0]); tv.tv_sec = 1; tv.tv_usec = 0; err = data.os_hnd->start_timer(data.os_hnd, data.timer, &tv, tick, &data); if (err) { fprintf(stderr, "Unable to start timer: 0x%x\n", err); exit(1); } data.os_hnd->operation_loop(data.os_hnd); return 0; } OpenIPMI-2.0.33/lanserv/ipmilan.80000644000175000017500000000440112116456523013300 00000000000000.TH ipmilan 8 06/26/12 OpenIPMI "IPMI LAN to System Interface Converter" .SH NAME ipmilan \- IPMI LAN to System Interface Converter .SH SYNOPSIS .B ipmilan .RB [ \-c .IR configfile ] .RB [ \-i .IR ipmidevice ] .RB [ \-d ] .RB [ \-n ] .SH DESCRIPTION The .B ipmilan daemon allows an IPMI system interface using the OpenIPMI device driver to be accessed using the IPMI 1.5 or 2.0 LAN protocol. .B ipmilan supports the full authentication capabilities of the IPMI LAN protocol. .B ipmilan supports multiple IP addresses for fault-tolerance. Note that messages coming in on an address are always sent back out on the same address they came in. .SH OPTIONS .TP .BI \-c\ config-file Set the configuration file to one other than the default of .I "/etc/ipmi_lan.conf" .TP .B \-n Stops the daemon from forking and detaching from the controlling terminal. This is useful for running from init. .TP .B \-d Turns on debugging to standard output. You generally have to use .B \-n with this. .SH CONFIGURATION Configuration is accomplished through the file .IR /etc/ipmi_lan.conf . A file with another name or path may be specified using the .B \-c option. See the ipmi_lan config file man page for more details. .SH SECURITY .B ipmilan implements normal IPMI security. The default is no access for anyone, so the default is pretty safe, but be careful what you add, because this is access to control your box. \fBstraight\fP and \fBnone\fP authorizations are not recommended, you should probably stick with \fBmd2\fP or \fBmd5\fP. .SH "SIGNALS" .TP 0.5i .B SIGHUP .B ipmilan should handle SIGHUP and reread it's configuration files. However, it doesn't right now. It might in the future, for now you will have to kill it and restart it. Clients should handle reconnecting in this case. If they don't, they are broken. .SH "ERROR OUTPUT" At startup, all error output goes to stderr. After that, all error output goes to syslog. .SH "FILES" /etc/ipmi_lan.conf .SH "SEE ALSO" .BR ipmi_lan (5), ipmi_ui (1), openipmish (1) .SH "KNOWN PROBLEMS" Currently, .B ipmilan does not implement writing the config file. IPMI commands to change configuration options are accepted, but the permanent writing of the changes does not currently work. .SH AUTHOR .PP Corey Minyard OpenIPMI-2.0.33/lanserv/bmc_chassis.c0000664000175000017500000003276113051576452014217 00000000000000/* * bmc_chassis.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 #include static extcmd_map_t boot_map[] = { { 0, "none" }, { 1, "pxe" }, { 2, "default" }, { 5, "cdrom" }, { 6, "bios" }, { 0, NULL } }; /* Matches the CHASSIS_CONTROL defines. */ static extcmd_info_t chassis_prog[] = { { "power", extcmd_int, NULL, 0 }, { "reset", extcmd_int, NULL, 0 }, { "boot", extcmd_uchar, boot_map, 0 }, { "boot", extcmd_uchar, boot_map, 0 }, // dup'd for boot info ack { "shutdown", extcmd_int, NULL, 0 }, { "identify", extcmd_ident, NULL, 0 }, }; static int set_power(lmc_data_t *mc, int pval) { int rv = 0; if (mc->power_timer) { mc->sysinfo->stop_timer(mc->power_timer); mc->sysinfo->free_timer(mc->power_timer); mc->power_timer = NULL; } if (mc->chassis_control_set_func) { unsigned char val = !!pval; rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_POWER, &val, mc->chassis_control_cb_data); } else if (mc->chassis_control_prog) { int val = !!pval; if (extcmd_setvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_POWER], NULL, 1)) rv = EINVAL; } else if (HW_OP_CAN_POWER(mc->channels[15])) { if (pval) mc->channels[15]->hw_op(mc->channels[15], HW_OP_POWERON); else mc->channels[15]->hw_op(mc->channels[15], HW_OP_POWEROFF); } else return ENOTSUP; return rv; } static void power_timeout(void *cb_data) { lmc_data_t *mc = cb_data; if (ipmi_mc_is_power_on(mc)) { struct timeval tv = { 1, 0 }; mc->sysinfo->start_timer(mc->power_timer, &tv); } else { set_power(mc, 1); } } int start_poweron_timer(lmc_data_t *mc) { int rv; struct timeval tv = { 1, 0 }; if (mc->power_timer) return 0; rv = mc->sysinfo->alloc_timer(mc->sysinfo, power_timeout, mc, &mc->power_timer); if (rv) return rv; mc->sysinfo->start_timer(mc->power_timer, &tv); return 0; } static void handle_get_chassis_capabilities(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { rdata[0] = 0; rdata[1] = 0; rdata[2] = mc->sysinfo->bmc_ipmb; rdata[3] = mc->sysinfo->bmc_ipmb; rdata[4] = mc->sysinfo->bmc_ipmb; rdata[5] = mc->sysinfo->bmc_ipmb; } int ipmi_mc_is_power_on(lmc_data_t *mc) { if (mc->chassis_control_get_func) { unsigned char val; int rv; rv = mc->chassis_control_get_func(mc, CHASSIS_CONTROL_POWER, &val, mc->chassis_control_cb_data); if (rv) return -1; return val; } else if (mc->chassis_control_prog) { int val; if (extcmd_getvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_POWER], 1)) return -1; return val; } else if (mc->startcmd.vmpid) { return 1; } else if (HW_OP_CAN_POWER(mc->channels[15])) { int rv = mc->channels[15]->hw_op(mc->channels[15], HW_OP_CHECK_POWER); return rv > 0; } return 0; /* Assume power is off */ } static void handle_get_chassis_status(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int rv; rdata[0] = 0; rv = ipmi_mc_is_power_on(mc); if (rv < 0) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } else { rdata[1] = !!rv; } rdata[2] = 0; rdata[3] = 0; *rdata_len = 4; } static void handle_chassis_control(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int rv; if (msg->len < 1) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } rdata[0] = 0; *rdata_len = 1; switch(msg->data[0] & 0xf) { case 0: /* power down */ rv = set_power(mc, 0); if (rv == ENOTSUP) goto no_support; else if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } break; case 1: /* power up */ rv = set_power(mc, 1); if (rv == ENOTSUP) goto no_support; else if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } break; case 2: /* power cycle */ rv = set_power(mc, 0); if (rv == ENOTSUP) goto no_support; else if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } rv = start_poweron_timer(mc); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } break; case 3: /* hard reset */ if (mc->chassis_control_set_func) { int rv; unsigned char val = 1; rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_RESET, &val, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (mc->chassis_control_prog) { int val = 1; if (extcmd_setvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_RESET], NULL, 1)) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (HW_OP_CAN_RESET(mc->channels[15])) mc->channels[15]->hw_op(mc->channels[15], HW_OP_RESET); else goto no_support; break; case 5: /* initiate soft-shutdown via overtemp */ if (mc->chassis_control_set_func) { int rv; unsigned char val = 1; rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_GRACEFUL_SHUTDOWN, &val, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (mc->chassis_control_prog) { int val = 1; if (extcmd_setvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_GRACEFUL_SHUTDOWN], NULL, 1)) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (HW_OP_CAN_GRACEFUL_SHUTDOWN(mc->channels[15])) mc->channels[15]->hw_op(mc->channels[15], HW_OP_GRACEFUL_SHUTDOWN); else goto no_support; break; case 4: /* pulse diag interrupt */ no_support: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } } static void handle_chassis_identify(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char val[2]; rdata[0] = 0; memset(val, 0, sizeof(val)); if (msg->len == 0) val[0] = 0xf; /* default 15 seconds */ else val[0] = msg->data[0]; /* interval */ if (msg->len > 1) /* force flag is set */ val[1] = msg->data[1] & 0x1; if (mc->chassis_control_set_func) { int rv; rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_IDENTIFY, val, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (mc->chassis_control_prog) { if (extcmd_setvals(mc->sysinfo, val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_IDENTIFY], NULL, 1)) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; } } static void set_system_boot_options(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char val; if (msg->len < 1) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } rdata[0] = 0; *rdata_len = 1; switch (msg->data[0] & 0x3f) { case 1: if (msg->len < 2) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } switch (msg->data[2] & 0x3) { case 0: case 1: /* Just ignore this for now. */ break; default: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; break; } break; case 3: /* BMC boot flag valid bit clearing, just ignore this for now. */ break; case 4: /* Boot Info Ack */ if (msg->len < 3) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (mc->chassis_control_set_func) { int rv; rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_BOOT_INFO_ACK, msg->data + 1, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (mc->chassis_control_prog) { if (extcmd_getvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_BOOT_INFO_ACK], 1)) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; } break; case 5: /* Boot flags */ if (msg->len < 6) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } val = (msg->data[2] >> 2) & 0xf; if (mc->chassis_control_set_func) { int rv; rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_BOOT, &val, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (mc->chassis_control_prog) { if (extcmd_setvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_BOOT], NULL, 1)) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; } break; default: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; break; } } static void get_system_boot_options(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char val; if (msg->len < 3) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = 1; rdata[2] = msg->data[0] & 0x3f; *rdata_len = 3; switch (msg->data[0] & 0x3f) { case 1: /* Dummy this out for now */ rdata[3] = 0; *rdata_len = 4; break; case 4: /* Boot Info Ack */ if (mc->chassis_control_set_func) { int rv; rv = mc->chassis_control_get_func(mc, CHASSIS_CONTROL_BOOT, rdata + 3, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } *rdata_len = 5; } break; case 5: /* Boot flags */ if (mc->chassis_control_set_func) { int rv; rv = mc->chassis_control_get_func(mc, CHASSIS_CONTROL_BOOT, &val, mc->chassis_control_cb_data); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else if (mc->chassis_control_prog) { if (extcmd_getvals(mc->sysinfo, &val, mc->chassis_control_prog, &chassis_prog[CHASSIS_CONTROL_BOOT], 1)) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[3] = 0; rdata[4] = val << 2; rdata[5] = 0; rdata[6] = 0; rdata[7] = 0; *rdata_len = 8; break; default: rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; break; } } cmd_handler_f chassis_netfn_handlers[256] = { [IPMI_GET_CHASSIS_CAPABILITIES_CMD] = handle_get_chassis_capabilities, [IPMI_GET_CHASSIS_STATUS_CMD] = handle_get_chassis_status, [IPMI_CHASSIS_CONTROL_CMD] = handle_chassis_control, [IPMI_SET_SYSTEM_BOOT_OPTIONS_CMD] = set_system_boot_options, [IPMI_GET_SYSTEM_BOOT_OPTIONS_CMD] = get_system_boot_options, [IPMI_CHASSIS_IDENTIFY_CMD] = handle_chassis_identify }; OpenIPMI-2.0.33/lanserv/marvell-bmc/0000775000175000017500000000000014261607642014045 500000000000000OpenIPMI-2.0.33/lanserv/marvell-bmc/TODO0000644000175000017500000000263212100350447014442 00000000000000 * I really need to find a way to set the time and date on the system. Is there some hardware clock on this system? I didn't find one on schematics, but perhaps it is buried in some chip someplace. Otherwise, we need to define a way to get the time from outside the system using NTP. * I need to write documentation for the full system. I have a few more hours left than I thought, so I should be able to do a pretty good job of this. * I need to define the procedures for building the entire system. Include busybox mods for arp to work. * I need to find the memory usage for ipmi_sim. * Automatically clear the IERR and DIMM errors from the board. * Save SOL history data on receiving a shutdown signal. * Power/reset all boards on a chassis operation. Done: * I need to do some more testing on board, fan and power supply removal, to make sure that the sensors all change states properly and the fans behave properly under different circumstances. I've done some testing by dummy-ing things out, but I need to drive over to the lab and test it for real. * Check that board power cannot be enabled if board is not present. * Fix syslog * I need to integrate the Marvell-specific code into a subdirectory of lanserv so it can be built along with the standard OpenIPMI code. * Fan fail LEDS. * This all needs to go up to the public OpenIPMI repository. OpenIPMI-2.0.33/lanserv/marvell-bmc/netsrvc0000755000175000017500000000062112116456523015371 00000000000000#! /bin/sh # Driven from marvell_mod, command to enable or disable network access. # Access with: # ipmitool -I lanplus -U ipmiusr -P test -H 10.70.0.106 raw 0x2e 1 0x0f 0x50 0x00 0 # to disable network services. Change the last value to "1" to enable it. # The last value is passed to this script as is. case $1 in 0) /etc/init.d/S50dropbear stop ;; 1) /etc/init.d/S50dropbear start ;; esac OpenIPMI-2.0.33/lanserv/marvell-bmc/marvell_bmc.config0000644000175000017500000004477112116456523017447 00000000000000# # Automatically generated make config: don't edit # Buildroot 2011.05 Configuration # Thu Feb 21 15:42:35 2013 # BR2_HAVE_DOT_CONFIG=y BR2_arm=y # BR2_armeb is not set # BR2_avr32 is not set # BR2_bfin is not set # BR2_i386 is not set # BR2_mips is not set # BR2_mipsel is not set # BR2_powerpc is not set # BR2_sh is not set # BR2_sh64 is not set # BR2_sparc is not set # BR2_x86_64 is not set # BR2_xtensa is not set # BR2_generic_arm is not set # BR2_arm7tdmi is not set # BR2_arm610 is not set # BR2_arm710 is not set # BR2_arm720t is not set # BR2_arm920t is not set # BR2_arm922t is not set # BR2_arm926t is not set # BR2_arm10t is not set # BR2_arm1136jf_s is not set # BR2_arm1176jz_s is not set # BR2_arm1176jzf_s is not set # # cortex-A8/A9 needs gcc >= 4.4.x # # BR2_cortex_a8 is not set # BR2_cortex_a9 is not set # BR2_sa110 is not set # BR2_sa1100 is not set # BR2_xscale is not set # BR2_iwmmxt is not set # # marvell-fv requires Marvell compiler # BR2_marvell_armv5te=y # BR2_marvell_fv7 is not set BR2_ARM_TYPE="ARM_MARVELLFV5TE" BR2_ARM_EABI=y # BR2_ARM_OABI is not set BR2_ARCH="arm" BR2_ENDIAN="LITTLE" BR2_GCC_TARGET_ARCH="armv5te" BR2_GCC_TARGET_ABI="aapcs-linux" # # Build options # # # Commands # BR2_WGET="wget --passive-ftp -nd -t 3" BR2_SVN="svn" BR2_BZR="bzr" BR2_GIT="git" BR2_ZCAT="gzip -d -c" BR2_BZCAT="bzcat" BR2_XZCAT="xzcat" BR2_TAR_OPTIONS="" BR2_DL_DIR="$(TOPDIR)/dl" BR2_HOST_DIR="$(BASE_DIR)/host" # # Mirrors and Download locations # BR2_PRIMARY_SITE="" BR2_BACKUP_SITE="http://sources.buildroot.net/" BR2_SOURCEFORGE_MIRROR="kent" BR2_KERNEL_MIRROR="http://www.kernel.org/pub/" BR2_GNU_MIRROR="http://ftp.gnu.org/pub/gnu" BR2_DEBIAN_MIRROR="http://ftp.debian.org" BR2_JLEVEL=8 # BR2_CCACHE is not set # BR2_DEPRECATED is not set # BR2_ENABLE_DEBUG is not set BR2_STRIP_strip=y # BR2_STRIP_sstrip is not set # BR2_STRIP_none is not set # BR2_OPTIMIZE_0 is not set # BR2_OPTIMIZE_1 is not set # BR2_OPTIMIZE_2 is not set # BR2_OPTIMIZE_3 is not set BR2_OPTIMIZE_S=y # BR2_PREFER_STATIC_LIB is not set # BR2_HAVE_DOCUMENTATION is not set # BR2_HAVE_DEVFILES is not set # # Toolchain # # BR2_TOOLCHAIN_BUILDROOT is not set BR2_TOOLCHAIN_EXTERNAL=y # BR2_TOOLCHAIN_CTNG is not set BR2_PTHREAD_DEBUG=y # BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_ARM201103 is not set # BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_ARM201009 is not set # BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_ARM2010Q1 is not set # BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_ARM2009Q3 is not set # BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_ARM2009Q1 is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y BR2_TOOLCHAIN_EXTERNAL_PATH="/work64/marvell/armv5-marvell-linux-gnueabi-soft_i686" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="arm-marvell-linux-gnueabi" BR2_TOOLCHAIN_EXTERNAL_PREFIX="arm-marvell-linux-gnueabi" BR2_TOOLCHAIN_EXTERNAL_GLIBC=y # BR2_TOOLCHAIN_EXTERNAL_CUSTOM_UCLIBC is not set BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y BR2_TOOLCHAIN_EXTERNAL_CXX=y # # Gdb Options # BR2_PACKAGE_GDB=y BR2_PACKAGE_GDB_SERVER=y # BR2_GDB_VERSION_6_7_1 is not set # BR2_GDB_VERSION_6_8 is not set # BR2_GDB_VERSION_7_0_1 is not set BR2_GDB_VERSION_7_1=y BR2_GDB_VERSION="7.1" BR2_LARGEFILE=y BR2_INET_IPV6=y BR2_INET_RPC=y BR2_USE_WCHAR=y BR2_ENABLE_LOCALE=y BR2_PROGRAM_INVOCATION=y BR2_INSTALL_LIBSTDCPP=y BR2_TOOLCHAIN_HAS_THREADS=y BR2_ENABLE_LOCALE_PURGE=y BR2_ENABLE_LOCALE_WHITELIST="C en_US" BR2_USE_MMU=y BR2_SOFT_FLOAT=y # BR2_VFP_FLOAT_ARMV5 is not set # BR2_VFP_FLOAT_ARMV7 is not set BR2_TARGET_OPTIMIZATION="-pipe " # # System configuration # BR2_TARGET_GENERIC_HOSTNAME="buildroot" BR2_TARGET_GENERIC_ISSUE="Welcome to Buildroot" BR2_TARGET_GENERIC_STORE_CONFIG=y # BR2_ROOTFS_DEVICE_CREATION_STATIC is not set # BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_DEVTMPFS is not set # BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV is not set BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_UDEV=y BR2_ROOTFS_DEVICE_TABLE="target/generic/device_table.txt target/generic/device_table_dev.txt" BR2_ROOTFS_SKELETON_DEFAULT=y # BR2_ROOTFS_SKELETON_CUSTOM is not set BR2_TARGET_GENERIC_GETTY_PORT="ttyS0" # BR2_TARGET_GENERIC_GETTY_BAUDRATE_KEEP is not set # BR2_TARGET_GENERIC_GETTY_BAUDRATE_9600 is not set # BR2_TARGET_GENERIC_GETTY_BAUDRATE_19200 is not set # BR2_TARGET_GENERIC_GETTY_BAUDRATE_38400 is not set # BR2_TARGET_GENERIC_GETTY_BAUDRATE_57600 is not set BR2_TARGET_GENERIC_GETTY_BAUDRATE_115200=y BR2_TARGET_GENERIC_GETTY_BAUDRATE="115200" BR2_ROOTFS_POST_BUILD_SCRIPT="" # # Package Selection for the target # BR2_PACKAGE_BUSYBOX=y # BR2_BUSYBOX_VERSION_1_16_X is not set # BR2_BUSYBOX_VERSION_1_17_X is not set BR2_BUSYBOX_VERSION_1_18_X=y # BR2_PACKAGE_BUSYBOX_SNAPSHOT is not set BR2_BUSYBOX_VERSION="1.18.4" BR2_PACKAGE_BUSYBOX_CONFIG="busybox-1.18.4.config" BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y BR2_PACKAGE_BUSYBOX_PREFER_OTHERS=y # BR2_PACKAGE_CUSTOMIZE is not set # # Audio and video libraries and applications # # BR2_PACKAGE_ALSA_LIB is not set # BR2_PACKAGE_ALSA_UTILS is not set # BR2_PACKAGE_AUMIX is not set # BR2_PACKAGE_FAAD2 is not set # BR2_PACKAGE_FLAC is not set # BR2_PACKAGE_FFMPEG is not set # BR2_PACKAGE_GSTREAMER is not set # BR2_PACKAGE_LAME is not set # BR2_PACKAGE_LIBAO is not set # BR2_PACKAGE_LIBCDAUDIO is not set # BR2_PACKAGE_LIBCUE is not set # BR2_PACKAGE_LIBCUEFILE is not set # BR2_PACKAGE_LIBDVDREAD is not set # BR2_PACKAGE_LIBDVDNAV is not set # BR2_PACKAGE_LIBID3TAG is not set # BR2_PACKAGE_LIBMAD is not set # BR2_PACKAGE_LIBMMS is not set # BR2_PACKAGE_LIBMPD is not set # BR2_PACKAGE_LIBMPEG2 is not set # BR2_PACKAGE_LIBOGG is not set # BR2_PACKAGE_LIBREPLAYGAIN is not set # BR2_PACKAGE_LIBSAMPLERATE is not set # BR2_PACKAGE_LIBSNDFILE is not set # BR2_PACKAGE_LIBTHEORA is not set # BR2_PACKAGE_LIBVORBIS is not set # BR2_PACKAGE_MADPLAY is not set # BR2_PACKAGE_MPD is not set # BR2_PACKAGE_MPG123 is not set # BR2_PACKAGE_MPLAYER is not set # BR2_PACKAGE_MUSEPACK is not set # BR2_PACKAGE_SPEEX is not set # BR2_PACKAGE_SWFDEC is not set # BR2_PACKAGE_TAGLIB is not set # BR2_PACKAGE_TREMOR is not set # BR2_PACKAGE_VORBIS_TOOLS is not set # BR2_PACKAGE_WAVPACK is not set # # Compressors and decompressors # BR2_PACKAGE_BZIP2=y BR2_PACKAGE_GZIP=y BR2_PACKAGE_LZOP=y BR2_PACKAGE_XZ=y # # Debugging, profiling and benchmark # # BR2_PACKAGE_BONNIE is not set # BR2_PACKAGE_DHRYSTONE is not set # BR2_PACKAGE_DMALLOC is not set # BR2_PACKAGE_DT is not set # BR2_PACKAGE_KEXEC is not set # BR2_PACKAGE_LMBENCH is not set BR2_PACKAGE_LSOF=y # BR2_PACKAGE_LTP_TESTSUITE is not set BR2_PACKAGE_LTRACE=y # BR2_PACKAGE_MEMSTAT is not set BR2_PACKAGE_NETPERF=y BR2_PACKAGE_STRACE=y # BR2_PACKAGE_WHETSTONE is not set # # Development tools # # BR2_PACKAGE_AUTOCONF is not set # BR2_PACKAGE_AUTOMAKE is not set # BR2_PACKAGE_BISON is not set # BR2_PACKAGE_BSDIFF is not set # BR2_PACKAGE_CCACHE is not set BR2_PACKAGE_COREUTILS=y # BR2_PACKAGE_CVS is not set # BR2_PACKAGE_DIFFUTILS is not set # BR2_PACKAGE_DISTCC is not set BR2_PACKAGE_FINDUTILS=y # BR2_PACKAGE_FLEX is not set BR2_PACKAGE_GAWK=y # BR2_PACKAGE_GMP is not set # BR2_PACKAGE_GPERF is not set BR2_PACKAGE_GREP=y # BR2_PACKAGE_MAKE is not set # BR2_PACKAGE_MPC is not set # BR2_PACKAGE_MPFR is not set # BR2_PACKAGE_LIBTOOL is not set # BR2_PACKAGE_M4 is not set # BR2_PACKAGE_PATCH is not set # BR2_PACKAGE_PKG_CONFIG is not set BR2_PACKAGE_SED=y # BR2_PACKAGE_SSTRIP is not set BR2_PACKAGE_TAR=y # # Games # # BR2_PACKAGE_GNUCHESS is not set # BR2_PACKAGE_PRBOOM is not set # # Graphic libraries and applications (graphic/text) # # # Graphic applications # # BR2_PACKAGE_RRDTOOL is not set # # graphic libraries # # BR2_PACKAGE_DIRECTFB is not set # BR2_PACKAGE_FBDUMP is not set # BR2_PACKAGE_FBGRAB is not set # BR2_PACKAGE_FBSET is not set # BR2_PACKAGE_FBV is not set # BR2_PACKAGE_IMAGEMAGICK is not set # BR2_PACKAGE_SDL is not set # # other GUIs # # BR2_PACKAGE_QT is not set # BR2_PACKAGE_XORG7 is not set # # X libraries and helper libraries # # BR2_PACKAGE_LIBERATION is not set # # X Window managers # # # X applications # # BR2_PACKAGE_GOB2 is not set # # midori requires C++, WCHAR in toolchain and libgtk2 # # # Hardware handling # # BR2_PACKAGE_CDRKIT is not set # BR2_PACKAGE_CRAMFS is not set # # dbus not available (need expat or libxml2) # # BR2_PACKAGE_DMRAID is not set BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_MKDOSFS=y BR2_PACKAGE_DOSFSTOOLS_DOSFSCK=y # BR2_PACKAGE_DOSFSTOOLS_DOSFSLABEL is not set BR2_PACKAGE_E2FSPROGS=y # BR2_PACKAGE_E2FSPROGS_UTILS is not set # # e2fsprogs libraries # BR2_PACKAGE_E2FSPROGS_LIBUUID=y # BR2_PACKAGE_E2FSPROGS_LIBBLKID is not set # BR2_PACKAGE_EEPROG is not set # BR2_PACKAGE_FCONFIG is not set # BR2_PACKAGE_FIS is not set # BR2_PACKAGE_GADGETFS_TEST is not set # BR2_PACKAGE_GDISK is not set # BR2_PACKAGE_GENEXT2FS is not set # BR2_PACKAGE_GENROMFS is not set # BR2_PACKAGE_GPSD is not set # BR2_PACKAGE_GVFS is not set # BR2_PACKAGE_HAL is not set # BR2_PACKAGE_HDPARM is not set # BR2_PACKAGE_HWDATA is not set # BR2_PACKAGE_I2C_TOOLS is not set # BR2_PACKAGE_INPUT_EVENT_DAEMON is not set # BR2_PACKAGE_INPUT_TOOLS is not set BR2_PACKAGE_IOSTAT=y # BR2_PACKAGE_IRDA_UTILS is not set # BR2_PACKAGE_KBD is not set # BR2_PACKAGE_LIBV4L is not set # BR2_PACKAGE_LM_SENSORS is not set # BR2_PACKAGE_LSUIO is not set # BR2_PACKAGE_LVM2 is not set BR2_PACKAGE_MAKEDEVS=y # BR2_PACKAGE_MDADM is not set # BR2_PACKAGE_MEMTESTER is not set BR2_PACKAGE_MTD=y # # MTD tools selection # # BR2_PACKAGE_MTD_DOCFDISK is not set # BR2_PACKAGE_MTD_DOC_LOADBIOS is not set BR2_PACKAGE_MTD_FLASHCP=y BR2_PACKAGE_MTD_FLASH_ERASE=y BR2_PACKAGE_MTD_FLASH_ERASEALL=y BR2_PACKAGE_MTD_FLASH_INFO=y BR2_PACKAGE_MTD_FLASH_LOCK=y # BR2_PACKAGE_MTD_FLASH_OTP_DUMP is not set # BR2_PACKAGE_MTD_FLASH_OTP_INFO is not set BR2_PACKAGE_MTD_FLASH_UNLOCK=y # BR2_PACKAGE_MTD_FTL_CHECK is not set # BR2_PACKAGE_MTD_FTL_FORMAT is not set # BR2_PACKAGE_MTD_JFFS2DUMP is not set BR2_PACKAGE_MTD_MKFSJFFS2=y BR2_PACKAGE_MTD_MTD_DEBUG=y BR2_PACKAGE_MTD_NANDDUMP=y BR2_PACKAGE_MTD_NANDTEST=y BR2_PACKAGE_MTD_NANDWRITE=y # BR2_PACKAGE_MTD_NFTLDUMP is not set # BR2_PACKAGE_MTD_NFTL_FORMAT is not set # BR2_PACKAGE_MTD_RECV_IMAGE is not set # BR2_PACKAGE_MTD_RFDDUMP is not set # BR2_PACKAGE_MTD_RFDFORMAT is not set # BR2_PACKAGE_MTD_SERVE_IMAGE is not set # BR2_PACKAGE_MTD_SUMTOOL is not set BR2_PACKAGE_MTD_MTDINFO=y BR2_PACKAGE_MTD_UBIATTACH=y BR2_PACKAGE_MTD_UBICRC32=y BR2_PACKAGE_MTD_UBIDETACH=y BR2_PACKAGE_MTD_UBIFORMAT=y BR2_PACKAGE_MTD_UBIMKVOL=y BR2_PACKAGE_MTD_UBINFO=y BR2_PACKAGE_MTD_UBINIZE=y BR2_PACKAGE_MTD_UBIRENAME=y BR2_PACKAGE_MTD_UBIRMVOL=y BR2_PACKAGE_MTD_UBIRSVOL=y BR2_PACKAGE_MTD_UBIUPDATEVOL=y # BR2_PACKAGE_NTFS_3G is not set # BR2_PACKAGE_NTFSPROGS is not set # BR2_PACKAGE_PCIUTILS is not set # BR2_PACKAGE_RNG_TOOLS is not set # BR2_PACKAGE_SDPARM is not set # BR2_PACKAGE_SETSERIAL is not set # BR2_PACKAGE_SMARTMONTOOLS is not set # BR2_PACKAGE_SQUASHFS is not set # BR2_PACKAGE_SSHFS is not set BR2_PACKAGE_SYSSTAT=y BR2_PACKAGE_UDEV=y BR2_PACKAGE_UDEV_UTILS=y # # Extra udev tools # # BR2_PACKAGE_UDEV_VOLUME_ID is not set # BR2_PACKAGE_USB_MODESWITCH is not set # BR2_PACKAGE_USBMOUNT is not set # BR2_PACKAGE_USBUTILS is not set # BR2_PACKAGE_WIPE is not set # BR2_PACKAGE_XFSPROGS is not set # # Interpreter languages and scripting # # BR2_PACKAGE_HASERL is not set # BR2_PACKAGE_LUA is not set # BR2_PACKAGE_MICROPERL is not set # BR2_PACKAGE_PHP is not set # BR2_PACKAGE_PYTHON is not set # BR2_PACKAGE_RUBY is not set # BR2_PACKAGE_TCL is not set # # Libraries # # # Compression and decompression # # BR2_PACKAGE_LIBARCHIVE is not set BR2_PACKAGE_LZO=y BR2_PACKAGE_ZLIB=y # # Crypto # # BR2_PACKAGE_BEECRYPT is not set # BR2_PACKAGE_LIBGCRYPT is not set # BR2_PACKAGE_LIBGPG_ERROR is not set BR2_PACKAGE_OPENSSL=y # BR2_PACKAGE_OPENSSL_BIN is not set BR2_PACKAGE_OPENSSL_ENGINES=y # BR2_PACKAGE_OPENSSL_OCF is not set # # Database # # BR2_PACKAGE_BERKELEYDB is not set # BR2_PACKAGE_MYSQL_CLIENT is not set # BR2_PACKAGE_SQLITE is not set # # Filesystem # # BR2_PACKAGE_GAMIN is not set # BR2_PACKAGE_LIBCONFIG is not set # BR2_PACKAGE_LIBCONFUSE is not set # BR2_PACKAGE_LIBFUSE is not set # BR2_PACKAGE_LIBLOCKFILE is not set # BR2_PACKAGE_LIBSYSFS is not set # # Graphics # # BR2_PACKAGE_ATK is not set # BR2_PACKAGE_CAIRO is not set # BR2_PACKAGE_FONTCONFIG is not set # BR2_PACKAGE_FREETYPE is not set # BR2_PACKAGE_JPEG is not set # BR2_PACKAGE_LIBART is not set # BR2_PACKAGE_LIBEXIF is not set # BR2_PACKAGE_GDK_PIXBUF is not set # BR2_PACKAGE_LIBPNG is not set # BR2_PACKAGE_LIBRAW is not set # BR2_PACKAGE_LIBSVGTINY is not set # BR2_PACKAGE_LIBUNGIF is not set # BR2_PACKAGE_PANGO is not set # BR2_PACKAGE_PIXMAN is not set # BR2_PACKAGE_TIFF is not set # # webkit requires C++, WCHAR in toolchain and libgtk2 # # # Hardware handling # # BR2_PACKAGE_LIBAIO is not set # BR2_PACKAGE_LIBRAW1394 is not set # BR2_PACKAGE_TSLIB is not set # BR2_PACKAGE_LIBHID is not set # BR2_PACKAGE_LIBUSB is not set # # Networking # # BR2_PACKAGE_LIBCGI is not set # BR2_PACKAGE_LIBCGICC is not set # BR2_PACKAGE_LIBCURL is not set # BR2_PACKAGE_LIBDNET is not set # BR2_PACKAGE_LIBEXOSIP2 is not set # BR2_PACKAGE_LIBIDN is not set # BR2_PACKAGE_LIBMICROHTTPD is not set # BR2_PACKAGE_NEON is not set BR2_PACKAGE_LIBNL=y BR2_PACKAGE_LIBPCAP=y # BR2_PACKAGE_LIBOSIP2 is not set # BR2_PACKAGE_LIBRSYNC is not set # BR2_PACKAGE_LIBSOUP is not set # BR2_PACKAGE_LIBUPNP is not set # # Other # # BR2_PACKAGE_ARGP_STANDALONE is not set # BR2_PACKAGE_LIBATOMIC_OPS is not set # BR2_PACKAGE_LIBCAP is not set # BR2_PACKAGE_LIBDAEMON is not set BR2_PACKAGE_LIBELF=y # BR2_PACKAGE_LIBEVENT is not set # BR2_PACKAGE_LIBFFI is not set # BR2_PACKAGE_LIBGLIB2 is not set # BR2_PACKAGE_LIBOIL is not set # BR2_PACKAGE_LIBSIGC is not set # # Text and terminal handling # # BR2_PACKAGE_ENCHANT is not set # BR2_PACKAGE_ICU is not set BR2_PACKAGE_NCURSES=y # BR2_PACKAGE_NCURSES_TARGET_PANEL is not set # BR2_PACKAGE_NCURSES_TARGET_FORM is not set # BR2_PACKAGE_NCURSES_TARGET_MENU is not set # BR2_PACKAGE_NEWT is not set # BR2_PACKAGE_PCRE is not set BR2_PACKAGE_POPT=y # BR2_PACKAGE_READLINE is not set # BR2_PACKAGE_SLANG is not set # # XML # # BR2_PACKAGE_EXPAT is not set # BR2_PACKAGE_EZXML is not set # BR2_PACKAGE_LIBXML2 is not set # BR2_PACKAGE_LIBXSLT is not set # BR2_PACKAGE_XERCES is not set # # Miscellaneous # # BR2_PACKAGE_SHARED_MIME_INFO is not set # # Networking applications # # BR2_PACKAGE_ARGUS is not set # BR2_PACKAGE_AVAHI is not set # BR2_PACKAGE_AXEL is not set # BR2_PACKAGE_BOA is not set # BR2_PACKAGE_BIND is not set # BR2_PACKAGE_BMON is not set # BR2_PACKAGE_BRIDGE is not set # BR2_PACKAGE_BWM_NG is not set # BR2_PACKAGE_CAN_UTILS is not set # BR2_PACKAGE_CTORRENT is not set # BR2_PACKAGE_CUPS is not set # BR2_PACKAGE_DHCP is not set # BR2_PACKAGE_DHCPDUMP is not set # BR2_PACKAGE_DNSMASQ is not set BR2_PACKAGE_DROPBEAR=y # BR2_PACKAGE_DROPBEAR_DISABLE_REVERSEDNS is not set BR2_PACKAGE_DROPBEAR_SMALL=y BR2_PACKAGE_ETHTOOL=y # BR2_PACKAGE_HOSTAPD is not set # BR2_PACKAGE_IFPLUGD is not set # BR2_PACKAGE_IPERF is not set # BR2_PACKAGE_IPROUTE2 is not set # BR2_PACKAGE_IPSEC_TOOLS is not set BR2_PACKAGE_IPTABLES=y # BR2_PACKAGE_IW is not set # BR2_PACKAGE_KISMET is not set # BR2_PACKAGE_XL2TP is not set # BR2_PACKAGE_LIGHTTPD is not set # BR2_PACKAGE_LINKS is not set # BR2_PACKAGE_LRZSZ is not set # BR2_PACKAGE_MII_DIAG is not set # BR2_PACKAGE_MROUTED is not set # BR2_PACKAGE_MUTT is not set # BR2_PACKAGE_NBD is not set # BR2_PACKAGE_NCFTP is not set # BR2_PACKAGE_NETCAT is not set # BR2_PACKAGE_NETKITBASE is not set # BR2_PACKAGE_NETKITTELNET is not set # BR2_PACKAGE_NETPLUG is not set # BR2_PACKAGE_NETSNMP is not set # BR2_PACKAGE_NETSTAT_NAT is not set BR2_PACKAGE_NFS_UTILS=y # # NFS utilities selection # # BR2_PACKAGE_NFS_UTILS_RPCDEBUG is not set # BR2_PACKAGE_NFS_UTILS_RPC_LOCKD is not set # BR2_PACKAGE_NFS_UTILS_RPC_RQUOTAD is not set # BR2_PACKAGE_NGIRCD is not set BR2_PACKAGE_NTP=y # BR2_PACKAGE_NTP_SNTP is not set BR2_PACKAGE_NTP_NTP_KEYGEN=y BR2_PACKAGE_NTP_NTPD=y BR2_PACKAGE_NTP_NTPDATE=y BR2_PACKAGE_NTP_NTPDC=y BR2_PACKAGE_NTP_NTPQ=y # BR2_PACKAGE_NTP_TICKADJ is not set # BR2_PACKAGE_NUTTCP is not set # BR2_PACKAGE_OLSR is not set # BR2_PACKAGE_OPENNTPD is not set # BR2_PACKAGE_OPENSSH is not set # BR2_PACKAGE_OPENVPN is not set # BR2_PACKAGE_OPENSWAN is not set # BR2_PACKAGE_PORTMAP is not set # BR2_PACKAGE_PPPD is not set # BR2_PACKAGE_RADVD is not set # BR2_PACKAGE_PPTP_LINUX is not set # BR2_PACKAGE_PROFTPD is not set # BR2_PACKAGE_QUAGGA is not set # BR2_PACKAGE_RSH_REDONE is not set # BR2_PACKAGE_RSYNC is not set # BR2_PACKAGE_SAMBA is not set # BR2_PACKAGE_SER2NET is not set # BR2_PACKAGE_SOCAT is not set # BR2_PACKAGE_SPAWN_FCGI is not set # BR2_PACKAGE_SQUID is not set BR2_PACKAGE_TCPDUMP=y BR2_PACKAGE_TCPDUMP_SMB=y # BR2_PACKAGE_TCPREPLAY is not set # BR2_PACKAGE_TFTPD is not set # BR2_PACKAGE_THTTPD is not set # BR2_PACKAGE_TINYHTTPD is not set # BR2_PACKAGE_TN5250 is not set # BR2_PACKAGE_TTCP is not set # BR2_PACKAGE_UDPCAST is not set # BR2_PACKAGE_VPNC is not set # BR2_PACKAGE_VSFTPD is not set # BR2_PACKAGE_VTUN is not set # BR2_PACKAGE_WGET is not set # BR2_PACKAGE_WIRELESS_TOOLS is not set # BR2_PACKAGE_WPA_SUPPLICANT is not set # # Package managers # # BR2_PACKAGE_IPKG is not set # # rpm requires libneon with SSL, XML and ZLIB support # # # Shell and utilities # # BR2_PACKAGE_AT is not set BR2_PACKAGE_BASH=y # BR2_PACKAGE_DASH is not set # BR2_PACKAGE_DIALOG is not set BR2_PACKAGE_FILE=y # BR2_PACKAGE_LOCKFILE_PROGS is not set # BR2_PACKAGE_LOGROTATE is not set # BR2_PACKAGE_SCREEN is not set # BR2_PACKAGE_SUDO is not set BR2_PACKAGE_WHICH=y # BR2_PACKAGE_XMLSTARLET is not set # # System tools # # BR2_PACKAGE_BOOTUTILS is not set BR2_PACKAGE_HTOP=y BR2_PACKAGE_MODULE_INIT_TOOLS=y BR2_PACKAGE_PROCPS=y BR2_PACKAGE_PSMISC=y # BR2_PACKAGE_SYSKLOGD is not set # BR2_PACKAGE_SYSVINIT is not set BR2_PACKAGE_UTIL-LINUX=y # # Text editors and viewers # # BR2_PACKAGE_ED is not set # BR2_PACKAGE_LESS is not set BR2_PACKAGE_NANO=y # BR2_PACKAGE_UEMACS is not set # BR2_PACKAGE_VIM is not set # # Filesystem images # # BR2_TARGET_ROOTFS_CRAMFS is not set # BR2_TARGET_ROOTFS_CLOOP is not set # BR2_TARGET_ROOTFS_EXT2 is not set # BR2_TARGET_ROOTFS_JFFS2 is not set # BR2_TARGET_ROOTFS_UBIFS is not set # BR2_TARGET_ROOTFS_SQUASHFS is not set BR2_TARGET_ROOTFS_TAR=y BR2_TARGET_ROOTFS_TAR_NONE=y # BR2_TARGET_ROOTFS_TAR_GZIP is not set # BR2_TARGET_ROOTFS_TAR_BZIP2 is not set # BR2_TARGET_ROOTFS_TAR_LZMA is not set BR2_TARGET_ROOTFS_TAR_OPTIONS="" # BR2_TARGET_ROOTFS_CPIO is not set # # initramfs requires a Linux kernel to be built # # BR2_TARGET_ROOTFS_ROMFS is not set # # Bootloaders # # BR2_TARGET_BAREBOX is not set # BR2_TARGET_UBOOT is not set # BR2_TARGET_AT91BOOTSTRAP is not set # BR2_TARGET_DATAFLASHBOOT is not set # # Kernel # # BR2_LINUX_KERNEL is not set OpenIPMI-2.0.33/lanserv/marvell-bmc/S90ast13000000755000175000017500000000010112116456523015265 00000000000000#!/bin/sh echo "Insert ast1300 module" insmod /root/ast1300.ko OpenIPMI-2.0.33/lanserv/marvell-bmc/marvell_mod.c0000664000175000017500000024471314002617260016433 00000000000000/* * marvel_mod.c * * Marvell specific modules for handling BMC and MC functions. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2012,2013 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "wiw.h" #define PVERSION "2.0.12" #define NUM_BOARDS 6 #define CHASSIS_FRU_SIZE 1024 #define BOARD_FRU_SIZE 2048 #define BOARD_TEMP_SHUTDOWN 105 #define SWITCH_TEMP_SHUTDOWN 115 #define FRONT_TEMP_SHUTDOWN 50 #define MARVELL_SEMI_ISREAL_IANA 20495 #define DISABLE_NETWORK_SRVC_CMD 1 #define RELOAD_BOARD_FRU_CMD 2 #define SET_ALL_FANS_DUTY_CMD 3 #define GET_ALL_FANS_DUTY_CMD 4 #define BOARD_FRU_FILE "/etc/ipmi/axp_board_fru" #define COLD_POWER_FILE "/var/lib/ipmi_sim_coldpower" #define RESET_REASON_FILE "/var/lib/reset_reason" #define RESET_REASON_UNKNOWN 0 #define RESET_REASON_COLD_BOOT 1 #define RESET_REASON_WARM_BOOT 2 static int init_complete; #define GPIODIR "/sys/class/astgpio/GPIO" #define COLD_POWER_UP_IO "/sys/class/astgpio/ColdBoot" static unsigned int cold_power_up = 1; /* * Set debugging with bits: * bit 0 - power * bit 1 - sensor reading * bit 2 - sensor writing * bit 3 - fan */ static unsigned int debug; /* 1 second poll time */ static unsigned int poll_time = 2000000; static lmc_data_t *bmc_mc; /* Set the file to "0" to enable reset */ #define BOARD_RESET_ON 0 #define BOARD_RESET_OFF 1 static const char *trg_reset[NUM_BOARDS] = { GPIODIR "H0", GPIODIR "H1", GPIODIR "H2", GPIODIR "H3", GPIODIR "H4", GPIODIR "H5" }; /* Set the file to "1" to power on, "0" to power off. */ #define BOARD_POWER_ON 1 #define BOARD_POWER_OFF 0 static const char *trg_power[NUM_BOARDS] = { GPIODIR "D6", GPIODIR "D7", GPIODIR "B0", GPIODIR "B1", GPIODIR "B2", GPIODIR "B3" }; /* Will contain "0" if present, "1" if not present. */ #define BOARD_PRESENT 0 #define BOARD_ABSENT 1 static const char *trg_present[NUM_BOARDS] = { GPIODIR "C0", GPIODIR "C1", GPIODIR "C2", GPIODIR "C3", GPIODIR "C4", GPIODIR "C5", }; static int simulate_board_absent[NUM_BOARDS]; /* Set this to zero to request that the board power off. */ #define BOARD_OFF_REQUEST_ON 0 #define BOARD_OFF_REQUEST_OFF 1 static const char *pow_off_request[NUM_BOARDS] = { GPIODIR "A6", GPIODIR "A7", GPIODIR "I4", GPIODIR "I5", GPIODIR "I6", GPIODIR "I7" }; /* The board will set the value to 0 when it is ready to power off. */ #define BOARD_OFF_READY 0 #define BOARD_OFF_NOT_READY 1 static const char *pow_off_ready[NUM_BOARDS] = { GPIODIR "A0", GPIODIR "A1", GPIODIR "A2", GPIODIR "A3", GPIODIR "G4", GPIODIR "G5" }; #define I2CDIR "/sys/class/i2c-adapter/i2c-" struct eeprom { unsigned char addr; const char *part; const char *dev; unsigned int size; }; static struct board_i2c_info { const char *add_dev; struct eeprom fru; } const board_i2c[NUM_BOARDS] = { { .add_dev = I2CDIR "1/new_device", .fru = { .addr = 0x50, .part = "24c64", .dev = I2CDIR "1/1-0050/at24c64", .size = BOARD_FRU_SIZE }, }, { .add_dev = I2CDIR "2/new_device", .fru = { .addr = 0x50, .part = "24c64", .dev = I2CDIR "2/2-0050/at24c64", .size = BOARD_FRU_SIZE }, }, { .add_dev = I2CDIR "3/new_device", .fru = { .addr = 0x50, .part = "24c64", .dev = I2CDIR "3/3-0050/at24c64", .size = BOARD_FRU_SIZE }, }, { .add_dev = I2CDIR "4/new_device", .fru = { .addr = 0x50, .part = "24c64", .dev = I2CDIR "4/4-0050/at24c64", .size = BOARD_FRU_SIZE }, }, { .add_dev = I2CDIR "5/new_device", .fru = { .addr = 0x50, .part = "24c64", .dev = I2CDIR "5/5-0050/at24c64", .size = BOARD_FRU_SIZE }, }, { .add_dev = I2CDIR "6/new_device", .fru = { .addr = 0x50, .part = "24c64", .dev = I2CDIR "6/6-0050/at24c64", .size = BOARD_FRU_SIZE }, }, }; static struct board_i2c_info *chassis_i2c; /* For older systems (before DVT2) */ static struct board_i2c_info chassis_i2c_old = { .add_dev = I2CDIR "7/new_device", .fru = { .addr = 0x54, .part = "24c128", .dev = I2CDIR "7/7-0054/at24c128", .size = CHASSIS_FRU_SIZE } }; /* For newer systems (DVT2 and later) */ static struct board_i2c_info chassis_i2c_new = { .add_dev = I2CDIR "0/new_device", .fru = { .addr = 0x54, .part = "24c128", .dev = I2CDIR "0/0-0051/at24c128", .size = CHASSIS_FRU_SIZE } }; static struct board_info { sys_data_t *sys; lmc_data_t *mc; unsigned char num; char present; char fru_good; unsigned char fru[BOARD_FRU_SIZE]; struct timeval button_press_time; unsigned int power_off_countdown; char button_pressed; char waiting_power_off; volatile char fru_data_ready_for_handling; /* * Tracks the state of the power request line, request happens * on a 1->0 transition. */ char last_power_request; } boards[NUM_BOARDS]; struct timeval last_board_power_on; static unsigned char chassis_fru[CHASSIS_FRU_SIZE]; static unsigned int chassis_iuse; static unsigned int chassis_iuse_len; static unsigned int chassis_chinfo; static unsigned int chassis_chinfo_len; static unsigned int chassis_brdinfo; static unsigned int chassis_brdinfo_len; /* Offset from beginning of chassis info area */ static unsigned int sernum_offset; static unsigned int sernum_offset2; static unsigned int sernum_len; static unsigned int sysmac_offset; /* Pieces of the serial number and MAC we need for generating board info */ static unsigned char sernum[10]; static unsigned char sysmac[17]; static const unsigned char board_ipmb[NUM_BOARDS] = { 1, 2, 3, 4, 5, 6 }; static int disable_wdt; static int wdt_fd; static ipmi_timer_t *wdt_test_timer; static volatile int wdt_test_timer_ran; static void add_to_timeval(struct timeval *tv, unsigned int usecs) { while (usecs >= 1000000) { tv->tv_sec += 1; usecs -= 1000000; } tv->tv_usec += usecs; while (tv->tv_usec >= 1000000) { tv->tv_sec += 1; tv->tv_usec -= 1000000; } } static void diff_timeval(struct timeval *result, struct timeval *tv1, struct timeval *tv2) { result->tv_sec = tv1->tv_sec - tv2->tv_sec; result->tv_usec = tv1->tv_usec - tv2->tv_usec; while (result->tv_usec < 0) { result->tv_usec += 1000000; result->tv_sec -= 1; } } static long diff_timeval_ms(struct timeval *tv1, struct timeval *tv2) { struct timeval tv; diff_timeval(&tv, tv1, tv2); if (tv.tv_sec > 1000) return 1000000; if (tv.tv_sec < -1000) return -1000000; return (tv.tv_sec * 1000) + ((tv.tv_usec + 500) / 1000); } /************************************************************************** * EEPROM handling *************************************************************************/ static unsigned char checksum(unsigned char *data, int size) { unsigned char csum = 0; for (; size > 0; size--, data++) csum += *data; return csum; } /* * Validate that the eeprom device exists and can be opened. */ static int check_eeprom(sys_data_t *sys, const struct eeprom *e) { int fd; fd = open(e->dev, O_RDONLY); if (fd == -1) return errno; close(fd); return 0; } /* * Write to the sysfs file to create the eeprom device. Sometimes it * doesn't get automatically created, so create it here. */ static int create_eeprom(sys_data_t *sys, const char *add_dev, const struct eeprom *e) { int fd; fd = open(e->dev, O_RDONLY); if (fd == -1) { FILE *f; f = fopen(add_dev, "w"); if (!f) return errno; fprintf(f, "%s %d\n", e->part, e->addr); fclose(f); fd = open(e->dev, O_RDONLY); if (fd == -1) return errno; } close(fd); return 0; } /* Note: Data must be at least e->size */ static int read_eeprom(const struct eeprom *e, unsigned char *data, unsigned int offset, int size) { int rv; int err = 0; int fd; if (offset + size > e->size) return EINVAL; fd = open(e->dev, O_RDONLY); if (fd == -1) return errno; if (lseek(fd, offset, SEEK_SET) == -1) { err = errno; close(fd); return err; } rv = read(fd, data, size); if (rv == -1) err = errno; else if (rv < size) err = EIO; close(fd); return err; } /* Note: Data must be at least e->size */ static int write_eeprom(const struct eeprom *e, unsigned char *data, unsigned int offset, unsigned int size) { int rv; int err = 0; int fd; if (size + offset > e->size) return EINVAL; fd = open(e->dev, O_WRONLY); if (fd == -1) return errno; if (lseek(fd, offset, SEEK_SET) == -1) { close(fd); return errno; } rv = write(fd, data, size); if (rv == -1) err = errno; else if (rv < size) err = EIO; close(fd); return err; } /************************************************************************** * General file handling. These are functions that read and write * sysfs files, generally. *************************************************************************/ /* * Convert an integer value to a string and write it to the device. */ static int set_intval(const char *fname, unsigned int val) { FILE *f; f = fopen(fname, "w"); if (!f) return errno; fprintf(f, "%u\n", val); fclose(f); return 0; } /* * Fetch an unsigned integer ASCII value from a file an convert it. */ static int get_uintval(const char *fname, unsigned int *val) { FILE *f; char line[80]; size_t rv; f = fopen(fname, "r"); if (!f) return errno; rv = fread(line, 1, sizeof(line), f); if (rv == 0) { int retval = 0; if (ferror(f)) { retval = errno; } fclose(f); return retval; } fclose(f); *val = strtoul(line, NULL, 0); return 0; } /* * Fetch a signed integer ASCII value from a file an convert it. */ static int get_intval(const char *fname, int *val) { FILE *f; char line[80]; size_t rv; f = fopen(fname, "r"); if (!f) return errno; rv = fread(line, 1, sizeof(line), f); if (rv == 0) { int retval = 0; if (ferror(f)) { retval = errno; } fclose(f); return retval; } fclose(f); *val = strtol(line, NULL, 0); return 0; } /************************************************************************** * Board power handling. * * This is kept as a list of boards waiting to power on. Only one * board may be waiting at a time, and the first thing in * boards_waiting_power_on will be the next thing to power on. *************************************************************************/ static ipmi_timer_t *power_timer; static unsigned int boards_waiting_power_on[NUM_BOARDS]; static unsigned int num_boards_waiting_power_on; static enum { PT_NOT_RUNNING, PT_RUNNING, PT_WAITING_RESET } power_timer_running; /* * Return true if the board is on, false if not. */ static int board_power_state(sys_data_t *sys, unsigned int num) { int rv; unsigned int rval; rv = get_uintval(trg_power[num], &rval); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to read board %u power state: %s", num + 1, strerror(rv)); return 0; } return rval == BOARD_POWER_ON; } /* * Return true if the given board number is waiting to power on. */ static int board_waiting_power_on(unsigned int num) { unsigned int i; for (i = 0; i < num_boards_waiting_power_on; i++) { if (boards_waiting_power_on[i] == num) return 1; } return 0; } /* * Start the timer to power on the board. The time will be * mintime + rand[1-6]. */ static void start_power_timer(sys_data_t *sys, unsigned int mintime) { struct timeval tv; unsigned int to_add; sys->gen_rand(sys, &to_add, sizeof(to_add)); to_add %= 5; to_add += 1 + mintime; tv.tv_sec = to_add; tv.tv_usec = 0; if (debug & 1) sys->log(sys, DEBUG, NULL, "Starting power timer on board %u for" " %u seconds", boards_waiting_power_on[0] + 1, to_add); sys->start_timer(power_timer, &tv); power_timer_running = PT_RUNNING; } /* * Set the given board number waiting to power up. */ static void board_add_power_wait(sys_data_t *sys, unsigned int num) { boards_waiting_power_on[num_boards_waiting_power_on] = num; num_boards_waiting_power_on++; if (num_boards_waiting_power_on == 1) start_power_timer(sys, 0); } /* * Remove the board from the power up wait list and start the next * board, if there is one. */ static void board_remove_power_wait(sys_data_t *sys, unsigned int num) { unsigned int i; for (i = 0; i < num_boards_waiting_power_on; i++) { if (boards_waiting_power_on[i] == num) break; } if (i == num_boards_waiting_power_on) /* Not found */ return; for (; i < num_boards_waiting_power_on - 1; i++) boards_waiting_power_on[i] = boards_waiting_power_on[i + 1]; num_boards_waiting_power_on--; if (num_boards_waiting_power_on == 0) { sys->stop_timer(power_timer); if (!init_complete) { set_intval(COLD_POWER_FILE, 0); init_complete = 1; } } else if (power_timer_running == PT_NOT_RUNNING) start_power_timer(sys, 5); } static int set_chassis_control(lmc_data_t *mc, int op, unsigned char *val, void *cb_data) { struct board_info *board = cb_data; sys_data_t *sys = board->sys; unsigned int num = board->num; int wval; int rv, err; switch (op) { case CHASSIS_CONTROL_POWER: if (debug & 1) { struct timeval now; board->sys->get_real_time(board->sys, &now); sys->log(sys, DEBUG, NULL, "Power request for board %d," " val=%d, wait=%d last=%ld.%ld, now=%ld.%ld", board->num + 1, *val, board->waiting_power_off, last_board_power_on.tv_sec, last_board_power_on.tv_sec, now.tv_sec, now.tv_sec); } if (debug & 1 && board->waiting_power_off) sys->log(sys, DEBUG, NULL, "Canceling power off wait on" "board power request for board %d", board->num + 1); /* It's going to be forced on or off soon, just disable this. */ board->waiting_power_off = 0; set_intval(pow_off_request[num], BOARD_OFF_REQUEST_OFF); if (*val) { if (!board->present) { if (debug & 1) sys->log(sys, DEBUG, NULL, "Power on request while board" " not present on %d", num + 1); return EAGAIN; } if (!board_power_state(sys, num) && !board_waiting_power_on(num)) board_add_power_wait(sys, num); else if (debug & 1) sys->log(sys, DEBUG, NULL, "Power on request, but board was" " alread on or waiting power up on board %d", num + 1); /* We always delay for a power on. */ break; } /* We are powering off. */ if (board_waiting_power_on(num)) { /* Don't power on later. */ if (debug & 1) sys->log(sys, DEBUG, NULL, "Stopping board power timer" " on %d", num + 1); board_remove_power_wait(sys, num); } if (debug & 1) sys->log(sys, DEBUG, NULL, "Setting board power off on %d", num + 1); rv = set_intval(trg_power[num], BOARD_POWER_OFF); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Unable to set power off" " for board %d: %s", board->num, strerror(rv)); return rv; } /* * We require a 0->1 transition for the power request to be * honored, so start at 1 for the next time to avoid board * insertion or startup issues. */ board->last_power_request = BOARD_OFF_READY; break; case CHASSIS_CONTROL_RESET: if (debug & 1) sys->log(sys, DEBUG, NULL, "Resetting board %d", board->num + 1); set_intval(trg_reset[num], BOARD_RESET_ON); set_intval(trg_reset[num], BOARD_RESET_OFF); break; case CHASSIS_CONTROL_BOOT_INFO_ACK: /* Just ignore this for now */ break; case CHASSIS_CONTROL_BOOT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Chassis control on %d present=%d, " "fru_good=%d, val=%d", board->num + 1, boards[num].present, boards[num].fru_good, *val); if (!boards[num].present) return EAGAIN; if (!boards[num].fru_good) return EBADFD; switch (*val) { case 0: /* none */ return 0; case 1: /* pxe */ wval = 1; break; case 2: /* default */ wval = 0; break; default: return EINVAL; } rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0); if (rv) return rv; boards[num].fru[11] = wval; rv = write_eeprom(&board_i2c[num].fru, boards[num].fru + 11, 11, 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " PXE boot: %s", num + 1, strerror(rv)); } else { boards[num].fru[79] = -checksum(boards[num].fru + 8, 71); rv = write_eeprom(&board_i2c[num].fru, boards[num].fru + 79, 79, 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing" " board %d" " PXE boot checksum: %s", num + 1, strerror(rv)); rv = 0; } } err = ipmi_mc_fru_sem_post(board->mc, 0); if (err) sys->log(sys, OS_ERROR, NULL, "Error posting board %d semaphore: %s", num + 1, strerror(err)); return rv; case CHASSIS_CONTROL_GRACEFUL_SHUTDOWN: if (board_waiting_power_on(num)) { if (debug & 1) sys->log(sys, DEBUG, NULL, "Graceful shutdown requested on %d," " shutting down power on timer", board->num + 1); board_remove_power_wait(sys, num); } else if (board->waiting_power_off) { /* Nothing to do, already waiting. */ } else if (board_power_state(sys, num)) { if (debug & 1) sys->log(sys, DEBUG, NULL, "Graceful shutdown requested on %d," " requesting board power off", board->num + 1); board->waiting_power_off = 1; board->power_off_countdown = 30; set_intval(pow_off_request[num], BOARD_OFF_REQUEST_ON); } break; default: return EINVAL; } return 0; } static int get_chassis_control(lmc_data_t *mc, int op, unsigned char *val, void *cb_data) { struct board_info *board = cb_data; sys_data_t *sys = board->sys; unsigned int num = board->num; unsigned char cval; int rv, err; switch (op) { case CHASSIS_CONTROL_POWER: *val = (board_power_state(board->sys, num) || board_waiting_power_on(num)); break; case CHASSIS_CONTROL_BOOT_INFO_ACK: val[0] = 0; val[1] = 0; break; case CHASSIS_CONTROL_BOOT: rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0); if (rv) return rv; rv = read_eeprom(&board_i2c[num].fru, &cval, 11, 1); if (rv) goto out_post; switch(cval) { case 0: *val = 2; /* default disk */ break; case 1: *val = 1; /* pxe */ break; default: *val = 0; /* Shouldn't happen */ break; } out_post: err = ipmi_mc_fru_sem_post(board->mc, 0); if (err) sys->log(sys, OS_ERROR, NULL, "Error posting board %d semaphore: %s", num + 1, strerror(err)); return rv; default: return EINVAL; } return 0; } /* * Chassis control for the chassis. This will perform the operation on * all boards. */ static int bmc_set_chassis_control(lmc_data_t *mc, int op, unsigned char *val, void *cb_data) { sys_data_t *sys = cb_data; unsigned int i; switch (op) { case CHASSIS_CONTROL_POWER: case CHASSIS_CONTROL_RESET: case CHASSIS_CONTROL_BOOT_INFO_ACK: case CHASSIS_CONTROL_BOOT: case CHASSIS_CONTROL_GRACEFUL_SHUTDOWN: break; default: return EINVAL; } if (debug & 1) { struct timeval now; sys->get_real_time(sys, &now); sys->log(sys, DEBUG, NULL, "Power request for all boards," " val=%d, now=%ld.%ld", *val, now.tv_sec, now.tv_sec); } for (i = 0; i < NUM_BOARDS; i++) set_chassis_control(NULL, op, val, &boards[i]); return 0; } /* * Chassis control get for the chassis. This only works for the power * control, and will return on if any board in the chassis is on, and * off otherwise. */ static int bmc_get_chassis_control(lmc_data_t *mc, int op, unsigned char *val, void *cb_data) { unsigned int i; if (op == CHASSIS_CONTROL_POWER) { unsigned char rval = 0, tval; /* If any board is on, report power as on. */ for (i = 0; i < NUM_BOARDS; i++) { get_chassis_control(NULL, op, &tval, &boards[i]); if (tval) rval = 1; } *val = rval; return 0; } /* This doesn't make sense for anything else. */ return EINVAL; } static void board_power_timeout(void *cb_data) { sys_data_t *sys = cb_data; unsigned int num = boards_waiting_power_on[0]; struct board_info *board = &boards[num]; int rv; if (num_boards_waiting_power_on == 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: power timer went off" " but no board waiting"); return; } if (power_timer_running == PT_RUNNING) { struct timeval tv; if (debug & 1) sys->log(sys, DEBUG, NULL, "Powering on board %d", num + 1); /* Hold the reset on the board for 100ms while it powers on. */ set_intval(trg_reset[num], BOARD_RESET_ON); rv = set_intval(trg_power[num], BOARD_POWER_ON); if (rv) sys->log(sys, OS_ERROR, NULL, "Warning: Unable to set power on" " for board %d: %s", num, strerror(rv)); /* Start the 100ms reset timer */ if (debug & 1) sys->log(sys, DEBUG, NULL, "Starting reset timer on board %u", num + 1); power_timer_running = PT_WAITING_RESET; tv.tv_sec = 0; tv.tv_usec = 100000; sys->start_timer(power_timer, &tv); } else { /* Take the board out of reset. */ set_intval(trg_reset[num], BOARD_RESET_OFF); power_timer_running = PT_NOT_RUNNING; /* Starts the next one if something is waiting. */ board_remove_power_wait(sys, num); } } static void power_down_system(sys_data_t *sys) { unsigned int i; unsigned char val = 0; for (i = 0; i < NUM_BOARDS; i++) set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, &boards[i]); } /* * Called at init time to make sure the board state is sane. */ static void check_chassis_state(sys_data_t *sys) { unsigned int i; /* * Make sure the reset is off on all boards. The power state will * be set later. */ for (i = 0; i < NUM_BOARDS; i++) set_intval(trg_reset[i], BOARD_RESET_OFF); } /************************************************************************** * Sensor handling *************************************************************************/ /* * The DIMM and CPU error sensors will remain set until rearmed. This * is the rearm handling to clear those bits. */ struct eesense_rearm { unsigned int num; unsigned int offset; unsigned char mask; }; static int rearm_eesense_sensor(void *cb_data, uint16_t assert, uint16_t deassert) { struct eesense_rearm *info = cb_data; unsigned int num = info->num; unsigned int off = info->offset; unsigned char mask = info->mask; struct board_info *board = &boards[num]; sys_data_t *sys = board->sys; unsigned char data[72]; unsigned int i; int rv, err; if (!(assert & mask)) return 0; rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0); if (rv) return rv; rv = read_eeprom(&board_i2c[num].fru, data, 8, 72); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error reading board %d fru: %s", num + 1, strerror(rv)); goto out_post; } if (!(data[off] & mask)) goto out_post; data[off] &= ~mask; data[71] = -checksum(data, 71); rv = write_eeprom(&board_i2c[num].fru, data + off, 8 + off, 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " sensor data: %s", num + 1, strerror(rv)); goto out_post; } for (i = 0; i < 8; i++) ipmi_mc_sensor_set_bit(boards[num].mc, 0, 19 + off, i, ((data[off] >> i) & 1), 0); rv = write_eeprom(&board_i2c[num].fru, data + 71, 79, 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " internal use checksum: %s", num + 1, strerror(rv)); rv = 0; } out_post: err = ipmi_mc_fru_sem_post(board->mc, 0); if (err) sys->log(sys, OS_ERROR, NULL, "Error posting board %d semaphore: %s", num + 1, strerror(err)); return rv; } /* * The rearm for the power supply sensor will set the clear fault flag * for the power supply, just to be sure it is clear. */ static int rearm_power_supply_sensor(void *cb_data, uint16_t assert, uint16_t deassert) { unsigned int num = (unsigned long) cb_data; sys_data_t *sys = boards[0].sys; int rv; char fname[100]; if (!(assert & 2)) return 0; sprintf(fname, "/sys/class/wixpmbus/CLEAR_FAULT_%d", num); rv = set_intval(fname, 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Error writing ps %d clear file: %s", num, strerror(rv)); return rv; } return 0; } /************************************************************************** * Board handling *************************************************************************/ /* * Read the board's FRU and update anything that needs to be updated, * like the chassis information, the board's external MAC address, etc. */ static int handle_board_fru(sys_data_t *sys, int num) { int rv; unsigned int iuse; unsigned int iuse_len; unsigned int chinfo; unsigned int chinfo_len; unsigned int brdinfo; unsigned int brdinfo_len; unsigned int mac_offset; unsigned int brdchsernum_offset; unsigned int brdsernum_offset; int modified = 0; int fruversion2 = 0; unsigned char *fru; if (debug & 1) sys->log(sys, DEBUG, NULL, "Checking board FRU on board %d", num + 1); /* Guilty until proven innocent */ boards[num].fru_good = 0; rv = read_eeprom(&board_i2c[num].fru, boards[num].fru, 0, board_i2c[num].fru.size); if (rv) { sys->log(sys, SETUP_ERROR, NULL, "Can't read board %d eeprom: %s", num + 1, strerror(rv)); return 0; } fru = boards[num].fru; if (fru[0] != 1) { sys->log(sys, SETUP_ERROR, NULL, "Invalid board %d FRU version: 0x%x", num + 1, fru[0]); return 0; } if (checksum(fru + 0, 8) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU header" " checksum fail", num + 1); } iuse = fru[1] * 8; iuse_len = 80 - 8; chinfo = fru[2] * 8; chinfo_len = 256 - 80; brdinfo = fru[3] * 8; brdinfo_len = 2048 - 256; brdchsernum_offset = 42; brdsernum_offset = 74; mac_offset = 95; if (iuse != 8) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU internal use" "area is not at offset 8", num + 1); return 0; } if (chinfo != 80) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU chassis info" "area is not at offset 80", num + 1); return 0; } if (brdinfo != 256) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU board info" "area is not at offset 256", num + 1); return 0; } if (checksum(fru + iuse, iuse_len) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU internal use" " checksum fail", num + 1); return 0; } if (checksum(fru + chinfo, chinfo_len) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU chassis info" " checksum fail", num + 1); return 0; } if (checksum(fru + brdinfo, brdinfo_len) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU board info" " checksum fail", num + 1); return 0; } boards[num].fru_good = 1; /* Set the chassis information if it is not correct. */ if (chassis_fru[chinfo + brdchsernum_offset] != 0xd4) { /* Try the version 2.0 of the FRU data */ brdchsernum_offset = 17; } if (sernum_len == 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: FRU chassis serial number" " invalid, not setting board %d data", num + 1); } else if (chassis_chinfo == 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis chassis info FRU" "invalid, not checking board %d FRU chassis data", num + 1); } else { /* * If we have a different FRU version, or if the serial * numbers don't match, then update the chassis info area. */ if ((brdchsernum_offset != sernum_offset) || memcmp(fru + chinfo + brdchsernum_offset, chassis_fru + chassis_chinfo + sernum_offset, sernum_len) != 0) { /* The chassis serial number has changed. */ sys->log(sys, INFO, NULL, "Info: Updating board %d" " chassis info area", num + 1); memcpy(fru + chinfo, chassis_fru + chassis_chinfo, chassis_chinfo_len); rv = write_eeprom(&board_i2c[num].fru, fru + chinfo, chinfo, chassis_chinfo_len); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " chassis info: %s", num + 1, strerror(rv)); } } } /* Set the board system serial number if it is not correct. */ if (fru[brdinfo + brdsernum_offset] != 0xd4) { /* FRU version 2.0 */ brdsernum_offset = 34; fruversion2 = 1; } if (fru[brdinfo + brdsernum_offset] != 0xd4) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU serial num" " data invalid", num + 1); } else if (!sernum[0]) { sys->log(sys, SETUP_ERROR, NULL, "Warning: System serial num invalid," " not checking board %d ser num", num + 1); } else { char mysernum[21]; if (fruversion2) { int len; len = sprintf(mysernum, "%s-%c", sernum, num + 'A'); memset(mysernum + len, ' ', 20 - len); mysernum[20] = '\0'; } else { memset(mysernum, 0, 21); sprintf(mysernum, "System SN %s-%c", sernum, num + 'A'); } if (memcmp(mysernum, fru + brdinfo + brdsernum_offset + 1, 20) != 0) { sys->log(sys, INFO, NULL, "Info: Updating board %d" " serial number", num + 1); memcpy(fru + brdinfo + brdsernum_offset + 1, mysernum, 20); rv = write_eeprom(&board_i2c[num].fru, fru + brdinfo + brdsernum_offset + 1, brdinfo + brdsernum_offset + 1, 20); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " serial num: %s", num + 1, strerror(rv)); } modified = 1; } } /* Set the board MAC address if it is not correct. */ if (fru[brdinfo + mac_offset] != 0xdc) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU external MAC" " data invalid", num + 1); } else if (!sysmac[0]) { sys->log(sys, SETUP_ERROR, NULL, "Warning: System MAC invalid, not" " checking board %d MAC", num + 1); } else { char mac[29]; memset(mac, 0, 29); sprintf(mac, "System MAC %s%d", sysmac, num + 1); if (memcmp(mac, fru + brdinfo + mac_offset + 1, 28) != 0) { sys->log(sys, INFO, NULL, "Info: Updating board %d" " MAC address", num + 1); memcpy(fru + brdinfo + mac_offset + 1, mac, 28); rv = write_eeprom(&board_i2c[num].fru, fru + brdinfo + mac_offset + 1, brdinfo + mac_offset + 1, 28); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " MAC address: %s", num + 1, strerror(rv)); } modified = 1; } } if (modified) { /* Recalculate the board checksum */ fru[brdinfo + brdinfo_len - 1] = -checksum(fru + brdinfo, brdinfo_len - 1); rv = write_eeprom(&board_i2c[num].fru, fru + brdinfo + brdinfo_len - 1, brdinfo + brdinfo_len - 1, 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d" " board info checksum: %s", num + 1, strerror(rv)); } } return 0; } /* * Check that the board has not changed states, and if it has then * handle the change. Called on insertion/removal events and * periodically by a timer. */ static int check_board(sys_data_t *sys, int num, unsigned int since_last, int power_up_new_board) { int rv; unsigned int present; unsigned int rval; unsigned char val; struct board_info *board = &boards[num]; if (board->present && board_power_state(sys, num)) { rv = get_uintval(pow_off_ready[num], &rval); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to read board %u power off ready: %s", num, strerror(rv)); } else { if (board->last_power_request == BOARD_OFF_NOT_READY && rval == BOARD_OFF_READY) { if (debug & 1) { if (board->waiting_power_off) sys->log(sys, DEBUG, NULL, "Graceful power of finished" " on %d, setting power off", board->num + 1); else sys->log(sys, DEBUG, NULL, "Board %d requested power" " off, setting power off", board->num + 1); } val = 0; set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board); } board->last_power_request = rval; } } if (board->waiting_power_off && since_last) { if (board->power_off_countdown == 0) { unsigned char val; if (debug & 1) sys->log(sys, DEBUG, NULL, "Graceful power off timeout" " on %d, forcing power off", board->num + 1); val = 0; set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board); } else { board->power_off_countdown--; } } rv = get_uintval(trg_present[num], &present); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to read board %d presence: %s", num + 1, strerror(rv)); return rv; } present = (present == BOARD_PRESENT) && !simulate_board_absent[num]; if (board->present == present) return 0; board->present = present; if (!present) { sys->log(sys, INFO, NULL, "Info: board %d has been removed", num + 1); board->fru_good = 0; /* * Turn off board power when not present, that way we can hold * off power on until we are done with messing with the board FRU * data. */ val = 0; set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board); return 0; } sys->log(sys, INFO, NULL, "Info: board %d is now present", num + 1); rv = create_eeprom(sys, board_i2c[num].add_dev, &board_i2c[num].fru); if (rv) { /* Force a retry, perhaps the device hasn't been created yet */ board->present = 0; sys->log(sys, SETUP_ERROR, NULL, "Can't create board %d eeprom: %s." " Will retry in a second", num + 1, strerror(rv)); return 0; } rv = handle_board_fru(sys, num); if (rv) return rv; if (power_up_new_board) { /* If the board was not present and now it is, power it on. */ val = 1; set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board); } return 0; } /* * If the board front-panel button is pressed, record the time, the * button will be handled on release. */ static void handle_button_press(sys_data_t *sys, unsigned int brdnum) { struct board_info *board = &boards[brdnum]; if (debug & 1) sys->log(sys, DEBUG, NULL, "Button press on %d", board->num + 1); board->button_pressed = 1; board->sys->get_monotonic_time(board->sys, &board->button_press_time); } /* * Handle the board's front-panel button. */ static void handle_button_release(sys_data_t *sys, unsigned int num) { struct timeval now; unsigned char val; struct board_info *board = &boards[num]; int power_state = board_power_state(sys, num); if (!board->button_pressed) return; if (debug & 1) sys->log(sys, DEBUG, NULL, "Button release on %d", num + 1); board->button_pressed = 0; board->sys->get_monotonic_time(board->sys, &now); /* * If the button is pressed more than 4 seconds, start a graceful * shutdown. */ if (power_state && (diff_timeval_ms(&now, &board->button_press_time) > 4000)) { if (board_waiting_power_on(num)) { if (debug & 1) sys->log(sys, DEBUG, NULL, "Button press on %d >4sec, stop" " power on timer", board->num + 1); board_remove_power_wait(sys, num); } else { if (debug & 1) sys->log(sys, DEBUG, NULL, "Button press on %d >4sec, start" " graceful shutdown", board->num + 1); val = 0; set_chassis_control(NULL, CHASSIS_CONTROL_GRACEFUL_SHUTDOWN, &val, board); } } /* * If the button is pressed less than 4 seconds, start a power up * if the board is not already on. */ if (!power_state && (diff_timeval_ms(&now, &board->button_press_time) <= 4000)) { if (debug & 1) sys->log(sys, DEBUG, NULL, "Button press on %d <4sec, power on", board->num + 1); val = 1; set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board); } } /* * Read data from the chassis FRU. */ static int init_chassis(sys_data_t *sys) { int rv; if (debug & 1) sys->log(sys, DEBUG, NULL, "Reading chassis eeprom info"); /* Detect which I2C channel to use for the chassis I2C. */ rv = check_eeprom(sys, &chassis_i2c_new.fru); if (rv) { rv = check_eeprom(sys, &chassis_i2c_old.fru); if (rv) { sys->log(sys, SETUP_ERROR, NULL, "Can't find chassis eeprom: %s", strerror(rv)); return rv; } chassis_i2c = &chassis_i2c_old; } else { chassis_i2c = &chassis_i2c_new; } rv = read_eeprom(&chassis_i2c->fru, chassis_fru, 0, chassis_i2c->fru.size); if (rv) { sys->log(sys, SETUP_ERROR, NULL, "Can't read chassis eeprom: %s", strerror(rv)); return rv; } if (chassis_fru[0] != 1) { sys->log(sys, SETUP_ERROR, NULL, "Invalid Chassis FRU version: 0x%x", chassis_fru[0]); return EINVAL; } if (checksum(chassis_fru + 0, 8) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU header" " checksum fail"); } chassis_iuse = chassis_fru[1] * 8; chassis_iuse_len = 80 - 8; chassis_chinfo = chassis_fru[2] * 8; chassis_chinfo_len = 256 - 80; chassis_brdinfo = chassis_fru[3] * 8; chassis_brdinfo_len = 1024 - 256; sernum_offset = 42; sernum_offset2 = 11; sernum_len = 20; sysmac_offset = 74; if (chassis_iuse != 8) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU internal use" "area is not at offset 8"); } if (chassis_chinfo != 80) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU chassis info" "area is not at offset 80"); } if (chassis_brdinfo != 256) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU board info" "area is not at offset 256"); } if (checksum(chassis_fru + chassis_iuse, chassis_iuse_len) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU internal use" " checksum fail"); } if (checksum(chassis_fru + chassis_chinfo, chassis_chinfo_len) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU chassis info" " checksum fail"); } if (checksum(chassis_fru + chassis_brdinfo, chassis_brdinfo_len) != 0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU board info" " checksum fail"); } if (chassis_fru[chassis_chinfo + sernum_offset] != 0xd4) { /* Try the version 2.0 of the FRU data */ sernum_offset = 17; sernum_offset2 = 1; } if (chassis_fru[chassis_chinfo + sernum_offset] != 0xd4) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU system serial" " number data invalid"); sernum_len = 0; } else { memcpy(sernum, chassis_fru + chassis_chinfo + sernum_offset + sernum_offset2, 8); sernum[9] = '\0'; } if (chassis_fru[chassis_brdinfo + sysmac_offset] != 0xe0) { sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU system MAC" " data invalid"); } else { /* Don't copy the last byte, we use that for the boards. */ memcpy(sysmac, chassis_fru + chassis_brdinfo + sysmac_offset + 14, 16); sysmac[16] = '\0'; } return 0; } /************************************************************************** * Event/timer handling *************************************************************************/ static int ast_fd; static ipmi_io_t *ast_fd_id; static int fork_event_wait = 0; static void ast_evt(int fd, void *cb_data) { int rv; int event; sys_data_t *sys = cb_data; if (!fork_event_wait) { rv = ioctl(fd, READ_WIW_NONBLOCKING, &event); if (rv == -1) { sys->log(sys, OS_ERROR, NULL, "Warning: MV: Error reading" " AST event: %s", strerror(errno)); return; } } else { unsigned char c; rv = read(fd, &c, 1); if (rv != 1) { sys->log(sys, OS_ERROR, NULL, "Warning: MV: AST1300 shim" " failed: %s", strerror(errno)); exit(1); } event = c; } if (debug & 1) sys->log(sys, DEBUG, NULL, "Got event %d", event); switch (event) { case WIW_NO_EVENT: break; case WIW_NODE1_IN: case WIW_NODE1_OUT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Board %s on 1", event == WIW_NODE1_IN ? "insertion" : "removal"); check_board(sys, 0, 0, 1); break; case WIW_NODE2_IN: case WIW_NODE2_OUT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Board %s on 2", event == WIW_NODE2_IN ? "insertion" : "removal"); check_board(sys, 1, 0, 1); break; case WIW_NODE3_IN: case WIW_NODE3_OUT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Board %s on 3", event == WIW_NODE3_IN ? "insertion" : "removal"); check_board(sys, 2, 0, 1); break; case WIW_NODE4_IN: case WIW_NODE4_OUT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Board %s on 4", event == WIW_NODE4_IN ? "insertion" : "removal"); check_board(sys, 3, 0, 1); break; case WIW_NODE5_IN: case WIW_NODE5_OUT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Board %s on 5", event == WIW_NODE5_IN ? "insertion" : "removal"); check_board(sys, 4, 0, 1); break; case WIW_NODE6_IN: case WIW_NODE6_OUT: if (debug & 1) sys->log(sys, DEBUG, NULL, "Board %s on 6", event == WIW_NODE6_IN ? "insertion" : "removal"); check_board(sys, 5, 0, 1); break; case WIW_NODE1_PBTN_P: handle_button_press(sys, 0); break; case WIW_NODE1_PBTN_R: handle_button_release(sys, 0); break; case WIW_NODE2_PBTN_P: handle_button_press(sys, 1); break; case WIW_NODE2_PBTN_R: handle_button_release(sys, 1); break; case WIW_NODE3_PBTN_P: handle_button_press(sys, 2); break; case WIW_NODE3_PBTN_R: handle_button_release(sys, 2); break; case WIW_NODE4_PBTN_P: handle_button_press(sys, 3); break; case WIW_NODE4_PBTN_R: handle_button_release(sys, 3); break; case WIW_NODE5_PBTN_P: handle_button_press(sys, 4); break; case WIW_NODE5_PBTN_R: handle_button_release(sys, 4); break; case WIW_NODE6_PBTN_P: handle_button_press(sys, 5); break; case WIW_NODE6_PBTN_R: handle_button_release(sys, 5); break; default: break; } } /* * This timer is called periodically to check the boards. */ static ipmi_timer_t *mv_timer; static void mv_timeout(void *cb_data) { int i; struct timeval tv; sys_data_t *sys = cb_data; for (i = 0; i < NUM_BOARDS; i++) check_board(sys, i, 1, 1); tv.tv_sec = 1; tv.tv_usec = 0; sys->start_timer(mv_timer, &tv); } static void shim_sig(int signr) { exit(1); } /* * The ast1300 device doesn't support select() in older * implementations. So add a small program that will wait for it * blocking and then feed it to the program through a pipe, which will * work as a select() device. */ static void ast1300_shim(sys_data_t *sys, int ast_fd, int writefd, int pid) { unsigned char c; int rv; int event; struct sigaction act; /* * Make sure to terminate if the main program goes away. */ memset(&act, 0, sizeof(act)); act.sa_handler = shim_sig; rv = sigaction(SIGCHLD, &act, NULL); if (rv == -1) { sys->log(sys, OS_ERROR, NULL, "Warning: MV: Error settint up" " signal: %s", strerror(errno)); exit(1); } for (;;) { rv = ioctl(ast_fd, READ_WIW_BLOCKING, &event); if (rv == -1) { sys->log(sys, OS_ERROR, NULL, "Warning: MV: Error reading" " AST event: %s", strerror(errno)); exit(1); } c = event; rv = write(writefd, &c, 1); if (rv != 1) { /* Other end of the pipe went away, just shut down. */ exit(0); } } } /************************************************************************** * General sensor handling *************************************************************************/ struct sensor_info { char *filename; unsigned char sensor_number; char *create_file; char *create_data; int invalid_if_off; int mult; int div; int sub; }; static struct sensor_info empty_sensors[] = { { NULL } }; static int all_fans_duty = 0; struct fan_duty_table { int reading; int setting; }; struct sensor_handling { struct sensor_info *switch_s; char *switch_valids; int *switch_last_values; struct sensor_info *board; char (*board_valids)[NUM_BOARDS]; int (*board_last_values)[NUM_BOARDS]; struct fan_duty_table *fan_duty; /* Modify the duty tables by this much. */ int duty_offset; }; static struct sensor_info switch_temp_sensors[] = { /* Switch Temp */ { "/sys/class/i2c-adapter/i2c-0/0-0058/temp2_input", 1, .div = 1000 }, /* Switch CPU Temp */ { "/sys/class/i2c-adapter/i2c-0/0-0058/temp3_input", 2, .div = 1000 }, { NULL } }; static char switch_temp_sensor_valids[2]; static int switch_temp_sensor_last_values[2]; static struct sensor_info board_temp_sensors[] = { /* Board CPU Temp */ { "/sys/class/i2c-adapter/i2c-%d/%d-0064/temp1_input", 2, .div = 1000, .invalid_if_off = 1, .create_file = "/sys/class/i2c-adapter/i2c-%d/new_device", .create_data = "axp 0x64" }, /* Board DIMM Temp */ { "/sys/class/i2c-adapter/i2c-%d/%d-001e/temp1_input", 3, .div = 1000, .invalid_if_off = 1, .create_file = "/sys/class/i2c-adapter/i2c-%d/new_device", .create_data = "dimm 0x1e" }, { NULL } }; static char board_temp_sensor_last_oor[NUM_BOARDS]; static char board_temp_sensor_valids[2][NUM_BOARDS]; static int board_temp_sensor_last_values[2][NUM_BOARDS]; static struct fan_duty_table main_fan_duty_table[] = { { 0, 42 }, { 60, 45 }, { 65, 48 }, { 70, 51 }, { 75, 54 }, { 80, 57 }, { 85, 60 }, { 95, 70 }, { 100, 85 }, { 105, 100 }, { -1 } }; static struct sensor_handling main_temp = { .switch_s = switch_temp_sensors, .switch_valids = switch_temp_sensor_valids, .switch_last_values = switch_temp_sensor_last_values, .board = board_temp_sensors, .board_valids = board_temp_sensor_valids, .board_last_values = board_temp_sensor_last_values, .fan_duty = main_fan_duty_table, .duty_offset = 10 }; static struct sensor_info board_mb_sensors[] = { /* Board MB Temp */ { "/sys/class/i2c-adapter/i2c-%d/%d-004a/temp1_input", 1, .div = 1000 }, { NULL } }; static char board_mb_sensor_valids[1][NUM_BOARDS]; static int board_mb_sensor_last_values[1][NUM_BOARDS]; static struct fan_duty_table mb_fan_duty_table[] = { { 0, 42 }, { 50, 45 }, { 52, 48 }, { 54, 51 }, { 56, 54 }, { 58, 57 }, { 60, 60 }, { -1 } }; static struct sensor_handling mb_temp = { .switch_s = empty_sensors, .board = board_mb_sensors, .board_valids = board_mb_sensor_valids, .board_last_values = board_mb_sensor_last_values, .fan_duty = mb_fan_duty_table, .duty_offset = 0 }; static struct sensor_info board_front_sensors[] = { /* Board Front Temp */ { "/sys/class/i2c-adapter/i2c-%d/%d-004c/temp1_input", 4, .div = 1000 }, { NULL } }; static char board_front_sensor_valids[1][NUM_BOARDS]; static int board_front_sensor_last_values[1][NUM_BOARDS]; static struct fan_duty_table front_fan_duty_table[] = { { 0, 42 }, { 37, 65 }, { 39, 70 }, { 41, 75 }, { 43, 80 }, { 45, 85 }, { -1 } }; static struct sensor_handling front_temp = { .switch_s = empty_sensors, .board = board_front_sensors, .board_valids = board_front_sensor_valids, .board_last_values = board_front_sensor_last_values, .fan_duty = front_fan_duty_table, .duty_offset = 0 }; static struct sensor_info switch_sensors[] = { /* Switch 12v */ { "/sys/class/i2c-adapter/i2c-0/0-0058/in11_input", 3, .mult=8, .div=125, .sub=10000 }, /* Switch 3.3v */ { "/sys/class/i2c-adapter/i2c-0/0-0058/in10_input", 4, .mult=8, .div=25, .sub=2900 }, /* Switch 1.8v */ { "/sys/class/i2c-adapter/i2c-0/0-0058/in2_input", 5, .mult=16, .div=25, .sub=1600 }, /* Fans */ { "/sys/class/astfan/fan1_input", 0x70, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan2_input", 0x71, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan3_input", 0x72, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan4_input", 0x73, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan5_input", 0x74, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan6_input", 0x75, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan7_input", 0x76, .mult = 10, .div = 392 }, { "/sys/class/astfan/fan8_input", 0x77, .mult = 10, .div = 392 }, { NULL } }; static char switch_sensor_valids[11]; static int switch_sensor_last_values[11]; static struct sensor_info board_sensors[] = { /* Board 1.0v */ { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in3_input", 5, .mult=32, .div=25, .sub=900, .invalid_if_off = 1 }, /* Board 1.8v */ { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in2_input", 6, .mult=16, .div=25, .sub=1600, .invalid_if_off = 1 }, /* Board 2.5v */ { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in1_input", 7, .mult=32, .div=125, .sub=2000, .invalid_if_off = 1 }, /* Board 3.3v */ { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in0_input", 8, .mult=8, .div=25, .sub=2900, .invalid_if_off = 1 }, /* Board 1.05v */ { "/sys/class/i2c-adapter/i2c-%d/%d-0049/in2_input", 9, .mult=16, .div=25, .sub=800, .invalid_if_off = 1 }, /* Board DIMMv */ { "/sys/class/i2c-adapter/i2c-%d/%d-0049/in1_input", 11, .mult=64, .div=75, .sub=1200, .invalid_if_off = 1 }, /* Board 0.9v */ { "/sys/class/i2c-adapter/i2c-%d/%d-0049/in0_input", 12, .mult=21, .div=50, .sub=700, .invalid_if_off = 1 }, { NULL } }; static char board_sensor_valids[8][NUM_BOARDS]; static int board_sensor_last_values[8][NUM_BOARDS]; static struct sensor_handling system_sensors = { .switch_s = switch_sensors, .switch_valids = switch_sensor_valids, .switch_last_values = switch_sensor_last_values, .board = board_sensors, .board_valids = board_sensor_valids, .board_last_values = board_sensor_last_values, }; static int get_readings(sys_data_t *sys, struct sensor_handling *h, int *rmax) { int err; int success = 0; int max = 0; unsigned int i, j; for (i = 0; h->switch_s[i].filename; i++) { int value; err = get_intval(h->switch_s[i].filename, &value); if (debug & 2) sys->log(sys, DEBUG, NULL, "Read value %s: %d %d", h->switch_s[i].filename, err, value); if (err) { h->switch_valids[i] = 0; } else { success = 1; h->switch_valids[i] = 1; h->switch_last_values[i] = value; if (value > max) max = value; } } for (i = 0; h->board[i].filename; i++) { for (j = 0; j < NUM_BOARDS; j++) { int value; char filename[100]; if (!boards[j].present || (h->board[i].invalid_if_off && !board_power_state(sys, j))) { h->board_valids[i][j] = 0; continue; } sprintf(filename, h->board[i].filename, j + 1, j + 1); err = get_intval(filename, &value); if ( err && h->board[i].create_file) { /* The sysfs file doesn't exist, create it. */ char cfilename[100]; FILE *f; sprintf(cfilename, h->board[i].create_file, j + 1); f = fopen(cfilename, "w"); if (!f) { sys->log(sys, OS_ERROR, NULL, "Unable to create %s", filename); } else { fprintf(f, "%s\n", h->board[i].create_data); fclose(f); } err = get_intval(filename, &value); } if (debug & 2) sys->log(sys, DEBUG, NULL, "Read value %s: %d %d", filename, err, value); if (err) { sys->log(sys, OS_ERROR, NULL, "Sensor read error of %s: %s", filename, strerror(err)); h->board_valids[i][j] = 0; } else { success = 1; h->board_valids[i][j] = 1; h->board_last_values[i][j] = value; if (value > max) max = value; } } } if (rmax) *rmax = max; return !success; } static int calc_duty(struct fan_duty_table *t, int duty_offset, int v, int *last_v, int *last_duty) { unsigned int i; int duty = 0; /* Hysteresis when going down, and is two degress C. */ if (v < *last_v) v += 2000; /* Convert to degrees, rounding */ v = (v + 500) / 1000; for (i = 1; t[i].reading != -1; i++) { if (v < t[i].reading) break; } duty = t[i - 1].setting + duty_offset; if (duty > 100) duty = 100; if (duty < 42) duty = 42; if (duty != *last_duty) { *last_duty = duty; *last_v = v; } else if (v > *last_v) { /* * This is subtle, but is required to correctly implement * hysteresis. We don't want to get in a situation where the * temperature goes down, but is still in the hysteresis area, * then goes back up a little bit. So we only set last_v when * going up. */ *last_v = v; } return duty; } static int last_main_v, last_mb_v, last_front_v; static int last_main_duty, last_mb_duty, last_front_duty; static int last_duty; static int scan_pipe[2]; static pthread_mutex_t scan_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t scan_cond = PTHREAD_COND_INITIALIZER; static pthread_t scan_thread; static ipmi_io_t *scan_fd_id; static int eesense_data_ready[NUM_BOARDS]; static unsigned char cpu_errors[NUM_BOARDS]; static uint16_t dimm_errors[NUM_BOARDS]; static int ps_status_good[2]; static unsigned int ps_status_word[2]; static void scan_eeprom_sensors(sys_data_t *sys) { int rv; unsigned int i; for (i = 0; i < NUM_BOARDS; i++) { if (!boards[i].present) { eesense_data_ready[i] = 0; } else { unsigned char data[2]; rv = ipmi_mc_fru_sem_trywait(boards[i].mc, 0); if (rv) continue; rv = read_eeprom(&board_i2c[i].fru, data, 9, 2); if (rv) { eesense_data_ready[i] = 0; sys->log(sys, OS_ERROR, NULL, "Error reading eeprom sensors for %d: %s", i + 1, strerror(rv)); } else { eesense_data_ready[i] = 1; cpu_errors[i] = data[0]; dimm_errors[i] = data[1]; } rv = ipmi_mc_fru_sem_post(boards[i].mc, 0); if (rv) sys->log(sys, OS_ERROR, NULL, "Error posting board %d semaphore: %s", i + 1, strerror(rv)); } } } static void scan_ps_sensors(sys_data_t *sys) { int rv; unsigned int i; rv = get_uintval("/sys/class/wixpmbus/STATUS_1", &i); if (rv) { /* Not present */ ps_status_good[0] = 0; } else { ps_status_good[0] = 1; ps_status_word[0] = i; } rv = get_uintval("/sys/class/wixpmbus/STATUS_2", &i); if (rv) { /* Not present */ ps_status_good[1] = 0; } else { ps_status_good[1] = 1; ps_status_word[1] = i; } } static char *fan_fail_led[4] = { "/sys/class/astgpio/GPIOP0", "/sys/class/astgpio/GPIOP1", "/sys/class/astgpio/GPIOP2", "/sys/class/astgpio/GPIOP3", }; static void * scan_sensors(void *cb_data) { sys_data_t *sys = cb_data; int err; int duty; int max_temp = 0; int max_duty = 0; char dummy = 0; struct timeval next, now, wait; unsigned int i; char fan_fail[8]; for (;;) { sys->get_monotonic_time(sys, &next); add_to_timeval(&next, poll_time); err = get_readings(sys, &main_temp, &max_temp); if (!err) { max_duty = calc_duty(main_temp.fan_duty, main_temp.duty_offset, max_temp, &last_main_v, &last_main_duty); } err = get_readings(sys, &mb_temp, &max_temp); if (!err) { duty = calc_duty(mb_temp.fan_duty, mb_temp.duty_offset, max_temp, &last_mb_v, &last_mb_duty); if (duty > max_duty) max_duty = duty; } err = get_readings(sys, &front_temp, &max_temp); if (!err) { duty = calc_duty(front_temp.fan_duty, front_temp.duty_offset, max_temp, &last_front_v, &last_front_duty); if (duty > max_duty) max_duty = duty; } duty = 0; for (i = 1; i < 9; i++) { char filename[50]; int val; sprintf(filename, "/sys/class/astfan/fan%u_input", i); err = get_intval(filename, &val); if (err) { sys->log(sys, OS_ERROR, NULL, "Can't read fan speed for %s: %s", filename, strerror(err)); /* Can't read fan, better safe than sorry. */ duty = 90; fan_fail[i - 1] = 1; } else { /* A fan is failing. */ if (val < 1000) { fan_fail[i - 1] = 1; duty = 90; } else fan_fail[i - 1] = 0; } } for (i = 0; i < 4; i++) { if (fan_fail[i * 2] || fan_fail[i * 2 + 1]) set_intval(fan_fail_led[i], 1); else set_intval(fan_fail_led[i], 0); } if (duty > max_duty) max_duty = duty; if (all_fans_duty) max_duty = all_fans_duty; if (max_duty != last_duty) { if (debug & 8) sys->log(sys, DEBUG, NULL, "Setting fan duty to %d", max_duty); for (i = 1; i < 5; i++) { char filename[50]; sprintf(filename, "/sys/class/astfan/pwm%u", i); err = set_intval(filename, max_duty * 256 / 100); if (err) sys->log(sys, OS_ERROR, NULL, "Can't set fan duty %s to %d: %s", filename, max_duty, strerror(err)); } } get_readings(sys, &system_sensors, NULL); scan_eeprom_sensors(sys); scan_ps_sensors(sys); pthread_mutex_lock(&scan_mutex); write(scan_pipe[1], &dummy, 1); pthread_cond_wait(&scan_cond, &scan_mutex); pthread_mutex_unlock(&scan_mutex); if (wdt_test_timer_ran) { unsigned char data = 1; err = write(wdt_fd, &data, 1); if (err == -1) { sys->log(sys, OS_ERROR, NULL, "Unable to write to watchdog timer: %s", strerror(err)); } wdt_test_timer_ran = 0; } /* Wait until poll_time seconds after the last scan started */ sys->get_monotonic_time(sys, &now); diff_timeval(&wait, &next, &now); select(0, NULL, NULL, NULL, &wait); } return NULL; } static unsigned char conv_value(struct sensor_info *info, int value) { value -= info->sub; if (info->mult) value *= info->mult; if (info->div) { value += info->div / 2; value /= info->div; } if (value < 0) return 0; if (value > 255) return 255; return value; } static void set_sensors_from_table(sys_data_t *sys, struct sensor_handling *h) { unsigned int i, j; for (i = 0; h->switch_s[i].filename; i++) { if (debug & 4) sys->log(sys, DEBUG, NULL, "process value %s: %d %d (%u)", h->switch_s[i].filename, h->switch_valids[i], h->switch_last_values[i], conv_value(&h->switch_s[i], h->switch_last_values[i])); ipmi_mc_sensor_set_enabled(bmc_mc, 0, h->switch_s[i].sensor_number, h->switch_valids[i]); if (h->switch_valids[i]) { ipmi_mc_sensor_set_value(bmc_mc, 0, h->switch_s[i].sensor_number, conv_value(&h->switch_s[i], h->switch_last_values[i]), 1); } } for (i = 0; h->board[i].filename; i++) { for (j = 0; j < NUM_BOARDS; j++) { if (debug & 4) sys->log(sys, DEBUG, NULL, "process value %s (%d): %d %d (%u)", h->board[i].filename, j + 1, h->board_valids[i][j], h->board_last_values[i][j], conv_value(&h->board[i], h->board_last_values[i][j])); ipmi_mc_sensor_set_enabled(boards[j].mc, 0, h->board[i].sensor_number, h->board_valids[i][j]); if (h->board_valids[i][j]) ipmi_mc_sensor_set_value(boards[j].mc, 0, h->board[i].sensor_number, conv_value(&h->board[i], h->board_last_values[i][j]), 1); } } } static void handle_eesense_data(sys_data_t *sys) { unsigned int i, j; for (i = 0; i < NUM_BOARDS; i++) { ipmi_mc_sensor_set_enabled(boards[i].mc, 0, 20, eesense_data_ready[i]); ipmi_mc_sensor_set_enabled(boards[i].mc, 0, 21, eesense_data_ready[i]); if (!eesense_data_ready[i]) continue; for (j = 0; j < 1; j++) ipmi_mc_sensor_set_bit(boards[i].mc, 0, 20, j, ((cpu_errors[i] >> j) & 1), 1); for (j = 0; j < 8; j++) ipmi_mc_sensor_set_bit(boards[i].mc, 0, 21, j, ((dimm_errors[i] >> j) & 1), 1); } } #define PMBUS_NONE_BIT (1 << 0) #define PMBUS_CML_BIT (1 << 1) #define PMBUS_TEMP_BIT (1 << 2) #define PMBUS_VIN_UV_BIT (1 << 3) #define PMBUS_IOUT_OC_BIT (1 << 4) #define PMBUS_VOUT_OV_BIT (1 << 5) #define PMBUS_OFF_BIT (1 << 6) #define PMBUS_BUSY_BIT (1 << 7) #define PMBUS_UNKNOWN_BIT (1 << 8) #define PMBUS_OTHER_BIT (1 << 9) #define PMBUS_FANS_BIT (1 << 10) #define PMBUS_NOT_POWER_GOOD_BIT (1 << 11) #define PMBUS_MRF_BIT (1 << 12) #define PMBUS_INPUT_BIT (1 << 13) #define PMBUS_I_P_OUT_BIT (1 << 14) #define PMBUS_VOUT_BIT (1 << 15) /* * This is a mask to convert the PMBus status work to the IPMI power * supply status bitmask. Each entry in this array has a set of bits; * if one of those bits is set in the status work then the index of * the entry is a bit that should be set in the IPMI sensor. */ static uint16_t pm_word_to_ipmi[7] = { 0, /* presence is handled separately */ 0xffff, /* If anything is set we declare a fault */ PMBUS_TEMP_BIT | PMBUS_FANS_BIT, /* Predictive failure */ 0, /* Input lost, nothing for this, only have "lost or out of range" */ PMBUS_INPUT_BIT, /* Input lost or out of range */ 0, /* Out of range but present. No bit for this, just previous. */ 0, /* Configuration error */ }; static void handle_ps_status(int num) { uint16_t val; unsigned int i; if (ps_status_good[num]) { val = 1; /* Present */ for (i = 1; i < 7; i++) val |= (!!(ps_status_word[num] & pm_word_to_ipmi[i])) << i; } else { val = 0; /* Not present */ } for (i = 0; i < 7; i++) ipmi_mc_sensor_set_bit(bmc_mc, 0, 8 + num, i, (val >> i) & 1, 1); } static void set_sensors_from_tables(int fd, void *cb_data) { sys_data_t *sys = cb_data; unsigned int i; int temp = 0; unsigned char dummy; int rv; read(fd, &dummy, 1); set_sensors_from_table(sys, &main_temp); set_sensors_from_table(sys, &mb_temp); set_sensors_from_table(sys, &front_temp); set_sensors_from_table(sys, &system_sensors); handle_eesense_data(sys); handle_ps_status(0); handle_ps_status(1); /* Check for shutdown thresholds */ if (switch_temp_sensor_valids[0]) temp = switch_temp_sensor_last_values[0]; if (switch_temp_sensor_valids[1] && temp < switch_temp_sensor_last_values[1]) temp = switch_temp_sensor_last_values[1]; if (temp >= SWITCH_TEMP_SHUTDOWN * 1000) { sys->log(sys, INFO, NULL, "CRITICAL: Switch has exceeded temperature" " threshold, powering down system"); power_down_system(sys); } temp = 0; for (i = 0; i < NUM_BOARDS; i++) { if (board_front_sensor_valids[0][i] && board_front_sensor_last_values[0][i] > temp) temp = board_front_sensor_last_values[0][i]; } if (temp >= FRONT_TEMP_SHUTDOWN * 1000) { sys->log(sys, INFO, NULL, "CRITICAL: External environment exceeded" " temperature threshold, raw value is %d, powering down" " system", temp); power_down_system(sys); } for (i = 0; i < NUM_BOARDS; i++) { temp = 0; if (board_temp_sensor_valids[0][i]) temp = board_temp_sensor_last_values[0][i]; if (board_temp_sensor_valids[1][i] && temp < board_temp_sensor_last_values[1][i]) temp = board_temp_sensor_last_values[1][i]; if (temp >= BOARD_TEMP_SHUTDOWN * 1000) { unsigned char val = 0; if (board_temp_sensor_last_oor[i]) { sys->log(sys, INFO, NULL, "CRITICAL: Board %d has exceeded" " temperature threshold, raw value is %d," " powering down", i + 1, temp); set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, &boards[i]); } else { sys->log(sys, INFO, NULL, "WARNING: Board %d has exceeded" " temperature threshold, raw value is %d," " will check again before shutdown", i + 1, temp); board_temp_sensor_last_oor[i]++; } } else board_temp_sensor_last_oor[i] = 0; if (boards[i].fru_data_ready_for_handling) { boards[i].fru_data_ready_for_handling = 0; handle_board_fru(sys, i); rv = ipmi_mc_fru_sem_post(boards[i].mc, 0); if (rv) sys->log(sys, OS_ERROR, NULL, "Error posting board %d semaphore: %s", i + 1, strerror(rv)); } } pthread_mutex_lock(&scan_mutex); pthread_cond_signal(&scan_cond); pthread_mutex_unlock(&scan_mutex); } /************************************************************************** * Marvell OEM commands. *************************************************************************/ struct fru_write_data { sys_data_t *sys; unsigned int num; }; /* * Writing FRU data is too slow to do in the main thread, so do it in * another thread. */ static void * fru_write_thread(void *cb_data) { struct fru_write_data *info = cb_data; sys_data_t *sys = info->sys; unsigned int num = info->num; unsigned char board_fru_data[2048]; int fd, rv; pthread_detach(pthread_self()); free(info); fd = open(BOARD_FRU_FILE, O_RDONLY); if (fd == -1) { sys->log(sys, OS_ERROR, NULL, "Unable to read board FRU file %s: %s", BOARD_FRU_FILE, strerror(errno)); } rv = read(fd, board_fru_data, sizeof(board_fru_data)); if (rv == -1) { sys->log(sys, OS_ERROR, NULL, "Unable to read board FRU file %s: %s", BOARD_FRU_FILE, strerror(errno)); goto out_err; } else if (rv != sizeof(board_fru_data)) { sys->log(sys, OS_ERROR, NULL, "board FRU file too small %s: %d", BOARD_FRU_FILE, rv); goto out_err; } rv = write_eeprom(&board_i2c[num].fru, board_fru_data, 0, sizeof(board_fru_data)); if (rv) { sys->log(sys, OS_ERROR, NULL, "Error writing board %d fru: %d", num, rv); goto out_err; } boards[num].fru_data_ready_for_handling = 1; return NULL; out_err: rv = ipmi_mc_fru_sem_post(boards[num].mc, 0); if (rv) sys->log(sys, OS_ERROR, NULL, "Error posting board %d semaphore: %s", num + 1, strerror(rv)); return NULL; } static void handle_marvell_cmd(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { sys_data_t *sys = cb_data; char cmd[100]; int rv; /* * Note that the calling function remove the IANA from the message * and inserts the IANA in the return message, we handle this like * a normal command. * * Start assuming success. */ rdata[0] = 0; *rdata_len = 1; switch (msg->cmd) { case DISABLE_NETWORK_SRVC_CMD: if (check_msg_length(msg, 1, rdata, rdata_len)) break; snprintf(cmd, sizeof(cmd), "/etc/ipmi/netsrvc %d\n", msg->data[0]); rv = system(cmd); if (rv == -1) { rdata[0] = 0xff; rdata[1] = errno; rdata[2] = 0; *rdata_len = 3; } else if (rv) { rdata[0] = 0xff; rdata[1] = 0; rdata[2] = rv; *rdata_len = 3; } break; case RELOAD_BOARD_FRU_CMD: { struct fru_write_data *info; pthread_t tid; unsigned int num; if (check_msg_length(msg, 1, rdata, rdata_len)) return; num = msg->data[0] - 1; if (num >= NUM_BOARDS) goto out_err; if (!boards[num].present) goto out_err; rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0); if (rv) { if (errno == EAGAIN) /* Already in progress. */ goto out_good; sys->log(sys, OS_ERROR, NULL, "Unable to claim board %d FRU semaphore: %s", num + 1, strerror(errno)); goto out_err; } info = malloc(sizeof(*info)); if (!info) goto out_err; info->sys = sys; info->num = num; rv = pthread_create(&tid, NULL, fru_write_thread, info); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to create fru write thread: %s", strerror(rv)); free(info); goto out_err; } } break; case SET_ALL_FANS_DUTY_CMD: { int duty; if (check_msg_length(msg, 1, rdata, rdata_len)) break; duty = msg->data[0]; if (duty == 0) ; /* Disable the duty by setting to zero */ else if (duty < 30) duty = 30; /* Minimum allowed fan duty */ else if (duty > 100) duty = 100; all_fans_duty = duty; } break; case GET_ALL_FANS_DUTY_CMD: rdata[1] = all_fans_duty; *rdata_len = 2; break; default: handle_invalid_cmd(mc, rdata, rdata_len); break; } out_good: return; out_err: rdata[0] = 0xff; } int ipmi_sim_module_print_version(sys_data_t *sys, char *initstr) { printf("IPMI Simulator Marvell AXP module version %s\n", PVERSION); return 0; } /* * An emulator command for simulating a change in the board's presence. */ static int simulate_board_presence(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned int board, present; const char *err; rv = get_uint(toks, &board, &err); if (!rv && ((board == 0 || board > NUM_BOARDS))) { err = "board number out of range"; rv = EINVAL; } if (rv) { out->eprintf(out, "Invalid board number: %s\n", err); return EINVAL; } board--; rv = get_bool(toks, &present, &err); if (rv) { out->eprintf(out, "Invalid board presence value: %s\n", err); return EINVAL; } simulate_board_absent[board] = !present; } /************************************************************************** * BMC reset handling *************************************************************************/ static void handle_cold_reset(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { sys_data_t *sys = cb_data; int rv; rv = set_intval(RESET_REASON_FILE, RESET_REASON_COLD_BOOT); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to write cold reset reason: %s", strerror(rv)); } system("reboot"); } static void handle_warm_reset(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { sys_data_t *sys = cb_data; int rv; rv = set_intval(RESET_REASON_FILE, RESET_REASON_WARM_BOOT); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to write warm reset reason: %s", strerror(rv)); } exit(1); } /* * This is a timer that is periodically called from the main thread, * it is basically used to tell if the main thread is running. */ static void wdt_test_timeout(void *cb_data) { struct timeval tv; sys_data_t *sys = cb_data; if (wdt_test_timer_ran) sys->log(sys, OS_ERROR, NULL, "MVMOD: WDT test timer not cleared"); wdt_test_timer_ran = 1; tv.tv_sec = 4; tv.tv_usec = 0; sys->start_timer(wdt_test_timer, &tv); } /************************************************************************** * Module initialization *************************************************************************/ int ipmi_sim_module_init(sys_data_t *sys, const char *initstr_i) { unsigned int num; int rv; const char *c; char *next; int use_events = 1; struct timeval tv; int power_up_force = 0; char *initstr = strdup(initstr_i); int val; printf("IPMI Simulator Marvell AXP module version %s\n", PVERSION); if (!initstr) { sys->log(sys, SETUP_ERROR, NULL, "Error: MV: Out of memory"); return ENOMEM; } c = mystrtok(initstr, " \t\n", &next); while (c) { if (strcmp(c, "noevents") == 0) { use_events = 0; } else if (strcmp(c, "fork") == 0) { fork_event_wait = 1; } else if (strncmp(c, "debug=", 6) == 0) { debug = strtoul(c + 6, NULL, 0); } else if (strcmp(c, "forcecold") == 0) { power_up_force = 1; } else if (strcmp(c, "forcewarm") == 0) { power_up_force = 1; cold_power_up = 0; } else if (strcmp(c, "disablewdt") == 0) { disable_wdt = 1; } else if (strncmp(c, "poll_time=", 10) == 0) { poll_time = strtoul(c + 10, NULL, 0); } else { sys->log(sys, SETUP_ERROR, NULL, "Warning: MV: Unknown init" " string: %s", c); } c = mystrtok(NULL, " \t\n", &next); } free(initstr); check_chassis_state(sys); rv = init_chassis(sys); if (rv) return rv; rv = pipe(scan_pipe); if (rv == -1) { int errval = errno; sys->log(sys, SETUP_ERROR, NULL, "MVMOD: Unable to open pipe"); return errval; } rv = sys->add_io_hnd(sys, scan_pipe[0], set_sensors_from_tables, sys, &scan_fd_id); if (rv) { int errval = errno; sys->log(sys, SETUP_ERROR, NULL, "MVMOD: Unable to add I/O handler"); close(scan_pipe[0]); close(scan_pipe[1]); return errval; } if (use_events) { ast_fd = open("/dev/event", O_RDWR); if (ast_fd == -1) { int errval = errno; sys->log(sys, SETUP_ERROR, NULL, "Unable to open /dev/event"); return errval; } if (fork_event_wait) { int pipefds[2]; rv = pipe(pipefds); if (rv == -1) { int errval = errno; close(ast_fd); sys->log(sys, SETUP_ERROR, NULL, "Unable to open pipe"); return errval; } rv = fork(); if (rv == -1) { int errval = errno; close(ast_fd); close(pipefds[0]); close(pipefds[1]); sys->log(sys, SETUP_ERROR, NULL, "Unable to fork"); return errval; } else if (rv != 0) { /* * Note that the main program runs as the child and * the shim program runs as the parent. This allows * the shim program to catch the SIGCHLD and terminate * if the main program goes away. Otherwise the shim * would be stuck waiting on an event and not * terminate properly. */ close(pipefds[0]); ast1300_shim(sys, ast_fd, pipefds[1], rv); } close(ast_fd); close(pipefds[1]); ast_fd = pipefds[0]; } rv = sys->add_io_hnd(sys, ast_fd, ast_evt, sys, &ast_fd_id); if (rv) { int errval = errno; sys->log(sys, SETUP_ERROR, NULL, "MVMOD: Unable to add I/O handler"); close(ast_fd); return errval; } } rv = sys->alloc_timer(sys, mv_timeout, sys, &mv_timer); if (rv) { int errval = errno; sys->log(sys, SETUP_ERROR, NULL, "MVMOD: Unable to create timer"); return errval; } else { tv.tv_sec = 1; tv.tv_usec = 0; sys->start_timer(mv_timer, &tv); } rv = sys->alloc_timer(sys, board_power_timeout, sys, &power_timer); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to allocate board power timer: %s", strerror(rv)); return rv; } if (!power_up_force) { rv = get_uintval(COLD_POWER_UP_IO, &cold_power_up); if (rv) { sys->log(sys, OS_ERROR, NULL, "Warning: MV: Could not read %s" " so assuming cold power up: %s", COLD_POWER_UP_IO, strerror(errno)); cold_power_up = 1; } else if (cold_power_up) { /* Save the setting in case we fail in startup */ set_intval(COLD_POWER_FILE, 1); } else { /* * Get the setting from the last startup. If it's not * there, no big deal. */ get_uintval(COLD_POWER_FILE, &cold_power_up); } } rv = sys->mc_alloc_unconfigured(sys, 0x20, &bmc_mc); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to allocate an mc: %s", strerror(rv)); return rv; } for (num = 0; num < NUM_BOARDS; num++) { lmc_data_t *mc; unsigned int rval = 0; struct board_info *board = &boards[num]; board->num = num; board->sys = sys; board->last_power_request = BOARD_OFF_READY; if (!cold_power_up) { /* * On a cold power up, we bring everything up that is * present. Otherwise we run this code to read the * current status and retain that. */ rv = get_uintval(trg_present[num], &rval); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to read board %u presence state: %s", num, strerror(rv)); return rv; } if (rval != BOARD_PRESENT) { unsigned char val = 0; set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board); } else if (board_power_state(sys, num)) { /* * This looks a bit unusual, so I will explain. The * board power request is only handled on a off-to-on * transition, the raw values is not used directly. * But this presents an issue at startup: what if the * board requested a power off while this code wasn't * running? To solve that, if it is not a cold power * up, assume that the request is off and then we will * power down if the request is asserted. */ board->last_power_request = BOARD_OFF_NOT_READY; } } rv = sys->mc_alloc_unconfigured(sys, board_ipmb[num], &mc); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to allocate an mc: %s", strerror(rv)); return rv; } boards[num].mc = mc; ipmi_mc_set_chassis_control_func(mc, set_chassis_control, get_chassis_control, board); rv = check_board(sys, num, 0, cold_power_up); if (rv) { if (ast_fd_id) sys->remove_io_hnd(ast_fd_id); if (mv_timer) sys->free_timer(mv_timer); return rv; } } ipmi_mc_set_chassis_control_func(bmc_mc, bmc_set_chassis_control, bmc_get_chassis_control, sys); rv = ipmi_emu_register_iana_handler(MARVELL_SEMI_ISREAL_IANA, handle_marvell_cmd, sys); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to register Marvell IANA handler: %s", strerror(rv)); } rv = ipmi_emu_register_cmd_handler(IPMI_APP_NETFN, IPMI_COLD_RESET_CMD, handle_cold_reset, sys); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to register cold reset handler: %s", strerror(rv)); } rv = ipmi_emu_register_cmd_handler(IPMI_APP_NETFN, IPMI_WARM_RESET_CMD, handle_warm_reset, sys); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to register cold reset handler: %s", strerror(rv)); } if (!disable_wdt) { wdt_fd = open("/dev/watchdog", O_WRONLY); if (wdt_fd == -1) { sys->log(sys, OS_ERROR, NULL, "Unable to open wdt: %s", strerror(errno)); return rv; } rv = sys->alloc_timer(sys, wdt_test_timeout, sys, &wdt_test_timer); if (rv) { sys->log(sys, OS_ERROR, NULL, "Unable to allocate wdt test timer: %s", strerror(rv)); return rv; } tv.tv_sec = 4; tv.tv_usec = 0; sys->start_timer(wdt_test_timer, &tv); } if (!cold_power_up) init_complete = 1; ipmi_emu_add_cmd("simulate_board_presence", NOMC, simulate_board_presence); return 0; } int ipmi_sim_module_post_init(sys_data_t *sys) { int rv; const char *ver = get_lanserv_version(); unsigned char lver[4]; unsigned char omajor, ominor, orel; unsigned int i; int val; sscanf(ver, "%hhu.%hhu.%hhu", lver + 0, lver + 1, lver + 2); lver[3] = 0; sscanf(PVERSION, "%hhu.%hhu.%hhu", &omajor, &ominor, &orel); for (i = 0; i < NUM_BOARDS; i++) { ipmi_mc_set_fw_revision(boards[i].mc, omajor, ominor << 4 | orel); ipmi_mc_set_aux_fw_revision(boards[i].mc, lver); } ipmi_mc_set_fw_revision(bmc_mc, omajor, ominor << 4 | orel); ipmi_mc_set_aux_fw_revision(bmc_mc, lver); /* * Set the rearm handler for the CPU and DIMM sensors to clear * them on rearm. */ for (i = 0; i < NUM_BOARDS; i++) { struct eesense_rearm *info; info = malloc(sizeof(*info)); if (!info) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to allocate eesense handler for board %d: " "Out of memory", i + 1); continue; } info->num = i; info->offset = 1; info->mask = 0x01; rv = ipmi_mc_sensor_add_rearm_handler(boards[i].mc, 0, 20, rearm_eesense_sensor, info); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Error adding eesense CPU rearm on %d: %s", i + 1, strerror(rv)); continue; } info = malloc(sizeof(*info)); if (!info) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to allocate eesense handler for board %d: " "Out of memory", i + 1); continue; } info->num = i; info->offset = 2; info->mask = 0x87; rv = ipmi_mc_sensor_add_rearm_handler(boards[i].mc, 0, 21, rearm_eesense_sensor, info); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Error adding eesense DIMM rearm on %d: %s", i + 1, strerror(rv)); } } rv = ipmi_mc_sensor_add_rearm_handler(bmc_mc, 0, 8, rearm_power_supply_sensor, (void *) 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Error adding power supply %d rearm: %s", 1, strerror(rv)); } rv = ipmi_mc_sensor_add_rearm_handler(bmc_mc, 0, 9, rearm_power_supply_sensor, (void *) 2); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Error adding power supply %d rearm: %s", 2, strerror(rv)); } /* Initial state of the PSU sensor is with the present bit set */ ipmi_mc_sensor_set_bit(bmc_mc, 0, 8, 0, 1, 0); ipmi_mc_sensor_set_bit(bmc_mc, 0, 9, 0, 1, 0); rv = pthread_create(&scan_thread, NULL, scan_sensors, sys); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to start scan thread: %s", strerror(rv)); } rv = get_intval(RESET_REASON_FILE, &val); if (rv || cold_power_up) { val = 0x00; /* Initiated by power up */ } else if (val == RESET_REASON_COLD_BOOT || rv || val == RESET_REASON_UNKNOWN) { val = 0x01; /* Initiated by hard reset */ } else if (val == RESET_REASON_WARM_BOOT) { val = 0x02; /* Initiated by warm reset */ } else { sys->log(sys, OS_ERROR, NULL, "MVMOD: known reset reason: %d", val); val = 0x01; /* Assume hard reset */ } { /* * We don't have an actual sensor for this, since it is * event-only, just send the event. */ unsigned char data[13]; memset(data, 0, sizeof(data)); data[4] = sys->mc_get_ipmb(bmc_mc); data[5] = 0; /* LUN */ data[6] = 0x04; /* Event message revision for IPMI 1.5. */ data[7] = 0x1d; /* System boot initiated. */ data[8] = 20; /* Sensor num */ data[9] = (IPMI_ASSERTION << 7) | 0x6f; data[10] = val; mc_new_event(bmc_mc, 0x02, data); } rv = set_intval(RESET_REASON_FILE, 0); if (rv) { sys->log(sys, OS_ERROR, NULL, "MVMOD: Unable to clear reset reason: %s", strerror(rv)); } return rv; } OpenIPMI-2.0.33/lanserv/marvell-bmc/busybox-1.18.4.config0000644000175000017500000006347412116456523017407 00000000000000# # Automatically generated make config: don't edit # Busybox version: 1.18.4 # Thu Jan 10 21:53:35 2013 # CONFIG_HAVE_DOT_CONFIG=y # # Busybox Settings # # # General Configuration # CONFIG_DESKTOP=y # CONFIG_EXTRA_COMPAT is not set CONFIG_INCLUDE_SUSv2=y # CONFIG_USE_PORTABLE_CODE is not set CONFIG_PLATFORM_LINUX=y CONFIG_FEATURE_BUFFERS_USE_MALLOC=y # CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_SHOW_USAGE=y CONFIG_FEATURE_VERBOSE_USAGE=y # CONFIG_FEATURE_COMPRESS_USAGE is not set CONFIG_FEATURE_INSTALLER=y # CONFIG_INSTALL_NO_USR is not set # CONFIG_LOCALE_SUPPORT is not set # CONFIG_UNICODE_SUPPORT is not set # CONFIG_UNICODE_USING_LOCALE is not set # CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set CONFIG_SUBST_WCHAR=0 CONFIG_LAST_SUPPORTED_WCHAR=0 # CONFIG_UNICODE_COMBINING_WCHARS is not set # CONFIG_UNICODE_WIDE_WCHARS is not set # CONFIG_UNICODE_BIDI_SUPPORT is not set # CONFIG_UNICODE_NEUTRAL_TABLE is not set # CONFIG_UNICODE_PRESERVE_BROKEN is not set CONFIG_LONG_OPTS=y CONFIG_FEATURE_DEVPTS=y CONFIG_FEATURE_CLEAN_UP=y CONFIG_FEATURE_WTMP=y CONFIG_FEATURE_UTMP=y # CONFIG_FEATURE_PIDFILE is not set CONFIG_FEATURE_SUID=y # CONFIG_FEATURE_SUID_CONFIG is not set # CONFIG_FEATURE_SUID_CONFIG_QUIET is not set # CONFIG_SELINUX is not set # CONFIG_FEATURE_PREFER_APPLETS is not set CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" CONFIG_FEATURE_SYSLOG=y CONFIG_FEATURE_HAVE_RPC=y # # Build Options # # CONFIG_STATIC is not set # CONFIG_PIE is not set # CONFIG_NOMMU is not set # CONFIG_BUILD_LIBBUSYBOX is not set # CONFIG_FEATURE_INDIVIDUAL is not set # CONFIG_FEATURE_SHARED_BUSYBOX is not set CONFIG_LFS=y CONFIG_CROSS_COMPILER_PREFIX="" CONFIG_EXTRA_CFLAGS="" # # Debugging Options # # CONFIG_DEBUG is not set # CONFIG_DEBUG_PESSIMIZE is not set # CONFIG_WERROR is not set CONFIG_NO_DEBUG_LIB=y # CONFIG_DMALLOC is not set # CONFIG_EFENCE is not set # # Installation Options ("make install" behavior) # CONFIG_INSTALL_APPLET_SYMLINKS=y # CONFIG_INSTALL_APPLET_HARDLINKS is not set # CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set # CONFIG_INSTALL_APPLET_DONT is not set # CONFIG_INSTALL_SH_APPLET_SYMLINK is not set # CONFIG_INSTALL_SH_APPLET_HARDLINK is not set # CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set CONFIG_PREFIX="./_install" # # Busybox Library Tuning # CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SIZE_VS_SPEED=2 # CONFIG_FEATURE_FAST_TOP is not set # CONFIG_FEATURE_ETC_NETWORKS is not set CONFIG_FEATURE_USE_TERMIOS=y CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 CONFIG_FEATURE_EDITING_VI=y CONFIG_FEATURE_EDITING_HISTORY=999 CONFIG_FEATURE_EDITING_SAVEHISTORY=y CONFIG_FEATURE_TAB_COMPLETION=y # CONFIG_FEATURE_USERNAME_COMPLETION is not set CONFIG_FEATURE_EDITING_FANCY_PROMPT=y # CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set CONFIG_FEATURE_NON_POSIX_CP=y # CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set CONFIG_FEATURE_COPYBUF_KB=4 CONFIG_MONOTONIC_SYSCALL=y CONFIG_IOCTL_HEX2STR_ERROR=y CONFIG_FEATURE_HWIB=y # # Applets # # # Archival Utilities # # CONFIG_FEATURE_SEAMLESS_XZ is not set # CONFIG_FEATURE_SEAMLESS_LZMA is not set # CONFIG_FEATURE_SEAMLESS_BZ2 is not set # CONFIG_FEATURE_SEAMLESS_GZ is not set # CONFIG_FEATURE_SEAMLESS_Z is not set CONFIG_AR=y # CONFIG_FEATURE_AR_LONG_FILENAMES is not set CONFIG_FEATURE_AR_CREATE=y CONFIG_BUNZIP2=y # CONFIG_BZIP2 is not set CONFIG_CPIO=y # CONFIG_FEATURE_CPIO_O is not set # CONFIG_FEATURE_CPIO_P is not set # CONFIG_DPKG is not set # CONFIG_DPKG_DEB is not set # CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set CONFIG_GUNZIP=y CONFIG_GZIP=y # CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set # CONFIG_LZOP is not set # CONFIG_LZOP_COMPR_HIGH is not set # CONFIG_RPM2CPIO is not set # CONFIG_RPM is not set CONFIG_TAR=y CONFIG_FEATURE_TAR_CREATE=y # CONFIG_FEATURE_TAR_AUTODETECT is not set CONFIG_FEATURE_TAR_FROM=y # CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set # CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y CONFIG_FEATURE_TAR_LONG_OPTIONS=y CONFIG_FEATURE_TAR_TO_COMMAND=y # CONFIG_FEATURE_TAR_UNAME_GNAME is not set # CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set # CONFIG_FEATURE_TAR_SELINUX is not set # CONFIG_UNCOMPRESS is not set CONFIG_UNLZMA=y # CONFIG_FEATURE_LZMA_FAST is not set CONFIG_LZMA=y CONFIG_UNXZ=y CONFIG_XZ=y CONFIG_UNZIP=y # # Coreutils # CONFIG_BASENAME=y CONFIG_CAT=y CONFIG_DATE=y CONFIG_FEATURE_DATE_ISOFMT=y # CONFIG_FEATURE_DATE_NANO is not set CONFIG_FEATURE_DATE_COMPAT=y CONFIG_TEST=y CONFIG_FEATURE_TEST_64=y CONFIG_TR=y CONFIG_FEATURE_TR_CLASSES=y CONFIG_FEATURE_TR_EQUIV=y # CONFIG_BASE64 is not set # CONFIG_CAL is not set CONFIG_CATV=y CONFIG_CHGRP=y CONFIG_CHMOD=y CONFIG_CHOWN=y # CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set CONFIG_CHROOT=y CONFIG_CKSUM=y # CONFIG_COMM is not set CONFIG_CP=y # CONFIG_FEATURE_CP_LONG_OPTIONS is not set CONFIG_CUT=y CONFIG_DD=y CONFIG_FEATURE_DD_SIGNAL_HANDLING=y # CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set CONFIG_FEATURE_DD_IBS_OBS=y CONFIG_DF=y # CONFIG_FEATURE_DF_FANCY is not set CONFIG_DIRNAME=y CONFIG_DOS2UNIX=y CONFIG_UNIX2DOS=y CONFIG_DU=y CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y CONFIG_ECHO=y CONFIG_FEATURE_FANCY_ECHO=y CONFIG_ENV=y # CONFIG_FEATURE_ENV_LONG_OPTIONS is not set # CONFIG_EXPAND is not set # CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set CONFIG_EXPR=y CONFIG_EXPR_MATH_SUPPORT_64=y CONFIG_FALSE=y CONFIG_FOLD=y # CONFIG_FSYNC is not set CONFIG_HEAD=y CONFIG_FEATURE_FANCY_HEAD=y CONFIG_HOSTID=y CONFIG_ID=y CONFIG_INSTALL=y CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y CONFIG_LENGTH=y CONFIG_LN=y CONFIG_LOGNAME=y CONFIG_LS=y CONFIG_FEATURE_LS_FILETYPES=y CONFIG_FEATURE_LS_FOLLOWLINKS=y CONFIG_FEATURE_LS_RECURSIVE=y CONFIG_FEATURE_LS_SORTFILES=y CONFIG_FEATURE_LS_TIMESTAMPS=y CONFIG_FEATURE_LS_USERNAME=y CONFIG_FEATURE_LS_COLOR=y CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y CONFIG_MD5SUM=y CONFIG_MKDIR=y CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y CONFIG_MKFIFO=y CONFIG_MKNOD=y CONFIG_MV=y CONFIG_FEATURE_MV_LONG_OPTIONS=y CONFIG_NICE=y CONFIG_NOHUP=y CONFIG_OD=y CONFIG_PRINTENV=y CONFIG_PRINTF=y CONFIG_PWD=y CONFIG_READLINK=y CONFIG_FEATURE_READLINK_FOLLOW=y CONFIG_REALPATH=y CONFIG_RM=y CONFIG_RMDIR=y # CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set CONFIG_SEQ=y CONFIG_SHA1SUM=y CONFIG_SHA256SUM=y CONFIG_SHA512SUM=y CONFIG_SLEEP=y # CONFIG_FEATURE_FANCY_SLEEP is not set # CONFIG_FEATURE_FLOAT_SLEEP is not set CONFIG_SORT=y CONFIG_FEATURE_SORT_BIG=y # CONFIG_SPLIT is not set # CONFIG_FEATURE_SPLIT_FANCY is not set # CONFIG_STAT is not set # CONFIG_FEATURE_STAT_FORMAT is not set CONFIG_STTY=y # CONFIG_SUM is not set CONFIG_SYNC=y # CONFIG_TAC is not set CONFIG_TAIL=y CONFIG_FEATURE_FANCY_TAIL=y CONFIG_TEE=y CONFIG_FEATURE_TEE_USE_BLOCK_IO=y CONFIG_TOUCH=y CONFIG_TRUE=y CONFIG_TTY=y CONFIG_UNAME=y # CONFIG_UNEXPAND is not set # CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set CONFIG_UNIQ=y CONFIG_USLEEP=y CONFIG_UUDECODE=y CONFIG_UUENCODE=y CONFIG_WC=y # CONFIG_FEATURE_WC_LARGE is not set CONFIG_WHO=y CONFIG_WHOAMI=y CONFIG_YES=y # # Common options for cp and mv # CONFIG_FEATURE_PRESERVE_HARDLINKS=y # # Common options for ls, more and telnet # CONFIG_FEATURE_AUTOWIDTH=y # # Common options for df, du, ls # CONFIG_FEATURE_HUMAN_READABLE=y # # Common options for md5sum, sha1sum, sha256sum, sha512sum # CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y # # Console Utilities # CONFIG_CHVT=y # CONFIG_FGCONSOLE is not set CONFIG_CLEAR=y CONFIG_DEALLOCVT=y CONFIG_DUMPKMAP=y # CONFIG_KBD_MODE is not set CONFIG_LOADFONT=y CONFIG_LOADKMAP=y CONFIG_OPENVT=y CONFIG_RESET=y CONFIG_RESIZE=y CONFIG_FEATURE_RESIZE_PRINT=y CONFIG_SETCONSOLE=y # CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set # CONFIG_SETFONT is not set # CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set CONFIG_DEFAULT_SETFONT_DIR="" CONFIG_SETKEYCODES=y CONFIG_SETLOGCONS=y # CONFIG_SHOWKEY is not set # # Common options for loadfont and setfont # CONFIG_FEATURE_LOADFONT_PSF2=y CONFIG_FEATURE_LOADFONT_RAW=y # # Debian Utilities # CONFIG_MKTEMP=y CONFIG_PIPE_PROGRESS=y CONFIG_RUN_PARTS=y CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y # CONFIG_FEATURE_RUN_PARTS_FANCY is not set CONFIG_START_STOP_DAEMON=y CONFIG_FEATURE_START_STOP_DAEMON_FANCY=y CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS=y CONFIG_WHICH=y # # Editors # CONFIG_PATCH=y CONFIG_AWK=y # CONFIG_FEATURE_AWK_LIBM is not set CONFIG_CMP=y CONFIG_DIFF=y # CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set CONFIG_FEATURE_DIFF_DIR=y # CONFIG_ED is not set CONFIG_SED=y CONFIG_VI=y CONFIG_FEATURE_VI_MAX_LEN=4096 CONFIG_FEATURE_VI_8BIT=y CONFIG_FEATURE_VI_COLON=y CONFIG_FEATURE_VI_YANKMARK=y CONFIG_FEATURE_VI_SEARCH=y CONFIG_FEATURE_VI_USE_SIGNALS=y CONFIG_FEATURE_VI_DOT_CMD=y CONFIG_FEATURE_VI_READONLY=y CONFIG_FEATURE_VI_SETOPTS=y CONFIG_FEATURE_VI_SET=y CONFIG_FEATURE_VI_WIN_RESIZE=y CONFIG_FEATURE_VI_ASK_TERMINAL=y CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y CONFIG_FEATURE_ALLOW_EXEC=y # # Finding Utilities # CONFIG_FIND=y CONFIG_FEATURE_FIND_PRINT0=y CONFIG_FEATURE_FIND_MTIME=y CONFIG_FEATURE_FIND_MMIN=y CONFIG_FEATURE_FIND_PERM=y CONFIG_FEATURE_FIND_TYPE=y CONFIG_FEATURE_FIND_XDEV=y CONFIG_FEATURE_FIND_MAXDEPTH=y CONFIG_FEATURE_FIND_NEWER=y # CONFIG_FEATURE_FIND_INUM is not set CONFIG_FEATURE_FIND_EXEC=y CONFIG_FEATURE_FIND_USER=y CONFIG_FEATURE_FIND_GROUP=y CONFIG_FEATURE_FIND_NOT=y CONFIG_FEATURE_FIND_DEPTH=y CONFIG_FEATURE_FIND_PAREN=y CONFIG_FEATURE_FIND_SIZE=y CONFIG_FEATURE_FIND_PRUNE=y # CONFIG_FEATURE_FIND_DELETE is not set CONFIG_FEATURE_FIND_PATH=y CONFIG_FEATURE_FIND_REGEX=y # CONFIG_FEATURE_FIND_CONTEXT is not set # CONFIG_FEATURE_FIND_LINKS is not set CONFIG_GREP=y CONFIG_FEATURE_GREP_EGREP_ALIAS=y CONFIG_FEATURE_GREP_FGREP_ALIAS=y CONFIG_FEATURE_GREP_CONTEXT=y CONFIG_XARGS=y # CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y # # Init Utilities # # CONFIG_BOOTCHARTD is not set # CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set # CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set CONFIG_HALT=y # CONFIG_FEATURE_CALL_TELINIT is not set CONFIG_TELINIT_PATH="" CONFIG_INIT=y CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_REMOVED=y CONFIG_FEATURE_KILL_DELAY=0 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y CONFIG_FEATURE_EXTRA_QUIET=y # CONFIG_FEATURE_INIT_COREDUMPS is not set CONFIG_FEATURE_INITRD=y CONFIG_INIT_TERMINAL_TYPE="linux" CONFIG_MESG=y # # Login/Password Management Utilities # # CONFIG_ADD_SHELL is not set # CONFIG_REMOVE_SHELL is not set CONFIG_FEATURE_SHADOWPASSWDS=y # CONFIG_USE_BB_PWD_GRP is not set # CONFIG_USE_BB_SHADOW is not set CONFIG_USE_BB_CRYPT=y # CONFIG_USE_BB_CRYPT_SHA is not set CONFIG_ADDUSER=y # CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set # CONFIG_FEATURE_CHECK_NAMES is not set CONFIG_FIRST_SYSTEM_ID=100 CONFIG_LAST_SYSTEM_ID=999 CONFIG_ADDGROUP=y # CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set # CONFIG_FEATURE_ADDUSER_TO_GROUP is not set CONFIG_DELUSER=y CONFIG_DELGROUP=y # CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set CONFIG_GETTY=y CONFIG_LOGIN=y # CONFIG_PAM is not set # CONFIG_LOGIN_SCRIPTS is not set CONFIG_FEATURE_NOLOGIN=y CONFIG_FEATURE_SECURETTY=y CONFIG_PASSWD=y CONFIG_FEATURE_PASSWD_WEAK_CHECK=y # CONFIG_CRYPTPW is not set # CONFIG_CHPASSWD is not set CONFIG_SU=y CONFIG_FEATURE_SU_SYSLOG=y CONFIG_FEATURE_SU_CHECKS_SHELLS=y CONFIG_SULOGIN=y CONFIG_VLOCK=y # # Linux Ext2 FS Progs # CONFIG_CHATTR=y CONFIG_FSCK=y CONFIG_LSATTR=y # CONFIG_TUNE2FS is not set # # Linux Module Utilities # # CONFIG_MODINFO is not set # CONFIG_MODPROBE_SMALL is not set # CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set # CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set CONFIG_INSMOD=y CONFIG_RMMOD=y CONFIG_LSMOD=y CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y CONFIG_MODPROBE=y # CONFIG_FEATURE_MODPROBE_BLACKLIST is not set # CONFIG_DEPMOD is not set # # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set # CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set CONFIG_FEATURE_CHECK_TAINTED_MODULE=y CONFIG_FEATURE_MODUTILS_ALIAS=y CONFIG_FEATURE_MODUTILS_SYMBOLS=y CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" # # Linux System Utilities # # CONFIG_BLOCKDEV is not set # CONFIG_REV is not set # CONFIG_ACPID is not set # CONFIG_FEATURE_ACPID_COMPAT is not set # CONFIG_BLKID is not set CONFIG_DMESG=y CONFIG_FEATURE_DMESG_PRETTY=y # CONFIG_FBSET is not set # CONFIG_FEATURE_FBSET_FANCY is not set # CONFIG_FEATURE_FBSET_READMODE is not set CONFIG_FDFLUSH=y CONFIG_FDFORMAT=y # CONFIG_FDISK is not set CONFIG_FDISK_SUPPORT_LARGE_DISKS=y # CONFIG_FEATURE_FDISK_WRITABLE is not set # CONFIG_FEATURE_AIX_LABEL is not set # CONFIG_FEATURE_SGI_LABEL is not set # CONFIG_FEATURE_SUN_LABEL is not set # CONFIG_FEATURE_OSF_LABEL is not set # CONFIG_FEATURE_GPT_LABEL is not set # CONFIG_FEATURE_FDISK_ADVANCED is not set # CONFIG_FINDFS is not set # CONFIG_FLOCK is not set CONFIG_FREERAMDISK=y # CONFIG_FSCK_MINIX is not set # CONFIG_MKFS_EXT2 is not set # CONFIG_MKFS_MINIX is not set # CONFIG_FEATURE_MINIX2 is not set # CONFIG_MKFS_REISER is not set # CONFIG_MKFS_VFAT is not set CONFIG_GETOPT=y CONFIG_FEATURE_GETOPT_LONG=y CONFIG_HEXDUMP=y # CONFIG_FEATURE_HEXDUMP_REVERSE is not set # CONFIG_HD is not set CONFIG_HWCLOCK=y CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS=y CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y CONFIG_IPCRM=y CONFIG_IPCS=y CONFIG_LOSETUP=y CONFIG_LSPCI=y CONFIG_LSUSB=y CONFIG_MDEV=y CONFIG_FEATURE_MDEV_CONF=y # CONFIG_FEATURE_MDEV_RENAME is not set # CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set CONFIG_FEATURE_MDEV_EXEC=y # CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set CONFIG_MKSWAP=y # CONFIG_FEATURE_MKSWAP_UUID is not set CONFIG_MORE=y CONFIG_MOUNT=y # CONFIG_FEATURE_MOUNT_FAKE is not set # CONFIG_FEATURE_MOUNT_VERBOSE is not set # CONFIG_FEATURE_MOUNT_HELPERS is not set # CONFIG_FEATURE_MOUNT_LABEL is not set CONFIG_FEATURE_MOUNT_NFS=y CONFIG_FEATURE_MOUNT_CIFS=y CONFIG_FEATURE_MOUNT_FLAGS=y CONFIG_FEATURE_MOUNT_FSTAB=y CONFIG_PIVOT_ROOT=y CONFIG_RDATE=y # CONFIG_RDEV is not set CONFIG_READPROFILE=y # CONFIG_RTCWAKE is not set # CONFIG_SCRIPT is not set # CONFIG_SCRIPTREPLAY is not set CONFIG_SETARCH=y CONFIG_SWAPONOFF=y # CONFIG_FEATURE_SWAPON_PRI is not set CONFIG_SWITCH_ROOT=y CONFIG_UMOUNT=y CONFIG_FEATURE_UMOUNT_ALL=y # # Common options for mount/umount # CONFIG_FEATURE_MOUNT_LOOP=y CONFIG_FEATURE_MOUNT_LOOP_CREATE=y # CONFIG_FEATURE_MTAB_SUPPORT is not set # CONFIG_VOLUMEID is not set # CONFIG_FEATURE_VOLUMEID_EXT is not set # CONFIG_FEATURE_VOLUMEID_BTRFS is not set # CONFIG_FEATURE_VOLUMEID_REISERFS is not set # CONFIG_FEATURE_VOLUMEID_FAT is not set # CONFIG_FEATURE_VOLUMEID_HFS is not set # CONFIG_FEATURE_VOLUMEID_JFS is not set # CONFIG_FEATURE_VOLUMEID_XFS is not set # CONFIG_FEATURE_VOLUMEID_NTFS is not set # CONFIG_FEATURE_VOLUMEID_ISO9660 is not set # CONFIG_FEATURE_VOLUMEID_UDF is not set # CONFIG_FEATURE_VOLUMEID_LUKS is not set # CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set # CONFIG_FEATURE_VOLUMEID_CRAMFS is not set # CONFIG_FEATURE_VOLUMEID_ROMFS is not set # CONFIG_FEATURE_VOLUMEID_SYSV is not set # CONFIG_FEATURE_VOLUMEID_OCFS2 is not set # CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set # # Miscellaneous Utilities # # CONFIG_CONSPY is not set # CONFIG_NANDWRITE is not set # CONFIG_NANDDUMP is not set # CONFIG_UBIATTACH is not set # CONFIG_UBIDETACH is not set # CONFIG_ADJTIMEX is not set # CONFIG_BBCONFIG is not set # CONFIG_FEATURE_COMPRESS_BBCONFIG is not set # CONFIG_BEEP is not set CONFIG_FEATURE_BEEP_FREQ=0 CONFIG_FEATURE_BEEP_LENGTH_MS=0 # CONFIG_CHAT is not set # CONFIG_FEATURE_CHAT_NOFAIL is not set # CONFIG_FEATURE_CHAT_TTY_HIFI is not set # CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set # CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set # CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set # CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set # CONFIG_FEATURE_CHAT_CLR_ABORT is not set CONFIG_CHRT=y CONFIG_CROND=y # CONFIG_FEATURE_CROND_D is not set # CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set CONFIG_FEATURE_CROND_DIR="/var/spool/cron" CONFIG_CRONTAB=y CONFIG_DC=y # CONFIG_FEATURE_DC_LIBM is not set # CONFIG_DEVFSD is not set # CONFIG_DEVFSD_MODLOAD is not set # CONFIG_DEVFSD_FG_NP is not set # CONFIG_DEVFSD_VERBOSE is not set # CONFIG_FEATURE_DEVFS is not set CONFIG_DEVMEM=y CONFIG_EJECT=y # CONFIG_FEATURE_EJECT_SCSI is not set # CONFIG_FBSPLASH is not set # CONFIG_FLASHCP is not set # CONFIG_FLASH_LOCK is not set # CONFIG_FLASH_UNLOCK is not set # CONFIG_FLASH_ERASEALL is not set # CONFIG_IONICE is not set # CONFIG_INOTIFYD is not set CONFIG_LAST=y CONFIG_FEATURE_LAST_SMALL=y # CONFIG_FEATURE_LAST_FANCY is not set CONFIG_LESS=y CONFIG_FEATURE_LESS_MAXLINES=9999999 CONFIG_FEATURE_LESS_BRACKETS=y CONFIG_FEATURE_LESS_FLAGS=y # CONFIG_FEATURE_LESS_MARKS is not set CONFIG_FEATURE_LESS_REGEXP=y # CONFIG_FEATURE_LESS_WINCH is not set # CONFIG_FEATURE_LESS_DASHCMD is not set # CONFIG_FEATURE_LESS_LINENUMS is not set CONFIG_HDPARM=y CONFIG_FEATURE_HDPARM_GET_IDENTITY=y # CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set # CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set # CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set # CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set # CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set CONFIG_MAKEDEVS=y # CONFIG_FEATURE_MAKEDEVS_LEAF is not set CONFIG_FEATURE_MAKEDEVS_TABLE=y # CONFIG_MAN is not set CONFIG_MICROCOM=y CONFIG_MOUNTPOINT=y CONFIG_MT=y # CONFIG_RAIDAUTORUN is not set # CONFIG_READAHEAD is not set # CONFIG_RFKILL is not set CONFIG_RUNLEVEL=y # CONFIG_RX is not set CONFIG_SETSID=y CONFIG_STRINGS=y # CONFIG_TASKSET is not set # CONFIG_FEATURE_TASKSET_FANCY is not set CONFIG_TIME=y # CONFIG_TIMEOUT is not set # CONFIG_TTYSIZE is not set # CONFIG_VOLNAME is not set # CONFIG_WALL is not set CONFIG_WATCHDOG=y # # Networking Utilities # # CONFIG_NBDCLIENT is not set # CONFIG_NC is not set # CONFIG_NC_SERVER is not set # CONFIG_NC_EXTRA is not set # CONFIG_NC_110_COMPAT is not set CONFIG_FEATURE_IPV6=y # CONFIG_FEATURE_UNIX_LOCAL is not set # CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set # CONFIG_VERBOSE_RESOLUTION_ERRORS is not set CONFIG_ARP=y CONFIG_ARPING=y # CONFIG_BRCTL is not set # CONFIG_FEATURE_BRCTL_FANCY is not set # CONFIG_FEATURE_BRCTL_SHOW is not set CONFIG_DNSD=y CONFIG_ETHER_WAKE=y # CONFIG_FAKEIDENTD is not set # CONFIG_FTPD is not set # CONFIG_FEATURE_FTP_WRITE is not set # CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set # CONFIG_FTPGET is not set # CONFIG_FTPPUT is not set # CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set CONFIG_HOSTNAME=y # CONFIG_HTTPD is not set # CONFIG_FEATURE_HTTPD_RANGES is not set # CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set # CONFIG_FEATURE_HTTPD_SETUID is not set # CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set # CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set # CONFIG_FEATURE_HTTPD_CGI is not set # CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set # CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set # CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set # CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set # CONFIG_FEATURE_HTTPD_PROXY is not set # CONFIG_FEATURE_HTTPD_GZIP is not set CONFIG_IFCONFIG=y CONFIG_FEATURE_IFCONFIG_STATUS=y CONFIG_FEATURE_IFCONFIG_SLIP=y CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y CONFIG_FEATURE_IFCONFIG_HW=y # CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set # CONFIG_IFENSLAVE is not set # CONFIG_IFPLUGD is not set CONFIG_IFUPDOWN=y CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate" CONFIG_FEATURE_IFUPDOWN_IP=y # CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set # CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set CONFIG_FEATURE_IFUPDOWN_IPV4=y CONFIG_FEATURE_IFUPDOWN_IPV6=y CONFIG_FEATURE_IFUPDOWN_MAPPING=y # CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set CONFIG_INETD=y CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO=y CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD=y CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME=y CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME=y CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN=y # CONFIG_FEATURE_INETD_RPC is not set CONFIG_IP=y CONFIG_FEATURE_IP_ADDRESS=y CONFIG_FEATURE_IP_LINK=y CONFIG_FEATURE_IP_ROUTE=y CONFIG_FEATURE_IP_TUNNEL=y CONFIG_FEATURE_IP_RULE=y CONFIG_FEATURE_IP_SHORT_FORMS=y # CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set CONFIG_IPADDR=y CONFIG_IPLINK=y CONFIG_IPROUTE=y CONFIG_IPTUNNEL=y CONFIG_IPRULE=y # CONFIG_IPCALC is not set # CONFIG_FEATURE_IPCALC_FANCY is not set # CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set CONFIG_NAMEIF=y # CONFIG_FEATURE_NAMEIF_EXTENDED is not set CONFIG_NETSTAT=y # CONFIG_FEATURE_NETSTAT_WIDE is not set # CONFIG_FEATURE_NETSTAT_PRG is not set CONFIG_NSLOOKUP=y # CONFIG_NTPD is not set # CONFIG_FEATURE_NTPD_SERVER is not set CONFIG_PING=y # CONFIG_PING6 is not set CONFIG_FEATURE_FANCY_PING=y # CONFIG_PSCAN is not set CONFIG_ROUTE=y # CONFIG_SLATTACH is not set # CONFIG_TCPSVD is not set CONFIG_TELNET=y CONFIG_FEATURE_TELNET_TTYPE=y CONFIG_FEATURE_TELNET_AUTOLOGIN=y # CONFIG_TELNETD is not set # CONFIG_FEATURE_TELNETD_STANDALONE is not set # CONFIG_FEATURE_TELNETD_INETD_WAIT is not set CONFIG_TFTP=y # CONFIG_TFTPD is not set # # Common options for tftp/tftpd # CONFIG_FEATURE_TFTP_GET=y CONFIG_FEATURE_TFTP_PUT=y CONFIG_FEATURE_TFTP_BLOCKSIZE=y # CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set # CONFIG_TFTP_DEBUG is not set CONFIG_TRACEROUTE=y # CONFIG_TRACEROUTE6 is not set # CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set # CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set # CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set # CONFIG_TUNCTL is not set # CONFIG_FEATURE_TUNCTL_UG is not set # CONFIG_UDHCPD is not set # CONFIG_DHCPRELAY is not set # CONFIG_DUMPLEASES is not set # CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set CONFIG_DHCPD_LEASES_FILE="" CONFIG_UDHCPC=y CONFIG_FEATURE_UDHCPC_ARPING=y # CONFIG_FEATURE_UDHCP_PORT is not set CONFIG_UDHCP_DEBUG=0 # CONFIG_FEATURE_UDHCP_RFC3397 is not set CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="-R -n" # CONFIG_UDPSVD is not set CONFIG_VCONFIG=y CONFIG_WGET=y CONFIG_FEATURE_WGET_STATUSBAR=y CONFIG_FEATURE_WGET_AUTHENTICATION=y CONFIG_FEATURE_WGET_LONG_OPTIONS=y CONFIG_FEATURE_WGET_TIMEOUT=y # CONFIG_ZCIP is not set # # Print Utilities # # CONFIG_LPD is not set # CONFIG_LPR is not set # CONFIG_LPQ is not set # # Mail Utilities # # CONFIG_MAKEMIME is not set CONFIG_FEATURE_MIME_CHARSET="" # CONFIG_POPMAILDIR is not set # CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set # CONFIG_REFORMIME is not set # CONFIG_FEATURE_REFORMIME_COMPAT is not set # CONFIG_SENDMAIL is not set # # Process Utilities # # CONFIG_IOSTAT is not set # CONFIG_MPSTAT is not set # CONFIG_PMAP is not set # CONFIG_POWERTOP is not set # CONFIG_SMEMCAP is not set CONFIG_FREE=y CONFIG_FUSER=y CONFIG_KILL=y CONFIG_KILLALL=y CONFIG_KILLALL5=y # CONFIG_NMETER is not set # CONFIG_PGREP is not set CONFIG_PIDOF=y CONFIG_FEATURE_PIDOF_SINGLE=y CONFIG_FEATURE_PIDOF_OMIT=y # CONFIG_PKILL is not set CONFIG_PS=y CONFIG_FEATURE_PS_WIDE=y # CONFIG_FEATURE_PS_TIME is not set # CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set CONFIG_RENICE=y CONFIG_BB_SYSCTL=y CONFIG_TOP=y CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y # CONFIG_FEATURE_TOP_SMP_CPU is not set # CONFIG_FEATURE_TOP_DECIMALS is not set # CONFIG_FEATURE_TOP_SMP_PROCESS is not set # CONFIG_FEATURE_TOPMEM is not set # CONFIG_FEATURE_SHOW_THREADS is not set CONFIG_UPTIME=y CONFIG_WATCH=y # # Runit Utilities # # CONFIG_RUNSV is not set # CONFIG_RUNSVDIR is not set # CONFIG_FEATURE_RUNSVDIR_LOG is not set # CONFIG_SV is not set CONFIG_SV_DEFAULT_SERVICE_DIR="" # CONFIG_SVLOGD is not set # CONFIG_CHPST is not set # CONFIG_SETUIDGID is not set # CONFIG_ENVUIDGID is not set # CONFIG_ENVDIR is not set # CONFIG_SOFTLIMIT is not set # CONFIG_CHCON is not set # CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set # CONFIG_GETENFORCE is not set # CONFIG_GETSEBOOL is not set # CONFIG_LOAD_POLICY is not set # CONFIG_MATCHPATHCON is not set # CONFIG_RESTORECON is not set # CONFIG_RUNCON is not set # CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set # CONFIG_SELINUXENABLED is not set # CONFIG_SETENFORCE is not set # CONFIG_SETFILES is not set # CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set # CONFIG_SETSEBOOL is not set # CONFIG_SESTATUS is not set # # Shells # CONFIG_ASH=y CONFIG_ASH_BASH_COMPAT=y CONFIG_ASH_JOB_CONTROL=y CONFIG_ASH_ALIAS=y # CONFIG_ASH_GETOPTS is not set CONFIG_ASH_BUILTIN_ECHO=y CONFIG_ASH_BUILTIN_PRINTF=y CONFIG_ASH_BUILTIN_TEST=y CONFIG_ASH_CMDCMD=y # CONFIG_ASH_MAIL is not set CONFIG_ASH_OPTIMIZE_FOR_SIZE=y CONFIG_ASH_RANDOM_SUPPORT=y CONFIG_ASH_EXPAND_PRMT=y # CONFIG_CTTYHACK is not set # CONFIG_HUSH is not set # CONFIG_HUSH_BASH_COMPAT is not set # CONFIG_HUSH_BRACE_EXPANSION is not set # CONFIG_HUSH_HELP is not set # CONFIG_HUSH_INTERACTIVE is not set # CONFIG_HUSH_SAVEHISTORY is not set # CONFIG_HUSH_JOB is not set # CONFIG_HUSH_TICK is not set # CONFIG_HUSH_IF is not set # CONFIG_HUSH_LOOPS is not set # CONFIG_HUSH_CASE is not set # CONFIG_HUSH_FUNCTIONS is not set # CONFIG_HUSH_LOCAL is not set # CONFIG_HUSH_RANDOM_SUPPORT is not set # CONFIG_HUSH_EXPORT_N is not set # CONFIG_HUSH_MODE_X is not set # CONFIG_MSH is not set CONFIG_FEATURE_SH_IS_ASH=y # CONFIG_FEATURE_SH_IS_HUSH is not set # CONFIG_FEATURE_SH_IS_NONE is not set # CONFIG_FEATURE_BASH_IS_ASH is not set # CONFIG_FEATURE_BASH_IS_HUSH is not set CONFIG_FEATURE_BASH_IS_NONE=y CONFIG_SH_MATH_SUPPORT=y # CONFIG_SH_MATH_SUPPORT_64 is not set CONFIG_FEATURE_SH_EXTRA_QUIET=y # CONFIG_FEATURE_SH_STANDALONE is not set # CONFIG_FEATURE_SH_NOFORK is not set # # System Logging Utilities # CONFIG_SYSLOGD=y CONFIG_FEATURE_ROTATE_LOGFILE=y CONFIG_FEATURE_REMOTE_LOG=y # CONFIG_FEATURE_SYSLOGD_DUP is not set CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256 # CONFIG_FEATURE_IPC_SYSLOG is not set CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 # CONFIG_LOGREAD is not set # CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set CONFIG_KLOGD=y CONFIG_FEATURE_KLOGD_KLOGCTL=y CONFIG_LOGGER=y OpenIPMI-2.0.33/lanserv/marvell-bmc/marvell_node.emu0000644000175000017500000000231112077274675017150 00000000000000# Add target n mc_add $MCNUM 1 no-device-sdrs 00 00 00 0xc9 0x00500f 0x0002 mc_enable $MCNUM # Now the FRU data mc_add_fru_data $MCNUM 0 2048 \ file 0 "/sys/class/i2c-adapter/i2c-"$MCNUM"/"$MCNUM"-0050/at24c64" # Board temp sensor sensor_add $MCNUM 0 1 1 1 # Board CPU temp sensor sensor_add $MCNUM 0 2 1 1 # DIMM temp sensor sensor_add $MCNUM 0 3 1 1 # Front panel temp sensor sensor_add $MCNUM 0 4 1 1 # V 1.0 Node X sensor_add $MCNUM 0 5 2 1 # V 1.8 Node X sensor_add $MCNUM 0 6 2 1 # V 2.5 Node X sensor_add $MCNUM 0 7 2 1 # V 3.3 Node X sensor_add $MCNUM 0 8 2 1 # V 1.05 Node X sensor_add $MCNUM 0 9 2 1 # V DIMM Node X sensor_add $MCNUM 0 10 2 1 # V DIMML Node X sensor_add $MCNUM 0 11 2 1 # V 0.9 Node X sensor_add $MCNUM 0 12 2 1 # CPU status sensor_add $MCNUM 0 20 7 0x6f # poll 1000 \ # file "/sys/class/i2c-adapter/i2c-"$MCNUM"/"$MCNUM"-0050/at24c64" \ # raw offset=9 length=1 # DIMM status sensor_add $MCNUM 0 21 12 0x6f # poll 1000 \ # file "/sys/class/i2c-adapter/i2c-"$MCNUM"/"$MCNUM"-0050/at24c64" \ # raw offset=10 length=1OpenIPMI-2.0.33/lanserv/marvell-bmc/lancontrol0000755000175000017500000002210412116456523016060 00000000000000#!/bin/sh # # An example script for handling external LAN configuration from the # IPMI simulator. This command is generally invoked by the IPMI # simulator to get and set external LAN configuration parameters. # # It's parameters are: # # ipmi_sim_lancontrol get [parm [parm ...]] # ipmi_sim_lancontrol set|check [parm val [parm val ...]] # # where is a network device (eth0, etc.) and parm is one of: # ip_addr # ip_addr_src # mac_addr # subnet_mask # default_gw_ip_addr # default_gw_mac_addr # backup_gw_ip_addr # backup_gw_mac_addr # These are config values out of the IPMI LAN config table that are # not IPMI-exclusive, they require setting external things. # # The output of the "get" is ":" for each listed parm. # The output of the "set" is empty on success. Error output goes to # standard out (so it can be captured in the simulator) and the program # returns an error. # # The IP address values are standard IP addresses in the form a.b.c.d. # The MAC addresses ar standard 6 octet xx:xx:xx:xx:xx:xx values. The # only special one is ip_addr_src, which can be "dhcp" or "static". # # The "check" operation checks to see if a value is valid without # committing it. # need_ip_addr=0 need_ip_addr_src=0 need_mac_addr=0 need_subnet_mask=0 need_default_gw_ip_addr=0 ip_addr="0.0.0.0" ip_addr_src="dhcp" mac_addr="00:00:00:00:00:00" subnet_mask="255.255.255.255" default_gw_ip_addr="0.0.0.0" prog=$0 device=$1 if [ "x$device" = "x" ]; then echo "No device given" exit 1; fi shift op=$1 if [ "x$op" = "x" ]; then echo "No operation given" exit 1 fi shift do_get() { while [ "x$1" != "x" ]; do case $1 in ip_addr) val=`ifconfig $device | grep '^ *inet addr:' | tr ':' ' ' | sed 's/.*inet addr \([0-9.]*\).*$/\1/'` if [ "x$val" = "x" ]; then val="0.0.0.0" fi ;; ip_addr_src) val=`grep "iface $device inet" /etc/network/interfaces | tr ' ' '\t' | tr -s '\t' '\t' | cut -f 4` case "x$val" in xstatic) ;; xdhcp) ;; *) val="unknown" ;; esac ;; mac_addr) val=`ifconfig $device | grep 'HWaddr' | sed 's/.*HWaddr \([0-9a-fA-F:]*\).*$/\1/'` if [ "x$val" = "x" ]; then val="00:00:00:00:00:00" fi ;; subnet_mask) val=`ifconfig $device | grep '^ *inet addr:' | tr ':' ' ' | sed 's/.*Mask \([0-9.]*\).*$/\1/'` if [ "x$val" = "x" ]; then val="0.0.0.0" fi ;; default_gw_ip_addr) val=`route -n | grep '^0\.0\.0\.0' | grep "$device\$" | tr ' ' '\t' | tr -s '\t' '\t' | cut -f 2` if [ "x$val" = "x" ]; then val="0.0.0.0" fi ;; default_gw_mac_addr) val=`route -n | grep '^0\.0\.0\.0' | grep "$device\$" | tr ' ' '\t' | tr -s '\t' '\t' | cut -s -f 2` if [ "x$val" = "x" ]; then val="00:00:00:00:00:00" else ping -W 1 -c 1 $val >/dev/null 2>&1 val=`arp -n $val | grep "($val)" | tr ' ' '\t' | tr -s '\t' '\t' | cut -f 4` if [ "x$val" = "x" -o "x$val" = 'x' ]; then val="00:00:00:00:00:00" fi fi ;; backup_gw_ip_addr) val="0.0.0.0" ;; backup_gw_mac_addr) val="00:00:00:00:00:00" ;; *) echo "Invalid parameter: $1" exit 1 ;; esac echo "$1:$val" shift done } do_check() { case $1 in ip_addr_src) # We only support static and dhcp IP address sources case $2 in static) ;; dhcp) ;; *) echo "Invalid ip_addr_src: $2" exit 1 ;; esac ;; ip_addr | subnet_mask | default_gw_ip_addr) if [ "$2" != "`echo $2 | grep -E [0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}`" ]; then echo "Invalid value $2 for parameter $1" exit 1 fi ;; mac_addr) if [ "$2" != "`echo $2 | grep -E [[:xdigit:]]\{1,2\}[:][[:xdigit:]]\{1,2\}[:][[:xdigit:]]\{1,2\}[:][[:xdigit:]]\{1,2\}[:][[:xdigit:]]\{1,2\}[:][[:xdigit:]]\{1,2\}`" ]; then echo "Invalid value $2 for parameter $1" exit 1 fi ;; *) echo "Invalid parameter: $parm" exit 1 ;; esac } do_create_stanza() { if [ $need_ip_addr_src != 1 ] then echo "ip_addr_src required for new interface stanza - fail" exit 1 fi case $ip_addr_src in dhcp) echo "iface $device inet dhcp" >/tmp/ipmi_ifaces_stanza if [ $need_mac_addr = 1 ] then echo " hwaddress $mac_addr" >>/tmp/ipmi_ifaces_stanza fi echo " " >>/tmp/ipmi_ifaces_stanza ;; static) echo "iface $device inet static" >/tmp/ipmi_ifaces_stanza if [ $need_ip_addr = 1 ] then echo " address $ip_addr" >>/tmp/ipmi_ifaces_stanza else echo "static configuration requires ip_addr - fail" exit 1 fi if [ $need_subnet_mask = 1 ] then echo " netmask $subnet_mask" >>/tmp/ipmi_ifaces_stanza else echo "static configuration requires subnet_mask - fail" exit 1 fi if [ $need_default_gw_ip_addr = 1 ] then echo " gateway $default_gw_ip_addr" >>/tmp/ipmi_ifaces_stanza fi if [ $need_mac_addr = 1 ] then echo " hwaddress ether $mac_addr" >>/tmp/ipmi_ifaces_stanza fi echo " " >>/tmp/ipmi_ifaces_stanza ;; esac } do_split_interfaces() { # separate the stanza for our device from the other stanzas sed "/^[ \t]*iface[ \t][ \t]*$device[ \t]/,/^\t$/d" /etc/network/interfaces >/tmp/ipmi_interfaces_unchanged sed -n "/^[ \t]*iface[ \t][ \t]*$device[ \t]/,/^\t$/p" /etc/network/interfaces >/tmp/ipmi_old_stanza } do_modify_stanza() { # fixup the previous stanza for our device, keeping parts that are unmodified if [ -s /tmp/ipmi_old_stanza ] then # now we need to modify the file that is there to update any new settings # For every new parameter, remove the old corresponding line cp /tmp/ipmi_old_stanza /tmp/ipmi_old_stanza_src if [ $need_ip_addr_src = 1 ] then sed '/^[ \t]*iface/d' /tmp/ipmi_old_stanza_src >/tmp/ipmi_old_stanza_dst.1 echo "iface $device inet $ip_addr_src" >/tmp/ipmi_ifaces_stanza cp /tmp/ipmi_old_stanza_dst.1 /tmp/ipmi_old_stanza_src else sed -n "1p" /tmp/ipmi_old_stanza_src >/tmp/ipmi_ifaces_stanza sed '/^[ \t]*iface/d' /tmp/ipmi_old_stanza_src >/tmp/ipmi_old_stanza_dst.1 cp /tmp/ipmi_old_stanza_dst.1 /tmp/ipmi_old_stanza_src fi if [ $need_ip_addr = 1 ] then sed '/^[ \t]*address/d' /tmp/ipmi_old_stanza_src >/tmp/ipmi_old_stanza_dst.2 echo " address $ip_addr" >>/tmp/ipmi_ifaces_stanza cp /tmp/ipmi_old_stanza_dst.2 /tmp/ipmi_old_stanza_src fi if [ $need_subnet_mask = 1 ] then sed '/^[ \t]*netmask/d' /tmp/ipmi_old_stanza_src >/tmp/ipmi_old_stanza_dst.3 echo " netmask $subnet_mask" >>/tmp/ipmi_ifaces_stanza cp /tmp/ipmi_old_stanza_dst.3 /tmp/ipmi_old_stanza_src fi if [ $need_default_gw_ip_addr = 1 ] then sed '/^[ \t]*gateway/d' /tmp/ipmi_old_stanza_src >/tmp/ipmi_old_stanza_dst.4 echo " gateway $default_gw_ip_addr" >>/tmp/ipmi_ifaces_stanza cp /tmp/ipmi_old_stanza_dst.4 /tmp/ipmi_old_stanza_src fi if [ $need_mac_addr = 1 ] then sed '/^[ \t]*hwaddress/d' /tmp/ipmi_old_stanza_src >/tmp/ipmi_old_stanza_dst.5 echo " hwaddress ether $mac_addr" >>/tmp/ipmi_ifaces_stanza cp /tmp/ipmi_old_stanza_dst.5 /tmp/ipmi_old_stanza_src fi cat /tmp/ipmi_old_stanza_src >>/tmp/ipmi_ifaces_stanza else # if /tmp/ipmi_old_stanza is empty, then we just need to create a new stanza # as this is adding an interface to the configuration do_create_stanza fi } # Parse existing interfaces file - # if there is an existing iface stanza for $device # then extract it for update with new parameters # We keep any parameters that are not set on the # command line for this script. # # Be careful - you may render your connection to the management # system unusable. Upon successful creation of a new interfaces # file, the interface is taken down and restarted to do_interfaces() { if [ -d /etc/network ] then if [ -f /etc/network/interfaces ] then if [ -w /etc/network/interfaces ] then do_split_interfaces do_modify_stanza cat /tmp/ipmi_interfaces_unchanged /tmp/ipmi_ifaces_stanza >/tmp/impi_new_interfaces mv /etc/network/interfaces /etc/network/interfaces.old cp /tmp/impi_new_interfaces /etc/network/interfaces else echo "/etc/network/interfaces exists and is not writable -fail" exit 1 fi else do_create_stanza cp /tmp/ipmi_ifaces_stanza /etc/network/interfaces fi else echo "No /etc/network directory found - failing" exit 1 fi } do_set() { if [ "x$1" = "x" ] then echo "no parameters given for set command - fail" exit 1 fi while [ "x$1" != "x" ]; do parm="$1" shift if [ "x$1" = "x" ]; then echo "No value present for parameter $parm" exit 1 fi val="$1" shift do_check $parm $val case $parm in ip_addr) need_ip_addr=1 ip_addr=$val ;; ip_addr_src) need_ip_addr_src=1 ip_addr_src=$val ;; mac_addr) need_mac_addr=1 mac_addr=$val ;; subnet_mask) need_subnet_mask=1 subnet_mask=$val ;; default_gw_ip_addr) need_default_gw_ip_addr=1 default_gw_ip_addr=$val ;; *) echo "Invalid parameter: $1" exit 1 ;; esac done do_interfaces ifdown $device ifup $device } case $op in get) do_get $@ ;; set) do_set $@ ;; check) do_check $@ ;; *) echo "Unknown operation: $op" exit 1 esac OpenIPMI-2.0.33/lanserv/marvell-bmc/wiw.h0000644000175000017500000000110512077274675014750 00000000000000enum { WIW_NO_EVENT, WIW_NODE1_IN, WIW_NODE1_OUT, WIW_NODE2_IN, WIW_NODE2_OUT, WIW_NODE3_IN, WIW_NODE3_OUT, WIW_NODE4_IN, WIW_NODE4_OUT, WIW_NODE5_IN, WIW_NODE5_OUT, WIW_NODE6_IN, WIW_NODE6_OUT, WIW_NODE1_PBTN_P, WIW_NODE1_PBTN_R, WIW_NODE2_PBTN_P, WIW_NODE2_PBTN_R, WIW_NODE3_PBTN_P, WIW_NODE3_PBTN_R, WIW_NODE4_PBTN_P, WIW_NODE4_PBTN_R, WIW_NODE5_PBTN_P, WIW_NODE5_PBTN_R, WIW_NODE6_PBTN_P, WIW_NODE6_PBTN_R, }; #define READ_WIW_BLOCKING _IOWR('c', 150, int) #define READ_WIW_NONBLOCKING _IOWR('c', 151, int) OpenIPMI-2.0.33/lanserv/marvell-bmc/Makefile.in0000664000175000017500000005600214261607634016036 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = lanserv/marvell-bmc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/ax_config_feature.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_pkg_swig.m4 \ $(top_srcdir)/m4/ax_prog_python_version.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) marvell_mod_la_LIBADD = am_marvell_mod_la_OBJECTS = marvell_mod.lo marvell_mod_la_OBJECTS = $(am_marvell_mod_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = marvell_mod_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(marvell_mod_la_LDFLAGS) $(LDFLAGS) -o \ $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/marvell_mod.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(marvell_mod_la_SOURCES) DIST_SOURCES = $(marvell_mod_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(noinst_DATA) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp TODO DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BIBTEX = @BIBTEX@ BUILD_CC = @BUILD_CC@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DIA = @DIA@ DIA_FILTER_NAME = @DIA_FILTER_NAME@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPDF = @DVIPDF@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDBM_LIB = @GDBM_LIB@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_DIR = @GLIB_DIR@ GLIB_LIB = @GLIB_LIB@ GLIB_LIBS = @GLIB_LIBS@ GLIB_PKGCONF = @GLIB_PKGCONF@ GLIB_SO = @GLIB_SO@ GLIB_TARGET = @GLIB_TARGET@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MARVELL_BMC_DIR = @MARVELL_BMC_DIR@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENIPMI_SWIG_LIBS = @OPENIPMI_SWIG_LIBS@ OPENIPMI_SWIG_SO = @OPENIPMI_SWIG_SO@ OPENIPMI_VERSION_EXTRA = @OPENIPMI_VERSION_EXTRA@ OPENIPMI_VERSION_MAJOR = @OPENIPMI_VERSION_MAJOR@ OPENIPMI_VERSION_MINOR = @OPENIPMI_VERSION_MINOR@ OPENIPMI_VERSION_RELEASE = @OPENIPMI_VERSION_RELEASE@ OPENSSLINCS = @OPENSSLINCS@ OPENSSLLIBS = @OPENSSLLIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL_CFLAGS = @PERL_CFLAGS@ PERL_DIR = @PERL_DIR@ PERL_HAS_POSIX_THREADS = @PERL_HAS_POSIX_THREADS@ PERL_INSTALL_DIR = @PERL_INSTALL_DIR@ PERL_POSIX_LIB = @PERL_POSIX_LIB@ PERL_POSIX_SO = @PERL_POSIX_SO@ POPTLIBS = @POPTLIBS@ PYTHON = @PYTHON@ PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ PYTHON_DIR = @PYTHON_DIR@ PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ PYTHON_GUI_DIR = @PYTHON_GUI_DIR@ PYTHON_HAS_POSIX_THREADS = @PYTHON_HAS_POSIX_THREADS@ PYTHON_INSTALL_DIR = @PYTHON_INSTALL_DIR@ PYTHON_INSTALL_LIB_DIR = @PYTHON_INSTALL_LIB_DIR@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM_SITE_PKG = @PYTHON_PLATFORM_SITE_PKG@ PYTHON_POSIX_LIB = @PYTHON_POSIX_LIB@ PYTHON_POSIX_SO = @PYTHON_POSIX_SO@ PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ PYTHON_SWIG_FLAGS = @PYTHON_SWIG_FLAGS@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ RT_LIB = @RT_LIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMPLIBS = @SNMPLIBS@ SOCKETLIB = @SOCKETLIB@ STRIP = @STRIP@ SWIG = @SWIG@ SWIG_DIR = @SWIG_DIR@ SWIG_LIB = @SWIG_LIB@ TCL_CFLAGS = @TCL_CFLAGS@ TCL_DIR = @TCL_DIR@ TCL_LIB = @TCL_LIB@ TCL_LIBS = @TCL_LIBS@ TCL_PKGCONF = @TCL_PKGCONF@ TCL_SO = @TCL_SO@ TCL_TARGET = @TCL_TARGET@ TERM_LIBS = @TERM_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ diaprog = @diaprog@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ perlprog = @perlprog@ pkgprog = @pkgprog@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/lanserv pkglib_LTLIBRARIES = marvell_mod.la marvell_mod_la_SOURCES = marvell_mod.c marvell_mod_la_LDFLAGS = -module noinst_DATA = sdrs.bin noinst_HEADERS = wiw.h EXTRA_DIST = main.sdrs board.sdrs fan.sdrs lan.conf netsrvc lancontrol \ busybox-1.18.4.config interfaces ntp.conf marvell_bmc.config \ S90ast1300 SystemInfo TODO BuildingAndConfiguring.tex \ Build_Marvell_BMC.sh Install_Marvell_BMC.sh marvell_node.emu \ marvell.emu all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lanserv/marvell-bmc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lanserv/marvell-bmc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } marvell_mod.la: $(marvell_mod_la_OBJECTS) $(marvell_mod_la_DEPENDENCIES) $(EXTRA_marvell_mod_la_DEPENDENCIES) $(AM_V_CCLD)$(marvell_mod_la_LINK) -rpath $(pkglibdir) $(marvell_mod_la_OBJECTS) $(marvell_mod_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/marvell_mod.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/marvell_mod.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/marvell_mod.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-pkglibLTLIBRARIES install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-pkglibLTLIBRARIES .PRECIOUS: Makefile sdrs.bin: main.sdrs board.sdrs fan.sdrs \ $(top_builddir)/lanserv/sdrcomp/sdrcomp $(top_builddir)/lanserv/sdrcomp/sdrcomp -I $(srcdir) \ $(srcdir)/main.sdrs >sdrs.bin # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: OpenIPMI-2.0.33/lanserv/marvell-bmc/Build_Marvell_BMC.sh0000664000175000017500000000301512206672403017514 00000000000000# # Script to build the Marvell BMC. # # Copy this script and the Install_Marvell_BMC.sh to the place where you # want to do the build and cd to there. # # Then you must get the software in the current directory: # # armv5-marvell-linux-gnueabi-soft_i686.tar.bz2 # buildroot-2011.05-sdk5.1.2.tar.bz2 # # then execute this script. This only builds the software, use # Install_Marvell_BMC.sh to isntall it into a rootfs. # TOOLCHAIN=armv5-marvell-linux-gnueabi-soft_i686 BUILDROOT=buildroot-2011.05-sdk5.1.2 # General variables we use MBASEDIR=`pwd` BRDIR=${MBASEDIR}/${BUILDROOT} # Untar the toolchain and build system and get openipmi tar xjf ${TOOLCHAIN}.tar.bz2 tar xjf ${BUILDROOT}.tar.bz2 git clone git://git.code.sf.net/p/openipmi/code openipmi # Install the busybox config and set the toolchain path cp openipmi/lanserv/marvell-bmc/marvell_bmc.config ${BRDIR}/.config sed -i "s%BR2_TOOLCHAIN_EXTERNAL_PATH=.*\$%BR2_TOOLCHAIN_EXTERNAL_PATH=\"${MBASEDIR}/${TOOLCHAIN}\"%" ${BRDIR}/.config cp openipmi/lanserv/marvell-bmc/busybox-1.18.4.config ${BRDIR} cd ${BRDIR} make # this will take a while # Now check out and build openipmi cd ${MBASEDIR} export PATH=${MBASEDIR}/${TOOLCHAIN}/bin:$PATH cd openipmi libtoolize aclocal autoconf automake -a autoreconf ./configure --host=arm-mv5sft-linux-gnueabi --prefix=/usr --sysconfdir=/etc \ --localstatedir=/var --with-glib=no --with-python=no --with-perl=no \ host_alias=arm-mv5sft-linux-gnueabi --with-marvell-bmc \ CC="arm-marvell-linux-gnueabi-gcc --sysroot=${BRDIR}/output/staging" make OpenIPMI-2.0.33/lanserv/marvell-bmc/Install_Marvell_BMC.sh0000644000175000017500000000660512116456523020074 00000000000000# # Script to install the Marvell BMC. Run from the same directory # you ran Build_Marvell_BMC.sh in. # VERSION=1.0.0 # These are the things you must configure for your setup. In general, # you would set these in an override file AST1300=${HOME}/hhl/marvell/ast1300.ko AXP_BOARD_FRU=${HOME}/hhl/marvell/axpfru-2.0.01.img NTPSERVER=pool.ntp.org MTIMEZONE=GMT #MTIMEZONE=US/Central if [ -e Install_Marvell_Overrides ]; then echo "Reading override file" source ./Install_Marvell_Overrides fi echo AST1300=$AST1300 echo AXP_BOARD_FRU=$AXP_BOARD_FRU echo NTPSERVER=$NTPSERVER echo MTIMEZONE=$MTIMEZONE BUILDROOT=buildroot-2011.05-sdk5.1.2 # General variables we use MBASEDIR=`pwd` BRDIR=${MBASEDIR}/${BUILDROOT} # Install openipmi into the image. Some of this *MUST* be done as root, # thus the sudo on those command. cd ${MBASEDIR} cd ${BRDIR}/output/images sudo rm -rf rootfs sudo mkdir rootfs cd rootfs sudo tar xf ../rootfs.tar cd ${MBASEDIR}/openipmi cd utils sudo cp .libs/libOpenIPMIutils.so.0 ${BRDIR}/output/images/rootfs/usr/lib cd ../unix sudo cp .libs/libOpenIPMIposix.so.0 ${BRDIR}/output/images/rootfs/usr/lib cd ../lanserv sudo cp .libs/libIPMIlanserv.so.0 ${BRDIR}/output/images/rootfs/usr/lib sudo cp .libs/ipmi_sim ${BRDIR}/output/images/rootfs/usr/sbin cd marvell-bmc sudo mkdir -p ${BRDIR}/output/images/rootfs/etc/ipmi sudo cp lan.conf lancontrol marvell.emu marvell_node.emu netsrvc \ ${BRDIR}/output/images/rootfs/etc/ipmi sudo cp interfaces ${BRDIR}/output/images/rootfs/etc/network sudo cp S90ast1300 ${BRDIR}/output/images/rootfs/etc/init.d sudo cp ntp.conf ${BRDIR}/output/images/rootfs/etc sudo mkdir -p ${BRDIR}/output/images/rootfs/usr/lib/ipmi_sim sudo cp .libs/marvell_mod.so ${BRDIR}/output/images/rootfs/usr/lib/ipmi_sim sudo mkdir -p ${BRDIR}/output/images/rootfs/var/ipmi_sim sudo mkdir -p ${BRDIR}/output/images/rootfs/var/ipmi_sim/AXP-SERVER sudo cp sdrs.bin \ ${BRDIR}/output/images/rootfs/var/ipmi_sim/AXP-SERVER/sdr.20.main # Now fix things up in the root filesystem cd ${BRDIR}/output/images/rootfs # Now install the board fru reference file in /etc/ipmi/axp_board_fru sudo cp ${AXP_BOARD_FRU} etc/ipmi/axp_board_fru # Now install ast1300.ko in root sudo mkdir -p root sudo cp ${AST1300} root/ast1300.ko # Add the following to etc/inittab: sudo sh -c 'echo "null::respawn:/usr/sbin/ipmi_sim -f /etc/ipmi/marvell.emu -n"\ >>etc/inittab' # Set the login prompt sudo sh -c "echo \"Welcome to Marvell BMC ${VERSION}\" >etc/issue" # Set the hostname. No '.' allowed in hostname, so translate to '_' sudo sh -c "echo \"BMC-${VERSION}\" | sed 's/\\./_/g' >etc/hostname" # Fix a problem setting the hostname sudo sed -i 's/hostname -F \/etc\/hostname/hostname "`cat \/etc\/hostname`"/' \ etc/inittab # Set the NTP server sudo sed -i 's/NTPDATE=no/NTPDATE=yes/' etc/default/ntpd sudo sed -i "s/pool\.ntp\.org/${NTPSERVER}/" etc/default/ntpd sudo sed -i "s/pool\.ntp\.org/${NTPSERVER}/" etc/ntp.conf # Set the time zone sudo ln -sf /usr/share/zoneinfo/${MTIMEZONE} etc/localtime # Create the event device for the AST1300 sudo mknod dev/event c 10 10 # The redirect for stdout is done so that the file is owned by the user, # not root.sudo sudo tar czf - * >${MBASEDIR}/rootfs-$VERSION.tar.gz cd .. sudo rm -rf rootfs echo "Now you can install rootfs-$VERSION.tar.gz on the chassis." echo "" echo "You will need to edit etc/network/interfaces in the rootfs" echo "to set it properly for your network." OpenIPMI-2.0.33/lanserv/marvell-bmc/lan.conf0000644000175000017500000000760012116456523015404 00000000000000# lan.conf # A configuration file for lanserv or ipmi_sim to configure the various # communication parameters for the device. # This is a name used to identify this instance, and used to create # the default name of the emulator startup command file and eventually # the storage facility for permanent storage. name "AXP-SERVER" # # Work on the BMC first set_working_mc 0x20 # Define a LAN channel on channel 1 (eth1) startlan 1 # Define an IP address and port to listen on. You can define more # than one address/port to listen on multiple addresses. The :: # listens on all addresses. addr 0.0.0.0 623 # Maximum privilege limit on the channel. priv_limit admin # Allowed IPMI 1.5 authorization types #allowed_auths_callback none md2 md5 straight #allowed_auths_user none md2 md5 straight #allowed_auths_operator none md2 md5 straight #allowed_auths_admin none md2 md5 straight # guid for IPMI 2.0 authorization You can also use a string #guid a123456789abcdefa123456789abcdef guid "vos92Gk2Ols901ls" # You can specify a BMC key for IPMI 2.0 authorization. See the # spec for details. #bmc_key "abcdefghijklmnopqrst" # A program to get and set the LAN configuration of the interface. lan_config_program "/etc/ipmi/lancontrol eth1" endlan # Define a LAN channel on channel 2 (eth0) startlan 2 # We don't define a listen address, as it is not necessary, the # one from channel 1 covers everything. # Maximum privilege limit on the channel. priv_limit admin # Allowed IPMI 1.5 authorization types #allowed_auths_callback none md2 md5 straight #allowed_auths_user none md2 md5 straight #allowed_auths_operator none md2 md5 straight #allowed_auths_admin none md2 md5 straight # guid for IPMI 2.0 authorization You can also use a string #guid a123456789abcdefa123456789abcdef guid "vos92Gk2Ols901ls" # You can specify a BMC key for IPMI 2.0 authorization. See the # spec for details. #bmc_key "abcdefghijklmnopqrst" # A program to get and set the LAN configuration of the interface. lan_config_program "/etc/ipmi/lancontrol eth0" endlan # Now add some users. User 0 is invalid, user 1 is the special "anonymous" # user and cannot take a username. Note that the users here are only # used if the persistent user config doesn't exist. # # valid name passw priv-lim max-sess allowed-auths user 1 false "" "test" user 10 none md2 md5 straight user 2 true "ADMIN" "ADMIN" admin 10 none md2 md5 straight # # Target board 1 # set_working_mc 1 sol "/dev/ttyAS0" 115200 history=65535,backupfile=/var/ipmi_sim/solhist1 historyfru=10 nortscts # # Target board 2 # set_working_mc 2 sol "/dev/ttyAS1" 115200 history=65535,backupfile=/var/ipmi_sim/solhist2 historyfru=10 nortscts # # Target board 3 # set_working_mc 3 sol "/dev/ttyAS2" 115200 history=65535,backupfile=/var/ipmi_sim/solhist3 historyfru=10 nortscts # # Target board 4 # set_working_mc 4 sol "/dev/ttyAS3" 115200 history=65535,backupfile=/var/ipmi_sim/solhist4 historyfru=10 nortscts # # Target board 5 # set_working_mc 5 sol "/dev/ttyAS4" 115200 history=65535,backupfile=/var/ipmi_sim/solhist5 historyfru=10 nortscts # # Target board 6 # set_working_mc 6 sol "/dev/ttyS1" 115200 history=65535,backupfile=/var/ipmi_sim/solhist6 historyfru=10 nortscts # Allow a console connection to perform emulation commands. #console localhost 9000 # Dynamically load a module to extend the simulator. After the module is # loaded, if the function "ipmi_sim_module_init" is defined in the module, # it will be called with the following parameters: # int ipmi_sim_module_init(sys_data_t *sys, char *initstr); # where initstr is the init string passed on the module load line. # It should return 0 on success or an errno no failure. loadlib "/usr/lib/ipmi_sim/marvell_mod.so" "" OpenIPMI-2.0.33/lanserv/marvell-bmc/BuildingAndConfiguring.tex0000664000175000017500000000140112256156727021063 00000000000000 The build script build procedure special files (NTP, ast1300...) How to modify the build config How to modify the busybox config The configuration file LAN channels MCs users emu files MCs sensors FRU data SDRs Custom commands Disable network services: raw 2e 01 0f 50 00 [0|1] Enables (1) or disables(0) ssh access to the BMC Reload board FRU raw 2e 02 0f 50 00 Reload the board FRU information for the given board number. Set force all fans duty cycle raw 2e 03 0f 50 00 [0|] Set all fans to the given duty cycle. Allowed values are 30-100. Setting it to zero will disable this feature Get force all fans duty cycle raw 2e 04 0f 50 00 Returns the current fan forced duty cycle setting. OpenIPMI-2.0.33/lanserv/marvell-bmc/ntp.conf0000644000175000017500000000204612116456523015432 00000000000000# /etc/ntp.conf, configuration for ntpd driftfile /var/lib/ntp/ntp.drift statsdir /var/log/ntpstats/ statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable # You do need to talk to an NTP server or two (or three). server pool.ntp.org # By default, ignore everything # See /usr/share/doc/ntp-doc/html/accopt.html for details. restrict -4 default ignore restrict -6 default ignore # Local users may interrogate the ntp server more closely. restrict 127.0.0.1 restrict ::1 # Clients from this subnet have access to time, but not configuration restrict 192.168.1.0 mask 255.255.255.0 kod notrap nomodify nopeer noquery # Clients from this (example!) subnet have unlimited access, # but only if cryptographically authenticated #restrict 172.23.9.0 mask 255.255.255.0 notrust # If you want to provide time to your local subnet, change the next line. # (Again, the address is an example only.) #broadcast 192.168.123.255 OpenIPMI-2.0.33/lanserv/marvell-bmc/fan.sdrs0000644000175000017500000000174212116456523015425 00000000000000# Fan # Range 0-10000 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 0x6f + $FAN entity_id fan_cooling_device entity_instance $FAN init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Fan event_reading_type_code 1 return_lnc true return_lc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit RPM modifier_unit_code unspecified linearization linear m 392 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -1 b_exp 0 sensor_maximum 255 sensor_minimum 0 lnc_fthresh 1500 lc_fthresh 1000 id_string "fan "$FAN endsdr OpenIPMI-2.0.33/lanserv/marvell-bmc/marvell.emu0000644000175000017500000000426212141732704016132 00000000000000# # Emulation setup file for the Marvell AXP server # # The BMC is the MC at address 20 mc_setbmc 0x20 # Now add the BMC # IPMB DevID DevSDRs? Rev Maj Min Dev MFG Prod # FW FW Sup ID Id # Rev Rev mc_add 0x20 0 no-device-sdrs 0x00 0x00 0x00 0x9f 0x00500f 0x0001 persist_sdr sel_enable 0x20 1000 0x0a mc_add_fru_data 0x20 0 2048 \ file 0 "/sys/class/i2c-adapter/i2c-0/0-0051/at24c128" # MC LUN Sens# type reading # Switch Temp sensor_add 0x20 0 1 1 1 # Switch CPU Temp sensor_add 0x20 0 2 1 1 # Switch 12V sensor_add 0x20 0 3 2 1 # Switch 3.3V sensor_add 0x20 0 4 2 1 # Switch 1.8V sensor_add 0x20 0 5 2 1 # Chassis fans sensor_add 0x20 0 0x70 4 1 sensor_add 0x20 0 0x71 4 1 sensor_add 0x20 0 0x72 4 1 sensor_add 0x20 0 0x73 4 1 sensor_add 0x20 0 0x74 4 1 sensor_add 0x20 0 0x75 4 1 sensor_add 0x20 0 0x76 4 1 sensor_add 0x20 0 0x77 4 1 # Power supply sensors sensor_add 0x20 0 8 8 0x6f sensor_add 0x20 0 9 8 0x6f sensor_add 0x20 0 10 2 1 poll 2000 \ file "/sys/class/wixpmbus/VOUT_1" mult=8 div=125 sub=10000 \ depends=0x20,0,8,0 sensor_add 0x20 0 11 2 1 poll 2000 \ file "/sys/class/wixpmbus/VOUT_2" mult=8 div=125 sub=10000 \ depends=0x20,0,9,0 sensor_add 0x20 0 12 3 1 poll 2000 \ file "/sys/class/wixpmbus/IOUT_1" div=1000 \ depends=0x20,0,8,0 sensor_add 0x20 0 13 3 1 poll 2000 \ file "/sys/class/wixpmbus/IOUT_2" div=1000 \ depends=0x20,0,9,0 sensor_add 0x20 0 14 3 1 poll 2000 \ file "/sys/class/wixpmbus/POUT_1" div=10000 \ depends=0x20,0,8,0 sensor_add 0x20 0 15 3 1 poll 2000 \ file "/sys/class/wixpmbus/POUT_2" div=10000 \ depends=0x20,0,9,0 define MCNUM "1" include "marvell_node.emu" define MCNUM "2" include "marvell_node.emu" define MCNUM "3" include "marvell_node.emu" define MCNUM "4" include "marvell_node.emu" define MCNUM "5" include "marvell_node.emu" define MCNUM "6" include "marvell_node.emu" # Turn on the BMC mc_enable 0x20 OpenIPMI-2.0.33/lanserv/marvell-bmc/SystemInfo0000664000175000017500000000410112151417740015776 00000000000000 The BMC uses the following devices in the kernel: Serial ports: 1: /dev/ttyAS0 2: /dev/ttyAS1 3: /dev/ttyAS2 4: /dev/ttyAS3 5: /dev/ttyAS4 6: /dev/ttyS1 Fan fail LEDs: /sys/class/astgpio/GPIOP0 /sys/class/astgpio/GPIOP1 /sys/class/astgpio/GPIOP2 /sys/class/astgpio/GPIOP3 Power supply status: /sys/class/wixpmbus/STATUS_1 /sys/class/wixpmbus/STATUS_2 Board reset: /sys/class/astgpio/GPIOH[0-5] Board power: /sys/class/astgpio/GPIOD[6-7] /sys/class/astgpio/GPIOB[0-3] Board present: /sys/class/astgpio/GPIOC[0-5] Power off request: /sys/class/astgpio/GPIOA[6-7] /sys/class/astgpio/GPIOI[4-7] Power off ready: /sys/class/astgpio/GPIOA[0-3] /sys/class/astgpio/GPIOG[4-5] System FRU data: /sys/class/i2c-adapter/i2c-0/0-0051/at24c128 Switch sensors: switch temp: /sys/class/i2c-adapter/i2c-0/0-0058/temp2_input switch cpu temp: /sys/class/i2c-adapter/i2c-0/0-0058/temp3_input 12V /sys/class/i2c-adapter/i2c-0/0-0058/in11_input 3.3V /sys/class/i2c-adapter/i2c-0/0-0058/in10_input 1.8V /sys/class/i2c-adapter/i2c-0/0-0058/in2_input Fan 1-8 /sys/class/astfan/fan[1-8]_input Power supply Voltage: /sys/class/wixpmbus/VOUT_[1-2] Current: /sys/class/wixpmbus/IOUT_[1-2] Power /sys/class/wixpmbus/POUT_[1-2] For the rest of these "n" is the board number. Board FRU data /sys/class/i2c-adapter/i2c-n/n-0050/at24c64 Board CPU temp /sys/class/i2c-adapter/i2c-n/n-0064/temp1_input Board DIMM temp /sys/class/i2c-adapter/i2c-n/n-001e/temp1_input Board motherboard temp /sys/class/i2c-adapter/i2c-n/n-004a/temp1_input Board front temp /sys/class/i2c-adapter/i2c-n/n-004c/temp1_input 1V /sys/class/i2c-adapter/i2c-n/n-0048/in3_input 1.8V /sys/class/i2c-adapter/i2c-n/n-0048/in2_input 2.5V /sys/class/i2c-adapter/i2c-n/n-0048/in1_input 3.3V /sys/class/i2c-adapter/i2c-n/n-0048/in0_input 1.05V /sys/class/i2c-adapter/i2c-n/n-0049/in2_input DIMM V /sys/class/i2c-adapter/i2c-n/n-0049/in1_input .9V /sys/class/i2c-adapter/i2c-n/n-0049/in0_input OpenIPMI-2.0.33/lanserv/marvell-bmc/Makefile.am0000664000175000017500000000122714002617260016011 00000000000000 AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/lanserv pkglib_LTLIBRARIES = marvell_mod.la marvell_mod_la_SOURCES = marvell_mod.c marvell_mod_la_LDFLAGS = -module sdrs.bin: main.sdrs board.sdrs fan.sdrs \ $(top_builddir)/lanserv/sdrcomp/sdrcomp $(top_builddir)/lanserv/sdrcomp/sdrcomp -I $(srcdir) \ $(srcdir)/main.sdrs >sdrs.bin noinst_DATA = sdrs.bin noinst_HEADERS = wiw.h EXTRA_DIST = main.sdrs board.sdrs fan.sdrs lan.conf netsrvc lancontrol \ busybox-1.18.4.config interfaces ntp.conf marvell_bmc.config \ S90ast1300 SystemInfo TODO BuildingAndConfiguring.tex \ Build_Marvell_BMC.sh Install_Marvell_BMC.sh marvell_node.emu \ marvell.emu OpenIPMI-2.0.33/lanserv/marvell-bmc/board.sdrs0000644000175000017500000003706412116456523015756 00000000000000 sdr type 8 container_entity_id processing_blade container_entity_inst $OWNER_MC entity_1_id processor entity_1_inst $OWNER_MC entity_2_id memory_module entity_2_inst $OWNER_MC entity_3_id front_panel_board entity_3_inst $OWNER_MC endsdr sdr type 18 device_slave_address $OWNER_MC device_channel_number 0 chassis true ipmb_event_gen true fru_inventory true sensor true entity_id processing_blade entity_instance $OWNER_MC id_string "AXP Board "$OWNER_MC endsdr # Board temp sensor sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 1 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_sensor_type true default_sensor_scan_on true sensor_type Temperature event_reading_type_code 1 analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 id_string "MB Node "$OWNER_MC" temp" endsdr # CPU temp sensor sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 2 entity_id processor entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Temperature event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true return_unr true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true assert_unrgh true deassert_unrgh true lc_thrsh_settable true lnc_thrsh_settable true unr_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 unr_thresh 105 uc_fthresh 90 unc_fthresh 75 lnc_fthresh 5 lc_fthresh 0 positive_hysteresis 2 negative_hysteresis 2 id_string "CPU Node "$OWNER_MC" temp" endsdr # DIMM temp sensor sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 3 entity_id memory_module entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Temperature event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 85 unc_fthresh 75 lnc_fthresh 5 lc_fthresh 0 positive_hysteresis 2 negative_hysteresis 2 id_string "DIMM Node "$OWNER_MC" temp" endsdr # Front panel temp sensor sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 4 entity_id front_panel_board entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Temperature event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 45 unc_fthresh 40 lnc_fthresh 5 lc_fthresh 0 positive_hysteresis 2 negative_hysteresis 2 id_string "FP Node "$OWNER_MC" temp" endsdr # V 1.0 Node X # Range 0.9 - 1.1 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 5 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 78 tolerance 0 b 9 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 1.0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 1.05 unc_fthresh 1.03 lnc_fthresh 0.97 lc_fthresh 0.95 positive_hysteresis 2 negative_hysteresis 2 id_string "1.0V Node "$OWNER_MC endsdr # V 1.8 Node X # Range 1.6 - 2.0 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 6 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 156 tolerance 0 b 16 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 1.8 sensor_maximum 255 sensor_minimum 0 uc_fthresh 1.89 unc_fthresh 1.854 lnc_fthresh 1.746 lc_fthresh 1.71 positive_hysteresis 2 negative_hysteresis 2 id_string "1.8V Node "$OWNER_MC endsdr # V 2.5 Node X # Range 2.0 - 3.0 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 7 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 391 tolerance 0 b 20 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 2.5 sensor_maximum 255 sensor_minimum 0 uc_fthresh 2.625 unc_fthresh 2.575 lnc_fthresh 2.425 lc_fthresh 2.375 positive_hysteresis 2 negative_hysteresis 2 id_string "2.5V Node "$OWNER_MC endsdr # V 3.3 Node X # Range 2.9 - 3.7 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 8 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 313 tolerance 0 b 29 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 3.3 sensor_maximum 255 sensor_minimum 0 uc_fthresh 3.465 unc_fthresh 3.399 lnc_fthresh 3.201 lc_fthresh 3.135 positive_hysteresis 2 negative_hysteresis 2 id_string "3.3V Node "$OWNER_MC endsdr # V 1.05 Node X # Range .80 to 1.2 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 9 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 156 tolerance 0 b 8 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 1.05 sensor_maximum 255 sensor_minimum 0 uc_fthresh 1.155 unc_fthresh 1.1025 lnc_fthresh 0.9975 lc_fthresh 0.945 positive_hysteresis 2 negative_hysteresis 2 id_string "1.05V Node "$OWNER_MC endsdr # V DIMM Node X # Range 1.2 - 1.5 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 11 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 117 tolerance 0 b 12 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 1.35 sensor_maximum 255 sensor_minimum 0 uc_fthresh 1.4175 unc_fthresh 1.3905 lnc_fthresh 1.3095 lc_fthresh 1.2825 positive_hysteresis 2 negative_hysteresis 2 id_string "DIMM V Node "$OWNER_MC endsdr # V 0.9 Node X # Range 0.7 - 1.32 sdr type 1 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 12 entity_id processing_blade entity_instance $OWNER_MC init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 243 tolerance 0 b 7 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 0.9 sensor_maximum 255 sensor_minimum 0 uc_fthresh 1.20 unc_fthresh 1.10 lnc_fthresh 0.855 lc_fthresh 0.81 positive_hysteresis 2 negative_hysteresis 2 id_string "0.9V Node "$OWNER_MC endsdr # Board CPU status sensor sdr type 2 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 20 entity_id processor entity_instance $OWNER_MC init_scanning true init_events true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm false sensor_type Processor event_reading_type_code 0x6f assert_event0 true deassert_event0 true event0_state_ret true id_string "CPU Status "$OWNER_MC endsdr # Board DIMM status sensor sdr type 2 sensor_owner_id $OWNER_MC sensor_owner_lun 0 channel_number 0 sensor_number 21 entity_id memory_module entity_instance $OWNER_MC init_scanning true init_events true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm false sensor_type Memory event_reading_type_code 0x6f assert_event0 true assert_event1 true assert_event2 true assert_event7 true deassert_event0 true deassert_event1 true deassert_event2 true deassert_event7 true event0_state_ret true event1_state_ret true event2_state_ret true event7_state_ret true id_string "DIMM Status "$OWNER_MC endsdr OpenIPMI-2.0.33/lanserv/marvell-bmc/main.sdrs0000644000175000017500000004161112116456523015604 00000000000000# # # # chassis 23 1 # board 1-n 41 n # CPU 3 n # DIMM 8 n # PSUs 1-n 10 n # Fans 1-n 29 n # Switch 42 1 # CPU 3 n+1 sdr type 18 device_slave_address 0x20 device_channel_number 0 chassis true ipmb_event_gen true ipmb_event_recv true fru_inventory true sel true sdr true sensor true entity_id connectivity_switch entity_instance 1 id_string "AXP switch" endsdr sdr type 8 container_entity_id system_chassis container_entity_inst 1 entity_1_id power_supply entity_1_inst 1 entity_2_id power_supply entity_2_inst 2 entity_3_id connectivity_switch entity_3_inst 1 endsdr sdr type 8 container_entity_id system_chassis container_entity_inst 1 entity_1_id fan_cooling_device entity_1_inst 1 entity_2_id fan_cooling_device entity_2_inst 2 entity_3_id fan_cooling_device entity_3_inst 3 entity_4_id fan_cooling_device entity_4_inst 4 endsdr sdr type 8 container_entity_id system_chassis container_entity_inst 1 entity_1_id fan_cooling_device entity_1_inst 5 entity_2_id fan_cooling_device entity_2_inst 6 entity_3_id fan_cooling_device entity_3_inst 7 entity_4_id fan_cooling_device entity_4_inst 8 endsdr sdr type 8 container_entity_id system_chassis container_entity_inst 1 entity_1_id processing_blade entity_1_inst 1 entity_2_id processing_blade entity_2_inst 2 entity_3_id processing_blade entity_3_inst 3 entity_4_id processing_blade entity_4_inst 4 endsdr sdr type 8 container_entity_id system_chassis container_entity_inst 1 entity_1_id processing_blade entity_1_inst 5 entity_2_id processing_blade entity_2_inst 6 endsdr sdr type 8 container_entity_id connectivity_switch container_entity_inst 1 entity_1_id processor entity_1_inst 7 endsdr # Switch reset reason sdr type 3 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 20 entity_id connectivity_switch entity_instance 1 sensor_type System_Boot_Initiated event_reading_type_code 0x6f id_string "reset reason" endsdr # Switch temp sensor sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 1 entity_id connectivity_switch entity_instance 1 init_scanning true init_sensor_type true default_sensor_scan_on true sensor_type Temperature event_reading_type_code 1 analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 id_string "switch temp" endsdr # Switch CPU temp sensor sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 2 entity_id processor entity_instance 7 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Temperature event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true return_unr true assert_lncgl true deassert_lncgl true assert_lcgl true deassert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true assert_unrgh true deassert_unrgh true lc_thrsh_settable true lnc_thrsh_settable true unr_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 unr_thresh 115 uc_thresh 90 unc_thresh 75 lnc_thresh 5 lc_thresh 0 positive_hysteresis 2 negative_hysteresis 2 id_string "switch CPU temp" endsdr # Switch 12V sensor # Range from 10-14 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 3 entity_id connectivity_switch entity_instance 1 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 16 tolerance 0 b 10 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -3 b_exp 3 nominal_specified true nominal_freading 12.0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 12.6 unc_fthresh 12.36 lnc_fthresh 11.64 lc_fthresh 11.4 positive_hysteresis 2 negative_hysteresis 2 id_string "12V Switch" endsdr # Switch 3.3 sensor # Range 2.9 - 3.7 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 4 entity_id connectivity_switch entity_instance 1 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 313 tolerance 0 b 29 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 3.3 sensor_maximum 255 sensor_minimum 0 uc_fthresh 3.465 unc_fthresh 3.399 lnc_fthresh 3.201 lc_fthresh 3.135 positive_hysteresis 2 negative_hysteresis 2 id_string "3.3V Switch" endsdr # Switch 1.8V sensor # Range 1.6-1.8 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 5 entity_id connectivity_switch entity_instance 1 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 156 tolerance 0 b 16 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -5 b_exp 4 nominal_specified true nominal_freading 1.8 sensor_maximum 255 sensor_minimum 0 uc_fthresh 1.89 unc_fthresh 1.854 lnc_fthresh 1.746 lc_fthresh 1.71 positive_hysteresis 2 negative_hysteresis 2 id_string "1.8V Switch" endsdr # PSU status sensors sdr type 2 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 8 entity_id power_supply entity_instance 1 init_scanning true init_events true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm false sensor_type Power_Supply event_reading_type_code 0x6f assert_event0 true assert_event1 true assert_event2 true assert_event3 true assert_event4 true assert_event5 true assert_event6 true deassert_event0 true deassert_event1 true deassert_event2 true deassert_event3 true deassert_event4 true deassert_event5 true deassert_event6 true event0_state_ret true event1_state_ret true event2_state_ret true event3_state_ret true event4_state_ret true event5_state_ret true event6_state_ret true id_string "PSU1 status" endsdr sdr type 2 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 9 entity_id power_supply entity_instance 2 init_scanning true init_events true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm false sensor_type Power_Supply event_reading_type_code 0x6f assert_event0 true assert_event1 true assert_event2 true assert_event3 true assert_event4 true assert_event5 true assert_event6 true deassert_event0 true deassert_event1 true deassert_event2 true deassert_event3 true deassert_event4 true deassert_event5 true deassert_event6 true event0_state_ret true event1_state_ret true event2_state_ret true event3_state_ret true event4_state_ret true event5_state_ret true event6_state_ret true id_string "PSU2 status" endsdr # PSU voltage sensors (12v) # Range 10-14 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 10 entity_id power_supply entity_instance 1 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 16 tolerance 0 b 10 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -3 b_exp 3 nominal_specified true nominal_freading 12.0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 12.6 unc_fthresh 12.36 lnc_fthresh 11.64 lc_fthresh 11.4 positive_hysteresis 2 negative_hysteresis 2 id_string "PSU1 voltage" endsdr sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 11 entity_id power_supply entity_instance 2 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Voltage event_reading_type_code 1 return_lnc true return_lc true return_unc true return_uc true deassert_lncgl true assert_lncgl true deassert_lcgl true assert_lcgl true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true lc_thrsh_settable true lnc_thrsh_settable true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Volts modifier_unit_code unspecified linearization linear m 16 tolerance 0 b 10 accuracy 1 accuracy_exp 0 sensor_direction input r_exp -3 b_exp 3 nominal_specified true nominal_freading 12.0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 12.6 unc_fthresh 12.36 lnc_fthresh 11.64 lc_fthresh 11.4 positive_hysteresis 2 negative_hysteresis 2 id_string "PSU2 voltage" endsdr # PSU current sensors # Range 0-63 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 12 entity_id power_supply entity_instance 1 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Current event_reading_type_code 1 return_unc true return_uc true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Amps modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 60 unc_fthresh 55 positive_hysteresis 2 negative_hysteresis 2 id_string "PSU1 current" endsdr sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 13 entity_id power_supply entity_instance 2 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Current event_reading_type_code 1 return_unc true return_uc true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Amps modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 60 unc_fthresh 55 positive_hysteresis 2 negative_hysteresis 2 id_string "PSU2 current" endsdr # PSU power sensors # Range 0-2550 sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 14 entity_id power_supply entity_instance 1 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Current event_reading_type_code 1 return_unc true return_uc true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Watts modifier_unit_code unspecified linearization linear m 10 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 480 unc_fthresh 440 positive_hysteresis 2 negative_hysteresis 2 id_string "PSU1 power" endsdr sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 15 entity_id power_supply entity_instance 2 init_scanning true init_events true init_thresholds true init_hysteresis true init_sensor_type true default_event_gen_on true default_sensor_scan_on true sensor_auto_rearm true sensor_hysteresis settable sensor_threshold_access settable sensor_event_msg_ctrl per_state sensor_type Current event_reading_type_code 1 return_unc true return_uc true assert_uncgh true deassert_uncgh true assert_ucgh true deassert_ucgh true uc_thrsh_settable true unc_thrsh_settable true analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit Watts modifier_unit_code unspecified linearization linear m 10 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 uc_fthresh 480 unc_fthresh 440 positive_hysteresis 2 negative_hysteresis 2 id_string "PSU2 power" endsdr define FAN "1" include "fan.sdrs" define FAN "2" include "fan.sdrs" define FAN "3" include "fan.sdrs" define FAN "4" include "fan.sdrs" define FAN "5" include "fan.sdrs" define FAN "6" include "fan.sdrs" define FAN "7" include "fan.sdrs" define FAN "8" include "fan.sdrs" define OWNER_MC "1" include "board.sdrs" define OWNER_MC "2" include "board.sdrs" define OWNER_MC "3" include "board.sdrs" define OWNER_MC "4" include "board.sdrs" define OWNER_MC "5" include "board.sdrs" define OWNER_MC "6" include "board.sdrs" OpenIPMI-2.0.33/lanserv/marvell-bmc/interfaces0000644000175000017500000000047512116456624016036 00000000000000# /etc/network/interfaces for the BMC # Configure Loopback auto lo iface lo inet loopback auto eth0 eth1 eth1:1 iface eth0 inet dhcp iface eth1 inet static gateway 192.168.0.254 address 192.168.0.10 netmask 255.255.255.0 # Internal network iface eth1:1 inet static address 192.168.1.7 netmask 255.255.255.0 OpenIPMI-2.0.33/lanserv/lanserv_config.c0000664000175000017500000001454513136461257014740 00000000000000/* * lanserv_config.c * * MontaVista IPMI code for reading lanserv configuration files. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2002,2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #ifndef IPMI_LAN_STD_PORT_STR #define IPMI_LAN_STD_PORT_STR "623" #endif int lanserv_read_config(sys_data_t *sys, FILE *f, int *line, unsigned int channel_num) { char buf[MAX_CONFIG_LINE]; const char *tok; char *tokptr; unsigned int val; int err = 0; const char *errstr; lanserv_data_t *lan; lan = sys->alloc(sys, sizeof(*lan)); if (!lan) { err = -1; errstr = "Out of memory allocating lan data"; goto out_err; } memset(lan, 0, sizeof(*lan)); lan->sysinfo = sys; lan->channel.chan_info = lan; lan->channel.channel_num = channel_num; lan->channel.medium_type = IPMI_CHANNEL_MEDIUM_8023_LAN; lan->channel.protocol_type = IPMI_CHANNEL_PROTOCOL_IPMB; lan->channel.session_support = IPMI_CHANNEL_MULTI_SESSION; lan->users = sys->cusers; if (sys->chan_set[channel_num]) { err = -1; errstr = "Channel already in use"; goto out_err; } while (fgets(buf, sizeof(buf), f) != NULL) { (*line)++; tok = mystrtok(buf, " \t\n", &tokptr); if (!tok || (tok[0] == '#')) continue; if (strcmp(tok, "endlan") == 0) { sys->chan_set[channel_num] = &lan->channel; return 0; } if (strcmp(tok, "PEF_alerting") == 0) { err = get_bool(&tokptr, &val, &errstr); lan->channel.PEF_alerting = val; } else if (strcmp(tok, "per_msg_auth") == 0) { err = get_bool(&tokptr, &val, &errstr); lan->channel.per_msg_auth = val; } else if (strcmp(tok, "priv_limit") == 0) { err = get_priv(&tokptr, &val, &errstr); lan->channel.privilege_limit = val; } else if (strcmp(tok, "allowed_auths_callback") == 0) { err = get_auths(&tokptr, &val, &errstr); lan->channel.priv_info[0].allowed_auths = val; } else if (strcmp(tok, "allowed_auths_user") == 0) { err = get_auths(&tokptr, &val, &errstr); lan->channel.priv_info[1].allowed_auths = val; } else if (strcmp(tok, "allowed_auths_operator") == 0) { err = get_auths(&tokptr, &val, &errstr); lan->channel.priv_info[2].allowed_auths = val; } else if (strcmp(tok, "allowed_auths_admin") == 0) { err = get_auths(&tokptr, &val, &errstr); lan->channel.priv_info[3].allowed_auths = val; } else if (strcmp(tok, "addr") == 0) { if (lan->lan_addr_set) { fprintf(stderr, "LAN address already set, line %d\n", *line); return -1; } err = get_sock_addr(&tokptr, &lan->lan_addr.addr, &lan->lan_addr.addr_len, IPMI_LAN_STD_PORT_STR, SOCK_DGRAM, &errstr); lan->lan_addr_set = 1; if (!err) { if (lan->lan_addr.addr.s_ipsock.s_addr0.sa_family == AF_INET) lan->port = lan->lan_addr.addr.s_ipsock.s_addr4.sin_port; else if (lan->lan_addr.addr.s_ipsock.s_addr0.sa_family == AF_INET6) lan->port = lan->lan_addr.addr.s_ipsock.s_addr6.sin6_port; else lan->port = 0; lan->port = htons(lan->port); } } else if (strcmp(tok, "guid") == 0) { if (!lan->guid) lan->guid = malloc(16); if (!lan->guid) return -1; err = read_bytes(&tokptr, lan->guid, &errstr, 16); if (err) goto out_err; } else if (strcmp(tok, "bmc_key") == 0) { if (!lan->bmc_key) lan->bmc_key = malloc(20); if (!lan->bmc_key) return -1; err = read_bytes(&tokptr, lan->bmc_key, &errstr, 20); if (err) goto out_err; } else if (strcmp(tok, "lan_config_program") == 0) { err = get_delim_str(&tokptr, &lan->config_prog, &errstr); if (err) goto out_err; } else { errstr = "Invalid configuration option"; err = -1; } if (err) { out_err: sys->free(sys, lan); fprintf(stderr, "Error on line %d: %s\n", *line, errstr); return err; } } sys->free(sys, lan); fprintf(stderr, "End of file in lan section\n"); return -1; } OpenIPMI-2.0.33/lanserv/bmc_transport.c0000644000175000017500000001615513042446666014616 00000000000000/* * 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 }; OpenIPMI-2.0.33/lanserv/sol.c0000664000175000017500000013166514002617260012527 00000000000000/* * sol.c * * MontaVista IPMI code for running the SOL protocol. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipmi_sim.h" #include "sol.h" #include "emu.h" static int sol_init_mc(sys_data_t *sys, lmc_data_t *mc); /* FIXME - move to configure handling */ #define USE_UUCP_LOCKING #define SOL_INBUF_SIZE 32 #define SOL_OUTBUF_SIZE 16384 #define SOL_TELNET_IAC 255 #define SOL_TELNET_DONT 254 #define SOL_TELNET_DO 253 #define SOL_TELNET_WONT 252 #define SOL_TELNET_WILL 251 #define SOL_TELNET_SB 250 #define SOL_TELNET_SE 240 #define SOL_TELNET_BREAK 243 #define SOL_TELNETCODE_BINARY 0 #define SOL_TELNETCODE_ECHO 1 enum sol_telnet_state { SOL_TELNETST_NORMAL = 0, SOL_TELNETST_IAC, SOL_TELNETST_TWOBYTE, SOL_TELNETST_SUBNEG, SOL_TELNETST_SUBNEG_IAC }; struct soldata_s { int fd; sys_data_t *sys; ipmi_io_t *fd_id; struct termios termctl; int modemstate; channel_t *channel; /* Channel for I/O */ channel_t *logchan; /* Channel for logging errors. */ msg_t dummy_send_msg; /* Data from the remote to the serial port */ unsigned char inbuf[SOL_INBUF_SIZE]; unsigned int inlen; /* Data from the serial port to the remote */ unsigned char outbuf[SOL_OUTBUF_SIZE]; unsigned int outlen; /* * A circular history buffer. Note that history_end points to the * last byte (not one past the last byte) and history_start points * to the first byte. */ unsigned char *history; int history_start; int history_end; /* * Used to register history file handler on a shutdown. */ ipmi_shutdown_t backupfilehandler; /* * The amount of actual history to store when the copy request happens. * If zero, this is ignored. This is guaranteed to be <= history_size. * If this is non-zero, this is the */ unsigned int history_return_size; /* A copy of the history, used for reliable streaming. */ unsigned char *history_copy; unsigned int history_copy_size; unsigned int history_pos; msg_t history_dummy_send_msg; channel_t *history_channel; int history_last_acked_packet; int history_last_acked_packet_len; int history_curr_packet_seq; char history_in_nack; ipmi_timer_t *history_timer; unsigned int history_num_sends; char in_nack; char read_enabled; char write_enabled; char waiting_ack; int last_acked_packet; int last_acked_packet_len; int curr_packet_seq; ipmi_timer_t *timer; unsigned int num_sends; enum sol_telnet_state telnet_state; unsigned char telnet_twobyte; void (*reset_modemstate)(ipmi_sol_t *sol); void (*update_bitrate)(ipmi_sol_t *sol); void (*send_break)(ipmi_sol_t *sol); void (*update_modemstate)(ipmi_sol_t *sol, int ctspaus, int deassertdcd); int (*activate)(ipmi_sol_t *sol, msg_t *msg); void (*shutdown)(ipmi_sol_t *sol); int (*initialize)(ipmi_sol_t *sol); }; #ifdef USE_UUCP_LOCKING static char *uucp_lck_dir = "/var/lock"; static char *progname = "ipmisim"; static int uucp_fname_lock_size(const char *devname) { const char *ptr; (ptr = strrchr(devname, '/')); if (ptr == NULL) { ptr = devname; } else { ptr = ptr + 1; } return 7 + strlen(uucp_lck_dir) + strlen(ptr); } static void uucp_fname_lock(char *buf, const char *devname) { const char *ptr; (ptr = strrchr(devname, '/')); if (ptr == NULL) { ptr = devname; } else { ptr = ptr + 1; } sprintf(buf, "%s/LCK..%s", uucp_lck_dir, ptr); } static int write_full(int fd, char *data, size_t count) { ssize_t written; restart: while ((written = write(fd, data, count)) > 0) { data += written; count -= written; } if (written < 0) { if (errno == EAGAIN) goto restart; return -1; } return 0; } static void uucp_rm_lock(sys_data_t *sys, const char *devname) { char *lck_file; lck_file = sys->alloc(sys, uucp_fname_lock_size(devname)); if (lck_file == NULL) { return; } uucp_fname_lock(lck_file, devname); unlink(lck_file); sys->free(sys, lck_file); } /* return 0=OK, -1=error, 1=locked by other proces */ static int uucp_mk_lock(sys_data_t *sys, const char *devname) { struct stat stt; int pid = -1; if (stat(uucp_lck_dir, &stt) == 0) { /* is lock file directory present? */ char *lck_file; union { uint32_t ival; char str[64]; } buf; int fd; lck_file = sys->alloc(sys, uucp_fname_lock_size(devname)); if (lck_file == NULL) return -1; uucp_fname_lock(lck_file, devname); pid = 0; if ((fd = open(lck_file, O_RDONLY)) >= 0) { int n; n = read(fd, &buf, sizeof(buf) - 1); close(fd); if( n == 4 ) /* Kermit-style lockfile. */ pid = buf.ival; else if (n > 0) { /* Ascii lockfile. */ buf.str[n] = 0; sscanf(buf.str, "%d", &pid); } if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { /* death lockfile - remove it */ unlink(lck_file); sleep(1); pid = 0; } } if (pid == 0) { int mask; int rv; mask = umask(022); fd = open(lck_file, O_WRONLY | O_CREAT | O_EXCL, 0666); umask(mask); if (fd >= 0) { snprintf(buf.str, sizeof(buf), "%10ld\t%s\n", (long)getpid(), progname ); rv = write_full(fd, buf.str, strlen(buf.str)); close(fd); if (rv < 0) { pid = -errno; unlink(lck_file); } } else { pid = -errno; } } sys->free(sys, lck_file); } return pid; } #endif /* USE_UUCP_LOCKING */ static int sol_to_termios_bitrate(ipmi_sol_t *sol, int solbps) { int retried = 0; retry: switch(solbps) { case 6: return B9600; case 7: return B19200; case 8: return B38400; case 9: return B57600; case 10: return B115200; case 0: default: if (retried) return B9600; solbps = sol->solparm.default_bitrate; retried =1; goto retry; } } static void sol_serial_reset_modemstate(ipmi_sol_t *sol) { int modemstate; /* Turn on CTS and DCD if we have history, off if not */ /* Assuming standard NULL modem, RTS->CTS, DTR->DSR/DCD */ ioctl(sol->soldata->fd, TIOCMGET, &modemstate); if (sol->history_size) modemstate |= TIOCM_DTR | TIOCM_RTS; else modemstate &= ~(TIOCM_DTR | TIOCM_RTS); sol->soldata->modemstate = modemstate & (TIOCM_DTR | TIOCM_RTS); ioctl(sol->soldata->fd, TIOCMSET, &modemstate); } #ifndef HAVE_CFMAKERAW static void cfmakeraw(struct termios *t) { t->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); t->c_oflag &= ~OPOST; t->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); t->c_cflag &= ~(CSIZE | PARENB); t->c_cflag |= CS8; } #endif /* Initialize a serial port control structure for the first time. */ static void devinit(ipmi_sol_t *sol, struct termios *termctl) { int bitrate = sol_to_termios_bitrate(sol, sol->solparm.bitrate); cfmakeraw(termctl); cfsetospeed(termctl, bitrate); cfsetispeed(termctl, bitrate); termctl->c_cflag &= ~(CSTOPB); termctl->c_cflag &= ~(CSIZE); termctl->c_cflag |= CS8; termctl->c_cflag &= ~(PARENB); termctl->c_cflag |= CLOCAL; termctl->c_cflag &= ~(HUPCL); termctl->c_cflag |= CREAD; if (sol->use_rtscts) termctl->c_cflag |= CRTSCTS; else termctl->c_cflag &= ~(CRTSCTS); termctl->c_iflag &= ~(IXON | IXOFF | IXANY); termctl->c_iflag |= IGNBRK; sol_serial_reset_modemstate(sol); } static void sol_serial_update_bitrate(ipmi_sol_t *sol) { int bitrate = sol_to_termios_bitrate(sol, sol->solparm.bitrate); cfsetospeed(&sol->soldata->termctl, bitrate); cfsetispeed(&sol->soldata->termctl, bitrate); tcsetattr(sol->soldata->fd, TCSANOW, &sol->soldata->termctl); } static void sol_serial_send_break(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; tcsendbreak(sd->fd, 0); } static void sol_serial_update_modemstate(ipmi_sol_t *sol, int ctspause, int deassert_dcd) { soldata_t *sd = sol->soldata; /* * If history is enabled, we don't allow DCD/CTS fiddling, just leave * them on all the time. */ if (!sol->history_size) { int modemstate = 0; if (!ctspause) modemstate |= TIOCM_RTS; if (!deassert_dcd) modemstate |= TIOCM_DTR; if (modemstate != sd->modemstate) { int val; ioctl(sol->soldata->fd, TIOCMGET, &val); val &= ~(TIOCM_DTR | TIOCM_RTS); val |= modemstate; ioctl(sol->soldata->fd, TIOCMSET, &val); sd->modemstate = modemstate; } } } static int sol_serial_activate(ipmi_sol_t *sol, msg_t *msg) { soldata_t *sd = sol->soldata; /* * Note that we enable CTS and DCD if history is set, because we * always monitor the history. */ if (!sol->history_size) { int modemstate; ioctl(sd->fd, TIOCMGET, &modemstate); if ((msg->data[2] & 1) == 0) { /* Assuming standard NULL modem, RTS->CTS, DTR->DSR/DCD */ modemstate |= TIOCM_DTR | TIOCM_RTS; sd->modemstate = TIOCM_DTR | TIOCM_RTS; } else { modemstate &= ~(TIOCM_DTR | TIOCM_RTS); sd->modemstate = 0; } ioctl(sd->fd, TIOCMSET, &modemstate); } return 0; } static void sol_serial_shutdown(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; if (sd->fd >= 0) close(sd->fd); sd->fd = -1; #ifdef USE_UUCP_LOCKING uucp_rm_lock(sd->sys, sol->device); #endif /* USE_UUCP_LOCKING */ } static int sol_serial_initialize(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; int err; #ifdef USE_UUCP_LOCKING err = uucp_mk_lock(sd->sys, sol->device); if (err > 0) { fprintf(stderr, "SOL device %s is already owned by process %d\n", sol->device, err); err = EBUSY; goto out_nounlock; } if (err < 0) { fprintf(stderr, "Error locking SOL device %s\n", sol->device); err = -err; goto out_nounlock; } #endif /* USE_UUCP_LOCKING */ devinit(sol, &sd->termctl); sd->fd = open(sol->device, O_NONBLOCK | O_NOCTTY | O_RDWR); if (sd->fd == -1) { err = errno; fprintf(stderr, "Error opening SOL device %s\n", sol->device); goto out; } err = tcsetattr(sd->fd, TCSANOW, &sd->termctl); if (err == -1) { err = errno; close(sd->fd); sd->fd = -1; fprintf(stderr, "Error configuring SOL device %s\n", sol->device); goto out; } /* Turn off BREAK. */ ioctl(sd->fd, TIOCCBRK); out: #ifdef USE_UUCP_LOCKING if (err) uucp_rm_lock(sd->sys, sol->device); out_nounlock: #endif return err; } static void sol_serial_setup(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; sd->reset_modemstate = sol_serial_reset_modemstate; sd->update_bitrate = sol_serial_update_bitrate; sd->send_break = sol_serial_send_break; sd->update_modemstate = sol_serial_update_modemstate; sd->activate = sol_serial_activate; sd->shutdown = sol_serial_shutdown; sd->initialize = sol_serial_initialize; } static void sol_tcp_reset_modemstate(ipmi_sol_t *sol) { } static void sol_tcp_update_bitrate(ipmi_sol_t *sol) { } static void sol_tcp_send_break(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; int left = sizeof(sd->inbuf) - sd->inlen; if (left < 2) return; sd->inbuf[sd->inlen++] = SOL_TELNET_IAC; sd->inbuf[sd->inlen++] = SOL_TELNET_BREAK; } static void sol_tcp_update_modemstate(ipmi_sol_t *sol, int ctspause, int deassert_dcd) { } static int sol_tcp_activate(ipmi_sol_t *sol, msg_t *msg) { return 0; } static void sol_tcp_shutdown(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; if (sd->fd >= 0) close_socket(sd->fd); sd->fd = -1; } static int sol_tcp_initialize(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; struct addrinfo hints, *addr; int rv; int options; if (sd->fd != -1) { sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error sol activate on active port %s:%s", sol->tcpdest, sol->tcpport); return -1; } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rv = getaddrinfo(sol->tcpdest, sol->tcpport, &hints, &addr); if (rv != 0) { sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error getting tcp sol port address for %s:%s: %s", sol->tcpdest, sol->tcpport, gai_strerror(rv)); return -1; } sd->fd = socket(addr->ai_family, SOCK_STREAM, 0); if (sd->fd == -1) { rv = -1; sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error creating tcp sol port socket for %s:%s: %s", sol->tcpdest, sol->tcpport, strerror(errno)); goto out; } rv = connect(sd->fd, addr->ai_addr, addr->ai_addrlen); if (rv == -1) { close_socket(sd->fd); sd->fd = -1; if (sd->sys->debug & DEBUG_SOL) sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error connecting tcp sol port socket for %s:%s: %s", sol->tcpdest, sol->tcpport, strerror(errno)); goto out; } options = 1; rv = setsockopt(sd->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &options, sizeof(options)); if (rv == -1) { close_socket(sd->fd); sd->fd = -1; sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error setting nodelay on tcp sol port socket" " for %s:%s: %s", sol->tcpdest, sol->tcpport, strerror(errno)); goto out; } rv = socket_set_nonblock(sd->fd); if (rv == -1) { close_socket(sd->fd); sd->fd = -1; sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error setting nonblock on tcp sol port socket" " for %s:%s: %s", sol->tcpdest, sol->tcpport, strerror(errno)); goto out; } out: freeaddrinfo(addr); return rv; } static void sol_tcp_setup(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; sd->reset_modemstate = sol_tcp_reset_modemstate; sd->update_bitrate = sol_tcp_update_bitrate; sd->send_break = sol_tcp_send_break; sd->update_modemstate = sol_tcp_update_modemstate; sd->activate = sol_tcp_activate; sd->shutdown = sol_tcp_shutdown; sd->initialize = sol_tcp_initialize; } static char *end_history_msg = "\r\n\r\n"; #define MAX_HISTORY_SEND 64 #define MAX_SOL_RESENDS 4 static void sol_timeout(void *cb_data); static void sol_history_timeout(void *cb_data); static void sol_data_ready(int fd, void *cb_data); static void sol_write_ready(int fd, void *cb_data); static void sol_set_history_return_size(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { ipmi_sol_t *sol = is_mc_get_sol(mc); soldata_t *sd = sol->soldata; unsigned int size; if (msg->len < 1) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!sd) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } size = msg->data[0] * 1024; if (size >= sol->history_size || size == 0) sd->history_return_size = 0; else sd->history_return_size = size; rdata[0] = 0; *rdata_len = 1; } static void sol_get_history_return_size(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { ipmi_sol_t *sol = is_mc_get_sol(mc); soldata_t *sd = sol->soldata; if (!sd) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = sd->history_return_size / 1024; *rdata_len = 2; } static void sol_session_closed(lmc_data_t *mc, uint32_t session_id, void *cb_data) { ipmi_sol_t *sol = cb_data; soldata_t *sd = sol->soldata; if (session_id == sol->session_id) { if (sol->soldata->dummy_send_msg.src_addr) { sd->sys->free(sd->sys, sol->soldata->dummy_send_msg.src_addr); sol->soldata->dummy_send_msg.src_addr = NULL; } sol->active = 0; sd->channel = NULL; sol->session_id = 0; sd->reset_modemstate(sol); } else if (session_id == sol->history_session_id) { if (sol->soldata->history_dummy_send_msg.src_addr) { sd->sys->free(sd->sys, sol->soldata->history_dummy_send_msg.src_addr); sol->soldata->history_dummy_send_msg.src_addr = NULL; } if (sol->soldata->history_copy) { sd->sys->free(sd->sys, sol->soldata->history_copy); sol->soldata->history_copy = NULL; } sol->history_active = 0; sol->history_session_id = 0; } } static unsigned char * copy_history_buffer(ipmi_sol_t *sol, unsigned int *rsize) { soldata_t *sd = sol->soldata; unsigned int to_copy; unsigned int endmsg_size = strlen(end_history_msg); unsigned char *dest = sd->sys->alloc(sd->sys, sol->history_size + endmsg_size); unsigned int size; int start; if (!dest) return NULL; if (sd->history_start > sd->history_end) /* Buffer is filled. */ size = sol->history_size; else if (sd->history_start == sd->history_end) size = 0; /* Nothing written yet. */ else /* Buffer is not yet filled, just runs from start to end */ size = sd->history_end - sd->history_start + 1; start = sd->history_start; if (sd->history_return_size && (size > sd->history_return_size)) { start += size - sd->history_return_size; if (start >= (int) sol->history_size) start -= sol->history_size; size = sd->history_return_size; } if (start > sd->history_end) { /* Buffer spans end, copy in two chunks. */ to_copy = sol->history_size - start; memcpy(dest + to_copy, sd->history, sd->history_end + 1); } else { /* Buffer is not yet filled, just runs from start to end */ to_copy = sd->history_end - start + 1; } memcpy(dest, sd->history + start, to_copy); memcpy(dest + size, end_history_msg, endmsg_size); size += endmsg_size; *rsize = size; if (sol->readclear) { sd->history_start = 0; sd->history_end = -1; } return dest; } unsigned char * sol_set_frudata(lmc_data_t *mc, unsigned int *size) { ipmi_sol_t *sol = is_mc_get_sol(mc); return copy_history_buffer(sol, size); } void sol_free_frudata(lmc_data_t *mc, unsigned char *data) { ipmi_sol_t *sol = is_mc_get_sol(mc); soldata_t *sd = sol->soldata; if (data) sd->sys->free(sd->sys, data); } void ipmi_sol_activate(lmc_data_t *mc, channel_t *channel, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { ipmi_sol_t *sol = is_mc_get_sol(mc); soldata_t *sd = sol->soldata; uint16_t port; int rv; msg_t *dmsg; unsigned int instance; if (!sol->solparm.enabled) { rdata[0] = 0x81; /* Payload is disabled. */ *rdata_len = 1; return; } /* * FIXME - we are currently ignoring all the payload encryption and * authentication bits in the message. */ instance = msg->data[1] & 0xf; if (instance == 1) { if (sol->active) { *rdata = 0x80; /* Payload already active */ *rdata_len = 1; return; } dmsg = &sd->dummy_send_msg; } else if (instance == 2 && sol->history_size) { if (sol->history_active) { *rdata = 0x80; /* Payload already active */ *rdata_len = 1; return; } dmsg = &sd->history_dummy_send_msg; } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } dmsg->src_addr = sd->sys->alloc(sd->sys, msg->src_len); if (!dmsg->src_addr) { rdata[0] = IPMI_OUT_OF_SPACE_CC; *rdata_len = 1; return; } memcpy(dmsg->src_addr, msg->src_addr, msg->src_len); dmsg->src_len = msg->src_len; dmsg->rmcpp.payload = IPMI_RMCPP_PAYLOAD_TYPE_SOL; rv = channel->set_associated_mc(channel, msg->sid, msg->data[0] & 0xf, mc, &port, sol_session_closed, sol); if (rv == EBUSY) { sd->sys->free(sd->sys, dmsg->src_addr); dmsg->src_addr = NULL; rdata[0] = IPMI_NODE_BUSY_CC; *rdata_len = 1; return; } else if (rv) { sd->sys->free(sd->sys, dmsg->src_addr); dmsg->src_addr = NULL; rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } dmsg->sid = msg->sid; if (instance == 1) { rv = sd->activate(sol, msg); if (rv) { sd->sys->free(sd->sys, dmsg->src_addr); dmsg->src_addr = NULL; rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } sol->active = 1; sol->session_id = msg->sid; sd->channel = channel; sd->outlen = 0; ipmi_set_uint16(rdata + 5, sizeof(sd->inbuf)); ipmi_set_uint16(rdata + 7, sizeof(sd->outbuf)); } else if (instance == 2 && sol->history_size) { struct timeval tv; sd->history_copy = copy_history_buffer(sol, &sd->history_copy_size); if (!sd->history_copy) { rdata[0] = IPMI_OUT_OF_SPACE_CC; *rdata_len = 1; return; } sd->history_pos = 0; sol->history_active = 1; sol->history_session_id = msg->sid; sd->history_channel = channel; ipmi_set_uint16(rdata + 5, MAX_HISTORY_SEND); ipmi_set_uint16(rdata + 7, MAX_HISTORY_SEND); tv.tv_sec = 0; tv.tv_usec = 0; /* Send immediately */ sd->history_num_sends = 0; sd->sys->start_timer(sd->history_timer, &tv); } rdata[0] = 0; ipmi_set_uint32(rdata + 1, 0); ipmi_set_uint16(rdata + 9, port); ipmi_set_uint16(rdata + 11, 0xffff); *rdata_len = 13; } void ipmi_sol_deactivate(lmc_data_t *mc, channel_t *channel, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { ipmi_sol_t *sol = is_mc_get_sol(mc); unsigned int instance; uint32_t session_id; instance = msg->data[1] & 0xf; if (instance == 1) { if (!sol->active) { *rdata = 0x80; /* Payload already deactivated */ *rdata_len = 1; return; } session_id = sol->session_id; } else if (instance == 2) { if (!sol->history_active) { *rdata = 0x80; /* Payload already deactivated */ *rdata_len = 1; return; } session_id = sol->history_session_id; } else { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sol_session_closed(mc, session_id, sol); channel->set_associated_mc(channel, session_id, msg->data[0] & 0xf, NULL, NULL, NULL, NULL); rdata[0] = 0; *rdata_len = 1; } static void sol_update_bitrate(lmc_data_t *mc) { ipmi_sol_t *sol = is_mc_get_sol(mc); soldata_t *sd = sol->soldata; sd->update_bitrate(is_mc_get_sol(mc)); } static void set_read_enable(soldata_t *sd) { int val; if (sd->history) return; if (sizeof(sd->outbuf) == sd->outlen) /* Read is always disabled if we have nothing to read into. */ val = 0; else val = !sd->in_nack; if (sd->read_enabled == val) return; sd->read_enabled = val; sd->sys->io_set_enables(sd->fd_id, sd->read_enabled, sd->write_enabled, 0); } static void set_write_enable(soldata_t *sd) { int val = sd->inlen > 0; if (sd->write_enabled == val) return; sd->write_enabled = val; sd->sys->io_set_enables(sd->fd_id, sd->read_enabled, sd->write_enabled, 0); } static void send_data(ipmi_sol_t *sol, int need_send_ack) { soldata_t *sd = sol->soldata; rsp_msg_t msg; unsigned char data[SOL_OUTBUF_SIZE + 4]; unsigned int size = sd->outlen; data[0] = sd->curr_packet_seq; if (need_send_ack) { data[1] = sd->last_acked_packet; data[2] = sd->last_acked_packet_len; } else { data[1] = 0; data[2] = 0; } data[3] = (sd->inlen == sizeof(sd->inbuf)) << 6; if (size > 255) size = 255; memcpy(data + 4, sd->outbuf, size); msg.data = data; msg.data_len = size + 4; sd->waiting_ack = 1; sd->channel->return_rsp(sd->channel, &sd->dummy_send_msg, &msg); } static void send_ack(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; rsp_msg_t msg; unsigned char data[SOL_OUTBUF_SIZE + 4]; data[0] = 0; data[1] = sd->last_acked_packet; data[2] = sd->last_acked_packet_len; data[3] = (sd->inlen == sizeof(sd->inbuf)) << 6; msg.data = data; msg.data_len = 4; sd->channel->return_rsp(sd->channel, &sd->dummy_send_msg, &msg); } static void next_seq(soldata_t *sd) { sd->curr_packet_seq++; if (sd->curr_packet_seq >= 16) sd->curr_packet_seq = 1; } static unsigned char sol_telnet_initseq[] = { SOL_TELNET_IAC, SOL_TELNET_DO, SOL_TELNETCODE_BINARY, SOL_TELNET_IAC, SOL_TELNET_WILL, SOL_TELNETCODE_BINARY, SOL_TELNET_IAC, SOL_TELNET_DONT, SOL_TELNETCODE_ECHO, SOL_TELNET_IAC, SOL_TELNET_WONT, SOL_TELNETCODE_ECHO }; static int sol_port_init(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; int err; err = sd->initialize(sol); if (err) goto out_err; sol->configured++; /* Marked that we locked the device. */ sol->update_bitrate = sol_update_bitrate; sd->read_enabled = 1; sd->write_enabled = 0; if (sol->do_telnet) { int len = sizeof(sol_telnet_initseq); memcpy(sd->inbuf, sol_telnet_initseq, len); sd->inlen = len; } err = sd->sys->add_io_hnd(sd->sys, sd->fd, sol_data_ready, sol, &sd->fd_id); if (err) { sol->configured--; sd->shutdown(sol); goto out_err; } sd->sys->io_set_hnds(sd->fd_id, sol_write_ready, NULL); set_write_enable(sd); out_err: return err; } static void sol_timeout(void *cb_data) { ipmi_sol_t *sol = cb_data; soldata_t *sd = sol->soldata; struct timeval tv; if (sd->fd == -1) { sol_port_init(sol); } else if (sol->active) { if (sd->num_sends > MAX_SOL_RESENDS) { sd->waiting_ack = 0; next_seq(sd); sd->outlen = 0; return; } sd->num_sends++; send_data(sol, 0); } if (sd->fd == -1) /* Attempt to reconnect every 10 seconds. */ tv.tv_sec = 10; else tv.tv_sec = 1; tv.tv_usec = 0; sd->sys->start_timer(sd->timer, &tv); } static void handle_sol_port_payload(lanserv_data_t *lan, ipmi_sol_t *sol, msg_t *msg) { soldata_t *sd = sol->soldata; unsigned char seq, ack, count; char isnack, isbreak, ctspause, deassert_dcd, flush_in, flush_out; unsigned char *data; unsigned int len; int need_send_ack = 0, is_dup = 0; struct timeval tv; if (!sol->active || msg->len < 4) return; seq = msg->data[0] & 0xf; ack = msg->data[1] & 0xf; count = msg->data[2]; isnack = msg->data[3] & (1 << 6); /* Ring Indicator is ignored for now */ isbreak = msg->data[3] & (1 << 4); ctspause = msg->data[3] & (1 << 3); deassert_dcd = msg->data[3] & (1 << 2); flush_in = msg->data[3] & (1 << 1); flush_out = msg->data[3] & (1 << 0); data = msg->data + 4; len = msg->len - 4; is_dup = seq == sd->last_acked_packet; if (!is_dup) { /* Don't re-do an operation that we already did. */ if (flush_out) { sd->waiting_ack = 0; next_seq(sd); sd->outlen = 0; } if (flush_in) { unsigned int oldlen = sd->inlen; sd->inlen = 0; if (oldlen == sizeof(sd->inbuf)) send_ack(sol); } if (isbreak) sd->send_break(sol); } /* Indepotent with respect to duplicates. */ sd->update_modemstate(sol, ctspause, deassert_dcd); if (seq != 0) { if (is_dup) { need_send_ack = 1; } else if (sd->fd == -1) { /* Ignore the data. */ sd->last_acked_packet = seq; need_send_ack = 1; sd->last_acked_packet_len = len; } else if (len) { sd->last_acked_packet = seq; if (sol->do_telnet) { unsigned int i; for (i = 0; i < len; i++) { int left = sizeof(sd->inbuf) - sd->inlen; if (left < 1) break; if (data[i] == SOL_TELNET_IAC) { if (left < 2) break; sd->inbuf[sd->inlen++] = SOL_TELNET_IAC; } sd->inbuf[sd->inlen++] = data[i]; } } else { if (len > (sizeof(sd->inbuf) - sd->inlen)) len = sizeof(sd->inbuf) - sd->inlen; memcpy(sd->inbuf + sd->inlen, data, len); sd->inlen += len; } sd->last_acked_packet_len = len; need_send_ack = 1; set_write_enable(sol->soldata); } else { sd->last_acked_packet = seq; sd->last_acked_packet_len = 0; need_send_ack = 1; } } if (ack == sd->curr_packet_seq) { next_seq(sd); sd->sys->stop_timer(sd->timer); if (isnack) { sd->in_nack = 1; set_read_enable(sd); } else { sd->in_nack = 0; if (count < sd->outlen) { unsigned int i; len = sd->outlen - count; for (i = 0; i < len; i++) sd->outbuf[i] = sd->outbuf[i + count]; sd->outlen = len; send_data(sol, need_send_ack); need_send_ack = 0; tv.tv_sec = 1; tv.tv_usec = 0; sd->sys->start_timer(sd->timer, &tv); } else { sd->waiting_ack = 0; sd->outlen = 0; } set_read_enable(sd); } } if (need_send_ack) send_ack(sol); } static int send_history_data(ipmi_sol_t *sol, int need_send_ack) { soldata_t *sd = sol->soldata; rsp_msg_t msg; unsigned char data[MAX_HISTORY_SEND + 4]; int to_send; to_send = sd->history_copy_size - sd->history_pos; if (to_send <= 0) return need_send_ack; if (to_send > MAX_HISTORY_SEND) to_send = MAX_HISTORY_SEND; data[0] = sd->history_curr_packet_seq; if (need_send_ack) { data[1] = sd->history_last_acked_packet; data[2] = sd->history_last_acked_packet_len; } else { data[1] = 0; data[2] = 0; } data[3] = 1 << 6; /* Always ready to get data, we just throw it away */ memcpy(data + 4, sd->history_copy + sd->history_pos, to_send); msg.data = data; msg.data_len = to_send + 4; sd->history_channel->return_rsp(sd->history_channel, &sd->history_dummy_send_msg, &msg); return 0; } static void send_history_ack(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; rsp_msg_t msg; unsigned char data[SOL_OUTBUF_SIZE + 4]; data[0] = 0; data[1] = sd->history_last_acked_packet; data[2] = sd->history_last_acked_packet_len; data[3] = 1 << 6; msg.data = data; msg.data_len = 4; sd->history_channel->return_rsp(sd->history_channel, &sd->history_dummy_send_msg, &msg); } static void sol_history_next_packet(soldata_t *sd) { /* Only send one size for history, no need to check msg's count */ sd->history_pos += MAX_HISTORY_SEND; sd->history_curr_packet_seq++; if (sd->history_curr_packet_seq >= 16) sd->history_curr_packet_seq = 1; sd->history_num_sends = 0; } static void sol_history_timeout(void *cb_data) { ipmi_sol_t *sol = cb_data; soldata_t *sd = sol->soldata; struct timeval tv; if (sd->history_num_sends > MAX_SOL_RESENDS) sol_history_next_packet(sd); if (sd->history_pos >= sd->history_copy_size) return; sd->history_num_sends++; send_history_data(sol, 0); tv.tv_sec = 1; tv.tv_usec = 0; sd->sys->start_timer(sd->history_timer, &tv); } static void handle_sol_history_payload(lanserv_data_t *lan, ipmi_sol_t *sol, msg_t *msg) { soldata_t *sd = sol->soldata; unsigned char seq, ack; char isnack; unsigned int len; int need_send_ack = 0; if (!sol->history_active || msg->len < 4) return; seq = msg->data[0] & 0xf; ack = msg->data[1] & 0xf; isnack = msg->data[3] & (1 << 6); len = msg->len - 4; if (seq != 0) { if (seq == sd->history_last_acked_packet) { need_send_ack = 1; } else if (len) { sd->history_last_acked_packet = seq; sd->history_last_acked_packet_len = len; need_send_ack = 1; } } if (ack == sd->history_curr_packet_seq) { if (isnack) { sd->history_in_nack = 1; } else { sd->history_in_nack = 0; sol_history_next_packet(sd); need_send_ack = send_history_data(sol, need_send_ack); } sd->sys->stop_timer(sd->history_timer); } if (need_send_ack) send_history_ack(sol); } static void handle_sol_payload(lanserv_data_t *lan, msg_t *msg) { ipmi_sol_t *sol; channel_t *channel = &lan->channel; lmc_data_t *mc; mc = channel->get_associated_mc(channel, msg->sid, IPMI_RMCPP_PAYLOAD_TYPE_SOL); if (!mc) return; sol = is_mc_get_sol(mc); if (msg->sid == sol->session_id) handle_sol_port_payload(lan, sol, msg); else if (msg->sid == sol->history_session_id) handle_sol_history_payload(lan, sol, msg); } static void sol_port_error(ipmi_sol_t *sol) { soldata_t *sd = sol->soldata; struct timeval tv; sd->sys->remove_io_hnd(sd->fd_id); sd->shutdown(sol); /* Clear any data to send to the serial port. */ sd->inlen = 0; /* Retry in 10 seconds. */ tv.tv_sec = 10; tv.tv_usec = 0; sd->sys->start_timer(sd->timer, &tv); } static void sol_write_ready(int fd, void *cb_data) { ipmi_sol_t *sol = cb_data; soldata_t *sd = sol->soldata; unsigned int oldlen; int rv; rv = write(fd, sd->inbuf, sd->inlen); if (rv < 0) { sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error writing to serial port: %d, disabling\n", errno); sol_port_error(sol); return; } if (rv == 0) return; if (((unsigned int) rv) < sd->inlen) memcpy(sd->inbuf, sd->inbuf + rv, sd->inlen - rv); oldlen = sd->inlen; sd->inlen -= rv; if (oldlen == sizeof(sd->inbuf)) send_ack(sol); set_write_enable(sd); } static void add_to_history(ipmi_sol_t *sol, unsigned char *buf, unsigned int len) { soldata_t *sd = sol->soldata; int to_copy; if (!sd->history || len == 0) return; /* * No point in handling more data than we can take, only take the * last history size section. */ if (len > sol->history_size) { buf += len - sol->history_size; len = sol->history_size; } if (sd->history_end + len + 1 > sol->history_size) { /* Wrap case, copy to the end and wrap history_end. */ to_copy = sol->history_size - sd->history_end - 1; memcpy(sd->history + sd->history_end + 1, buf, to_copy); sd->history_end = -1; len -= to_copy; buf += to_copy; } /* * At this point all the data should fit between history_end * and the end of the buffer. */ memcpy(sd->history + sd->history_end + 1, buf, len); if (sd->history_start > sd->history_end) { /* * Before we completely fill the buffer, history_start will * always be <= history_end. After we fill the buffer, * history_end will always be < history_start. */ sd->history_start += len; if (sd->history_start >= (int) sol->history_size) sd->history_start -= sol->history_size; } else if (sd->history_start == sd->history_end) { /* * First write to the buffer, it starts with start == end == 0, * so we need to fix things up on the first write. */ sd->history_start++; } sd->history_end += len; } static int sol_handle_telnet(ipmi_sol_t *sol, unsigned char *buf, int len) { soldata_t *sd = sol->soldata; int i, j; for (i = 0, j = 0; i < len; i++) { switch (sd->telnet_state) { case SOL_TELNETST_NORMAL: if (buf[i] == SOL_TELNET_IAC) sd->telnet_state = SOL_TELNETST_IAC; else buf[j++] = buf[i]; break; case SOL_TELNETST_IAC: switch (buf[i]) { case SOL_TELNET_DONT: case SOL_TELNET_DO: case SOL_TELNET_WONT: case SOL_TELNET_WILL: sd->telnet_twobyte = buf[i]; sd->telnet_state = SOL_TELNETST_TWOBYTE; break; case SOL_TELNET_SB: sd->telnet_state = SOL_TELNETST_SUBNEG; break; case SOL_TELNET_IAC: buf[j++] = SOL_TELNET_IAC; /* Fallthrough */ default: /* Ignore everything else. */ sd->telnet_state = SOL_TELNETST_NORMAL; break; } break; case SOL_TELNETST_TWOBYTE: /* Don't listen to these. */ sd->telnet_state = SOL_TELNETST_NORMAL; break; case SOL_TELNETST_SUBNEG: /* Don't listen to these. */ if (buf[i] == SOL_TELNET_IAC) sd->telnet_state = SOL_TELNETST_SUBNEG_IAC; break; case SOL_TELNETST_SUBNEG_IAC: if (buf[i] == SOL_TELNET_SE) sd->telnet_state = SOL_TELNETST_NORMAL; } } return j; } static void sol_data_ready(int fd, void *cb_data) { ipmi_sol_t *sol = cb_data; soldata_t *sd = sol->soldata; int rv; struct timeval tv; unsigned char buf[128]; unsigned int readsize = sizeof(buf); if (!sd->history && (readsize > (sizeof(sd->outbuf) - sd->outlen))) readsize = sizeof(sd->outbuf) - sd->outlen; rv = read(fd, buf, readsize); if (rv < 0) { sd->logchan->log(sd->logchan, OS_ERROR, NULL, "Error reading from serial port: %d, disabling\n", errno); sol_port_error(sol); return; } else if (rv == 0) { /* End of input, socket probably closed. */ sol_port_error(sol); return; } if (sol->do_telnet) rv = sol_handle_telnet(sol, buf, rv); add_to_history(sol, buf, rv); if (((unsigned int) rv) > (sizeof(sd->outbuf) - sd->outlen)) { /* Overflow happened. */ rv = sizeof(sd->outbuf) - sd->outlen; } if (!sol->active) { sd->outlen = 0; return; } memcpy(sd->outbuf + sd->outlen, buf, rv); sd->outlen += rv; /* Looks strange, but will turn off read if the buffer is full */ set_read_enable(sd); if (!sd->waiting_ack) { send_data(sol, 0); sd->num_sends = 0; tv.tv_sec = 1; tv.tv_usec = 0; sd->sys->start_timer(sd->timer, &tv); } } int is_sol_read_config(char **tokptr, sys_data_t *sys, const char **err) { ipmi_sol_t *sol = sys->sol; unsigned int val; int rv; const char *tok; sys->sol->use_rtscts = 1; rv = get_delim_str(tokptr, &sol->device, err); if (rv) return rv; if (strncmp(sol->device, "tcp:", 4) == 0) { sol->tcpdest = sol->device + 4; } else if (strncmp(sol->device, "telnet:", 7) == 0) { sol->do_telnet = 1; sol->tcpdest = sol->device + 7; } if (sol->tcpdest) { char *colon = strchr(sol->tcpdest, ':'); if (!colon) { *err = "No port specified in sol tcp connection"; return -1; } sol->tcpport = colon + 1; *colon = '\0'; } rv = get_uint(tokptr, &val, err); if (rv) return rv; switch (val) { case 9600: val = 6; break; case 19200: val = 7; break; case 38400: val = 8; break; case 57600: val = 9; break; case 115200: val = 10; break; default: *err = "Invalid bitrate, must be 9600, 19200, 38400, 57600, or 115200"; return -1; } while ((tok = mystrtok(NULL, " \t\n", tokptr))) { if (strncmp(tok, "history=", 8) == 0) { char *end, next; sol->history_size = strtoul(tok + 8, &end, 0); next = *end; while (next == ',') { char *opt = end + 1; end = strchr(opt, ','); if (!end) end = opt + strlen(opt); next = *end; *end = '\0'; if (strncmp(opt, "backupfile=", 11) == 0) { sol->backupfile = strdup(opt + 11); } else { *err = "Unknown history option"; return -1; } } if (*end != '\0') { *err = "Invalid history value"; return -1; } } else if (strncmp(tok, "historyfru=", 11) == 0) { char *end; unsigned int history_fru; history_fru = strtoul(tok + 11, &end, 0); if (*end != '\0') { *err = "Invalid history FRU value"; return -1; } if (history_fru >= 0xff) { *err = "history FRU value must be < 0xff"; return -1; } rv = ipmi_mc_add_fru_data(sys->mc, history_fru, 0, NULL, NULL); if (rv) { *err = "Cannot add frudata handler"; return -1; } rv = ipmi_mc_set_frudata_handler(sys->mc, history_fru, sol_set_frudata, sol_free_frudata); if (rv) { *err = "Cannot set frudata handler"; return -1; } } else if (strncmp(tok, "nortscts", 8) == 0) { sol->use_rtscts = 0; } else if (strncmp(tok, "readclear", 8) == 0) { sol->readclear = 1; } else { *err = "Invalid item"; return -1; } } sol->solparm.default_bitrate = val; sol->configured = 1; return 0; } int read_sol_config(sys_data_t *sys) { unsigned int i; int rv; for (i = 0; i < IPMI_MAX_MCS; i++) { lmc_data_t *mc = sys->ipmb_addrs[i]; ipmi_sol_t *sol; persist_t *p; long iv; if (!mc) continue; sol = is_mc_get_sol(mc); if (!sol->configured) continue; sys->sol_present = 1; sol->solparm.enabled = 1; sol->solparm.bitrate_nonv = 0; p = read_persist("sol.mc%2.2x", sys->mc_get_ipmb(mc)); if (p) { if (!read_persist_int(p, &iv, "enabled")) sol->solparm.enabled = iv; if (!read_persist_int(p, &iv, "bitrate")) sol->solparm.bitrate_nonv = iv; sol->solparm.bitrate = sol->solparm.bitrate_nonv; free_persist(p); } rv = sol_init_mc(sys, mc); if (rv) return rv; } return 0; } int write_sol_config(lmc_data_t *mc) { ipmi_sol_t *sol; persist_t *p; sol = is_mc_get_sol(mc); p = alloc_persist("sol.mc%2.2x", sol->soldata->sys->mc_get_ipmb(mc)); if (!p) return ENOMEM; sol = is_mc_get_sol(mc); add_persist_int(p, sol->solparm.enabled, "enabled"); add_persist_int(p, sol->solparm.bitrate_nonv, "bitrate"); write_persist(p); free_persist(p); return 0; } int sol_init(sys_data_t *sys) { int rv; rv = ipmi_emu_register_oi_iana_handler( OPENIPMI_IANA_CMD_SET_HISTORY_RETURN_SIZE, sol_set_history_return_size, NULL); if (rv) return rv; rv = ipmi_emu_register_oi_iana_handler( OPENIPMI_IANA_CMD_GET_HISTORY_RETURN_SIZE, sol_get_history_return_size, NULL); if (rv) return rv; return ipmi_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_SOL, handle_sol_payload); } static void handle_sol_shutdown(void *info, int sig) { ipmi_sol_t *sol = info; soldata_t *sd = sol->soldata; FILE *f; if (sol->configured < 2 || !sd) return; sol->configured--; sd->shutdown(sol); if (!sol->backupfile || (sd->history_start == sd->history_end)) return; /* * Write the current history to the backup file. */ f = fopen(sol->backupfile, "w"); if (!f) return; if (sd->history_end >= sd->history_start) { /* History is fully contained between start and end. */ fwrite(sd->history + sd->history_start, 1, sd->history_end - sd->history_start + 1, f); } else { /* History laps over end, need two writes. */ fwrite(sd->history + sd->history_start, 1, sol->history_size - sd->history_start, f); fwrite(sd->history, 1, sd->history_end + 1, f); } fclose(f); } static int sol_init_mc(sys_data_t *sys, lmc_data_t *mc) { ipmi_sol_t *sol = is_mc_get_sol(mc); soldata_t *sd; sd = sys->alloc(sys, sizeof(*sd)); if (!sd) return ENOMEM; memset(sd, 0, sizeof(*sd)); sd->sys = sys; sol->soldata = sd; if (sol->tcpdest) sol_tcp_setup(sol); else sol_serial_setup(sol); if (sys->alloc_timer(sys, sol_timeout, sol, &sd->timer)) { sys->free(sys, sd); return ENOMEM; } if (sol->history_size) { if (sys->alloc_timer(sys, sol_history_timeout, sol, &sd->history_timer)) { sys->free_timer(sd->timer); sys->free(sys, sd); return ENOMEM; } sd->history = sys->alloc(sys, sol->history_size); if (!sd->history) { sys->free_timer(sd->history_timer); sys->free_timer(sd->timer); sys->free(sys, sd); return ENOMEM; } if (sol->backupfile) { FILE *f = fopen(sol->backupfile, "r"); if (f) { /* Ignore errors, it doesn't really matter. */ fseek(f, -sol->history_size, SEEK_END); sd->history_end = fread(sd->history, 1, sol->history_size, f); sd->history_end--; /* end point to last, not one after. */ fclose(f); } } } sd->backupfilehandler.handler = handle_sol_shutdown; sd->backupfilehandler.info = sol; ipmi_register_shutdown_handler(&sd->backupfilehandler); sd->fd = -1; sd->curr_packet_seq = 1; sd->history_curr_packet_seq = 1; sd->logchan = sd->sys->mc_get_channelset(mc)[0]; if (sol_port_init(sol)) { /* Retry in 10 seconds. */ struct timeval tv; tv.tv_sec = 10; tv.tv_usec = 0; sd->sys->start_timer(sd->timer, &tv); } return 0; } OpenIPMI-2.0.33/lanserv/extcmd.c0000664000175000017500000002723514002617260013213 00000000000000/* * extcmd.c * * MontaVista IPMI IPMI LAN interface extern command handler * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_NETINET_ETHER_H #include #elif defined(HAVE_SYS_ETHERNET_H) #include #else #include #include struct ether_addr { uint8_t ether_addr_octet[6]; }; static char * ether_ntoa_r(const struct ether_addr *addr, char *buf) { sprintf(buf, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", addr->ether_addr_octet[0], addr->ether_addr_octet[1], addr->ether_addr_octet[2], addr->ether_addr_octet[3], addr->ether_addr_octet[4], addr->ether_addr_octet[5]); return buf; } static struct ether_addr * ether_aton_r(const char *asc, struct ether_addr *addr) { int rv; unsigned int v[6], i; rv = sscanf(asc, "%x:%x:%x:%x:%x:%x", &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]); if (rv < 6) return NULL; for (i = 0; i < 6; i++) { if (v[i] > 255) return NULL; } for (i = 0; i < 6; i++) addr->ether_addr_octet[i] = v[i]; return addr; } #endif static int extcmd_getval(void *baseloc, extcmd_info_t *t, char *val) { unsigned char *loc = baseloc; char *end; int ival; struct in_addr iaddr; while (isspace(*val)) val++; loc += t->offset; switch (t->type) { case extcmd_ip: if (inet_aton(val, &iaddr) == 0) return EINVAL; loc[3] = (iaddr.s_addr >> 24) & 0xff; loc[2] = (iaddr.s_addr >> 16) & 0xff; loc[1] = (iaddr.s_addr >> 8) & 0xff; loc[0] = (iaddr.s_addr >> 0) & 0xff; break; case extcmd_mac: if (ether_aton_r(val, (struct ether_addr *) loc) == 0) return EINVAL; break; case extcmd_uchar: if (*val == '\0') return EINVAL; if (t->map) { char *eval = val; unsigned int i; while (*eval && !isspace(*eval)) eval++; for (i = 0; t->map[i].name; i++) { if (strncmp(t->map[i].name, val, eval - val) == 0) break; } if (!t->map[i].name) return EINVAL; ival = t->map[i].value; } else { ival = strtol(val, &end, 0); if (!isspace(*end) && (*end != '\0')) return EINVAL; } *((unsigned char *) loc) = ival; break; case extcmd_int: if (*val == '\0') return EINVAL; if (t->map) { char *eval = val; unsigned int i; while (*eval && !isspace(*eval)) eval++; for (i = 0; t->map[i].name; i++) { if (strncmp(t->map[i].name, val, eval - val) == 0) break; } if (!t->map[i].name) return EINVAL; ival = t->map[i].value; } else { ival = strtol(val, &end, 0); if (!isspace(*end) && (*end != '\0')) return EINVAL; } *((int *) loc) = ival; break; default: return EINVAL; } return 0; } static char * extcmd_setval(void *baseloc, extcmd_info_t *t) { unsigned char *loc = baseloc; char cbuf[20]; /* Big enough to hold IP, MAC and src */ char *buf = cbuf; struct in_addr iaddr; loc += t->offset; switch (t->type) { case extcmd_ip: iaddr.s_addr = loc[3] << 24; iaddr.s_addr |= loc[2] << 16; iaddr.s_addr |= loc[1] << 8; iaddr.s_addr |= loc[0] << 0; if (!inet_ntop(AF_INET, &iaddr, buf, sizeof(cbuf))) return NULL; break; case extcmd_ident: sprintf(buf, "%u %u", (unsigned char)loc[0], (unsigned char)loc[1]); break; case extcmd_mac: if (!ether_ntoa_r((struct ether_addr *) loc, buf)) return NULL; break; case extcmd_uchar: if (t->map) { unsigned int i; buf = NULL; for (i = 0; t->map[i].name; i++) { if (t->map[i].value == *((unsigned char *) loc)) { buf = t->map[i].name; break; } } if (!buf) return NULL; } else { sprintf(buf, "%u", *((unsigned char *) loc)); } break; case extcmd_int: if (t->map) { unsigned int i; buf = NULL; for (i = 0; t->map[i].name; i++) { if (t->map[i].value == *((int *) loc)) { buf = t->map[i].name; break; } } if (!buf) return NULL; } else { sprintf(buf, "%d", *((int *) loc)); } break; default: return NULL; } return strdup(buf); } static int process_extcmd_value(void *baseloc, extcmd_info_t *t, char *buf) { unsigned int len = strlen(t->name); while (buf) { while (*buf == '\n') buf++; if ((strncmp(buf, t->name, len) == 0) && buf[len] == ':') return extcmd_getval(baseloc, t, buf + len + 1); buf = strchr(buf, '\n'); } return EEXIST; } static int add_cmd(char **cmd, const char *name, char *value, int freevalue) { unsigned int size; char *newcmd; int rv = 0; if (freevalue && !value) { rv = EINVAL; goto out; } size = strlen(name) + 1; if (value) size += strlen(value) + 3; size += strlen(*cmd); newcmd = malloc(size + 1); if (!newcmd) { rv = ENOMEM; goto out; } strcpy(newcmd, *cmd); free(*cmd); strcat(newcmd, " "); strcat(newcmd, name); if (value) { strcat(newcmd, " \""); strcat(newcmd, value); strcat(newcmd, "\""); } *cmd = newcmd; out: if (freevalue) free(value); return rv; } int extcmd_getvals(sys_data_t *sys, void *baseloc, const char *incmd, extcmd_info_t *ts, unsigned int count) { int rv; char *cmd; FILE *f = NULL; unsigned int i; char buf[2048]; unsigned int buflen = sizeof(buf); if (!incmd) return 0; cmd = malloc(strlen(incmd) + 5); if (!cmd) return ENOMEM; strcpy(cmd, incmd); strcat(cmd, " get"); for (i = 0; i < count; i++) { rv = add_cmd(&cmd, ts[i].name, NULL, 0); if (rv) { sys->log(sys, OS_ERROR, NULL, "Out of memory in extcmd read command\n"); goto out; } } f = popen(cmd, "r"); if (!f) { sys->log(sys, OS_ERROR, NULL, "Unable to execute extcmd read command (%s): %s\n", cmd, strerror(errno)); rv = errno; goto out; } rv = fread(buf, 1, buflen - 1, f); if ((unsigned int) rv == buflen - 1) { sys->log(sys, OS_ERROR, NULL, "Output of extcmd config read command (%s) is too big", cmd); rv = EINVAL; goto out; } buf[rv] = '\0'; rv = pclose(f); f = NULL; if (rv) { sys->log(sys, OS_ERROR, NULL, "extcmd read command (%s) failed: %x: %s", cmd, rv, buf); goto out; } for (i = 0; i < count; i++) { rv = process_extcmd_value(baseloc, ts + i, buf); if (rv) { sys->log(sys, OS_ERROR, NULL, "Setting extern command value of %s failed: %s", ts[i].name, strerror(rv)); goto out; } } out: if (f) pclose(f); free(cmd); return rv; } int extcmd_setvals(sys_data_t *sys, void *baseloc, const char *incmd, extcmd_info_t *ts, unsigned char *setit, unsigned int count) { int rv = 0; char *cmd; FILE *f = NULL; unsigned int i; char buf[2048]; unsigned int buflen = sizeof(buf); int oneset = 0; if (!incmd) return 0; cmd = malloc(strlen(incmd) + 5); if (!cmd) return ENOMEM; strcpy(cmd, incmd); strcat(cmd, " set"); for (i = 0; i < count; i++) { if (setit && !setit[i]) continue; oneset = 1; rv = add_cmd(&cmd, ts[i].name, extcmd_setval(baseloc, ts + i), 1); if (rv) { sys->log(sys, OS_ERROR, NULL, "Out of memory in extcmd write command (%d) %s\n", rv, strerror(rv)); goto out; } } if (!oneset) goto out; f = popen(cmd, "r"); if (!f) { sys->log(sys, OS_ERROR, NULL, "Unable to execute extcmd write command (%s): %s\n", cmd, strerror(errno)); rv = errno; goto out; } rv = fread(buf, 1, buflen - 1, f); if ((unsigned int) rv == buflen - 1) { sys->log(sys, OS_ERROR, NULL, "Output of extcmd config write command (%s) is too big", cmd); rv = EINVAL; goto out; } buf[rv] = '\0'; rv = pclose(f); f = NULL; if (rv) { sys->log(sys, OS_ERROR, NULL, "extcmd write command (%s) failed: %x: %s", cmd, rv, buf); goto out; } out: if (f) pclose(f); free(cmd); return rv; } int extcmd_checkvals(sys_data_t *sys, void *baseloc, const char *incmd, extcmd_info_t *ts, unsigned int count) { int rv = 0; char *cmd; FILE *f = NULL; unsigned int i; char buf[2048]; unsigned int buflen = sizeof(buf); if (!incmd) return 0; cmd = malloc(strlen(incmd) + 7); if (!cmd) return ENOMEM; strcpy(cmd, incmd); strcat(cmd, " check"); for (i = 0; i < count; i++) { rv = add_cmd(&cmd, ts[i].name, extcmd_setval(baseloc, ts + i), 1); if (rv == ENOMEM) { sys->log(sys, OS_ERROR, NULL, "Out of memory in extcmd check command\n"); goto out; } else if (rv) { sys->log(sys, OS_ERROR, NULL, "Invalid value in extcmd check command for %s\n", ts[i].name); goto out; } } f = popen(cmd, "r"); if (!f) { sys->log(sys, OS_ERROR, NULL, "Unable to execute extcmd check command (%s): %s\n", cmd, strerror(errno)); rv = errno; goto out; } rv = fread(buf, 1, buflen - 1, f); if ((unsigned int) rv == buflen - 1) { sys->log(sys, OS_ERROR, NULL, "Output of extcmd config check command (%s) is too big", cmd); rv = EINVAL; goto out; } buf[rv] = '\0'; /* Return value should tell us if it's ok. */ rv = pclose(f); f = NULL; out: if (f) pclose(f); free(cmd); return rv; } OpenIPMI-2.0.33/lanserv/persist.c0000664000175000017500000002766113360135570013430 00000000000000/* * persist.c * * MontaVista IPMI LAN server persistence tool * * Author: MontaVista Software, LLC. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software LLC. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include enum pitem_type { PITEM_DATA = 'd', PITEM_INT = 'i', PITEM_STR = 's' }; struct pitem { char *iname; enum pitem_type type; void *data; long dval; struct pitem *next; }; struct persist_s { char *name; struct pitem *items; }; int persist_enable = 1; static char *app = NULL; static const char *basedir; int persist_init(const char *papp, const char *instance, const char *ibasedir) { unsigned int len; char *dname; struct stat st; char *n; int rv = 0; if (!persist_enable) return 0; if (app) return EBUSY; basedir = ibasedir; len = strlen(papp) + strlen(instance) + 2; app = malloc(len); if (!app) return ENOMEM; strcpy(app, papp); strcat(app, "/"); strcat(app, instance); len = strlen(basedir) + strlen(app) + 3; dname = malloc(len); if (!dname) { free(app); return ENOMEM; } strcpy(dname, basedir); strcat(dname, "/"); strcat(dname, app); strcat(dname, "/"); if (dname[0] == '/') n = strchr(dname + 1, '/'); else n = strchr(dname, '/'); while (n) { *n = '\0'; if (stat(dname, &st) != 0) { if (mkdir(dname, 0755) != 0) { rv = errno; goto out; } } else if (!S_ISDIR(st.st_mode)) { rv = ENOTDIR; goto out; } *n++ = '/'; n = strchr(n, '/'); } out: free(dname); return rv; } static char * do_va_nameit(const char *name, va_list ap) { unsigned int len; va_list aq; char dummy; char *rv; va_copy(aq, ap); len = vsnprintf(&dummy, 1, name, aq); va_end(aq); rv = malloc(len + 1); if (!rv) return NULL; vsprintf(rv, name, ap); return rv; } persist_t * alloc_vpersist(const char *iname, va_list ap) { persist_t *p = malloc(sizeof(*p)); if (!p) return NULL; p->name = do_va_nameit(iname, ap); if (!p->name) { free(p); return NULL; } p->items = NULL; return p; } persist_t * alloc_persist(const char *name, ...) { persist_t *p; va_list ap; va_start(ap, name); p = alloc_vpersist(name, ap); va_end(ap); return p; } static char * get_fname(persist_t *p, char *sfx) { int len = (strlen(basedir) + strlen(app) + strlen(p->name) + strlen(sfx) + 3); char *fname = malloc(len); if (!fname) return NULL; strcpy(fname, basedir); strcat(fname, "/"); strcat(fname, app); strcat(fname, "/"); strcat(fname, p->name); strcat(fname, sfx); return fname; } static unsigned char fromhex(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'Z') return (c - 'A' + 10) & 0xf; return c - 'a' + 10; } static void * read_data(char *l, long *rsize, int isstr) { int size = 0; char *c; unsigned char *r, *p; for (c = l; *c && *c != '\n'; c++) { if (*c == '\\') { c++; if (!isxdigit(*c)) return NULL; c++; if (!isxdigit(*c)) return NULL; } size++; } r = malloc(size + isstr); if (!r) return NULL; *rsize = size; for (c = l, p = r; *c && *c != '\n'; c++, p++) { if (*c == '\\') { *p = (fromhex(*(c + 1)) << 4) | fromhex(*(c + 2)); c += 2; } else { *p = *c; } } if (isstr) *p = '\0'; return r; } static void write_data(void *idata, unsigned int len, FILE *f) { unsigned char *d = idata; unsigned int i; for (i = 0; i < len; i++, d++) { if (isprint(*d) && (*d != '\\')) fputc(*d, f); else fprintf(f, "\\%2.2x", *d); } } persist_t * read_persist(const char *name, ...) { char *fname; va_list ap; persist_t *p; FILE *f; char *line; char *end; size_t n; if (!persist_enable) return NULL; va_start(ap, name); p = alloc_vpersist(name, ap); if (!p) return NULL; fname = get_fname(p, ""); if (!fname) { free_persist(p); return NULL; } f = fopen(fname, "r"); free(fname); if (!f) { free_persist(p); return NULL; } for (line = NULL; getline(&line, &n, f) != -1; free(line), line = NULL) { char *name = line; char *type = strchr(name, ':'); char *val; struct pitem *pi; if (!type) continue; *type++ = '\0'; if (strlen(name) == 0 || !*type || *(type + 1) != ':') continue; *(type + 1) = '\0'; val = type + 2; pi = malloc(sizeof(*pi)); if (!pi) { free(line); free_persist(p); return NULL; } pi->iname = strdup(name); if (!pi->iname) { free(pi); free(line); free_persist(p); return NULL; } pi->type = type[0]; switch (type[0]) { case PITEM_DATA: pi->data = read_data(val, &pi->dval, 0); if (!pi->data) goto bad_data; break; case PITEM_INT: pi->data = NULL; pi->dval = strtol(val, &end, 0); if (*end != '\n' && *end != '\0') goto bad_data; break; case PITEM_STR: pi->data = read_data(val, &pi->dval, 1); if (!pi->data) goto bad_data; break; bad_data: default: free(pi->iname); free(pi); continue; } pi->next = p->items; p->items = pi; } return p; } int write_persist_file(persist_t *p, FILE *f) { struct pitem *pi; for (pi = p->items; pi; pi = pi->next) { fprintf(f, "%s:%c:", pi->iname, pi->type); switch (pi->type) { case PITEM_DATA: case PITEM_STR: write_data(pi->data, pi->dval, f); break; case PITEM_INT: fprintf(f, "%ld", pi->dval); } fputc('\n', f); } return 0; } int write_persist(persist_t *p) { char *fname, *fname2; int rv = 0; FILE *f; if (!persist_enable) return 0; fname = get_fname(p, ".tmp"); if (!fname) { return ENOMEM; } fname2 = get_fname(p, ""); if (!fname2) { free(fname); return ENOMEM; } f = fopen(fname, "w"); if (!f) { free(fname); free(fname2); return ENOMEM; } write_persist_file(p, f); fclose(f); if (rename(fname, fname2) != 0) rv = errno; free(fname); free(fname2); return rv; } int iterate_persist(persist_t *p, void *cb_data, int (*data_func)(const char *name, void *data, unsigned int len, void *cb_data), int (*int_func)(const char *name, long val, void *cb_data)) { struct pitem *pi; int rv = 0; for (pi = p->items; pi; pi = pi->next) { rv = ITER_PERSIST_CONTINUE; switch (pi->type) { case PITEM_DATA: case PITEM_STR: if (data_func) rv = data_func(pi->iname, pi->data, pi->dval, cb_data); break; case PITEM_INT: if (int_func) rv = int_func(pi->iname, pi->dval, cb_data); break; } if (rv != ITER_PERSIST_CONTINUE) return rv; } return rv; } void free_persist(persist_t *p) { struct pitem *pi; while (p->items) { pi = p->items; p->items = pi->next; if (pi->data) free(pi->data); free(pi->iname); free(pi); } free(p); } static int alloc_pi(persist_t *p, enum pitem_type type, const void *data, long len, const char *iname, va_list ap) { struct pitem *pi; pi = malloc(sizeof(*pi)); if (!pi) return ENOMEM; pi->type = type; pi->iname = do_va_nameit(iname, ap); if (!pi->iname) { free(pi); return ENOMEM; } if (data) { pi->data = malloc(len); if (!pi->data) { free(pi->iname); free(pi); return ENOMEM; } memcpy(pi->data, data, len); } else { pi->data = NULL; } pi->dval = len; pi->next = p->items; p->items = pi; return 0; } static struct pitem * find_pi(persist_t *p, const char *iname, va_list ap) { struct pitem *pi = p->items; char *name = do_va_nameit(iname, ap); if (!name) return NULL; while (pi) { if (strcmp(pi->iname, name) == 0) break; pi = pi->next; } free(name); return pi; } int add_persist_data(persist_t *p, void *data, unsigned int len, const char *name, ...) { va_list ap; int rv; va_start(ap, name); rv = alloc_pi(p, PITEM_DATA, data, len, name, ap); va_end(ap); return rv; } int read_persist_data(persist_t *p, void **data, unsigned int *len, const char *name, ...) { va_list ap; struct pitem *pi; va_start(ap, name); pi = find_pi(p, name, ap); va_end(ap); if (!pi) return ENOENT; if (pi->type != PITEM_DATA) return EINVAL; *data = malloc(pi->dval); if (!*data) return ENOMEM; memcpy(*data, pi->data, pi->dval); *len = pi->dval; return 0; } int add_persist_int(persist_t *p, long val, const char *name, ...) { va_list ap; int rv; va_start(ap, name); rv = alloc_pi(p, PITEM_INT, NULL, val, name, ap); va_end(ap); return rv; } int read_persist_int(persist_t *p, long *val, const char *name, ...) { va_list ap; struct pitem *pi; va_start(ap, name); pi = find_pi(p, name, ap); va_end(ap); if (!pi) return ENOENT; if (pi->type != PITEM_INT) return EINVAL; *val = pi->dval; return 0; } int add_persist_str(persist_t *p, const char *val, const char *name, ...) { va_list ap; int rv; va_start(ap, name); rv = alloc_pi(p, PITEM_STR, val, strlen(val), name, ap); va_end(ap); return rv; } int read_persist_str(persist_t *p, char **val, const char *name, ...) { va_list ap; struct pitem *pi; va_start(ap, name); pi = find_pi(p, name, ap); va_end(ap); if (!pi) return ENOENT; if (pi->type != PITEM_STR) return EINVAL; *val = strdup(pi->data); if (!*val) return ENOMEM; return 0; } void free_persist_data(void *data) { free(data); } void free_persist_str(char *str) { free(str); } OpenIPMI-2.0.33/lanserv/emu.h0000664000175000017500000001663514002617260012524 00000000000000/* * emu.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005,2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __EMU_IPMI_ #define __EMU_IPMI_ #include #include #include void ipmi_emu_tick(emu_data_t *emu, unsigned int seconds); typedef void (*ipmi_emu_sleep_cb)(emu_data_t *emu, struct timeval *time); emu_data_t *ipmi_emu_alloc(void *user_data, ipmi_emu_sleep_cb sleeper, sys_data_t *sysinfo); void *ipmi_emu_get_user_data(emu_data_t *emu); void ipmi_emu_sleep(emu_data_t *emu, struct timeval *time); void ipmi_emu_handle_msg(emu_data_t *emu, lmc_data_t *srcmc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); #define IPMI_MC_DYNAMIC_SENSOR_POPULATION (1 << 0) #define IPMI_MC_PERSIST_SDR (1 << 1) int ipmi_emu_add_mc(emu_data_t *emu, unsigned char ipmb, unsigned char device_id, unsigned char has_device_sdrs, unsigned char device_revision, unsigned char major_fw_rev, unsigned char minor_fw_rev, unsigned char device_support, unsigned char mfg_id[3], unsigned char product_id[2], unsigned int flags); lmc_data_t *ipmi_emu_get_bmc_mc(emu_data_t *emu); int ipmi_emu_set_bmc_mc(emu_data_t *emu, unsigned char ipmb); int ipmi_emu_get_mc_by_addr(emu_data_t *emu, unsigned char ipmb, lmc_data_t **mc); /* ATCA support */ int ipmi_emu_atca_enable(emu_data_t *emu); int ipmi_emu_atca_set_site(emu_data_t *emu, unsigned char hw_address, unsigned char site_type, unsigned char site_number); int ipmi_emu_set_addr(emu_data_t *emu, unsigned int addr_num, unsigned char addr_type, void *addr_data, unsigned int addr_len); int ipmi_emu_clear_addr(emu_data_t *emu, unsigned int addr_num); /* In emu_cmd.c */ void ipmi_emu_shutdown(emu_data_t *emu); int ipmi_emu_cmd(emu_out_t *out, emu_data_t *emu, char *cmd_str); int read_command_file(emu_out_t *out, emu_data_t *emu, const char *command_file); void emu_set_debug_level(emu_data_t *emu, unsigned int debug_level); int ipmi_emu_set_mc_guid(lmc_data_t *mc, unsigned char guid[16], int force); void ipmi_mc_destroy(lmc_data_t *mc); void ipmi_mc_disable(lmc_data_t *mc); void ipmi_mc_enable(lmc_data_t *mc); int ipmi_mc_enable_sel(lmc_data_t *emu, int max_entries, unsigned char flags); int ipmi_mc_add_to_sel(lmc_data_t *emu, unsigned char record_type, unsigned char event[13], unsigned int *recid); int ipmi_mc_add_main_sdr(lmc_data_t *mc, unsigned char *data, unsigned int data_len); int ipmi_mc_add_device_sdr(lmc_data_t *mc, unsigned char lun, unsigned char *data, unsigned int data_len); enum fru_io_cb_op { FRU_IO_READ, FRU_IO_WRITE }; typedef int (*fru_io_cb)(void *cb_data, enum fru_io_cb_op op, unsigned char *data, unsigned int offset, unsigned int length); /* * Add a fru inventory device to the MC. If fru_io_cb is NULL, the data * and length is the initial data for the FRU. Otherwise, fru_io_cb is * called for reads and writes, and the data is the callback data for * fru_io_cb. */ int ipmi_mc_add_fru_data(lmc_data_t *mc, unsigned char device_id, unsigned int length, fru_io_cb fru_io_cb, void *data); /* * Add a fru inventory device to the MC, mapping it to a file at the * given filename, starting in the file at the given offset. */ int ipmi_mc_add_fru_file(lmc_data_t *mc, unsigned char device_id, unsigned int length, unsigned int file_offset, const char *filename); int ipmi_mc_get_fru_data_len(lmc_data_t *mc, unsigned char device_id, unsigned int *length); int ipmi_mc_get_fru_data(lmc_data_t *mc, unsigned char device_id, unsigned int length, unsigned char *data); struct ipmi_sensor_handler_s { char *name; int (*poll)(void *cb_data, unsigned int *val, const char **errstr); int (*init)(lmc_data_t *mc, unsigned char lun, unsigned char sensor_num, char **toks, void *cb_data, void **rcb_data, const char **errstr); int (*postinit)(void *cb_data, const char **errstr); void *cb_data; struct ipmi_sensor_handler_s *next; }; typedef struct ipmi_sensor_handler_s ipmi_sensor_handler_t; int ipmi_sensor_add_handler(ipmi_sensor_handler_t *handler); ipmi_sensor_handler_t *ipmi_sensor_find_handler(const char *name); int ipmi_mc_add_sensor(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char type, unsigned char event_reading_code, int event_only); int ipmi_mc_add_polled_sensor(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char type, unsigned char event_reading_code, unsigned int poll_rate, int (*poll)(void *cb_data, unsigned int *val, const char **errstr), void *cb_data); int ipmi_mc_set_power(lmc_data_t *mc, unsigned char power, int gen_int); int ipmi_mc_set_num_leds(lmc_data_t *mc, unsigned int count); #endif /* __EMU_IPMI_ */ OpenIPMI-2.0.33/lanserv/emu_cmd.c0000664000175000017500000007707114141240666013351 00000000000000/* * config.c * * MontaVista IPMI code for reading lanserv configuration files. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005,2012,2016 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include "emu.h" #include #define BASE_CONF_STR SYSCONFDIR "/ipmi" static int emu_get_uchar(emu_out_t *out, char **toks, unsigned char *val, char *errstr, int empty_ok) { const char *str; char *tmpstr; str = mystrtok(NULL, " \t\n", toks); if (!str) { if (empty_ok) return ENOSPC; if (errstr) out->eprintf(out, "**No %s given\n", errstr); return EINVAL; } if (str[0] == '\'') { *val = str[1]; return 0; } *val = strtoul(str, &tmpstr, 0); if (*tmpstr != '\0') { if (errstr) out->eprintf(out, "**Invalid %s given\n", errstr); return EINVAL; } return 0; } static int emu_get_uchar_with_vals(emu_out_t *out, char **toks, unsigned char *val, char *errstr, int empty_ok, unsigned int numopts, ...) { const char *str; char *tmpstr; va_list ap; unsigned int i; str = mystrtok(NULL, " \t\n", toks); if (!str) { if (empty_ok) return ENOSPC; if (errstr) out->eprintf(out, "**No %s given\n", errstr); return EINVAL; } if (str[0] == '\'') { *val = str[1]; return 0; } va_start(ap, numopts); for (i = 0; i < numopts; i++) { char *v = va_arg(ap, char *); unsigned char vval = va_arg(ap, unsigned int); if (strcmp(v, str) == 0) { *val = vval; va_end(ap); goto out; } } va_end(ap); *val = strtoul(str, &tmpstr, 0); if (*tmpstr != '\0') { if (errstr) out->eprintf(out, "**Invalid %s given\n", errstr); return EINVAL; } out: return 0; } static int emu_get_bitmask(emu_out_t *out, char **toks, uint16_t *val, char *errstr, unsigned int size, int empty_ok) { const char *str; int i, j; str = mystrtok(NULL, " \t\n", toks); if (!str) { if (empty_ok) return ENOSPC; if (errstr) out->eprintf(out, "**No %s given\n", errstr); return EINVAL; } if (strlen(str) != size) { if (errstr) out->eprintf(out, "**invalid number of bits in %s\n", errstr); return EINVAL; } *val = 0; for (i=size-1, j=0; i>=0; i--, j++) { if (str[j] == '0') { /* Nothing to do */ } else if (str[j] == '1') { *val |= 1 << i; } else { if (errstr) out->eprintf(out, "**Invalid bit value '%c' in %s\n", str[j], errstr); return EINVAL; } } return 0; } static int emu_get_uint(emu_out_t *out, char **toks, unsigned int *val, char *errstr) { const char *str; char *tmpstr; str = mystrtok(NULL, " \t\n", toks); if (!str) { if (errstr) out->eprintf(out, "**No %s given\n", errstr); return EINVAL; } *val = strtoul(str, &tmpstr, 0); if (*tmpstr != '\0') { if (errstr) out->eprintf(out, "**Invalid %s given\n", errstr); return EINVAL; } return 0; } static int emu_get_bytes(emu_out_t *out, char **tokptr, unsigned char *data, char *errstr, unsigned int len) { const char *tok = mystrtok(NULL, " \t\n", tokptr); char *end; if (!tok) { if (errstr) out->eprintf(out, "**No %s given\n", errstr); return EINVAL; } if (*tok == '"') { unsigned int end; /* Ascii PW */ tok++; end = strlen(tok) - 1; if (tok[end] != '"') { out->eprintf(out, "**ASCII %s doesn't end in '\"'", errstr); return EINVAL; } if (end > (len - 1)) end = len - 1; memcpy(data, tok, end); data[end] = '\0'; zero_extend_ascii(data, len); } else { unsigned int i; char c[3]; /* HEX pw */ if (strlen(tok) != 32) { out->eprintf(out, "**HEX %s not 32 HEX characters long", errstr); return EINVAL; } c[2] = '\0'; for (i=0; ieprintf(out, "**Invalid HEX character in %s", errstr); return -1; } } } return 0; } #define INPUT_BUFFER_SIZE 65536 int read_command_file(emu_out_t *out, emu_data_t *emu, const char *command_file) { FILE *f = fopen(command_file, "r"); int rv = 0; if (!f) { rv = ENOENT; } else { char *buffer; int pos = 0; buffer = malloc(INPUT_BUFFER_SIZE); if (!buffer) { out->eprintf(out, "Could not allocate buffer memory\n"); rv = ENOMEM; goto out; } while (fgets(buffer+pos, INPUT_BUFFER_SIZE-pos, f)) { out->eprintf(out, "%s", buffer+pos); if (buffer[pos] == '#') continue; pos = strlen(buffer); if (pos == 0) continue; pos--; while ((pos > 0) && (buffer[pos] == '\n')) pos--; if (pos == 0) continue; if ((pos > 0) && (buffer[pos] == '\\')) { /* Continue the line. */ /* Don't do pos--, write over the "\\" */ continue; } pos++; buffer[pos] = 0; rv = ipmi_emu_cmd(out, emu, buffer); if (rv) break; pos = 0; } out: if (buffer) free(buffer); fclose(f); } return rv; } static int sel_enable(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned int max_records; unsigned char flags; rv = emu_get_uint(out, toks, &max_records, "max records"); if (rv) return rv; rv = emu_get_uchar(out, toks, &flags, "flags", 0); if (rv) return rv; rv = ipmi_mc_enable_sel(mc, max_records, flags); if (rv) out->eprintf(out, "**Unable to enable sel, error 0x%x\n", rv); return rv; } static int sel_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int i; int rv; unsigned char record_type; unsigned char data[13]; unsigned int r; rv = emu_get_uchar(out, toks, &record_type, "record type", 0); if (rv) return rv; for (i=0; i<13; i++) { rv = emu_get_uchar(out, toks, &data[i], "data byte", 0); if (rv) return rv; } rv = ipmi_mc_add_to_sel(mc, record_type, data, &r); if (rv) out->eprintf(out, "**Unable to add to sel, error 0x%x\n", rv); else out->eprintf(out, "Added record %d\n", r); return rv; } static int main_sdr_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int i; int rv; unsigned char data[256]; for (i=0; i<256; i++) { rv = emu_get_uchar(out, toks, &data[i], "data byte", 1); if (rv == ENOSPC) break; if (rv) { out->eprintf(out, "**Error 0x%x in data byte %d\n", rv, i); return rv; } } rv = ipmi_mc_add_main_sdr(mc, data, i); if (rv) out->eprintf(out, "**Unable to add to sdr, error 0x%x\n", rv); return rv; } static int device_sdr_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int i; int rv; unsigned char data[256]; unsigned char lun; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; for (i=0; i<256; i++) { rv = emu_get_uchar(out, toks, &data[i], "data byte", 1); if (rv == ENOSPC) break; if (rv) { out->eprintf(out, "**Error 0x%x in data byte %d\n", rv, i); return rv; } } rv = ipmi_mc_add_device_sdr(mc, lun, data, i); if (rv) out->eprintf(out, "**Unable to add to sdr, error 0x%x\n", rv); return rv; } static int sensor_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char type; unsigned char code; int event_only = 0; const char *tok; ipmi_sensor_handler_t *handler = NULL; unsigned int poll_rate = 0; void *rcb_data = NULL; const char *errstr; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &type, "sensor type", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &code, "event reading code", 0); if (rv) return rv; /* * FIXME - the depends that is part of the polled file sensor should * really be part of the main sensor structure. */ tok = mystrtok(NULL, " \t\n", toks); while (tok) { if (strcmp(tok, "poll") == 0) { if (handler) { out->eprintf(out, "**poll given twice in sensor\n", tok); return -1; } rv = emu_get_uint(out, toks, &poll_rate, "poll rate"); if (rv) return rv; tok = mystrtok(NULL, " \t\n", toks); if (!tok) { out->eprintf(out, "**No polled sensor handler given\n", tok); return -1; } handler = ipmi_sensor_find_handler(tok); if (!handler) { out->eprintf(out, "**Invalid sensor handler: %s\n", tok); return -1; } rv = handler->init(mc, lun, num, toks, handler->cb_data, &rcb_data, &errstr); if (rv) { out->eprintf(out, "**Error initializing sensor handler: %s\n", errstr); return rv; } } else if (strcmp(tok, "event-only") == 0) { event_only = 1; } else { out->eprintf(out, "**Unknown sensor option: %s\n", tok); return -1; } tok = mystrtok(NULL, " \t\n", toks); } if (handler && event_only) { out->eprintf(out, "**An event-only sensor cannot be polled\n"); return -1; } if (handler) { rv = ipmi_mc_add_polled_sensor(mc, lun, num, type, code, poll_rate, handler->poll, rcb_data); if (!rv && handler->postinit) { rv = handler->postinit(rcb_data, &errstr); if (rv) { out->eprintf(out, "**Error in sensor handler postinit: %s\n", errstr); } } } else { rv = ipmi_mc_add_sensor(mc, lun, num, type, code, event_only); } if (rv) out->eprintf(out, "**Unable to add to sensor, error 0x%x\n", rv); return rv; } static int sensor_set_bit(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char bit; unsigned char value; unsigned char gen_event; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &bit, "bit to set", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &value, "bit value", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &gen_event, "generate event", 0); if (rv) return rv; rv = ipmi_mc_sensor_set_bit(mc, lun, num, bit, value, gen_event); if (rv) out->eprintf(out, "**Unable to set sensor bit, error 0x%x\n", rv); return rv; } static int sensor_set_bit_clr_rest(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char bit; unsigned char gen_event; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &bit, "bit to set", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &gen_event, "generate event", 0); if (rv) return rv; rv = ipmi_mc_sensor_set_bit_clr_rest(mc, lun, num, bit, gen_event); if (rv) out->eprintf(out, "**Unable to set sensor bit, error 0x%x\n", rv); return rv; } static int sensor_set_value(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char value; unsigned char gen_event; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &value, "value", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &gen_event, "generate event", 0); if (rv) return rv; rv = ipmi_mc_sensor_set_value(mc, lun, num, value, gen_event); if (rv) out->eprintf(out, "**Unable to set sensor value, error 0x%x\n", rv); return rv; } static int sensor_set_hysteresis(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char support; unsigned char positive, negative; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar_with_vals(out, toks, &support, "hysteresis support", 0, 4, "none", 0, "readable", 1, "settable", 2, "fixed", 3); if (rv) return rv; printf("Hysteresis: %d\n", support); rv = emu_get_uchar(out, toks, &positive, "positive hysteresis", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &negative, "negative hysteresis", 0); if (rv) return rv; rv = ipmi_mc_sensor_set_hysteresis(mc, lun, num, support, positive, negative); if (rv) out->eprintf(out, "**Unable to set sensor hysteresis, error 0x%x\n", rv); return rv; } static int sensor_set_threshold(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char support; uint16_t enabled; unsigned char thresholds[6]; int i; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar_with_vals(out, toks, &support, "threshold support", 0, 4, "none", 0, "readable", 1, "settable", 2, "fixed", 3); if (rv) return rv; rv = emu_get_bitmask(out, toks, &enabled, "threshold enabled", 6, 0); if (rv) return rv; for (i=5; i>=0; i--) { rv = emu_get_uchar(out, toks, &thresholds[i], "threshold value", 0); if (rv) return rv; } rv = ipmi_mc_sensor_set_threshold(mc, lun, num, support, enabled, 1, thresholds); if (rv) out->eprintf(out, "**Unable to set sensor thresholds, error 0x%x\n", rv); return rv; } static int sensor_set_event_support(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char lun; unsigned char num; unsigned char support; unsigned char events_enable; unsigned char scanning; uint16_t assert_support; uint16_t deassert_support; uint16_t assert_enabled; uint16_t deassert_enabled; rv = emu_get_uchar(out, toks, &lun, "LUN", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &num, "sensor num", 0); if (rv) return rv; rv = emu_get_uchar_with_vals(out, toks, &events_enable, "events enable", 0, 4, "enable", 1, "true", 1, "disable", 0, "false", 0); if (rv) return rv; rv = emu_get_uchar_with_vals(out, toks, &scanning, "scanning", 0, 4, "scanning", 1, "true", 1, "no-scanning", 0, "false", 0); if (rv) return rv; rv = emu_get_uchar_with_vals(out, toks, &support, "event support", 0, 4, "per-state", 0, "entire-sensor", 1, "global", 2, "none", 3); if (rv) return rv; rv = emu_get_bitmask(out, toks, &assert_support, "assert support", 15, 0); if (rv) return rv; rv = emu_get_bitmask(out, toks, &deassert_support, "deassert support", 15, 0); if (rv) return rv; rv = emu_get_bitmask(out, toks, &assert_enabled, "assert enabled", 15, 0); if (rv) return rv; rv = emu_get_bitmask(out, toks, &deassert_enabled, "deassert enabled", 15, 0); if (rv) return rv; rv = ipmi_mc_sensor_set_event_support(mc, lun, num, 1, events_enable, 1, scanning, support, assert_support, deassert_support, assert_enabled, deassert_enabled); if (rv) out->eprintf(out, "**Unable to set sensor thresholds, error 0x%x\n", rv); return rv; } static int mc_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned char ipmb; unsigned char device_id; unsigned char has_device_sdrs; unsigned char device_revision; unsigned char major_fw_rev; unsigned char minor_fw_rev; unsigned char device_support; unsigned char mfg_id[3]; unsigned int mfg_id_i; unsigned char product_id[2]; unsigned int product_id_i; unsigned int flags = 0; int rv; const char *tok; rv = emu_get_uchar(out, toks, &ipmb, "IPMB address", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &device_id, "Device ID", 0); if (rv) return rv; rv = emu_get_uchar_with_vals(out, toks, &has_device_sdrs, "Has Device SDRs", 0, 2, "has-device-sdrs", 1, "no-device-sdrs", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &device_revision, "Device Revision", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &major_fw_rev, "Major FW Rev", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &minor_fw_rev, "Minor FW Rev", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &device_support, "Device Support", 0); if (rv) return rv; rv = emu_get_uint(out, toks, &mfg_id_i, "Manufacturer ID"); if (rv) return rv; rv = emu_get_uint(out, toks, &product_id_i, "Product ID"); if (rv) return rv; while ((tok = mystrtok(NULL, " \t\n", toks))) { if (strcmp("dynsens", tok) == 0) flags |= IPMI_MC_DYNAMIC_SENSOR_POPULATION; else if (strcmp("persist_sdr", tok) == 0) flags |= IPMI_MC_PERSIST_SDR; else { out->eprintf(out, "**Invalid MC flag: %s\n", tok); return -1; } } mfg_id[0] = mfg_id_i & 0xff; mfg_id[1] = (mfg_id_i >> 8) & 0xff; mfg_id[2] = (mfg_id_i >> 16) & 0xff; product_id[0] = product_id_i & 0xff; product_id[1] = (product_id_i >> 8) & 0xff; rv = ipmi_emu_add_mc(emu, ipmb, device_id, has_device_sdrs, device_revision, major_fw_rev, minor_fw_rev, device_support, mfg_id, product_id, flags); if (rv) out->eprintf(out, "**Unable to add the MC, error 0x%x\n", rv); return rv; } static int mc_set_guid(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned char guid[16]; int rv; rv = emu_get_bytes(out, toks, guid, "GUID", 16); if (rv) return rv; rv = ipmi_emu_set_mc_guid(mc, guid, 1); return rv; } static int mc_delete(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { ipmi_mc_destroy(mc); return 0; } static int mc_disable(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { ipmi_mc_disable(mc); return 0; } static int mc_enable(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { ipmi_mc_enable(mc); return 0; } static int mc_set_power(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned char power; unsigned char gen_int; int rv; rv = emu_get_uchar(out, toks, &power, "Power", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &gen_int, "Gen int", 0); if (rv) return rv; rv = ipmi_mc_set_power(mc, power, gen_int); if (rv) out->eprintf(out, "**Unable to set power, error 0x%x\n", rv); return rv; } #define MAX_FRU_SIZE 8192 static int mc_add_fru_data(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned char data[MAX_FRU_SIZE]; unsigned char devid; unsigned int length; unsigned int i; int rv; const char *tok; const char *errstr; rv = emu_get_uchar(out, toks, &devid, "Device ID", 0); if (rv) return rv; rv = emu_get_uint(out, toks, &length, "FRU physical size"); if (rv) return rv; if (length > MAX_FRU_SIZE) return EINVAL; tok = mystrtok(NULL, " \t\n", toks); if (!tok) { out->eprintf(out, "**No FRU data type given"); return -1; } if (strcmp(tok, "file") == 0) { unsigned int file_offset; char *frufn; rv = emu_get_uint(out, toks, &file_offset, "file offset"); if (rv) return rv; rv = get_delim_str(toks, &frufn, &errstr); if (rv) { out->eprintf(out, "**Error with FRU filename: %d", strerror(rv)); return rv; } rv = ipmi_mc_add_fru_file(mc, devid, length, file_offset, (void *) frufn); if (rv) out->eprintf(out, "**Unable to add FRU file, error 0x%x\n", rv); free(frufn); } else if (strcmp(tok, "data") == 0) { for (i=0; ieprintf(out, "**Error 0x%x in data byte %d\n", rv, i); return rv; } } rv = emu_get_uchar(out, toks, &data[i], "data byte", 1); if (rv != ENOSPC) { out->eprintf(out, "**Error: input data too long for FRU\n", rv, i); return EINVAL; } memset(data + i, 0, length - i); rv = ipmi_mc_add_fru_data(mc, devid, length, NULL, data); if (rv) out->eprintf(out, "**Unable to add FRU data, error 0x%x\n", rv); } else { out->eprintf(out, "**FRU type not given, need file or data\n"); rv = EINVAL; } return rv; } static int mc_dump_fru_data(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned char *data = NULL; unsigned char devid; unsigned int length; unsigned int i; int rv; rv = emu_get_uchar(out, toks, &devid, "Device ID", 0); if (rv) return rv; rv = ipmi_mc_get_fru_data_len(mc, devid, &length); if (rv) { out->eprintf(out, "**Unable to dump FRU data, error 0x%x\n", rv); goto out; } data = malloc(length); if (!data) { out->eprintf(out, "**Unable to dump FRU data, out of memory\n", rv); goto out; } rv = ipmi_mc_get_fru_data(mc, devid, length, data); if (rv) { out->eprintf(out, "**Unable to dump FRU data, error 0x%x\n", rv); goto out; } for (i=0; i 0) && ((i % 8) == 0)) out->eprintf(out, "\n"); out->eprintf(out, " 0x%2.2x", data[i]); } out->eprintf(out, "\n"); out: if (data) free(data); return rv; } static int mc_setbmc(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned char ipmb; int rv; rv = emu_get_uchar(out, toks, &ipmb, "IPMB address of BMC", 0); if (rv) return rv; rv = ipmi_emu_set_bmc_mc(emu, ipmb); if (rv) out->eprintf(out, "**Invalid IPMB address\n"); return rv; } static int atca_enable(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; rv = ipmi_emu_atca_enable(emu); if (rv) out->eprintf(out, "**Unable to enable ATCA mode, error 0x%x\n", rv); return rv; } static int atca_set_site(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char hw_address; unsigned char site_type; unsigned char site_number; rv = emu_get_uchar(out, toks, &hw_address, "hardware address", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &site_type, "site type", 0); if (rv) return rv; rv = emu_get_uchar(out, toks, &site_number, "site number", 0); if (rv) return rv; rv = ipmi_emu_atca_set_site(emu, hw_address, site_type, site_number); if (rv) out->eprintf(out, "**Unable to set site type, error 0x%x\n", rv); return rv; } static int mc_set_num_leds(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { int rv; unsigned char count; rv = emu_get_uchar(out, toks, &count, "number of LEDs", 0); if (rv) return rv; rv = ipmi_mc_set_num_leds(mc, count); if (rv) out->eprintf(out, "**Unable to set number of LEDs, error 0x%x\n", rv); return rv; } static int read_cmds(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { char *filename; const char *errstr; int err; err = get_delim_str(toks, &filename, &errstr); if (err) { out->eprintf(out, "Could not get include filename: %s\n", errstr); return err; } err = read_command_file(out, emu, filename); if (err == ENOENT && filename[0] != '/' && strncmp(filename, "./", 2) && strncmp(filename, "../", 3)) { char *nf = malloc(strlen(BASE_CONF_STR) + strlen(filename) + 2); if (!nf) { out->eprintf(out, "Out of memory in include\n", errstr); goto out_err; } strcpy(nf, BASE_CONF_STR); strcat(nf, "/"); strcat(nf, filename); free((char *) filename); filename = nf; err = read_command_file(out, emu, filename); if (err) { out->eprintf(out, "Could not read include file %s\n", filename); } } out_err: free((char *) filename); return err; } static int sleep_cmd(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned int time; struct timeval tv; int rv; rv = emu_get_uint(out, toks, &time, "timeout"); if (rv) return rv; tv.tv_sec = time / 1000; tv.tv_usec = (time % 1000) * 1000; ipmi_emu_sleep(emu, &tv); return 0; } static int debug_cmd(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { unsigned int level = 0; const char *tok; while ((tok = mystrtok(NULL, " \t\n", toks))) { if (strcmp(tok, "raw") == 0) { level |= DEBUG_RAW_MSG; } else if (strcmp(tok, "msg") == 0) { level |= DEBUG_MSG; } else if (strcmp(tok, "sol") == 0) { level |= DEBUG_SOL; } else { out->eprintf(out, "Invalid debug level '%s', options are 'raw' and 'msg'\n", tok); return EINVAL; } } emu_set_debug_level(emu, level); return 0; } static int persist_cmd(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { const char *tok; while ((tok = mystrtok(NULL, " \t\n", toks))) { if (strcmp(tok, "on") == 0) { persist_enable = 1; } else if (strcmp(tok, "off") == 0) { persist_enable = 0; } else { out->eprintf(out, "Invalid persist vale '%s', options are 'on' and 'off'\n", tok); return EINVAL; } } return 0; } static int quit(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { fflush(stdout); ipmi_emu_shutdown(emu); return 0; } static int do_define(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks) { const char *name; char *value; int err; const char *errstr; name = mystrtok(NULL, " \t\n", toks); if (!name) { out->eprintf(out, "No variable name given for define\n"); return EINVAL; } err = get_delim_str(toks, &value, &errstr); if (err) { out->eprintf(out, "Could not get variable %s value: %s\n", name, errstr); return err; } err = add_variable(name, value); if (err) { free(value); out->eprintf(out, "Out of memory setting variable %s\n", name); return err; } return 0; } struct emu_cmd_info { const char *name; unsigned int flags; ipmi_emu_cmd_handler handler; struct emu_cmd_info *next; }; static struct emu_cmd_info cmds[] = { { "quit", NOMC, quit, &cmds[1] }, { "define", NOMC, do_define, &cmds[2] }, { "sel_enable", MC, sel_enable, &cmds[3] }, { "sel_add", MC, sel_add, &cmds[4] }, { "main_sdr_add", MC, main_sdr_add, &cmds[5] }, { "device_sdr_add", MC, device_sdr_add, &cmds[6] }, { "sensor_add", MC, sensor_add, &cmds[7] }, { "sensor_set_bit", MC, sensor_set_bit, &cmds[8] }, { "sensor_set_bit_clr_rest", MC, sensor_set_bit_clr_rest, &cmds[9] }, { "sensor_set_value", MC, sensor_set_value, &cmds[10] }, { "sensor_set_hysteresis", MC, sensor_set_hysteresis, &cmds[11] }, { "sensor_set_threshold", MC, sensor_set_threshold, &cmds[12] }, { "sensor_set_event_support", MC, sensor_set_event_support,&cmds[13] }, { "mc_set_power", MC, mc_set_power, &cmds[14] }, { "mc_add_fru_data",MC, mc_add_fru_data, &cmds[15] }, { "mc_dump_fru_data",MC, mc_dump_fru_data, &cmds[16] }, { "mc_set_num_leds",MC, mc_set_num_leds, &cmds[17] }, { "mc_add", NOMC, mc_add, &cmds[18] }, { "mc_delete", MC, mc_delete, &cmds[19] }, { "mc_disable", MC, mc_disable, &cmds[20] }, { "mc_enable", MC, mc_enable, &cmds[21] }, { "mc_setbmc", NOMC, mc_setbmc, &cmds[22] }, { "mc_set_guid", MC, mc_set_guid, &cmds[23] }, { "atca_enable", NOMC, atca_enable, &cmds[24] }, { "atca_set_site", NOMC, atca_set_site, &cmds[25] }, { "read_cmds", NOMC, read_cmds, &cmds[26] }, { "include", NOMC, read_cmds, &cmds[27] }, { "sleep", NOMC, sleep_cmd, &cmds[28] }, { "debug", NOMC, debug_cmd, &cmds[29] }, { "persist", NOMC, persist_cmd, NULL }, { NULL } }; static struct emu_cmd_info *cmdlist = &cmds[0]; int ipmi_emu_add_cmd(const char *name, unsigned int flags, ipmi_emu_cmd_handler handler) { struct emu_cmd_info *mcmd; mcmd = malloc(sizeof(*mcmd)); if (!mcmd) return ENOMEM; mcmd->name = strdup(name); if (!mcmd->name) { free(mcmd); return ENOMEM; } mcmd->flags = flags; mcmd->handler = handler; mcmd->next = cmdlist; cmdlist = mcmd; return 0; } int ipmi_emu_cmd(emu_out_t *out, emu_data_t *emu, char *cmd_str) { char *toks; const char *cmd; int rv = EINVAL; lmc_data_t *mc = NULL; struct emu_cmd_info *mcmd; cmd = mystrtok(cmd_str, " \t\n", &toks); if (!cmd) return 0; if (cmd[0] == '#') return 0; for (mcmd = cmdlist; mcmd; mcmd = mcmd->next) { if (strcmp(cmd, mcmd->name) == 0) { if (mcmd->flags & MC) { unsigned char ipmb; rv = emu_get_uchar(out, &toks, &ipmb, "MC address", 0); if (rv) return rv; rv = ipmi_emu_get_mc_by_addr(emu, ipmb, &mc); if (rv) { out->eprintf(out, "**Invalid MC address\n"); return rv; } } rv = mcmd->handler(out, emu, mc, &toks); if (rv) return rv; goto out; } } out->eprintf(out, "**Unknown command: %s\n", cmd); out: return rv; } OpenIPMI-2.0.33/lanserv/bmc_sensor.c0000664000175000017500000013513214002617260014055 00000000000000/* * bmc_sensor.c * * MontaVista IPMI code for emulating a MC. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2012,2013 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 #include #include #include #include #include #include #include #include static void sensor_poll(void *cb_data); static void handle_get_event_receiver(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_IPMB_EVENT_GEN)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } rdata[0] = 0; rdata[1] = mc->event_receiver; rdata[2] = mc->event_receiver_lun & 0x3; *rdata_len = 3; } static void handle_set_event_receiver(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_IPMB_EVENT_GEN)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 2, rdata, rdata_len)) return; mc->event_receiver = msg->data[0] & 0xfe; mc->event_receiver_lun = msg->data[1] & 0x3; rdata[0] = 0; *rdata_len = 1; } static void handle_get_device_sdr_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (! mc->has_device_sdrs) { handle_invalid_cmd(mc, rdata, rdata_len); return; } rdata[0] = 0; rdata[1] = mc->num_sensors_per_lun[msg->rs_lun]; rdata[2] = ((mc->dynamic_sensor_population << 7) | (mc->lun_has_sensors[3] << 3) | (mc->lun_has_sensors[2] << 2) | (mc->lun_has_sensors[1] << 1) | (mc->lun_has_sensors[0] << 0)); if (!mc->dynamic_sensor_population) { *rdata_len = 3; return; } ipmi_set_uint32(rdata+3, mc->sensor_population_change_time); *rdata_len = 7; } static void handle_reserve_device_sdr_repository(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->has_device_sdrs)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->dynamic_sensor_population)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->device_sdrs[msg->rs_lun].reservation++; if (mc->device_sdrs[msg->rs_lun].reservation == 0) mc->device_sdrs[msg->rs_lun].reservation++; rdata[0] = 0; ipmi_set_uint16(rdata+1, mc->device_sdrs[msg->rs_lun].reservation); *rdata_len = 3; } static void handle_get_device_sdr(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint16_t record_id; unsigned int offset; unsigned int count; sdr_t *entry; if (!(mc->has_device_sdrs)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (mc->dynamic_sensor_population) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->device_sdrs[msg->rs_lun].reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } record_id = ipmi_get_uint16(msg->data+2); offset = msg->data[4]; count = msg->data[5]; if (record_id == 0) { entry = mc->device_sdrs[msg->rs_lun].sdrs; } else if (record_id == 0xffff) { entry = mc->device_sdrs[msg->rs_lun].sdrs; if (entry) { while (entry->next) { entry = entry->next; } } } else { entry = find_sdr_by_recid(&mc->device_sdrs[msg->rs_lun], record_id, NULL); } if (entry == NULL) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } if (offset >= entry->length) { rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC; *rdata_len = 1; return; } if ((offset+count) > entry->length) count = entry->length - offset; if (count+3 > *rdata_len) { /* Too much data to put into response. */ rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; *rdata_len = 1; return; } rdata[0] = 0; if (entry->next) ipmi_set_uint16(rdata+1, entry->next->record_id); else { rdata[1] = 0xff; rdata[2] = 0xff; } memcpy(rdata+3, entry->data+offset, count); *rdata_len = count + 3; } static void handle_set_sensor_hysteresis(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; if (check_msg_length(msg, 4, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if (sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_SETTABLE) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } sensor->positive_hysteresis = msg->data[2]; sensor->negative_hysteresis = msg->data[3]; rdata[0] = 0; *rdata_len = 1; } static void handle_get_sensor_hysteresis(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; if (check_msg_length(msg, 1, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if ((sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_SETTABLE) && (sensor->hysteresis_support != IPMI_HYSTERESIS_SUPPORT_READABLE)) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = sensor->positive_hysteresis; rdata[2] = sensor->negative_hysteresis; *rdata_len = 3; } static void do_event(lmc_data_t *mc, sensor_t *sensor, int gen_event, unsigned char direction, unsigned char byte1, unsigned char byte2, unsigned char byte3) { lmc_data_t *dest_mc; unsigned char data[13]; int rv; if ((mc->event_receiver == 0) || (!sensor->enabled) || (!sensor->events_enabled) || (!gen_event)) return; rv = ipmi_emu_get_mc_by_addr(mc->emu, mc->event_receiver, &dest_mc); if (rv) return; /* Timestamp is ignored. */ data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = mc->ipmb; data[5] = sensor->lun; data[6] = 0x04; /* Event message revision for IPMI 1.5. */ data[7] = sensor->sensor_type; data[8] = sensor->num; data[9] = (direction << 7) | sensor->event_reading_code; data[10] = byte1; data[11] = byte2; data[12] = byte3; mc_new_event(dest_mc, 0x02, data); } void set_sensor_bit(lmc_data_t *mc, sensor_t *sensor, unsigned char bit, unsigned char value, unsigned char evd1, unsigned char evd2, unsigned char evd3, int gen_event) { if (sensor->event_only) { if (value) do_event(mc, sensor, gen_event, IPMI_ASSERTION, evd1 | bit, evd2, evd3); else do_event(mc, sensor, gen_event, IPMI_DEASSERTION, evd1 | bit, evd2, evd3); } else if (value != bit_set(sensor->event_status, bit)) { /* The bit value has changed. */ set_bit(sensor->event_status, bit, value); if (value && bit_set(sensor->event_enabled[0], bit)) { do_event(mc, sensor, gen_event, IPMI_ASSERTION, evd1 | bit, evd2, evd3); } else if (!value && bit_set(sensor->event_enabled[1], bit)) { do_event(mc, sensor, gen_event, IPMI_DEASSERTION, evd1 | bit, evd2, evd3); } } } static void check_thresholds(lmc_data_t *mc, sensor_t *sensor, int gen_event) { int i; int bits_to_set = 0; int bits_to_clear = 0; for (i=0; i<3; i++) { if (bit_set(sensor->threshold_supported, i)) { if (sensor->value <= sensor->thresholds[i]) bits_to_set |= (1 << i); else if ((sensor->value - sensor->negative_hysteresis) > sensor->thresholds[i]) bits_to_clear |= (1 << i); } } for (; i<6; i++) { if (bit_set(sensor->threshold_supported, i)) { if (sensor->value >= sensor->thresholds[i]) bits_to_set |= (1 << i); else if ((sensor->value + sensor->positive_hysteresis) < sensor->thresholds[i]) bits_to_clear |= (1 << i); } } /* We don't support lower assertions for high thresholds or higher assertions for low thresholds because that's just stupid. */ for (i=0; i<3; i++) { if (((bits_to_set >> i) & 1) && !bit_set(sensor->event_status, i)) { /* This bit was not set, but we need to set it. */ set_bit(sensor->event_status, i, 1); if (bit_set(sensor->event_enabled[0], i * 2)) { do_event(mc, sensor, gen_event, IPMI_ASSERTION, 0x50 | (i*2), sensor->value, sensor->thresholds[i]); } } else if (((bits_to_clear >> i) & 1) && bit_set(sensor->event_status, i)) { /* This bit was not clear, but we need to clear it. */ set_bit(sensor->event_status, i, 0); if (bit_set(sensor->event_enabled[1], i * 2)) { do_event(mc, sensor, gen_event, IPMI_DEASSERTION, 0x50 | (i*2), sensor->value, sensor->thresholds[i]); } } } for (; i<6; i++) { if (((bits_to_set >> i) & 1) && !bit_set(sensor->event_status, i)) { /* This bit was not set, but we need to set it. */ set_bit(sensor->event_status, i, 1); if (bit_set(sensor->event_enabled[0], i * 2 + 1)) { do_event(mc, sensor, gen_event, IPMI_ASSERTION, 0x50 | (i*2+1), sensor->value, sensor->thresholds[i]); } } else if (((bits_to_clear >> i) & 1) && bit_set(sensor->event_status, i)) { /* This bit was not clear, but we need to clear it. */ set_bit(sensor->event_status, i, 0); if (bit_set(sensor->event_enabled[1], i * 2 + 1)) { do_event(mc, sensor, gen_event, IPMI_DEASSERTION, 0x50 | (i*2+1), sensor->value, sensor->thresholds[i]); } } } } static void handle_set_sensor_thresholds(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; int i; if (check_msg_length(msg, 8, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if ((sensor->event_reading_code != IPMI_EVENT_READING_TYPE_THRESHOLD) || (sensor->threshold_support != IPMI_THRESHOLD_ACCESS_SUPPORT_SETTABLE)) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } for (i=0; i<6; i++) { if ((msg->data[1] & (1 << i)) && (!bit_set(sensor->threshold_supported, i))) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } } for (i=0; i<6; i++) { if (msg->data[1] & (1 << i)) { sensor->thresholds[i] = msg->data[i+2]; } } check_thresholds(mc, sensor, 1); rdata[0] = 0; *rdata_len = 1; } static void handle_get_sensor_thresholds(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; int i; if (check_msg_length(msg, 1, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if ((sensor->event_reading_code != IPMI_EVENT_READING_TYPE_THRESHOLD) || ((sensor->threshold_support != IPMI_THRESHOLD_ACCESS_SUPPORT_SETTABLE) && (sensor->threshold_support != IPMI_THRESHOLD_ACCESS_SUPPORT_READABLE))) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = 0; for (i=0; i<6; i++) { if (bit_set(sensor->threshold_supported, i)) { rdata[1] |= 1 << i; rdata[2+i] = sensor->thresholds[i]; } else rdata[2+i] = 0; } *rdata_len = 8; } static void handle_set_sensor_event_enable(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; unsigned int i; int j, e; unsigned char op; if (check_msg_length(msg, 2, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if ((sensor->event_support == IPMI_EVENT_SUPPORT_NONE) || (sensor->event_support == IPMI_EVENT_SUPPORT_GLOBAL_ENABLE)) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } op = (msg->data[1] >> 4) & 0x3; if (sensor->event_support == IPMI_EVENT_SUPPORT_ENTIRE_SENSOR) { if (op != 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } } if (op == 3) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor->events_enabled = (msg->data[1] >> 7) & 1; sensor->scanning_enabled = (msg->data[1] >> 6) & 1; sensor_poll(sensor); if (op == 0) return; else if (op == 1) /* Enable selected events */ op = 1; else /* Disable selected events */ op = 0; e = 0; for (i=2; i<=3; i++) { if (msg->len <= i) break; for (j=0; j<8; j++, e++) { if (e >= 15) break; if (((msg->data[i] >> j) & 1) && bit_set(sensor->event_supported[0], e)) set_bit(sensor->event_enabled[0], e, op); } } e = 0; for (i=4; i<=5; i++) { if (msg->len <= i) break; for (j=0; j<8; j++, e++) { if (e >= 15) break; if (((msg->data[i] >> j) & 1) && bit_set(sensor->event_supported[1], e)) set_bit(sensor->event_enabled[1], e, op); } } rdata[0] = 0; *rdata_len = 1; } static void handle_get_sensor_event_enable(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; if (check_msg_length(msg, 1, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if ((sensor->event_support == IPMI_EVENT_SUPPORT_NONE) || (sensor->event_support == IPMI_EVENT_SUPPORT_GLOBAL_ENABLE)) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = ((sensor->events_enabled << 7) | ((sensor->scanning_enabled && sensor->enabled) << 6)); if (sensor->event_support == IPMI_EVENT_SUPPORT_ENTIRE_SENSOR) { *rdata_len = 2; return; } rdata[2] = sensor->event_enabled[0] & 0xff; rdata[3] = (sensor->event_enabled[0] >> 8) & 0xff; rdata[4] = sensor->event_enabled[1] & 0xff; rdata[5] = (sensor->event_enabled[1] >> 8) & 0xff; *rdata_len = 6; } static void handle_set_sensor_type(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { handle_invalid_cmd(mc, rdata, rdata_len); } static void handle_get_sensor_type(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; if (check_msg_length(msg, 1, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; rdata[0] = 0; rdata[1] = sensor->sensor_type; rdata[2] = sensor->event_reading_code; *rdata_len = 3; } static void handle_get_sensor_reading(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; if (check_msg_length(msg, 1, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if (sensor->event_only) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = sensor->value; rdata[2] = ((sensor->events_enabled << 7) | ((sensor->scanning_enabled && sensor->enabled) << 6)); rdata[3] = sensor->event_status & 0xff; rdata[4] = (sensor->event_status >> 8) & 0xff; *rdata_len = 5; } static void handle_rearm_sensor_events(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int sens_num; sensor_t *sensor; uint16_t rearm_assert = 0, rearm_deassert = 0; unsigned int i; int rv; if (check_msg_length(msg, 2, rdata, rdata_len)) return; sens_num = msg->data[0]; if ((sens_num >= 255) || (!mc->sensors[msg->rs_lun][sens_num])) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } sensor = mc->sensors[msg->rs_lun][sens_num]; if (msg->data[1] & (1 << 7)) { rearm_assert = 0x7fff; rearm_deassert = 0x7fff; } else { if (msg->len > 2) rearm_assert = msg->data[2]; if (msg->len > 3) rearm_assert |= msg->data[3] << 8; if (msg->len > 4) rearm_deassert = msg->data[4]; if (msg->len > 5) rearm_deassert |= msg->data[5] << 8; } if (sensor->rearm_handler) { rv = sensor->rearm_handler(sensor->rearm_cb_data, rearm_assert, rearm_deassert); if (rv) { rdata[0] = 0xff; *rdata_len = 1; return; } } rearm_assert &= sensor->event_enabled[0] & sensor->event_status; rearm_deassert &= sensor->event_enabled[1] & ~sensor->event_status; for (i = 0; i < 15; i++) { if (bit_set(rearm_assert, i)) do_event(mc, sensor, 1, IPMI_ASSERTION, 0, 0xff, 0xff); else if (bit_set(rearm_deassert, i)) do_event(mc, sensor, 1, IPMI_DEASSERTION, 0, 0xff, 0xff); } rdata[0] = 0; *rdata_len = 1; } int ipmi_mc_sensor_add_rearm_handler(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, int (*handler)(void *cb_data, uint16_t assert, uint16_t deassert), void *cb_data) { sensor_t *sensor; if ((sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; sensor = mc->sensors[lun][sens_num]; sensor->rearm_handler = handler; sensor->rearm_cb_data = cb_data; return 0; } int ipmi_mc_sensor_set_bit(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char bit, unsigned char value, int gen_event) { sensor_t *sensor; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; if (bit >= 15) return EINVAL; sensor = mc->sensors[lun][sens_num]; set_sensor_bit(mc, sensor, bit, value, 0, 0xff, 0xff, gen_event); if (sensor->sensor_update_handler) sensor->sensor_update_handler(mc, sensor); return 0; } int ipmi_mc_sensor_set_bit_clr_rest(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char bit, int gen_event) { sensor_t *sensor; int i; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; if (bit >= 15) return EINVAL; sensor = mc->sensors[lun][sens_num]; /* Clear all the other bits. */ for (i=0; i<15; i++) { if ((i != bit) && bit_set(sensor->event_status, i)) set_sensor_bit(mc, sensor, i, 0, 0, 0xff, 0xff, gen_event); } sensor->value = bit; set_sensor_bit(mc, sensor, bit, 1, 0, 0xff, 0xff, gen_event); if (sensor->sensor_update_handler) sensor->sensor_update_handler(mc, sensor); return 0; } int ipmi_mc_sensor_set_enabled(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char enabled) { sensor_t *sensor; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; sensor = mc->sensors[lun][sens_num]; sensor->enabled = enabled; sensor_poll(sensor); return 0; } static void set_sensor_value(lmc_data_t *mc, sensor_t *sensor, unsigned char value, int gen_event) { sensor->value = value; if (sensor->sensor_update_handler) sensor->sensor_update_handler(mc, sensor); check_thresholds(mc, sensor, gen_event); } int ipmi_mc_sensor_set_value(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char value, int gen_event) { sensor_t *sensor; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; sensor = mc->sensors[lun][sens_num]; set_sensor_value(mc, sensor, value, gen_event); return 0; } int ipmi_mc_sensor_set_hysteresis(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char support, unsigned char positive, unsigned char negative) { sensor_t *sensor; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; sensor = mc->sensors[lun][sens_num]; sensor->hysteresis_support = support; sensor->positive_hysteresis = positive; sensor->negative_hysteresis = negative; return 0; } int ipmi_mc_sensor_set_threshold(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char support, uint16_t supported, int set_values, unsigned char values[6]) { sensor_t *sensor; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; sensor = mc->sensors[lun][sens_num]; sensor->threshold_support = support; sensor->threshold_supported = supported; if (set_values) memcpy(sensor->thresholds, values, 6); return 0; } int ipmi_mc_sensor_set_event_support(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char init_events, unsigned char events_enable, unsigned char init_scanning, unsigned char scanning_enable, unsigned char event_support, uint16_t assert_supported, uint16_t deassert_supported, uint16_t assert_enabled, uint16_t deassert_enabled) { sensor_t *sensor; if ((lun >= 4) || (sens_num >= 255) || (!mc->sensors[lun][sens_num])) return EINVAL; sensor = mc->sensors[lun][sens_num]; if (init_events) sensor->events_enabled = events_enable; if (init_scanning) sensor->scanning_enabled = scanning_enable; sensor->event_support = event_support; sensor->event_supported[0] = assert_supported; sensor->event_supported[1] = deassert_supported; sensor->event_enabled[0] = assert_enabled & assert_supported; sensor->event_enabled[1] = deassert_enabled & deassert_supported; sensor_poll(sensor); return 0; } static int init_sensor_from_sdr(lmc_data_t *mc, unsigned char *sdr) { int err; unsigned int len = sdr[4]; unsigned char num = sdr[7]; unsigned char lun = sdr[6] & 0x3; uint16_t assert_sup, deassert_sup, assert_en, deassert_en; unsigned char events_on = (sdr[10] >> 1) & 1; unsigned char scan_on = (sdr[10] >> 0) & 1; unsigned char init_events = (sdr[10] >> 5) & 1; unsigned char init_scan = (sdr[10] >> 6) & 1; unsigned char init_thresh = (sdr[10] >> 4) & 1; unsigned char init_hyst = (sdr[10] >> 3) & 1; unsigned char init_type = (sdr[10] >> 2) & 1; unsigned char event_sup = sdr[11] & 0x3; unsigned char thresh_sup = (sdr[11] >> 2) & 0x3; uint16_t thresh_set; unsigned char hyst_sup = (sdr[11] >> 4) & 3; sensor_t *sensor; if ((lun >= 4) || (num >= 255) || (!mc->sensors[lun][num])) return EINVAL; sensor = mc->sensors[lun][num]; if (len < 20) return 0; if ((sdr[3] < 1) || (sdr[3] > 2)) return 0; /* Not a sensor SDR we set from */ thresh_set = ((sdr[15] >> 4) & 0x7) | (((sdr[17] >> 4) & 0x7) << 3); assert_sup = sdr[14] | (sdr[15] << 8); deassert_sup = sdr[16] | (sdr[17] << 8); assert_en = sdr[14] | (sdr[15] << 8); deassert_en = sdr[16] | (sdr[17] << 8); if (init_type) { sensor->sensor_type = sdr[12]; sensor->event_reading_code = sdr[13]; } err = ipmi_mc_sensor_set_event_support(mc, lun, num, init_events, events_on, init_scan, scan_on, event_sup, assert_sup, deassert_sup, assert_en, deassert_en); if (err) return err; if (init_thresh) { if (thresh_sup == 2 && sdr[3] == 1) { unsigned char thresh_val[6]; thresh_val[0] = sdr[41]; thresh_val[1] = sdr[40]; thresh_val[2] = sdr[39]; thresh_val[3] = sdr[38]; thresh_val[4] = sdr[37]; thresh_val[5] = sdr[36]; err = ipmi_mc_sensor_set_threshold(mc, lun, num, thresh_sup, thresh_set, 1, thresh_val); } else { err = ipmi_mc_sensor_set_threshold(mc, lun, num, thresh_sup, thresh_set, 0, NULL); } if (err) return err; } if (init_hyst) { if (sdr[3] == 1) { err = ipmi_mc_sensor_set_hysteresis(mc, lun, num, hyst_sup, sdr[42], sdr[43]); } else if (sdr[3] == 2) { err = ipmi_mc_sensor_set_hysteresis(mc, lun, num, hyst_sup, sdr[25], sdr[26]); } } return err; } static int check_sensor_sdr(lmc_data_t *mc, unsigned char *sdr, unsigned int len, void *cb_data) { sensor_t *sensor = cb_data; uint8_t mc_ipmb = is_mc_get_ipmb(mc); if (len < 8) return 0; if ((sdr[3] != 1) && (sdr[3] != 2)) return 0; if (sdr[5] != mc_ipmb) return 0; if ((sdr[6] & 0x3) != sensor->lun) return 0; if (sdr[7] != sensor->num) return 0; init_sensor_from_sdr(mc, sdr); return 1; } int ipmi_mc_add_sensor(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char type, unsigned char event_reading_code, int event_only) { sensor_t *sensor; lmc_data_t *bmc; if ((lun >= 4) || (sens_num >= 255) || (mc->sensors[lun][sens_num])) return EINVAL; sensor = malloc(sizeof(*sensor)); if (!sensor) return ENOMEM; memset(sensor, 0, sizeof(*sensor)); sensor->mc = mc; sensor->lun = lun; sensor->num = sens_num; sensor->sensor_type = type; sensor->event_reading_code = event_reading_code; sensor->event_only = event_only; mc->sensors[lun][sens_num] = sensor; if (mc->emu->atca_mode && (type == 0xf0)) { /* This is the ATCA hot-swap sensor. */ mc->hs_sensor = sensor; sensor->sensor_update_handler = picmg_led_set; } bmc = ipmi_emu_get_bmc_mc(mc->emu); if (bmc) iterate_sdrs(mc, &bmc->main_sdrs, check_sensor_sdr, sensor); /* Delay enable so the above process won't generate any events. */ sensor->enabled = 1; /* Clear any status we might have just generated. */ sensor->event_status = 0; return 0; } struct file_data { char *filename; unsigned int offset; unsigned int length; unsigned int mask; unsigned int initstate; int is_raw; int mult; int div; int sub; int base; emu_data_t *emu; lmc_data_t *sensor_mc; unsigned char sensor_lun; unsigned char sensor_num; unsigned char depends_mc_addr; unsigned char depends_lun; unsigned char depends_sensor_num; unsigned char depends_sensor_bit; }; static int file_poll(void *cb_data, unsigned int *rval, const char **errstr) { struct file_data *f = cb_data; int fd; int rv; int val; char *end; int errv; if (f->depends_mc_addr) { lmc_data_t *mc = f->sensor_mc; sensor_t *sensor, *dsensor; sensor = mc->sensors[f->sensor_lun][f->sensor_num]; if (!sensor) { *errstr = "Invalid sensor"; return EINVAL; } errv = ipmi_emu_get_mc_by_addr(mc->emu, f->depends_mc_addr, &mc); if (errv) { *errstr = "Invalid depends mc address"; return errv; } dsensor = mc->sensors[f->depends_lun][f->depends_sensor_num]; if (!dsensor) { *errstr = "Invalid depends sensor number or LUN"; return EINVAL; } sensor->enabled = bit_set(dsensor->event_status, f->depends_sensor_bit); if (!sensor->enabled) return 0; } fd = open(f->filename, O_RDONLY); if (fd == -1) { errv = errno; *errstr = "Unable to open sensor file"; return errv; } if (f->offset) { if (lseek(fd, f->offset, SEEK_SET) == -1) { errv = errno; close(fd); *errstr = "Unable to seek file"; return errv; } } if (f->is_raw) { unsigned char data[4]; int i; int length = f->length; if (length > 4) length = 4; rv = read(fd, data, length); errv = errno; close(fd); if (rv == -1) { *errstr = "No data read from file"; return errv; } else if (rv < length) { *errstr = "Short data read from file"; return -1; } val = 0; for (i = 0; i < length; i++) val |= data[i] << (i * 8); } else { char data[100]; rv = read(fd, data, sizeof(data) - 1); errv = errno; close(fd); if (rv == -1) { *errstr = "No data read from file"; return errv; } data[rv] = '\0'; val = strtol(data, &end, f->base); if ((*end != '\0' && !isspace(*end)) || (end == data)) { *errstr = "Invalid data read from file"; return EINVAL; } } if (f->mask) val &= f->mask; val -= f->sub; if (f->mult) val = val * f->mult; if (f->div) val = (val + (f->div / 2)) / f->div; *rval = val; return 0; } static int file_init(lmc_data_t *mc, unsigned char lun, unsigned char sensor_num, char **toks, void *cb_data, void **rcb_data, const char **errstr) { char *fname = NULL; struct file_data *f; char *end; int err; const char *tok; if (lun >= 4) { *errstr = "Invalid sensor LUN"; return EINVAL; } err = get_delim_str(toks, &fname, errstr); if (err) return ENOMEM; f = malloc(sizeof(*f)); if (!f) { free(fname); return ENOMEM; } memset(f, 0, sizeof(*f)); f->emu = mc->emu; f->sensor_mc = mc; f->sensor_lun = lun; f->sensor_num = sensor_num; tok = mystrtok(NULL, " \t\n", toks); while (tok) { if (strncmp("div=", tok, 4) == 0) { f->div = strtol(tok + 4, &end, 0); if (*end != '\0') { *errstr = "Invalid div value"; goto out_err; } } else if (strncmp("mult=", tok, 5) == 0) { f->mult = strtol(tok + 5, &end, 0); if (*end != '\0') { *errstr = "Invalid mult value"; goto out_err; } } else if (strncmp("sub=", tok, 4) == 0) { f->sub = strtol(tok + 4, &end, 0); if (*end != '\0') { *errstr = "Invalid sub value"; goto out_err; } } else if (strncmp("base=", tok, 5) == 0) { f->base = strtol(tok + 5, &end, 0); if (*end != '\0') { *errstr = "Invalid base value"; goto out_err; } } else if (strncmp("mask=", tok, 5) == 0) { f->mask = strtol(tok + 5, &end, 0); if (*end != '\0') { *errstr = "Invalid mask value"; goto out_err; } } else if (strncmp("initstate=", tok, 5) == 0) { f->initstate = strtol(tok + 5, &end, 0); if (*end != '\0') { *errstr = "Invalid initstate value"; goto out_err; } } else if (strcmp("raw", tok) == 0) { f->is_raw = 1; } else if (strcmp("ascii", tok) == 0) { f->is_raw = 0; } else if (strncmp("offset=", tok, 7) == 0) { f->offset = strtoul(tok + 7, &end, 0); if (*end != '\0') { *errstr = "Invalid offset value"; goto out_err; } } else if (strncmp("length=", tok, 7) == 0) { f->length = strtoul(tok + 7, &end, 0); if (*end != '\0') { *errstr = "Invalid length value"; goto out_err; } } else if (strncmp("depends=", tok, 8) == 0) { char *toks2; tok = mystrtok((char *) tok + 8, ",", &toks2); if (!tok) { *errstr = "No mc address for sensor depends"; goto out_err; } f->depends_mc_addr = strtoul((char *) tok, &end, 0); if (*end != '\0') { *errstr = "Invalid depends mc addr"; goto out_err; } tok = mystrtok(NULL, ",", &toks2); if (!tok) { *errstr = "No lun for sensor depends"; goto out_err; } f->depends_lun = strtoul(tok, &end, 0); if (*end != '\0' || f->depends_lun >= 4) { *errstr = "Invalid depends lun"; goto out_err; } tok = mystrtok(NULL, ",", &toks2); if (!tok) { *errstr = "No sensor number for sensor depends"; goto out_err; } f->depends_sensor_num = strtoul(tok, &end, 0); if (*end != '\0') { *errstr = "Invalid depends sensor_number"; goto out_err; } tok = mystrtok(NULL, ",", &toks2); if (!tok) { *errstr = "No sensor bit for sensor depends"; goto out_err; } f->depends_sensor_bit = strtoul(tok, &end, 0); if (*end != '\0' || f->depends_sensor_bit >= 15) { *errstr = "Invalid depends sensor_number"; goto out_err; } } else { *errstr = "Invalid file option, options are div= and base="; goto out_err; } tok = mystrtok(NULL, " \t\n", toks); } f->filename = fname; *rcb_data = f; return 0; out_err: free(fname); free(f); return -1; } static int file_post_init(void *cb_data, const char **errstr) { struct file_data *f = cb_data; lmc_data_t *mc = f->sensor_mc; sensor_t *sensor; sensor = mc->sensors[f->sensor_lun][f->sensor_num]; if (!sensor) { *errstr = "Unable to find sensor"; return EINVAL; } sensor->event_status = f->initstate; return 0; } static ipmi_sensor_handler_t file_sensor = { .name = "file", .poll = file_poll, .init = file_init, .postinit = file_post_init }; static ipmi_sensor_handler_t *sensor_handlers = &file_sensor; int ipmi_sensor_add_handler(ipmi_sensor_handler_t *handler) { handler->next = sensor_handlers; sensor_handlers = handler; return 0; } ipmi_sensor_handler_t * ipmi_sensor_find_handler(const char *name) { ipmi_sensor_handler_t *handler = sensor_handlers; while (handler) { if (strcmp(handler->name, name) == 0) return handler; handler = handler->next; } return NULL; } static void free_sensor(lmc_data_t *mc, sensor_t *sensor) { mc->sensors[sensor->lun][sensor->num] = NULL; free(sensor); } static void sensor_poll(void *cb_data) { sensor_t *sensor = cb_data; if (sensor->poll && sensor->scanning_enabled) { lmc_data_t *mc = sensor->mc; unsigned int val; const char *errstr; int err; err = sensor->poll(sensor->cb_data, &val, &errstr); if (err) { mc->sysinfo->log(mc->sysinfo, OS_ERROR, NULL, "Error getting sensor value (%2.2x,%d,%d): %s, %s", is_mc_get_ipmb(mc), sensor->lun, sensor->num, strerror(err), errstr); goto out_restart; } if (sensor->event_reading_code == IPMI_EVENT_READING_TYPE_THRESHOLD) { if (val > 255) val = 255; set_sensor_value(mc, sensor, val, 1); } else { unsigned int i; for (i = 0; i < 15; i++) set_sensor_bit(mc, sensor, i, ((val >> i) & 1), 0, 0xff, 0xff, 1); } out_restart: mc->sysinfo->start_timer(sensor->poll_timer, &sensor->poll_timer_time); } } int ipmi_mc_add_polled_sensor(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char type, unsigned char event_reading_code, unsigned int poll_rate, int (*poll)(void *cb_data, unsigned int *val, const char **errstr), void *cb_data) { sensor_t *sensor; int err; err = ipmi_mc_add_sensor(mc, lun, sens_num, type, event_reading_code, 0); if (err) return err; sensor = mc->sensors[lun][sens_num]; sensor->poll = poll; sensor->poll_timer_time.tv_sec = poll_rate / 1000; sensor->poll_timer_time.tv_usec = (poll_rate % 1000) * 1000; sensor->cb_data = cb_data; err = mc->sysinfo->alloc_timer(mc->sysinfo, sensor_poll, sensor, &sensor->poll_timer); if (err) { free_sensor(mc, sensor); return err; } mc->sysinfo->start_timer(sensor->poll_timer, &sensor->poll_timer_time); return 0; } static void handle_ipmi_get_pef_capabilities(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!mc->sysinfo) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = 0x51; /* version */ rdata[2] = 0x3f; /* support everything but OEM */ rdata[3] = MAX_EVENT_FILTERS; *rdata_len = 4; } static void handle_ipmi_set_pef_config_parms(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char err = 0; int set, block; sys_data_t *sys = mc->sysinfo; if (msg->len < 2) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!sys) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } switch (msg->data[0] & 0x7f) { case 0: switch (msg->data[1] & 0x3) { case 0: if (mc->pef.set_in_progress) { /* rollback */ memcpy(&mc->pef, &mc->pef_rollback, sizeof(mc->pef)); } /* No affect otherwise */ break; case 1: if (mc->pef.set_in_progress) err = 0x81; /* Another user is writing. */ else { /* Save rollback data */ memcpy(&mc->pef_rollback, &mc->pef, sizeof(mc->pef)); mc->pef.set_in_progress = 1; } break; case 2: if (mc->pef.commit) mc->pef.commit(sys); memset(&mc->pef.changed, 0, sizeof(mc->pef.changed)); mc->pef.set_in_progress = 0; break; case 3: err = IPMI_INVALID_DATA_FIELD_CC; } break; case 5: case 8: case 11: err = 0x82; /* Read-only data */ break; case 1: mc->pef.pef_control = msg->data[1]; mc->pef.changed.pef_control = 1; break; case 2: mc->pef.pef_action_global_control = msg->data[1]; mc->pef.changed.pef_action_global_control = 1; break; case 3: mc->pef.pef_startup_delay = msg->data[1]; mc->pef.changed.pef_startup_delay = 1; break; case 4: mc->pef.pef_alert_startup_delay = msg->data[1]; mc->pef.changed.pef_alert_startup_delay = 1; break; case 6: set = msg->data[1] & 0x7f; if (msg->len < 22) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else if ((set <= 0) || (set >= mc->pef.num_event_filters)) err = IPMI_INVALID_DATA_FIELD_CC; else { set = msg->data[1] & 0x7f; memcpy(mc->pef.event_filter_table[set], msg->data+1, 21); mc->pef.changed.event_filter_table[set] = 1; } break; case 7: set = msg->data[1] & 0x7f; if (msg->len < 3) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else if ((set <= 0) || (set >= mc->pef.num_event_filters)) err = IPMI_INVALID_DATA_FIELD_CC; else { set = msg->data[1] & 0x7f; memcpy(mc->pef.event_filter_data1[set], msg->data+1, 2); mc->pef.changed.event_filter_data1[set] = 1; } break; case 9: set = msg->data[1] & 0x7f; if (msg->len < 5) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else if ((set <= 0) || (set >= mc->pef.num_alert_policies)) err = IPMI_INVALID_DATA_FIELD_CC; else { set = msg->data[1] & 0x7f; memcpy(mc->pef.alert_policy_table[set], msg->data+1, 4); mc->pef.changed.alert_policy_table[set] = 1; } break; case 10: if (msg->len < 18) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(mc->pef.system_guid, msg->data+1, 17); mc->pef.changed.system_guid = 1; } break; case 12: set = msg->data[1] & 0x7f; if (msg->len < 4) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else if (set >= mc->pef.num_alert_strings) err = IPMI_INVALID_DATA_FIELD_CC; else { set = msg->data[1] & 0x7f; memcpy(mc->pef.alert_string_keys[set], msg->data+1, 3); mc->pef.changed.alert_string_keys[set] = 1; } break; case 13: set = msg->data[1] & 0x7f; if (msg->len < 4) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else if (set >= mc->pef.num_alert_strings) err = IPMI_INVALID_DATA_FIELD_CC; else if (msg->data[2] == 0) err = IPMI_INVALID_DATA_FIELD_CC; else { int dlen = msg->len - 3; set = msg->data[1] & 0x7f; block = msg->data[2] - 1; if (((block*16) + dlen) > MAX_ALERT_STRING_LEN) { err = IPMI_PARAMETER_OUT_OF_RANGE_CC; break; } memcpy(mc->pef.alert_strings[set]+(block*16), msg->data+3, dlen); mc->pef.changed.alert_strings[set] = 1; } break; default: err = 0x80; /* Parm not supported */ } rdata[0] = err; *rdata_len = 1; } static void handle_ipmi_get_pef_config_parms(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int set, block; unsigned char databyte = 0; unsigned char *data = NULL; unsigned int length = 0; unsigned char err = 0; unsigned char tmpdata[18]; sys_data_t *sys = mc->sysinfo; if (msg->len < 3) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return; } if (!sys) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; return; } switch (msg->data[0] & 0x7f) { case 0: databyte = mc->pef.set_in_progress; break; case 5: databyte = mc->pef.num_event_filters - 1; break; case 8: databyte = mc->pef.num_alert_policies - 1; break; case 11: databyte = mc->pef.num_alert_strings - 1; break; case 1: databyte = mc->pef.pef_control; break; case 2: databyte = mc->pef.pef_action_global_control; break; case 3: databyte = mc->pef.pef_startup_delay; break; case 4: databyte = mc->pef.pef_alert_startup_delay; break; case 6: set = msg->data[1] & 0x7f; if ((set <= 0) || (set >= mc->pef.num_event_filters)) err = IPMI_INVALID_DATA_FIELD_CC; else { data = mc->pef.event_filter_table[set]; length = 21; } break; case 7: set = msg->data[1] & 0x7f; if ((set <= 0) || (set >= mc->pef.num_event_filters)) err = IPMI_INVALID_DATA_FIELD_CC; else { data = mc->pef.event_filter_data1[set]; length = 2; } break; case 9: set = msg->data[1] & 0x7f; if ((set <= 0) || (set >= mc->pef.num_alert_policies)) err = IPMI_INVALID_DATA_FIELD_CC; else { data = mc->pef.alert_policy_table[set]; length = 4; } break; case 10: data = mc->pef.system_guid; length = 17; break; case 12: set = msg->data[1] & 0x7f; if (set >= mc->pef.num_alert_strings) err = IPMI_INVALID_DATA_FIELD_CC; else { data = mc->pef.alert_string_keys[set]; length = 3; } break; case 13: set = msg->data[1] & 0x7f; if (set >= mc->pef.num_alert_strings) err = IPMI_INVALID_DATA_FIELD_CC; else if (msg->data[2] == 0) err = IPMI_INVALID_DATA_FIELD_CC; else { block = msg->data[2] - 1; if ((block*16) > MAX_ALERT_STRING_LEN) { err = IPMI_PARAMETER_OUT_OF_RANGE_CC; break; } tmpdata[0] = set; tmpdata[1] = block + 1; memcpy(tmpdata+2, mc->pef.alert_strings[set]+(block*16), 16); data = tmpdata; length = 18; } break; default: err = 0x80; /* Parm not supported */ } rdata[0] = err; if (err) { *rdata_len = 1; return; } rdata[1] = 0x11; /* rev */ if (msg->data[0] & 0x80) { *rdata_len = 2; } else if (data) { memcpy(rdata + 2, data, length); *rdata_len = length + 2; } else { rdata[2] = databyte; *rdata_len = 3; } } cmd_handler_f sensor_event_netfn_handlers[256] = { [IPMI_GET_EVENT_RECEIVER_CMD] = handle_get_event_receiver, [IPMI_SET_EVENT_RECEIVER_CMD] = handle_set_event_receiver, [IPMI_GET_DEVICE_SDR_INFO_CMD] = handle_get_device_sdr_info, [IPMI_RESERVE_DEVICE_SDR_REPOSITORY_CMD] = handle_reserve_device_sdr_repository, [IPMI_GET_DEVICE_SDR_CMD] = handle_get_device_sdr, [IPMI_SET_SENSOR_HYSTERESIS_CMD] = handle_set_sensor_hysteresis, [IPMI_GET_SENSOR_HYSTERESIS_CMD] = handle_get_sensor_hysteresis, [IPMI_SET_SENSOR_THRESHOLD_CMD] = handle_set_sensor_thresholds, [IPMI_GET_SENSOR_THRESHOLD_CMD] = handle_get_sensor_thresholds, [IPMI_SET_SENSOR_EVENT_ENABLE_CMD] = handle_set_sensor_event_enable, [IPMI_GET_SENSOR_EVENT_ENABLE_CMD] = handle_get_sensor_event_enable, [IPMI_SET_SENSOR_TYPE_CMD] = handle_set_sensor_type, [IPMI_GET_SENSOR_TYPE_CMD] = handle_get_sensor_type, [IPMI_GET_SENSOR_READING_CMD] = handle_get_sensor_reading, [IPMI_GET_PEF_CAPABILITIES_CMD] = handle_ipmi_get_pef_capabilities, [IPMI_SET_PEF_CONFIG_PARMS_CMD] = handle_ipmi_set_pef_config_parms, [IPMI_GET_PEF_CONFIG_PARMS_CMD] = handle_ipmi_get_pef_config_parms, [IPMI_GET_SENSOR_EVENT_STATUS_CMD] = NULL, [IPMI_REARM_SENSOR_EVENTS_CMD] = handle_rearm_sensor_events, [IPMI_GET_SENSOR_READING_FACTORS_CMD] = NULL }; OpenIPMI-2.0.33/lanserv/Makefile.in0000664000175000017500000017670614261607634013653 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = ipmi_sim$(EXEEXT) $(am__EXEEXT_1) noinst_PROGRAMS = ipmi_checksum$(EXEEXT) subdir = lanserv ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/ax_config_feature.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_pkg_swig.m4 \ $(top_srcdir)/m4/ax_prog_python_version.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @HAVE_OPENIPMI_SMI_TRUE@am__EXEEXT_1 = ipmilan$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \ "$(DESTDIR)$(man8dir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libIPMIlanserv_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libIPMIlanserv_la_OBJECTS = lanserv_ipmi.lo lanserv_asf.lo \ priv_table.lo lanserv_oem_force.lo lanserv_config.lo config.lo \ serv.lo serial_ipmi.lo persist.lo extcmd.lo ipmb_ipmi.lo libIPMIlanserv_la_OBJECTS = $(am_libIPMIlanserv_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libIPMIlanserv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libIPMIlanserv_la_LDFLAGS) $(LDFLAGS) \ -o $@ am_ipmi_checksum_OBJECTS = ipmi_checksum.$(OBJEXT) ipmi_checksum_OBJECTS = $(am_ipmi_checksum_OBJECTS) ipmi_checksum_LDADD = $(LDADD) am_ipmi_sim_OBJECTS = ipmi_sim-ipmi_sim.$(OBJEXT) \ ipmi_sim-bmc.$(OBJEXT) ipmi_sim-emu_cmd.$(OBJEXT) \ ipmi_sim-sol.$(OBJEXT) ipmi_sim-bmc_storage.$(OBJEXT) \ ipmi_sim-bmc_app.$(OBJEXT) ipmi_sim-bmc_chassis.$(OBJEXT) \ ipmi_sim-bmc_transport.$(OBJEXT) ipmi_sim-bmc_sensor.$(OBJEXT) \ ipmi_sim-bmc_picmg.$(OBJEXT) ipmi_sim_OBJECTS = $(am_ipmi_sim_OBJECTS) ipmi_sim_DEPENDENCIES = $(am__DEPENDENCIES_1) libIPMIlanserv.la \ $(am__DEPENDENCIES_1) ipmi_sim_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipmi_sim_CFLAGS) \ $(CFLAGS) $(ipmi_sim_LDFLAGS) $(LDFLAGS) -o $@ am__ipmilan_SOURCES_DIST = lanserv.c @HAVE_OPENIPMI_SMI_TRUE@am_ipmilan_OBJECTS = \ @HAVE_OPENIPMI_SMI_TRUE@ ipmilan-lanserv.$(OBJEXT) ipmilan_OBJECTS = $(am_ipmilan_OBJECTS) @HAVE_OPENIPMI_SMI_TRUE@ipmilan_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @HAVE_OPENIPMI_SMI_TRUE@ libIPMIlanserv.la \ @HAVE_OPENIPMI_SMI_TRUE@ $(am__DEPENDENCIES_1) ipmilan_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipmilan_CFLAGS) \ $(CFLAGS) $(ipmilan_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/config.Plo ./$(DEPDIR)/extcmd.Plo \ ./$(DEPDIR)/ipmb_ipmi.Plo ./$(DEPDIR)/ipmi_checksum.Po \ ./$(DEPDIR)/ipmi_sim-bmc.Po ./$(DEPDIR)/ipmi_sim-bmc_app.Po \ ./$(DEPDIR)/ipmi_sim-bmc_chassis.Po \ ./$(DEPDIR)/ipmi_sim-bmc_picmg.Po \ ./$(DEPDIR)/ipmi_sim-bmc_sensor.Po \ ./$(DEPDIR)/ipmi_sim-bmc_storage.Po \ ./$(DEPDIR)/ipmi_sim-bmc_transport.Po \ ./$(DEPDIR)/ipmi_sim-emu_cmd.Po \ ./$(DEPDIR)/ipmi_sim-ipmi_sim.Po ./$(DEPDIR)/ipmi_sim-sol.Po \ ./$(DEPDIR)/ipmilan-lanserv.Po ./$(DEPDIR)/lanserv_asf.Plo \ ./$(DEPDIR)/lanserv_config.Plo ./$(DEPDIR)/lanserv_ipmi.Plo \ ./$(DEPDIR)/lanserv_oem_force.Plo ./$(DEPDIR)/persist.Plo \ ./$(DEPDIR)/priv_table.Plo ./$(DEPDIR)/serial_ipmi.Plo \ ./$(DEPDIR)/serv.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libIPMIlanserv_la_SOURCES) $(ipmi_checksum_SOURCES) \ $(ipmi_sim_SOURCES) $(ipmilan_SOURCES) DIST_SOURCES = $(libIPMIlanserv_la_SOURCES) $(ipmi_checksum_SOURCES) \ $(ipmi_sim_SOURCES) $(am__ipmilan_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) DATA = $(noinst_DATA) HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir distdir-am am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp TODO DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BIBTEX = @BIBTEX@ BUILD_CC = @BUILD_CC@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DIA = @DIA@ DIA_FILTER_NAME = @DIA_FILTER_NAME@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPDF = @DVIPDF@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDBM_LIB = @GDBM_LIB@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_DIR = @GLIB_DIR@ GLIB_LIB = @GLIB_LIB@ GLIB_LIBS = @GLIB_LIBS@ GLIB_PKGCONF = @GLIB_PKGCONF@ GLIB_SO = @GLIB_SO@ GLIB_TARGET = @GLIB_TARGET@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MARVELL_BMC_DIR = @MARVELL_BMC_DIR@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENIPMI_SWIG_LIBS = @OPENIPMI_SWIG_LIBS@ OPENIPMI_SWIG_SO = @OPENIPMI_SWIG_SO@ OPENIPMI_VERSION_EXTRA = @OPENIPMI_VERSION_EXTRA@ OPENIPMI_VERSION_MAJOR = @OPENIPMI_VERSION_MAJOR@ OPENIPMI_VERSION_MINOR = @OPENIPMI_VERSION_MINOR@ OPENIPMI_VERSION_RELEASE = @OPENIPMI_VERSION_RELEASE@ OPENSSLINCS = @OPENSSLINCS@ OPENSSLLIBS = @OPENSSLLIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL_CFLAGS = @PERL_CFLAGS@ PERL_DIR = @PERL_DIR@ PERL_HAS_POSIX_THREADS = @PERL_HAS_POSIX_THREADS@ PERL_INSTALL_DIR = @PERL_INSTALL_DIR@ PERL_POSIX_LIB = @PERL_POSIX_LIB@ PERL_POSIX_SO = @PERL_POSIX_SO@ POPTLIBS = @POPTLIBS@ PYTHON = @PYTHON@ PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ PYTHON_DIR = @PYTHON_DIR@ PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ PYTHON_GUI_DIR = @PYTHON_GUI_DIR@ PYTHON_HAS_POSIX_THREADS = @PYTHON_HAS_POSIX_THREADS@ PYTHON_INSTALL_DIR = @PYTHON_INSTALL_DIR@ PYTHON_INSTALL_LIB_DIR = @PYTHON_INSTALL_LIB_DIR@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM_SITE_PKG = @PYTHON_PLATFORM_SITE_PKG@ PYTHON_POSIX_LIB = @PYTHON_POSIX_LIB@ PYTHON_POSIX_SO = @PYTHON_POSIX_SO@ PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ PYTHON_SWIG_FLAGS = @PYTHON_SWIG_FLAGS@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ RT_LIB = @RT_LIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMPLIBS = @SNMPLIBS@ SOCKETLIB = @SOCKETLIB@ STRIP = @STRIP@ SWIG = @SWIG@ SWIG_DIR = @SWIG_DIR@ SWIG_LIB = @SWIG_LIB@ TCL_CFLAGS = @TCL_CFLAGS@ TCL_DIR = @TCL_DIR@ TCL_LIB = @TCL_LIB@ TCL_LIBS = @TCL_LIBS@ TCL_PKGCONF = @TCL_PKGCONF@ TCL_SO = @TCL_SO@ TCL_TARGET = @TCL_TARGET@ TERM_LIBS = @TERM_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ diaprog = @diaprog@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ perlprog = @perlprog@ pkgprog = @pkgprog@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ LIB_VERSION = 0.0.1 LD_VERSION = 0:1:0 PVERSION = "1.0.13" SUBDIRS = OpenIPMI sdrcomp @MARVELL_BMC_DIR@ DIST_SUBDIRS = OpenIPMI sdrcomp marvell-bmc AM_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include -DIPMI_CHECK_LOCKS \ $(OPENSSLINCS) -DPVERSION="\"$(PVERSION)\"" -DBUILDING_IPMI_LANSERV_DLL AM_CPPFLAGS = -DSYSCONFDIR='"$(sysconfdir)"' -DSTATEDIR='"$(localstatedir)"' lib_LTLIBRARIES = libIPMIlanserv.la @HAVE_OPENIPMI_SMI_TRUE@IPMILAN_PROG = ipmilan @HAVE_OPENIPMI_SMI_FALSE@IPMILAN_MAN = @HAVE_OPENIPMI_SMI_TRUE@IPMILAN_MAN = ipmilan.8 @HAVE_OPENIPMI_SMI_FALSE@IPMILAN_NOMAN = ipmilan.8 @HAVE_OPENIPMI_SMI_TRUE@IPMILAN_NOMAN = @HAVE_OPENIPMI_SMI_FALSE@IPMILANPROG = noinst_HEADERS = emu.h bmc.h ipmi_sim.h sol.h libIPMIlanserv_la_SOURCES = lanserv_ipmi.c lanserv_asf.c priv_table.c \ lanserv_oem_force.c lanserv_config.c config.c serv.c serial_ipmi.c \ persist.c extcmd.c ipmb_ipmi.c libIPMIlanserv_la_LIBADD = $(OPENSSLLIBS) -ldl $(RT_LIB) libIPMIlanserv_la_LDFLAGS = -version-info $(LD_VERSION) \ ../utils/libOpenIPMIutils.la -no-undefined ipmi_checksum_SOURCES = ipmi_checksum.c @HAVE_OPENIPMI_SMI_TRUE@ipmilan_SOURCES = lanserv.c @HAVE_OPENIPMI_SMI_TRUE@ipmilan_LDADD = $(POPTLIBS) libIPMIlanserv.la -ldl $(RT_LIB) @HAVE_OPENIPMI_SMI_TRUE@ipmilan_LDFLAGS = -rdynamic ../unix/libOpenIPMIposix.la \ @HAVE_OPENIPMI_SMI_TRUE@ ../utils/libOpenIPMIutils.la @HAVE_OPENIPMI_SMI_TRUE@ipmilan_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include \ @HAVE_OPENIPMI_SMI_TRUE@ -DIPMI_CHECK_LOCKS $(OPENSSLINCS) -DPVERSION="\"$(PVERSION)\"" ipmi_sim_SOURCES = ipmi_sim.c bmc.c emu_cmd.c sol.c \ bmc_storage.c bmc_app.c bmc_chassis.c bmc_transport.c \ bmc_sensor.c bmc_picmg.c ipmi_sim_LDADD = $(POPTLIBS) libIPMIlanserv.la -lpthread $(RT_LIB) ipmi_sim_LDFLAGS = -rdynamic ../unix/libOpenIPMIposix.la \ ../utils/libOpenIPMIutils.la $(SOCKETLIB) ipmi_sim_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include \ -DIPMI_CHECK_LOCKS $(OPENSSLINCS) -DPVERSION="\"$(PVERSION)\"" man_MANS = $(IPMILAN_MAN) ipmi_lan.5 ipmi_sim.1 ipmi_sim_cmd.5 READMES = README.ipmi_sim README.vm README.design README.yourownbmc EXTRA_DIST = atca.emu lan.conf ipmisim1.emu ipmisim1.sdrs \ $(man_MANS) $(IPMILAN_NOMAN) $(READMES) noinst_DATA = ipmisim1.bsdr SUFFIXES = .bsdr .sdrs CLEANFILES = ipmisim1.bsdr all: all-recursive .SUFFIXES: .SUFFIXES: .bsdr .sdrs .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lanserv/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lanserv/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libIPMIlanserv.la: $(libIPMIlanserv_la_OBJECTS) $(libIPMIlanserv_la_DEPENDENCIES) $(EXTRA_libIPMIlanserv_la_DEPENDENCIES) $(AM_V_CCLD)$(libIPMIlanserv_la_LINK) -rpath $(libdir) $(libIPMIlanserv_la_OBJECTS) $(libIPMIlanserv_la_LIBADD) $(LIBS) ipmi_checksum$(EXEEXT): $(ipmi_checksum_OBJECTS) $(ipmi_checksum_DEPENDENCIES) $(EXTRA_ipmi_checksum_DEPENDENCIES) @rm -f ipmi_checksum$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ipmi_checksum_OBJECTS) $(ipmi_checksum_LDADD) $(LIBS) ipmi_sim$(EXEEXT): $(ipmi_sim_OBJECTS) $(ipmi_sim_DEPENDENCIES) $(EXTRA_ipmi_sim_DEPENDENCIES) @rm -f ipmi_sim$(EXEEXT) $(AM_V_CCLD)$(ipmi_sim_LINK) $(ipmi_sim_OBJECTS) $(ipmi_sim_LDADD) $(LIBS) ipmilan$(EXEEXT): $(ipmilan_OBJECTS) $(ipmilan_DEPENDENCIES) $(EXTRA_ipmilan_DEPENDENCIES) @rm -f ipmilan$(EXEEXT) $(AM_V_CCLD)$(ipmilan_LINK) $(ipmilan_OBJECTS) $(ipmilan_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extcmd.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmb_ipmi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_checksum.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc_app.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc_chassis.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc_picmg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc_sensor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc_storage.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-bmc_transport.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-emu_cmd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-ipmi_sim.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sim-sol.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilan-lanserv.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanserv_asf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanserv_config.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanserv_ipmi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanserv_oem_force.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/persist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/priv_table.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serial_ipmi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serv.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< ipmi_sim-ipmi_sim.o: ipmi_sim.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-ipmi_sim.o -MD -MP -MF $(DEPDIR)/ipmi_sim-ipmi_sim.Tpo -c -o ipmi_sim-ipmi_sim.o `test -f 'ipmi_sim.c' || echo '$(srcdir)/'`ipmi_sim.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-ipmi_sim.Tpo $(DEPDIR)/ipmi_sim-ipmi_sim.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipmi_sim.c' object='ipmi_sim-ipmi_sim.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-ipmi_sim.o `test -f 'ipmi_sim.c' || echo '$(srcdir)/'`ipmi_sim.c ipmi_sim-ipmi_sim.obj: ipmi_sim.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-ipmi_sim.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-ipmi_sim.Tpo -c -o ipmi_sim-ipmi_sim.obj `if test -f 'ipmi_sim.c'; then $(CYGPATH_W) 'ipmi_sim.c'; else $(CYGPATH_W) '$(srcdir)/ipmi_sim.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-ipmi_sim.Tpo $(DEPDIR)/ipmi_sim-ipmi_sim.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipmi_sim.c' object='ipmi_sim-ipmi_sim.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-ipmi_sim.obj `if test -f 'ipmi_sim.c'; then $(CYGPATH_W) 'ipmi_sim.c'; else $(CYGPATH_W) '$(srcdir)/ipmi_sim.c'; fi` ipmi_sim-bmc.o: bmc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc.Tpo -c -o ipmi_sim-bmc.o `test -f 'bmc.c' || echo '$(srcdir)/'`bmc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc.Tpo $(DEPDIR)/ipmi_sim-bmc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc.c' object='ipmi_sim-bmc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc.o `test -f 'bmc.c' || echo '$(srcdir)/'`bmc.c ipmi_sim-bmc.obj: bmc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc.Tpo -c -o ipmi_sim-bmc.obj `if test -f 'bmc.c'; then $(CYGPATH_W) 'bmc.c'; else $(CYGPATH_W) '$(srcdir)/bmc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc.Tpo $(DEPDIR)/ipmi_sim-bmc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc.c' object='ipmi_sim-bmc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc.obj `if test -f 'bmc.c'; then $(CYGPATH_W) 'bmc.c'; else $(CYGPATH_W) '$(srcdir)/bmc.c'; fi` ipmi_sim-emu_cmd.o: emu_cmd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-emu_cmd.o -MD -MP -MF $(DEPDIR)/ipmi_sim-emu_cmd.Tpo -c -o ipmi_sim-emu_cmd.o `test -f 'emu_cmd.c' || echo '$(srcdir)/'`emu_cmd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-emu_cmd.Tpo $(DEPDIR)/ipmi_sim-emu_cmd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='emu_cmd.c' object='ipmi_sim-emu_cmd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-emu_cmd.o `test -f 'emu_cmd.c' || echo '$(srcdir)/'`emu_cmd.c ipmi_sim-emu_cmd.obj: emu_cmd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-emu_cmd.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-emu_cmd.Tpo -c -o ipmi_sim-emu_cmd.obj `if test -f 'emu_cmd.c'; then $(CYGPATH_W) 'emu_cmd.c'; else $(CYGPATH_W) '$(srcdir)/emu_cmd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-emu_cmd.Tpo $(DEPDIR)/ipmi_sim-emu_cmd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='emu_cmd.c' object='ipmi_sim-emu_cmd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-emu_cmd.obj `if test -f 'emu_cmd.c'; then $(CYGPATH_W) 'emu_cmd.c'; else $(CYGPATH_W) '$(srcdir)/emu_cmd.c'; fi` ipmi_sim-sol.o: sol.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-sol.o -MD -MP -MF $(DEPDIR)/ipmi_sim-sol.Tpo -c -o ipmi_sim-sol.o `test -f 'sol.c' || echo '$(srcdir)/'`sol.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-sol.Tpo $(DEPDIR)/ipmi_sim-sol.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sol.c' object='ipmi_sim-sol.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-sol.o `test -f 'sol.c' || echo '$(srcdir)/'`sol.c ipmi_sim-sol.obj: sol.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-sol.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-sol.Tpo -c -o ipmi_sim-sol.obj `if test -f 'sol.c'; then $(CYGPATH_W) 'sol.c'; else $(CYGPATH_W) '$(srcdir)/sol.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-sol.Tpo $(DEPDIR)/ipmi_sim-sol.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sol.c' object='ipmi_sim-sol.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-sol.obj `if test -f 'sol.c'; then $(CYGPATH_W) 'sol.c'; else $(CYGPATH_W) '$(srcdir)/sol.c'; fi` ipmi_sim-bmc_storage.o: bmc_storage.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_storage.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_storage.Tpo -c -o ipmi_sim-bmc_storage.o `test -f 'bmc_storage.c' || echo '$(srcdir)/'`bmc_storage.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_storage.Tpo $(DEPDIR)/ipmi_sim-bmc_storage.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_storage.c' object='ipmi_sim-bmc_storage.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_storage.o `test -f 'bmc_storage.c' || echo '$(srcdir)/'`bmc_storage.c ipmi_sim-bmc_storage.obj: bmc_storage.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_storage.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_storage.Tpo -c -o ipmi_sim-bmc_storage.obj `if test -f 'bmc_storage.c'; then $(CYGPATH_W) 'bmc_storage.c'; else $(CYGPATH_W) '$(srcdir)/bmc_storage.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_storage.Tpo $(DEPDIR)/ipmi_sim-bmc_storage.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_storage.c' object='ipmi_sim-bmc_storage.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_storage.obj `if test -f 'bmc_storage.c'; then $(CYGPATH_W) 'bmc_storage.c'; else $(CYGPATH_W) '$(srcdir)/bmc_storage.c'; fi` ipmi_sim-bmc_app.o: bmc_app.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_app.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_app.Tpo -c -o ipmi_sim-bmc_app.o `test -f 'bmc_app.c' || echo '$(srcdir)/'`bmc_app.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_app.Tpo $(DEPDIR)/ipmi_sim-bmc_app.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_app.c' object='ipmi_sim-bmc_app.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_app.o `test -f 'bmc_app.c' || echo '$(srcdir)/'`bmc_app.c ipmi_sim-bmc_app.obj: bmc_app.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_app.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_app.Tpo -c -o ipmi_sim-bmc_app.obj `if test -f 'bmc_app.c'; then $(CYGPATH_W) 'bmc_app.c'; else $(CYGPATH_W) '$(srcdir)/bmc_app.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_app.Tpo $(DEPDIR)/ipmi_sim-bmc_app.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_app.c' object='ipmi_sim-bmc_app.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_app.obj `if test -f 'bmc_app.c'; then $(CYGPATH_W) 'bmc_app.c'; else $(CYGPATH_W) '$(srcdir)/bmc_app.c'; fi` ipmi_sim-bmc_chassis.o: bmc_chassis.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_chassis.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_chassis.Tpo -c -o ipmi_sim-bmc_chassis.o `test -f 'bmc_chassis.c' || echo '$(srcdir)/'`bmc_chassis.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_chassis.Tpo $(DEPDIR)/ipmi_sim-bmc_chassis.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_chassis.c' object='ipmi_sim-bmc_chassis.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_chassis.o `test -f 'bmc_chassis.c' || echo '$(srcdir)/'`bmc_chassis.c ipmi_sim-bmc_chassis.obj: bmc_chassis.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_chassis.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_chassis.Tpo -c -o ipmi_sim-bmc_chassis.obj `if test -f 'bmc_chassis.c'; then $(CYGPATH_W) 'bmc_chassis.c'; else $(CYGPATH_W) '$(srcdir)/bmc_chassis.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_chassis.Tpo $(DEPDIR)/ipmi_sim-bmc_chassis.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_chassis.c' object='ipmi_sim-bmc_chassis.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_chassis.obj `if test -f 'bmc_chassis.c'; then $(CYGPATH_W) 'bmc_chassis.c'; else $(CYGPATH_W) '$(srcdir)/bmc_chassis.c'; fi` ipmi_sim-bmc_transport.o: bmc_transport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_transport.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_transport.Tpo -c -o ipmi_sim-bmc_transport.o `test -f 'bmc_transport.c' || echo '$(srcdir)/'`bmc_transport.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_transport.Tpo $(DEPDIR)/ipmi_sim-bmc_transport.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_transport.c' object='ipmi_sim-bmc_transport.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_transport.o `test -f 'bmc_transport.c' || echo '$(srcdir)/'`bmc_transport.c ipmi_sim-bmc_transport.obj: bmc_transport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_transport.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_transport.Tpo -c -o ipmi_sim-bmc_transport.obj `if test -f 'bmc_transport.c'; then $(CYGPATH_W) 'bmc_transport.c'; else $(CYGPATH_W) '$(srcdir)/bmc_transport.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_transport.Tpo $(DEPDIR)/ipmi_sim-bmc_transport.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_transport.c' object='ipmi_sim-bmc_transport.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_transport.obj `if test -f 'bmc_transport.c'; then $(CYGPATH_W) 'bmc_transport.c'; else $(CYGPATH_W) '$(srcdir)/bmc_transport.c'; fi` ipmi_sim-bmc_sensor.o: bmc_sensor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_sensor.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_sensor.Tpo -c -o ipmi_sim-bmc_sensor.o `test -f 'bmc_sensor.c' || echo '$(srcdir)/'`bmc_sensor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_sensor.Tpo $(DEPDIR)/ipmi_sim-bmc_sensor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_sensor.c' object='ipmi_sim-bmc_sensor.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_sensor.o `test -f 'bmc_sensor.c' || echo '$(srcdir)/'`bmc_sensor.c ipmi_sim-bmc_sensor.obj: bmc_sensor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_sensor.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_sensor.Tpo -c -o ipmi_sim-bmc_sensor.obj `if test -f 'bmc_sensor.c'; then $(CYGPATH_W) 'bmc_sensor.c'; else $(CYGPATH_W) '$(srcdir)/bmc_sensor.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_sensor.Tpo $(DEPDIR)/ipmi_sim-bmc_sensor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_sensor.c' object='ipmi_sim-bmc_sensor.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_sensor.obj `if test -f 'bmc_sensor.c'; then $(CYGPATH_W) 'bmc_sensor.c'; else $(CYGPATH_W) '$(srcdir)/bmc_sensor.c'; fi` ipmi_sim-bmc_picmg.o: bmc_picmg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_picmg.o -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_picmg.Tpo -c -o ipmi_sim-bmc_picmg.o `test -f 'bmc_picmg.c' || echo '$(srcdir)/'`bmc_picmg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_picmg.Tpo $(DEPDIR)/ipmi_sim-bmc_picmg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_picmg.c' object='ipmi_sim-bmc_picmg.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_picmg.o `test -f 'bmc_picmg.c' || echo '$(srcdir)/'`bmc_picmg.c ipmi_sim-bmc_picmg.obj: bmc_picmg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -MT ipmi_sim-bmc_picmg.obj -MD -MP -MF $(DEPDIR)/ipmi_sim-bmc_picmg.Tpo -c -o ipmi_sim-bmc_picmg.obj `if test -f 'bmc_picmg.c'; then $(CYGPATH_W) 'bmc_picmg.c'; else $(CYGPATH_W) '$(srcdir)/bmc_picmg.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_sim-bmc_picmg.Tpo $(DEPDIR)/ipmi_sim-bmc_picmg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bmc_picmg.c' object='ipmi_sim-bmc_picmg.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_sim_CFLAGS) $(CFLAGS) -c -o ipmi_sim-bmc_picmg.obj `if test -f 'bmc_picmg.c'; then $(CYGPATH_W) 'bmc_picmg.c'; else $(CYGPATH_W) '$(srcdir)/bmc_picmg.c'; fi` ipmilan-lanserv.o: lanserv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmilan_CFLAGS) $(CFLAGS) -MT ipmilan-lanserv.o -MD -MP -MF $(DEPDIR)/ipmilan-lanserv.Tpo -c -o ipmilan-lanserv.o `test -f 'lanserv.c' || echo '$(srcdir)/'`lanserv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmilan-lanserv.Tpo $(DEPDIR)/ipmilan-lanserv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lanserv.c' object='ipmilan-lanserv.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmilan_CFLAGS) $(CFLAGS) -c -o ipmilan-lanserv.o `test -f 'lanserv.c' || echo '$(srcdir)/'`lanserv.c ipmilan-lanserv.obj: lanserv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmilan_CFLAGS) $(CFLAGS) -MT ipmilan-lanserv.obj -MD -MP -MF $(DEPDIR)/ipmilan-lanserv.Tpo -c -o ipmilan-lanserv.obj `if test -f 'lanserv.c'; then $(CYGPATH_W) 'lanserv.c'; else $(CYGPATH_W) '$(srcdir)/lanserv.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipmilan-lanserv.Tpo $(DEPDIR)/ipmilan-lanserv.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lanserv.c' object='ipmilan-lanserv.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmilan_CFLAGS) $(CFLAGS) -c -o ipmilan-lanserv.obj `if test -f 'lanserv.c'; then $(CYGPATH_W) 'lanserv.c'; else $(CYGPATH_W) '$(srcdir)/lanserv.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man5: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f ./$(DEPDIR)/config.Plo -rm -f ./$(DEPDIR)/extcmd.Plo -rm -f ./$(DEPDIR)/ipmb_ipmi.Plo -rm -f ./$(DEPDIR)/ipmi_checksum.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_app.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_chassis.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_picmg.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_sensor.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_storage.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_transport.Po -rm -f ./$(DEPDIR)/ipmi_sim-emu_cmd.Po -rm -f ./$(DEPDIR)/ipmi_sim-ipmi_sim.Po -rm -f ./$(DEPDIR)/ipmi_sim-sol.Po -rm -f ./$(DEPDIR)/ipmilan-lanserv.Po -rm -f ./$(DEPDIR)/lanserv_asf.Plo -rm -f ./$(DEPDIR)/lanserv_config.Plo -rm -f ./$(DEPDIR)/lanserv_ipmi.Plo -rm -f ./$(DEPDIR)/lanserv_oem_force.Plo -rm -f ./$(DEPDIR)/persist.Plo -rm -f ./$(DEPDIR)/priv_table.Plo -rm -f ./$(DEPDIR)/serial_ipmi.Plo -rm -f ./$(DEPDIR)/serv.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-data-local install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 install-man5 install-man8 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/config.Plo -rm -f ./$(DEPDIR)/extcmd.Plo -rm -f ./$(DEPDIR)/ipmb_ipmi.Plo -rm -f ./$(DEPDIR)/ipmi_checksum.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_app.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_chassis.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_picmg.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_sensor.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_storage.Po -rm -f ./$(DEPDIR)/ipmi_sim-bmc_transport.Po -rm -f ./$(DEPDIR)/ipmi_sim-emu_cmd.Po -rm -f ./$(DEPDIR)/ipmi_sim-ipmi_sim.Po -rm -f ./$(DEPDIR)/ipmi_sim-sol.Po -rm -f ./$(DEPDIR)/ipmilan-lanserv.Po -rm -f ./$(DEPDIR)/lanserv_asf.Plo -rm -f ./$(DEPDIR)/lanserv_config.Plo -rm -f ./$(DEPDIR)/lanserv_ipmi.Plo -rm -f ./$(DEPDIR)/lanserv_oem_force.Plo -rm -f ./$(DEPDIR)/persist.Plo -rm -f ./$(DEPDIR)/priv_table.Plo -rm -f ./$(DEPDIR)/serial_ipmi.Plo -rm -f ./$(DEPDIR)/serv.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-local uninstall-man uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8 .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--depfiles check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-data-local install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-man1 install-man5 install-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-libLTLIBRARIES uninstall-local \ uninstall-man uninstall-man1 uninstall-man5 uninstall-man8 .PRECIOUS: Makefile install-data-local: $(INSTALL) -m 755 -d "$(DESTDIR)$(sysconfdir)/ipmi/"; \ $(INSTALL) -m 600 $(srcdir)/lan.conf "$(DESTDIR)$(sysconfdir)/ipmi/"; $(INSTALL) -m 600 $(srcdir)/ipmisim1.emu "$(DESTDIR)$(sysconfdir)/ipmi/"; .sdrs.bsdr: sdrcomp/sdrcomp_build -o $@ $< ipmisim1.bsdr: $(top_srcdir)/lanserv/ipmisim1.sdrs sdrcomp/sdrcomp_build uninstall-local: -rm -f "$(DESTDIR)$(sysconfdir)/ipmi/ipmisim1.emu" -rm -f "$(DESTDIR)$(sysconfdir)/ipmi/lan.conf" -rm -f "$(DESTDIR)$(sysconfdir)/ipmi/sim.emu" -rmdir "$(DESTDIR)$(sysconfdir)/ipmi" 2>/dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: OpenIPMI-2.0.33/lanserv/OpenIPMI/0000775000175000017500000000000014261607642013224 500000000000000OpenIPMI-2.0.33/lanserv/OpenIPMI/persist.h0000664000175000017500000001056314002617260015001 00000000000000/* * persist.h * * MontaVista IPMI LAN server persistence tool * * Author: MontaVista Software, LLC. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software LLC. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __PERSIST_H__ #define __PERSIST_H__ #include typedef struct persist_s persist_t; IPMI_LANSERV_DLL_PUBLIC int persist_init(const char *app, const char *instance, const char *basedir); IPMI_LANSERV_DLL_PUBLIC persist_t *alloc_persist(const char *name, ...); IPMI_LANSERV_DLL_PUBLIC persist_t *read_persist(const char *name, ...); IPMI_LANSERV_DLL_PUBLIC int write_persist(persist_t *p); IPMI_LANSERV_DLL_PUBLIC int write_persist_file(persist_t *p, FILE *f); IPMI_LANSERV_DLL_PUBLIC void free_persist(persist_t *p); IPMI_LANSERV_DLL_PUBLIC int add_persist_data(persist_t *p, void *data, unsigned int len, const char *name, ...); IPMI_LANSERV_DLL_PUBLIC int read_persist_data(persist_t *p, void **data, unsigned int *len, const char *name, ...); IPMI_LANSERV_DLL_PUBLIC int add_persist_int(persist_t *p, long val, const char *name, ...); IPMI_LANSERV_DLL_PUBLIC int read_persist_int(persist_t *p, long *val, const char *name, ...); IPMI_LANSERV_DLL_PUBLIC int add_persist_str(persist_t *p, const char *val, const char *name, ...); IPMI_LANSERV_DLL_PUBLIC int read_persist_str(persist_t *p, char **val, const char *name, ...); /* * Iterate over all the values in the persist. Call the data function * for each data or string entry, and call the int function for each * integer. */ #define ITER_PERSIST_CONTINUE 0 #define ITER_PERSIST_STOP 1 IPMI_LANSERV_DLL_PUBLIC int iterate_persist(persist_t *p, void *cb_data, int (*data_func)(const char *name, void *data, unsigned int len, void *cb_data), int (*int_func)(const char *name, long val, void *cb_data)); /* Free the values return by read_persist_data() and read_persist_str() */ IPMI_LANSERV_DLL_PUBLIC void free_persist_data(void *data); IPMI_LANSERV_DLL_PUBLIC void free_persist_str(char *str); /* Can be set to zero to disable persistence. */ IPMI_LANSERV_DLL_PUBLIC extern int persist_enable; #endif /* __PERSIST_H__ */ OpenIPMI-2.0.33/lanserv/OpenIPMI/ipmbserv.h0000664000175000017500000000577314002617260015146 00000000000000/* * ipmbserv.h * * IPMB server include file * * Copyright 2019 Mellanox * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __IPMBSERV_H #define __IPMBSERV_H #include #include typedef struct ipmbserv_data_s ipmbserv_data_t; struct ipmbserv_data_s { lan_addr_t addr; channel_t channel; os_handler_t *os_hnd; sys_data_t *sysinfo; void *user_info; int fd; void (*send_out)(ipmbserv_data_t *si, unsigned char *data, unsigned int data_len); char *ipmbdev; }; IPMI_LANSERV_DLL_PUBLIC int ipmbserv_read_config(char **tokptr, sys_data_t *sys, const char **errstr); IPMI_LANSERV_DLL_PUBLIC int ipmbserv_init(ipmbserv_data_t *ipmb); IPMI_LANSERV_DLL_PUBLIC void ipmbserv_handle_data(ipmbserv_data_t *ipmb, uint8_t *imsg, unsigned int len); #endif /* __IPMBSERV_H */ OpenIPMI-2.0.33/lanserv/OpenIPMI/serserv.h0000664000175000017500000001001514002617260014771 00000000000000/* * serserv.h * * MontaVista IPMI serial server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __SERSERV_H #define __SERSERV_H #include #include typedef struct serserv_data_s serserv_data_t; typedef struct ser_codec_s { const char *name; void (*handle_char)(unsigned char ch, serserv_data_t *si); void (*send)(msg_t *msg, serserv_data_t *si); int (*setup)(serserv_data_t *si); void (*connected)(serserv_data_t *si); void (*disconnected)(serserv_data_t *si); } ser_codec_t; typedef struct ser_oem_handler_s { const char *name; int (*handler)(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); void (*init)(serserv_data_t *si); } ser_oem_handler_t; struct serserv_data_s { lan_addr_t addr; channel_t channel; os_handler_t *os_hnd; sys_data_t *sysinfo; void *user_info; int bind_fd; int con_fd; int connected; void (*send_out)(serserv_data_t *si, unsigned char *data, unsigned int data_len); ser_codec_t *codec; void *codec_info; ser_oem_handler_t *oem; void *oem_info; /* Settings */ int debug; unsigned int do_connect : 1; unsigned int echo : 1; unsigned int do_attn : 1; unsigned char my_ipmb; unsigned char global_enables; unsigned char attn_chars[8]; unsigned int attn_chars_len; }; IPMI_LANSERV_DLL_PUBLIC int serserv_read_config(char **tokptr, sys_data_t *sys, const char **errstr); IPMI_LANSERV_DLL_PUBLIC int serserv_init(serserv_data_t *ser); IPMI_LANSERV_DLL_PUBLIC void serserv_handle_data(serserv_data_t *ser, uint8_t *data, unsigned int len); #endif /* __SERSERV_H */ OpenIPMI-2.0.33/lanserv/OpenIPMI/extcmd.h0000664000175000017500000000730714002617260014576 00000000000000/* * extcmd.h * * MontaVista IPMI IPMI LAN interface extern command handler * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef _EXTCMD_H_ #define _EXTCMD_H_ #include #include enum extcmd_info_type_e { extcmd_ip, extcmd_mac, extcmd_uchar, extcmd_int, extcmd_ident, }; typedef struct extcmd_map_s { int value; char *name; } extcmd_map_t; #define extcmdglue(a, b) a ## b #define EXTCMD_MEMB(name, type) \ [extcmdglue(name, _o)] = { #name, type, NULL, offsetof(BASETYPE, name) } #define EXTCMD_MEMB_MAPUCHAR(name, map) \ [extcmdglue(name, _o)] = { #name, extcmd_uchar, map, \ offsetof(BASETYPE, name) } typedef struct extcmd_info_s { const char *name; enum extcmd_info_type_e type; extcmd_map_t *map; size_t offset; } extcmd_info_t; IPMI_LANSERV_DLL_PUBLIC int extcmd_getvals(sys_data_t *sys, void *baseloc, const char *cmd, extcmd_info_t *ts, unsigned int count); IPMI_LANSERV_DLL_PUBLIC int extcmd_setvals(sys_data_t *sys, void *baseloc, const char *cmd, extcmd_info_t *ts, unsigned char *setit, unsigned int count); IPMI_LANSERV_DLL_PUBLIC int extcmd_checkvals(sys_data_t *sys, void *baseloc, const char *cmd, extcmd_info_t *ts, unsigned int count); int ipmi_cmd_permitted(unsigned char priv, unsigned char netfn, unsigned char cmd); #endif /* _EXTCMD_H_ */ OpenIPMI-2.0.33/lanserv/OpenIPMI/Makefile.in0000664000175000017500000004474414261607634015227 00000000000000# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = lanserv/OpenIPMI ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/ax_config_feature.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_pkg_swig.m4 \ $(top_srcdir)/m4/ax_prog_python_version.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgincludedir)" HEADERS = $(pkginclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BIBTEX = @BIBTEX@ BUILD_CC = @BUILD_CC@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DIA = @DIA@ DIA_FILTER_NAME = @DIA_FILTER_NAME@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPDF = @DVIPDF@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GDBM_LIB = @GDBM_LIB@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_DIR = @GLIB_DIR@ GLIB_LIB = @GLIB_LIB@ GLIB_LIBS = @GLIB_LIBS@ GLIB_PKGCONF = @GLIB_PKGCONF@ GLIB_SO = @GLIB_SO@ GLIB_TARGET = @GLIB_TARGET@ GLIB_VERSION = @GLIB_VERSION@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MARVELL_BMC_DIR = @MARVELL_BMC_DIR@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENIPMI_SWIG_LIBS = @OPENIPMI_SWIG_LIBS@ OPENIPMI_SWIG_SO = @OPENIPMI_SWIG_SO@ OPENIPMI_VERSION_EXTRA = @OPENIPMI_VERSION_EXTRA@ OPENIPMI_VERSION_MAJOR = @OPENIPMI_VERSION_MAJOR@ OPENIPMI_VERSION_MINOR = @OPENIPMI_VERSION_MINOR@ OPENIPMI_VERSION_RELEASE = @OPENIPMI_VERSION_RELEASE@ OPENSSLINCS = @OPENSSLINCS@ OPENSSLLIBS = @OPENSSLLIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL_CFLAGS = @PERL_CFLAGS@ PERL_DIR = @PERL_DIR@ PERL_HAS_POSIX_THREADS = @PERL_HAS_POSIX_THREADS@ PERL_INSTALL_DIR = @PERL_INSTALL_DIR@ PERL_POSIX_LIB = @PERL_POSIX_LIB@ PERL_POSIX_SO = @PERL_POSIX_SO@ POPTLIBS = @POPTLIBS@ PYTHON = @PYTHON@ PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ PYTHON_DIR = @PYTHON_DIR@ PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ PYTHON_GUI_DIR = @PYTHON_GUI_DIR@ PYTHON_HAS_POSIX_THREADS = @PYTHON_HAS_POSIX_THREADS@ PYTHON_INSTALL_DIR = @PYTHON_INSTALL_DIR@ PYTHON_INSTALL_LIB_DIR = @PYTHON_INSTALL_LIB_DIR@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_PLATFORM_SITE_PKG = @PYTHON_PLATFORM_SITE_PKG@ PYTHON_POSIX_LIB = @PYTHON_POSIX_LIB@ PYTHON_POSIX_SO = @PYTHON_POSIX_SO@ PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ PYTHON_SWIG_FLAGS = @PYTHON_SWIG_FLAGS@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_LIBS = @READLINE_LIBS@ RT_LIB = @RT_LIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMPLIBS = @SNMPLIBS@ SOCKETLIB = @SOCKETLIB@ STRIP = @STRIP@ SWIG = @SWIG@ SWIG_DIR = @SWIG_DIR@ SWIG_LIB = @SWIG_LIB@ TCL_CFLAGS = @TCL_CFLAGS@ TCL_DIR = @TCL_DIR@ TCL_LIB = @TCL_LIB@ TCL_LIBS = @TCL_LIBS@ TCL_PKGCONF = @TCL_PKGCONF@ TCL_SO = @TCL_SO@ TCL_TARGET = @TCL_TARGET@ TERM_LIBS = @TERM_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ diaprog = @diaprog@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ perlprog = @perlprog@ pkgprog = @pkgprog@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkginclude_HEADERS = lanserv.h serserv.h serv.h extcmd.h persist.h msg.h \ mcserv.h ipmbserv.h lanserv_dllvisibility.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lanserv/OpenIPMI/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lanserv/OpenIPMI/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkgincludeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-pkgincludeHEADERS install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am \ uninstall-pkgincludeHEADERS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: OpenIPMI-2.0.33/lanserv/OpenIPMI/Makefile.am0000664000175000017500000000017114002617260015165 00000000000000 pkginclude_HEADERS = lanserv.h serserv.h serv.h extcmd.h persist.h msg.h \ mcserv.h ipmbserv.h lanserv_dllvisibility.h OpenIPMI-2.0.33/lanserv/OpenIPMI/lanserv.h0000664000175000017500000005732714002617260014773 00000000000000/* * lanserv.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __LANSERV_H #define __LANSERV_H #include #include #include #include /* for iovec */ #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Restrictions: <=64 sessions */ #define SESSION_BITS_REQ 6 /* Bits required to hold a session. */ #define SESSION_MASK 0x3f typedef struct lmc_data_s lmc_data_t; typedef struct ipmi_sol_s ipmi_sol_t; typedef struct session_s session_t; typedef struct lanserv_data_s lanserv_data_t; typedef struct integ_handlers_s { int (*init)(lanserv_data_t *lan, session_t *session); void (*cleanup)(lanserv_data_t *lan, session_t *session); int (*add)(lanserv_data_t *lan, session_t *session, unsigned char *pos, unsigned int *data_len, unsigned int data_size); int (*check)(lanserv_data_t *lan, session_t *session, msg_t *msg); } integ_handlers_t; typedef struct conf_handlers_s { int (*init)(lanserv_data_t *lan, session_t *session); void (*cleanup)(lanserv_data_t *lan, session_t *session); int (*encrypt)(lanserv_data_t *lan, session_t *session, unsigned char **pos, unsigned int *hdr_left, unsigned int *data_len, unsigned int *data_size); int (*decrypt)(lanserv_data_t *lan, session_t *session, msg_t *msg); } conf_handlers_t; typedef struct auth_handlers_s { int (*init)(lanserv_data_t *lan, session_t *session); int (*set2)(lanserv_data_t *lan, session_t *session, unsigned char *data, unsigned int *data_len, unsigned int max_len); int (*check3)(lanserv_data_t *lan, session_t *session, unsigned char *data, unsigned int *data_len); int (*set4)(lanserv_data_t *lan, session_t *session, unsigned char *data, unsigned int *data_len, unsigned int max_len); } auth_handlers_t; typedef struct auth_data_s { unsigned char rand[16]; unsigned char rem_rand[16]; unsigned char role; unsigned char username_len; unsigned char username[16]; unsigned char sik[20]; unsigned char k1[20]; unsigned char k2[20]; unsigned int akey_len; unsigned int integ_len; void *adata; const void *akey; unsigned int ikey_len; void *idata; const void *ikey; const void *ikey2; unsigned int ckey_len; void *cdata; const void *ckey; } auth_data_t; #define LANSERV_NUM_CLOSERS 3 struct session_s { unsigned int active : 1; unsigned int in_startup : 1; unsigned int rmcpplus : 1; int handle; /* My index in the table. */ uint32_t recv_seq; uint32_t xmit_seq; uint32_t sid; unsigned char userid; /* RMCP data */ unsigned char authtype; ipmi_authdata_t authdata; /* RMCP+ data */ uint32_t unauth_recv_seq; uint32_t unauth_xmit_seq; uint32_t rem_sid; unsigned int auth; unsigned int conf; unsigned int integ; integ_handlers_t *integh; conf_handlers_t *confh; auth_handlers_t *authh; auth_data_t auth_data; unsigned char priv; unsigned char max_priv; /* The number of seconds left before the session is shut down. */ unsigned int time_left; /* Address of the message that started the sessions. */ void *src_addr; int src_len; struct { /* Function to call when the session closes */ void (*close_cb)(lmc_data_t *mc, uint32_t session_id, void *cb_data); void *close_cb_data; /* The MC associated with the RMCP session activation, used for SOL. */ lmc_data_t *mc; } closers[3]; }; typedef struct lanparm_data_s lanparm_data_t; struct lanparm_data_s { unsigned int set_in_progress : 2; unsigned int num_destinations : 4; /* Read-only */ unsigned char ip_addr_src; unsigned char ip_addr[4]; unsigned char mac_addr[6]; unsigned char subnet_mask[4]; unsigned char default_gw_ip_addr[4]; unsigned char default_gw_mac_addr[6]; unsigned char backup_gw_ip_addr[4]; unsigned char backup_gw_mac_addr[6]; /* FIXME - we don't handle these now. */ unsigned char ipv4_hdr_parms[3]; unsigned char vlan_id[2]; unsigned char vlan_priority; unsigned int num_cipher_suites : 4; unsigned char cipher_suite_entry[17]; unsigned char max_priv_for_cipher_suite[9]; }; enum lanread_e { ip_addr_o, ip_addr_src_o, mac_addr_o, subnet_mask_o, default_gw_ip_addr_o, default_gw_mac_addr_o, backup_gw_ip_addr_o, backup_gw_mac_addr_o, lanread_len }; typedef struct ipmi_tick_handler_s { void (*handler)(void *info, unsigned int seconds); void *info; struct ipmi_tick_handler_s *next; } ipmi_tick_handler_t; typedef struct oem_handlers_s { void *oem_data; void *user_data; /* IPMB address changed. Can be called by OEM code if it detects an IPMB address change. It should be ignored if NULL. */ void (*ipmb_addr_change)(channel_t *chan, unsigned char addr); /* Do OEM message handling; this is called after the message is authenticated. Should return 0 if the standard handling should continue, or non-zero if the message should not go through normal handling. This field may be NULL, and it will be ignored. */ int (*oem_handle_msg)(channel_t *chan, msg_t *msg); /* Called before a response is sent. Should return 0 if the standard handling should continue, or non-zero if the OEM handled the response itself. */ int (*oem_handle_rsp)(channel_t *chan, msg_t *msg, rsp_msg_t *rsp); /* Check the privilege of a command to see if it is permitted. */ int (*oem_check_permitted)(unsigned char priv, unsigned char netfn, unsigned char cmd); } oem_handlers_t; #define IPMI_MAX_CHANNELS 16 #define NUM_PRIV_LEVEL 4 struct channel_s { lmc_data_t *mc; unsigned char medium_type; unsigned char protocol_type; unsigned char session_support; unsigned int PEF_alerting : 1; unsigned int PEF_alerting_nonv : 1; unsigned int per_msg_auth : 1; /* We don't support user-level authentication disable, and access mode is always available and cannot be set. */ unsigned int privilege_limit : 4; unsigned int privilege_limit_nonv : 4; #define MAX_SESSIONS 63 unsigned int active_sessions : 6; struct { unsigned char allowed_auths; } priv_info[NUM_PRIV_LEVEL]; /* Information about the MC we are hooked to. */ unsigned int manufacturer_id; unsigned int product_id; unsigned int channel_num; int has_recv_q; msg_t *recv_q_head; msg_t *recv_q_tail; /* Used by channel code. */ void (*log)(channel_t *chan, int logtype, msg_t *msg, const char *format, ...) __attribute__ ((__format__ (__printf__, 4, 5))); int (*smi_send)(channel_t *chan, msg_t *msg); void *(*alloc)(channel_t *chan, int size); void (*free)(channel_t *chan, void *data); /* Set by channel code */ void (*return_rsp)(channel_t *chan, msg_t *msg, rsp_msg_t *rsp); /* Available for the specific channel code. */ void *chan_info; /* Set or clear the attn flag. If irq is set, set/clear the irq. */ void (*set_atn)(channel_t *chan, int val, int irq); /* Something is about to be added to the receive queue. If this returns true, then this function consumed the message and it shouldn't be queued. */ int (*recv_in_q)(channel_t *chan, msg_t *msg); void (*start_cmd)(channel_t *chan); void (*stop_cmd)(channel_t *chan, int do_it_now); /* Perform some hardware operations. */ #define HW_OP_RESET 0 #define HW_OP_POWERON 1 #define HW_OP_POWEROFF 2 #define HW_OP_SEND_NMI 3 #define HW_OP_IRQ_ENABLE 4 #define HW_OP_IRQ_DISABLE 5 #define HW_OP_GRACEFUL_SHUTDOWN 6 #define HW_OP_CHECK_POWER 7 unsigned int hw_capabilities; /* Bitmask of above bits for capabilities. */ #define HW_OP_CAN_RESET(chan) ((chan)->hw_capabilities & (1 << HW_OP_RESET)) #define HW_OP_CAN_POWER(chan) ((chan)->hw_capabilities & (1 << HW_OP_POWERON)) #define HW_OP_CAN_NMI(chan) ((chan)->hw_capabilities & (1 << HW_OP_SEND_NMI)) #define HW_OP_CAN_IRQ(chan) ((chan)->hw_capabilities & (1 << HW_OP_IRQ_ENABLE)) #define HW_OP_CAN_GRACEFUL_SHUTDOWN(chan) ((chan)->hw_capabilities & \ (1 << HW_OP_GRACEFUL_SHUTDOWN)) int (*hw_op)(channel_t *chan, unsigned int op); /* Special command handlers. */ void (*set_lan_parms)(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); void (*get_lan_parms)(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); void (*set_chan_access)(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); int (*set_associated_mc)(channel_t *chan, uint32_t session_id, unsigned int payload, lmc_data_t *mc, uint16_t *port, void (*close)(lmc_data_t *mc, uint32_t session_id, void *cb_data), void *cb_data); lmc_data_t *(*get_associated_mc)(channel_t *chan, uint32_t session_id, unsigned int payload); oem_handlers_t oem; /* * Set by the low-level interface code if it needs to handle * received messages specially. */ int (*oem_intf_recv_handler)(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); /* Set to 1 if ipmb channel 0 is listed in the config file, 0 otherwise */ int prim_ipmb_in_cfg_file; }; typedef struct sockaddr_ip_s { union { struct sockaddr s_addr0; struct sockaddr_in s_addr4; #ifdef PF_INET6 struct sockaddr_in6 s_addr6; #endif } s_ipsock; /* socklen_t addr_len;*/ } sockaddr_ip_t; typedef struct lan_addr_s { sockaddr_ip_t addr; socklen_t addr_len; } lan_addr_t; struct lanserv_data_s { sys_data_t *sysinfo; ipmi_tick_handler_t tick_handler; unsigned char *guid; channel_t channel; /* user 0 is not used. */ user_t *users; pef_data_t *pef; /* The amount of time in seconds before a session will be shut down if there is no activity. */ unsigned int default_session_timeout; unsigned char *bmc_key; void *user_info; /* Set by the user code, used to actually send a raw message out the UDP socket */ void (*send_out)(lanserv_data_t *lan, struct iovec *data, int vecs, void *addr, int addr_len); /* Generate 'size' bytes of random data into 'data'. */ int (*gen_rand)(lanserv_data_t *lan, void *data, int size); /* Don't fill in the below in the user code. */ /* session 0 is not used. */ session_t sessions[MAX_SESSIONS+1]; /* Used to make the sid somewhat unique. */ uint32_t sid_seq; ipmi_authdata_t challenge_auth; unsigned int next_challenge_seq; lanparm_data_t lanparm; unsigned char lanparm_changed[lanread_len]; unsigned int persist_changed; lanparm_data_t lanparm_rollback; /* Used to access and set the external LAN config items. */ char *config_prog; lan_addr_t lan_addr; int lan_addr_set; uint16_t port; }; IPMI_LANSERV_DLL_PUBLIC void handle_asf(lanserv_data_t *lan, unsigned char *data, int len, void *from_addr, int from_len); IPMI_LANSERV_DLL_PUBLIC void ipmi_handle_lan_msg(lanserv_data_t *lan, unsigned char *data, int len, void *from_addr, int from_len); /* Read in a configuration file and fill in the lan and address info. */ IPMI_LANSERV_DLL_PUBLIC int lanserv_read_config(sys_data_t *sys, FILE *f, int *line, unsigned int channel_num); IPMI_LANSERV_DLL_PUBLIC int ipmi_lan_init(lanserv_data_t *lan); typedef void (*ipmi_payload_handler_cb)(lanserv_data_t *lan, msg_t *msg); IPMI_LANSERV_DLL_PUBLIC int ipmi_register_payload(unsigned int payload_id, ipmi_payload_handler_cb handler); #ifndef __GNUC__ # ifndef __attribute__ # define __attribute__(x) /*NOTHING*/ # endif #endif typedef void (*handle_oem_cb)(channel_t *chan, void *cb_data); typedef struct oem_handler_s { unsigned int manufacturer_id; unsigned int product_id; handle_oem_cb handler; void *cb_data; struct oem_handler_s *next; } oem_handler_t; /* Register a new OEM handler. */ IPMI_LANSERV_DLL_PUBLIC void ipmi_register_oem(oem_handler_t *handler); struct user_s { unsigned char valid; unsigned char link_auth; unsigned char cb_only; unsigned char username[16]; unsigned char pw[20]; unsigned char privilege; unsigned char max_sessions; unsigned char curr_sessions; /* Set by the user code. */ int idx; /* My idx in the table. */ }; /* * Restrictions: <=64 users (per spec, 6 bits) */ #define MAX_USERS 63 #define USER_BITS_REQ 6 /* Bits required to hold a user. */ #define USER_MASK 0x3f #define MAX_EVENT_FILTERS 16 #define MAX_ALERT_POLICIES 16 #define MAX_ALERT_STRINGS 16 #define MAX_ALERT_STRING_LEN 64 struct pef_data_s { unsigned int set_in_progress : 2; void (*commit)(sys_data_t *sys); /* Called when the commit occurs. */ unsigned char pef_control; unsigned char pef_action_global_control; unsigned char pef_startup_delay; unsigned char pef_alert_startup_delay; unsigned char num_event_filters; unsigned char event_filter_table[MAX_EVENT_FILTERS][21]; unsigned char event_filter_data1[MAX_EVENT_FILTERS][2]; unsigned char num_alert_policies; unsigned char alert_policy_table[MAX_ALERT_POLICIES][4]; unsigned char system_guid[17]; unsigned char num_alert_strings; unsigned char alert_string_keys[MAX_ALERT_STRINGS][3]; unsigned char alert_strings[MAX_ALERT_STRINGS][MAX_ALERT_STRING_LEN]; /* Tells what has changed, so the commit can do something about it. */ struct { unsigned int pef_control : 1; unsigned int pef_action_global_control : 1; unsigned int pef_startup_delay : 1; unsigned int pef_alert_startup_delay : 1; unsigned int system_guid : 1; unsigned char event_filter_table[MAX_EVENT_FILTERS]; unsigned char event_filter_data1[MAX_EVENT_FILTERS]; unsigned char alert_policy_table[MAX_ALERT_POLICIES]; unsigned int alert_string_keys[MAX_ALERT_STRINGS]; unsigned int alert_strings[MAX_ALERT_STRINGS]; } changed; }; typedef struct ipmi_timer_s ipmi_timer_t; typedef struct ipmi_io_s ipmi_io_t; struct startcmd_s { /* Command to start a VM */ char *startcmd; unsigned int startnow; /* Start startcmd at simulator startup? */ unsigned int poweroff_wait_time; unsigned int kill_wait_time; int vmpid; /* Process id of the VM, 0 if not running. */ int wait_poweroff; }; /* * Note that we keep odd addresses, too. In some cases that's useful * in virtual systems that don't have I2C restrictions. */ #define IPMI_MAX_MCS 256 /* * Generic data about the system that is global for the whole system and * required for all server types. */ struct sys_data_s { char *name; /* The MCs in the system */ lmc_data_t *ipmb_addrs[IPMI_MAX_MCS]; #define DEBUG_RAW_MSG (1 << 0) #define DEBUG_MSG (1 << 1) #define DEBUG_SOL (1 << 2) unsigned int debug; #define NEW_SESSION 1 #define NEW_SESSION_FAILED 2 #define SESSION_CLOSED 3 #define SESSION_CHALLENGE 4 #define SESSION_CHALLENGE_FAILED 5 #define AUTH_FAILED 6 #define INVALID_MSG 7 #define OS_ERROR 8 #define LAN_ERR 9 #define INFO 10 #define DEBUG 11 #define SETUP_ERROR 12 void (*log)(sys_data_t *sys, int type, msg_t *msg, const char *format, ...) __attribute__ ((__format__ (__printf__, 4, 5))); /* Console port. Length is zero if not set. */ sockaddr_ip_t console_addr; socklen_t console_addr_len; int console_fd; unsigned char bmc_ipmb; int sol_present; void *info; /* * When reading in config, this tracks which information we are * working on. This is initialized to the MC at 0x20, setting * the working MC changes these to the new MC. */ channel_t **chan_set; startcmd_t *startcmd; user_t *cusers; pef_data_t *cpef; ipmi_sol_t *sol; lmc_data_t *mc; void *(*alloc)(sys_data_t *sys, int size); void (*free)(sys_data_t *sys, void *data); int (*get_monotonic_time)(sys_data_t *sys, struct timeval *tv); int (*get_real_time)(sys_data_t *sys, struct timeval *tv); int (*alloc_timer)(sys_data_t *sys, void (*cb)(void *cb_data), void *cb_data, ipmi_timer_t **timer); int (*start_timer)(ipmi_timer_t *timer, struct timeval *timeout); int (*stop_timer)(ipmi_timer_t *timer); void (*free_timer)(ipmi_timer_t *timer); int (*add_io_hnd)(sys_data_t *sys, int fd, void (*read_hnd)(int fd, void *cb_data), void *cb_data, ipmi_io_t **io); void (*remove_io_hnd)(ipmi_io_t *io); void (*io_set_hnds)(ipmi_io_t *io, void (*write_hnd)(int fd, void *cb_data), void (*except_hnd)(int fd, void *cb_data)); void (*io_set_enables)(ipmi_io_t *io, int read, int write, int except); int (*gen_rand)(sys_data_t *sys, void *data, int len); /* Called by interface code to report that the target did a reset. */ /* FIXME - move */ void (*target_reset)(sys_data_t *sys); /* * These are a hack so the channel code in the MCs can pick up * these functions. */ void (*clog)(channel_t *chan, int logtype, msg_t *msg, const char *format, ...); int (*csmi_send)(channel_t *chan, msg_t *msg); void *(*calloc)(channel_t *chan, int size); void (*cfree)(channel_t *chan, void *data); int (*lan_channel_init)(void *info, channel_t *chan); int (*ser_channel_init)(void *info, channel_t *chan); int (*ipmb_channel_init)(void *info, channel_t *chan); /* * Various MC related info that must be provided. */ int (*mc_alloc_unconfigured)(sys_data_t *sys, unsigned char ipmb, lmc_data_t **rmc); void (*resend_atn)(channel_t *chan); unsigned char (*mc_get_ipmb)(lmc_data_t *mc); channel_t **(*mc_get_channelset)(lmc_data_t *mc); ipmi_sol_t *(*mc_get_sol)(lmc_data_t *mc); startcmd_t *(*mc_get_startcmdinfo)(lmc_data_t *mc); user_t *(*mc_get_users)(lmc_data_t *mc); int (*mc_users_changed)(lmc_data_t *mc); pef_data_t *(*mc_get_pef)(lmc_data_t *mc); msg_t *(*mc_get_next_recv_q)(channel_t *chan); int (*sol_read_config)(char **tokptr, sys_data_t *sys, const char **err); void (*set_chassis_control_prog)(lmc_data_t *mc, const char *prog); void (*register_tick_handler)(ipmi_tick_handler_t *handler); }; static inline void zero_extend_ascii(uint8_t *c, unsigned int len) { unsigned int i; i = 0; while ((i < len) && (*c != 0)) { c++; i++; } while (i < len) { *c = 0; c++; i++; } } /* A helper function to allow OEM code to send messages. */ IPMI_LANSERV_DLL_PUBLIC int ipmi_oem_send_msg(channel_t *chan, unsigned char netfn, unsigned char cmd, unsigned char *data, unsigned int len, long oem_data); IPMI_LANSERV_DLL_PUBLIC void ipmi_handle_smi_rsp(channel_t *chan, msg_t *msg, unsigned char *rsp, int rsp_len); IPMI_LANSERV_DLL_PUBLIC int channel_smi_send(channel_t *chan, msg_t *msg); IPMI_LANSERV_DLL_PUBLIC int chan_init(channel_t *chan); IPMI_LANSERV_DLL_PUBLIC void sysinfo_init(sys_data_t *sys); #define MAX_CONFIG_LINE 1024 IPMI_LANSERV_DLL_PUBLIC const char *mystrtok(char *str, const char *delim, char **next); /* * Note that "value" must be dynamically allocated. "name" does not have * to be. */ IPMI_LANSERV_DLL_PUBLIC int add_variable(const char *name, char *value); IPMI_LANSERV_DLL_PUBLIC int get_delim_str(char **rtokptr, char **rval, const char **err); IPMI_LANSERV_DLL_PUBLIC int get_bool(char **tokptr, unsigned int *rval, const char **err); IPMI_LANSERV_DLL_PUBLIC int get_uint(char **tokptr, unsigned int *rval, const char **err); IPMI_LANSERV_DLL_PUBLIC int get_int(char **tokptr, int *rval, const char **err); IPMI_LANSERV_DLL_PUBLIC int get_priv(char **tokptr, unsigned int *rval, const char **err); IPMI_LANSERV_DLL_PUBLIC int get_auths(char **tokptr, unsigned int *rval, const char **err); IPMI_LANSERV_DLL_PUBLIC int read_bytes(char **tokptr, unsigned char *data, const char **err, unsigned int len); IPMI_LANSERV_DLL_PUBLIC int get_sock_addr(char **tokptr, sockaddr_ip_t *addr, socklen_t *len, char *def_port, int socktype, const char **err); IPMI_LANSERV_DLL_PUBLIC int read_config(sys_data_t *sys, char *config_file, int print_version); IPMI_LANSERV_DLL_PUBLIC int load_dynamic_libs(sys_data_t *sys, int print_version); IPMI_LANSERV_DLL_PUBLIC void post_init_dynamic_libs(sys_data_t *sys); IPMI_LANSERV_DLL_PUBLIC void debug_log_raw_msg(sys_data_t *sys, unsigned char *data, unsigned int len, const char *format, ...); IPMI_LANSERV_DLL_PUBLIC unsigned int ipmi_get_uint16(uint8_t *data); IPMI_LANSERV_DLL_PUBLIC void ipmi_set_uint16(uint8_t *data, int val); IPMI_LANSERV_DLL_PUBLIC unsigned int ipmi_get_uint32(uint8_t *data); IPMI_LANSERV_DLL_PUBLIC void ipmi_set_uint32(uint8_t *data, int val); IPMI_LANSERV_DLL_PUBLIC uint8_t ipmb_checksum(uint8_t *data, int size, uint8_t start); /* * Command handler interface. */ typedef struct emu_data_s emu_data_t; typedef struct emu_out_s { void (*eprintf)(struct emu_out_s *out, char *format, ...); void *data; } emu_out_t; IPMI_LANSERV_DLL_PUBLIC void read_persist_users(sys_data_t *sys); IPMI_LANSERV_DLL_PUBLIC int write_persist_users(sys_data_t *sys); #ifdef __cplusplus } #endif #endif /* __LANSERV_H */ OpenIPMI-2.0.33/lanserv/OpenIPMI/mcserv.h0000664000175000017500000001663314002617260014613 00000000000000/* * mcserv.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __MCSERV_H #define __MCSERV_H #include typedef struct sensor_s sensor_t; #define MC 1 #define NOMC 0 typedef int (*ipmi_emu_cmd_handler)(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks); int ipmi_emu_add_cmd(const char *name, unsigned int flags, ipmi_emu_cmd_handler handler); #define CHASSIS_CONTROL_POWER 0 #define CHASSIS_CONTROL_RESET 1 #define CHASSIS_CONTROL_BOOT 2 #define CHASSIS_CONTROL_BOOT_INFO_ACK 3 #define CHASSIS_CONTROL_GRACEFUL_SHUTDOWN 4 #define CHASSIS_CONTROL_IDENTIFY 5 void ipmi_mc_set_chassis_control_func(lmc_data_t *mc, int (*set)(lmc_data_t *mc, int op, unsigned char *val, void *cb_data), int (*get)(lmc_data_t *mc, int op, unsigned char *val, void *cb_data), void *cb_data); /* * FRUs have a semaphore that can be use to grant exclusive access. * The semaphore is attempted to get before read and write operations, * if it fails then an error is returned. If something else reads or * writes the FRU, then it should claim the semaphore before posting. */ int ipmi_mc_fru_sem_wait(lmc_data_t *mc, unsigned char device_id); int ipmi_mc_fru_sem_trywait(lmc_data_t *mc, unsigned char device_id); int ipmi_mc_fru_sem_post(lmc_data_t *mc, unsigned char device_id); int ipmi_mc_sensor_set_enabled(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char enabled); int ipmi_mc_sensor_set_bit(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char bit, unsigned char value, int gen_event); int ipmi_mc_sensor_set_bit_clr_rest(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char bit, int gen_event); int ipmi_mc_sensor_set_value(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char value, int gen_event); int ipmi_mc_sensor_set_hysteresis(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char support, unsigned char positive, unsigned char negative); int ipmi_mc_sensor_set_threshold(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char support, uint16_t supported, int set_values, unsigned char values[6]); int ipmi_mc_sensor_add_rearm_handler(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, int (*handler)(void *cb_data, uint16_t assert, uint16_t deassert), void *cb_data); int ipmi_mc_sensor_set_event_support(lmc_data_t *mc, unsigned char lun, unsigned char sens_num, unsigned char init_events, unsigned char events_enable, unsigned char init_scanning, unsigned char scanning_enable, unsigned char support, uint16_t assert_supported, uint16_t deassert_supported, uint16_t assert_enabled, uint16_t deassert_enabled); /* * Message handling. */ void handle_invalid_cmd(lmc_data_t *mc, unsigned char *rdata, unsigned int *rdata_len); int check_msg_length(msg_t *msg, unsigned int len, unsigned char *rdata, unsigned int *rdata_len); void ipmi_mc_set_dev_revision(lmc_data_t *mc, unsigned char dev_revision); void ipmi_mc_set_fw_revision(lmc_data_t *mc, unsigned char fw_revision_major, unsigned char fw_revision_minor); void ipmi_mc_set_aux_fw_revision(lmc_data_t *mc, unsigned char aux_fw_revision[4]); const char *get_lanserv_version(void); /* * Types and functions for registering handlers with the MC emulator. */ typedef void (*cmd_handler_f)(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data); int ipmi_emu_register_cmd_handler(unsigned char netfn, unsigned char cmd, cmd_handler_f handler, void *cb_data); /* * Note that for IANA command handlers the IANA is stripped (and put into * msg->iana) before being passed to the handler, and inserted into the * response message automatically. So the handler should handle this * like a normal message, setting the data and length as if the IANA was * not there. This way standard handling functions will work properly, * and it simplifies the handling of IANA messages. */ int ipmi_emu_register_iana_handler(uint32_t iana, cmd_handler_f handler, void *cb_data); int ipmi_emu_register_oi_iana_handler(uint8_t cmd, cmd_handler_f handler, void *cb_data); #define OPENIPMI_IANA_CMD_SET_HISTORY_RETURN_SIZE 1 #define OPENIPMI_IANA_CMD_GET_HISTORY_RETURN_SIZE 2 /* * Registration for group extensions */ void ipmi_emu_register_group_extension_handler(uint8_t group_extension, cmd_handler_f handler, void *cb_data); void mc_new_event(lmc_data_t *mc, unsigned char record_type, unsigned char event[13]); #endif /* __MCSERV_H */ OpenIPMI-2.0.33/lanserv/OpenIPMI/serv.h0000664000175000017500000000011214002617260014254 00000000000000/* This file is now pulled into lanserv. */ #include OpenIPMI-2.0.33/lanserv/OpenIPMI/msg.h0000644000175000017500000000763313364062612014105 00000000000000/* * serv.h * * MontaVista IPMI server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005,2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __MSG_H_ #define __MSG_H_ #include typedef struct channel_s channel_t; typedef struct msg_s { void *src_addr; int src_len; long oem_data; /* For use by OEM handlers. This will be set to zero by the calling code. */ unsigned char channel; /* The channel the message originally came in on. */ channel_t *orig_channel; unsigned char authtype; uint32_t seq; uint32_t sid; union { struct { /* RMCP parms */ unsigned char *authcode; unsigned char authcode_data[16]; } rmcp; struct { /* RMCP+ parms */ unsigned char payload; unsigned char encrypted; unsigned char authenticated; unsigned char iana[3]; uint16_t payload_id; unsigned char *authdata; unsigned int authdata_len; } rmcpp; }; unsigned char netfn; unsigned char rs_addr; unsigned char rs_lun; unsigned char rq_addr; unsigned char rq_lun; unsigned char rq_seq; unsigned char cmd; unsigned char *data; unsigned int len; uint32_t iana; /* Set for IANA commands */ struct msg_s *next; } msg_t; #define IPMI_SIM_MAX_MSG_LENGTH 255 typedef struct rsp_msg { uint8_t netfn; uint8_t cmd; unsigned short data_len; uint8_t *data; } rsp_msg_t; typedef struct sys_data_s sys_data_t; typedef struct startcmd_s startcmd_t; typedef struct user_s user_t; typedef struct pef_data_s pef_data_t; #endif /* __MSG_H_ */ OpenIPMI-2.0.33/lanserv/OpenIPMI/lanserv_dllvisibility.h0000664000175000017500000000656614002617260017735 00000000000000/* * lanserv.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __LANSERV_DLLVISIBILITY_H #define __LANSERV_DLLVISIBILITY_H #if defined _WIN32 || defined __CYGWIN__ #ifdef BUILDING_IPMI_LANSERV_DLL #ifdef __GNUC__ #define IPMI_LANSERV_DLL_PUBLIC __attribute__ ((dllexport)) #else #define IPMI_LANSERV_DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. #endif #else #ifdef __GNUC__ #define IPMI_LANSERV_DLL_PUBLIC __attribute__ ((dllimport)) #else #define IPMI_LANSERV_DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. #endif #endif #define IPMI_LANSERV_DLL_LOCAL #else #if __GNUC__ >= 4 #define IPMI_LANSERV_DLL_PUBLIC __attribute__ ((visibility ("default"))) #define IPMI_LANSERV_DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define IPMI_LANSERV_DLL_PUBLIC #define IPMI_LANSERV_DLL_LOCAL #endif #endif #endif /* __LANSERV_DLLVISIBILITY_H */ OpenIPMI-2.0.33/lanserv/README.design0000644000175000017500000001514013520705737013714 00000000000000This directory contains two programs: lanserv and ipmi_sim. These grew out of a need to be able to test OpenIPMI without having to have real hardware, but they have taken on more than that. lanserv is a program that provides a LAN connection for a BMC that does not otherwise have a LAN connection. It takes a standard Linux IPMI device and implements the IPMI LAN protocol. ipmi_sim is a full IPMI simulator and does not require a real BMC. It can be used to simulate an entire IPMI system, including satellite MCs. You can use it over a LAN connection, or it provides a serial interface so it can be used with QEMU or other VMs. The serial interface implements the serial protocols available on many ATCA blades, and it also emulates a protocol so it may be used for emulation of a standard IPMI interface (KCS, SMIC, BT, SSIF) including the handling of reset, power, and interrupts. Files ----- The include files are in the OpenIPMI directory: lanserv.h - The configuration of a LAN interface is defined in this file. mcserv.h - This defines the interface for an MC. msg.h - This defines an IPMI message that is passed around, and a few other global things that pretty much everything uses. This is separate from serv.h because of chicken and egg problems. serserv.h - The configuration of a serial interface. ipmbserv.h - The configuration of an IPMB interface. serv.h - This defines data structures used by the whole system. The code is in this directory: lanserv.c - The main file for the lanserv program. config.c - Reads a configuration file. This defines things that are common between lanserv and ipmi_sim, LAN configuration, serial port configuration, users, etc. lanserv_config.c - Specific code for reading in LAN configuration, used by config.c. priv_table.c - Holds the tables used map IPMI commands to their required privilege levels. bmc.c - The basic code dealing MC command routing and configuration. bmc.h - Internal include file for communication between the various bmc_xxx files. bmc_app.c - Handling for application commands (get device info, etc.) bmc_chassis.c - Handling for chassis-specific commands. bmc_picmg.c - Handling for PICMG (ATCA) specific commands. bmc_sensor.c - Handling for sensor specific commands. bmc_storage.c - Handling for FRU and SDR commands. bmc_transport.c - Handling for LAN control commands. config.c - Read the configuration file. emu_cmd.c - Implements a command language used for both configuration and control of the MCs in ipmi_sim. It is used by configuration files (see the .emu files) to define the system, and it can be used to generate real-time events by setting sensor values. emu.h - Defines the interface between bmc_xxx.c and emu_cmd.c extcmd.c - Code for running the external command for dealing with LAN configuration. ipmb_ipmi.c - An implementation of the IPMB protocol. ipmi_sim.c - The main file for the ipmi_sim program. lanserv_asf.c - Handles LAN ASF commands. lanserv_config.c- Handles reading LAN configuration, called from config.c lanserv_ipmi.c - An implementation of the IPMI LAN protocol. lanserv_oem_force.c - Some OEM handling for some older Force computer systems. persist.c - Handling for writing and reading persistent information for the MC. priv_table.c - Privilege lookups for commands, to know which privilege levels are required for each command. serial_ipmi.c - An implementation of the IPMI serial protocols, and also code to handle reading a serial configuration line. serv.c - General utilities used by a lot of the system. sol.c - An implementation of the serial over LAN protocol. And here's a few other miscellaneous things: ipmi_checksum.c - A program that takes a string of bytes and generates an IPMI checksum. Primarily used for testing. ipmisim1.emu - emu commands for creating a simple IPMI system. atca.emu - emu commands for creating a more complex ATCA system. lan.conf - A configuration file example. sdrcomp (directory) - A compiler for SDRs. marvell-bmc (directory) - Code for implementing a BMC for a Marvell server. General Design (for ipmi_sim) ----------------------------- The ipmi_sim.c file has all the startup code and handles all the I/O and timers for the simulator. It does all the system initialization, opens all the the necessary sockets, and handles the input and output for the sockets and the emu_cmd emulator. The rest of the simulator is completely event-driven and does no I/O on it's own. ipmi_sim uses the POSIX OS handler defined in the ../unix directory. When ipmi_sim.c starts up, it defines the sysinfo structure, which provides interfaces for doing timers, logging, LAN and serial initialization, and message output. It then reads the configuration file and the emu file. As part of reading the configuration file, LAN and serial interfaces are implemented. These result in callbacks into the ipmi_sim.c code to open the sockets. When a message comes in on the LAN interface, ipmi_sim will either call handle_asf() (in lanserv_asf.c) or ipmi_handle_lan_msg() (in lanserv_ipmi.c) depending on the message type. lanserv_ipmi.c will handle the IPMI LAN protocol part. It handles session establishment for both RMCP and RMCP+, it handles checking the privilege levels for command, and it handles all the LAN-specific IPMI commands. This code may send an immediate response to a message, or if a normal message comes in, it will send it to channel_smi_send() (in serv.c). channel_smi_send() will call the channel-specific handling callback, which will generall result it in going back to ipmi_sim.c's smi_send() function. smi_send() calls ipmi_emu_handle_msg() in bmc.c to handle the message ipmi_emu_handle_msg() will route the command to the proper function to handle it. It passes in a response message to the handler, which the handler must fill in. Then it will call ipmi_handle_smi_rsp() (in serv.c) to send the response. ipmi_handle_smi_rsp() does a little bit of formatting then calls the channel-specific return_rsp() function. In the LAN case, this results in lan_return_rsp() (in lanserv_ipmi.c) being called. lan_return_rsp() does the formatting and handling to transmit the message then calls the send_out function variable, resulting in lan_send() in ipmi_sim.c being called. That transmits the message. The serial case is similar, substituting the serial code for the LAN code. Serial Over LAN (SOL) --------------------- The sol.c code has three tie-ins to the rest of the code: It is called from config.c to handle sol-specific configuration. It installs a hook into lanserv_ipmi.c to receive the SOL payload and send the SOL payload. It ties into bmc.c to handle SOL-specific commands. OpenIPMI-2.0.33/lanserv/lan.conf0000644000175000017500000001467513520705737013221 00000000000000# lan.conf # A configuration file for lanserv or ipmi_sim to configure the various # communication parameters for the device. # This is a name used to identify this instance, and used to create # the default name of the emulator startup command file and eventually # the storage facility for permanent storage. name "ipmisim1" # # Work on the BMC first set_working_mc 0x20 # Define a LAN channel on channel 1 startlan 1 # Define an IP address and port to listen on. You can define more # than one address/port to listen on multiple addresses. The :: # listens on all addresses. addr localhost 9001 #addr 192.168.27.126 9000 #addr 192.168.27.200 9000 # Maximum privilege limit on the channel. priv_limit admin # Allowed IPMI 1.5 authorization types allowed_auths_callback none md2 md5 straight allowed_auths_user none md2 md5 straight allowed_auths_operator none md2 md5 straight allowed_auths_admin none md2 md5 straight # guid for IPMI 2.0 authorization You can also use a string guid a123456789abcdefa123456789abcdef #guid "I_AM_A_REAL_BMC!" # You can specify a BMC key for IPMI 2.0 authorization. See the # spec for details. #bmc_key "abcdefghijklmnopqrst" # A program to get and set the LAN configuration of the interface. #lan_config_program "/usr/local/bin/ipmi_sim_lancontrol eth0" lan_config_program "./ipmi_sim_lancontrol eth1" endlan #chassis_control "./ipmi_sim_chassiscontrol 0x20" # Define a serial VM inteface for channel 15 (the system interface) on # port 9002, just available to the local system (localhost). serial 15 localhost 9002 codec VM # startcmd is what to execute to start a VM associated with the # codec above (localhost 9002). It also starts a console serial port # on port 9003 that is also used as the monitor interface. startcmd "qemu-system-x86_64 --enable-kvm -drive file=/opt/qemu/cge-complete-image-x86-generic-64-1.ext2,format=raw -nographic -kernel /opt/qemu/bzImage-1 -append 'root=/dev/sdb console=ttyS0,115200' -net nic,model=e1000,macaddr=52:54:00:12:34:59 -net user,hostfwd=tcp::5556-10.0.2.15:22 -chardev socket,id=ipmi0,host=localhost,port=9002,reconnect=10 -device ipmi-bmc-extern,id=bmc0,chardev=ipmi0 -device isa-ipmi-bt,bmc=bmc0 -serial mon:telnet::9003,server,telnet,nowait" sol "telnet:localhost:9003" 115200 # Start startcmd at startup? Default is false. startnow false # The amount of time to wait for the startcmd to do a power off # on a powerdown request. The simulator will send a request to the # target, wait this amount of time, and then do a SIGTERM kill on the # process. If this is zero, a SIGTERM will not be done (nor will a SIGKILL). # Note that if the simulator does not have a connection to the VM, the # graceful shutdown is skipped and a SIGTERM is done immediately. # Default time is 60 seconds. #poweroff_wait 30 # The amount of time to wait for SIGTERM to kill the process. If the process # does not terminate in this period of time, send a SIGKILL kill. If this # is zero, don't send the SIGKILL. Default time is 20 seconds. #kill_wait 5 # Now add some users. User 0 is invalid, user 1 is the special "anonymous" # user and cannot take a username. Note that the users here are only # used if the persistent user config doesn't exist. # # valid name passw priv-lim max-sess allowed-auths (ignored) user 1 true "" "test" user 10 none md2 md5 straight user 2 true "ipmiusr" "test" admin 10 none md2 md5 straight # sol "/dev/ttyUSB0" 38400 history=4000 historyfru=10 # # Switch to a new MC # set_working_mc 0x30 # Add a SOL config, a device and a default baud rate. # "history" sets a history buffer size. This means that DCD and CTS will # always be enabled to the device, and we will constantly collect # history for the device. It will be available as SOL instance 2 # on the device. If the optional backupfile option is specified, # the history data is stored in the given file if the BMC shuts down # (or is killed by a catchable signal) and restored from that file if it # starts up. # If historyfru=N is specified, then FRU device N on the MC will be # able to fetch the contents of the history buffer, too, up to # 65535 bytes (the max size of FRU data). # Specifying nortscts disabled rtscts on the port. It will still change # the RTS output line, but it won't listen to CTS. # Normally the data is left in the history buffer when read. If # you want the history data to be cleared from the buffer on read # add readclear. #sol "/dev/ttyUSB0" 19200 nortscts readclear # sol "/dev/ttyUSB0" 38400 history=4000,backupfile=/var/ipmi_sim/solhist1 historyfru=10 # Define a serial VM inteface for channel 15 (the system interface) on # port 9003 for the MC at 0x30 serial 15 localhost 9012 codec VM startcmd "qemu-system-x86_64 --enable-kvm -drive file=/opt/qemu/cge-complete-image-x86-generic-64-2.ext2,format=raw -nographic -kernel /opt/qemu/bzImage-2 -append 'root=/dev/sdb console=ttyS0,115200' -net nic,model=e1000,macaddr=52:54:00:12:34:59 -net user,hostfwd=tcp::5557-10.0.2.15:22 -chardev socket,id=ipmi0,host=localhost,port=9012,reconnect=10 -device ipmi-bmc-extern,id=bmc0,chardev=ipmi0 -device isa-ipmi-kcs,bmc=bmc0,irq=5 -serial mon:tcp::9013,server,telnet,nowait" sol "telnet:localhost:9013" 115200 # Start startcmd at startup? Default is false. startnow false # Allow a console connection to perform emulation commands. #console localhost 9000 # Dynamically load a module to extend the simulator. After the module is # loaded, if the function "ipmi_sim_module_init" is defined in the module, # it will be called with the following parameters: # int ipmi_sim_module_init(sys_data_t *sys, char *initstr); # where initstr is the init string passed on the module load line. # It should return 0 on success or an errno no failure. #loadlib "/opt/lib/ipmi_sim_extend.so" "Initialization String" # "ipmb" should be added to the config file of a device # that needs to handle an IPMB request and generate a response # back to the requester. # In the case of an IPMB bridge request for example, the # BMC is considered the requester and the responder device # should have a config file defining the IPMB channel number. # For example: # ipmb # ipmb 2 ipmb_dev_int /dev/ipmb-2 # # At the moment, this OpenIPMI ipmb interface works with the # linux driver ipmb_dev_int.c. OpenIPMI-2.0.33/lanserv/serv.c0000664000175000017500000001773114002617260012706 00000000000000/* * lanserv_ipmi.c * * MontaVista IPMI IPMI LAN interface protocol engine * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005,2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include int ipmi_oem_send_msg(channel_t *chan, unsigned char netfn, unsigned char cmd, unsigned char *data, unsigned int len, long oem_data) { msg_t *nmsg; int rv; nmsg = chan->alloc(chan, sizeof(*nmsg)+len); if (!nmsg) { chan->log(chan, OS_ERROR, NULL, "SMI message: out of memory"); return ENOMEM; } memset(nmsg, 0, sizeof(*nmsg)); nmsg->oem_data = oem_data; nmsg->netfn = netfn; nmsg->cmd = cmd; nmsg->data = ((unsigned char *) nmsg) + sizeof(*nmsg); nmsg->len = len; if (len > 0) memcpy(nmsg->data, data, len); rv = chan->smi_send(chan, nmsg); if (rv) { chan->log(chan, OS_ERROR, nmsg, "SMI send: error %d", rv); chan->free(chan, nmsg); } return rv; } void ipmi_handle_smi_rsp(channel_t *chan, msg_t *msg, uint8_t *rspd, int rsp_len) { rsp_msg_t rsp; rsp.netfn = msg->netfn | 1; rsp.cmd = msg->cmd; rsp.data = rspd; rsp.data_len = rsp_len; if (chan->oem.oem_handle_rsp && chan->oem.oem_handle_rsp(chan, msg, &rsp)) /* OEM code handled the response. */ return; chan->return_rsp(chan, msg, &rsp); chan->free(chan, msg); } static oem_handler_t *oem_handlers = NULL; void ipmi_register_oem(oem_handler_t *handler) { handler->next = oem_handlers; oem_handlers = handler; } static void check_oem_handlers(channel_t *chan) { oem_handler_t *c; c = oem_handlers; while (c) { if ((c->manufacturer_id == chan->manufacturer_id) && (c->product_id == chan->product_id)) { c->handler(chan, c->cb_data); break; } c = c->next; } } int channel_smi_send(channel_t *chan, msg_t *msg) { int rv; msg_t *nmsg; msg->channel = chan->channel_num; nmsg = chan->alloc(chan, sizeof(*nmsg)+msg->src_len+msg->len); if (!nmsg) { chan->log(chan, OS_ERROR, msg, "SMI message: out of memory"); return ENOMEM; } memcpy(nmsg, msg, sizeof(*nmsg)); if (msg->src_addr) { nmsg->src_addr = ((char *) nmsg) + sizeof(*nmsg); memcpy(nmsg->src_addr, msg->src_addr, msg->src_len); } nmsg->data = ((uint8_t *) nmsg) + sizeof(*nmsg) + msg->src_len; memcpy(nmsg->data, msg->data, msg->len); /* Let the low-level interface intercept. */ if (chan->oem_intf_recv_handler) { unsigned char msgd[36]; unsigned int msgd_len = sizeof(msgd); if (chan->oem_intf_recv_handler(chan, nmsg, msgd, &msgd_len)) { ipmi_handle_smi_rsp(chan, nmsg, msgd, msgd_len); return 0; } } rv = chan->smi_send(chan, nmsg); if (rv) chan->free(chan, nmsg); return rv; } static int look_for_get_devid(channel_t *chan, msg_t *msg, rsp_msg_t *rsp) { if ((rsp->netfn == (IPMI_APP_NETFN | 1)) && (rsp->cmd == IPMI_GET_DEVICE_ID_CMD) && (rsp->data_len >= 12) && (rsp->data[0] == 0)) { chan->oem.oem_handle_rsp = NULL; chan->manufacturer_id = (rsp->data[7] | (rsp->data[8] << 8) | (rsp->data[9] << 16)); chan->product_id = rsp->data[10] | (rsp->data[11] << 8); check_oem_handlers(chan); /* Will be set to 1 if we sent it. */ if (msg->oem_data) { chan->free(chan, msg); return 1; } } return 0; } int chan_init(channel_t *chan) { int rv = 0; /* If the calling code already hasn't set up an OEM handler, we set up our own to look for a get device id. When we find a get device ID, we call the OEM code to install their own. Hijack channel 0 for this. */ if ((chan->channel_num == 15) && (chan->oem.oem_handle_rsp == NULL)) { chan->oem.oem_handle_rsp = look_for_get_devid; /* Send a get device id to the low-level code so we can discover who we are. */ rv = ipmi_oem_send_msg(chan, IPMI_APP_NETFN, IPMI_GET_DEVICE_ID_CMD, NULL, 0, 1); } return rv; } void sysinfo_init(sys_data_t *sys) { memset(sys, 0, sizeof(*sys)); } void debug_log_raw_msg(sys_data_t *sys, unsigned char *data, unsigned int len, const char *format, ...) { va_list ap; char *str; int slen; int pos; char dummy; unsigned int i; struct timeval tv; gettimeofday(&tv, NULL); va_start(ap, format); slen = vsnprintf(&dummy, 0, format, ap); slen += snprintf(&dummy, 0, " %ld.%6.6ld", tv.tv_sec, tv.tv_usec); va_end(ap); slen += len * 3 + 2; str = malloc(slen); if (!str) return; va_start(ap, format); pos = vsprintf(str, format, ap); va_end(ap); pos += sprintf(str + pos, " %ld.%6.6ld", tv.tv_sec, tv.tv_usec); str[pos++] = '\n'; str[pos] = '\0'; for (i = 0; i < len; i++) pos += sprintf(str + pos, " %2.2x", data[i]); sys->log(sys, DEBUG, NULL, "%s", str); free(str); } /* Deal with multi-byte data, IPMI (little-endian) style. */ unsigned int ipmi_get_uint16(uint8_t *data) { return (data[0] | (data[1] << 8)); } void ipmi_set_uint16(uint8_t *data, int val) { data[0] = val & 0xff; data[1] = (val >> 8) & 0xff; } unsigned int ipmi_get_uint32(uint8_t *data) { return (data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24)); } void ipmi_set_uint32(uint8_t *data, int val) { data[0] = val & 0xff; data[1] = (val >> 8) & 0xff; data[2] = (val >> 16) & 0xff; data[3] = (val >> 24) & 0xff; } uint8_t ipmb_checksum(uint8_t *data, int size, uint8_t start) { uint8_t csum = start; for (; size > 0; size--, data++) csum += *data; return csum; } OpenIPMI-2.0.33/lanserv/ipmi_sim.10000644000175000017500000001130413115245676013453 00000000000000.TH ipmi_sim 1 06/26/12 OpenIPMI "IPMI LAN BMC Simulator" .SH "NAME" ipmi_sim \- IPMI LAN BMC Simulator .SH SYNOPSIS .B ipmi_sim .RB [ \-c .IR config-file ] .RB [ \-f .IR command-file ] .RB [ \-x .IR command ] .RB [ \-s .IR state-dir ] .RB [ \-d ] .RB [ \-n ] .SH "DESCRIPTION" The .B ipmi_sim daemon emulates an IPMI BMC simulator that may be accessed using the IPMI 1.5 or 2.0 LAN protocol, or via various serial protocols. It is useful stand-along for prototyping, it may be used with a virtual machine such as QEMU to provide an IPMI BMC emulator, and it may be used to implement an actual BMC (where it's not such a simulator any more) .B ipmi_sim supports the full authentication capabilities of the IPMI LAN protocol. .B ipmi_sim supports multiple IP addresses for fault-tolerance. Note that messages coming in on an address are always sent back out on the same address they came in. .SH "OPTIONS" .TP .BI \-c\ config-file Set the configuration file to one other than the default of .I "/etc/ipmi/lan.conf". See ipmi_lan(5) for details. .TP .BI \-f\ command-file Specify a command file to execute when .B ipmi_sim is starting. This is generally used to set up the IPMI environment. See ipmi_sim_cmd(5) for details. .TP .B \-x\ command Execute a single command. .TP .BI \-s\ state-dir Specify a state directory for .B ipmi_sim to use instead of the default. The state directory must exist, and .B ipmi_sim will store information there for when it restarts. For instance, if someone changes user information, then it will store the new user information there and what is in the config file will no longer be used. .TP .TP .B \-d Turns on debugging to standard output (if -n is not specified) and the debug output of syslog. .TP .B \-n Disables console and I/O on standard input and output. .SH "CONFIGURATION" Configuration is accomplished through the file .IR /etc/ipmi/lan.conf . A file with another name or path may be specified using the .B \-c option. See the ipmi_lan(5) config file man page for more details. .SH "COMMANDS" When .B ipmi_sim starts up, it has an empty environment with no BMC or management controllers. You have to execute commands to set things up. The commands can also be used to set sensor states, inject events, and other things you might want to do when simulating a BMC. See the ipmi_sim_cmd(5) man page for details. .SH "SECURITY" .B ipmi_sim implements normal IPMI security. The default is no access for anyone, so the default is pretty safe, but be careful what you add, because this is access to control your box. \fBstraight\fP and \fBnone\fP authorizations are not recommended, you should probably stick with \fBmd2\fP or \fBmd5\fP if you are not using \fBRMCP+\fP. .SH "PERSISTENCE" Things that are supposed to be persistent in a BMC are kept in files, generall in /var/ipmi_sim/, where is the name of the BMC specified in the configuration file. The following things are persistent: .TP .BI SDRs - This is named sdr..main and is the main SDR repository. .TP .BI SEL - This is named sel.. .TP .BI Users - This is named users.mc. .TP .BI LAN\ parameters - This is named lanparm.mc.. .TP .BI SOL\ parameters - This is named sol.mc. .P The is the hexadecimal number of the MC. .SH "Serial Over LAN (SOL)" .B ipmi_sim implements Serial Over LAN for hooking an RMCP+ connection to a standard Unix serial port. This is configured in the ipmi_lan(5) configuration file. A SOL interface is done on a per-MC basis. So if the MC is set to a non-BMC, you can define a SOL interface on it and it will work if you reroute the commands to that MC. It's a little weird, but it works. Only interface 1 is supported at the moment. A SOL interface can also hold history that is kept even if nothing is connected to the SOL interface from the LAN. So if you want to see what has happened on the serial port, you can connect to interface 2 and it will dump the history. The history is optionally persistent, if the program terminates normally and is restarted, the history is restored if it is configured to do so. A SOL interface can create a FRU on the MC to let you fetch the history via the FRU interface. .SH "SIGNALS" .TP 0.5i .B SIGHUP .B ipmi_sim should handle SIGHUP and reread it's configuration files. However, it doesn't right now. It might in the future, for now you will have to kill it and restart it. Clients should handle reconnecting in this case. If they don't, they are broken. .SH "ERROR OUTPUT" At startup, all error output goes to stderr. After that, all error output goes to syslog. .SH "FILES" /etc/ipmi_lan.conf .SH "SEE ALSO" .BR ipmi_lan (5), ipmi_sim_cmd (5), ipmi_ui (1), openipmish (1) .SH AUTHOR .PP Corey Minyard OpenIPMI-2.0.33/lanserv/ipmi_sim.h0000664000175000017500000001006014002617260013526 00000000000000/* * bmc.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2020 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef IPMI_SIM_H #define IPMI_SIM_H int is_mc_alloc_unconfigured(sys_data_t *sys, unsigned char ipmb, lmc_data_t **rmc); unsigned char is_mc_get_ipmb(lmc_data_t *mc); channel_t **is_mc_get_channelset(lmc_data_t *mc); ipmi_sol_t *is_mc_get_sol(lmc_data_t *mc); startcmd_t *is_mc_get_startcmdinfo(lmc_data_t *mc); user_t *is_mc_get_users(lmc_data_t *mc); int is_mc_users_changed(lmc_data_t *mc); pef_data_t *is_mc_get_pef(lmc_data_t *mc); msg_t *is_mc_get_next_recv_q(channel_t *chan); int is_sol_read_config(char **tokptr, sys_data_t *sys, const char **err); void is_set_chassis_control_prog(lmc_data_t *mc, const char *prog); void is_resend_atn(channel_t *chan); typedef unsigned char *(*get_frudata_f)(lmc_data_t *mc, unsigned int *size); typedef void (*free_frudata_f)(lmc_data_t *mc, unsigned char *data); int ipmi_mc_set_frudata_handler(lmc_data_t *mc, unsigned int fru, get_frudata_f handler, free_frudata_f freefunc); typedef struct ipmi_child_quit_s { void (*handler)(void *info, pid_t pid); void *info; struct ipmi_child_quit_s *next; } ipmi_child_quit_t; void ipmi_register_child_quit_handler(ipmi_child_quit_t *handler); typedef struct ipmi_shutdown_s { void (*handler)(void *info, int sig); void *info; struct ipmi_shutdown_s *next; } ipmi_shutdown_t; void ipmi_register_shutdown_handler(ipmi_shutdown_t *handler); /* * Start the "startcmd" specified in the configuration file. */ void ipmi_do_start_cmd(startcmd_t *startcmd); void ipmi_do_kill(startcmd_t *startcmd, int noblock); int sol_init(sys_data_t *sys); int read_sol_config(sys_data_t *sys); int write_sol_config(lmc_data_t *mc); #endif /* IPMI_SIM_H */ OpenIPMI-2.0.33/lanserv/ipmisim1.emu0000664000175000017500000000365713107042442014024 00000000000000# This is an example simulation setup for ipmi_sim. It creates a single # management controller as a BMC. That will have the standard watchdog # sensor and we add a temperature sensor. # The BMC is the MC at address 20 mc_setbmc 0x20 # Now add the BMC mc_add 0x20 0 no-device-sdrs 0x23 9 8 0x9f 0x1291 0xf02 persist_sdr sel_enable 0x20 1000 0x0a # Watchdog sensor. This must be sensor zero. sensor_add 0x20 0 0 35 0x6f event-only sensor_set_event_support 0x20 0 0 enable scanning per-state \ 000000000001111 000000000000000 \ 000000000001111 000000000000000 # Add a temperature sensor and its SDR. Note that sensor 0 is already # taken as the watchdog sensor. sensor_add 0x20 0 1 0x01 0x01 # Start with the value set to 0x60 sensor_set_value 0x20 0 1 0x60 0 # Set just the upper thresholds with the values 0x70, 0x90, and 0xa0 sensor_set_threshold 0x20 0 1 settable 111000 0xa0 0x90 0x70 00 00 00 # Enable all upper threshold events events sensor_set_event_support 0x20 0 1 enable scanning per-state \ 000111111000000 000111111000000 \ 000111111000000 000111111000000 # Add a memory module presence sensor. sensor_add 0x20 0 2 37 0x6f sensor_set_bit_clr_rest 0x20 0 2 1 1 #sensor_set_bit_clr_rest 0x20 0 2 0 1 sensor_set_event_support 0x20 0 2 enable scanning per-state \ 000000000000011 000000000000011 \ 000000000000011 000000000000011 # FRU data for entity 8.2 mc_add_fru_data 0x30 3 128 data 0 # Add a satellite MC mc_add 0x30 2 no-device-sdrs 0x98 0x10 1 0xa0 0x1291 0xf03 sensor_add 0x30 0 1 0x01 0x01 # Uncomment the following and comment the proceding to read the value # from the given file. You can modify the file contents. #sensor_add 0x30 0 1 0x01 0x01 poll 1000 file "/tmp/file1.ipm" sensor_set_threshold 0x30 0 1 settable 111000 0xa0 0x90 0x70 00 00 00 sensor_set_event_support 0x30 0 1 enable scanning per-state \ 000111111000000 000111111000000 \ 000111111000000 000111111000000 mc_enable 0x30 # Turn on the BMC mc_enable 0x20 OpenIPMI-2.0.33/lanserv/Makefile.am0000664000175000017500000000525114261603511013612 00000000000000 LIB_VERSION = 0.0.1 LD_VERSION = 0:1:0 PVERSION="1.0.13" BUILD_CC = @BUILD_CC@ SUBDIRS = OpenIPMI sdrcomp @MARVELL_BMC_DIR@ DIST_SUBDIRS = OpenIPMI sdrcomp marvell-bmc AM_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include -DIPMI_CHECK_LOCKS \ $(OPENSSLINCS) -DPVERSION="\"$(PVERSION)\"" -DBUILDING_IPMI_LANSERV_DLL AM_CPPFLAGS = -DSYSCONFDIR='"$(sysconfdir)"' -DSTATEDIR='"$(localstatedir)"' lib_LTLIBRARIES = libIPMIlanserv.la if HAVE_OPENIPMI_SMI IPMILAN_PROG = ipmilan IPMILAN_MAN = ipmilan.8 IPMILAN_NOMAN = else IPMILANPROG = IPMILAN_MAN = IPMILAN_NOMAN = ipmilan.8 endif bin_PROGRAMS = ipmi_sim $(IPMILAN_PROG) noinst_PROGRAMS = ipmi_checksum noinst_HEADERS = emu.h bmc.h ipmi_sim.h sol.h libIPMIlanserv_la_SOURCES = lanserv_ipmi.c lanserv_asf.c priv_table.c \ lanserv_oem_force.c lanserv_config.c config.c serv.c serial_ipmi.c \ persist.c extcmd.c ipmb_ipmi.c libIPMIlanserv_la_LIBADD = $(OPENSSLLIBS) -ldl $(RT_LIB) libIPMIlanserv_la_LDFLAGS = -version-info $(LD_VERSION) \ ../utils/libOpenIPMIutils.la -no-undefined ipmi_checksum_SOURCES = ipmi_checksum.c if HAVE_OPENIPMI_SMI ipmilan_SOURCES = lanserv.c ipmilan_LDADD = $(POPTLIBS) libIPMIlanserv.la -ldl $(RT_LIB) ipmilan_LDFLAGS = -rdynamic ../unix/libOpenIPMIposix.la \ ../utils/libOpenIPMIutils.la ipmilan_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include \ -DIPMI_CHECK_LOCKS $(OPENSSLINCS) -DPVERSION="\"$(PVERSION)\"" endif ipmi_sim_SOURCES = ipmi_sim.c bmc.c emu_cmd.c sol.c \ bmc_storage.c bmc_app.c bmc_chassis.c bmc_transport.c \ bmc_sensor.c bmc_picmg.c ipmi_sim_LDADD = $(POPTLIBS) libIPMIlanserv.la -lpthread $(RT_LIB) ipmi_sim_LDFLAGS = -rdynamic ../unix/libOpenIPMIposix.la \ ../utils/libOpenIPMIutils.la $(SOCKETLIB) ipmi_sim_CFLAGS = -Wall -Wsign-compare -I$(top_srcdir)/include \ -DIPMI_CHECK_LOCKS $(OPENSSLINCS) -DPVERSION="\"$(PVERSION)\"" man_MANS = $(IPMILAN_MAN) ipmi_lan.5 ipmi_sim.1 ipmi_sim_cmd.5 READMES = README.ipmi_sim README.vm README.design README.yourownbmc EXTRA_DIST = atca.emu lan.conf ipmisim1.emu ipmisim1.sdrs \ $(man_MANS) $(IPMILAN_NOMAN) $(READMES) install-data-local: $(INSTALL) -m 755 -d "$(DESTDIR)$(sysconfdir)/ipmi/"; \ $(INSTALL) -m 600 $(srcdir)/lan.conf "$(DESTDIR)$(sysconfdir)/ipmi/"; $(INSTALL) -m 600 $(srcdir)/ipmisim1.emu "$(DESTDIR)$(sysconfdir)/ipmi/"; noinst_DATA = ipmisim1.bsdr SUFFIXES = .bsdr .sdrs .sdrs.bsdr: sdrcomp/sdrcomp_build -o $@ $< ipmisim1.bsdr: $(top_srcdir)/lanserv/ipmisim1.sdrs sdrcomp/sdrcomp_build uninstall-local: -rm -f "$(DESTDIR)$(sysconfdir)/ipmi/ipmisim1.emu" -rm -f "$(DESTDIR)$(sysconfdir)/ipmi/lan.conf" -rm -f "$(DESTDIR)$(sysconfdir)/ipmi/sim.emu" -rmdir "$(DESTDIR)$(sysconfdir)/ipmi" 2>/dev/null CLEANFILES = ipmisim1.bsdr OpenIPMI-2.0.33/lanserv/bmc.h0000664000175000017500000003121214002617260012463 00000000000000/* * bmc.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef __BMC_H_ #define __BMC_H_ #include #include #include #include "emu.h" #include "sol.h" #include "ipmi_sim.h" #define WATCHDOG_SENSOR_NUM 0 #define OPENIPMI_IANA 40820 /* OpenIPMI's own number */ typedef struct sel_entry_s { uint16_t record_id; unsigned char data[16]; struct sel_entry_s *next; } sel_entry_t; typedef struct sel_s { sel_entry_t *entries; int count; int max_count; uint32_t last_add_time; uint32_t last_erase_time; unsigned char flags; uint16_t reservation; uint16_t next_entry; long time_offset; } sel_t; #define MAX_SDR_LENGTH 261 #define MAX_NUM_SDRS 1024 typedef struct sdr_s { uint16_t record_id; unsigned int length; unsigned char *data; struct sdr_s *next; } sdr_t; typedef struct sdrs_s { uint16_t reservation; uint16_t sdr_count; uint16_t sensor_count; uint32_t last_add_time; uint32_t last_erase_time; long time_offset; unsigned char flags; uint16_t next_entry; unsigned int sdrs_length; /* A linked list of SDR entries. */ sdr_t *sdrs; } sdrs_t; struct sensor_s { lmc_data_t *mc; unsigned char num; unsigned int lun : 2; unsigned int scanning_enabled : 1; unsigned int events_enabled : 1; unsigned int enabled : 1; unsigned char sensor_type; unsigned char event_reading_code; unsigned char value; unsigned char hysteresis_support; unsigned char positive_hysteresis; unsigned char negative_hysteresis; unsigned char threshold_support; uint16_t threshold_supported; /* Bitmask */ unsigned char thresholds[6]; int event_only; unsigned char event_support; /* 0 for assertion, 1 for deassertion. */ uint16_t event_supported[2]; uint16_t event_enabled[2]; int (*rearm_handler)(void *cb_data, uint16_t assert, uint16_t deassert); void *rearm_cb_data; /* Current bit values */ uint16_t event_status; /* Called when the sensor changes values. */ void (*sensor_update_handler)(lmc_data_t *mc, sensor_t *sensor); ipmi_timer_t *poll_timer; struct timeval poll_timer_time; int (*poll)(void *cb_data, unsigned int *val, const char **errstr); void *cb_data; }; typedef struct fru_data_s fru_data_t; typedef struct fru_session_s { unsigned char *data_to_free; unsigned char *data; unsigned int length; unsigned int sid; fru_data_t *fru; struct fru_session_s *next; } fru_session_t; struct fru_data_s { unsigned int devid; fru_io_cb fru_io_cb; unsigned int length; unsigned char *data; fru_session_t *sessions; get_frudata_f get; free_frudata_f free; sem_t sem; fru_data_t *next; }; typedef struct led_data_s { unsigned char off_dur; unsigned char def_off_dur; unsigned char on_dur; unsigned char def_on_dur; unsigned char color; unsigned char color_sup; unsigned char loc_cnt; unsigned char loc_cnt_sup; unsigned char def_loc_cnt_color; unsigned char def_override_color; } led_data_t; struct lmc_data_s { emu_data_t *emu; char enabled; char configured; unsigned char ipmb; unsigned char guid_set; unsigned char guid[16]; channel_t *channels[IPMI_MAX_CHANNELS]; channel_t sys_channel; channel_t ipmb_channel; int users_changed; user_t users[MAX_USERS + 1]; pef_data_t pef; pef_data_t pef_rollback; ipmi_tick_handler_t tick_handler; ipmi_child_quit_t child_quit_handler; startcmd_t startcmd; unsigned char evq[16]; char ev_in_q; /* Get Device Id contents. */ unsigned char device_id; /* byte 2 */ unsigned char has_device_sdrs; /* byte 3, bit 7 */ unsigned char device_revision; /* byte 3, bits 0-6 */ unsigned char major_fw_rev; /* byte 4, bits 0-6 */ unsigned char minor_fw_rev; /* byte 5 */ unsigned char device_support; /* byte 7 */ unsigned char mfg_id[3]; /* bytes 8-10 */ unsigned char product_id[2]; /* bytes 11-12 */ unsigned char aux_fw_rev[4]; /* bytes 13-16 */ #define IPMI_MC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK (1 << 3) #define IPMI_MC_MSG_FLAG_EVT_BUF_FULL (1 << 1) #define IPMI_MC_MSG_FLAG_RCV_MSG_QUEUE (1 << 0) #define IPMI_MC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(mc) \ (IPMI_MC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK & (mc)->msg_flags) #define IPMI_MC_MSG_FLAG_EVT_BUF_FULL_SET(mc) \ (IPMI_MC_MSG_FLAG_EVT_BUF_FULL & (mc)->msg_flags) #define IPMI_MC_MSG_FLAG_RCV_MSG_QUEUE_SET(mc) \ (IPMI_MC_MSG_FLAG_RCV_MSG_QUEUE & (mc)->msg_flags) unsigned char msg_flags; #define IPMI_MC_RCV_MSG_QUEUE_INT_BIT 0 #define IPMI_MC_EVBUF_FULL_INT_BIT 1 #define IPMI_MC_EVENT_MSG_BUF_BIT 2 #define IPMI_MC_EVENT_LOG_BIT 3 #define IPMI_MC_MSG_INTS_ON(mc) ((mc)->global_enables & \ (1 << IPMI_MC_RCV_MSG_QUEUE_INT_BIT)) #define IPMI_MC_EVBUF_FULL_INT_ENABLED(mc) ((mc)->global_enables & \ (1 << IPMI_MC_EVBUF_FULL_INT_BIT)) #define IPMI_MC_EVENT_LOG_ENABLED(mc) ((mc)->global_enables & \ (1 << IPMI_MC_EVENT_LOG_BIT)) #define IPMI_MC_EVENT_MSG_BUF_ENABLED(mc) ((mc)->global_enables & \ (1 << IPMI_MC_EVENT_MSG_BUF_BIT)) unsigned char global_enables; sys_data_t *sysinfo; sel_t sel; sdrs_t main_sdrs; sdr_t *part_add_sdr; unsigned int part_add_next; int in_update_mode; unsigned char event_receiver; unsigned char event_receiver_lun; sdrs_t device_sdrs[4]; unsigned int dynamic_sensor_population : 1; unsigned int sensors_enabled : 1; unsigned char lun_has_sensors[4]; unsigned char num_sensors_per_lun[4]; sensor_t *(sensors[4][255]); uint32_t sensor_population_change_time; fru_data_t *frulist; ipmi_sol_t sol; int (*chassis_control_set_func)(lmc_data_t *mc, int op, unsigned char *val, void *cb_data); int (*chassis_control_get_func)(lmc_data_t *mc, int op, unsigned char *val, void *cb_data); ipmi_timer_t *power_timer; void *chassis_control_cb_data; const char *chassis_control_prog; unsigned char power_value; #define MAX_LEDS 8 #define MIN_ATCA_LEDS 2 unsigned int num_leds; led_data_t leds[MAX_LEDS]; /* Will be NULL if not valid. */ sensor_t *hs_sensor; #define IPMI_MC_WATCHDOG_USE_MASK 0xc7 #define IPMI_MC_WATCHDOG_ACTION_MASK 0x77 #define IPMI_MC_WATCHDOG_GET_USE(s) ((s)->watchdog_use & 0x7) #define IPMI_MC_WATCHDOG_GET_DONT_LOG(s) (((s)->watchdog_use >> 7) & 0x1) #define IPMI_MC_WATCHDOG_GET_DONT_STOP(s) (((s)->watchdog_use >> 6) & 0x1) #define IPMI_MC_WATCHDOG_GET_PRE_ACTION(s) (((s)->watchdog_action >> 4) & 0x7) #define IPMI_MC_WATCHDOG_PRE_NONE 0 #define IPMI_MC_WATCHDOG_PRE_SMI 1 #define IPMI_MC_WATCHDOG_PRE_NMI 2 #define IPMI_MC_WATCHDOG_PRE_MSG_INT 3 #define IPMI_MC_WATCHDOG_GET_ACTION(s) ((s)->watchdog_action & 0x7) #define IPMI_MC_WATCHDOG_ACTION_NONE 0 #define IPMI_MC_WATCHDOG_ACTION_RESET 1 #define IPMI_MC_WATCHDOG_ACTION_POWER_DOWN 2 #define IPMI_MC_WATCHDOG_ACTION_POWER_CYCLE 3 unsigned char watchdog_use; unsigned char watchdog_action; unsigned char watchdog_pretimeout; unsigned char watchdog_expired; int watchdog_running; int watchdog_preaction_ran; int watchdog_initialized; struct timeval watchdog_time; /* Set time */ struct timeval watchdog_expiry; /* Timeout time */ ipmi_timer_t *watchdog_timer; }; typedef struct atca_site_s { unsigned char valid; unsigned char hw_address; unsigned char site_type; unsigned char site_number; } atca_site_t; #define MAX_EMU_ADDR 16 #define MAX_EMU_ADDR_DATA 64 typedef struct emu_addr_s { unsigned char valid; unsigned char addr_type; unsigned char addr_data[MAX_EMU_ADDR_DATA]; unsigned int addr_len; } emu_addr_t; struct emu_data_s { sys_data_t *sysinfo; int users_changed; int atca_mode; atca_site_t atca_sites[128]; /* Indexed by HW address. */ uint32_t atca_fru_inv_curr_timestamp; uint16_t atca_fru_inv_curr_lock_id; int atca_fru_inv_locked; int atca_fru_inv_lock_timeout; unsigned char *temp_fru_inv_data; unsigned int temp_fru_inv_data_len; void *user_data; ipmi_emu_sleep_cb sleeper; struct timeval last_addr_change_time; emu_addr_t addr[MAX_EMU_ADDR]; }; /* Device ID support bits */ #define IPMI_DEVID_CHASSIS_DEVICE (1 << 7) #define IPMI_DEVID_BRIDGE (1 << 6) #define IPMI_DEVID_IPMB_EVENT_GEN (1 << 5) #define IPMI_DEVID_IPMB_EVENT_RCV (1 << 4) #define IPMI_DEVID_FRU_INVENTORY_DEV (1 << 3) #define IPMI_DEVID_SEL_DEVICE (1 << 2) #define IPMI_DEVID_SDR_REPOSITORY_DEV (1 << 1) #define IPMI_DEVID_SENSOR_DEV (1 << 0) fru_data_t *find_fru(lmc_data_t *mc, unsigned int devid); int start_poweron_timer(lmc_data_t *mc); sdr_t *find_sdr_by_recid(sdrs_t *sdrs, uint16_t record_id, sdr_t **prev); sdr_t *new_sdr_entry(sdrs_t *sdrs, unsigned char length); void add_sdr_entry(lmc_data_t *mc, sdrs_t *sdrs, sdr_t *entry); void read_mc_sdrs(lmc_data_t *mc, sdrs_t *sdrs, const char *sdrtype); void iterate_sdrs(lmc_data_t *mc, sdrs_t *sdrs, int (*func)(lmc_data_t *mc, unsigned char *sdr, unsigned int len, void *cb_data), void *cb_data); #define IPMI_SDR_DELETE_SDR_SUPPORTED (1 << 3) #define IPMI_SDR_PARTIAL_ADD_SDR_SUPPORTED (1 << 2) #define IPMI_SDR_RESERVE_SDR_SUPPORTED (1 << 1) #define IPMI_SDR_GET_SDR_ALLOC_INFO_SDR_SUPPORTED (1 << 0) void picmg_led_set(lmc_data_t *mc, sensor_t *sensor); void set_sensor_bit(lmc_data_t *mc, sensor_t *sensor, unsigned char bit, unsigned char value, unsigned char evd1, unsigned char evd2, unsigned char evd3, int gen_event); void watchdog_timeout(void *cb_data); extern cmd_handler_f storage_netfn_handlers[256]; extern cmd_handler_f app_netfn_handlers[256]; extern cmd_handler_f chassis_netfn_handlers[256]; extern cmd_handler_f transport_netfn_handlers[256]; extern cmd_handler_f sensor_event_netfn_handlers[256]; extern cmd_handler_f oem0_netfn_handlers[256]; #define set_bit(m, b, v) (m) = (v) ? ((m) | (1 << (b))) : ((m) & ~(1 << (b))) #define bit_set(m, b) (!!((m) & (1 << (b)))) int ipmi_mc_is_power_on(lmc_data_t *mc); #endif /* __BMC_H_ */ OpenIPMI-2.0.33/lanserv/lanserv_oem_force.c0000664000175000017500000001454014002617260015412 00000000000000/* * lanserv_force_oem.c * * MontaVista IPMI IPMI LAN code for OEM Force Computers board handling * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003 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 #include typedef struct force_oem_data_s { unsigned char slave_addr; unsigned char curr_addr; } force_oem_data_t; static int force_rsp_handler(channel_t *chan, msg_t *msg, rsp_msg_t *rsp) { unsigned char new_addr; if (rsp->netfn == 0x31) { /* A force OEM response. */ force_oem_data_t *fdata = chan->oem.oem_data; switch (rsp->cmd) { case 3: /* A response to a change mode. */ /* Ignore errors. */ if (rsp->data_len < 1) return 0; if (rsp->data[0] != 0) return 0; /* See what it was changed to. */ if (msg->data[0] == 0) /* Changed to master, address is 0x20 */ new_addr = 0x20; else new_addr = fdata->slave_addr; if (new_addr != fdata->curr_addr) { fdata->curr_addr = fdata->slave_addr; chan->log(chan, INFO, NULL, "Change Force MC address to 0x%x", new_addr); if (chan->oem.ipmb_addr_change) chan->oem.ipmb_addr_change(chan, fdata->curr_addr); } break; case 4: /* A request for the IPMB address. */ /* Ignore errors. */ if (rsp->data_len < 4) return 0; if (rsp->data[0] != 0) return 0; fdata->slave_addr = rsp->data[3]; if (fdata->curr_addr != rsp->data[2]) { fdata->curr_addr = rsp->data[2]; if (chan->oem.ipmb_addr_change) chan->oem.ipmb_addr_change(chan, fdata->curr_addr); } return msg->oem_data; } } return 0; } static int force_check_permitted(unsigned char priv, unsigned char netfn, unsigned char cmd) { int req_priv = IPMI_PRIVILEGE_ADMIN; if (netfn != 0x30) return IPMI_PRIV_INVALID; switch (cmd) { case 3: req_priv = IPMI_PRIVILEGE_OPERATOR; break; case 4: req_priv = IPMI_PRIVILEGE_USER; break; case 5: req_priv = IPMI_PRIVILEGE_USER; break; case 6: req_priv = IPMI_PRIVILEGE_OPERATOR; break; } if (priv >= req_priv) return IPMI_PRIV_PERMITTED; else return IPMI_PRIV_DENIED; } static force_oem_data_t force_data = { .slave_addr = 0, .curr_addr = 0, }; static void force_oem_installer(channel_t *chan, void *cb_data) { chan->oem.oem_handle_rsp = force_rsp_handler; chan->oem.oem_check_permitted = force_check_permitted; chan->oem.oem_data = &force_data; /* Set a command to get the current address. */ ipmi_oem_send_msg(chan, 0x30, 4, NULL, 0, 1); } static oem_handler_t force_735_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0804, .handler = force_oem_installer, .cb_data = NULL, }; static oem_handler_t force_740_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0808, .handler = force_oem_installer, .cb_data = NULL, }; static oem_handler_t force_786_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0810, .handler = force_oem_installer, .cb_data = NULL, }; static oem_handler_t force_550_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0880, .handler = force_oem_installer, .cb_data = NULL, }; static oem_handler_t force_560_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0888, .handler = force_oem_installer, .cb_data = NULL, }; static oem_handler_t force_690_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0900, .handler = force_oem_installer, .cb_data = NULL, }; static oem_handler_t force_695_oem = { .manufacturer_id = 0x000e48, .product_id = 0x0904, .handler = force_oem_installer, .cb_data = NULL, }; void init_oem_force(void) { ipmi_register_oem(&force_735_oem); ipmi_register_oem(&force_740_oem); ipmi_register_oem(&force_786_oem); ipmi_register_oem(&force_550_oem); ipmi_register_oem(&force_560_oem); ipmi_register_oem(&force_690_oem); ipmi_register_oem(&force_695_oem); } #if 0 /* If you include this as a module under Linux, you can use the following code to initialize it. Otherwise, something has to call init_oem_force(). */ static void (*const __init_patch_debug[1]) \ (void) __attribute__ ((section(".ctors"))) = { init_oem_force }; #endif OpenIPMI-2.0.33/lanserv/README.yourownbmc0000664000175000017500000002004513136646220014643 00000000000000 Using ipmi_sim For A Real BMC ----------------------------- So you want to create a real BMC. This is now possible with the simulator. So it's really not a simulator in this case, but that's its heritage, so the name is still stuck. Maybe I'll change it later. Anyway, It can do most of the work without even writing any C code, just with configuration. It probably won't do everything you want out of the box, though, so it has plugin capability to let you add your own code to handle special conditions. This documentation assumes a good working knowledge of IPMI. How It Works ------------ The simulator has the two standard configuration files as defined in the ipmi_sim_cmd.5 and ipmi_lan.5 man pages. The LAN configuration file defines the lan interfaces and a few other things, like SOL configuration. The emulator command file has commands to define the IPMI structure of the system, like management controllers, sensors, FRU data, SDRs, etc. So to create a BMC, you define the LAN interfaces, the management controllers, the sensors, etc. in your system. You can tie the FRU data to physical files on the system (like EEPROMS in sysfs, or real files). You can tie the sensors to files, like sensors in sysfs. You can also write custom code and tie it in to set the sensor values. Management Controllers ---------------------- To have a management controller handled by ipmi_sim, you have to add it via the mc_add command, then you have to enable it with mc_enable. This is a virtual management controller. You have to add the BMC at 0x20, of course, but you can add others, too, if that makes sense. For instance, if you have multiple boards in the system, it may make sense to define a virtual MC for each board. This is pretty simple. Note that the capabilities you set with the mc_add command affect what the MC can do. You can't add SDRs, for instance, if the MC doesn't have SDR capability. LAN Configuration ----------------- The LAN configuration file mostly defines the LAN interfaces. It also has a lot of simulator configuration, like how to start virtual machine sessions tied to the management controllers and how the VMs interface to the simulator. These aren't terribly useful for a real BMC (though the serial interface might one day with some modifications). The name of the BMC is set here. This is used for a few things, like to tell where to store persistent information (in /var/ipmi_sim/) and in logging. A few other things in the file are SOL configuration, chassis control handling, and loading custom code. These are discussed later. Sensors ------- Sensors are added with the emulator command file with the sensor_add command. This command also lets you poll a file for data and has a lot of options for massaging the data from the file into the 256 byte value returned by an IPMI sensor. It also lets you tie a dependency to a discrete sensor, so that the enabling of the sensor can be done based on a bit in the other discrete sensor. For instance, a power supply sensor has a presence bit in it, the power supply voltage and current sensors can depend on that bit to be enabled or disabled. If you are writing custom code to handle a sensor, you still have to add it with sensor_add, then you can use the sensor number to manipulate the sensor's value. You have three main functions to do this: ipmi_mc_sensor_set_enabled() will let you enable or disable a sensor directly. Generally you would modify the sensor enable based upon the presence of the entity the sensor measures. ipmi_mc_sensor_set_value() sets a threshold sensor's value. ipmi_mc_sensor_set_bit() sets/clears a discrete sensor bit. SDRs ---- If you have sensors, you need SDRs to describe them. You can directly add these via the emulator command main_sdr_add (or device_sdr_add), but that only deals with raw data and is a fairly inconvenient way to do this. The main SDRs for an MC are persistent and stored in /var/ipmi_sim/.main. For instance, the main SDRs for a BMC at 0x20 are in /var/ipmi_sim//sdr.20.main. If the user makes changes, they are stored there. But, you can store your SDRs here, too. The easier way is to use the SDR compiler in the sdrcomp directory, which can output data in the persistence format. Then you can write your SDRs in a more human-readable (or perhaps ipmi-engineer-readable) format rather than just a bunch of bits. Then generate the file and copy it into the right place. Serial Over LAN --------------- As mentioned earlier, you can define SOL port in the lan configuration file. You can assign a physical serial port to a SOL port. This is described in the docs and is pretty straightforward. There are a couple of unusual things about this, though. One is that you can create a SOL interface on an MC besides the BMC. But the standard SOL protocol will still work with it. This means you can use "ipmitool -t " to address a specific SOL instance, which is convenient if you want to tie SOL interfaces to specific MCs. Yes, it's kind of an abuse of the spec, but it works and is convenient. The other unusual thing about the SOL implementation is that it can have a history buffer. So say you want to keep around the last 64K or so of data without having to be constantly connected to the BMC. You can define a 64K history buffer and connect to the BMC later to fetch it. You have two ways to fetch it. The first is that the history buffer appears as a second SOL instance at instance 2. So you can connect to SOL instance 2 and it will dump all the history. The disadvantage of this approach is that ipmitool cannot connect to SOL instances besides 1 without a special patch. The other way to fetch it is to define a FRU data buffer that holds the history. You can define which FRU device does this. Then you can use the FRU data fetching commands to get the data. The disadvantage of this is that FRU data is limited to 64K. FRU Data -------- FRU data has already been mentioned with respect to SOL, but you can create FRU data for an MC with the mc_add_fru_data emulator command. You can either directly define the FRU data there (not ideal for a real BMC) or tie it to a file. Reading and writing all work. Chassis Control --------------- You can define an external command to handle chassis control commands. The ipmi_sim_chassiscontrol file gives a framework for writing your own script for handling this, and defines the various things that can be done. This is how reset, power, and boot control are done. Custom Code ----------- As mentioned before, you can load your own custom modules to do whatever you like. Any module must define the following function: int ipmi_sim_module_init(sys_data_t *sys, const char *initstr); This is used to initialize the module. It is called after the configuration has been read from the LAN configuration file, but before the emulator commands are run. The module must also define the following function: int ipmi_sim_module_print_version(sys_data_t *sys, char *initstr); This should print out an identifier and version number to standard out. The module may optionally define the following function: int ipmi_sim_module_post_init(sys_data_t *sys); This is called after the emulator command file is run. This can be used to finish up configuration of things, add functions to sensors, do any sensor initialization, or anything else that needs to be done after the emulator commands are run. The include files in lanserv/OpenIPMI define the interface function that a module may use. Primarily, serv.h and mcserv.c. Threading --------- The ipmi_sim code itself is not multi-threaded. You cannot have concurrent calls into any of the code. You can, however, define your own threads using pthreads as long as none of them call into the ipmi_sim code. What's Still Missing -------------------- ipmi_sim currently does not have any provisions for direct IPMI support or the handling of any I2C commands. This should be fairly easy to add, but has not yet been needed. Lots of other things are probably missing, too, of course, but it's hard to know what you don't know...OpenIPMI-2.0.33/lanserv/ipmi_sim_cmd.50000644000175000017500000002575713136646176014326 00000000000000.TH ipmi_sim_cmd 5 06/26/12 OpenIPMI "IPMI LAN Simulator commands" .SH DESCRIPTION The .B ipmi_sim emulation is set up using these commands. They can be read from a command file, run from the command line, or executed inside the simulator after it is started. This may be a little confusing, but the network interfaces are configured by the ipmi_lan configuration file, and the various management controllers, sensors, etc. are specified using this file. Plus, this can be used to configure the simulator after it is up, set sensor values, inject events, and things of that nature. .SH GENERAL COMMANDS Blank lines and lines starting with `#' are ignored. Long lines may be broken up by putting a '\' at the end of the line to be continued. .TP \fBquit\fP Exit the simulator .TP \fBinclude\fP \fI"file"\fP Include the given file. .TP \fBdefine\fP \fIname\fP \fI"value"\fP Define the given name as a variable with the given value. This variable may be used later by doing \fI$name\fP. This cannot be used in quotes, but quotes may be broken up and the variable put between them. For instance, if you say: define MCNUM "40" you can use it later as in mc_add $MCNUM 1 no-device-sdrs 00 00 00 0xc9 0x009000 0x0002 or sensor_add $MCNUM 0 21 12 0x6f poll 1000 file "/sys/dev/sens1-"$MCNUM"-1" .TP \fBsleep\fP \fItime\fP Pause the command interface for the given number of seconds. This does not affect the execution of the simulator. .TP \fBdebug\fP \fIoptions\fP Set the debugging output. Valid options are: .I msg Dump messages. .I raw Dump raw I/O Entering nothing turns of debugging. .TP \fBread_cmds\fP \fIfilename\fP Execute the commands in the given file. .SH MC COMMANDS .TP \fBmc_add\fP \fIIPMBAddress\fP \fIDeviceID\fP \fIHasDeviceSDRs\fP \fIDeviceRevision\fP \fIMajorFWRev\fP \fIMinorFWRev\fP \fIDeviceSupport\fP \fIManufacturerID\fP \fIProductID\fP Add an MC to the simulator. All values are hexadecimal. These are mostly values for the ``Get Device ID'' command, see the spec for details. Note that the MC is not enabled after being added, you must add it. Note that some of these values control the capabilities of the MC. For instance, HasDeviceSDRs sets whether device SDR repository commands will work. You may use has-device-sdrs or no-device-sdrs in the HasDeviceSDRs field. .TP \fBmc_add_fru_data\fP \fImc-addr\fP \fIDeviceID\fP \fIFRUSize\fP (data [\fIbyte1\fP [\fIbyte2\fP [...]]] | \fIfile\fP \fIoffset\fP \fIfilename\f{) Set the FRU data for a given MC and device id. Data may be supplied directly here, or it may be given as a file. The offset is the start from the beginning of the file where the data is kept. .TP \fBmc_dump_fru_data\fP \fImc-addr\fP \fIDeviceID\fP Dump the FRU data for a given MC and device id. .TP \fBmc_delete\fP \fImc-addr\fP Remove the MC from the system. .TP \fBmc_disable\fP \fImc-addr\fP Disable the MC, but don't remove it. .TP \fBmc_enable\fP \fImc-addr\fP Enable the given MC. .TP \fBmc_setbmc\fP \fImc-addr\fP Set the BMC's address. .TP \fBmc_set_guid\fP \fImc-addr\fP \fIguid\fP Set the GUID value. The guid may be a string (in quotes) or a hexadecimal string. .TP \fBsel_enable\fP \fImc-addr\fP \fImax-entries\fP \fIflags\fP Enable the System Event Log on the given MC. The flags is a byte this is returned from the ``Get SEL Info'' command; it controls various aspects of the SEL. See the spec for details. .TP \fBsel_add\fP \fImc-addr\fP \fIRecordType\fP \fIbyte1\fP \fIbyte2\fP ... \fIbyte13\fP Add an entry to the MC's SEL. .TP \fBmain_sdr_add\fP \fImc-addr\fP \fIbyte1\fP [\fIbyte2\fP [...]] Add an entry to the main SDR of the MC. .TP \fBdevice_sdr_add\fP \fImc-addr\fP \fILUN\fP \fIbyte1\fP [\fIbyte2\fP [...]] Add an entry to the device SDR of the MC. .SH SENSOR COMMANDS .TP \fBsensor_add\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIsensor-type\fP \fIevent-reading-code\fP [\fIpoll\fP \fIpoll_rate\fP \fIpoll_type\fP \fIpoll_type_options\fP] [event-only] Add a sensor to the given MC and LUN. The type of sensor is set by the event reading code. If \fIpoll\fP is specified, then the sensor will be polled for data. Only the \fIfile\fP poll type is currently supported. The value is a number read from a file. It has the following options, all optional: .I div=val will divide the read value by the given number. This is done after the multiply operation. .I mult=val will multiply the read value by the given number. This is done after the subtraction. .I sub=val will subtract the value by the given number. This is done after the mask. .I mask=val will mask (bitwise and) the value by the given number. .I base=value Specify the base of the value read from the file. By default this is zero, meaning "C" conventions are used. .I initstate=value sets what the event state is initially set to. This is useful for discrete sensors with bits that should normally be set to "1", like a presence bit, to keep the program from issuing an event every time the program starts. .I raw specifies that the data from the file is a raw value. Only \fIlength\fP bytes are read from \fIoffset\fP. .I ascii specifies that the data from the file is in ASCII. This is the default. The \fIoffset\fP value is used, but no the \fIlength\fP. .I length=val specifies the length of the data to read from the file. The maximum value is 4,and this is only used for raw data. .I depends=,,, specifies a discrete sensor bit that must be set to 1 for the sensor to be active. Generally, you use the presence bit of a sensor to mark whether other sensors on the device are actually present. Each of the other sensors would have one of these pointing to the presence bit. .I event-only specifies that the sensor will not be readable, it will only generate events (specified with a type 3 SDR). .TP \fBsensor_set_bit\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIbit-to-set\fP \fIbit-value\fP \fIgenerate-event\fP Set the given bit to bit-value (0 or 1) for the sensor by bit number, either the threshold for analog or the discrete sensor bit. If generate-event is non-zero and the sensor has events enabled for that bit, then generate an event. .TP \fBsensor_set_bit_clr_rest\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIbit-to-set\fP \fIbit-value\fP \fIgenerate-event\fP Like sensor_set_bit, but automatically clears all other bits. .TP \fBsensor_set_value\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIvalue\fP \fIgenerate-event\fP Set the byte value for an analog sensor. If the sensor exceeds a threshold, the sensor has events enabled, and generate-event is non-zero, then generate an event for the condition. .TP \fBsensor_set_hysteresis\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIsupport\fP \fIpositive\fP \fInegative\fP Set the hysteresis capabilities of the sensor. It must be an analog sensor. The support value is the hysteresis capability, the same as the hysteresis support value in the sensor SDR. The positive and negative hysteresis values are also set by this command. The support value may also be none, readable, settable, or fixed instead of the numbers. .TP \fBsensor_set_threshold\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIthreshold-support\fP \fIthreshold-enabled\fP [\fIvalue5\fP [\fIvalue4\fP [... [\fIvalue0\fP]]]] Set the threshold support for a sensor. It must be an analog sensor. The threshold-support value is the same as the threshold access support value in the sensor SDR. The threshold-enabled values is a string of ``0'' and ``1'' characters that enable the 6 corresponding thresholds; the rightmost value is value 0, the leftmost is value 5. Optionally, the threshold values may be specified as their byte values. The threshold-support value may also be none, readable, settable, or fixed to make it a bit more readable. The thresholds are: .I 0 - lower non critical .I 1 - lower critical .I 2 - lower non recoverable .I 3 - upper non critical .I 4 - upper critical .I 5 - upper non recoverable .TP \fBsensor_set_event_support\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIevents-enable\fP \fIscanning\fP \fIevent-support\fP \fIassert-support\fP \fIdeassert-support\fP \fIassert-enabled\fP \fIdeassert-enabled\fP Set the event support of a sensor. The events-enable will enable global events on the sensor if non-zero, otherwise they are disabled. The scanning values set the scanning value for the sensor. The event-support value sets the event capabilities in the sensor, this is the same as the ``sensor event message control support'' value in the sensor SDR. The assert-support, deassert-support, assert-enabled, and deassert-enabled are all bitmasks (a string of ``0'' and ``1'' characters) that set their corresponding sensor bit's capability to generate events (support) and whether it will generate events now (enabled). Note that all bitmasks have the rightmost digit as the zeroth bit, and the leftmost digit as the highest order bit. Note that you must specify 15 bits here, even if you don't use all of them. Note that you may use enable or disable in the events-enable field, and you may use scanning or no-scanning in the scanning field. For event-support, you may use per-state, entire-sensor, global or none instead of a number. For a threshold sensor, the values are: .I 0 - lower non-critical going low .I 1 - lower non-critical going high .I 2 - lower critical going low .I 3 - lower critical going high .I 4 - lower non-recoverable going low .I 5 - lower non-recoverable going high .I 6 - upper non-critical going low .I 7 - upper non-critical going high .I 8 - upper critical going low .I 9 - upper critical going high .I 1 - upper non-recoverable going low .I 1 - upper non-recoverable going high Note that the "lower going high" and "upper going low" values are not supported, since they are simply stupid. .SH ATCA OEM COMMANDS These are for emulation of special ATCA capabilities. .TP \fBatca_enable\fP The system is an ATCA system, enables the other ATCA capabilities. Note that you should do this *before* creating any MCs (this should really be first) because the MCs are set up a little differently for ATCA mode. This causes the MCs to be able to handle PICMG commands properly, sets up 2 LEDs by default, and enables proper hot-swap handling, including the blue LED. By default the blue LED supports local control and the other LEDs do not and are red. In ATCA mode, to drive the hot-swap state machine, you should use sensor_set_bit_clr_rest to set the hot-swap state. .TP \fBatca_set_site\fP \fIhardware-address\fP \fIsite-type\fP \fIsite-number\fP Sets the given values for an ATCA system, the values returned by the get address commands. .TP \fBmc_set_num_leds\fP \fImc-addr\fP \fIcount\fP Set the number of ATCA LEDs the MC has. .TP \fBmc_set_power\fP \fImc-addr\fP \fIpower\fP \fIgen-event\fP Set the ATCA power setting for the MC as its numeric value. If gen-event is non-zero, generate an event for the change. .SH "FILES" /etc/ipmi/lan.conf .SH "SEE ALSO" .BR ipmi_sim (1) .SH "KNOWN PROBLEMS" IPMI is unnecessarily complicated. Hords of capabilities are not yet implemented. .SH AUTHOR .PP Corey Minyard OpenIPMI-2.0.33/lanserv/config.c0000664000175000017500000004770014002617260013173 00000000000000/* * config.c * * MontaVista IPMI code for reading lanserv configuration files. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2002,2003,2004,2005,2012 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #include #include #include #include #include #include #include void read_persist_users(sys_data_t *sys) { unsigned int i, j; for (i = 0; i < IPMI_MAX_MCS; i++) { lmc_data_t *mc = sys->ipmb_addrs[i]; user_t *users; persist_t *p; long iv; if (!mc) continue; p = read_persist("users.mc%2.2x", sys->mc_get_ipmb(mc)); if (!p) continue; users = sys->mc_get_users(mc); for (j = 0; j <= MAX_USERS; j++) { void *data; unsigned int len; if (!read_persist_int(p, &iv, "%d.valid", j)) users[j].valid = iv; if (!read_persist_int(p, &iv, "%d.link_auth", j)) users[j].link_auth = iv; if (!read_persist_int(p, &iv, "%d.cb_only", j)) users[j].cb_only = iv; if (!read_persist_data(p, &data, &len, "%d.username", j)) { if (len == sizeof(users[j].username)) memcpy(users[j].username, data, len); free_persist_data(data); } if (!read_persist_data(p, &data, &len, "%d.passwd", j)) { if (len == sizeof(users[j].pw)) memcpy(users[j].pw, data, len); free_persist_data(data); } if (!read_persist_int(p, &iv, "%d.privilege", j)) users[j].privilege = iv; if (!read_persist_int(p, &iv, "%d.max_sessions", j)) users[j].max_sessions = iv; } free_persist(p); } } int write_persist_users(sys_data_t *sys) { unsigned int i, j; for (i = 0; i < IPMI_MAX_MCS; i++) { lmc_data_t *mc = sys->ipmb_addrs[i]; user_t *users; persist_t *p; if (!mc || !sys->mc_users_changed(mc)) continue; p = alloc_persist("users.mc%2.2x", sys->mc_get_ipmb(mc)); if (!p) return ENOMEM; users = sys->mc_get_users(mc); for (j = 0; j <= MAX_USERS; j++) { add_persist_int(p, users[j].valid, "%d.valid", j); add_persist_int(p, users[j].link_auth, "%d.link_auth", j); add_persist_int(p, users[j].cb_only, "%d.cb_only", j); add_persist_data(p, users[j].username, sizeof(users[j].username), "%d.username", j); add_persist_data(p, users[j].pw, sizeof(users[j].pw), "%d.passwd", j); add_persist_int(p, users[j].privilege, "%d.privilege", j); add_persist_int(p, users[j].max_sessions, "%d.max_sessions", j); } write_persist(p); free_persist(p); } return 0; } struct variable { char *name; char *value; struct variable *next; } *vars; /* * */ int add_variable(const char *name, char *value) { struct variable *var = vars, *last = NULL; while (var) { if (strcmp(name, var->name) == 0) break; last = var; var = var->next; } if (var) { free(var->value); } else { var = malloc(sizeof(*var)); if (!var) return ENOMEM; var->name = strdup(name); if (!var->name) { free(var); return ENOMEM; } var->next = NULL; if (last) last->next = var; else vars = var; } var->value = value; if (!var->value) return ENOMEM; return 0; } const char *find_variable(const char *name) { struct variable *var = vars; while (var) { if (strcmp(name, var->name) == 0) break; var = var->next; } if (!var) return NULL; return var->value; } /* * To parse more complex expressions, we really need to know what the * save state is. So we, unfortunately, have to create our own * version of strtok so we know what it is. */ const char * mystrtok(char *str, const char *delim, char **next) { char *pos; char *curr; if (str) curr = str; else curr = *next; /* Skip initial delimiters. */ for (;;) { const char *c = delim; if (*curr == '\0') { *next = curr; return NULL; } while (*c != '\0') { if (*c == *curr) break; c++; } if (*c == '\0') break; curr++; } pos = curr; /* Now collect until there is a delimiter. */ for (;;) { const char *c = delim; if (*curr == '\0') { *next = curr; goto out; } while (*c != '\0') { if (*c == *curr) { *curr = '\0'; *next = curr + 1; goto out; } c++; } curr++; } out: if (*pos == '$') return find_variable(pos + 1); else return pos; } int isquote(char c) { return c == '\'' || c == '"'; } int get_delim_str(char **rtokptr, char **rval, const char **err) { char *tokptr = *rtokptr; char endc; char *rv = NULL; while (isspace(*tokptr)) tokptr++; if (*tokptr == '\0') { *err = "missing string value"; return -1; } for (;;) { const char *val; if (*tokptr == '$') { char oldc; tokptr++; val = tokptr; while (*tokptr && *tokptr != '$' && !isspace(*tokptr) && !isquote(*tokptr)) { tokptr++; } oldc = *tokptr; *tokptr = '\0'; val = find_variable(val); if (!val) { if (rv) free(rv); *err = "unable to find variable"; return -1; } *tokptr = oldc; } else if (isquote(*tokptr)) { endc = *tokptr; tokptr++; val = tokptr; while (*tokptr != endc) { if (*tokptr == '\0') { if (rv) free(rv); *err = "End of line in string"; return -1; } tokptr++; } *tokptr = '\0'; tokptr++; } else { if (rv) free(rv); *err = "string value must start with '\"' or '''"; return -1; } if (rv) { char *newrv = malloc(strlen(rv) + strlen(val) + 1); if (!newrv) { free(rv); *err = "Out of memory copying string"; return -1; } strcpy(newrv, rv); strcat(newrv, val); free(rv); rv = newrv; } else { rv = strdup(val); if (!rv) { *err = "Out of memory copying string"; return -1; } } if (*tokptr == '\0' || isspace(*tokptr)) break; } *rtokptr = tokptr; *rval = rv; return 0; } int get_bool(char **tokptr, unsigned int *rval, const char **err) { const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No boolean value given"; return -1; } if (strcasecmp(tok, "true") == 0) *rval = 1; else if (strcasecmp(tok, "false") == 0) *rval = 0; else if (strcasecmp(tok, "on") == 0) *rval = 1; else if (strcasecmp(tok, "off") == 0) *rval = 0; else if (strcasecmp(tok, "yes") == 0) *rval = 1; else if (strcasecmp(tok, "no") == 0) *rval = 0; else if (strcasecmp(tok, "1") == 0) *rval = 1; else if (strcasecmp(tok, "0") == 0) *rval = 0; else { *err = "Invalid boolean value, must be 'true', 'on', 'false', or 'off'"; return -1; } return 0; } int get_uint(char **tokptr, unsigned int *rval, const char **err) { char *end; const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No integer value given"; return -1; } *rval = strtoul(tok, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } return 0; } int get_int(char **tokptr, int *rval, const char **err) { char *end; const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No integer value given"; return -1; } *rval = strtol(tok, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } return 0; } int get_uchar(char **tokptr, unsigned char *rval, const char **err) { char *end; const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No integer value given"; return -1; } *rval = strtoul(tok, &end, 0); if (*end != '\0') { *err = "Invalid integer value"; return -1; } return 0; } int get_priv(char **tokptr, unsigned int *rval, const char **err) { const char *tok = mystrtok(NULL, " \t\n", tokptr); if (!tok) { *err = "No privilege specified, must be 'callback', 'user'," " 'operator', or 'admin'"; return -1; } if (strcmp(tok, "callback") == 0) *rval = IPMI_PRIVILEGE_CALLBACK; else if (strcmp(tok, "user") == 0) *rval = IPMI_PRIVILEGE_USER; else if (strcmp(tok, "operator") == 0) *rval = IPMI_PRIVILEGE_OPERATOR; else if (strcmp(tok, "admin") == 0) *rval = IPMI_PRIVILEGE_ADMIN; else { *err = "Invalid privilege specified, must be 'callback', 'user'," " 'operator', or 'admin'"; return -1; } return 0; } int get_auths(char **tokptr, unsigned int *rval, const char **err) { const char *tok = mystrtok(NULL, " \t\n", tokptr); int val = 0; while (tok) { if (strcmp(tok, "none") == 0) val |= (1 << IPMI_AUTHTYPE_NONE); else if (strcmp(tok, "md2") == 0) val |= (1 << IPMI_AUTHTYPE_MD2); else if (strcmp(tok, "md5") == 0) val |= (1 << IPMI_AUTHTYPE_MD5); else if (strcmp(tok, "straight") == 0) val |= (1 << IPMI_AUTHTYPE_STRAIGHT); else { *err = "Invalid authorization type, must be 'none', 'md2'," " 'md5', or 'straight'"; return -1; } tok = mystrtok(NULL, " \t\n", tokptr); } *rval = val; return 0; } int read_bytes(char **tokptr, unsigned char *data, const char **err, unsigned int len) { const char *tok = mystrtok(NULL, " \t\n", tokptr); char *end; if (!tok) { *err = "Missing password or username"; return -1; } if (*tok == '"') { unsigned int end; /* Ascii PW */ tok++; end = strlen(tok) - 1; if (tok[end] != '"') { *err = "ASCII password or username doesn't end in '\"'"; return -1; } if (end > (len - 1)) end = len - 1; memcpy(data, tok, end); data[end] = '\0'; zero_extend_ascii(data, len); } else { unsigned int i; char c[3]; /* HEX pw */ if (strlen(tok) != 32) { *err = "HEX password or username not 32 HEX characters long"; return -1; } c[2] = '\0'; for (i=0; iai_addr, res0->ai_addrlen); *len = res0->ai_addrlen; freeaddrinfo(res0); } #else /* System does not support getaddrinfo, just for IPv4*/ { struct hostent *ent; struct sockaddr_in *paddr; char *end; ent = gethostbyname(s); if (!ent) { *err = "Invalid IP address specified"; return -1; } paddr = (struct sockaddr_in *)addr; paddr->sin_family = AF_INET; if (p) { paddr->sin_port = htons(strtoul(p, &end, 0)); if (*end != '\0') { *err = "Invalid IP port specified"; return -1; } } else { paddr->sin_port = htons(623); } *len = sizeof(struct sockaddr_in); } #endif return 0; } static int get_user(char **tokptr, sys_data_t *sys, const char **err) { unsigned int num; unsigned int val; int rv; rv = get_uint(tokptr, &num, err); if (rv) return rv; if (num > MAX_USERS) { *err = "User number larger than the allowed number of users"; return -1; } rv = get_bool(tokptr, &val, err); if (rv) return rv; sys->cusers[num].valid = val; rv = read_bytes(tokptr, sys->cusers[num].username, err, 16); if (rv) return rv; rv = read_bytes(tokptr, sys->cusers[num].pw, err, 20); if (rv) return rv; rv = get_priv(tokptr, &val, err); if (rv) return rv; sys->cusers[num].privilege = val; rv = get_uint(tokptr, &val, err); if (rv) return rv; sys->cusers[num].max_sessions = val; return 0; } struct dliblist { const char *file; const char *init; void *handle; struct dliblist *next; }; static struct dliblist *dlibs; int load_dynamic_libs(sys_data_t *sys, int print_version) { struct dliblist *dlib = dlibs; int (*func)(sys_data_t *sys, const char *initstr); void *handle; int err; while (dlib) { handle = dlopen(dlib->file, RTLD_NOW | RTLD_GLOBAL); if (!handle) { fprintf(stderr, "Unable to load dynamic library %s: %s\n", dlib->file, dlerror()); return EINVAL; } if (print_version) { func = dlsym(handle, "ipmi_sim_module_print_version"); if (func) { err = func(sys, dlib->init); if (err) { dlclose(handle); fprintf(stderr, "Error from module %s version print: %s\n", dlib->file, strerror(err)); return EINVAL; } } dlclose(handle); } else { func = dlsym(handle, "ipmi_sim_module_init"); if (func) { err = func(sys, dlib->init); if (err) { dlclose(handle); fprintf(stderr, "Error from module %s init: %s\n", dlib->file, strerror(err)); return EINVAL; } } dlib->handle = handle; } dlib = dlib->next; } return 0; } void post_init_dynamic_libs(sys_data_t *sys) { struct dliblist *dlib = dlibs; void (*func)(sys_data_t *sys); while (dlib) { func = dlsym(dlib->handle, "ipmi_sim_module_post_init"); if (func) func(sys); dlib = dlib->next; } } int read_config(sys_data_t *sys, char *config_file, int print_version) { FILE *f = fopen(config_file, "r"); int line; unsigned int val; char buf[MAX_CONFIG_LINE]; const char *tok; char *tokptr; int err = 0; const char *errstr; if (!f) { fprintf(stderr, "Unable to open configuration file '%s'\n", config_file); return -1; } line = 0; while (fgets(buf, sizeof(buf), f) != NULL) { line++; tok = mystrtok(buf, " \t\n", &tokptr); if (!tok || (tok[0] == '#')) continue; if (strcmp(tok, "define") == 0) { const char *varname; char *value; varname = mystrtok(NULL, " \t\n", &tokptr); if (!varname) { err = EINVAL; errstr = "No variable supplied for define"; goto next; } err = get_delim_str(&tokptr, &value, &errstr); if (err) goto next; err = add_variable(varname, value); if (err) { free(value); err = ENOMEM; errstr = "Out of memory"; goto next; } } else if (strcmp(tok, "loadlib") == 0) { char *library = NULL, *initstr = NULL; struct dliblist *dlib, *dlibp; err = get_delim_str(&tokptr, &library, &errstr); if (!err) err = get_delim_str(&tokptr, &initstr, &errstr); if (!err) { dlib = malloc(sizeof(*dlib)); if (!dlib) { err = ENOMEM; errstr = "Out of memory"; } else { dlib->file = library; dlib->init = initstr; dlib->next = NULL; if (!dlibs) { dlibs = dlib; } else { dlibp = dlibs; while (dlibp->next) dlibp = dlibp->next; dlibp->next = dlib; } } } if (err) { if (library) free((char *) library); if (initstr) free((char *) initstr); } goto next; } if (print_version) goto next; if (strcmp(tok, "startlan") == 0) { err = get_uint(&tokptr, &val, &errstr); if (!err && (val >= IPMI_MAX_CHANNELS)) { err = -1; errstr = "Channel number out of range"; } if (!err) { err = lanserv_read_config(sys, f, &line, val); } } else if (strcmp(tok, "user") == 0) { err = get_user(&tokptr, sys, &errstr); } else if (strcmp(tok, "ipmb") == 0) { err = ipmbserv_read_config(&tokptr, sys, &errstr); } else if (strcmp(tok, "serial") == 0) { err = serserv_read_config(&tokptr, sys, &errstr); } else if (strcmp(tok, "sol") == 0) { err = sys->sol_read_config(&tokptr, sys, &errstr); } else if (strcmp(tok, "chassis_control") == 0) { char *prog; err = get_delim_str(&tokptr, &prog, &errstr); if (!err) sys->set_chassis_control_prog(sys->mc, prog); } else if (strcmp(tok, "name") == 0) { err = get_delim_str(&tokptr, &sys->name, &errstr); } else if (strcmp(tok, "startcmd") == 0) { if (sys->startcmd) err = get_delim_str(&tokptr, &sys->startcmd->startcmd, &errstr); } else if (strcmp(tok, "startnow") == 0) { if (sys->startcmd) err = get_bool(&tokptr, &sys->startcmd->startnow, &errstr); } else if (strcmp(tok, "poweroff_wait") == 0) { if (sys->startcmd) err = get_uint(&tokptr, &sys->startcmd->poweroff_wait_time, &errstr); } else if (strcmp(tok, "kill_wait") == 0) { if (sys->startcmd) err = get_uint(&tokptr, &sys->startcmd->kill_wait_time, &errstr); } else if (strcmp(tok, "set_working_mc") == 0) { unsigned char ipmb; err = get_uchar(&tokptr, &ipmb, &errstr); if (!err) { lmc_data_t *mc; err = sys->mc_alloc_unconfigured(sys, ipmb, &mc); if (err == ENOMEM) { errstr = "Out of memory"; err = -1; } else if (err) { errstr = "Invalid IPMB specified"; err = -1; } else { sys->mc = mc; sys->cusers = sys->mc_get_users(mc); sys->chan_set = sys->mc_get_channelset(mc); sys->cpef = sys->mc_get_pef(mc); sys->startcmd = sys->mc_get_startcmdinfo(mc); sys->sol = sys->mc_get_sol(mc); } } } else if (strcmp(tok, "console") == 0) { err = get_sock_addr(&tokptr, &sys->console_addr, &sys->console_addr_len, NULL, SOCK_STREAM, &errstr); } else { errstr = "Invalid configuration option"; err = -1; } next: if (err) { fprintf(stderr, "Error on line %d: %s\n", line, errstr); break; } } fclose(f); if (print_version) load_dynamic_libs(sys, print_version); return err; } OpenIPMI-2.0.33/lanserv/bmc.c0000664000175000017500000006244714002617260012474 00000000000000/* * emu.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 #include #include #include #include #include #include #include #include "ipmi_sim.h" static void ipmi_mc_start_cmd(lmc_data_t *mc); const char * get_lanserv_version(void) { return PVERSION; } struct { cmd_handler_f handler; void *cb_data; } group_extension_handlers[256]; void ipmi_emu_register_group_extension_handler(uint8_t group_extension, cmd_handler_f handler, void *cb_data) { group_extension_handlers[group_extension].handler = handler; group_extension_handlers[group_extension].cb_data = cb_data; } static void handle_group_extension_netfn(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint8_t ge; if (check_msg_length(msg, 1, rdata, rdata_len)) return; ge = msg->data[0]; if (group_extension_handlers[ge].handler) group_extension_handlers[ge].handler(mc, msg, rdata, rdata_len, group_extension_handlers[ge].cb_data); else handle_invalid_cmd(mc, rdata, rdata_len); } static struct iana_handler_elem { uint32_t iana; cmd_handler_f handler; void *cb_data; struct iana_handler_elem *next; } *iana_handlers; static struct iana_handler_elem *find_iana(uint32_t iana) { struct iana_handler_elem *p = iana_handlers; while (p) { if (p->iana == iana) return p; p = p->next; } return NULL; } int ipmi_emu_register_iana_handler(uint32_t iana, cmd_handler_f handler, void *cb_data) { struct iana_handler_elem *p; if (iana > 0xffffff) return EINVAL; if (find_iana(iana)) return EAGAIN; p = malloc(sizeof(*p)); if (!p) return ENOMEM; p->iana = iana; p->handler = handler; p->cb_data = cb_data; p->next = iana_handlers; iana_handlers = p; return 0; } static void handle_iana_netfn(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { struct iana_handler_elem *p; if (check_msg_length(msg, 3, rdata, rdata_len)) return; msg->iana = msg->data[0] | (msg->data[1] << 8) | (msg->data[2] << 16); p = find_iana(msg->iana); if (!p) { handle_invalid_cmd(mc, rdata, rdata_len); goto out; } /* Remove the IANA */ memcpy(msg->data, msg->data + 3, msg->len - 3); msg->len -= 3; p->handler(mc, msg, rdata, rdata_len, p->cb_data); out: /* Insert the IANA back in. */ memcpy(rdata + 4, rdata + 1, *rdata_len); rdata[1] = msg->iana & 0xff; rdata[2] = (msg->iana >> 8) & 0xff; rdata[3] = (msg->iana >> 16) & 0xff; *rdata_len += 3; } static struct oi_iana_cmd_elem { uint8_t cmd; cmd_handler_f handler; void *cb_data; struct oi_iana_cmd_elem *next; } *oi_iana_cmds; static struct oi_iana_cmd_elem *find_oi_iana(uint8_t cmd) { struct oi_iana_cmd_elem *p = oi_iana_cmds; while (p) { if (p->cmd == cmd) return p; p = p->next; } return NULL; } static void handle_oi_iana_cmd(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { struct oi_iana_cmd_elem *p; p = find_oi_iana(msg->cmd); if (!p) { handle_invalid_cmd(mc, rdata, rdata_len); return; } p->handler(mc, msg, rdata, rdata_len, p->cb_data); } int ipmi_emu_register_oi_iana_handler(uint8_t cmd, cmd_handler_f handler, void *cb_data) { struct oi_iana_cmd_elem *p; int rv; if (find_oi_iana(cmd)) return EAGAIN; rv = ipmi_emu_register_iana_handler(OPENIPMI_IANA, handle_oi_iana_cmd, NULL); if (rv != 0 && rv != EAGAIN) return rv; p = malloc(sizeof(*p)); if (!p) return ENOMEM; p->cmd = cmd; p->handler = handler; p->cb_data = cb_data; p->next = oi_iana_cmds; oi_iana_cmds = p; return 0; } static int check_chassis_capable(lmc_data_t *mc) { return (mc->device_support & IPMI_DEVID_CHASSIS_DEVICE); } typedef struct netfn_handler_s { cmd_handler_f *handlers; void **cb_data; cmd_handler_f main_handler; void *main_handler_cb_data; int (*check_capable)(lmc_data_t *mc); } netfn_handler_t; static netfn_handler_t netfn_handlers[32] = { [IPMI_APP_NETFN >> 1] = { .handlers = app_netfn_handlers }, [IPMI_STORAGE_NETFN >> 1] = { .handlers = storage_netfn_handlers }, [IPMI_CHASSIS_NETFN >> 1] = { .handlers = chassis_netfn_handlers, .check_capable = check_chassis_capable }, [IPMI_TRANSPORT_NETFN >> 1] = { .handlers = transport_netfn_handlers }, [IPMI_SENSOR_EVENT_NETFN >> 1] = { .handlers = sensor_event_netfn_handlers }, [IPMI_GROUP_EXTENSION_NETFN >> 1] = { .main_handler = handle_group_extension_netfn }, [IPMI_OEM_GROUP_NETFN >> 1] = { .main_handler = handle_iana_netfn }, [0x30 >> 1] = { .handlers = oem0_netfn_handlers } }; int ipmi_emu_register_cmd_handler(unsigned char netfn, unsigned char cmd, cmd_handler_f handler, void *cb_data) { unsigned int ni = netfn >> 1; if (ni >= 32) return EINVAL; if (!netfn_handlers[ni].handlers) { netfn_handlers[ni].handlers = malloc(256 * sizeof(cmd_handler_f)); if (!netfn_handlers[ni].handlers) return ENOMEM; memset(netfn_handlers[ni].handlers, 0, 256 * sizeof(cmd_handler_f)); } if (!netfn_handlers[ni].cb_data) { netfn_handlers[ni].cb_data = malloc(256 * sizeof(void *)); if (!netfn_handlers[ni].cb_data) return ENOMEM; memset(netfn_handlers[ni].cb_data, 0, 256 * sizeof(void *)); } netfn_handlers[ni].cb_data[cmd] = cb_data; netfn_handlers[ni].handlers[cmd] = handler; return 0; } void ipmi_emu_tick(emu_data_t *emu, unsigned int seconds) { if (emu->atca_fru_inv_locked) { emu->atca_fru_inv_lock_timeout -= seconds; if (emu->atca_fru_inv_lock_timeout < 0) { emu->atca_fru_inv_locked = 0; free(emu->temp_fru_inv_data); emu->temp_fru_inv_data = NULL; } } if (emu->users_changed) { emu->users_changed = 0; write_persist_users(emu->sysinfo); } } #define IPMI_SEND_MSG_NO_TRACK 0x0 #define IPMI_SEND_MSG_TRACK_REQUEST 0x01 #define IPMI_SEND_MSG_SEND_RAW 0x2 #define IPMI_SEND_MSG_GET_TRACKING(v) ((v >> 6) & 0x3) void ipmi_emu_handle_msg(emu_data_t *emu, lmc_data_t *srcmc, msg_t *omsg, unsigned char *ordata, unsigned int *ordata_len) { lmc_data_t *mc; msg_t smsg, *rmsg = NULL; msg_t *msg; unsigned char *data = NULL; unsigned char *rdata; unsigned int *rdata_len; channel_t *rchan = omsg->orig_channel; if (emu->sysinfo->debug & DEBUG_MSG) emu->sysinfo->log(emu->sysinfo, DEBUG, omsg, "Receive message:"); if (omsg->netfn == IPMI_APP_NETFN && omsg->cmd == IPMI_SEND_MSG_CMD) { /* Encapsulated IPMB, do special handling. */ unsigned char slave; unsigned int data_len; if (check_msg_length(omsg, 8, ordata, ordata_len)) return; if ((omsg->data[0] & 0x3f) != 0) { ordata[0] = IPMI_INVALID_DATA_FIELD_CC; *ordata_len = 1; return; } switch (IPMI_SEND_MSG_GET_TRACKING(omsg->data[0])) { case IPMI_SEND_MSG_NO_TRACK: rchan = srcmc->channels[15]; break; case IPMI_SEND_MSG_TRACK_REQUEST: break; default: ordata[0] = IPMI_INVALID_DATA_FIELD_CC; *ordata_len = 1; return; } data = omsg->data + 1; data_len = omsg->len - 1; if (data[0] == 0) { /* Broadcast, just skip the first byte, but check len. */ data++; data_len--; if (data_len < 7) { ordata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *ordata_len = 1; return; } } slave = data[0]; mc = emu->sysinfo->ipmb_addrs[slave]; if (!mc || !mc->enabled) { ordata[0] = 0x83; /* NAK on Write */ *ordata_len = 1; return; } rmsg = malloc(sizeof(*rmsg) + IPMI_SIM_MAX_MSG_LENGTH); if (!rmsg) { ordata[0] = IPMI_OUT_OF_SPACE_CC; *ordata_len = 1; return; } *rmsg = *omsg; rmsg->data = ((unsigned char *) rmsg) + sizeof(*rmsg); rmsg->len = IPMI_SIM_MAX_MSG_LENGTH - 7; /* header and checksum */ rmsg->netfn = (data[1] & 0xfc) >> 2; rmsg->cmd = data[5]; rdata = rmsg->data + 6; rdata_len = &rmsg->len; rmsg->data[0] = emu->sysinfo->bmc_ipmb; rmsg->data[1] = ((data[1] & 0xfc) | 0x4) | (data[4] & 0x3); rmsg->data[2] = -ipmb_checksum(rdata+1, 2, 0); rmsg->data[3] = data[0]; rmsg->data[4] = (data[4] & 0xfc) | (data[1] & 0x03); rmsg->data[5] = data[5]; smsg.src_addr = omsg->src_addr; smsg.src_len = omsg->src_len; smsg.netfn = data[1] >> 2; smsg.rs_lun = data[1] & 0x3; smsg.cmd = data[5]; smsg.data = data + 6; smsg.len = data_len - 7; /* Subtract off the header and the end checksum */ smsg.channel = 0; /* IPMB channel is 0 */ smsg.orig_channel = omsg->orig_channel; smsg.sid = omsg->sid; msg = &smsg; } else { mc = srcmc; if (!mc || !mc->enabled) { ordata[0] = 0xff; *ordata_len = 1; return; } rdata = ordata; rdata_len = ordata_len; msg = omsg; } if (netfn_handlers[msg->netfn >> 1].check_capable && !netfn_handlers[msg->netfn >> 1].check_capable(mc)) handle_invalid_cmd(mc, rdata, rdata_len); else if (netfn_handlers[msg->netfn >> 1].main_handler) netfn_handlers[msg->netfn >> 1].main_handler(mc, msg, rdata, rdata_len, netfn_handlers[msg->netfn >> 1].main_handler_cb_data); else if (netfn_handlers[msg->netfn >> 1].handlers && netfn_handlers[msg->netfn >> 1].handlers[msg->cmd]) { void *cb_data = NULL; if (netfn_handlers[msg->netfn >> 1].cb_data) cb_data = netfn_handlers[msg->netfn >> 1].cb_data[msg->cmd]; netfn_handlers[msg->netfn >> 1].handlers[msg->cmd](mc, msg, rdata, rdata_len, cb_data); } else handle_invalid_cmd(mc, rdata, rdata_len); if (omsg->netfn == IPMI_APP_NETFN && omsg->cmd == IPMI_SEND_MSG_CMD) { /* An encapsulated command, put the response into the receive q. */ if (rchan->recv_in_q) { if (rchan->recv_in_q(srcmc->channels[15], rmsg)) return; } ordata[0] = 0; *ordata_len = 1; if (emu->sysinfo->debug & DEBUG_MSG) debug_log_raw_msg(emu->sysinfo, rdata, *rdata_len, "Response message:"); if (!rchan->has_recv_q) { free(rmsg); return; } rmsg->len += 6; rmsg->data[rmsg->len] = -ipmb_checksum(rmsg->data, rmsg->len, 0); rmsg->len += 1; if (rchan->recv_q_tail) { rmsg->next = rchan->recv_q_tail; rchan->recv_q_tail = rmsg; } else { rmsg->next = NULL; rchan->recv_q_head = rmsg; rchan->recv_q_tail = rmsg; if (rchan->channel_num == 15) { srcmc->msg_flags |= IPMI_MC_MSG_FLAG_RCV_MSG_QUEUE; if (rchan->set_atn) rchan->set_atn(rchan, 1, IPMI_MC_MSG_INTS_ON(mc)); } } } else if (emu->sysinfo->debug & DEBUG_MSG) debug_log_raw_msg(emu->sysinfo, ordata, *ordata_len, "Response message:"); } void is_resend_atn(channel_t *chan) { lmc_data_t *mc = chan->mc; if (chan->set_atn) chan->set_atn(chan, !!mc->msg_flags, IPMI_MC_MSG_INTS_ON(mc)); } msg_t * is_mc_get_next_recv_q(channel_t *chan) { msg_t *rv; if (!chan->recv_q_head) return NULL; rv = chan->recv_q_head; chan->recv_q_head = rv->next; if (!chan->recv_q_head) { chan->recv_q_tail = NULL; } return rv; } emu_data_t * ipmi_emu_alloc(void *user_data, ipmi_emu_sleep_cb sleeper, sys_data_t *sysinfo) { emu_data_t *data = malloc(sizeof(*data)); if (data) { memset(data, 0, sizeof(*data)); data->user_data = user_data; data->sleeper = sleeper; data->sysinfo = sysinfo; } return data; } int ipmi_emu_set_addr(emu_data_t *emu, unsigned int addr_num, unsigned char addr_type, void *addr_data, unsigned int addr_len) { emu_addr_t *addr; if (addr_num >= MAX_EMU_ADDR) return EINVAL; addr = &(emu->addr[addr_num]); if (addr_len > sizeof(addr->addr_data)) return EINVAL; emu->sysinfo->get_monotonic_time(emu->sysinfo, &emu->last_addr_change_time); addr->addr_type = addr_type; memcpy(addr->addr_data, addr_data, addr_len); addr->addr_len = addr_len; addr->valid = 1; return 0; } int ipmi_emu_clear_addr(emu_data_t *emu, unsigned int addr_num) { emu_addr_t *addr; if (addr_num >= MAX_EMU_ADDR) return EINVAL; addr = &(emu->addr[addr_num]); addr->valid = 0; return 0; } void ipmi_emu_sleep(emu_data_t *emu, struct timeval *time) { emu->sleeper(emu, time); } void * ipmi_emu_get_user_data(emu_data_t *emu) { return emu->user_data; } void ipmi_mc_destroy(lmc_data_t *mc) { sel_entry_t *entry, *n_entry; entry = mc->sel.entries; while (entry) { n_entry = entry->next; free(entry); entry = n_entry; } free(mc); } int ipmi_emu_set_mc_guid(lmc_data_t *mc, unsigned char guid[16], int force) { if (force || !mc->guid_set) memcpy(mc->guid, guid, 16); mc->guid_set = 1; return 0; } void ipmi_mc_disable(lmc_data_t *mc) { mc->enabled = 0; } void ipmi_mc_enable(lmc_data_t *mc) { unsigned int i; sys_data_t *sys = mc->sysinfo; mc->enabled = 1; for (i = 0; i < IPMI_MAX_CHANNELS; i++) { channel_t *chan = mc->channels[i]; int err = 0; if (!chan) continue; chan->smi_send = sys->csmi_send; chan->oem.user_data = sys->info; chan->alloc = sys->calloc; chan->free = sys->cfree; chan->log = sys->clog; chan->mc = mc; if (chan->medium_type == IPMI_CHANNEL_MEDIUM_8023_LAN) err = sys->lan_channel_init(sys->info, chan); else if (chan->medium_type == IPMI_CHANNEL_MEDIUM_RS232) err = sys->ser_channel_init(sys->info, chan); else if ((chan->medium_type == IPMI_CHANNEL_MEDIUM_IPMB) && ((chan->channel_num != 0) || (chan->prim_ipmb_in_cfg_file))) err = sys->ipmb_channel_init(sys->info, chan); else chan_init(chan); if (err) { chan->log(chan, SETUP_ERROR, NULL, "Unable to initialize channel for " "IPMB 0x%2.2x, channel %d: %d", mc->ipmb, chan->channel_num, err); } } if (mc->startcmd.startnow && mc->startcmd.startcmd) ipmi_mc_start_cmd(mc); } int ipmi_mc_set_num_leds(lmc_data_t *mc, unsigned int count) { if (count > MAX_LEDS) return EINVAL; if (mc->emu->atca_mode && (count < MIN_ATCA_LEDS)) return EINVAL; mc->num_leds = count; return 0; } static int init_mc(emu_data_t *emu, lmc_data_t *mc, unsigned int persist_sdr) { int err; err = mc->sysinfo->alloc_timer(mc->sysinfo, watchdog_timeout, mc, &mc->watchdog_timer); if (err) return err; if (persist_sdr && mc->has_device_sdrs) { read_mc_sdrs(mc, &mc->device_sdrs[0], "device0"); read_mc_sdrs(mc, &mc->device_sdrs[1], "device1"); read_mc_sdrs(mc, &mc->device_sdrs[2], "device2"); read_mc_sdrs(mc, &mc->device_sdrs[3], "device3"); } if (persist_sdr && (mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) read_mc_sdrs(mc, &mc->main_sdrs, "main"); return err; } static void ipmi_mc_start_cmd(lmc_data_t *mc) { if (!mc->startcmd.startcmd) { mc->sysinfo->log(mc->sysinfo, OS_ERROR, NULL, "Power on issued, no start command set"); return; } if (mc->startcmd.vmpid) { /* Already running */ /* If we are waiting for a poweroff, disable that. */ if (mc->startcmd.wait_poweroff) mc->startcmd.wait_poweroff = 0; return; } ipmi_do_start_cmd(&mc->startcmd); } static void chan_start_cmd(channel_t *chan) { ipmi_mc_start_cmd(chan->mc); } static void ipmi_mc_stop_cmd(lmc_data_t *mc, int do_it_now) { if (mc->startcmd.wait_poweroff || !mc->startcmd.vmpid) /* Already powering/powered off. */ return; if (!do_it_now) mc->startcmd.wait_poweroff = mc->startcmd.poweroff_wait_time; else mc->startcmd.wait_poweroff = 1; /* Just power off now. */ } static void chan_stop_cmd(channel_t *chan, int do_it_now) { ipmi_mc_stop_cmd(chan->mc, do_it_now); } channel_t ** is_mc_get_channelset(lmc_data_t *mc) { return mc->channels; } ipmi_sol_t * is_mc_get_sol(lmc_data_t *mc) { return &mc->sol; } unsigned char is_mc_get_ipmb(lmc_data_t *mc) { return mc->ipmb; } int is_mc_users_changed(lmc_data_t *mc) { int rv = mc->users_changed; mc->users_changed = 0; return rv; } user_t * is_mc_get_users(lmc_data_t *mc) { return mc->users; } pef_data_t * is_mc_get_pef(lmc_data_t *mc) { return &mc->pef; } startcmd_t * is_mc_get_startcmdinfo(lmc_data_t *mc) { return &mc->startcmd; } int is_mc_alloc_unconfigured(sys_data_t *sys, unsigned char ipmb, lmc_data_t **rmc) { lmc_data_t *mc; unsigned int i; mc = sys->ipmb_addrs[ipmb]; if (mc) { if (mc->configured) { sys->log(sys, SETUP_ERROR, NULL, "MC IPMB specified twice: 0x%x.", ipmb); return EBUSY; } goto out; } mc = malloc(sizeof(*mc)); if (!mc) return ENOMEM; memset(mc, 0, sizeof(*mc)); mc->ipmb = ipmb; sys->ipmb_addrs[ipmb] = mc; mc->startcmd.poweroff_wait_time = 60; mc->startcmd.kill_wait_time = 20; mc->startcmd.startnow = 0; for (i=0; i<=MAX_USERS; i++) { mc->users[i].idx = i; } mc->pef.num_event_filters = MAX_EVENT_FILTERS; for (i=0; ipef.event_filter_table[i][0] = i; mc->pef.event_filter_data1[i][0] = i; } mc->pef.num_alert_policies = MAX_ALERT_POLICIES; for (i=0; ipef.alert_policy_table[i][0] = i; mc->pef.num_alert_strings = MAX_ALERT_STRINGS; for (i=0; ipef.alert_string_keys[i][0] = i; } mc->ipmb_channel.medium_type = IPMI_CHANNEL_MEDIUM_IPMB; mc->ipmb_channel.channel_num = 0; mc->ipmb_channel.protocol_type = IPMI_CHANNEL_PROTOCOL_IPMB; mc->ipmb_channel.session_support = IPMI_CHANNEL_SESSION_LESS; mc->ipmb_channel.active_sessions = 0; mc->ipmb_channel.prim_ipmb_in_cfg_file = 0; mc->channels[0] = &mc->ipmb_channel; mc->channels[0]->log = sys->clog; out: *rmc = mc; return 0; } void handle_invalid_cmd(lmc_data_t *mc, unsigned char *rdata, unsigned int *rdata_len) { rdata[0] = IPMI_INVALID_CMD_CC; *rdata_len = 1; } int check_msg_length(msg_t *msg, unsigned int len, unsigned char *rdata, unsigned int *rdata_len) { if (msg->len < len) { rdata[0] = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; *rdata_len = 1; return 1; } return 0; } static void handle_tick(void *info, unsigned int seconds) { lmc_data_t *mc = info; if (mc->startcmd.wait_poweroff) { if (mc->startcmd.wait_poweroff > 0) { /* Waiting for the first kill */ mc->startcmd.wait_poweroff--; if (mc->startcmd.wait_poweroff == 0) { if (mc->startcmd.vmpid) ipmi_do_kill(&mc->startcmd, 0); mc->startcmd.wait_poweroff = -mc->startcmd.kill_wait_time; } } else { mc->startcmd.wait_poweroff++; if (mc->startcmd.wait_poweroff == 0 && mc->startcmd.vmpid) ipmi_do_kill(&mc->startcmd, 1); } } } static void handle_child_quit(void *info, pid_t pid) { lmc_data_t *mc = info; if (mc->startcmd.vmpid == pid) { mc->startcmd.vmpid = 0; mc->startcmd.wait_poweroff = 0; } } int ipmi_emu_add_mc(emu_data_t *emu, unsigned char ipmb, unsigned char device_id, unsigned char has_device_sdrs, unsigned char device_revision, unsigned char major_fw_rev, unsigned char minor_fw_rev, unsigned char device_support, unsigned char mfg_id[3], unsigned char product_id[2], unsigned int flags) { lmc_data_t *mc; struct timeval t; int i; sys_data_t *sys = emu->sysinfo; i = is_mc_alloc_unconfigured(sys, ipmb, &mc); if (i) return i; mc->sysinfo = sys; mc->emu = emu; mc->ipmb = ipmb; mc->device_id = device_id; mc->has_device_sdrs = has_device_sdrs; mc->device_revision = device_revision; mc->major_fw_rev = major_fw_rev; mc->minor_fw_rev = minor_fw_rev; mc->device_support = device_support; mc->dynamic_sensor_population = flags & IPMI_MC_DYNAMIC_SENSOR_POPULATION; memcpy(mc->mfg_id, mfg_id, 3); memcpy(mc->product_id, product_id, 2); /* Enable the event log by default. */ mc->global_enables = 1 << IPMI_MC_EVENT_LOG_BIT; /* Start the time at zero. */ emu->sysinfo->get_monotonic_time(emu->sysinfo, &t); mc->sel.time_offset = 0; mc->main_sdrs.time_offset = 0; mc->main_sdrs.next_entry = 1; mc->main_sdrs.flags |= IPMI_SDR_RESERVE_SDR_SUPPORTED; for (i=0; i<4; i++) { mc->device_sdrs[i].time_offset = 0; mc->device_sdrs[i].next_entry = 1; } mc->event_receiver = sys->bmc_ipmb; mc->event_receiver_lun = 0; mc->hs_sensor = NULL; if (emu->atca_mode) { mc->num_leds = 2; /* By default only blue LED has local control. */ mc->leds[0].loc_cnt = 1; mc->leds[0].loc_cnt_sup = 1; mc->leds[0].def_loc_cnt_color = 1; /* Blue LED */ mc->leds[0].def_override_color = 1; mc->leds[0].color_sup = 0x2; mc->leds[0].color = 0x1; for (i=1; ileds[i].def_loc_cnt_color = 2; mc->leds[i].def_override_color = 2; mc->leds[i].color_sup = 0x2; mc->leds[i].color = 0x2; } } if (ipmb == emu->sysinfo->bmc_ipmb) { int rv; if (!mc->channels[15]) { /* No one specified a system channel, make one up */ mc->sys_channel.medium_type = IPMI_CHANNEL_MEDIUM_SYS_INTF; mc->sys_channel.channel_num = 15; mc->sys_channel.protocol_type = IPMI_CHANNEL_PROTOCOL_KCS; mc->sys_channel.session_support = IPMI_CHANNEL_SESSION_LESS; mc->sys_channel.active_sessions = 0; mc->channels[15] = &mc->sys_channel; } mc->channels[15]->has_recv_q = 1; mc->sysinfo = emu->sysinfo; rv = init_mc(emu, mc, flags & IPMI_MC_PERSIST_SDR); if (rv) { free(mc); return rv; } } if (mc->startcmd.startcmd) { mc->child_quit_handler.info = mc; mc->child_quit_handler.handler = handle_child_quit; ipmi_register_child_quit_handler(&mc->child_quit_handler); mc->tick_handler.info = mc; mc->tick_handler.handler = handle_tick; emu->sysinfo->register_tick_handler(&mc->tick_handler); mc->channels[15]->start_cmd = chan_start_cmd; mc->channels[15]->stop_cmd = chan_stop_cmd; } mc->configured = 1; return 0; } void is_set_chassis_control_prog(lmc_data_t *mc, const char *prog) { mc->chassis_control_prog = prog; } void ipmi_mc_set_chassis_control_func(lmc_data_t *mc, int (*set)(lmc_data_t *mc, int op, unsigned char *val, void *cb_data), int (*get)(lmc_data_t *mc, int op, unsigned char *val, void *cb_data), void *cb_data) { mc->chassis_control_set_func = set; mc->chassis_control_get_func = get; mc->chassis_control_cb_data = cb_data; } void ipmi_get_product_id(lmc_data_t *mc, unsigned char product_id[2]) { memcpy(product_id, mc->product_id, 2); } int ipmi_emu_get_mc_by_addr(emu_data_t *emu, unsigned char ipmb, lmc_data_t **mc) { if (!emu->sysinfo->ipmb_addrs[ipmb]) return ENOSYS; *mc = emu->sysinfo->ipmb_addrs[ipmb]; return 0; } int ipmi_emu_set_bmc_mc(emu_data_t *emu, unsigned char ipmb) { lmc_data_t *mc; if (ipmb & 1) return EINVAL; emu->sysinfo->bmc_ipmb = ipmb; if (!ipmi_emu_get_mc_by_addr(emu, ipmb, &mc)) mc->sysinfo = emu->sysinfo; return 0; } lmc_data_t * ipmi_emu_get_bmc_mc(emu_data_t *emu) { lmc_data_t *mc; if (!ipmi_emu_get_mc_by_addr(emu, emu->sysinfo->bmc_ipmb, &mc)) return mc; return NULL; } void emu_set_debug_level(emu_data_t *emu, unsigned int debug_level) { emu->sysinfo->debug = debug_level; } OpenIPMI-2.0.33/lanserv/ipmi_checksum.c0000644000175000017500000000145512002623311014531 00000000000000 #include #include #include char buffer[65536]; int main(int argc, char *argv[]) { unsigned int sum = 0; int bytenum = 0; while (fgets(buffer, sizeof(buffer), stdin)) { char *s; s = strtok(buffer, " \n\t"); while (s) { unsigned char val; char *eos; if (*s == '\\') goto next_byte; bytenum++; if (*s == '\'') { val = *(s+1); sum += val; goto next_byte; } val = strtoul(s, &eos, 16); if (*eos != '\0') { fprintf(stderr, "Invalid byte %d\n", bytenum); return 1; } sum += val; next_byte: s = strtok(NULL, " \n\t"); } } sum &= 0xff; printf("Checksum of %d (%x) bytes is %x, to make zero is %x\n", bytenum, bytenum, sum, (0x100-sum) & 0xff); return 0; } OpenIPMI-2.0.33/lanserv/ipmi_lan.50000664000175000017500000002415713075744321013451 00000000000000.TH ipmi_lan 5 06/26/12 OpenIPMI "IPMI LAN Interface config file" .SH NAME ipmi/lan.conf \- IPMI LAN Interface config file .SH SYNOPSIS .B /etc/ipmi/lan.conf .SH DESCRIPTION The .B ipmi_sim and .B ipmilan commands are configured using this configuration file. .SH CONFIGURATION ITEMS The following fields are used in many commands: .I "boolean" May be "\fBtrue\fP", "\fBfalse\fP", "\fBon\fP" or "\fBoff\fP". .I "priv" An IPMI privilege level. This may be "\fBcallback\fP", "\fBuser\fP", "\fBoperator\fP", or "\fBadmin\fP". .I "auth" An IPMI authorization type. This may be "\fBnone\fP" for no authentication, "\fBstraight\fP" for straight, in-the-clear password authentication, "\fBmd2\fP" for use MD2 message digest authentication, or "\fBmd5\fP" for using MD5 message digest authentication. .SH FILE STRUCTURE Blank lines and lines starting with `#' are ignored. .PP The following commands are allowed the configuration file: .TP \fBname\fP \fI"name"\fP Set a name for the BMC. This will control other things, like the default value of the ipmi_sim startup command file and the place where persistent data is stored. .TP \fBuser\fP \fIusernum\fP \fIenabled\fP \fIusername\fP \fIpassword\fP \fImax-priv\fP \fImax-session\fP .I usernum specifies the user number for the user. Note that user number \fB0\fP is invalid, and user number \fB1\fP is the special "anonymous" user, whose username is ignored. This value may be up to \fB63\fP, the maximum possible IPMI user. If you want anonymous access, you .B must have a user number \fB1\fI. .I enabled is a boolean that specified whether the user is enabled or not. .I username specifies the name of the user, specified as a name. .I password specifies the password of the user, specified as a name. .I max-priv specifies the maximum privilege level allowed for the user. .I max.sessions specifies the maximum number of session the user may open. .TP \fBstartcmd\fP \fI"cmd"\fP specifies a command to execute when a power on is requested. This lets a virtual machine be started that can then connect back to the simulator. The simulator does management of the process here, and the power on state of the process depends on if the process exists or not. If a poweroff is requested, if the process is connected to a VM serial interface, a graceful shutdown is first requested. If the process does not terminate in a specified amount of time, a SIGTERM is sent to the process. The SIGTERM is sent immediately if there is no connection. If the process doesn't go way in another specified amount of time, a SIGKILL is sent. .TP \fBstartnow\fPtrue|false\fI\fP If true, start the startcmd at the startup of the simulator. Otherwise wait until a poweron is issued. .TP \fBpoweroff_wait\fP \fIseconds\fP specifies the amount of time to wait for the startcmd to do a graceful shutdown on a powerdown request. The simulator will send a request to the target, wait this amount of time, and then do a SIGTERM kill on the process. If this is zero, a SIGTERM will not be done (nor will a SIGKILL). Note that if the simulator does not have a connection to the VM, the graceful shutdown is skipped and a SIGTERM is done immediately. Default time is 60 seconds. .TP \fBkill_wait\fP \fIseconds\fP specifies the amount of time to wait for SIGTERM to kill the process. If the process does not terminate in this period of time, send a SIGKILL kill. If this is zero, don't send the SIGKILL. Default time is 20 seconds. .TP \fBconsole\fP \fIaddress\fP \fIport\fP specifies that a console port be opened at the given address and port. You can telnet to the console and execute emulation commands. Note that this is a pretty huge security hole, it should only be used for debugging in a captive environment. .TP \fBserial\fP \fIchannel\fP \fIaddr\fP \fIport\fP [\fIoption\fP [\fIoption\fP [...]]] .I channel specifies the channel number or type. This may be \fBkcs\fP, \fBsmic\fP, or \fBbt\fP or it may be 15. Currently, only the system interface channel (channel 15) is supported for serial interfaces, if the others are specified it is channel 15 and the given interface is reported in channel configuration commands. .I addr specifies the IP address to listen on for connections. .I port specifies the port to listen on for connections. Valid options are: .I codec name specifies which codec to use on the serial port. Valid options are: \fBTerminalMode\fP, \fBDirect\fP, \fBRadisysAscii\fP, and \fBVM\fP. The first three are implementations of IPMI serial interfaces on certain systems and might be used for simulations of that system. The \fBVM\fP is probably the most interesting; it is designed to be used with a virtual machine like qemu. .I oem name specified implementation of some OEM custom commands and options on the interface. Valid options oare \fBPigeonPoint\fP and \fBRadisys\fP. .I attn c1[,c2[...]] specifies a list of characters, separated by commas, to use as the attention character on the interface. Generally the default is correct. The characters are specified as decimal, octal, or hex digits in C style. .I ipmb addr specifies the IPMI address of the interface. The default, 0x20, is usually correct, but when emulating ATCA systems this might be required. .TP \fBsol\fP \fIdevice\fP \fIdefault_baud\fP [\fIhistory=size[,backupfile=filename]\fP] [\fIhistoryfru=frunum\fP] Allow a Serial Over LAN (SOL) connection to the given device. This will be over interface 1 for the MC. .I device is the full path to the device name. It can also be in the form "tcp:address:port" or "telnet:address:port" to do connections over tcp (without or with telnet processing). This is useful for providing SOL access to qemu ports. .I default_baud sets the initial default baud rate to use. This is overriden by the persistent SOL settings. .I history creates a history device on SOL interface 2. The size is the size of the buffer. Data from the device is stored in the history buffer all the time. Connecting to SOL interface 2 will cause the full history buffer to be dumped. If .I backupfile is specified, then the history is made persistent. However, it is only stored when a catchable signal or normal shutdown is done, so a poweroff or fatal signal will cause the data to be lost. .I historyfru makes the history available via the given FRU number on the MC. Note that if the connection fails to come up, the simulator will continue to try to connect. This way you can fix UDP serial ports or qemu sessions and it will automatically reconnect. .TP \fBloadlib\fP \fI"module"\fP [\fI"options"\fP] Load the given shared object into the program. .I "module" is the full path to the module. It must be in quotes. .I "options" is an optional string in quotes that passes options to the module. The contents of the string are not specified, the module defines that. The module may have a number of functions that are called: .I ipmi_sim_module_print_version(sys_data_t *sys, char *options) is called when ipmi_sim is started with the version print option. This way the versions of all loaded modules may be printed. The module should print it's version. You must provide this function. .I ipmi_sim_module_init(sys_data_t *sys, char *options) is called after the configuration file is read and before any other initialization is done. The module should do most of its initialization here. You must provide this function. .I ipmi_sim_module_post_init(sys_data_t *sys) is called after ipmi_sim has finished initializing. This function is optional. .P The .I sys parameter is used for most functions interfacing to the main ipmi_sim code, like logging, timers, and a few of the MC calls. The contents are opaque to the module. .TP \fBstartlan\fP \fIchannel\fP Starts a LAN configuration area. This specifies the settings for a LAN connection using the given channel. This may be specified more than once in a file to support multiple LAN connections. Commands following this, up to \fBendlan\fP, are LAN-specific commands listed below. .I channel specifies the channel to set the LAN configuration for. .SH LAN CONFIGURATION COMMANDS The following commands are only valid inside a \fBstartlen\fP area. .TP \fBaddr\fP \fIIP-address\fP [\fIUDP-port\fP] .I IP-address specifies the IP address to use for an IP port. Up to 4 addresses may be specified. If no address is specified, it defaults to one port at \fB0.0.0.0\fP (for every address on the machine) at port \fB623\fP. .I UDP-port specifies an optional port to listen on. It defaults to \fB623\fP (the standard port). .TP .BI PEF_alerting\ boolean Turn PEF alerting on or off (not currently supported). .TP .BI per_msg_auth\ boolean Turn per-message authentication on or off. .TP .BI priv_limit\ priv The maximum privilege allowed on this interface. .TP \fBallowed_auths_callback\fP [\fIauth\fP [\fIauth\fP [...]]] .I auth specifies allowed authorization levels for the callback privilege level. Only the levels specified on this line are allowed for the authorization level. If this line is not present, callback authorization cannot be used. .TP \fBallowed_auths_user\fP [\fIauth\fP [\fIauth\fP [...]]] .I auth specifies allowed authorization levels for the user privilege level. Only the levels specified on this line are allowed for the authorization level. If this line is not present, user authorization cannot be used. .TP \fBallowed_auths_operator\fP [\fIauth\fP [\fIauth\fP [...]]] .I auth specifies allowed authorization levels for the operator privilege level. Only the levels specified on this line are allowed for the authorization level. If this line is not present, operator authorization cannot be used. .TP \fBallowed_auths_admin\fP [\fIauth\fP [\fIauth\fP [...]]] .I auth specifies allowed authorization levels for the admin privilege level. Only the levels specified on this line are allowed for the authorization level. If this line is not present, user authorization cannot be used. .TP \fBguid\fP \fIname\fP Allows the 16-byte GUID for the IPMI LAN connection to be specified. If this is not specified, then the GUID command is not supported. .SH "FILES" /etc/ipmi_lan.conf .SH "SEE ALSO" .BR ipmilan (8), ipmi_sim (1) .SH "KNOWN PROBLEMS" IPMI is unnecessarily complicated. .SH AUTHOR .PP Corey Minyard OpenIPMI-2.0.33/lanserv/lanserv_asf.c0000644000175000017500000001040313136646135014227 00000000000000/* * lanserv_asf.c * * MontaVista IPMI RMCP/ASF LAN interface protocol engine * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include /* Deal with multi-byte data, RMCP (big-endian) style. */ #if 0 /* These are not currently used. */ static unsigned int rmcp_get_uint16(uint8_t *data) { return (data[1] | (data[0] << 8)); } static void rmcp_set_uint16(uint8_t *data, int val) { data[1] = val & 0xff; data[0] = (val >> 8) & 0xff; } #endif static unsigned int rmcp_get_uint32(uint8_t *data) { return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24)); } static void rmcp_set_uint32(uint8_t *data, int val) { data[3] = val & 0xff; data[2] = (val >> 8) & 0xff; data[1] = (val >> 16) & 0xff; data[0] = (val >> 24) & 0xff; } #define ASF_IANA 4542 void handle_asf(lanserv_data_t *lan, uint8_t *data, int len, void *from_addr, int from_len) { uint8_t rsp[28]; struct iovec vec[1]; if (len < 12) return; if (rmcp_get_uint32(data+4) != ASF_IANA) return; /* Not ASF IANA */ if (data[8] != 0x80) return; /* Not a presence ping. */ /* Ok, it's a valid RMCP/ASF Presence Ping, start working on the response. */ rsp[0] = 6; rsp[1] = 0; rsp[2] = 0xff; /* No ack, the ack is not required, so we don't do it. */ rsp[3] = 6; /* ASF class */ rmcp_set_uint32(rsp+4, ASF_IANA); rsp[8] = 0x40; /* Presence Pong */ rsp[9] = data[9]; /* Message tag */ rsp[10] = 0; rsp[11] = 16; /* Data length */ rmcp_set_uint32(rsp+12, ASF_IANA); /* no special capabilities */ rmcp_set_uint32(rsp+16, 0); /* no special capabilities */ rsp[20] = 0x81; /* We support IPMI */ rsp[21] = 0x0; /* No supported interactions */ memset(rsp+22, 0, 6); /* Reserved. */ vec[0].iov_base = rsp; vec[0].iov_len = 28; /* Return the response. */ lan->send_out(lan, vec, 1, from_addr, from_len); } OpenIPMI-2.0.33/lanserv/priv_table.c0000664000175000017500000005432514002617260014056 00000000000000/* * priv_table.h * * MontaVista IPMI interface, table and associated code for figuring * out priviledge levels for messages. * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #define PRIV_ENTRY(c,u,o,a) ((c) | ((u)<<4) | ((o)<<8) | ((a)<<12)) typedef unsigned short priv_val; #define n 0 /* No priviledge (blank entry) */ #define s 1 /* System interface only. */ #define p 2 /* No authentication required. */ #define X 3 /* Permitted */ #define b 4 /* bmc-only */ #define h 5 /* special send-message handling is needed. */ #define i 6 /* Special set system boot options handling. */ #define b2 7 /* bmc-only, can be sent to a serial channel when serial port sharing is used and actvating the SOL payload causes the serial session to be terminated. */ /* An entry marked with a comment at the beginning has special handling. */ /* Chassis netfn (0x00) */ static priv_val chassis_privs[] = { PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHASSIS_CAPABILITIES_CMD 0x00 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHASSIS_STATUS_CMD 0x01 */ PRIV_ENTRY(n,n,X,X), /* IPMI_CHASSIS_CONTROL_CMD 0x02 */ PRIV_ENTRY(n,n,X,X), /* IPMI_CHASSIS_RESET_CMD 0x03 */ PRIV_ENTRY(n,n,X,X), /* IPMI_CHASSIS_IDENTIFY_CMD 0x04 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_CHASSIS_CAPABILITIES_CMD 0x05 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_POWER_RESTORE_POLICY_CMD 0x06 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SYSTEM_RESTART_CAUSE_CMD 0x07 */ /**/PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SYSTEM_BOOT_OPTIONS_CMD 0x08 */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_SYSTEM_BOOT_OPTIONS_CMD 0x09 */ PRIV_ENTRY(n,n,n,X), /* 0x0a */ PRIV_ENTRY(n,n,n,X), /* 0x0b */ PRIV_ENTRY(n,n,n,X), /* 0x0c */ PRIV_ENTRY(n,n,n,X), /* 0x0d */ PRIV_ENTRY(n,n,n,X), /* 0x0e */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_POH_COUNTER_CMD 0x0f */ }; /* Bridge netfn (0x02) */ static priv_val bridge_privs[] = { PRIV_ENTRY(n,X,X,X), /* IPMI_GET_BRIDGE_STATE_CMD 0x00 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_BRIDGE_STATE_CMD 0x01 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_ICMB_ADDRESS_CMD 0x02 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_ICMB_ADDRESS_CMD 0x03 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_BRIDGE_PROXY_ADDRESS_CMD 0x04 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_BRIDGE_STATISTICS_CMD 0x05 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_ICMB_CAPABILITIES_CMD 0x06 */ PRIV_ENTRY(n,n,n,X), /* 0x07 */ PRIV_ENTRY(n,n,X,X), /* IPMI_CLEAR_BRIDGE_STATISTICS_CMD 0x08 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_BRIDGE_PROXY_ADDRESS_CMD 0x09 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_ICMB_CONNECTOR_INFO_CMD 0x0a */ PRIV_ENTRY(n,X,X,X), /* IPMI_SET_ICMB_CONNECTOR_INFO_CMD 0x0b */ PRIV_ENTRY(n,X,X,X), /* IPMI_SEND_ICMB_CONNECTION_ID_CMD 0x0c */ PRIV_ENTRY(n,n,n,X), /* 0x0d */ PRIV_ENTRY(n,n,n,X), /* 0x0e */ PRIV_ENTRY(n,n,n,X), /* 0x0f */ PRIV_ENTRY(n,n,X,X), /* IPMI_PREPARE_FOR_DISCOVERY_CMD 0x10 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_ADDRESSES_CMD 0x11 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_DISCOVERED_CMD 0x12 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHASSIS_DEVICE_ID_CMD 0x13 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_CHASSIS_DEVICE_ID_CMD 0x14 */ PRIV_ENTRY(n,n,n,X), /* 0x15 */ PRIV_ENTRY(n,n,n,X), /* 0x16 */ PRIV_ENTRY(n,n,n,X), /* 0x17 */ PRIV_ENTRY(n,n,n,X), /* 0x18 */ PRIV_ENTRY(n,n,n,X), /* 0x19 */ PRIV_ENTRY(n,n,n,X), /* 0x1a */ PRIV_ENTRY(n,n,n,X), /* 0x1b */ PRIV_ENTRY(n,n,n,X), /* 0x1c */ PRIV_ENTRY(n,n,n,X), /* 0x1d */ PRIV_ENTRY(n,n,n,X), /* 0x1e */ PRIV_ENTRY(n,n,n,X), /* 0x1f */ PRIV_ENTRY(n,n,X,X), /* IPMI_BRIDGE_REQUEST_CMD 0x20 */ PRIV_ENTRY(n,n,X,X), /* IPMI_BRIDGE_MESSAGE_CMD 0x21 */ PRIV_ENTRY(n,n,n,X), /* 0x22 */ PRIV_ENTRY(n,n,n,X), /* 0x23 */ PRIV_ENTRY(n,n,n,X), /* 0x24 */ PRIV_ENTRY(n,n,n,X), /* 0x25 */ PRIV_ENTRY(n,n,n,X), /* 0x26 */ PRIV_ENTRY(n,n,n,X), /* 0x27 */ PRIV_ENTRY(n,n,n,X), /* 0x28 */ PRIV_ENTRY(n,n,n,X), /* 0x29 */ PRIV_ENTRY(n,n,n,X), /* 0x2a */ PRIV_ENTRY(n,n,n,X), /* 0x2b */ PRIV_ENTRY(n,n,n,X), /* 0x2c */ PRIV_ENTRY(n,n,n,X), /* 0x2d */ PRIV_ENTRY(n,n,n,X), /* 0x2e */ PRIV_ENTRY(n,n,n,X), /* 0x2f */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_EVENT_COUNT_CMD 0x30 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_EVENT_DESTINATION_CMD 0x31 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_EVENT_RECEPTION_STATE_CMD 0x32 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SEND_ICMB_EVENT_MESSAGE_CMD 0x33 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_EVENT_DESTIATION_CMD 0x34 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_EVENT_RECEPTION_STATE_CMD 0x35 */ #if 0 /* Handled as administrator by virtue of not being there. */ /**/PRIV_ENTRY(n,n,n,X), /* IPMI_ERROR_REPORT_CMD 0xff */ #endif }; /* Sensor/Event netfn (0x04) */ static priv_val sensor_privs[] = { PRIV_ENTRY(n,n,n,X), /* IPMI_SET_EVENT_RECEIVER_CMD 0x00 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_EVENT_RECEIVER_CMD 0x01 */ PRIV_ENTRY(n,n,X,X), /* IPMI_PLATFORM_EVENT_CMD 0x02 */ PRIV_ENTRY(n,n,n,X), /* 0x03 */ PRIV_ENTRY(n,n,n,X), /* 0x04 */ PRIV_ENTRY(n,n,n,X), /* 0x05 */ PRIV_ENTRY(n,n,n,X), /* 0x06 */ PRIV_ENTRY(n,n,n,X), /* 0x07 */ PRIV_ENTRY(n,n,n,X), /* 0x08 */ PRIV_ENTRY(n,n,n,X), /* 0x09 */ PRIV_ENTRY(n,n,n,X), /* 0x0a */ PRIV_ENTRY(n,n,n,X), /* 0x0b */ PRIV_ENTRY(n,n,n,X), /* 0x0c */ PRIV_ENTRY(n,n,n,X), /* 0x0d */ PRIV_ENTRY(n,n,n,X), /* 0x0e */ PRIV_ENTRY(n,n,n,X), /* 0x0f */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_PEF_CAPABILITIES_CMD 0x10 */ PRIV_ENTRY(n,n,n,X), /* IPMI_ARM_PEF_POSTPONE_TIMER_CMD 0x11 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_PEF_CONFIG_PARMS_CMD 0x12 */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_PEF_CONFIG_PARMS_CMD 0x13 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_LAST_PROCESSED_EVENT_ID_CMD 0x14 */ PRIV_ENTRY(n,n,n,X), /* IPMI_GET_LAST_PROCESSED_EVENT_ID_CMD 0x15 */ PRIV_ENTRY(n,n,n,X), /* IPMI_ALERT_IMMEDIATE_CMD 0x16 */ PRIV_ENTRY(p,p,p,p), /* IPMI_PET_ACKNOWLEDGE_CMD 0x17 */ PRIV_ENTRY(n,n,n,X), /* 0x18 */ PRIV_ENTRY(n,n,n,X), /* 0x19 */ PRIV_ENTRY(n,n,n,X), /* 0x1a */ PRIV_ENTRY(n,n,n,X), /* 0x1b */ PRIV_ENTRY(n,n,n,X), /* 0x1c */ PRIV_ENTRY(n,n,n,X), /* 0x1d */ PRIV_ENTRY(n,n,n,X), /* 0x1e */ PRIV_ENTRY(n,n,n,X), /* 0x1f */ /* Note, the following are "I I I I" in the table, but I think that's wrong. */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_DEVICE_SDR_INFO_CMD 0x20 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_DEVICE_SDR_CMD 0x21 */ PRIV_ENTRY(n,X,X,X), /* IPMI_RESERVE_DEVICE_SDR_REPOSITORY_CMD 0x22 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_READING_FACTORS_CMD 0x23 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SENSOR_HYSTERESIS_CMD 0x24 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_HYSTERESIS_CMD 0x25 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SENSOR_THRESHOLD_CMD 0x26 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_THRESHOLD_CMD 0x27 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SENSOR_EVENT_ENABLE_CMD 0x28 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_EVENT_ENABLE_CMD 0x29 */ PRIV_ENTRY(n,n,X,X), /* IPMI_REARM_SENSOR_EVENTS_CMD 0x2a */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_EVENT_STATUS_CMD 0x2b */ PRIV_ENTRY(n,n,n,X), /* 0x2c */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_READING_CMD 0x2d */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SENSOR_TYPE_CMD 0x2e */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SENSOR_TYPE_CMD 0x2f */ }; /* App netfn (0x06) */ static priv_val app_privs[] = { PRIV_ENTRY(n,n,n,X), /* 0x00 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_DEVICE_ID_CMD 0x01 */ PRIV_ENTRY(n,n,n,X), /* IPMI_COLD_RESET_CMD 0x02 */ PRIV_ENTRY(n,n,n,X), /* IPMI_WARM_RESET_CMD 0x03 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SELF_TEST_RESULTS_CMD 0x04 */ PRIV_ENTRY(n,n,n,X), /* IPMI_MANUFACTURING_TEST_ON_CMD 0x05 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_ACPI_POWER_STATE_CMD 0x06 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_ACPI_POWER_STATE_CMD 0x07 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_DEVICE_GUID_CMD 0x08 */ PRIV_ENTRY(n,n,n,X), /* 0x09 */ PRIV_ENTRY(n,n,n,X), /* 0x0a */ PRIV_ENTRY(n,n,n,X), /* 0x0b */ PRIV_ENTRY(n,n,n,X), /* 0x0c */ PRIV_ENTRY(n,n,n,X), /* 0x0d */ PRIV_ENTRY(n,n,n,X), /* 0x0e */ PRIV_ENTRY(n,n,n,X), /* 0x0f */ PRIV_ENTRY(n,n,n,X), /* 0x10 */ PRIV_ENTRY(n,n,n,X), /* 0x11 */ PRIV_ENTRY(n,n,n,X), /* 0x12 */ PRIV_ENTRY(n,n,n,X), /* 0x13 */ PRIV_ENTRY(n,n,n,X), /* 0x14 */ PRIV_ENTRY(n,n,n,X), /* 0x15 */ PRIV_ENTRY(n,n,n,X), /* 0x16 */ PRIV_ENTRY(n,n,n,X), /* 0x17 */ PRIV_ENTRY(n,n,n,X), /* 0x18 */ PRIV_ENTRY(n,n,n,X), /* 0x19 */ PRIV_ENTRY(n,n,n,X), /* 0x1a */ PRIV_ENTRY(n,n,n,X), /* 0x1b */ PRIV_ENTRY(n,n,n,X), /* 0x1c */ PRIV_ENTRY(n,n,n,X), /* 0x1d */ PRIV_ENTRY(n,n,n,X), /* 0x1e */ PRIV_ENTRY(n,n,n,X), /* 0x1f */ PRIV_ENTRY(n,n,n,X), /* 0x20 */ PRIV_ENTRY(n,n,n,X), /* 0x21 */ PRIV_ENTRY(n,n,X,X), /* IPMI_RESET_WATCHDOG_TIMER_CMD 0x22 */ PRIV_ENTRY(n,n,n,X), /* 0x23 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_WATCHDOG_TIMER_CMD 0x24 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_WATCHDOG_TIMER_CMD 0x25 */ PRIV_ENTRY(n,n,n,X), /* 0x26 */ PRIV_ENTRY(n,n,n,X), /* 0x27 */ PRIV_ENTRY(n,n,n,X), /* 0x28 */ PRIV_ENTRY(n,n,n,X), /* 0x29 */ PRIV_ENTRY(n,n,n,X), /* 0x2a */ PRIV_ENTRY(n,n,n,X), /* 0x2b */ PRIV_ENTRY(n,n,n,X), /* 0x2c */ PRIV_ENTRY(n,n,n,X), /* 0x2d */ PRIV_ENTRY(s,s,s,s), /* IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f */ PRIV_ENTRY(s,s,s,s), /* IPMI_CLEAR_MSG_FLAGS_CMD 0x30 */ PRIV_ENTRY(s,s,s,s), /* IPMI_GET_MSG_FLAGS_CMD 0x31 */ PRIV_ENTRY(s,s,s,s), /* IPMI_ENABLE_MESSAGE_CHANNEL_RCV_CMD 0x32 */ PRIV_ENTRY(s,s,s,s), /* IPMI_GET_MSG_CMD 0x33 */ /**/PRIV_ENTRY(n,h,X,X), /* IPMI_SEND_MSG_CMD 0x34 */ PRIV_ENTRY(s,s,s,s), /* IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_BT_INTERFACE_CAPABILITIES_CMD 0x36 */ PRIV_ENTRY(p,p,p,p), /* IPMI_GET_SYSTEM_GUID_CMD 0x37 */ PRIV_ENTRY(p,p,p,p), /* IPMI_GET_CHANNEL_AUTH_CAPABILITIES_CMD 0x38 */ PRIV_ENTRY(p,p,p,p), /* IPMI_GET_SESSION_CHALLENGE_CMD 0x39 */ PRIV_ENTRY(p,p,p,p), /* IPMI_ACTIVATE_SESSION_CMD 0x3a */ PRIV_ENTRY(n,X,X,X), /* IPMI_SET_SESSION_PRIVILEGE_CMD 0x3b */ PRIV_ENTRY(X,X,X,X), /* IPMI_CLOSE_SESSION_CMD 0x3c */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SESSION_INFO_CMD 0x3d */ PRIV_ENTRY(n,n,n,X), /* 0x3e */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_AUTHCODE_CMD 0x3f */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_CHANNEL_ACCESS_CMD 0x40 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHANNEL_ACCESS_CMD 0x41 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHANNEL_INFO_CMD 0x42 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_USER_ACCESS_CMD 0x43 */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_USER_ACCESS_CMD 0x44 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_USER_NAME_CMD 0x45 */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_USER_NAME_CMD 0x46 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_USER_PASSWORD_CMD 0x47 */ PRIV_ENTRY(X,X,X,X), /* IPMI_ACTIVATE_PAYLOAD_CMD 0x48 */ PRIV_ENTRY(X,X,X,X), /* IPMI_DEACTIVATE_PAYLOAD_CMD 0x49 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_PAYLOAD_ACTIVATION_STATUS_CMD 0x4a */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_PAYLOAD_INSTANCE_INFO_CMD 0x4b */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_USER_PAYLOAD_ACCESS_CMD 0x4c */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_USER_PAYLOAD_ACCESS_CMD 0x4d */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHANNEL_PAYLOAD_SUPPORT_CMD 0x4e */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHANNEL_PAYLOAD_VERSION_CMD 0x4f */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_CHANNEL_OEM_PAYLOAD_INFO_CMD 0x50 */ PRIV_ENTRY(n,n,n,X), /* 0x51 */ PRIV_ENTRY(n,n,X,X), /* IPMI_MASTER_READ_WRITE_CMD 0x52 */ PRIV_ENTRY(n,n,n,X), /* 0x53 */ PRIV_ENTRY(p,p,p,p), /* IPMI_GET_CHANNEL_CIPHER_SUITES_CMD 0x54 */ PRIV_ENTRY(n,X,X,X), /* IPMI_SUSPEND_RESUME_PAYLOAD_ENCRYPTION_CMD 0x55 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_CHANNEL_SECURITY_KEY_CMD 0x56 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD 0x57 */ }; /* Firmware netfn (0x08) */ static priv_val firmware_privs[] = { PRIV_ENTRY(n,n,n,X), /* 0x00 */ }; /* Storage netfn (0x0a) */ static priv_val storage_privs[] = { PRIV_ENTRY(n,n,n,X), /* 0x00 */ PRIV_ENTRY(n,n,n,X), /* 0x01 */ PRIV_ENTRY(n,n,n,X), /* 0x02 */ PRIV_ENTRY(n,n,n,X), /* 0x03 */ PRIV_ENTRY(n,n,n,X), /* 0x04 */ PRIV_ENTRY(n,n,n,X), /* 0x05 */ PRIV_ENTRY(n,n,n,X), /* 0x06 */ PRIV_ENTRY(n,n,n,X), /* 0x07 */ PRIV_ENTRY(n,n,n,X), /* 0x08 */ PRIV_ENTRY(n,n,n,X), /* 0x09 */ PRIV_ENTRY(n,n,n,X), /* 0x0a */ PRIV_ENTRY(n,n,n,X), /* 0x0b */ PRIV_ENTRY(n,n,n,X), /* 0x0c */ PRIV_ENTRY(n,n,n,X), /* 0x0d */ PRIV_ENTRY(n,n,n,X), /* 0x0e */ PRIV_ENTRY(n,n,n,X), /* 0x0f */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_FRU_INVENTORY_AREA_INFO_CMD 0x10 */ PRIV_ENTRY(n,X,X,X), /* IPMI_READ_FRU_DATA_CMD 0x11 */ PRIV_ENTRY(n,n,X,X), /* IPMI_WRITE_FRU_DATA_CMD 0x12 */ PRIV_ENTRY(n,n,n,X), /* 0x13 */ PRIV_ENTRY(n,n,n,X), /* 0x14 */ PRIV_ENTRY(n,n,n,X), /* 0x15 */ PRIV_ENTRY(n,n,n,X), /* 0x16 */ PRIV_ENTRY(n,n,n,X), /* 0x17 */ PRIV_ENTRY(n,n,n,X), /* 0x18 */ PRIV_ENTRY(n,n,n,X), /* 0x19 */ PRIV_ENTRY(n,n,n,X), /* 0x1a */ PRIV_ENTRY(n,n,n,X), /* 0x1b */ PRIV_ENTRY(n,n,n,X), /* 0x1c */ PRIV_ENTRY(n,n,n,X), /* 0x1d */ PRIV_ENTRY(n,n,n,X), /* 0x1e */ PRIV_ENTRY(n,n,n,X), /* 0x1f */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SDR_REPOSITORY_INFO_CMD 0x20 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SDR_REPOSITORY_ALLOC_INFO_CMD 0x21 */ PRIV_ENTRY(n,X,X,X), /* IPMI_RESERVE_SDR_REPOSITORY_CMD 0x22 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SDR_CMD 0x23 */ PRIV_ENTRY(n,n,X,X), /* IPMI_ADD_SDR_CMD 0x24 */ PRIV_ENTRY(n,n,X,X), /* IPMI_PARTIAL_ADD_SDR_CMD 0x25 */ PRIV_ENTRY(n,n,X,X), /* IPMI_DELETE_SDR_CMD 0x26 */ PRIV_ENTRY(n,n,X,X), /* IPMI_CLEAR_SDR_REPOSITORY_CMD 0x27 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SDR_REPOSITORY_TIME_CMD 0x28 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SDR_REPOSITORY_TIME_CMD 0x29 */ PRIV_ENTRY(n,n,X,X), /* IPMI_ENTER_SDR_REPOSITORY_UPDATE_CMD 0x2a */ PRIV_ENTRY(n,n,X,X), /* IPMI_EXIT_SDR_REPOSITORY_UPDATE_CMD 0x2b */ PRIV_ENTRY(n,n,X,X), /* IPMI_RUN_INITIALIZATION_AGENT_CMD 0x2c */ PRIV_ENTRY(n,n,n,X), /* 0x2d */ PRIV_ENTRY(n,n,n,X), /* 0x2e */ PRIV_ENTRY(n,n,n,X), /* 0x2f */ PRIV_ENTRY(n,n,n,X), /* 0x30 */ PRIV_ENTRY(n,n,n,X), /* 0x31 */ PRIV_ENTRY(n,n,n,X), /* 0x32 */ PRIV_ENTRY(n,n,n,X), /* 0x33 */ PRIV_ENTRY(n,n,n,X), /* 0x34 */ PRIV_ENTRY(n,n,n,X), /* 0x35 */ PRIV_ENTRY(n,n,n,X), /* 0x36 */ PRIV_ENTRY(n,n,n,X), /* 0x37 */ PRIV_ENTRY(n,n,n,X), /* 0x38 */ PRIV_ENTRY(n,n,n,X), /* 0x39 */ PRIV_ENTRY(n,n,n,X), /* 0x3a */ PRIV_ENTRY(n,n,n,X), /* 0x4b */ PRIV_ENTRY(n,n,n,X), /* 0x3c */ PRIV_ENTRY(n,n,n,X), /* 0x3d */ PRIV_ENTRY(n,n,n,X), /* 0x3e */ PRIV_ENTRY(n,n,n,X), /* 0x3f */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SEL_INFO_CMD 0x40 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SEL_ALLOCATION_INFO_CMD 0x41 */ PRIV_ENTRY(n,X,X,X), /* IPMI_RESERVE_SEL_CMD 0x42 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SEL_ENTRY_CMD 0x43 */ PRIV_ENTRY(n,n,X,X), /* IPMI_ADD_SEL_ENTRY_CMD 0x44 */ PRIV_ENTRY(n,n,X,X), /* IPMI_PARTIAL_ADD_SEL_ENTRY_CMD 0x45 */ PRIV_ENTRY(n,n,X,X), /* IPMI_DELETE_SEL_ENTRY_CMD 0x46 */ PRIV_ENTRY(n,n,X,X), /* IPMI_CLEAR_SEL_CMD 0x47 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SEL_TIME_CMD 0x48 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_SEL_TIME_CMD 0x49 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_AUXILIARY_LOG_STATUS_CMD 0x5a */ PRIV_ENTRY(n,n,X,X), /* IPMI_SET_AUXILIARY_LOG_STATUS_CMD 0x5b */ }; /* Transport netfn (0x0c) */ static priv_val transport_privs[] = { PRIV_ENTRY(n,n,n,X), /* 0x00 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_LAN_CONFIG_PARMS_CMD 0x01 */ PRIV_ENTRY(n,n,X,X), /* IPMI_GET_LAN_CONFIG_PARMS_CMD 0x02 */ PRIV_ENTRY(n,n,X,X), /* IPMI_SUSPEND_BMC_ARPS_CMD 0x03 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_IP_UDP_RMCP_STATS_CMD 0x04 */ PRIV_ENTRY(n,n,n,X), /* 0x05 */ PRIV_ENTRY(n,n,n,X), /* 0x06 */ PRIV_ENTRY(n,n,n,X), /* 0x07 */ PRIV_ENTRY(n,n,n,X), /* 0x08 */ PRIV_ENTRY(n,n,n,X), /* 0x09 */ PRIV_ENTRY(n,n,n,X), /* 0x0a */ PRIV_ENTRY(n,n,n,X), /* 0x0b */ PRIV_ENTRY(n,n,n,X), /* 0x0c */ PRIV_ENTRY(n,n,n,X), /* 0x0d */ PRIV_ENTRY(n,n,n,X), /* 0x0e */ PRIV_ENTRY(n,n,n,X), /* 0x0f */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_SERIAL_MODEM_CONFIG_CMD 0x10 */ PRIV_ENTRY(n,n,n,X), /* IPMI_GET_SERIAL_MODEM_CONFIG_CMD 0x11 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_SERIAL_MODEM_MUX_CMD 0x12 */ PRIV_ENTRY(n,n,n,X), /* IPMI_GET_TAP_RESPONSE_CODES_CMD 0x13 */ PRIV_ENTRY(s,s,s,s), /* IPMI_SET_PPP_UDP_PROXY_XMIT_DATA_CMD 0x14 */ PRIV_ENTRY(s,s,s,s), /* IPMI_GET_PPP_UDP_PROXY_XMIT_DATA_CMD 0x15 */ PRIV_ENTRY(s,s,s,s), /* IPMI_SEND_PPP_UDP_PROXY_PACKET_CMD 0x16 */ PRIV_ENTRY(s,s,s,s), /* IPMI_GET_PPP_UDP_PROXY_RECV_DATA_CMD 0x17 */ PRIV_ENTRY(b,b,b,b), /* IPMI_SERIAL_MODEM_CONN_ACTIVE_CMD 0x18 */ PRIV_ENTRY(X,n,X,X), /* IPMI_CALLBACK_CMD 0x19 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_USER_CALLBACK_OPTIONS_CMD 0x1a */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_USER_CALLBACK_OPTIONS_CMD 0x1b */ PRIV_ENTRY(n,n,n,X), /* 0x1c */ PRIV_ENTRY(n,n,n,X), /* 0x1d */ PRIV_ENTRY(n,n,n,X), /* 0x1e */ PRIV_ENTRY(n,n,n,X), /* 0x1f */ PRIV_ENTRY(b2,b2,b2,b2), /* IPMI_SOL_ACTIVATING_CMD 0x20 */ PRIV_ENTRY(n,n,n,X), /* IPMI_SET_SOL_CONFIGURATION_PARAMETERS 0x21 */ PRIV_ENTRY(n,X,X,X), /* IPMI_GET_SOL_CONFIGURATION_PARAMETERS 0x22 */ }; static struct { int size; priv_val *vals; } priv_table[7] = { { sizeof(chassis_privs)/sizeof(priv_val), chassis_privs }, { sizeof(bridge_privs)/sizeof(priv_val), bridge_privs }, { sizeof(sensor_privs)/sizeof(priv_val), sensor_privs }, { sizeof(app_privs)/sizeof(priv_val), app_privs }, { sizeof(firmware_privs)/sizeof(priv_val), firmware_privs }, { sizeof(storage_privs)/sizeof(priv_val), storage_privs }, { sizeof(transport_privs)/sizeof(priv_val), transport_privs }, }; int ipmi_cmd_permitted(unsigned char priv, unsigned char netfn, unsigned char cmd) { int perm; /* Priviledges */ if ((priv < IPMI_PRIVILEGE_CALLBACK) || (priv > IPMI_PRIVILEGE_ADMIN)) return IPMI_PRIV_INVALID; if ((netfn > IPMI_TRANSPORT_NETFN) || (cmd >= priv_table[netfn>>1].size)) { /* All things not in the table are assumed to take administrator priviledge. */ if (priv == IPMI_PRIVILEGE_ADMIN) return IPMI_PRIV_PERMITTED; else return IPMI_PRIV_DENIED; } perm = priv_table[netfn>>1].vals[cmd]; /* Extract the permissions for the given privilege from the permission word. The tables are 0-based, but the first valid privilege is 1, thus the (priv - 1) here. */ perm >>= 4 * (priv - 1); perm &= 0xf; switch (perm) { case n: case s: case b: case b2: return 0; case p: case X: return IPMI_PRIV_PERMITTED; case h: return IPMI_PRIV_SEND; case i: return IPMI_PRIV_BOOT; } return IPMI_PRIV_DENIED; } OpenIPMI-2.0.33/lanserv/bmc_storage.c0000664000175000017500000013724714002617260014221 00000000000000/* * bmc_storage.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 #include #include #include #include #include #include #include /* * SEL handling commands. */ #define IPMI_SEL_SUPPORTS_DELETE (1 << 3) #define IPMI_SEL_SUPPORTS_RESERVE (1 << 1) #define IPMI_SEL_SUPPORTS_GET_ALLOC_INFO (1 << 0) static sel_entry_t * find_sel_event_by_recid(lmc_data_t *mc, uint16_t record_id, sel_entry_t **prev) { sel_entry_t *entry; sel_entry_t *p_entry = NULL; entry = mc->sel.entries; while (entry) { if (record_id == entry->record_id) break; p_entry = entry; entry = entry->next; } if (prev) *prev = p_entry; return entry; } static int handle_sel(const char *name, void *data, unsigned int len, void *cb_data) { sel_entry_t *e, *n; lmc_data_t *mc = cb_data; if (len != 16) { mc->sysinfo->log(mc->sysinfo, INFO, NULL, "Got invalid SEL entry for %2.2x, name is %s", is_mc_get_ipmb(mc), name); goto out; } n = malloc(sizeof(*n)); if (!n) return ENOMEM; memcpy(n->data, data, 16); n->record_id = n->data[0] | (n->data[1] << 8); n->next = NULL; e = mc->sel.entries; if (!e) mc->sel.entries = n; else { while (e->next) e = e->next; e->next = n; } mc->sel.count++; out: return ITER_PERSIST_CONTINUE; } static int handle_sel_time(const char *name, long val, void *cb_data) { lmc_data_t *mc = cb_data; if (strcmp(name, "last_add_time") == 0) mc->sel.last_add_time = val; else if (strcmp(name, "last_erase_time") == 0) mc->sel.last_erase_time = val; return ITER_PERSIST_CONTINUE; } int ipmi_mc_enable_sel(lmc_data_t *mc, int max_entries, unsigned char flags) { persist_t *p; mc->sel.entries = NULL; mc->sel.count = 0; mc->sel.max_count = max_entries; mc->sel.last_add_time = 0; mc->sel.last_erase_time = 0; mc->sel.flags = flags & 0xb; mc->sel.reservation = 0; mc->sel.next_entry = 1; p = read_persist("sel.%2.2x", is_mc_get_ipmb(mc)); if (!p) return 0; iterate_persist(p, mc, handle_sel, handle_sel_time); free_persist(p); return 0; } static void rewrite_sels(lmc_data_t *mc) { persist_t *p = NULL; sel_entry_t *e; int err; p = alloc_persist("sel.%2.2x", is_mc_get_ipmb(mc)); if (!p) { err = ENOMEM; goto out_err; } err = add_persist_int(p, mc->sel.last_add_time, "last_add_time"); if (err) goto out_err; err = add_persist_int(p, mc->sel.last_erase_time, "last_erase_time"); if (err) goto out_err; for (e = mc->sel.entries; e; e = e->next) { err = add_persist_data(p, e->data, 16, "%d", e->record_id); if (err) goto out_err; } err = write_persist(p); if (err) goto out_err; free_persist(p); return; out_err: mc->sysinfo->log(mc->sysinfo, OS_ERROR, NULL, "Unable to write persistent SELs for MC %d: %d", is_mc_get_ipmb(mc), err); if (p) free_persist(p); } int ipmi_mc_add_to_sel(lmc_data_t *mc, unsigned char record_type, unsigned char event[13], unsigned int *recid) { sel_entry_t *e; struct timeval t; uint16_t start_record_id; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) return ENOTSUP; if (mc->sel.count >= mc->sel.max_count) { mc->sel.flags |= 0x80; return EAGAIN; } e = malloc(sizeof(*e)); if (!e) return ENOMEM; /* FIXME - this is inefficient, but simple */ e->record_id = mc->sel.next_entry; mc->sel.next_entry++; start_record_id = e->record_id; while ((mc->sel.next_entry == 0) || find_sel_event_by_recid(mc, e->record_id, NULL)) { e->record_id++; if (e->record_id == start_record_id) { free(e); return EAGAIN; } mc->sel.next_entry++; } mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); ipmi_set_uint16(e->data, e->record_id); e->data[2] = record_type; if (record_type < 0xe0) { ipmi_set_uint32(e->data+3, t.tv_sec + mc->sel.time_offset); memcpy(e->data+7, event+4, 9); } else { memcpy(e->data+3, event, 13); } e->next = NULL; if (!mc->sel.entries) { mc->sel.entries = e; } else { sel_entry_t *f = mc->sel.entries; while (f->next) f = f->next; f->next = e; } mc->sel.count++; mc->sel.last_add_time = t.tv_sec + mc->sel.time_offset; if (recid) *recid = e->record_id; rewrite_sels(mc); return 0; } void mc_new_event(lmc_data_t *mc, unsigned char record_type, unsigned char event[13]) { unsigned int recid; int rv; if (IPMI_MC_EVENT_LOG_ENABLED(mc)) { rv = ipmi_mc_add_to_sel(mc, record_type, event, &recid); if (rv) recid = 0xffff; } else recid = 0xffff; if (!mc->ev_in_q && IPMI_MC_EVENT_MSG_BUF_ENABLED(mc)) { channel_t *chan = mc->channels[15]; mc->ev_in_q = 1; ipmi_set_uint16(mc->evq, recid); mc->evq[2] = record_type; memcpy(mc->evq + 3, event, 13); mc->msg_flags |= IPMI_MC_MSG_FLAG_EVT_BUF_FULL; if (chan->set_atn) chan->set_atn(chan, 1, IPMI_MC_EVBUF_FULL_INT_ENABLED(mc)); } } static void handle_get_sel_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } memset(rdata, 0, 15); rdata[1] = 0x51; ipmi_set_uint16(rdata+2, mc->sel.count); ipmi_set_uint16(rdata+4, (mc->sel.max_count - mc->sel.count) * 16); ipmi_set_uint32(rdata+6, mc->sel.last_add_time); ipmi_set_uint32(rdata+10, mc->sel.last_erase_time); rdata[14] = mc->sel.flags; *rdata_len = 15; } static void handle_get_sel_allocation_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->sel.flags & IPMI_SEL_SUPPORTS_GET_ALLOC_INFO)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } memset(rdata, 0, 10); ipmi_set_uint16(rdata+1, mc->sel.max_count * 16); ipmi_set_uint16(rdata+3, 16); ipmi_set_uint32(rdata+5, (mc->sel.max_count - mc->sel.count) * 16); ipmi_set_uint32(rdata+7, (mc->sel.max_count - mc->sel.count) * 16); rdata[9] = 1; *rdata_len = 10; } static void handle_reserve_sel(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->sel.flags & IPMI_SEL_SUPPORTS_RESERVE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->sel.reservation++; if (mc->sel.reservation == 0) mc->sel.reservation++; rdata[0] = 0; ipmi_set_uint16(rdata+1, mc->sel.reservation); *rdata_len = 3; } static void handle_get_sel_entry(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint16_t record_id; int offset; int count; sel_entry_t *entry; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (mc->sel.flags & IPMI_SEL_SUPPORTS_RESERVE) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->sel.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } record_id = ipmi_get_uint16(msg->data+2); offset = msg->data[4]; count = msg->data[5]; if (offset >= 16) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (record_id == 0) { entry = mc->sel.entries; } else if (record_id == 0xffff) { entry = mc->sel.entries; if (entry) { while (entry->next) { entry = entry->next; } } } else { entry = find_sel_event_by_recid(mc, record_id, NULL); } if (entry == NULL) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } rdata[0] = 0; if (entry->next) ipmi_set_uint16(rdata+1, entry->next->record_id); else { rdata[1] = 0xff; rdata[2] = 0xff; } if ((offset+count) > 16) count = 16 - offset; memcpy(rdata+3, entry->data+offset, count); *rdata_len = count + 3; } static void handle_add_sel_entry(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int rv; unsigned int r; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 16, rdata, rdata_len)) return; rv = ipmi_mc_add_to_sel(mc, msg->data[2], msg->data+3, &r); if (rv == EAGAIN) { rdata[0] = IPMI_OUT_OF_SPACE_CC; } else if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; } else { rdata[0] = 0; ipmi_set_uint16(rdata+1, r); } *rdata_len = 3; } static void handle_delete_sel_entry(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint16_t record_id; sel_entry_t *entry, *p_entry; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->sel.flags & IPMI_SEL_SUPPORTS_DELETE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 4, rdata, rdata_len)) return; if (mc->sel.flags & IPMI_SEL_SUPPORTS_RESERVE) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->sel.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } record_id = ipmi_get_uint16(msg->data+2); if (record_id == 0) { entry = mc->sel.entries; p_entry = NULL; } else if (record_id == 0xffff) { entry = mc->sel.entries; p_entry = NULL; if (entry) { while (entry->next) { p_entry = entry; entry = entry->next; } } } else { entry = find_sel_event_by_recid(mc, record_id, &p_entry); } if (!entry) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } if (p_entry) p_entry->next = entry->next; else mc->sel.entries = entry->next; /* Clear the overflow flag. */ mc->sel.flags &= ~0x80; rdata[0] = 0; ipmi_set_uint16(rdata+1, entry->record_id); *rdata_len = 3; mc->sel.count--; free(entry); rewrite_sels(mc); } static void handle_clear_sel(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { sel_entry_t *entry, *n_entry; unsigned char op; struct timeval t; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (mc->sel.flags & IPMI_SEL_SUPPORTS_RESERVE) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->sel.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } if ((msg->data[2] != 'C') || (msg->data[3] != 'L') || (msg->data[4] != 'R')) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } op = msg->data[5]; if ((op != 0) && (op != 0xaa)) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[1] = 1; if (op == 0xaa) { entry = mc->sel.entries; mc->sel.entries = NULL; mc->sel.count = 0; while (entry) { n_entry = entry->next; free(entry); entry = n_entry; } } mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); mc->sel.last_erase_time = t.tv_sec + mc->sel.time_offset; rdata[0] = 0; *rdata_len = 2; /* Clear the overflow flag. */ mc->sel.flags &= ~0x80; rewrite_sels(mc); } static void handle_get_sel_time(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { struct timeval t; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); rdata[0] = 0; ipmi_set_uint32(rdata+1, t.tv_sec + mc->sel.time_offset); *rdata_len = 5; } static void handle_set_sel_time(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { struct timeval t; if (!(mc->device_support & IPMI_DEVID_SEL_DEVICE)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 4, rdata, rdata_len)) return; mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); mc->sel.time_offset = ipmi_get_uint32(msg->data) - t.tv_sec; rdata[0] = 0; *rdata_len = 1; } /* * SDR handling commands */ #define IPMI_SDR_OVERFLOW_FLAG (1 << 7) #define IPMI_SDR_GET_MODAL(v) (((v) >> 5) & 0x3) #define IPMI_SDR_MODAL_UNSPECIFIED 0 #define IPMI_SDR_NON_MODAL_ONLY 1 #define IPMI_SDR_MODAL_ONLY 2 #define IPMI_SDR_MODAL_BOTH 3 sdr_t * find_sdr_by_recid(sdrs_t *sdrs, uint16_t record_id, sdr_t **prev) { sdr_t *entry; sdr_t *p_entry = NULL; entry = sdrs->sdrs; while (entry) { if (record_id == entry->record_id) break; p_entry = entry; entry = entry->next; } if (prev) *prev = p_entry; return entry; } sdr_t * new_sdr_entry(sdrs_t *sdrs, unsigned char length) { sdr_t *entry; uint16_t start_recid; start_recid = sdrs->next_entry; while (find_sdr_by_recid(sdrs, sdrs->next_entry, NULL)) { sdrs->next_entry++; if (sdrs->next_entry == 0xffff) sdrs->next_entry = 1; if (sdrs->next_entry == start_recid) return NULL; } entry = malloc(sizeof(*entry)); if (!entry) return NULL; entry->data = malloc(length + 6); if (!entry->data) { free(entry); return NULL; } entry->record_id = sdrs->next_entry; sdrs->next_entry++; ipmi_set_uint16(entry->data, entry->record_id); entry->length = length + 6; entry->next = NULL; return entry; } static void rewrite_sdrs(lmc_data_t *mc, sdrs_t *sdrs) { persist_t *p = NULL; sdr_t *sdr; int err; p = alloc_persist("sdr.%2.2x.main", is_mc_get_ipmb(mc)); if (!p) { err = ENOMEM; goto out_err; } err = add_persist_int(p, sdrs->last_add_time, "last_add_time"); if (err) goto out_err; err = add_persist_int(p, sdrs->last_erase_time, "last_erase_time"); if (err) goto out_err; for (sdr = sdrs->sdrs; sdr; sdr = sdr->next) { unsigned int recid = ipmi_get_uint16(sdr->data); err = add_persist_data(p, sdr->data, sdr->length, "%d", recid); if (err) goto out_err; } err = write_persist(p); if (err) goto out_err; free_persist(p); return; out_err: mc->sysinfo->log(mc->sysinfo, OS_ERROR, NULL, "Unable to write persistent SDRs for MC %d: %d", is_mc_get_ipmb(mc), err); if (p) free_persist(p); } void add_sdr_entry(lmc_data_t *mc, sdrs_t *sdrs, sdr_t *entry) { sdr_t *p; struct timeval t; entry->next = NULL; p = sdrs->sdrs; if (!p) sdrs->sdrs = entry; else { while (p->next) p = p->next; p->next = entry; } mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); sdrs->last_add_time = t.tv_sec + mc->main_sdrs.time_offset; sdrs->sdr_count++; rewrite_sdrs(mc, sdrs); } static void free_sdr(sdr_t *sdr) { free(sdr->data); free(sdr); } static int handle_sdr(const char *name, void *data, unsigned int len, void *cb_data) { sdr_t *sdr, *p; sdrs_t *sdrs = cb_data; sdr = new_sdr_entry(sdrs, len); if (!sdr) return ENOMEM; memcpy(sdr->data, data, len); sdr->next = NULL; p = sdrs->sdrs; if (!p) sdrs->sdrs = sdr; else { while (p->next) p = p->next; p->next = sdr; } sdrs->sdr_count++; return ITER_PERSIST_CONTINUE; } static int handle_sdr_time(const char *name, long val, void *cb_data) { sdrs_t *sdrs = cb_data; if (strcmp(name, "last_add_time") == 0) sdrs->last_add_time = val; else if (strcmp(name, "last_erase_time") == 0) sdrs->last_erase_time = val; return ITER_PERSIST_CONTINUE; } void read_mc_sdrs(lmc_data_t *mc, sdrs_t *sdrs, const char *sdrtype) { persist_t *p; p = read_persist("sdr.%2.2x.%s", is_mc_get_ipmb(mc), sdrtype); if (!p) return; iterate_persist(p, sdrs, handle_sdr, handle_sdr_time); free_persist(p); } int ipmi_mc_add_main_sdr(lmc_data_t *mc, unsigned char *data, unsigned int data_len) { sdr_t *entry; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) return ENOSYS; if ((data_len < 5) || (data_len != (((unsigned int) data[4]) + 5))) return EINVAL; entry = new_sdr_entry(&mc->main_sdrs, data_len); if (!entry) return ENOMEM; memcpy(entry->data+2, data+2, data_len-2); add_sdr_entry(mc, &mc->main_sdrs, entry); return 0; } int ipmi_mc_add_device_sdr(lmc_data_t *mc, unsigned char lun, unsigned char *data, unsigned int data_len) { struct timeval t; sdr_t *entry; if (lun >= 4) return EINVAL; if (!(mc->has_device_sdrs)) { return ENOSYS; } entry = new_sdr_entry(&mc->device_sdrs[lun], data_len); if (!entry) return ENOMEM; add_sdr_entry(mc, &mc->device_sdrs[lun], entry); memcpy(entry->data+2, data+2, data_len-2); mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); mc->sensor_population_change_time = t.tv_sec + mc->main_sdrs.time_offset; mc->lun_has_sensors[lun] = 1; mc->num_sensors_per_lun[lun]++; return 0; } static void handle_get_sdr_repository_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned int space; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } rdata[0] = 0; rdata[1] = 0x51; ipmi_set_uint16(rdata+2, mc->main_sdrs.sdr_count); space = MAX_SDR_LENGTH * (MAX_NUM_SDRS - mc->main_sdrs.sdr_count); if (space > 0xfffe) space = 0xfffe; ipmi_set_uint16(rdata+4, space); ipmi_set_uint32(rdata+6, mc->main_sdrs.last_add_time); ipmi_set_uint32(rdata+10, mc->main_sdrs.last_erase_time); rdata[14] = mc->main_sdrs.flags; *rdata_len = 15; } static void handle_get_sdr_repository_alloc_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->main_sdrs.flags & IPMI_SDR_GET_SDR_ALLOC_INFO_SDR_SUPPORTED)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } rdata[0] = 0; ipmi_set_uint16(rdata+1, MAX_NUM_SDRS); ipmi_set_uint16(rdata+3, MAX_SDR_LENGTH); ipmi_set_uint16(rdata+5, MAX_NUM_SDRS - mc->main_sdrs.sdr_count); ipmi_set_uint16(rdata+7, MAX_NUM_SDRS - mc->main_sdrs.sdr_count); rdata[9] = 1; *rdata_len = 10; } static void handle_reserve_sdr_repository(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->main_sdrs.flags & IPMI_SDR_RESERVE_SDR_SUPPORTED)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->main_sdrs.reservation++; if (mc->main_sdrs.reservation == 0) mc->main_sdrs.reservation++; rdata[0] = 0; ipmi_set_uint16(rdata+1, mc->main_sdrs.reservation); *rdata_len = 3; /* If adding an SDR and the reservation changes, we have to destroy the working SDR addition. */ if (mc->part_add_sdr) { free_sdr(mc->part_add_sdr); mc->part_add_sdr = NULL; } } static void handle_get_sdr(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint16_t record_id; unsigned int offset; unsigned int count; sdr_t *entry; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (mc->main_sdrs.flags & IPMI_SDR_RESERVE_SDR_SUPPORTED) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->main_sdrs.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } record_id = ipmi_get_uint16(msg->data+2); offset = msg->data[4]; count = msg->data[5]; if (record_id == 0) { entry = mc->main_sdrs.sdrs; } else if (record_id == 0xffff) { entry = mc->main_sdrs.sdrs; if (entry) { while (entry->next) { entry = entry->next; } } } else { entry = find_sdr_by_recid(&mc->main_sdrs, record_id, NULL); } if (entry == NULL) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } if (offset >= entry->length) { rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC; *rdata_len = 1; return; } if ((offset+count) > entry->length) count = entry->length - offset; if (count+3 > *rdata_len) { /* Too much data to put into response. */ rdata[0] = IPMI_CANNOT_RETURN_REQ_LENGTH_CC; *rdata_len = 1; return; } rdata[0] = 0; if (entry->next) ipmi_set_uint16(rdata+1, entry->next->record_id); else { rdata[1] = 0xff; rdata[2] = 0xff; } memcpy(rdata+3, entry->data+offset, count); *rdata_len = count + 3; } static void handle_add_sdr(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int modal; sdr_t *entry; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } modal = IPMI_SDR_GET_MODAL(mc->main_sdrs.flags); if ((modal == IPMI_SDR_NON_MODAL_ONLY) && !mc->in_update_mode) { rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC; *rdata_len = 1; return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (msg->len != (unsigned int) msg->data[5] + 6) { rdata[0] = 0x80; /* Length is invalid. */ *rdata_len = 1; return; } entry = new_sdr_entry(&mc->main_sdrs, msg->data[5]); if (!entry) { rdata[0] = IPMI_OUT_OF_SPACE_CC; *rdata_len = 1; return; } add_sdr_entry(mc, &mc->main_sdrs, entry); memcpy(entry->data+2, msg->data+2, entry->length-2); rdata[0] = 0; ipmi_set_uint16(rdata+1, entry->record_id); *rdata_len = 3; } static void handle_partial_add_sdr(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint16_t record_id; unsigned int offset; int modal; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (!(mc->main_sdrs.flags & IPMI_SDR_PARTIAL_ADD_SDR_SUPPORTED)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (mc->main_sdrs.flags & IPMI_SDR_RESERVE_SDR_SUPPORTED) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->main_sdrs.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } modal = IPMI_SDR_GET_MODAL(mc->main_sdrs.flags); if ((modal == IPMI_SDR_NON_MODAL_ONLY) && !mc->in_update_mode) { rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC; *rdata_len = 1; return; } offset = msg->data[4]; record_id = ipmi_get_uint16(rdata+2); if (record_id == 0) { /* New add. */ if (check_msg_length(msg, 12, rdata, rdata_len)) return; if (offset != 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (msg->len > (unsigned int) msg->data[11] + 12) { rdata[0] = 0x80; /* Invalid data length */ *rdata_len = 1; return; } if (mc->part_add_sdr) { /* Still working on a previous one, return an error and abort. */ free_sdr(mc->part_add_sdr); mc->part_add_sdr = NULL; rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } mc->part_add_sdr = new_sdr_entry(&mc->main_sdrs, msg->data[11]); memcpy(mc->part_add_sdr->data+2, msg->data+8, msg->len - 8); mc->part_add_next = msg->len - 8; } else { if (!mc->part_add_next) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } if (offset != mc->part_add_next) { free_sdr(mc->part_add_sdr); mc->part_add_sdr = NULL; rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if ((offset + msg->len - 6) > mc->part_add_sdr->length) { free_sdr(mc->part_add_sdr); mc->part_add_sdr = NULL; rdata[0] = 0x80; /* Invalid data length */ *rdata_len = 1; return; } memcpy(mc->part_add_sdr->data+offset, msg->data+6, msg->len-6); mc->part_add_next += msg->len - 6; } if ((msg->data[5] & 0xf) == 1) { /* End of the operation. */ if (mc->part_add_next != mc->part_add_sdr->length) { free_sdr(mc->part_add_sdr); mc->part_add_sdr = NULL; rdata[0] = 0x80; /* Invalid data length */ *rdata_len = 1; return; } add_sdr_entry(mc, &mc->main_sdrs, mc->part_add_sdr); mc->part_add_sdr = NULL; } rdata[0] = 0; *rdata_len = 1; } void iterate_sdrs(lmc_data_t *mc, sdrs_t *sdrs, int (*func)(lmc_data_t *mc, unsigned char *sdr, unsigned int len, void *cb_data), void *cb_data) { sdr_t *entry; for (entry = sdrs->sdrs; entry; entry = entry->next) func(mc, entry->data, entry->length, cb_data); } static void handle_delete_sdr(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { uint16_t record_id; sdr_t *entry, *p_entry; struct timeval t; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 4, rdata, rdata_len)) return; if (mc->main_sdrs.flags & IPMI_SDR_RESERVE_SDR_SUPPORTED) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->main_sdrs.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } record_id = ipmi_get_uint16(rdata+2); if (record_id == 0) { entry = mc->main_sdrs.sdrs; p_entry = NULL; } else if (record_id == 0xffff) { entry = mc->main_sdrs.sdrs; p_entry = NULL; if (entry) { while (entry->next) { p_entry = entry; entry = entry->next; } } } else { entry = find_sdr_by_recid(&mc->main_sdrs, record_id, &p_entry); } if (!entry) { rdata[0] = IPMI_NOT_PRESENT_CC; *rdata_len = 1; return; } if (p_entry) p_entry->next = entry->next; else mc->main_sdrs.sdrs = entry->next; rdata[0] = 0; ipmi_set_uint16(rdata+1, entry->record_id); *rdata_len = 3; free_sdr(entry); mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); mc->main_sdrs.last_erase_time = t.tv_sec + mc->main_sdrs.time_offset; mc->main_sdrs.sdr_count--; rewrite_sdrs(mc, &mc->main_sdrs); } static void handle_clear_sdr_repository(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { sdr_t *entry, *n_entry; struct timeval t; unsigned char op; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 6, rdata, rdata_len)) return; if (mc->main_sdrs.flags & IPMI_SDR_RESERVE_SDR_SUPPORTED) { uint16_t reservation = ipmi_get_uint16(msg->data+0); if ((reservation != 0) && (reservation != mc->main_sdrs.reservation)) { rdata[0] = IPMI_INVALID_RESERVATION_CC; *rdata_len = 1; return; } } if ((msg->data[2] != 'C') || (msg->data[3] != 'L') || (msg->data[4] != 'R')) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } op = msg->data[5]; if ((op != 0) && (op != 0xaa)) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[1] = 1; if (op == 0) { entry = mc->main_sdrs.sdrs; while (entry) { n_entry = entry->next; free_sdr(entry); entry = n_entry; } } rdata[0] = 0; *rdata_len = 2; mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); mc->main_sdrs.last_erase_time = t.tv_sec + mc->main_sdrs.time_offset; rewrite_sdrs(mc, &mc->main_sdrs); } static void handle_get_sdr_repository_time(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { struct timeval t; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); rdata[0] = 0; ipmi_set_uint32(rdata+1, t.tv_sec + mc->main_sdrs.time_offset); *rdata_len = 5; } static void handle_set_sdr_repository_time(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { struct timeval t; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } if (check_msg_length(msg, 4, rdata, rdata_len)) return; mc->emu->sysinfo->get_monotonic_time(mc->emu->sysinfo, &t); mc->main_sdrs.time_offset = ipmi_get_uint32(msg->data) - t.tv_sec; rdata[0] = 0; *rdata_len = 1; } static void handle_enter_sdr_repository_update(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int modal; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } modal = IPMI_SDR_GET_MODAL(mc->main_sdrs.flags); if ((modal == IPMI_SDR_MODAL_UNSPECIFIED) || (modal == IPMI_SDR_NON_MODAL_ONLY)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->in_update_mode = 1; rdata[0] = 0; *rdata_len = 1; } static void handle_exit_sdr_repository_update(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { int modal; if (!(mc->device_support & IPMI_DEVID_SDR_REPOSITORY_DEV)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } modal = IPMI_SDR_GET_MODAL(mc->main_sdrs.flags); if ((modal == IPMI_SDR_MODAL_UNSPECIFIED) || (modal == IPMI_SDR_NON_MODAL_ONLY)) { handle_invalid_cmd(mc, rdata, rdata_len); return; } mc->in_update_mode = 0; rdata[0] = 0; *rdata_len = 1; } /* * FRU Inventory handling */ fru_data_t * find_fru(lmc_data_t *mc, unsigned int devid) { fru_data_t *fru = mc->frulist; while (fru && fru->devid != devid) fru = fru->next; return fru; } int ipmi_mc_set_frudata_handler(lmc_data_t *mc, unsigned int devid, get_frudata_f handler, free_frudata_f freefunc) { fru_data_t *fru = find_fru(mc, devid); if (!fru) return EINVAL; fru->get = handler; fru->free = freefunc; return 0; } static void fru_session_closed(lmc_data_t *mc, uint32_t session_id, void *cb_data) { fru_session_t *ses = cb_data; fru_data_t *fru = ses->fru; if (fru->sessions == ses) { fru->sessions = ses->next; } else { fru_session_t *p = fru->sessions; while (p && p->next != ses) p = p->next; if (p && p->next != ses) p->next = ses->next; } fru->free(mc, ses->data_to_free); free(ses); } static void handle_get_fru_inventory_area_info(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char devid; fru_data_t *fru; unsigned int size; unsigned char *data; int rv; if (check_msg_length(msg, 1, rdata, rdata_len)) return; devid = msg->data[0]; fru = find_fru(mc, devid); if (!fru) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (fru->get) { channel_t *channel; fru_session_t *ses; int link_in = 0; ses = fru->sessions; while (ses) { if (ses->sid == msg->sid) break; ses = ses->next; } if (!ses) { ses = malloc(sizeof(*ses)); if (!ses) { rdata[0] = IPMI_OUT_OF_SPACE_CC; *rdata_len = 1; return; } memset(ses, 0, sizeof(*ses)); ses->sid = msg->sid; ses->fru = fru; link_in = 1; } /* Set up to free the FRU data when the session closes. */ channel = msg->orig_channel; rv = channel->set_associated_mc(channel, msg->sid, 0, mc, NULL, fru_session_closed, ses); if (rv == EBUSY) { rdata[0] = IPMI_NODE_BUSY_CC; *rdata_len = 1; return; } else if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } data = fru->get(mc, &size); if (!data) { channel->set_associated_mc(channel, msg->sid, 0, NULL, NULL, NULL, NULL); rdata[0] = IPMI_OUT_OF_SPACE_CC; *rdata_len = 1; return; } if (ses->data_to_free) fru->free(mc, ses->data_to_free); ses->data_to_free = data; if (size > 65535) { ses->data = data + (size - 65535); size = 65535; } else { ses->data = data; } ses->length = size; if (link_in) { ses->next = fru->sessions; fru->sessions = ses; } } else { size = fru->length; data = fru->data; } if (!data) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rdata[0] = 0; ipmi_set_uint16(rdata+1, size); rdata[3] = 0; /* We only support byte access for now. */ *rdata_len = 4; } static int fru_sem_trywait(fru_data_t *fru) { struct timespec ts; int rv; /* Wait 250ms for the semaphore. */ restart: rv = clock_gettime(CLOCK_REALTIME, &ts); if (rv == -1) return errno; ts.tv_nsec += 250000000; if (ts.tv_nsec >= 1000000000) { ts.tv_nsec -= 1000000000; ts.tv_sec += 1; } rv = sem_timedwait(&fru->sem, &ts); if (rv) { if (rv == EINTR) goto restart; if (rv == ETIMEDOUT) rv = EAGAIN; else rv = errno; return rv; } return 0; } static void handle_read_fru_data(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char devid; unsigned int offset; unsigned int count; unsigned char *data = NULL; unsigned int size; fru_session_t *ses; fru_data_t *fru; int rv; if (check_msg_length(msg, 4, rdata, rdata_len)) return; devid = msg->data[0]; fru = find_fru(mc, devid); if (!fru) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rv = fru_sem_trywait(fru); if (rv) { if (rv == EAGAIN) rdata[0] = IPMI_NODE_BUSY_CC; else rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } offset = ipmi_get_uint16(msg->data+1); count = msg->data[3]; size = fru->length; if (!fru->fru_io_cb) { data = fru->data; ses = fru->sessions; while (ses && (ses->sid != msg->sid)) ses = ses->next; if (ses) { data = ses->data; size = ses->length; } if (!data) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; goto out_unlock; } if (offset >= size) { rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC; *rdata_len = 1; goto out_unlock; } } if ((offset+count) > size) count = size - offset; if (count+2 > *rdata_len) { /* Too much data to put into response. */ rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; *rdata_len = 1; goto out_unlock; } if (fru->fru_io_cb) { int rv; rv = fru->fru_io_cb(fru->data, FRU_IO_READ, rdata + 2, offset, count); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; goto out_unlock; } } else { memcpy(rdata + 2, data + offset, count); } rdata[0] = 0; rdata[1] = count; *rdata_len = 2 + count; out_unlock: sem_post(&fru->sem); } static void handle_write_fru_data(lmc_data_t *mc, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len, void *cb_data) { unsigned char device_id; unsigned int offset; unsigned int count; fru_data_t *fru; int rv; if (check_msg_length(msg, 3, rdata, rdata_len)) return; device_id = msg->data[0]; fru = find_fru(mc, device_id); if (!fru) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } rv = fru_sem_trywait(fru); if (rv) { if (rv == EAGAIN) rdata[0] = IPMI_NODE_BUSY_CC; else rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } offset = ipmi_get_uint16(msg->data+1); count = msg->len - 3; if (offset >= fru->length) { rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC; *rdata_len = 1; goto out_unlock; } if ((offset+count) > fru->length) { /* Too much data to put into FRU. */ rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; *rdata_len = 1; goto out_unlock; } if (fru->fru_io_cb) { int rv; rv = fru->fru_io_cb(fru->data, FRU_IO_WRITE, msg->data + 3, offset, count); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; goto out_unlock; } } else { memcpy(fru->data+offset, msg->data+3, count); } rdata[0] = 0; rdata[1] = count; *rdata_len = 2; out_unlock: sem_post(&fru->sem); } int ipmi_mc_get_fru_data_len(lmc_data_t *mc, unsigned char device_id, unsigned int *length) { fru_data_t *fru; if (!(mc->device_support & IPMI_DEVID_FRU_INVENTORY_DEV)) return ENOSYS; if (device_id >= 255) return EINVAL; fru = find_fru(mc, device_id); if (!fru || !fru->data) return EINVAL; *length = fru->length; return 0; } int ipmi_mc_get_fru_data(lmc_data_t *mc, unsigned char device_id, unsigned int length, unsigned char *data) { fru_data_t *fru; int rv; if (!(mc->device_support & IPMI_DEVID_FRU_INVENTORY_DEV)) return ENOSYS; fru = find_fru(mc, device_id); if (!fru) return EINVAL; if (length > fru->length) return EINVAL; rv = fru_sem_trywait(fru); if (rv) return errno; if (fru->fru_io_cb) { rv = fru->fru_io_cb(fru->data, FRU_IO_READ, data, 0, length); } else { memcpy(data, fru->data, length); } sem_post(&fru->sem); return rv; } int ipmi_mc_add_fru_data(lmc_data_t *mc, unsigned char device_id, unsigned int length, fru_io_cb fru_io_cb, void *data) { fru_data_t *fru; if (device_id > 255) return EINVAL; fru = find_fru(mc, device_id); if (!fru) { int rv; fru = malloc(sizeof(*fru)); memset(fru, 0, sizeof(*fru)); rv = sem_init(&fru->sem, 0, 1); if (rv) { rv = errno; free(fru); return rv; } fru->devid = device_id; fru->next = mc->frulist; mc->frulist = fru; } if (fru->data) { free(fru->data); fru->length = 0; } if (fru_io_cb) { fru->fru_io_cb = fru_io_cb; fru->data = data; } else if (length) { fru->data = malloc(length); if (!fru->data) return ENOMEM; memcpy(fru->data, data, length); } else fru->data = NULL; fru->length = length; return 0; } int ipmi_mc_fru_sem_wait(lmc_data_t *mc, unsigned char device_id) { int rv; fru_data_t *fru = find_fru(mc, device_id); if (!fru) return EINVAL; rv = sem_wait(&fru->sem); if (rv) return errno; return 0; } int ipmi_mc_fru_sem_trywait(lmc_data_t *mc, unsigned char device_id) { int rv; fru_data_t *fru = find_fru(mc, device_id); if (!fru) return EINVAL; rv = fru_sem_trywait(fru); if (rv) return errno; return 0; } int ipmi_mc_fru_sem_post(lmc_data_t *mc, unsigned char device_id) { int rv; fru_data_t *fru = find_fru(mc, device_id); if (!fru) return EINVAL; rv = sem_post(&fru->sem); if (rv) return errno; return 0; } struct fru_file_io_info { lmc_data_t *mc; char *filename; unsigned int file_offset; unsigned int length; }; static int fru_file_io_cb(void *cb_data, enum fru_io_cb_op op, unsigned char *data, unsigned int offset, unsigned int length) { struct fru_file_io_info *info = cb_data; int fd; int rv = 0; int l; if (offset + length > info->length) return EINVAL; switch (op) { case FRU_IO_READ: fd = open(info->filename, O_RDONLY); if (fd == -1) { rv = errno; info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: (read) error on open of %s: %s", info->filename, strerror(rv)); return rv; } if (lseek(fd, info->file_offset + offset, SEEK_SET) == -1) { rv = errno; close(fd); info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: (read) error on lseek" " of %s to %u: %s", info->filename, info->file_offset + offset, strerror(rv)); return rv; } restart_read: l = read(fd, data, length); if (l == -1) { if (errno == EINTR) goto restart_read; rv = errno; info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: error on read of %u bytes of %s" " at %u: %s", length, info->filename, info->file_offset + offset, strerror(rv)); } else if (l == 0) { rv = EIO; info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: end of file read of %u bytes of %s" " at %u: %s", length, info->filename, info->file_offset + offset, strerror(rv)); } else if (((unsigned int) l) != length) { length -= l; data += l; goto restart_read; } close(fd); break; case FRU_IO_WRITE: fd = open(info->filename, O_WRONLY); if (fd == -1) { rv = errno; info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: (write) error on open of %s: %s", info->filename, strerror(rv)); return rv; } if (lseek(fd, info->file_offset + offset, SEEK_SET) == -1) { rv = errno; close(fd); info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: (write) error on lseek" " of %s to %u: %s", info->filename, info->file_offset + offset, strerror(rv)); return rv; } restart_write: l = write(fd, data, length); if (l == -1) { if (errno == EINTR) goto restart_write; rv = errno; info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: error on write of %u bytes of %s" " at %u: %s", length, info->filename, info->file_offset + offset, strerror(rv)); } else if (l == 0) { rv = EIO; info->mc->sysinfo->log(info->mc->sysinfo, OS_ERROR, NULL, "fru_io: end of file write of %u bytes of %s" " at %u: %s", length, info->filename, info->file_offset + offset, strerror(rv)); } else if (((unsigned int) l) != length) { length -= l; data += l; goto restart_write; } close(fd); break; default: return EINVAL; } return rv; } int ipmi_mc_add_fru_file(lmc_data_t *mc, unsigned char device_id, unsigned int length, unsigned int file_offset, const char *filename) { struct fru_file_io_info *info; int rv; info = malloc(sizeof(*info)); if (!info) return ENOMEM; info->filename = strdup(filename); if (!info->filename) { free(info); return ENOMEM; } info->mc = mc; info->length = length; info->file_offset = file_offset; rv = ipmi_mc_add_fru_data(mc, device_id, length, fru_file_io_cb, info); if (rv) { free(info->filename); free(info); } return rv; } /* We don't currently care about partial sel adds, since they are pretty stupid. */ cmd_handler_f storage_netfn_handlers[256] = { [IPMI_GET_SEL_INFO_CMD] = handle_get_sel_info, [IPMI_GET_SEL_ALLOCATION_INFO_CMD] = handle_get_sel_allocation_info, [IPMI_RESERVE_SEL_CMD] = handle_reserve_sel, [IPMI_GET_SEL_ENTRY_CMD] = handle_get_sel_entry, [IPMI_ADD_SEL_ENTRY_CMD] = handle_add_sel_entry, [IPMI_DELETE_SEL_ENTRY_CMD] = handle_delete_sel_entry, [IPMI_CLEAR_SEL_CMD] = handle_clear_sel, [IPMI_GET_SEL_TIME_CMD] = handle_get_sel_time, [IPMI_SET_SEL_TIME_CMD] = handle_set_sel_time, [IPMI_GET_SDR_REPOSITORY_INFO_CMD] = handle_get_sdr_repository_info, [IPMI_GET_SDR_REPOSITORY_ALLOC_INFO_CMD] = handle_get_sdr_repository_alloc_info, [IPMI_RESERVE_SDR_REPOSITORY_CMD] = handle_reserve_sdr_repository, [IPMI_GET_SDR_CMD] = handle_get_sdr, [IPMI_ADD_SDR_CMD] = handle_add_sdr, [IPMI_PARTIAL_ADD_SDR_CMD] = handle_partial_add_sdr, [IPMI_DELETE_SDR_CMD] = handle_delete_sdr, [IPMI_CLEAR_SDR_REPOSITORY_CMD] = handle_clear_sdr_repository, [IPMI_GET_SDR_REPOSITORY_TIME_CMD] = handle_get_sdr_repository_time, [IPMI_SET_SDR_REPOSITORY_TIME_CMD] = handle_set_sdr_repository_time, [IPMI_ENTER_SDR_REPOSITORY_UPDATE_CMD] = handle_enter_sdr_repository_update, [IPMI_EXIT_SDR_REPOSITORY_UPDATE_CMD] = handle_exit_sdr_repository_update, [IPMI_GET_FRU_INVENTORY_AREA_INFO_CMD] = handle_get_fru_inventory_area_info, [IPMI_READ_FRU_DATA_CMD] = handle_read_fru_data, [IPMI_WRITE_FRU_DATA_CMD] = handle_write_fru_data }; OpenIPMI-2.0.33/lanserv/atca.emu0000644000175000017500000002704312002623311013166 00000000000000# Turn on ATCA mode atca_enable # Add the BMC at 0x20 # Entity id 0xf0 1 mc_add 20 0 1 23 9 8 1f 1291 f02 atca_set_site 0x10 3 1 mc_setbmc 20 main_sdr_add 20 00 00 51 12 0f 20 00 00 1f 00 00 00 f0 1 0 c4 'T 'e 's 't sel_enable 20 100 0b mc_add_fru_data 20 0 400 \ 01 00 01 03 00 00 00 fb \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 mc_add_fru_data 20 9 200 \ 0x01 0x00 0x00 0x01 0x09 0x17 0x00 0xde \ 0x01 0x08 0x19 0xa4 0x76 0x4e 0xc3 0x43 \ 0x45 0x53 0xcf 0x41 0x64 0x76 0x61 0x6e \ 0x63 0x65 0x64 0x4d 0x43 0x20 0x39 0x34 \ 0x37 0x38 0x89 0x23 0x5a 0x49 0x13 0x04 \ 0x45 0xd2 0x04 0x00 0x86 0x19 0x75 0x61 \ 0x21 0x00 0x00 0xd2 0x66 0x72 0x75 0x2d \ 0x69 0x6e 0x66 0x6f 0x2d 0x30 0x2d 0x30 \ 0x2d 0x34 0x2e 0x69 0x6e 0x66 0xc1 0x11 \ 0x01 0x0e 0x19 0xc3 0x43 0x45 0x53 0xcf \ 0x41 0x64 0x76 0x61 0x6e 0x63 0x65 0x64 \ 0x4d 0x43 0x20 0x39 0x34 0x37 0x38 0x86 \ 0x10 0x04 0x41 0x10 0x04 0x00 0xe4 0x42 \ 0x65 0x74 0x61 0x20 0x70 0x72 0x6f 0x74 \ 0x6f 0x74 0x79 0x70 0x65 0x73 0x20 0x2f \ 0x20 0x43 0x45 0x53 0x20 0x49 0x50 0x4d \ 0x49 0x20 0x72 0x65 0x76 0x20 0x30 0x2e \ 0x31 0x2e 0x30 0x89 0x23 0x5a 0x49 0x13 \ 0x04 0x45 0xd2 0x04 0x00 0x86 0x90 0x03 \ 0x39 0x14 0x00 0x00 0xd2 0x66 0x72 0x75 \ 0x2d 0x69 0x6e 0x66 0x6f 0x2d 0x30 0x2d \ 0x30 0x2d 0x34 0x2e 0x69 0x6e 0x66 0xc1 \ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xb8 \ 0xc0 0x02 0x06 0x55 0xe3 0x5a 0x31 0x00 \ 0x16 0x00 0x0a 0xc0 0x82 0x22 0xf1 0xab \ 0x5a 0x31 0x00 0x19 0x00 0x00 0x80 0x02 \ 0xa4 0x98 0xf3 0x28 0xa9 0xf5 0x00 0x2f \ 0x10 0x00 0xfd 0x01 0x2f 0x10 0x00 0xfd \ 0x00 0x2f 0x10 0x01 0xfd 0x01 0x2f 0x10 \ 0x01 0xfd 0x00 0x00 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff \ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff # Shelf FRU information mc_add_fru_data 20 fe 400 \ 01 00 01 03 00 08 00 f3 \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 \ # The multi-records # record 1, the address table c0 02 2b 1f f4 5a 31 00 \ 10 00 c6 'S 'h 'e 'l 'f \ '1 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 03 \ 08 01 02 09 02 02 41 01 \ 00 00 00 00 00 00 00 00 \ # record 2, the backplane point-to-point connectivity record c0 02 17 51 d6 5a 31 00 \ 04 00 09 40 02 42 21 00 \ 44 32 02 08 42 01 40 21 \ 00 0a 44 00 \ # record 3, the shelf power distribution record c0 02 1a 89 9b 5a 31 00 \ 11 00 02 00 01 e0 00 40 \ 02 30 20 40 21 00 02 d0 \ 01 3a 01 50 23 60 24 \ # record 4, the shelf activation and power management record c0 02 1b de 45 5a 31 00 \ 12 00 27 04 10 24 00 04 \ 47 20 25 03 07 49 30 26 \ 01 10 48 40 27 09 1b 09 \ # record 5, the shelf manager ip connection record, version 0 c0 02 09 bd 78 5a 31 00 \ 13 00 c0 a8 19 24 \ # record 6, the shelf manager ip connection record, version 1 c0 02 11 3d f0 5a 31 00 \ 13 01 c0 a8 19 24 c0 a8 \ 19 01 ff ff ff 00 \ # record 7, the board point-to-point connectivity record c0 02 2e f6 1a 5a 31 00 \ 14 00 02 11 22 33 44 55 \ 66 77 88 99 aa bb cc dd \ ee ff fe 12 23 34 45 56 \ 67 78 89 9a ab bc cd de \ ef f0 01 01 0f 11 02 42 \ 13 00 03 \ # record 8, the radial IPMB-0 link mapping record c0 02 19 fb 2a 5a 31 00 \ 15 00 11 22 33 44 55 02 \ 20 01 01 30 10 30 03 03 \ 11 31 12 32 13 33 \ # record 9, the shelf fan geography record c0 02 16 72 b6 5a 31 00 \ 1b 00 04 20 10 01 02 21 \ 11 02 03 22 12 03 04 23 \ 13 04 05 \ # record 10, Bogus end record c1 82 1b 3d 65 5a 31 00 \ 13 00 27 04 10 24 00 04 \ 27 20 25 03 07 29 30 26 \ 01 10 28 40 27 09 1b 09 mc_enable 20 ## Add a shelf FRU device at 0x10 ## Entity id 0xf2 60 mc_add 10 0 1 23 9 8 08 1291 f03 main_sdr_add 20 00 00 51 12 0f 10 00 00 08 00 00 00 f2 60 0 c4 'F 'R 'U '1 atca_set_site 9 2 1 # Board FRU information mc_add_fru_data 10 0 400 \ 01 00 01 03 00 00 00 fb \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 # Shelf FRU information mc_add_fru_data 10 1 400 \ 01 00 01 03 00 08 00 f3 \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 \ # The multi-records # record 1, the address table c0 02 2b 1f f4 5a 31 00 \ 10 00 c6 'S 'h 'e 'l 'f \ '1 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 03 \ 08 01 02 09 02 02 41 01 \ 00 00 00 00 00 00 00 00 \ # record 2, the backplane point-to-point connectivity record c0 82 17 51 56 5a 31 00 \ 04 00 09 40 02 42 21 00 \ 44 32 02 08 42 01 40 21 \ 00 0a 44 00 # The hot-swap sensor # sensor #0 sensor_add 10 0 0 f0 6f sensor_set_event_support 10 0 0 1 1 0 \ 000000011111111 000000000000000 000000011111111 000000000000000 sensor_set_bit_clr_rest 10 0 0 1 1 device_sdr_add 10 0 \ 00 00 51 02 22 \ 10 00 00 f2 60 ff c0 f0 6f ff 00 ff 00 ff 00 00 \ 00 00 00 00 00 00 00 00 00 00 c7 'H 'o 't 's 'w \ 'a 'p device_sdr_add 10 0 \ 01 00 51 02 22 \ 11 00 01 f2 60 ff c0 0c 6f ff 00 ff 00 ff 00 00 \ 00 00 00 00 00 00 00 00 00 00 c7 'T 'e 's 't '0 \ '0 '1 device_sdr_add 10 0 \ 02 00 51 03 12 \ 10 00 02 f2 60 0c 6f 00 00 00 c7 'T 'e 's 't '0 \ '0 '2 device_sdr_add 10 0 \ 03 00 51 01 38 \ 82 00 18 a0 60 7f 69 02 \ 01 04 22 04 22 12 12 00 \ 04 00 00 ac 00 00 00 00 \ c0 07 bf c5 b9 ff 00 00 \ c9 00 00 b5 00 01 01 00 \ 00 00 ce 53 42 43 20 2b \ 33 2e 33 56 20 53 55 53 mc_enable 10 # Add a shelf FRU device at 0x12 # Entity id 0xf2 60 mc_add 12 0 1 23 9 8 08 1291 f03 main_sdr_add 20 00 00 51 12 0f 12 00 00 08 00 00 00 f2 60 0 c4 'F 'R 'U '2 atca_set_site 9 2 2 # Board FRU information mc_add_fru_data 12 0 400 \ 01 00 01 03 00 00 00 fb \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 mc_add_fru_data 12 1 400 \ 01 00 01 03 00 08 00 f3 \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 \ # The multi-records # record 1, the address table c0 02 2b 1f f4 5a 31 00 \ 10 00 c6 'S 'h 'e 'l 'f \ '1 00 00 00 00 00 00 00 \ 00 00 00 00 00 00 00 03 \ 08 01 02 09 02 02 41 01 \ 00 00 00 00 00 00 00 00 \ # record 2, the backplane point-to-point connectivity record c0 82 17 51 56 5a 31 00 \ 04 00 09 40 02 42 21 00 \ 44 32 02 08 42 01 40 21 \ 00 0a 44 00 # The hot-swap sensor # sensor #0 sensor_add 12 0 0 f0 6f sensor_set_event_support 12 0 0 1 1 0 \ 000000011111111 000000000000000 000000011111111 000000000000000 sensor_set_bit_clr_rest 12 0 0 1 1 device_sdr_add 12 0 \ 00 00 51 02 22 \ 12 00 00 f2 60 ff c0 f0 6f ff 00 ff 00 ff 00 00 \ 00 00 00 00 00 00 00 00 00 00 c7 'H 'o 't 's 'w \ 'a 'p mc_enable 12 # Add a board in site 1 (0x82) # Entity id 0xa0 60 mc_add 82 0 1 19 4 3 29 1291 f04 #main_sdr_add 20 00 00 51 12 12 \ # 82 00 00 29 00 00 00 a0 60 0 c6 'B 'o 'a 'r 'd '1 atca_set_site 41 0 1 mc_add_fru_data 82 0 400 \ 01 00 01 03 00 00 00 fb \ # Chassis info 01 02 01 c4 'A 'T 'C 'A \ c4 'T 'e 's 't c1 00 fa \ # Board info 01 05 00 00 00 00 c4 'T \ 'e 's 't c4 'T 'e 's 't \ c4 'T 'e 's 't c4 'T 'e \ 's 't c4 'T 'e 's 't c1 \ 00 00 00 00 00 00 00 45 # The hot-swap sensor # sensor #0 sensor_add 82 0 0 f0 6f sensor_set_event_support 82 0 0 1 1 0 \ 000000011111111 000000000000000 000000011111111 000000000000000 sensor_set_bit_clr_rest 82 0 0 1 1 device_sdr_add 82 0 \ 00 00 51 12 12 \ 82 00 00 29 00 00 00 a0 60 0 c6 'B 'o 'a 'r 'd '1 device_sdr_add 82 0 \ 00 00 51 02 22 \ 82 00 00 a0 60 ff c0 f0 6f ff 00 ff 00 ff 00 00 \ 00 00 00 00 00 00 00 00 00 00 c7 'H 'o 't 's 'w \ 'a 'p mc_enable 82 # # An SDR for an MC that is not present. # IPMB 84 # device_sdr_add 82 0 \ 00 00 51 12 11 \ 84 00 00 29 00 00 00 a0 60 0 c6 'B 'o 'a 'r 'd \ '2 OpenIPMI-2.0.33/lanserv/ipmisim1.sdrs0000664000175000017500000000460513107042442014203 00000000000000 sdr type 18 device_slave_address 0x20 device_channel_number 0 chassis true ipmb_event_gen false ipmb_event_recv false fru_inventory true sel true sdr true sensor true entity_id system_board entity_instance 1 id_string "IPMI sim1" endsdr # Watchdog timer sdr type 3 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 0 entity_id system_board entity_instance 1 sensor_type Watchdog_2 event_reading_type_code 0x6f id_string "watchdog" endsdr # Temperature sensor on the main board sdr type 1 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 1 entity_id system_board entity_instance 1 sensor_type Temperature init_scanning true init_sensor_type true default_sensor_scan_on true event_reading_type_code 1 analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 id_string "MBTemp" endsdr # Temperature sensor on the sub board sdr type 1 sensor_owner_id 0x30 sensor_owner_lun 0 channel_number 0 sensor_number 1 entity_id system_board entity_instance 1 sensor_type Temperature init_scanning true init_sensor_type true default_sensor_scan_on true event_reading_type_code 1 analog_data_format unsigned rate_unit none modifier_unit none percentage false base_unit degrees_C modifier_unit_code unspecified linearization linear m 1 tolerance 0 b 0 accuracy 1 accuracy_exp 0 sensor_direction input r_exp 0 b_exp 0 sensor_maximum 255 sensor_minimum 0 id_string "SubTemp" endsdr # A presence sensor for memory module 1 sdr type 2 sensor_owner_id 0x20 sensor_owner_lun 0 channel_number 0 sensor_number 2 entity_id memory_module entity_instance 1 sensor_type Entity_Presence event_reading_type_code 0x6f event0_state_ret true assert_event0 true deassert_event0 true event1_state_ret true assert_event1 true deassert_event1 true id_string "mm1pres" endsdr # A FRU device locator for memory module 2 sdr type 0x11 device_access_address 0x30 fru_device_address 3 logical_fru 1 lun 0 device_type 0x10 device_type_modifier 0 fru_entity_id memory_module fru_entity_instance 2 id_string "mm2frudev" endsdrOpenIPMI-2.0.33/lanserv/README.vm0000644000175000017500000001145612002623311013050 00000000000000The ipmi_sim command can be used as an IPMI simulator for a virtual machine. The virtual machine talks to the simulator over a TCP socket, and the simulator can control the virtual machine aspects that it needs to be able to control. A Quick Start ------------- This section describes a quick start for getting running using the OpenIPMI simulator with qemu-kvm. This assume you have qemu-kvm patched with the IPMI patches, or they have been included. You will need: OpenIPMI-2.0.21-rc1 or later A qemu bootable disk with Linux (or something else that can use IPMI) installed on it. qemu-kvm compiled with the proper IPMI patches First, configure OpenIPMI to install someplace. We will assume this is $HOME/x3. Do this with: ./configure --prefix=$HOME/x3/usr --sysconfdir=$HOME/x3/etc \ --with-perlinstall=$HOME/x3/usr/lib/perl \ --with-pythoninstall=$HOME/x3/usr/lib/python then "make", then "make install". Note that I also had to add --with-tclcflags="-I/usr/include/tcl8.5" --with-tcllibs="-ltcl8.5" to the configure line for the gui to work because the TCL configuration was screwed up on my machine. Then edit $HOME/x3/etc/ipmi/lan.conf and find the "startcmd" variable. Edit that for your configuration of qemu. You need to leave the -ipmi option as is, of course. Run $HOME/x3/usr/bin/ipmi_sim. This will start the simulator and it will also automatically start ("Power on") the VM. You can telnet to port 9003 to get a console to the VM. In the OpenIPMI build directory, type "make rungui". This will run the OpenIPMI GUI. Pull down "File" and select "OpenDomain". In the dialog that comes up, enter "test" for the Domain name, "localhost" for the Address, "9001" for the Port, "ipmiusr" for the Username, and "test" for the Password. Then select "Ok". (Note that the username and password are configured in the lan.conf file that gets installed in $HOME/x3/etc/ipmi.) You should have "test" in the list of domains. Open it up, then open "Entities", then "test(23.1 system_chassis)", then "Controls". You will see a power and reset control. Right click on those; you can set them to "0" or "1" to perform the obvious functions. You will see that the VM is already powered on as it was started when ipmi_sim started up. If you log in to the VM, you can do a "modprobe ipmi_si" and "modprobe ipmi_devintf" and talk to the simulated BMC from there. A full watchdog is also simulated, so you can do a "modprobe ipmi_watchdog" and get a watchdog timer running. If you have the watchdog loaded, go to the OpenIPMI GUI window and right click on the "test" entry (the topmost one). Choose "Display SELS". Then in the target login, do "echo 1 >/dev/watchdog". In about 10 seconds, the VM will reset and you will see the reset log in the IPMI SEL display window. The VM Interface ---------------- The VM interface is a much simplified interface similar to the direct mode IPMI serial codec. The framing is done with special characters. A 0xa0 character says that all characters since the last framing character (or beginning of the session) is an IPMI message. A 0xa1 character says that the preceding characters are a control command. A 0xaa character says to change bit 4 of the next character from a '1' to a '0'. This way, a 0xa0 data character is sent as 0xaa 0xb0. An IPMI message has the following format: seq netfn << 2 | lun cmd data... checksum 0xa0 The sequence is a one-byte sequence number, it will be returned in the response. The response is the same as above, except a completion code is added after the cmd byte. This is much like the KCS interface with a sequence number at the beginning. Commands are pretty simple. The first byte of a command is the command id. The rest is data for the command. There are two commands sent from the VM to the simulator. Command 0x08 is followed by a single byte with the following bits telling the simulator the capabilities of the VM. These bits are: bit 0 - can do a power off. bit 1 - can do a target reset. bit 2 - can enable/disable the IPMI interrupt. bit 3 - can generate an NMI. bit 4 - can set the ATTN bit on the interface. A reset command is sent from the VM to the simulator to say that a reset has occurred. The commands from the simulator to the VM are based on the above capabilities. The simulator will not send a command where the VM does not have the capability. None of these have any data with them. The commands are: 0xFF - The next byte is the version of the protocol, currently 1 0x00 - Clear ATTN 0x01 - Set ATTN without an interrupt 0x02 - Set ATTN with an interrupt 0x03 - Power off (shut down) the VM 0x04 - Reset the target in the VM 0x05 - Enable the IPMI messaging interrupt 0x06 - Disable the IPMI messaging interrupt 0x07 - Send an NMI from the BMC. That's pretty much it. The idea was to keep it simple.OpenIPMI-2.0.33/lanserv/README.ipmi_sim0000664000175000017500000000657413033261266014257 00000000000000This is the IPMI simulator, which can perform the function of a BMC. It can act as a real BMC, too, see README.yourownbmc for details. Unfortunately, the documentation is lacking at the moment. The available docs will have to suffice at the moment. There are some example config files in this directory. If you want to just try it out, you can run: mkdir my_statedir ./ipmi_sim lan.conf -f ipmisim1.emu -s my_statedir You will be a BMC on your host at 9001. Then you can do, for instance: cminyard@t430:~$ ipmitool -I lanplus -U ipmiusr -P test -p 9001 -H localhost mc info Device ID : 0 Device Revision : 3 Firmware Revision : 9.08 IPMI Version : 2.0 Manufacturer ID : 4753 Manufacturer Name : Unknown (0x1291) Product ID : 3842 (0x0f02) Product Name : Unknown (0xF02) Device Available : yes Provides Device SDRs : no Additional Device Support : Sensor Device SDR Repository Device SEL Device FRU Inventory Device IPMB Event Receiver Chassis Device Aux Firmware Rev Info : 0x00 0x00 0x00 0x00 Unfortunately, you won't get any SDRs by default, the SDR repository will be empty: cminyard@t430:~$ ipmitool -I lanplus -U ipmiusr -P test -p 9001 -H localhost sdr list SDRR successfully erased Err in cmd get sensor sdr info Get SDR 0000 command failed: Requested sensor, data, or record not found Get SDR 0000 command failed: Requested sensor, data, or record not found Get SDR 0000 command failed: Requested sensor, data, or record not found Get SDR 0000 command failed: Requested sensor, data, or record not found Get SDR 0000 command failed: Requested sensor, data, or record not found To fix this, you have to install SDRs in the state directory. The SDRs should already be build for you, so you just have to copy them in. If you look in the my_statedir directory, you will see that it has created some directories: cminyard@t430:~/git/openipmi/O/lanserv$ ls -lR my_statedir/ my_statedir/: total 4 drwxr-xr-x 3 cminyard cminyard 4096 Jan 4 14:54 ipmi_sim my_statedir/ipmi_sim: total 4 drwxr-xr-x 2 cminyard cminyard 4096 Jan 4 14:54 ipmisim1 my_statedir/ipmi_sim/ipmisim1: total 0 Stop ipmi_sim, install the compiled SDRs: cp ipmisim1.bsdr my_statedir/ipmi_sim/ipmisim1/sdr.20.main then restart ipmi_sim as above. Now you have SDRs matching the sensors: cminyard@t430:~$ ipmitool -I lanplus -U ipmiusr -P test -p 9001 -H localhost sdr list MBTemp | 96 degrees C | ok SubTemp | 0 degrees C | ok Note that if you use IPMI commands to make any changes to the users, the users in the lan.conf file will no longer work, as the persistent data overrides what is in lan.conf. For more information, see: README.yourownbmc - More information on setting up BMCs, simulated and real README.vm - Information on the protocol to talk to qemu. README.design - Information about the design structure of ipmi_sim. ipmi_lan.5 - A man file describing lan.conf. lan.conf has quite a bit of information in it, too. ipmi_sim_cmd.5 - A amn file describing the ipmi_sim command language. This is what is in ipmisim1.emu (which doesn't have that much info in it) and is how you add MCs, sensors, etc. ipmi_sim.1 - A short man page on the program itself.OpenIPMI-2.0.33/lanserv/lanserv_ipmi.c0000664000175000017500000023304314141240666014421 00000000000000/* * lanserv_ipmi.c * * MontaVista IPMI IPMI LAN interface protocol engine * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #ifdef HAVE_OPENSSL #include #endif #include #include #include #include #include #include #include #include static int is_authval_null(uint8_t *val) { int i; for (i=0; i<16; i++) if (val[i] != 0) return 0; return 1; } static user_t * find_user(lanserv_data_t *lan, uint8_t *user, int name_only_lookup, int priv) { int i; user_t *rv = NULL; for (i=1; i<=MAX_USERS; i++) { if (lan->users[i].valid && (memcmp(user, lan->users[i].username, 16) == 0)) { if (name_only_lookup || (lan->users[i].privilege == priv)) { rv = &(lan->users[i]); break; } } } return rv; } static session_t * sid_to_session(lanserv_data_t *lan, unsigned int sid) { int idx; session_t *session; if (sid & 1) return NULL; idx = (sid >> 1) & SESSION_MASK; if (idx > MAX_SESSIONS) return NULL; session = lan->sessions + idx; if (!session->active) return NULL; if (session->sid != sid) return NULL; return session; } static void close_session(lanserv_data_t *lan, session_t *session) { unsigned int i; for (i = 0; i < LANSERV_NUM_CLOSERS; i++) { if (session->closers[i].close_cb) { session->closers[i].close_cb( session->closers[i].mc, session->sid, session->closers[i].close_cb_data); session->closers[i].close_cb = NULL; session->closers[i].mc = NULL; } } session->active = 0; if (session->authtype <= 4) ipmi_auths[session->authtype].authcode_cleanup(session->authdata); if (session->integh) session->integh->cleanup(lan, session); if (session->confh) session->confh->cleanup(lan, session); lan->channel.active_sessions--; if (session->src_addr) { lan->channel.free(&lan->channel, session->src_addr); session->src_addr = NULL; } } static int auth_gen(session_t *ses, uint8_t *out, uint8_t *sid, uint8_t *seq, uint8_t *data1, int data1_len, uint8_t *data2, int data2_len, uint8_t *data3, int data3_len) { int rv; ipmi_auth_sg_t l[] = { { sid, 4 }, { data1, data1_len }, { data2, data2_len }, { data3, data3_len }, { seq, 4 }, { NULL, 0 }}; rv = ipmi_auths[ses->authtype].authcode_gen(ses->authdata, l, out); return rv; } static int auth_check(session_t *ses, uint8_t *sid, uint8_t *seq, uint8_t *data, int data_len, uint8_t *code) { int rv; ipmi_auth_sg_t l[] = { { sid, 4 }, { data, data_len }, { seq, 4 }, { NULL, 0 }}; rv = ipmi_auths[ses->authtype].authcode_check(ses->authdata, l, code); return rv; } static int gen_challenge(lanserv_data_t *lan, uint8_t *out, uint32_t sid) { int rv; ipmi_auth_sg_t l[] = { { &sid, 4 }, { NULL, 0 }}; rv = ipmi_md5_authcode_gen(lan->challenge_auth, l, out); return rv; } static int check_challenge(lanserv_data_t *lan, uint32_t sid, uint8_t *code) { int rv; ipmi_auth_sg_t l[] = { { &sid, 4 }, { NULL, 0 }}; rv = ipmi_md5_authcode_check(lan->challenge_auth, l, code); return rv; } #define IPMI_LAN_MAX_HEADER_SIZE 64 #define IPMI_LAN_MAX_TRAILER_SIZE 960 static void raw_send(lanserv_data_t *lan, struct iovec *vec, unsigned int vecs, void *addr, int addr_len) { if (lan->sysinfo->debug & DEBUG_RAW_MSG) { char *str; int slen; int pos; #define format "Raw LAN msg:" char dummy; unsigned int i, j; unsigned int len = 0; debug_log_raw_msg(lan->sysinfo, addr, addr_len, "Raw LAN send to:"); for (i = 0; i < vecs; i++) len += vec[i].iov_len; slen = snprintf(&dummy, 0, format); slen += len * 3 + 3; str = malloc(slen); if (!str) goto send; pos = sprintf(str, format); #undef format str[pos++] = '\n'; str[pos++] = '\0'; for (i = 0; i < vecs; i++) { for (j = 0; j < vec[i].iov_len; j++) pos += sprintf(str + pos, " %2.2x", ((unsigned char *) vec[i].iov_base)[j]); } lan->sysinfo->log(lan->sysinfo, DEBUG, NULL, "%s", str); free(str); } send: lan->send_out(lan, vec, vecs, addr, addr_len); } static void return_rmcpp_rsp(lanserv_data_t *lan, session_t *session, msg_t *msg, unsigned int payload, unsigned char *data, unsigned int len, unsigned char *iana, unsigned int payload_id) { uint8_t d[IPMI_LAN_MAX_HEADER_SIZE+IPMI_LAN_MAX_HEADER_SIZE +IPMI_LAN_MAX_TRAILER_SIZE+1]; uint8_t *pos = d + IPMI_LAN_MAX_HEADER_SIZE; uint8_t *tpos; unsigned int hdr_left = IPMI_LAN_MAX_HEADER_SIZE; unsigned int dlen = IPMI_LAN_MAX_HEADER_SIZE + IPMI_LAN_MAX_TRAILER_SIZE; unsigned int mlen; struct iovec vec[3]; uint32_t sid, seq, *seqp; int rv; unsigned int s; if (!session) session = sid_to_session(lan, msg->sid); if (len > dlen) return; memcpy(pos, data, len); if (payload == 0) { /* Add the IPMI header - fixme -cheap hack */ if (hdr_left < 6) return; hdr_left -= 6; pos -= 6; dlen += 6; /* Adding header, increase total length */ len += 6; pos[0] = msg->rq_addr; pos[1] = ((msg->netfn | 1) << 2) | msg->rq_lun; pos[2] = -ipmb_checksum(pos, 2, 0); pos[3] = msg->rs_addr; pos[4] = (msg->rq_seq << 2) | msg->rs_lun; pos[5] = msg->cmd; pos[len] = -ipmb_checksum(pos+3, len-3, 0); len++; dlen++; } if (session && !session->in_startup) { if (session->conf) { rv = session->confh->encrypt(lan, session, &pos, &hdr_left, &len, &dlen); if (rv) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Message failure:" " encryption failed: 0x%x", rv); return; } } } mlen = len; if (session && !session->in_startup && session->integ) { unsigned int count; /* Pad to the next multiple of 4, including the pad length and next header. */ count = 0; while ((mlen+2) % 4) { if (mlen == dlen) return; pos[mlen] = 0xff; count++; mlen++; } if (mlen == dlen) return; pos[mlen] = count; mlen++; if (mlen == dlen) return; pos[mlen] = 0x07; /* Next header */ mlen++; } if (payload == 2) s = 22; else s = 16; if (hdr_left < s) return; hdr_left -= s; pos -= s; dlen += s; /* Adding header, increase total length */ mlen += s; pos[0] = 0x06; pos[1] = 0; pos[2] = 0xff; pos[3] = 0x07; pos[4] = IPMI_AUTHTYPE_RMCP_PLUS; pos[5] = payload; if (!session || session->in_startup) { sid = 0; seq = 0; seqp = NULL; } else { sid = session->rem_sid; if (session->integ != 0) { seq = session->xmit_seq; seqp = &session->xmit_seq; pos[5] |= 0x40; } else { seq = session->unauth_xmit_seq; seqp = &session->unauth_xmit_seq; } if (session->conf != 0) pos[5] |= 0x80; } tpos = pos + 6; if (payload == 2) { assert(iana); memcpy(tpos, iana, 3); tpos[3] = 0; ipmi_set_uint16(tpos+4, payload_id); tpos += 6; } ipmi_set_uint32(tpos, sid); tpos += 4; ipmi_set_uint32(tpos, seq); tpos += 4; ipmi_set_uint16(tpos, seq); ipmi_set_uint16(tpos, len); if (session && !session->in_startup && session->integ) { rv = session->integh->add(lan, session, pos, &mlen, dlen); if (rv) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Message failure:" " encryption failed: 0x%x", rv); return; } } if (seqp) { (*seqp)++; if (*seqp == 0) *seqp = 1; } vec[0].iov_base = pos; vec[0].iov_len = mlen; raw_send(lan, vec, 1, msg->src_addr, msg->src_len); } static void return_rsp(lanserv_data_t *lan, msg_t *msg, session_t *session, rsp_msg_t *rsp) { uint8_t data[IPMI_LAN_MAX_HEADER_SIZE]; struct iovec vec[3]; uint8_t csum; session_t dummy_session; uint8_t *pos; int len; int rv; if (!session) session = sid_to_session(lan, msg->sid); if (session && session->rmcpplus) { return_rmcpp_rsp(lan, session, msg, msg->rmcpp.payload, rsp->data, rsp->data_len, NULL, 0); return; } else if (msg->sid == 0) { session = &dummy_session; session->active = 1; session->authtype = IPMI_AUTHTYPE_NONE; session->xmit_seq = 0; session->sid = 0; } if (!session) return; data[0] = 6; /* RMCP version. */ data[1] = 0; data[2] = 0xff; /* No seq num */ data[3] = 7; /* IPMI msg class */ data[4] = session->authtype; ipmi_set_uint32(data+5, session->xmit_seq); session->xmit_seq++; if (session->xmit_seq == 0) session->xmit_seq++; ipmi_set_uint32(data+9, session->sid); if (session->authtype == IPMI_AUTHTYPE_NONE) pos = data+13; else pos = data+29; len = rsp->data_len + 7; *pos = len; pos++; pos[0] = msg->rq_addr; pos[1] = (rsp->netfn << 2) | msg->rq_lun; pos[2] = -ipmb_checksum(pos, 2, 0); pos[3] = msg->rs_addr; pos[4] = (msg->rq_seq << 2) | msg->rs_lun; pos[5] = rsp->cmd; csum = ipmb_checksum(pos+3, 3, 0); csum = -ipmb_checksum(rsp->data, rsp->data_len, csum); vec[0].iov_base = data; if (session->authtype == IPMI_AUTHTYPE_NONE) vec[0].iov_len = 14 + 6; else { rv = auth_gen(session, data+13, data+9, data+5, pos, 6, rsp->data, rsp->data_len, &csum, 1); if (rv) { /* FIXME - what to do? */ return; } vec[0].iov_len = 30 + 6; } vec[1].iov_base = rsp->data; vec[1].iov_len = rsp->data_len; vec[2].iov_base = &csum; vec[2].iov_len = 1; raw_send(lan, vec, 3, msg->src_addr, msg->src_len); } static void lan_return_rsp(channel_t *chan, msg_t *msg, rsp_msg_t *rsp) { lanserv_data_t *lan = chan->chan_info; rsp_msg_t rrsp; return_rsp(lan, msg, NULL, rsp); msg = lan->sysinfo->mc_get_next_recv_q(chan); if (!msg) return; while (msg) { /* Extract relevant header information and remove the header and checksum. */ msg->rq_addr = msg->data[0]; msg->rq_lun = msg->data[1] & 0x3; msg->rs_addr = msg->data[3]; msg->rs_lun = msg->data[4] & 0x3; rrsp.netfn = msg->netfn | 1; rrsp.cmd = msg->data[5]; rrsp.data = msg->data + 6; rrsp.data_len = msg->len - 7; return_rsp(lan, msg, NULL, &rrsp); chan->free(chan, msg); msg = lan->sysinfo->mc_get_next_recv_q(chan); } if (chan->recv_in_q) chan->recv_in_q(chan, 0); } static void return_rsp_data(lanserv_data_t *lan, msg_t *msg, session_t *session, uint8_t *data, int len) { rsp_msg_t rsp; rsp.netfn = msg->netfn | 1; rsp.cmd = msg->cmd; rsp.data = data; rsp.data_len = len; return_rsp(lan, msg, session, &rsp); } static void return_err(lanserv_data_t *lan, msg_t *msg, session_t *session, uint8_t err) { rsp_msg_t rsp; rsp.netfn = msg->netfn | 1; rsp.cmd = msg->cmd; rsp.data = &err; rsp.data_len = 1; return_rsp(lan, msg, session, &rsp); } static void handle_get_system_guid(lanserv_data_t *lan, session_t *session, msg_t *msg) { unsigned char rdata[17]; unsigned int rdata_len = sizeof(rdata); if (lan->guid) { if (rdata_len < 17) { rdata[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; rdata_len = 1; goto out; } rdata[0] = 0; memcpy(rdata + 1, lan->guid, 16); rdata_len = 17; } else { rdata[0] = IPMI_INVALID_CMD_CC; rdata_len = 1; } out: return_rsp_data(lan, msg, session, rdata, rdata_len); } static void handle_get_channel_auth_capabilities(lanserv_data_t *lan, msg_t *msg) { uint8_t data[9]; uint8_t chan; uint8_t priv; int do_rmcpp; if (msg->len < 2) { return_err(lan, msg, NULL, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } do_rmcpp = (msg->data[0] >> 7) & 1; chan = msg->data[0] & 0xf; priv = msg->data[1] & 0xf; if (chan == 0xe) chan = lan->channel.channel_num; if (chan != lan->channel.channel_num) { return_err(lan, msg, NULL, IPMI_INVALID_DATA_FIELD_CC); } else if (priv > lan->channel.privilege_limit) { return_err(lan, msg, NULL, IPMI_INVALID_DATA_FIELD_CC); } else { if (! lan->guid) do_rmcpp = 0; /* Must have a GUID to do RMCP+ */ data[0] = 0; data[1] = chan; data[2] = lan->channel.priv_info[priv-1].allowed_auths; if (do_rmcpp) data[2] |= 0x80; data[3] = 0x04; /* per-message authentication is on, user-level authenitcation is on, non-null user names disabled, no anonymous support. */ if (lan->users[1].valid) { if (is_authval_null(lan->users[1].pw)) data[3] |= 0x01; /* Anonymous login. */ else data[3] |= 0x02; /* Null user supported. */ } if (lan->bmc_key) data[3] |= 0x20; data[4] = 0; if (do_rmcpp) data[4] |= 0x3; /* Support RMCP and RMCP+ */ data[5] = lan->channel.manufacturer_id & 0xff; data[6] = (lan->channel.manufacturer_id >> 8) & 0xff; data[7] = (lan->channel.manufacturer_id >> 16) & 0xff; data[8] = 0; return_rsp_data(lan, msg, NULL, data, 9); } } static void handle_get_session_challenge(lanserv_data_t *lan, msg_t *msg) { uint8_t data[21]; user_t *user; uint32_t sid; int rv; if (msg->len < 17) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Session challenge failed: message too short"); return_err(lan, msg, NULL, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } user = find_user(lan, msg->data+1, 1, 0); if (!user) { lan->sysinfo->log(lan->sysinfo, SESSION_CHALLENGE_FAILED, msg, "Session challenge failed: Invalid user"); if (is_authval_null(msg->data+1)) return_err(lan, msg, NULL, 0x82); /* no null user */ else return_err(lan, msg, NULL, 0x81); /* no user */ return; } if (lan->channel.active_sessions >= MAX_SESSIONS) { lan->sysinfo->log(lan->sysinfo, SESSION_CHALLENGE_FAILED, msg, "Session challenge failed: To many open sessions"); return_err(lan, msg, NULL, IPMI_OUT_OF_SPACE_CC); return; } data[0] = 0; sid = (lan->next_challenge_seq << (USER_BITS_REQ+1)) | (user->idx << 1) | 1; lan->next_challenge_seq++; ipmi_set_uint32(data+1, sid); rv = gen_challenge(lan, data+5, sid); if (rv) { lan->sysinfo->log(lan->sysinfo, SESSION_CHALLENGE_FAILED, msg, "Session challenge failed: Error generating challenge"); return_err(lan, msg, NULL, IPMI_UNKNOWN_ERR_CC); } else { return_rsp_data(lan, msg, NULL, data, 21); } } static unsigned char cipher_suites[] = { 0xc0, 0x00, 0x00, 0x40, 0x80, 0xc0, 0x01, 0x01, 0x40, 0x80, 0xc0, 0x02, 0x01, 0x41, 0x80, 0xc0, 0x03, 0x01, 0x41, 0x81, 0xc0, 0x04, 0x01, 0x41, 0x82, 0xc0, 0x05, 0x01, 0x41, 0x83, 0xc0, 0x06, 0x02, 0x40, 0x80, 0xc0, 0x07, 0x02, 0x42, 0x80, 0xc0, 0x08, 0x02, 0x42, 0x81, 0xc0, 0x09, 0x02, 0x42, 0x82, 0xc0, 0x0a, 0x02, 0x42, 0x83, 0xc0, 0x0b, 0x02, 0x43, 0x80, 0xc0, 0x0c, 0x02, 0x43, 0x81, 0xc0, 0x0d, 0x02, 0x43, 0x82, 0xc0, 0x0e, 0x02, 0x43, 0x83 }; static unsigned char cipher_algos[] = { 0x00, 0x01, 0x02, 0x40, 0x41, 0x42, 0x43, 0x80, 0x81, 0x82, 0x83 }; static void handle_get_channel_cipher_suites(lanserv_data_t *lan, msg_t *msg) { unsigned int chan; channel_t **channels, *channel; unsigned char *adata, data[18]; unsigned int start, size; if (msg->len < 3) { return_err(lan, msg, NULL, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } chan = msg->data[0] & 0xf; if (chan == 0xe) chan = lan->channel.channel_num; channels = lan->sysinfo->mc_get_channelset(lan->channel.mc); channel = channels[chan]; if (!channel) { return_err(lan, msg, NULL, IPMI_NOT_PRESENT_CC); return; } if (channel->medium_type != IPMI_CHANNEL_MEDIUM_8023_LAN) { return_err(lan, msg, NULL, IPMI_INVALID_DATA_FIELD_CC); return; } /* * The cipher suites are all fixed, so just need to validate the * channel and return our hard-coded info. */ if (msg->data[2] & 0x80) { adata = cipher_suites; size = sizeof(cipher_suites); } else { adata = cipher_algos; size = sizeof(cipher_algos); } start = (msg->data[2] & 0x1f) * 16; if (start >= size) { start = 0; size = 0; } else { size = size - start; } if (size > 16) size = 16; data[0] = 0; data[1] = chan; memcpy(data + 2, adata + start, size); return_rsp_data(lan, msg, NULL, data, size + 2); } static void handle_no_session(lanserv_data_t *lan, msg_t *msg) { /* Should be a session challenge, validate everything else. */ if (msg->seq != 0) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "No session message failed: Invalid seq"); return; } if (msg->authtype != IPMI_AUTHTYPE_NONE) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "No session message failed: Invalid authtype: %d", msg->authtype); return; } switch (msg->cmd) { case IPMI_GET_SYSTEM_GUID_CMD: handle_get_system_guid(lan, NULL, msg); break; case IPMI_GET_CHANNEL_AUTH_CAPABILITIES_CMD: handle_get_channel_auth_capabilities(lan, msg); break; case IPMI_GET_SESSION_CHALLENGE_CMD: handle_get_session_challenge(lan, msg); break; case IPMI_GET_CHANNEL_CIPHER_SUITES_CMD: handle_get_channel_cipher_suites(lan, msg); break; default: lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "No session message failed: Invalid command: 0x%x", msg->cmd); return_err(lan, msg, NULL, IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC); break; } } static void * ialloc(void *info, int size) { lanserv_data_t *lan = info; return lan->channel.alloc(&lan->channel, size); } static void ifree(void *info, void *data) { lanserv_data_t *lan = info; lan->channel.free(&lan->channel, data); } static session_t * find_free_session(lanserv_data_t *lan) { int i; /* Find a free session. Session 0 is invalid. */ for (i=1; i<=MAX_SESSIONS; i++) { if (! lan->sessions[i].active) return &(lan->sessions[i]); } return NULL; } static void handle_temp_session(lanserv_data_t *lan, msg_t *msg) { uint8_t seq_data[4]; int user_idx; user_t *user; uint8_t auth, priv; session_t *session = NULL; session_t dummy_session; int rv; uint32_t xmit_seq; uint8_t data[11]; unsigned char tsid[4]; unsigned char tseq[4]; if (msg->cmd != IPMI_ACTIVATE_SESSION_CMD) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, " message failed: Invalid command: 0x%x", msg->cmd); return; } if (msg->len < 22) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Activate session failed: message too short"); return; } rv = check_challenge(lan, msg->sid, msg->data+2); if (rv) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: challenge failed"); return; } user_idx = (msg->sid >> 1) & USER_MASK; if ((user_idx > MAX_USERS) || (user_idx == 0)) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Invalid sid: 0x%x", msg->sid); return; } auth = msg->data[0] & 0xf; user = &(lan->users[user_idx]); if (! (user->valid)) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Invalid user idx: 0x%x", user_idx); return; } if (lan->channel.active_sessions >= MAX_SESSIONS) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Session challenge failed: To many open sessions"); return; } xmit_seq = ipmi_get_uint32(msg->data+18); memset(&dummy_session, 0, sizeof(dummy_session)); dummy_session.active = 1; dummy_session.authtype = msg->authtype; dummy_session.xmit_seq = xmit_seq; dummy_session.sid = msg->sid; rv = ipmi_auths[msg->authtype].authcode_init(user->pw, &dummy_session.authdata, lan, ialloc, ifree); if (rv) { lan->sysinfo->log(lan->sysinfo, AUTH_FAILED, msg, "Activate session failed: Message auth init failed"); return; } /* The "-6, +7" is cheating a little, but we need the last checksum to correctly calculate the code. */ ipmi_set_uint32(tsid, msg->sid); ipmi_set_uint32(tseq, msg->seq); rv = auth_check(&dummy_session, tsid, tseq, msg->data-6, msg->len+7, msg->rmcp.authcode); if (rv) { lan->sysinfo->log(lan->sysinfo, AUTH_FAILED, msg, "Activate session failed: Message auth failed"); goto out_free; } /* Note that before this point, we cannot return an error, there's no way to generate an authcode for it. */ if (xmit_seq == 0) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Invalid sequence number"); return_err(lan, msg, &dummy_session, 0x85); /* Invalid seq id */ goto out_free; } priv = msg->data[1] & 0xf; if ((user->privilege == 0xf) || (priv > user->privilege) || (priv > lan->channel.privilege_limit)) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Privilege %d for user 0x%d failed", priv, user_idx); return_err(lan, msg, &dummy_session, 0x86); /* Privilege error */ goto out_free; } if (! (lan->channel.priv_info[priv-1].allowed_auths & (1 << auth))) { /* Authentication level not permitted for this privilege */ lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Auth level %d invalid for" " privilege %d", auth, priv); return_err(lan, msg, &dummy_session, IPMI_INVALID_DATA_FIELD_CC); goto out_free; } session = find_free_session(lan); if (!session) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: out of free sessions"); return_err(lan, msg, &dummy_session, 0x81); /* No session slot */ goto out_free; } session->src_addr = lan->channel.alloc(&lan->channel, msg->src_len); if (!session->src_addr) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: out of memory"); return_err(lan, msg, &dummy_session, IPMI_UNKNOWN_ERR_CC); goto out_free; } memcpy(session->src_addr, msg->src_addr, msg->src_len); session->src_len = msg->src_len; session->active = 1; session->rmcpplus = 0; session->authtype = auth; session->authdata = dummy_session.authdata; rv = lan->gen_rand(lan, seq_data, 4); if (rv) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Could not generate random number"); return_err(lan, msg, &dummy_session, IPMI_UNKNOWN_ERR_CC); goto out_free; } session->recv_seq = ipmi_get_uint32(seq_data) & ~1; if (!session->recv_seq) session->recv_seq = 2; session->xmit_seq = xmit_seq; session->max_priv = priv; session->priv = IPMI_PRIVILEGE_USER; /* Start at user privilege. */ session->userid = user->idx; session->time_left = lan->default_session_timeout; lan->channel.active_sessions++; lan->sysinfo->log(lan->sysinfo, NEW_SESSION, msg, "Activate session: Session opened for user 0x%x, max priv %d", user_idx, priv); if (lan->sid_seq == 0) lan->sid_seq++; session->sid = ((lan->sid_seq << (SESSION_BITS_REQ+1)) | (session->handle << 1)); lan->sid_seq++; data[0] = 0; data[1] = auth; ipmi_set_uint32(data+2, session->sid); ipmi_set_uint32(data+6, session->recv_seq); data[10] = session->max_priv; return_rsp_data(lan, msg, &dummy_session, data, 11); return; out_free: ipmi_auths[msg->authtype].authcode_cleanup(dummy_session.authdata); } /* The command handling below is for active sessions. */ static void handle_smi_msg(lanserv_data_t *lan, session_t *session, msg_t *msg) { int rv; rv = channel_smi_send(&lan->channel, msg); if (rv == ENOMEM) return_err(lan, msg, NULL, IPMI_UNKNOWN_ERR_CC); else if (rv == EMSGSIZE) return_err(lan, msg, session, IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC); else if (rv) return_err(lan, msg, session, IPMI_UNKNOWN_ERR_CC); } static void handle_activate_session_cmd(lanserv_data_t *lan, session_t *session, msg_t *msg) { uint8_t data[11]; if (msg->len < 22) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Activate session failure: message too short"); return_err(lan, msg, session, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } /* We are already connected, we ignore everything but the outbound sequence number. */ session->xmit_seq = ipmi_get_uint32(msg->data+18); data[0] = 0; data[1] = session->authtype; ipmi_set_uint32(data+2, session->sid); ipmi_set_uint32(data+6, session->recv_seq); data[10] = session->max_priv; return_rsp_data(lan, msg, session, data, 11); } static void handle_set_session_privilege(lanserv_data_t *lan, session_t *session, msg_t *msg) { uint8_t data[2]; uint8_t priv; if (msg->len < 1) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Set session priv failure: message too short"); return_err(lan, msg, session, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } priv = msg->data[0] & 0xf; if (priv == 0) priv = session->priv; if (priv == IPMI_PRIVILEGE_CALLBACK) { return_err(lan, msg, session, 0x80); /* Can't drop below user priv. */ return; } if (priv > session->max_priv) { return_err(lan, msg, session, 0x81); /* Cannot set the priv this high. */ return; } session->priv = priv; data[0] = 0; data[1] = priv; return_rsp_data(lan, msg, session, data, 2); } static void handle_close_session(lanserv_data_t *lan, session_t *session, msg_t *msg) { uint32_t sid; session_t *nses = session; if (msg->len < 4) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Close session failure: message too short"); return_err(lan, msg, session, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } sid = ipmi_get_uint32(msg->data); if (sid != session->sid) { if (session->priv != IPMI_PRIVILEGE_ADMIN) { /* Only admins can close other people's sessions. */ return_err(lan, msg, session, IPMI_INSUFFICIENT_PRIVILEGE_CC); return; } nses = sid_to_session(lan, sid); if (!nses) { return_err(lan, msg, session, 0x87); /* session not found */ return; } } lan->sysinfo->log(lan->sysinfo, SESSION_CLOSED, msg, "Session closed: Closed due to request"); return_err(lan, msg, session, 0); close_session(lan, nses); } static void handle_get_session_info(lanserv_data_t *lan, session_t *session, msg_t *msg) { uint8_t idx; session_t *nses = NULL; uint8_t data[19]; if (msg->len < 1) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Get session failure: message too short"); return_err(lan, msg, session, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } idx = msg->data[0]; if (idx == 0xff) { unsigned int sid; if (msg->len < 5) { return_err(lan, msg, session, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } sid = ipmi_get_uint32(msg->data+1); nses = sid_to_session(lan, sid); } else if (idx == 0xfe) { int handle; if (msg->len < 2) { return_err(lan, msg, session, IPMI_REQUEST_DATA_LENGTH_INVALID_CC); return; } handle = msg->data[1]; if (handle >= MAX_SESSIONS) { return_err(lan, msg, session, IPMI_INVALID_DATA_FIELD_CC); return; } if (lan->sessions[handle].active) nses = &lan->sessions[handle]; } else if (idx == 0) { nses = session; } else { int i; if (idx <= lan->channel.active_sessions) { for (i=0; i<=MAX_SESSIONS; i++) { if (lan->sessions[i].active) { idx--; if (idx == 0) { nses = &lan->sessions[i]; break; } } } } } data[0] = 0; data[2] = MAX_SESSIONS; data[3] = lan->channel.active_sessions; if (nses) { data[1] = nses->handle; data[4] = nses->userid; data[5] = nses->priv; data[6] = lan->channel.channel_num | (session->rmcpplus << 4); return_rsp_data(lan, msg, session, data, 7); } else { data[1] = 0; return_rsp_data(lan, msg, session, data, 4); } /* FIXME - We don't currently return the IP information, because it's hard to get. Maybe later. */ } static extcmd_map_t ip_src_map[] = { { 0, "unknown" }, { 1, "static" }, { 2, "dhcp" }, { 3, "bios" }, { 4, "other" }, { 0, NULL } }; #define BASETYPE lanparm_data_t static extcmd_info_t lanread_vals[] = { EXTCMD_MEMB(ip_addr, extcmd_ip), EXTCMD_MEMB_MAPUCHAR(ip_addr_src, ip_src_map), EXTCMD_MEMB(mac_addr, extcmd_mac), EXTCMD_MEMB(subnet_mask, extcmd_ip), EXTCMD_MEMB(default_gw_ip_addr, extcmd_ip), EXTCMD_MEMB(default_gw_mac_addr, extcmd_mac), EXTCMD_MEMB(backup_gw_ip_addr, extcmd_ip), EXTCMD_MEMB(backup_gw_mac_addr, extcmd_mac) }; #undef BASETYPE static void write_lan_config(lanserv_data_t *lan) { if (lan->persist_changed) { persist_t *p; p = alloc_persist("lanparm.mc%2.2x.%d", 0x20, lan->channel.channel_num); if (!p) return; add_persist_data(p, lan->lanparm.max_priv_for_cipher_suite, 9, "max_priv_for_cipher"); add_persist_int(p, lan->channel.privilege_limit, "privilege_limit"); write_persist(p); free_persist(p); lan->persist_changed = 0; } if (extcmd_setvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals, lan->lanparm_changed, lanread_len)) { lan->sysinfo->log(lan->sysinfo, OS_ERROR, NULL, "Error writing external LANPARM values"); } else { memset(lan->lanparm_changed, 0, sizeof(lan->lanparm_changed)); } } static void set_channel_access(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { uint8_t upd1, upd2; int write_nonv = 0; uint8_t newv; lanserv_data_t *lan = chan->chan_info; upd1 = (msg->data[1] >> 6) & 0x3; if ((upd1 == 1) || (upd1 == 2)) { newv = (msg->data[1] >> 4) & 1; if (newv) { /* Don't support per-msg authentication */ rdata[0] = 0x83; *rdata_len = 1; return; } newv = (msg->data[1] >> 3) & 1; if (newv) { /* Don't support unauthenticated user-level access */ rdata[0] = 0x83; *rdata_len = 1; return; } newv = (msg->data[1] >> 0) & 7; if (newv != 0x2) { /* Only support "always available" channel */ rdata[0] = 0x83; *rdata_len = 1; return; } #if 0 if (upd1 == 1) { lan->channel.PEF_alerting = (msg->data[1] >> 5) & 1; } else { lan->channel.PEF_alerting_nonv = (msg->data[1] >> 5) & 1; write_nonv = 1; } #endif } else if (upd1 != 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } upd2 = (msg->data[2] >> 6) & 0x3; if ((upd2 == 1) || (upd2 == 2)) { newv = (msg->data[2] >> 0) & 0xf; if ((newv == 0) || (newv > 4)) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (upd2 == 1) { lan->channel.privilege_limit_nonv = newv; write_nonv = 1; } else { lan->channel.privilege_limit = newv; } } else if (upd2 != 0) { rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } if (write_nonv) { lan->persist_changed = 1; write_lan_config(lan); } rdata[0] = 0; *rdata_len = 1; } static void set_lan_config_parms(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { unsigned char err = 0; lanserv_data_t *lan = chan->chan_info; int rv; unsigned char oldval; /* * Note that in all of these, if a set is in progress and the data * value has been modified (but not committed), it will return the * modified value, not the one from the external command. */ switch (msg->data[1]) { case 0: switch (msg->data[2] & 0x3) { case 0: if (lan->lanparm.set_in_progress) { /* rollback */ memcpy(&lan->lanparm, &lan->lanparm_rollback, sizeof(lan->lanparm)); lan->lanparm.set_in_progress = 0; } /* No effect otherwise */ break; case 1: if (lan->lanparm.set_in_progress) err = 0x81; /* Another user is writing. */ else { /* Save rollback data */ memcpy(&lan->lanparm_rollback, &lan->lanparm, sizeof(lan->lanparm)); lan->lanparm.set_in_progress = 1; } break; case 2: if (!lan->lanparm.set_in_progress) { err = 0x81; /* Not in proper state. */ } else { /* Re-save rollback data */ memcpy(&lan->lanparm_rollback, &lan->lanparm, sizeof(lan->lanparm)); write_lan_config(lan); } break; case 3: err = IPMI_INVALID_DATA_FIELD_CC; } break; case 1: case 2: case 17: case 22: case 23: err = 0x82; /* Read-only data */ break; case 3: if (msg->len < 6) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.ip_addr, msg->data+2, 4); lan->lanparm_changed[ip_addr_o] = 1; } break; case 4: oldval = lan->lanparm.ip_addr_src; lan->lanparm.ip_addr_src = msg->data[2]; /* Check to see if the system supports this value */ rv = extcmd_checkvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + ip_addr_src_o, 1); if (rv) { lan->lanparm.ip_addr_src = oldval; rdata[0] = IPMI_INVALID_DATA_FIELD_CC; *rdata_len = 1; return; } lan->lanparm_changed[ip_addr_src_o] = 1; break; case 5: if (msg->len < 8) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.mac_addr, msg->data+2, 6); lan->lanparm_changed[mac_addr_o] = 1; } break; case 6: if (msg->len < 6) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.subnet_mask, msg->data+2, 4); lan->lanparm_changed[subnet_mask_o] = 1; } break; case 7: if (msg->len < 5) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.ipv4_hdr_parms, msg->data+2, 3); } break; case 12: if (msg->len < 6) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.default_gw_ip_addr, msg->data+2, 4); lan->lanparm_changed[default_gw_ip_addr_o] = 1; } break; case 13: if (msg->len < 8) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.default_gw_mac_addr, msg->data+2, 6); lan->lanparm_changed[default_gw_mac_addr_o] = 1; } break; case 14: if (msg->len < 6) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.backup_gw_ip_addr, msg->data+2, 4); lan->lanparm_changed[backup_gw_ip_addr_o] = 1; } break; case 15: if (msg->len < 8) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.backup_gw_mac_addr, msg->data+2, 6); lan->lanparm_changed[backup_gw_mac_addr_o] = 1; } break; case 16: /* Just ignore this. */ break; case 20: if (msg->len < 4) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.vlan_id, msg->data+2, 2); } break; case 21: lan->lanparm.vlan_priority = msg->data[2]; break; case 24: if (msg->len < 11) err = IPMI_REQUEST_DATA_LENGTH_INVALID_CC; else { memcpy(lan->lanparm.max_priv_for_cipher_suite, msg->data+2, 9); lan->persist_changed = 1; } break; default: err = 0x80; /* Parm not supported */ } rdata[0] = err; *rdata_len = 1; } static void get_lan_config_parms(channel_t *chan, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len) { unsigned char databyte = 0; unsigned char databytes[5]; unsigned char *data = NULL; unsigned int length = 0; lanserv_data_t *lan = chan->chan_info; int rv; switch (msg->data[1]) { case 0: databyte = lan->lanparm.set_in_progress; break; case 1: databyte = 0x1f; /* We support all authentications. */ break; case 2: data = databytes; data[0] = chan->priv_info[0].allowed_auths; data[1] = chan->priv_info[1].allowed_auths; data[2] = chan->priv_info[2].allowed_auths; data[3] = chan->priv_info[3].allowed_auths; data[4] = 0; length = 5; break; case 17: databyte = lan->lanparm.num_destinations; break; case 3: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[ip_addr_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + ip_addr_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.ip_addr; length = 4; break; case 4: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[ip_addr_src_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + ip_addr_src_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } databyte = lan->lanparm.ip_addr_src; break; case 5: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[mac_addr_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + mac_addr_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.mac_addr; length = 6; break; case 6: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[subnet_mask_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + subnet_mask_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.subnet_mask; length = 4; break; case 7: /* FIXME - this is not handled */ data = lan->lanparm.ipv4_hdr_parms; length = 3; break; case 12: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[default_gw_ip_addr_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + default_gw_ip_addr_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.default_gw_ip_addr; length = 4; break; case 13: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[default_gw_mac_addr_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + default_gw_mac_addr_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.default_gw_mac_addr; length = 6; break; case 14: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[backup_gw_ip_addr_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + backup_gw_ip_addr_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.backup_gw_ip_addr; length = 4; break; case 15: if (!lan->lanparm.set_in_progress || !lan->lanparm_changed[backup_gw_mac_addr_o]) { rv = extcmd_getvals(lan->sysinfo, &lan->lanparm, lan->config_prog, lanread_vals + backup_gw_mac_addr_o, 1); if (rv) { rdata[0] = IPMI_UNKNOWN_ERR_CC; *rdata_len = 1; return; } } data = lan->lanparm.backup_gw_mac_addr; length = 6; break; case 16: /* Dummy value, we don't support this. */ data = (unsigned char *) "public\0\0\0\0\0\0\0\0\0\0\0\0"; length = 18; break; case 20: /* FIXME - no VLAN support */ data = lan->lanparm.vlan_id; length = 2; break; case 21: /* FIXME - no VLAN support */ databyte = lan->lanparm.vlan_priority; break; case 22: databyte = lan->lanparm.num_cipher_suites; break; case 23: data = lan->lanparm.cipher_suite_entry; length = 17; break; case 24: data = lan->lanparm.max_priv_for_cipher_suite; length = 9; break; default: rdata[0] = 0x80; /* Parm not supported */ *rdata_len = 1; return; } rdata[0] = 0; rdata[1] = 0x11; *rdata_len = 2; if (msg->data[0] & 0x80) return; if (data) { memcpy(rdata + 2, data, length); *rdata_len += length; } else { rdata[2] = databyte; *rdata_len = 3; } } static void handle_normal_session(lanserv_data_t *lan, msg_t *msg) { session_t *session = sid_to_session(lan, msg->sid); int rv; if (session == NULL) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: Invalid SID"); return; } session->time_left = lan->default_session_timeout; if (lan->channel.oem.oem_handle_msg && lan->channel.oem.oem_handle_msg(&lan->channel, msg)) /* OEM code handled the message. */ return; rv = IPMI_PRIV_INVALID; if (lan->channel.oem.oem_check_permitted) rv = lan->channel.oem.oem_check_permitted(session->priv, msg->netfn, msg->cmd); if (rv == IPMI_PRIV_INVALID) rv = ipmi_cmd_permitted(session->priv, msg->netfn, msg->cmd); switch (rv) { case IPMI_PRIV_PERMITTED: break; case IPMI_PRIV_SEND: /* The spec says that operator privilege is require to send on other channels, but that doesn't make any sense. Instead, we look at the message to tell if the operation is permitted. */ rv = ipmi_cmd_permitted(session->priv, msg->data[2]>>2, /* netfn */ msg->data[6]); /* cmd */ if (rv == IPMI_PRIV_PERMITTED) break; /* fallthrough */ case IPMI_PRIV_DENIED: case IPMI_PRIV_BOOT: /* FIXME - this can sometimes be permitted. */ lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: no privilege"); return_err(lan, msg, session, IPMI_INSUFFICIENT_PRIVILEGE_CC); return; case IPMI_PRIV_INVALID: default: lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: Internal error 1"); return_err(lan, msg, session, IPMI_UNKNOWN_ERR_CC); return; } if (msg->netfn == IPMI_APP_NETFN) { switch (msg->cmd) { case IPMI_GET_SYSTEM_GUID_CMD: handle_get_system_guid(lan, session, msg); break; case IPMI_GET_CHANNEL_CIPHER_SUITES_CMD: handle_get_channel_cipher_suites(lan, msg); break; case IPMI_GET_CHANNEL_AUTH_CAPABILITIES_CMD: case IPMI_GET_SESSION_CHALLENGE_CMD: return_err(lan, msg, session, IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC); break; case IPMI_ACTIVATE_SESSION_CMD: handle_activate_session_cmd(lan, session, msg); break; case IPMI_SET_SESSION_PRIVILEGE_CMD: handle_set_session_privilege(lan, session, msg); break; case IPMI_CLOSE_SESSION_CMD: handle_close_session(lan, session, msg); break; case IPMI_GET_SESSION_INFO_CMD: handle_get_session_info(lan, session, msg); break; default: goto normal_msg; } } else { normal_msg: handle_smi_msg(lan, session, msg); } } static void handle_ipmi_payload(lanserv_data_t *lan, msg_t *msg) { if (msg->len < 7) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: Length field too short"); return; } if (ipmb_checksum(msg->data, 3, 0) != 0) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: Checksum 1 failed"); return; } if (ipmb_checksum(msg->data+3, msg->len-3, 0) != 0) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: Checksum 2 failed"); return; } msg->len--; /* Remove the final checksum */ msg->rs_addr = msg->data[0]; msg->netfn = msg->data[1] >> 2; msg->rs_lun = msg->data[1] & 0x3; msg->rq_addr = msg->data[3]; msg->rq_seq = msg->data[4] >> 2; msg->rq_lun = msg->data[4] & 0x3; msg->cmd = msg->data[5]; msg->data += 6; msg->len -= 6; if (msg->sid == 0) { handle_no_session(lan, msg); } else if (msg->sid & 1) { /* We use odd SIDs for temporary ones. */ /* Temp sessions have to be set up before the auth is done, so we can't do that here. */ handle_temp_session(lan, msg); } else { handle_normal_session(lan, msg); } } #ifdef HAVE_OPENSSL static int rakp_hmac_sha1_init(lanserv_data_t *lan, session_t *session) { session->auth_data.akey = EVP_sha1(); session->auth_data.akey_len = 20; session->auth_data.integ_len = 12; return 0; } static int rakp_hmac_md5_init(lanserv_data_t *lan, session_t *session) { session->auth_data.akey = EVP_md5(); session->auth_data.akey_len = 16; session->auth_data.integ_len = 16; return 0; } static int rakp_hmac_set2(lanserv_data_t *lan, session_t *session, unsigned char *data, unsigned int *data_len, unsigned int max_len) { unsigned char idata[74]; unsigned int ilen; const unsigned char *p; user_t *user; auth_data_t *a = &session->auth_data; if (((*data_len) + a->akey_len) > max_len) return E2BIG; ipmi_set_uint32(idata+0, session->rem_sid); ipmi_set_uint32(idata+4, session->sid); memcpy(idata+8, a->rem_rand, 16); memcpy(idata+24, a->rand, 16); memcpy(idata+40, lan->guid, 16); idata[56] = a->role; idata[57] = a->username_len; memcpy(idata+58, a->username, idata[57]); user = &(lan->users[session->userid]); HMAC(a->akey, user->pw, a->akey_len, idata, 58+idata[57], data + *data_len, &ilen); *data_len += a->akey_len; /* Now generate the SIK */ memcpy(idata+0, a->rem_rand, 16); memcpy(idata+16, a->rand, 16); idata[32] = a->role; idata[33] = a->username_len; memcpy(idata+34, a->username, idata[33]); if (lan->bmc_key) p = lan->bmc_key; else p = user->pw; HMAC(a->akey, p, a->akey_len, idata, 34+idata[33], a->sik, &ilen); /* Now generate k1 and k2. */ memset(idata, 1, a->akey_len); HMAC(a->akey, a->sik, a->akey_len, idata, a->akey_len, a->k1, &ilen); memset(idata, 2, a->akey_len); HMAC(a->akey, a->sik, a->akey_len, idata, a->akey_len, a->k2, &ilen); return 0; } static int rakp_hmac_check3(lanserv_data_t *lan, session_t *session, unsigned char *data, unsigned int *data_len) { unsigned char idata[38]; unsigned int ilen; unsigned char integ[20]; user_t *user = &(lan->users[session->userid]); auth_data_t *a = &session->auth_data; if (((*data_len) - a->akey_len) < 8) return E2BIG; memcpy(idata+0, a->rand, 16); ipmi_set_uint32(idata+16, session->rem_sid); idata[20] = a->role; idata[21] = a->username_len; memcpy(idata+22, a->username, idata[21]); HMAC(a->akey, user->pw, a->akey_len, idata, 22+idata[21], integ, &ilen); if (memcmp(integ, data+(*data_len)-a->akey_len, a->akey_len) != 0) return EINVAL; *data_len -= a->akey_len; return 0; } static int rakp_hmac_set4(lanserv_data_t *lan, session_t *session, unsigned char *data, unsigned int *data_len, unsigned int max_len) { unsigned char idata[36]; unsigned int ilen; auth_data_t *a = &session->auth_data; unsigned char integ[20]; if (((*data_len) + a->akey_len) > max_len) return E2BIG; memcpy(idata+0, a->rem_rand, 16); ipmi_set_uint32(idata+16, session->sid); memcpy(idata+20, lan->guid, 16); HMAC(a->akey, a->sik, a->akey_len, idata, 36, integ, &ilen); memcpy(data+*data_len, integ, a->integ_len); *data_len += a->integ_len; return 0; } static auth_handlers_t rakp_hmac_sha1 = { .init = rakp_hmac_sha1_init, .set2 = rakp_hmac_set2, .check3 = rakp_hmac_check3, .set4 = rakp_hmac_set4 }; static auth_handlers_t rakp_hmac_md5 = { .init = rakp_hmac_md5_init, .set2 = rakp_hmac_set2, .check3 = rakp_hmac_check3, .set4 = rakp_hmac_set4 }; #define RAKP_INIT , &rakp_hmac_sha1, &rakp_hmac_md5 static int hmac_sha1_init(lanserv_data_t *lan, session_t *session) { session->auth_data.ikey2 = EVP_sha1(); session->auth_data.ikey = session->auth_data.k1; session->auth_data.ikey_len = 20; session->auth_data.integ_len = 12; return 0; } static int hmac_md5_init(lanserv_data_t *lan, session_t *session) { user_t *user = &(lan->users[session->userid]); session->auth_data.ikey2 = EVP_md5(); session->auth_data.ikey = user->pw; session->auth_data.ikey_len = 16; session->auth_data.integ_len = 16; return 0; } static void hmac_cleanup(lanserv_data_t *lan, session_t *session) { } static int hmac_add(lanserv_data_t *lan, session_t *session, unsigned char *pos, unsigned int *data_len, unsigned int data_size) { auth_data_t *a = &session->auth_data; unsigned int ilen; unsigned char integ[20]; if (((*data_len) + a->ikey_len) > data_size) return E2BIG; HMAC(a->ikey2, a->ikey, a->ikey_len, pos+4, (*data_len)-4, integ, &ilen); memcpy(pos+(*data_len), integ, a->integ_len); *data_len += a->integ_len; return 0; } static int hmac_check(lanserv_data_t *lan, session_t *session, msg_t *msg) { unsigned char integ[20]; auth_data_t *a = &session->auth_data; unsigned int ilen; if ((msg->len-5) < a->integ_len) return E2BIG; HMAC(a->ikey2, a->ikey, a->ikey_len, msg->data, msg->len-a->integ_len, integ, &ilen); if (memcmp(msg->data+msg->len-a->integ_len, integ, a->integ_len) != 0) return EINVAL; return 0; } static void * auth_alloc(void *info, int size) { return malloc(size); } static void auth_free(void *info, void *data) { free(data); } static int md5_init(lanserv_data_t *lan, session_t *session) { user_t *user = &(lan->users[session->userid]); int rv; ipmi_authdata_t idata; rv = ipmi_md5_authcode_initl(user->pw, 20, &idata, NULL, auth_alloc, auth_free); if (rv) return rv; session->auth_data.idata = idata; session->auth_data.ikey_len = 16; return 0; } static void md5_cleanup(lanserv_data_t *lan, session_t *session) { ipmi_md5_authcode_cleanup(session->auth_data.idata); session->auth_data.idata = NULL; } static int md5_add(lanserv_data_t *lan, session_t *session, unsigned char *pos, unsigned int *data_len, unsigned int data_size) { auth_data_t *a = &session->auth_data; ipmi_auth_sg_t data[2]; int rv; if (((*data_len) + a->ikey_len) > data_size) return E2BIG; data[0].data = pos+4; data[0].len = (*data_len)-4; data[1].data = NULL; rv = ipmi_md5_authcode_gen(a->idata, data, pos+(*data_len)); if (rv) return rv; *data_len += a->ikey_len; return 0; } static int md5_check(lanserv_data_t *lan, session_t *session, msg_t *msg) { auth_data_t *a = &session->auth_data; ipmi_auth_sg_t data[2]; int rv; if ((msg->len-5) < a->ikey_len) return E2BIG; data[0].data = msg->data; data[0].len = msg->len - a->ikey_len; data[1].data = NULL; rv = ipmi_md5_authcode_check(a->idata, data, msg->data + msg->len - a->ikey_len); return rv; } static integ_handlers_t hmac_sha1_integ = { hmac_sha1_init, hmac_cleanup, hmac_add, hmac_check }; static integ_handlers_t hmac_md5_integ = { hmac_md5_init, hmac_cleanup, hmac_add, hmac_check }; static integ_handlers_t md5_integ = { md5_init, md5_cleanup, md5_add, md5_check }; #define HMAC_INIT , &hmac_sha1_integ, &hmac_md5_integ #define MD5_INIT , &md5_integ static int aes_cbc_init(lanserv_data_t *lan, session_t *session) { session->auth_data.ckey = session->auth_data.k2; session->auth_data.ckey_len = 16; return 0; } static void aes_cbc_cleanup(lanserv_data_t *lan, session_t *session) { } static int aes_cbc_encrypt(lanserv_data_t *lan, session_t *session, unsigned char **pos, unsigned int *hdr_left, unsigned int *data_len, unsigned int *data_size) { auth_data_t *a = &session->auth_data; unsigned int l = *data_len; unsigned char *d; unsigned char *iv; unsigned int i; EVP_CIPHER_CTX *ctx; int rv; int outlen; int tmplen; unsigned char *padpos; unsigned char padval; unsigned int padlen; if (*hdr_left < 16) return E2BIG; /* Calculate the number of padding bytes -> e. Note that the pad length byte is included, thus the +1. We don't add the pad, AES does, but we need to know what it is. */ /* Calculate the number of padding bytes -> e. Note that the pad length byte is included, thus the +1. We then do the padding. */ padlen = 15 - (l % 16); l += padlen + 1; if (l > *data_size) return E2BIG; /* We store the unencrypted data here, then crypt into the real data. */ d = malloc(l); if (!d) return ENOMEM; memcpy(d, *pos, *data_len); /* Now add the padding. */ padpos = d + *data_len; padval = 1; for (i=0; igen_rand(lan, iv, 16); if (rv) { free(d); return rv; } *hdr_left -= 16; *data_size += 16; /* Ok, we're set to do the crypt operation. */ ctx = EVP_CIPHER_CTX_new(); if (!ctx) { rv = ENOMEM; goto out_cleanup; } EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, a->ckey, iv); EVP_CIPHER_CTX_set_padding(ctx, 0); if (!EVP_EncryptUpdate(ctx, *pos, &outlen, d, l)) { rv = ENOMEM; goto out_cleanup; } if (!EVP_EncryptFinal_ex(ctx, (*pos) + outlen, &tmplen)) { rv = ENOMEM; /* right? */ goto out_cleanup; } outlen += tmplen; *pos = iv; *data_len = outlen + 16; out_cleanup: EVP_CIPHER_CTX_free(ctx); free(d); return rv; } static int aes_cbc_decrypt(lanserv_data_t *lan, session_t *session, msg_t *msg) { auth_data_t *a = &session->auth_data; unsigned int l = msg->len; unsigned char *d; EVP_CIPHER_CTX *ctx; int outlen; unsigned char *pad; int padlen; int rv = 0; if (l < 32) /* Not possible with this algorithm. */ return EINVAL; l -= 16; /* We store the encrypted data here, then decrypt into the real data. */ d = malloc(l); if (!d) return ENOMEM; memcpy(d, msg->data+16, l); /* Ok, we're set to do the decrypt operation. */ ctx = EVP_CIPHER_CTX_new(); if (!ctx) { rv = ENOMEM; goto out_cleanup; } EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, a->k2, msg->data); EVP_CIPHER_CTX_set_padding(ctx, 0); if (!EVP_DecryptUpdate(ctx, msg->data+16, &outlen, d, l)) { rv = EINVAL; goto out_cleanup; } if (outlen < 16) { rv = EINVAL; goto out_cleanup; } /* Now remove the padding */ pad = msg->data + 16 + outlen - 1; padlen = *pad; if (padlen >= 16) { rv = EINVAL; goto out_cleanup; } outlen--; pad--; while (padlen) { if (*pad != padlen) { rv = EINVAL; goto out_cleanup; } outlen--; pad--; padlen--; } msg->data += 16; /* Remove the init vector */ msg->len = outlen; out_cleanup: EVP_CIPHER_CTX_free(ctx); free(d); return rv; } static conf_handlers_t aes_cbc_conf = { aes_cbc_init, aes_cbc_cleanup, aes_cbc_encrypt, aes_cbc_decrypt }; #define AES_CBC_INIT , &aes_cbc_conf unsigned int default_auth = 1; /* RAKP-HMAC-SHA1 */ unsigned int default_integ = 1; /* HMAC-SHA1-96 */ unsigned int default_conf = 1; /* AES-CBC-128 */ #else #define RAKP_INIT , NULL, NULL #define MD5_INIT , NULL #define HMAC_INIT , NULL #define AES_CBC_INIT , NULL unsigned int default_auth = 0; unsigned int default_integ = 0; unsigned int default_conf = 0; #endif integ_handlers_t *integs[64] = { NULL HMAC_INIT MD5_INIT }; conf_handlers_t *confs[64] = { NULL AES_CBC_INIT }; auth_handlers_t *auths[64] = { NULL RAKP_INIT }; struct valid_cypher_suites_s { int auth, integ, conf; } valid_cipher_suites[] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 1, 3 }, { 2, 0, 0 }, { 2, 2, 0 }, { 2, 2, 1 }, { 2, 2, 2 }, { 2, 2, 3 }, { 2, 3, 0 }, { 2, 3, 1 }, { 2, 3, 2 }, { 2, 3, 3 }, { -1, -1. -1 } }; static void handle_open_session_payload(lanserv_data_t *lan, msg_t *msg) { unsigned char data[36]; unsigned char priv, max_priv; unsigned char auth; unsigned char integ; unsigned char conf; session_t *session = NULL; uint32_t rem_sid; unsigned char err; int i; int rv; if (msg->sid != 0) { err = IPMI_RMCPP_INVALID_SESSION_ID; goto out_err; } if (msg->len < 32) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } priv = msg->data[1] & 0xf; if (priv > 4) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } rem_sid = ipmi_get_uint32(msg->data+4); if (rem_sid == 0) { err = IPMI_RMCPP_INVALID_SESSION_ID; goto out_err; } if (msg->data[8] != 0) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } if (msg->data[11] == 0) auth = default_auth; else if (msg->data[11] != 8) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } else auth = msg->data[12] & 0x3f; if (auth && !auths[auth]) { err = IPMI_RMCPP_INVALID_AUTHENTICATION_ALGORITHM; goto out_err; } if (msg->data[16] != 1) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } if (msg->data[19] == 0) integ = default_integ; else if (msg->data[19] != 8) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } else integ = msg->data[20] & 0x3f; if (integ && !integs[integ]) { err = IPMI_RMCPP_INVALID_INTEGRITY_ALGORITHM; goto out_err; } if (msg->data[24] != 2) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } if (msg->data[27] == 0) conf = default_conf; else if (msg->data[27] != 8) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } else conf = msg->data[28] & 0x3f; if (conf && !confs[conf]) { err = IPMI_RMCPP_INVALID_CONFIDENTIALITY_ALGORITHM; goto out_err; } for (i=0; ; i++) { if (valid_cipher_suites[i].auth == -1) break; if ((valid_cipher_suites[i].auth == auth) && (valid_cipher_suites[i].integ == integ) && (valid_cipher_suites[i].conf == conf)) break; } if (valid_cipher_suites[i].auth == -1) { err = IPMI_RMCPP_NO_CIPHER_SUITE_MATCHES; goto out_err; } max_priv = lan->lanparm.max_priv_for_cipher_suite[priv >> 1]; if (max_priv & 1) max_priv >>= 4; max_priv &= 0xf; if (priv > max_priv) { err = IPMI_RMCPP_UNAUTHORIZED_ROLE_OR_PRIVILEGE; goto out_err; } session = find_free_session(lan); if (!session) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: out of free sessions"); err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION; goto out_err; } session->src_addr = lan->channel.alloc(&lan->channel, msg->src_len); if (!session->src_addr) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: out of memory"); err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION; goto out_err; } memcpy(session->src_addr, msg->src_addr, msg->src_len); session->src_len = msg->src_len; session->active = 1; session->in_startup = 1; session->rmcpplus = 1; session->authtype = IPMI_AUTHTYPE_RMCP_PLUS; rv = lan->gen_rand(lan, session->auth_data.rand, 16); if (rv) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "Activate session failed: Could not generate random number"); err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION; goto out_err; } session->recv_seq = 1; session->xmit_seq = 1; session->unauth_recv_seq = 1; session->unauth_xmit_seq = 1; session->rem_sid = rem_sid; session->auth = auth; session->authh = auths[auth]; if (session->authh) session->authh->init(lan, session); session->integ = integ; session->integh = integs[integ]; session->conf = conf; session->confh = confs[conf]; session->userid = 0; session->time_left = lan->default_session_timeout; session->sid = ((lan->sid_seq << (SESSION_BITS_REQ+1)) | (session->handle << 1)); lan->sid_seq++; lan->sysinfo->log(lan->sysinfo, NEW_SESSION, msg, "Activate session: Session started, max priv %d", priv); memset(data, 0, sizeof(data)); data[0] = msg->data[0]; data[1] = 0; data[2] = priv; ipmi_set_uint32(data+4, session->rem_sid); ipmi_set_uint32(data+8, session->sid); data[12] = 0; data[15] = 8; data[16] = auth; data[20] = 1; data[23] = 8; data[24] = integ; data[28] = 2; data[31] = 8; data[32] = conf; lan->channel.active_sessions++; return_rmcpp_rsp(lan, session, msg, 0x11, data, 36, NULL, 0); return; out_err: data[0] = msg->data[0]; data[1] = err; return_rmcpp_rsp(lan, session, msg, 0x11, data, 2, NULL, 0); if (session) close_session(lan, session); } static void handle_rakp1_payload(lanserv_data_t *lan, msg_t *msg) { unsigned char data[64]; unsigned char priv; session_t *session = NULL; uint32_t sid; unsigned char err = 0; unsigned char username[17]; int name_only_lookup; unsigned char name_len; user_t *user; unsigned int len; if (msg->sid != 0) return; if (msg->len < 28) return; sid = ipmi_get_uint32(msg->data+4); if (sid == 0) return; session = sid_to_session(lan, sid); if (!session) return; memcpy(session->auth_data.rem_rand, msg->data+8, 16); session->auth_data.role = msg->data[24]; priv = msg->data[24] & 0xf; if (priv > 4) { err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } name_only_lookup = (msg->data[24] >> 4) & 1; name_len = msg->data[27]; if (name_len > 16) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "RAKP msg: name length too long: %d", name_len); err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } if ((unsigned int) (28+name_len) > msg->len) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "RAKP msg: name length doesn't match: %d", name_len); err = IPMI_RMCPP_ILLEGAL_PARAMETER; goto out_err; } session->max_priv = priv; session->priv = IPMI_PRIVILEGE_USER; /* Start at user privilege. */ memset(username, 0, sizeof(username)); memcpy(username, msg->data+28, name_len); user = find_user(lan, username, name_only_lookup, priv); if (!user) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "RAKP msg: invalid user: %s", username); err = IPMI_RMCPP_UNAUTHORIZED_NAME; goto out_err; } session->userid = user->idx; session->auth_data.username_len = name_len; memcpy(session->auth_data.username, username, 16); if (session->integh) { int rv = session->integh->init(lan, session); if (rv) { err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION; goto out_err; } } if (session->confh) { int rv = session->confh->init(lan, session); if (rv) { err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION; goto out_err; } } out_err: memset(data, 0, sizeof(data)); data[0] = msg->data[0]; data[1] = err; ipmi_set_uint32(data+4, session->rem_sid); memcpy(data+8, session->auth_data.rand, 16); memcpy(data+24, lan->guid, 16); len = 40; if (session->authh) { int rv; rv = session->authh->set2(lan, session, data, &len, sizeof(data)); if (rv) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "RAKP msg: set2 failed: 0x%x", rv); return; } } return_rmcpp_rsp(lan, session, msg, 0x13, data, len, NULL, 0); if (err) close_session(lan, session); } static void handle_rakp3_payload(lanserv_data_t *lan, msg_t *msg) { unsigned char data[32]; session_t *session = NULL; uint32_t sid; unsigned char err = 0; unsigned int len; if (msg->sid != 0) return; if (msg->len < 8) return; sid = ipmi_get_uint32(msg->data+4); if (sid == 0) return; session = sid_to_session(lan, sid); if (!session) return; if (session->authh) { int rv; rv = session->authh->check3(lan, session, msg->data, &msg->len); if (rv) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "RAKP msg: check3 failed: 0x%x", rv); err = 0x0f; /* Invalid integrity check */ goto out_err; } } if (msg->data[1]) { /* Other end reported an error, shut down. */ close_session(lan, session); return; } out_err: memset(data, 0, sizeof(data)); data[0] = msg->data[0]; data[1] = err; ipmi_set_uint32(data+4, session->rem_sid); len = 8; if (session->authh) { int rv; rv = session->authh->set4(lan, session, data, &len, sizeof(data)); if (rv) { lan->sysinfo->log(lan->sysinfo, NEW_SESSION_FAILED, msg, "RAKP msg: set4 failed: 0x%x", rv); } } return_rmcpp_rsp(lan, session, msg, 0x15, data, len, NULL, 0); if (err) close_session(lan, session); else session->in_startup = 0; } ipmi_payload_handler_cb payload_handlers[64] = { [0] = handle_ipmi_payload, [0x10] = handle_open_session_payload, [0x12] = handle_rakp1_payload, [0x14] = handle_rakp3_payload, }; int ipmi_register_payload(unsigned int payload_id, ipmi_payload_handler_cb handler) { if (payload_id >= 64) return EINVAL; if (payload_handlers[payload_id]) return EBUSY; payload_handlers[payload_id] = handler; return 0; } static int decrypt_message(lanserv_data_t *lan, session_t *session, msg_t *msg) { if (!msg->rmcpp.encrypted) { if (session->conf != 0) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Message failure:" " Unencrypted msg on encrypted session"); return EINVAL; } return 0; } return session->confh->decrypt(lan, session, msg); } static int check_message_integrity(lanserv_data_t *lan, session_t *session, msg_t *msg) { if (!msg->rmcpp.authenticated) { if (session->integ != 0) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Message failure:" " Unauthenticated msg on authenticated session"); return EINVAL; } return 0; } else if (session->integ == 0) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Message failure:" " Authenticated msg on unauthenticated session"); return EINVAL; } return session->integh->check(lan, session, msg); } static void ipmi_handle_rmcpp_msg(lanserv_data_t *lan, msg_t *msg) { unsigned int len; uint32_t *seq; msg_t imsg; imsg.data = msg->data-1; imsg.len = msg->len+1; if (msg->len < 11) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: message too short"); return; } msg->rmcpp.payload = msg->data[0] & 0x3f; msg->rmcpp.encrypted = (msg->data[0] >> 7) & 1; msg->rmcpp.authenticated = (msg->data[0] >> 6) & 1; msg->data++; if (msg->rmcpp.payload == 2) { if (msg->len < 17) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: message too short"); return; } memcpy(msg->rmcpp.iana, msg->data + 1, 3); msg->data += 4; msg->rmcpp.payload_id = ipmi_get_uint16(msg->data); msg->data += 2; } msg->sid = ipmi_get_uint32(msg->data); msg->data += 4; msg->seq = ipmi_get_uint32(msg->data); msg->data += 4; len = ipmi_get_uint16(msg->data); msg->data += 2; if (len > msg->len) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: Length field invalid: %d, %d", len, msg->len); return; /* The length field is not valid. We allow extra bytes, but reject if not enough. */ } msg->rmcpp.authdata_len = msg->len - len; msg->rmcpp.authdata = msg->data + len; msg->len = len; if (msg->sid == 0) { if (msg->rmcpp.authenticated || msg->rmcpp.encrypted) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure:" " Got encrypted or authenticated SID 0 msg"); return; } } else { session_t *session = sid_to_session(lan, msg->sid); int rv; int diff; if (session == NULL) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: Invalid SID"); return; } if (!session->rmcpplus) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure:" " RMCP+ msg on RMCP session"); return; } imsg.rmcpp.encrypted = msg->rmcpp.encrypted; imsg.rmcpp.authenticated = msg->rmcpp.authenticated; rv = check_message_integrity(lan, session, &imsg); if (rv) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure:" " Message integrity failed"); return; } rv = decrypt_message(lan, session, msg); if (rv) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure:" " Message decryption failed"); return; } /* Check that the session sequence number is valid. We make sure it is within 8 of the last highest received sequence number, per the spec. */ if (msg->rmcpp.authenticated) seq = &session->recv_seq; else seq = &session->unauth_recv_seq; diff = msg->seq - *seq; if ((diff < -16) || (diff > 15)) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: SEQ out of range"); return; } /* We wait until after the message is authenticated to set the sequence number, to prevent spoofing. */ if (msg->seq > *seq) *seq = msg->seq; } if (payload_handlers[msg->rmcpp.payload]) payload_handlers[msg->rmcpp.payload](lan, msg); } static void ipmi_handle_rmcp_msg(lanserv_data_t *lan, msg_t *msg) { unsigned char *tsid; unsigned char *tseq; if (msg->len < 9) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: message too short"); return; } tseq = msg->data+0; msg->seq = ipmi_get_uint32(msg->data+0); tsid = msg->data+4; msg->sid = ipmi_get_uint32(msg->data+4); if (msg->authtype != IPMI_AUTHTYPE_NONE) { if (msg->len < 25) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: message too short"); return; } memcpy(msg->rmcp.authcode_data, msg->data + 8, 16); msg->rmcp.authcode = msg->rmcp.authcode_data; msg->data += 24; msg->len -= 24; } else { msg->rmcp.authcode = NULL; msg->data += 8; msg->len -= 8; } if (msg->len < msg->data[0]) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, msg, "LAN msg failure: Length field invalid"); return; /* The length field is not valid. We allow extra bytes, but reject if not enough. */ } msg->len = msg->data[0]; msg->data++; /* Validate even, non-zero sids here. The odd sids are temporary sessions and get authenticated in that handling. */ if ((msg->sid > 0) && ((msg->sid & 1) == 0)) { /* The "-6, +7" is cheating a little, but we need the last checksum to correctly calculate the code. */ session_t *session = sid_to_session(lan, msg->sid); int rv; int diff; if (session == NULL) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: Invalid SID"); return; } if (session->rmcpplus) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure:" " RMCP msg on RMCP+ session"); return; } rv = auth_check(session, tsid, tseq, msg->data, msg->len, msg->rmcp.authcode); if (rv) { lan->sysinfo->log(lan->sysinfo, AUTH_FAILED, msg, "Normal session message failure: auth failure"); return; } /* Check that the session sequence number is valid. We make sure it is within 8 of the last highest received sequence number, per the spec. */ diff = msg->seq - session->recv_seq; if ((diff < -8) || (diff > 8)) { lan->sysinfo->log(lan->sysinfo, INVALID_MSG, msg, "Normal session message failure: SEQ out of range"); return; } /* We wait until after the message is authenticated to set the sequence number, to prevent spoofing. */ if (msg->seq > session->recv_seq) session->recv_seq = msg->seq; } handle_ipmi_payload(lan, msg); } void ipmi_handle_lan_msg(lanserv_data_t *lan, uint8_t *data, int len, void *from_addr, int from_len) { msg_t msg; msg.src_addr = from_addr; msg.src_len = from_len; msg.oem_data = 0; if (len < 5) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, &msg, "LAN msg failure: message too short"); return; } if (data[2] != 0xff) { lan->sysinfo->log(lan->sysinfo, LAN_ERR, &msg, "LAN msg failure: seq not ff"); return; /* Sequence # must be ff (no ack) */ } msg.authtype = data[4]; msg.data = data+5; msg.len = len - 5; msg.channel = lan->channel.channel_num; msg.orig_channel = &lan->channel; if (msg.authtype == IPMI_AUTHTYPE_RMCP_PLUS) { ipmi_handle_rmcpp_msg(lan, &msg); } else { ipmi_handle_rmcp_msg(lan, &msg); } } static void ipmi_lan_tick(void *info, unsigned int time_since_last) { lanserv_data_t *lan = info; int i; for (i=1; i<=MAX_SESSIONS; i++) { if (lan->sessions[i].active) { if (lan->sessions[i].time_left <= time_since_last) { msg_t msg = { 0 }; /* A fake message to hold the address. */ msg.src_addr = lan->sessions[i].src_addr; msg.src_len = lan->sessions[i].src_len; lan->sysinfo->log(lan->sysinfo, SESSION_CLOSED, &msg, "Session closed: Closed due to timeout"); close_session(lan, &(lan->sessions[i])); } else { lan->sessions[i].time_left -= time_since_last; } } } } static int read_lan_config(lanserv_data_t *lan) { unsigned int i; persist_t *p; void *data; unsigned int len; long iv; p = read_persist("lanparm.mc%2.2x.%d", 0x20, lan->channel.channel_num); if (p && !read_persist_data(p, &data, &len, "max_priv_for_cipher")) { if (len > 9) len = 9; memcpy(lan->lanparm.max_priv_for_cipher_suite, data, len); free_persist_data(data); } else { for (i = 0; i < 9; i++) lan->lanparm.max_priv_for_cipher_suite[i] = IPMI_PRIVILEGE_ADMIN | (IPMI_PRIVILEGE_ADMIN << 4); } if (p && !read_persist_int(p, &iv, "privilege_limit")) { lan->channel.privilege_limit_nonv = iv; lan->channel.privilege_limit = iv; } else { lan->channel.privilege_limit_nonv = IPMI_PRIVILEGE_ADMIN; lan->channel.privilege_limit = IPMI_PRIVILEGE_ADMIN; } if (p) free_persist(p); return 0; } static int set_associated_mc(channel_t *chan, uint32_t session_id, unsigned int payload, lmc_data_t *mc, uint16_t *port, void (*close)(lmc_data_t *mc, uint32_t session_id, void *cb_data), void *cb_data) { lanserv_data_t *lan = chan->chan_info; session_t *session = sid_to_session(lan, session_id); lmc_data_t *emc; if (payload >= LANSERV_NUM_CLOSERS) return EINVAL; if (!session) return EINVAL; emc = session->closers[payload].mc; if (emc && mc && (mc != emc)) return EBUSY; session->closers[payload].close_cb = close; session->closers[payload].close_cb_data = cb_data; session->closers[payload].mc = mc; if (port) *port = lan->port; return 0; } static lmc_data_t * get_associated_mc(channel_t *chan, uint32_t session_id, unsigned int payload) { lanserv_data_t *lan = chan->chan_info; session_t *session = sid_to_session(lan, session_id); if (payload >= LANSERV_NUM_CLOSERS || session == NULL) return NULL; return session->closers[payload].mc; } int ipmi_lan_init(lanserv_data_t *lan) { unsigned int i; int rv; uint8_t challenge_data[16]; for (i=0; i<=MAX_SESSIONS; i++) { lan->sessions[i].handle = i; } rv = read_lan_config(lan); if (rv) return rv; lan->lanparm.num_destinations = 0; /* LAN alerts not supported */ lan->lanparm.num_cipher_suites = 15; for (i=0; i<17; i++) lan->lanparm.cipher_suite_entry[i] = i; lan->channel.return_rsp = lan_return_rsp; lan->channel.get_lan_parms = get_lan_config_parms; lan->channel.set_lan_parms = set_lan_config_parms; lan->channel.set_chan_access = set_channel_access; lan->channel.set_associated_mc = set_associated_mc; lan->channel.get_associated_mc = get_associated_mc; lan->channel.has_recv_q = 1; /* Force user 1 to be a null user. */ memset(lan->users[1].username, 0, 16); rv = lan->gen_rand(lan, challenge_data, 16); if (rv) goto out; rv = ipmi_md5_authcode_init(challenge_data, &(lan->challenge_auth), lan, ialloc, ifree); if (rv) goto out; lan->sid_seq = 0; lan->next_challenge_seq = 0; /* Default the timeout to 30 seconds. */ if (lan->default_session_timeout == 0) lan->default_session_timeout = 30; chan_init(&lan->channel); lan->tick_handler.handler = ipmi_lan_tick; lan->tick_handler.info = lan; lan->sysinfo->register_tick_handler(&lan->tick_handler); out: return rv; } OpenIPMI-2.0.33/lanserv/sol.h0000664000175000017500000000720214002617260012521 00000000000000/* * sol.h * * MontaVista IPMI LAN server include file * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2003,2004,2005 MontaVista Software Inc. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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. */ #ifndef SOL_H #define SOL_H /* * SOL handling */ typedef struct solparm_s { int enabled; int bitrate; int bitrate_nonv; int default_bitrate; } solparm_t; typedef struct soldata_s soldata_t; typedef struct ipmi_sol_s { int configured; char *device; /* TCP-specific information. */ const char *tcpdest; const char *tcpport; int do_telnet; int set_in_progress; solparm_t solparm; solparm_t solparm_rollback; void (*update_bitrate)(lmc_data_t *mc); int active; uint32_t session_id; /* A history buffer, hooking to instance 2 will dump it, if it's non-zero */ unsigned int history_size; int history_active; uint32_t history_session_id; /* History is stored in this file is the program fails. */ char *backupfile; int use_rtscts; int readclear; soldata_t *soldata; } ipmi_sol_t; void ipmi_sol_activate(lmc_data_t *mc, channel_t *channel, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); void ipmi_sol_deactivate(lmc_data_t *mc, channel_t *channel, msg_t *msg, unsigned char *rdata, unsigned int *rdata_len); #endif /* SOL_H */ OpenIPMI-2.0.33/lanserv/ipmb_ipmi.c0000664000175000017500000001401314002617260013662 00000000000000/* * ipmb_ipmi.c * * IPMB server interface. * * Copyright 2019 Mellanox * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * Lesser General Public License (GPL) Version 2 or the modified BSD * license below. The following disclamer applies to both licenses: * * 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. * * GNU Lesser General Public Licence * * 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. * * 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 #include #include #include #define IPMIDEV_MAX_SIZE 15 static void ipmb_send(msg_t *imsg, ipmbserv_data_t *ipmb) { unsigned char msg[(IPMI_SIM_MAX_MSG_LENGTH + 7) * 3]; unsigned int msg_len; msg[0] = imsg->len + 7; msg[1] = imsg->rs_addr; msg[2] = (imsg->netfn << 2) | imsg->rs_lun; msg[3] = -ipmb_checksum(msg + 1, 2, 0); msg[4] = imsg->rq_addr; msg[5] = (imsg->rq_seq << 2) | imsg->rq_lun; msg[6] = imsg->cmd; memcpy(msg + 7, imsg->data, imsg->len); msg_len = imsg->len + 7; msg[msg_len] = -ipmb_checksum(msg + 4, msg_len - 4, 0); msg_len++; if (ipmb->sysinfo->debug & DEBUG_RAW_MSG) debug_log_raw_msg(ipmb->sysinfo, msg, msg_len, "Raw ipmb send:"); ipmb->send_out(ipmb, msg, msg_len); } static void ipmb_return_rsp(channel_t *chan, msg_t *imsg, rsp_msg_t *rsp) { ipmbserv_data_t *ipmb = chan->chan_info; msg_t msg; msg.netfn = rsp->netfn; msg.cmd = rsp->cmd; msg.data = rsp->data; msg.len = rsp->data_len; msg.rq_lun = imsg->rs_lun; msg.rq_addr = imsg->rs_addr; msg.rs_lun = imsg->rq_lun; msg.rs_addr = imsg->rq_addr; msg.rq_seq = imsg->rq_seq; ipmb_send(&msg, ipmb); } int ipmbserv_init(ipmbserv_data_t *ipmb) { ipmb->channel.return_rsp = ipmb_return_rsp; chan_init(&ipmb->channel); return 0; } void ipmbserv_handle_data(ipmbserv_data_t *ipmb, uint8_t *imsg, unsigned int len) { msg_t msg; if (len < 8) { fprintf(stderr, "Message too short\n"); return; } /* subtract len field and checksum */ len--; imsg++; if (ipmb_checksum(imsg, len, 0) != 0) { fprintf(stderr, "Message checksum failure\n"); return; } len--; memset(&msg, 0, sizeof(msg)); msg.rs_addr = imsg[0]; msg.netfn = imsg[1] >> 2; msg.rs_lun = imsg[1] & 3; /* imsg[2] is first checksum */ msg.rq_addr = imsg[3]; msg.rq_seq = imsg[4] >> 2; msg.rq_lun = imsg[4] & 3; msg.cmd = imsg[5]; msg.len = len - 6; msg.data = imsg + 6; msg.src_addr = NULL; msg.src_len = 0; channel_smi_send(&ipmb->channel, &msg); } int ipmbserv_read_config(char **tokptr, sys_data_t *sys, const char **errstr) { ipmbserv_data_t *ipmb; unsigned int chan_num; int err; const char *tok; char *ipmbdev; err = get_uint(tokptr, &chan_num, errstr); if (err) return -1; if (chan_num >= IPMI_MAX_CHANNELS) { *errstr = "Invalid channel number, must be 0-15"; return -1; } /* * Allow an IPMB channel to override the default channel 0. */ if (chan_num != 0 && sys->chan_set[chan_num]) { *errstr = "Channel already in use"; return -1; } tok = mystrtok(NULL, " \t\n", tokptr); if (!tok || strcmp(tok, "ipmb_dev_int")) { *errstr = "Config file missing "; return -1; } tok = mystrtok(NULL, " \t\n", tokptr); if (strlen(tok) > IPMIDEV_MAX_SIZE) { *errstr = "Length of device file name %s > 15"; return -1; } ipmbdev = strdup(tok); if (!ipmbdev) { *errstr = "Unable to alloc device file name"; return -1; } ipmb = malloc(sizeof(*ipmb)); if (!ipmb) { free(ipmbdev); *errstr = "Out of memory"; return -1; } memset(ipmb, 0, sizeof(*ipmb)); ipmb->ipmbdev = ipmbdev; ipmb->channel.session_support = IPMI_CHANNEL_SESSION_LESS; ipmb->channel.medium_type = IPMI_CHANNEL_MEDIUM_IPMB; ipmb->channel.protocol_type = IPMI_CHANNEL_PROTOCOL_IPMB; ipmb->channel.channel_num = chan_num; ipmb->sysinfo = sys; ipmb->channel.chan_info = ipmb; if (chan_num == 0) ipmb->channel.prim_ipmb_in_cfg_file = 1; else ipmb->channel.prim_ipmb_in_cfg_file = 0; sys->chan_set[chan_num] = &ipmb->channel; return 0; } OpenIPMI-2.0.33/CONFIGURING_FOR_LAN0000644000175000017500000001133612002623311012767 00000000000000I get asked this question a lot. Configuring a LAN interface is unfortunately complex because you have to do a bunch of different things to get one up and running. However, it can be done. First, I *strongly* recommend using the GUI for this. There are many parameters, far too many to easily handle in a command-line interface. It can be done with a command-line interface, but it is ugly. The first thing to do is open a connection to the system. Generally you would be doing this on a local BMC (because the LAN is not working), so I'll assume that. You can configure LAN remotely, with the obvious risks. Anyway, in the GUI, do File->Open Domain, select "smi", and select 0 for the interface (assuming that's the one you want). Let the connection come up. In openipmish, do: domain open local smi 0 and wait for it to come up. Once up, you have 3 major configuration items: * Channel configuration * User configuration * LAN Parameters CHANNEL CONFIGURATION --------------------- Once your connection is up, you need to figure out what channels need to be configured. Systems with more than one Ethernet port will generally have one channel for each port. In this case, figuring out which port goes to which channel is left as an exercise for the reader. You can list all the channels by right-clicking on the MC in the GUI and choosing "Channel Info", or by doing: mc chan info in ipmish. You are looking for channels with a medium of 4, or 8023_LAN. Once you have the channel(s), you need to enable them. Iin the GUI, open the tree for each channel you need to configure, and open up user access. There are two different user access setting, one is volatile (and will be set immediately) the other is non-volatile (and will be restored upon power-up). You need to set both of them. Enable "Per Msg Auth", "User Auth", set the "Access Mode" to "ALWAYS", and set the "Privilege Limit" to the limit you want, generally "admin". Then "Save" the configuration. In openipmish, do "help mc chan" and follow the instructions for the "set_access" command. USER CONFIGURATION ------------------ After this, re-open the channel menu because you need that to get to the user and LANPARM configuration. Right click on each channel you need to configure and choose "User Info". You need to add a user for each channel. User 1 generally has no username and is a generic user. The other users can get a name set. Unfortunately, there is no way to fetch the "Enabled" or "Session Limit" values, so those will show as "?" until you set them. You need to set the name (if not user 1), "Enabled" to True, "Link Auth Enabled" to True, "Msg Auth Enabled" to True, "Access Callback Only" to False, and the "Privilege Limit" to the privilege you want, generally admin for full access. To set the password for a user, right click on the user's number and choose "Set Password". Passwords cannot be fetched or displayed in IPMI. In openipmish, do "help mc chan user" and use these tools to set the various settings listed above for a user Note that on some systems, setting the user will fail unless you explicitly set the "Session Limit" (this is a bug in their implementation). so you might have to set that. Zero disables it and is generally a good choice. LAN CONFIGURATION ----------------- Once you have users configured, you are ready to configure LAN setting. Right-click on the channel again and choose "LANPARMS". This pulls up a large list of settings. There are several things you need to configure. First you need to set the ip_addr_source. If it is DHCP, BIOS, or some other automatic setting, that's fine. If it is manually configured, you must set the ip_addr and subnet_mask settings. If you want the system to be accessible when off, you must set the bmc_generated_arps and/or bmc_generated_garps to true. You might have to experiment to see which one works. If you want to route through a router, you must set up the gateway IP addresses and MAC addresses. Last, but not least, you must set up the enables. For LAN 1.5 (non-RMCP+) access, you must set the "enable_auth_xxx[privilege]" values to the ones you want. In general, md5 is the best you have with LAN 1.5, so enable md5 and disable everything else, unless you just want no access controls and enable "none". You should enable it for the privilege levels you want. FOr RMCP+, you have to enable the cipher suites you are interested in. The cipher suite entries are listed, you have to set the "max_priv_for_cipher_suite" for the corresponding cipher suites you want. Again, these are privilege levels. If you are using openipmish, use the "help lanparm" command and trace down. And good luck, you will need it. ANYTHING ELSE ------------- I think that is all, but I've probably missed something. OpenIPMI-2.0.33/swig/0000775000175000017500000000000014261607642011143 500000000000000OpenIPMI-2.0.33/swig/OpenIPMI.i0000664000175000017500000120411614141240666012616 00000000000000/* * OpenIPMI.i * * A SWIG interface file for OpenIPMI * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2004 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. */ %module OpenIPMI %{ #include #include #include #ifdef HAVE_GETADDRINFO #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* For ipmi_debug_malloc_cleanup() */ #include #include "OpenIPMI.h" typedef struct intarray { int *val; int len; } intarray; typedef struct charbuf { char *val; int len; } charbuf; os_handler_t *swig_os_hnd; static int next_parm(char *s, int *start, int *next) { while (s[*start] && isspace(s[*start])) (*start)++; if (!s[*start]) return EINVAL; *next = *start; while (s[*next] && !isspace(s[*next])) (*next)++; return 0; } static int next_colon_parm(char *s, int *start, int *next) { while (s[*start] && (s[*start] == ':')) (*start)++; if (!s[*start]) return EINVAL; *next = *start; while (s[*next] && (s[*next] != ':')) (*next)++; return 0; } static int num_parm(char *s, int len, int *rval) { char numstr[10]; char *end; int val; if (len > 9) return EINVAL; memcpy(numstr, s, len); numstr[len] = '\0'; val = strtoul(numstr, &end, 0); if (*end != '\0') return EINVAL; *rval = val; return 0; } static int parse_ipmi_addr(char *addr, int lun, ipmi_addr_t *i, unsigned int *addr_len) { int start, next; int rv; int num; int len; start = 0; rv = next_parm(addr, &start, &next); if (rv) return rv; len = next - start; if (strncmp(addr+start, "smi", len) == 0) { ipmi_system_interface_addr_t *si = (void *) i; si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; si->lun = lun; start = next; rv = next_parm(addr, &start, &next); if (rv) return rv; len = next - start; rv = num_parm(addr+start, len, &num); if (rv) return rv; si->channel = num; *addr_len = sizeof(*si); } else if (strncmp(addr+start, "ipmb", len) == 0) { ipmi_ipmb_addr_t *ipmb = (void *) i; ipmb->addr_type = IPMI_IPMB_ADDR_TYPE; ipmb->lun = lun; start = next; rv = next_parm(addr, &start, &next); if (rv) return rv; len = next - start; rv = num_parm(addr+start, len, &num); if (rv) return rv; ipmb->channel = num; start = next; rv = next_parm(addr, &start, &next); if (rv) return rv; len = next - start; rv = num_parm(addr+start, len, &num); if (rv) return rv; ipmb->slave_addr = num; *addr_len = sizeof(*ipmb); } else { return EINVAL; } return 0; } static void make_ipmi_addr(char *out, int max_len, ipmi_addr_t *addr, int addr_len, int *lun) { if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) { ipmi_system_interface_addr_t *si = (void *) addr; snprintf(out, max_len, "smi %d", si->channel); *lun = si->lun; } else if (addr->addr_type == IPMI_IPMB_ADDR_TYPE) { ipmi_ipmb_addr_t *ipmb = (void *) addr; snprintf(out, max_len, "ipmb %d %d", ipmb->channel, ipmb->slave_addr); *lun = ipmb->lun; } else { strncpy(out, "unknown", max_len); *lun = 0; } } static int parse_ipmi_data(intarray data, unsigned char *odata, unsigned int max_len, unsigned int *rlen) { int i; if (data.len > max_len) return E2BIG; for (i=0; iai_family == PF_INET) break; s = s->ai_next; } if (!s) { freeaddrinfo(res0); return EINVAL; } paddr = (struct sockaddr_in *) s->ai_addr; *addr = paddr->sin_addr; freeaddrinfo(res0); return 0; #else /* System does not support getaddrinfo, just for IPv4*/ struct hostent *ent; ent = gethostbyname(str); if (!ent) return EINVAL; memcpy(&addr->s_addr, ent->h_addr_list[0], 4); return 0; #endif } static int parse_mac_addr(char *str, unsigned char *addr) { char *s; int i; char *endstr; s = str; while (isspace(*s)) s++; if (! isxdigit(*s)) return EINVAL; for (i=0; i<5; i++) { addr[i] = strtoul(s, &endstr, 16); if (*endstr != ':') return EINVAL; s = endstr+1; } addr[i] = strtoul(s, &endstr, 16); if (*endstr != '\0') return EINVAL; return 0; } %} %{ /* For output returning an array of constant strings */ typedef struct strconstarray { const char **val; int len; } strconstarray; /* For input only */ typedef struct argarray { char **val; int len; } argarray; /* For input only */ typedef struct iargarray { ipmi_args_t **val; int len; } iargarray; %} typedef struct strconstarray { char **val; int len; } strconstarray; typedef struct argarray { char **val; int len; } argarray; typedef struct iargarray { ipmi_args_t **val; int len; } iargarray; %include "OpenIPMI_lang.i" %nodefault; %{ swig_cb_val *swig_log_handler; void openipmi_swig_vlog(os_handler_t *os_handler, const char *format, enum ipmi_log_type_e log_type, va_list ap) { char *pfx = ""; static char log[1024]; static int curr = 0; swig_cb_val *handler = swig_log_handler; if (! handler) return; switch(log_type) { case IPMI_LOG_INFO: pfx = "INFO"; break; case IPMI_LOG_WARNING: pfx = "WARN"; break; case IPMI_LOG_SEVERE: pfx = "SEVR"; break; case IPMI_LOG_FATAL: pfx = "FATL"; break; case IPMI_LOG_ERR_INFO: pfx = "EINF"; break; case IPMI_LOG_DEBUG: pfx = "DEBG"; break; case IPMI_LOG_DEBUG_START: case IPMI_LOG_DEBUG_CONT: if (curr < sizeof(log)) curr += vsnprintf(log+curr, sizeof(log)-curr, format, ap); return; case IPMI_LOG_DEBUG_END: if (curr < sizeof(log)) vsnprintf(log+curr, sizeof(log)-curr, format, ap); pfx = "DEBG"; curr = 0; goto plog; } vsnprintf(log, sizeof(log), format, ap); plog: swig_call_cb(handler, "log", "%s%s", pfx, log); } static void handle_domain_cb(ipmi_domain_t *domain, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_cb", "%p", &domain_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); } static void domain_connect_change_handler(ipmi_domain_t *domain, int err, unsigned int conn_num, unsigned int port_num, int still_connected, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "conn_change_cb", "%p%d%d%d%d", &domain_ref, err, conn_num, port_num, still_connected); swig_free_ref_check(domain_ref, ipmi_domain_t); } static void domain_connect_change_handler_cl(ipmi_domain_con_cb handler, void *handler_data, void *cb_data) { if (handler != domain_connect_change_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void domain_iterate_connections_handler(ipmi_domain_t *domain, int conn, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_iter_connection_cb", "%p%d", &domain_ref, conn); swig_free_ref_check(domain_ref, ipmi_domain_t); } static void domain_event_handler(ipmi_domain_t *domain, ipmi_event_t *event, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref event_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); event_ref = swig_make_ref_destruct(ipmi_event_dup(event), ipmi_event_t); swig_call_cb(cb, "event_cb", "%p%p", &domain_ref, &event_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref(event_ref); } static void domain_event_handler_cl(ipmi_event_handler_cb handler, void *handler_data, void *cb_data) { if (handler != domain_event_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void domain_mc_updated_handler(enum ipmi_update_e op, ipmi_domain_t *domain, ipmi_mc_t *mc, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref mc_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_update_cb", "%s%p%p", ipmi_update_e_string(op), &domain_ref, &mc_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref_check(mc_ref, ipmi_mc_t); } static void domain_mc_updated_handler_cl(ipmi_domain_mc_upd_cb handler, void *handler_data, void *cb_data) { if (handler != domain_mc_updated_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void domain_entity_update_handler(enum ipmi_update_e op, ipmi_domain_t *domain, ipmi_entity_t *entity, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref entity_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "entity_update_cb", "%s%p%p", ipmi_update_e_string(op), &domain_ref, &entity_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref_check(entity_ref, ipmi_entity_t); } static void domain_entity_update_handler_cl(ipmi_domain_entity_cb handler, void *handler_data, void *cb_data) { if (handler != domain_entity_update_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void domain_fully_up(ipmi_domain_t *domain, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_up_cb", "%p", &domain_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void parse_args_iter_help_hnd(const char *name, const char *help, void *cb_data) { swig_cb_val *cb = cb_data; swig_call_cb(cb, "parse_args_iter_help_cb", "%s%s", name, help); } static void domain_close_done(void *cb_data) { swig_cb_val *cb = cb_data; swig_call_cb(cb, "domain_close_done_cb", " "); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void domain_iterate_entities_handler(ipmi_entity_t *entity, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref entity_ref; domain_ref = swig_make_ref(ipmi_entity_get_domain(entity), ipmi_domain_t); entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "domain_iter_entity_cb", "%p%p", &domain_ref, &entity_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref_check(entity_ref, ipmi_entity_t); } static void ipmb_mc_scan_handler(ipmi_domain_t *domain, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_ipmb_mc_scan_cb", "%p%d", &domain_ref, err); swig_free_ref_check(domain_ref, ipmi_domain_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void domain_reread_sels_handler(ipmi_domain_t *domain, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_reread_sels_cb", "%p%d", &domain_ref, err); swig_free_ref_check(domain_ref, ipmi_domain_t); } static int domain_msg_cb(ipmi_domain_t *domain, ipmi_msgi_t *rspi) { swig_cb_val *cb = rspi->data1; swig_ref domain_ref; ipmi_msg_t *msg = &rspi->msg; ipmi_addr_t *addr = &rspi->addr; int addr_len = rspi->addr_len; char addr_str[50]; int lun; make_ipmi_addr(addr_str, sizeof(addr_str), addr, addr_len, &lun); domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_addr_cmd_cb", "%p%s%d%d%d%*s", &domain_ref, addr_str, lun, msg->netfn, msg->cmd, msg->data_len, msg->data); swig_free_ref_check(domain_ref, ipmi_domain_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); return IPMI_MSG_ITEM_NOT_USED; } static void domain_iterate_mcs_handler(ipmi_domain_t *domain, ipmi_mc_t *mc, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref mc_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "domain_iter_mc_cb", "%p%p", &domain_ref, &mc_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref_check(mc_ref, ipmi_mc_t); } static void fru_written_done(ipmi_domain_t *domain, ipmi_fru_t *fru, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref fru_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); fru_ref = swig_make_ref_destruct(fru, ipmi_fru_t); /* The FRU is already referenced because of the callback, no need to mess with refcounts. */ swig_call_cb(cb, "fru_written", "%p%p%d", &domain_ref, &fru_ref, err); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref(fru_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void fru_fetched(ipmi_domain_t *domain, ipmi_fru_t *fru, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; swig_ref fru_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); fru_ref = swig_make_ref_destruct(fru, ipmi_fru_t); /* The FRU is already referenced because of the callback, no need to mess with refcounts. */ swig_call_cb(cb, "fru_fetched", "%p%p%d", &domain_ref, &fru_ref, err); swig_free_ref_check(domain_ref, ipmi_domain_t); swig_free_ref(fru_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void handle_entity_cb(ipmi_entity_t *entity, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "entity_cb", "%p", &entity_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); } static void entity_iterate_entities_handler(ipmi_entity_t *ent1, ipmi_entity_t *ent2, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref ent1_ref; swig_ref ent2_ref; ent1_ref = swig_make_ref(ent1, ipmi_entity_t); ent2_ref = swig_make_ref(ent2, ipmi_entity_t); swig_call_cb(cb, "entity_iter_entities_cb", "%p%p", &ent1_ref, &ent2_ref); swig_free_ref_check(ent2_ref, ipmi_entity_t); swig_free_ref_check(ent1_ref, ipmi_entity_t); } static void entity_iterate_sensors_handler(ipmi_entity_t *entity, ipmi_sensor_t *sensor, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref sensor_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "entity_iter_sensors_cb", "%p%p", &entity_ref, &sensor_ref); swig_free_ref_check(sensor_ref, ipmi_sensor_t); swig_free_ref_check(entity_ref, ipmi_entity_t); } static void entity_iterate_controls_handler(ipmi_entity_t *entity, ipmi_control_t *control, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref control_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); control_ref = swig_make_ref(control, ipmi_control_t); swig_call_cb(cb, "entity_iter_controls_cb", "%p%p", &entity_ref, &control_ref); swig_free_ref_check(control_ref, ipmi_control_t); swig_free_ref_check(entity_ref, ipmi_entity_t); } static int entity_presence_handler(ipmi_entity_t *entity, int present, void *cb_data, ipmi_event_t *event) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref event_ref; int rv = IPMI_EVENT_NOT_HANDLED; entity_ref = swig_make_ref(entity, ipmi_entity_t); event_ref = swig_make_ref_destruct(ipmi_event_dup(event), ipmi_event_t); swig_call_cb_rv('I', &rv, cb, "entity_presence_cb", "%p%d%p", &entity_ref, present, &event_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); swig_free_ref(event_ref); return rv; } static void entity_presence_handler_cl(ipmi_entity_presence_change_cb handler, void *handler_data, void *cb_data) { if (handler != entity_presence_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void entity_sensor_update_handler(enum ipmi_update_e op, ipmi_entity_t *entity, ipmi_sensor_t *sensor, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref sensor_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "entity_sensor_update_cb", "%s%p%p", ipmi_update_e_string(op), &entity_ref, &sensor_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); swig_free_ref_check(sensor_ref, ipmi_sensor_t); } static void entity_sensor_update_handler_cl(ipmi_entity_sensor_cb handler, void *handler_data, void *cb_data) { if (handler != entity_sensor_update_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void entity_control_update_handler(enum ipmi_update_e op, ipmi_entity_t *entity, ipmi_control_t *control, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref control_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); control_ref = swig_make_ref(control, ipmi_control_t); swig_call_cb(cb, "entity_control_update_cb", "%s%p%p", ipmi_update_e_string(op), &entity_ref, &control_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); swig_free_ref_check(control_ref, ipmi_control_t); } static void entity_control_update_handler_cl(ipmi_entity_control_cb handler, void *handler_data, void *cb_data) { if (handler != entity_control_update_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void entity_fru_update_handler(enum ipmi_update_e op, ipmi_entity_t *entity, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref fru_ref; ipmi_fru_t *fru; entity_ref = swig_make_ref(entity, ipmi_entity_t); fru = ipmi_entity_get_fru(entity); if (fru) ipmi_fru_ref(fru); fru_ref = swig_make_ref_destruct(fru, ipmi_fru_t); swig_call_cb(cb, "entity_fru_update_cb", "%s%p%p", ipmi_update_e_string(op), &entity_ref, &fru_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); swig_free_ref(fru_ref); } static void entity_fru_update_werr_handler(enum ipmi_update_werr_e op, int err, ipmi_entity_t *entity, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref fru_ref; ipmi_fru_t *fru; entity_ref = swig_make_ref(entity, ipmi_entity_t); fru = ipmi_entity_get_fru(entity); if (fru) ipmi_fru_ref(fru); fru_ref = swig_make_ref_destruct(fru, ipmi_fru_t); swig_call_cb(cb, "entity_fru_update_werr_cb", "%s%d%p%p", ipmi_update_werr_e_string(op), err, &entity_ref, &fru_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); swig_free_ref(fru_ref); } static void entity_fru_update_handler_cl(ipmi_entity_fru_cb handler, void *handler_data, void *cb_data) { if (handler != entity_fru_update_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void entity_fru_update_werr_handler_cl(ipmi_entity_fru_werr_cb handler, void *handler_data, void *cb_data) { if (handler != entity_fru_update_werr_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static int entity_hot_swap_handler(ipmi_entity_t *entity, enum ipmi_hot_swap_states last_state, enum ipmi_hot_swap_states curr_state, void *cb_data, ipmi_event_t *event) { swig_cb_val *cb = cb_data; swig_ref entity_ref; swig_ref event_ref; int rv = IPMI_EVENT_NOT_HANDLED; entity_ref = swig_make_ref(entity, ipmi_entity_t); event_ref = swig_make_ref_destruct(ipmi_event_dup(event), ipmi_event_t); swig_call_cb_rv('I', &rv, cb, "entity_hot_swap_update_cb", "%p%s%s%p", &entity_ref, ipmi_hot_swap_state_name(last_state), ipmi_hot_swap_state_name(curr_state), &event_ref); swig_free_ref_check(entity_ref, ipmi_entity_t); swig_free_ref(event_ref); return rv; } static void entity_hot_swap_handler_cl(ipmi_entity_hot_swap_cb handler, void *handler_data, void *cb_data) { if (handler != entity_hot_swap_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void entity_get_hot_swap_handler(ipmi_entity_t *entity, int err, enum ipmi_hot_swap_states state, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "entity_hot_swap_cb", "%p%d%s", &entity_ref, err, ipmi_hot_swap_state_name(state)); swig_free_ref_check(entity_ref, ipmi_entity_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void entity_get_hot_swap_time_handler(ipmi_entity_t *entity, int err, ipmi_timeout_t time, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "entity_hot_swap_get_time_cb", "%p%d%f", &entity_ref, err, ((double) time) / 1000000000.0); swig_free_ref_check(entity_ref, ipmi_entity_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void entity_set_hot_swap_time_handler(ipmi_entity_t *entity, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "entity_hot_swap_set_time_cb", "%p%d", &entity_ref, err); swig_free_ref_check(entity_ref, ipmi_entity_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void entity_activate_handler(ipmi_entity_t *entity, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref entity_ref; entity_ref = swig_make_ref(entity, ipmi_entity_t); swig_call_cb(cb, "entity_activate_cb", "%p%d", &entity_ref, err); swig_free_ref_check(entity_ref, ipmi_entity_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void handle_mc_cb(ipmi_mc_t *mc, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_cb", "%p", &mc_ref); swig_free_ref_check(mc_ref, ipmi_mc_t); } static void mc_active_handler(ipmi_mc_t *mc, int active, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_active_cb", "%p%d", &mc_ref, active); swig_free_ref_check(mc_ref, ipmi_mc_t); } static void mc_active_handler_cl(ipmi_mc_active_cb handler, void *handler_data, void *cb_data) { if (handler != mc_active_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void mc_fully_up_handler(ipmi_mc_t *mc, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_fully_up_cb", "%p", &mc_ref); swig_free_ref_check(mc_ref, ipmi_mc_t); } static void mc_fully_up_handler_cl(ipmi_mc_ptr_cb handler, void *handler_data, void *cb_data) { if (handler != mc_fully_up_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void mc_msg_cb(ipmi_mc_t *mc, ipmi_msg_t *msg, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_cmd_cb", "%p%d%d%*s", &mc_ref, msg->netfn, msg->cmd, msg->data_len, msg->data); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_reset_handler(ipmi_mc_t *mc, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_reset_cb", "%p%d", &mc_ref, err); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_events_enable_handler(ipmi_mc_t *mc, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_events_enable_cb", "%p%d", &mc_ref, err); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_get_event_log_enable_handler(ipmi_mc_t *mc, int err, int val, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_get_event_log_enable_cb", "%p%d%d", &mc_ref, err, val); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_set_event_log_enable_handler(ipmi_mc_t *mc, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_set_event_log_enable_cb", "%p%d", &mc_ref, err); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_reread_sensors_handler(ipmi_mc_t *mc, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_reread_sensors_cb", "%p%d", &mc_ref, err); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_reread_sel_handler(ipmi_mc_t *mc, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_reread_sel_cb", "%p%d", &mc_ref, err); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_sel_get_time_cb(ipmi_mc_t *mc, int err, unsigned long time, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_get_sel_time_cb", "%p%d%ld", &mc_ref, err, time); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_channel_get_info(ipmi_mc_t *mc, int err, ipmi_channel_info_t *info, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; swig_ref info_ref; info = ipmi_channel_info_copy(info); mc_ref = swig_make_ref(mc, ipmi_mc_t); info_ref = swig_make_ref_destruct(info, ipmi_channel_info_t); swig_call_cb(cb, "mc_channel_got_info_cb", "%p%d%p", &mc_ref, err, &info_ref); swig_free_ref_check(mc_ref, ipmi_mc_t); swig_free_ref(info_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_channel_get_access(ipmi_mc_t *mc, int err, ipmi_channel_access_t *info, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; swig_ref info_ref; info = ipmi_channel_access_copy(info); mc_ref = swig_make_ref(mc, ipmi_mc_t); info_ref = swig_make_ref_destruct(info, ipmi_channel_access_t); swig_call_cb(cb, "mc_channel_got_access_cb", "%p%d%p", &mc_ref, err, &info_ref); swig_free_ref_check(mc_ref, ipmi_mc_t); swig_free_ref(info_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_channel_set_access(ipmi_mc_t *mc, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; mc_ref = swig_make_ref(mc, ipmi_mc_t); swig_call_cb(cb, "mc_channel_set_access_cb", "%p%d", &mc_ref, err); swig_free_ref_check(mc_ref, ipmi_mc_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void mc_channel_got_users(ipmi_mc_t *mc, int err, ipmi_user_list_t *info, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref mc_ref; swig_ref *info_ref; int count; swig_ref dummy; int i; unsigned int max, enabled, fixed; if (info) { count = ipmi_user_list_get_user_count(info); info_ref = malloc(count * sizeof(swig_ref *)); if (!info_ref) { count = 0; info_ref = &dummy; } } else { count = 0; info_ref = &dummy; } mc_ref = swig_make_ref(mc, ipmi_mc_t); for (i=0; i 3)) return NULL; *offset = strtoul(s, &s, 0); if (*offset >= 15) return NULL; if (*s == 'a') *dir = IPMI_ASSERTION; else if (*s == 'd') *dir = IPMI_DEASSERTION; else return NULL; s++; return s; } static char * discrete_event_str(char *s, int offset, enum ipmi_event_dir_e dir) { if (offset >= 100) offset = 99; if (offset < 0) offset = 0; s += sprintf(s, "%d", offset); if (dir == IPMI_ASSERTION) { *s = 'a'; s++; } else { *s = 'd'; s++; } *s = '\0'; return s; } static char * threshold_event_state_to_str(ipmi_event_state_t *events) { int len = 0; char *str; enum ipmi_thresh_e thresh; enum ipmi_event_value_dir_e value_dir; enum ipmi_event_dir_e dir; char *s; if (ipmi_event_state_get_events_enabled(events)) len += strlen("events "); if (ipmi_event_state_get_scanning_enabled(events)) len += strlen("scanning "); if (ipmi_event_state_get_busy(events)) len += strlen("busy "); for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { for (value_dir = IPMI_GOING_LOW; value_dir <= IPMI_GOING_HIGH; value_dir++) { for (dir = IPMI_ASSERTION; dir <= IPMI_DEASSERTION; dir++) { if (ipmi_is_threshold_event_set(events,thresh, value_dir, dir)) len += 5; } } } str = malloc(len+1); str[0] = '\0'; if (ipmi_event_state_get_events_enabled(events)) strcat(str, "events "); if (ipmi_event_state_get_scanning_enabled(events)) strcat(str, "scanning "); if (ipmi_event_state_get_busy(events)) strcat(str, "busy "); s = str + strlen(str); for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { for (value_dir = IPMI_GOING_LOW; value_dir <= IPMI_GOING_HIGH; value_dir++) { for (dir = IPMI_ASSERTION; dir <= IPMI_DEASSERTION; dir++) { if (!ipmi_is_threshold_event_set(events,thresh,value_dir,dir)) continue; s = threshold_event_str(s, thresh, value_dir, dir); *s = ' '; s++; } } } *s = '\0'; len = s - str; if (len > 0) str[len-1] = '\0'; /* Remove the final space */ return str; } static int str_to_threshold_event_state(char *str, ipmi_event_state_t **events) { enum ipmi_thresh_e thresh; enum ipmi_event_value_dir_e value_dir; enum ipmi_event_dir_e dir; ipmi_event_state_t *e; int start, next; int rv; e = malloc(ipmi_event_state_size()); ipmi_event_state_init(e); start = 0; rv = next_parm(str, &start, &next); while (!rv) { char *s = str+start; int len = next - start; if (strncasecmp(s, "events", len) == 0) ipmi_event_state_set_events_enabled(e, 1); else if (strncasecmp(s, "scanning", len) == 0) ipmi_event_state_set_scanning_enabled(e, 1); else if (strncasecmp(s, "busy", len) == 0) ipmi_event_state_set_busy(e, 1); else { s = threshold_event_from_str(s, len, &thresh, &value_dir, &dir); if (!s) goto out_err; ipmi_threshold_event_set(e, thresh, value_dir, dir); } start = next; rv = next_parm(str, &start, &next); } *events = e; return 0; out_err: free(e); return EINVAL; } static char * discrete_event_state_to_str(ipmi_event_state_t *events) { int len = 0; char *str; int offset; enum ipmi_event_dir_e dir; char *s; if (ipmi_event_state_get_events_enabled(events)) len += strlen("events "); if (ipmi_event_state_get_scanning_enabled(events)) len += strlen("scanning "); if (ipmi_event_state_get_busy(events)) len += strlen("busy "); for (offset=0; offset<15; offset++) { for (dir = IPMI_ASSERTION; dir <= IPMI_DEASSERTION; dir++) { if (ipmi_is_discrete_event_set(events, offset, dir)) len += 4; } } str = malloc(len+1); str[0] = '\0'; if (ipmi_event_state_get_events_enabled(events)) strcat(str, "events "); if (ipmi_event_state_get_scanning_enabled(events)) strcat(str, "scanning "); if (ipmi_event_state_get_busy(events)) strcat(str, "busy "); s = str + strlen(str); for (offset=0; offset<15; offset++) { for (dir = IPMI_ASSERTION; dir <= IPMI_DEASSERTION; dir++) { if (! ipmi_is_discrete_event_set(events, offset, dir)) continue; s = discrete_event_str(s, offset, dir); *s = ' '; s++; } } *s = '\0'; len = s - str; if (len > 0) str[len-1] = '\0'; /* Remove the final space */ return str; } static int str_to_discrete_event_state(char *str, ipmi_event_state_t **events) { int offset; enum ipmi_event_dir_e dir; ipmi_event_state_t *e; int start, next; int rv; e = malloc(ipmi_event_state_size()); ipmi_event_state_init(e); start = 0; rv = next_parm(str, &start, &next); while (!rv) { char *s = str+start; int len = next - start; if (strncasecmp(s, "events", len) == 0) ipmi_event_state_set_events_enabled(e, 1); else if (strncasecmp(s, "scanning", len) == 0) ipmi_event_state_set_scanning_enabled(e, 1); else if (strncasecmp(s, "busy", len) == 0) ipmi_event_state_set_busy(e, 1); else { s = discrete_event_from_str(s, len, &offset, &dir); if (!s) goto out_err; ipmi_discrete_event_set(e, offset, dir); } start = next; rv = next_parm(str, &start, &next); } *events = e; return 0; out_err: free(e); return EINVAL; } static char * threshold_states_to_str(ipmi_states_t *states) { int len = 0; char *str; enum ipmi_thresh_e thresh; char *s; if (ipmi_is_event_messages_enabled(states)) len += strlen("events "); if (ipmi_is_sensor_scanning_enabled(states)) len += strlen("scanning "); if (ipmi_is_initial_update_in_progress(states)) len += strlen("busy "); for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { if (ipmi_is_threshold_out_of_range(states, thresh)) len += 3; } str = malloc(len+1); str[0] = '\0'; if (ipmi_is_event_messages_enabled(states)) strcat(str, "events "); if (ipmi_is_sensor_scanning_enabled(states)) strcat(str, "scanning "); if (ipmi_is_initial_update_in_progress(states)) strcat(str, "busy "); s = str + strlen(str); for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { if (!ipmi_is_threshold_out_of_range(states, thresh)) continue; s = threshold_str(s, thresh); *s = ' '; s++; } *s = '\0'; len = s - str; if (len > 0) str[len-1] = '\0'; /* Remove the final space */ return str; } static char * discrete_states_to_str(ipmi_states_t *states) { int len = 0; char *str; int offset; char *s; if (ipmi_is_event_messages_enabled(states)) len += strlen("events "); if (ipmi_is_sensor_scanning_enabled(states)) len += strlen("scanning "); if (ipmi_is_initial_update_in_progress(states)) len += strlen("busy "); for (offset=0; offset<15; offset++) { if (ipmi_is_state_set(states, offset)) len += 3; } str = malloc(len+1); str[0] = '\0'; if (ipmi_is_event_messages_enabled(states)) strcat(str, "events "); if (ipmi_is_sensor_scanning_enabled(states)) strcat(str, "scanning "); if (ipmi_is_initial_update_in_progress(states)) strcat(str, "busy "); s = str + strlen(str); for (offset=0; offset<15; offset++) { if (! ipmi_is_state_set(states, offset)) continue; s += sprintf(s, "%d", offset); *s = ' '; s++; } *s = '\0'; len = s - str; if (len > 0) str[len-1] = '\0'; /* Remove the final space */ return str; } static char * thresholds_to_str(ipmi_thresholds_t *t) { int len = 0; char *str; enum ipmi_thresh_e thresh; char dummy[3]; char *s; double val; for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { if (ipmi_threshold_get(t, thresh, &val) == 0) len += snprintf(dummy, 1, "aa %f:", val) + 1; } str = malloc(len+1); s = str; for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { if (ipmi_threshold_get(t, thresh, &val) != 0) continue; threshold_str(dummy, thresh); dummy[2] = '\0'; s += sprintf(s, "%s %f:", dummy, val); *s = ' '; s++; } *s = '\0'; len = s - str; if (len > 0) str[len-2] = '\0'; /* Remove the final ': ' */ return str; } static int str_to_thresholds(char *str, ipmi_sensor_t *sensor, ipmi_thresholds_t **thresholds) { enum ipmi_thresh_e thresh; ipmi_thresholds_t *t; int start, next; int rv; double val; int err = EINVAL; t = malloc(ipmi_thresholds_size()); ipmi_thresholds_init(t); start = 0; rv = next_colon_parm(str, &start, &next); while (!rv) { char *s = str+start; char *endstr; int len = next - start; if (len < 4) goto out_err; if (strncasecmp(s, "un ", 3) == 0) thresh = IPMI_UPPER_NON_CRITICAL; else if (strncasecmp(s, "uc ", 3) == 0) thresh = IPMI_UPPER_CRITICAL; else if (strncasecmp(s, "ur ", 3) == 0) thresh = IPMI_UPPER_NON_RECOVERABLE; else if (strncasecmp(s, "ln ", 3) == 0) thresh = IPMI_LOWER_NON_CRITICAL; else if (strncasecmp(s, "lc ", 3) == 0) thresh = IPMI_LOWER_CRITICAL; else if (strncasecmp(s, "lr ", 3) == 0) thresh = IPMI_LOWER_NON_RECOVERABLE; else goto out_err; val = strtod(s+3, &endstr); if ((*endstr != ':') && (*endstr != '\0')) goto out_err; rv = ipmi_threshold_set(t, sensor, thresh, val); if (rv) { err = rv; goto out_err; } start = next; rv = next_colon_parm(str, &start, &next); } *thresholds = t; return 0; out_err: free(t); return err; } static int sensor_threshold_event_handler(ipmi_sensor_t *sensor, enum ipmi_event_dir_e dir, enum ipmi_thresh_e threshold, enum ipmi_event_value_dir_e high_low, enum ipmi_value_present_e value_present, unsigned int raw_value, double value, void *cb_data, ipmi_event_t *event) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; char eventstr[5]; int raw_set = 0; int value_set = 0; swig_ref event_ref; int rv = IPMI_EVENT_NOT_HANDLED; if (value_present == IPMI_RAW_VALUE_PRESENT) raw_set = 1; if (value_present == IPMI_BOTH_VALUES_PRESENT) { raw_set = 1; value_set = 1; } sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); threshold_event_str(eventstr, threshold, high_low, dir); event_ref = swig_make_ref_destruct(ipmi_event_dup(event), ipmi_event_t); swig_call_cb_rv('I', &rv, cb, "threshold_event_cb", "%p%s%d%d%d%f%p", &sensor_ref, eventstr, raw_set, raw_value, value_set, value, &event_ref); swig_free_ref_check(sensor_ref, ipmi_sensor_t); swig_free_ref(event_ref); return rv; } static void sensor_threshold_event_handler_cl(ipmi_sensor_threshold_event_cb handler, void *handler_data, void *cb_data) { if (handler != sensor_threshold_event_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static int sensor_discrete_event_handler(ipmi_sensor_t *sensor, enum ipmi_event_dir_e dir, int offset, int severity, int prev_severity, void *cb_data, ipmi_event_t *event) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; char eventstr[5]; swig_ref event_ref; int rv = IPMI_EVENT_NOT_HANDLED; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); discrete_event_str(eventstr, offset, dir); event_ref = swig_make_ref_destruct(ipmi_event_dup(event), ipmi_event_t); swig_call_cb_rv('I', &rv, cb, "discrete_event_cb", "%p%s%d%d%p", &sensor_ref, eventstr, severity, prev_severity, &event_ref); swig_free_ref_check(sensor_ref, ipmi_sensor_t); swig_free_ref(event_ref); return rv; } static void sensor_discrete_event_handler_cl(ipmi_sensor_discrete_event_cb handler, void *handler_data, void *cb_data) { if (handler != sensor_discrete_event_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } /* * For the event method call_handler to use. */ typedef struct event_call_handler_data_s { ipmi_event_t *event; swig_cb_val *handlers_val; ipmi_event_handlers_t *handlers; int rv; } event_call_handler_data_t; static void event_call_handler_mc_cb(ipmi_mc_t *mc, void *cb_data) { event_call_handler_data_t *info = cb_data; ipmi_domain_t *domain = ipmi_mc_get_domain(mc); info->rv = ipmi_event_call_handler(domain, info->handlers, info->event, info->handlers_val); } /* A generic callback for a lot of things. */ static void sensor_event_enable_handler(ipmi_sensor_t *sensor, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_event_enable_cb", "%p%d", &sensor_ref, err); swig_free_ref_check(sensor_ref, ipmi_sensor_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_get_event_enables_handler(ipmi_sensor_t *sensor, int err, ipmi_event_state_t *states, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; char *st; if (ipmi_sensor_get_event_reading_type(sensor) == IPMI_EVENT_READING_TYPE_THRESHOLD) { st = threshold_event_state_to_str(states); } else { st = discrete_event_state_to_str(states); } sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_get_event_enable_cb", "%p%d%s", &sensor_ref, err, st); swig_free_ref_check(sensor_ref, ipmi_sensor_t); free(st); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_rearm_handler(ipmi_sensor_t *sensor, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_rearm_cb", "%p%d", &sensor_ref, err); swig_free_ref_check(sensor_ref, ipmi_sensor_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_get_hysteresis_handler(ipmi_sensor_t *sensor, int err, unsigned int positive_hysteresis, unsigned int negative_hysteresis, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_get_hysteresis_cb", "%p%d%d%d", &sensor_ref, err, positive_hysteresis, negative_hysteresis); swig_free_ref_check(sensor_ref, ipmi_sensor_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_set_hysteresis_handler(ipmi_sensor_t *sensor, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_set_hysteresis_cb", "%p%d", &sensor_ref, err); swig_free_ref_check(sensor_ref, ipmi_sensor_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_set_thresholds_handler(ipmi_sensor_t *sensor, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_set_thresholds_cb", "%p%d", &sensor_ref, err); swig_free_ref_check(sensor_ref, ipmi_sensor_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_get_thresholds_handler(ipmi_sensor_t *sensor, int err, ipmi_thresholds_t *th, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; char *thstr = thresholds_to_str(th); sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); swig_call_cb(cb, "sensor_get_thresholds_cb", "%p%d%s", &sensor_ref, err, thstr); swig_free_ref_check(sensor_ref, ipmi_sensor_t); free(thstr); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_get_reading_handler(ipmi_sensor_t *sensor, int err, enum ipmi_value_present_e value_present, unsigned int raw_value, double value, ipmi_states_t *states, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; int raw_set = 0; int value_set = 0; char *statestr; if (value_present == IPMI_RAW_VALUE_PRESENT) raw_set = 1; if (value_present == IPMI_BOTH_VALUES_PRESENT) { raw_set = 1; value_set = 1; } sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); statestr = threshold_states_to_str(states); swig_call_cb(cb, "threshold_reading_cb", "%p%d%d%d%d%f%s", &sensor_ref, err, raw_set, raw_value, value_set, value, statestr); swig_free_ref_check(sensor_ref, ipmi_sensor_t); free(statestr); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sensor_get_states_handler(ipmi_sensor_t *sensor, int err, ipmi_states_t *states, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref sensor_ref; char *statestr; sensor_ref = swig_make_ref(sensor, ipmi_sensor_t); statestr = discrete_states_to_str(states); swig_call_cb(cb, "discrete_states_cb", "%p%d%s", &sensor_ref, err, statestr); swig_free_ref_check(sensor_ref, ipmi_sensor_t); free(statestr); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static int str_to_color(char *s, int len, int *color) { int i; for (i=IPMI_CONTROL_COLOR_BLACK; i<=IPMI_CONTROL_COLOR_ORANGE; i++) { if (strncasecmp(s, ipmi_get_color_string(i), len) == 0) { *color = i; return 0; } } return EINVAL; } static int str_to_light_setting(char *s, ipmi_light_setting_t **setting) { int rv; ipmi_light_setting_t *e; int start, next; int count; count = 0; start = 0; rv = next_colon_parm(s, &start, &next); while (!rv) { start = next; count++; rv = next_colon_parm(s, &start, &next); } if (count == 0) return EINVAL; e = ipmi_alloc_light_settings(count); count = 0; start = 0; rv = next_colon_parm(s, &start, &next); while (!rv) { int color, on_time, off_time; char *ms; int mstart, mnext; char *endstr; char buf[100]; int len = next - start; if (len >= 100) goto out_err; memcpy(buf, s+start, len); buf[len] = '\0'; ms = buf; mstart = 0; rv = next_parm(ms, &mstart, &mnext); if (rv) goto out_err; len = mnext - mstart; if ((len == 2) && (strncasecmp(ms+mstart, "lc", 2) == 0)) { rv = ipmi_light_setting_set_local_control(e, count, 1); if (rv) goto out_err; mstart = mnext; rv = next_parm(ms, &mstart, &mnext); if (rv) goto out_err; } rv = str_to_color(ms+mstart, mnext-mstart, &color); if (rv) goto out_err; mstart = mnext; rv = next_parm(ms, &mstart, &mnext); if (rv) goto out_err; on_time = strtoul(ms+mstart, &endstr, 0); if (endstr != (ms+mnext)) goto out_err; mstart = mnext; rv = next_parm(ms, &mstart, &mnext); if (rv) goto out_err; off_time = strtoul(ms+mstart, &endstr, 0); if (endstr != (ms+mnext)) goto out_err; rv = ipmi_light_setting_set_color(e, count, color); rv |= ipmi_light_setting_set_on_time(e, count, on_time); rv |= ipmi_light_setting_set_off_time(e, count, off_time); if (rv) goto out_err; count++; start = next; rv = next_colon_parm(s, &start, &next); } *setting = e; return 0; out_err: ipmi_free_light_settings(e); return EINVAL; } static char * light_setting_to_str(ipmi_light_setting_t *e) { char *s, *str; int i; int count = ipmi_light_setting_get_count(e); char dummy[1]; int size = 0; for (i = 0; i < count; i++) { int val; size += 1; /* For the colon */ val = 0; ipmi_light_setting_in_local_control(e, i, &val); if (val) size += 3; val = 0; ipmi_light_setting_get_color(e, i, &val); size += strlen(ipmi_get_color_string(val)) + 1; val = 0; ipmi_light_setting_get_on_time(e, i, &val); size += snprintf(dummy, 1, "%d ", val); val = 0; ipmi_light_setting_get_off_time(e, i, &val); size += snprintf(dummy, 1, "%d ", val); } str = malloc(size + 1); if (!str) return NULL; s = str; for (i = 0; i < count; i++) { int val; const char *ov; val = 0; ipmi_light_setting_in_local_control(e, i, &val); if (val) { strcpy(s, "lc "); s += 3; } val = 0; ipmi_light_setting_get_color(e, i, &val); ov = ipmi_get_color_string(val); strcpy(s, ov); s += strlen(ov); *s = ' '; s++; val = 0; ipmi_light_setting_get_on_time(e, i, &val); s += sprintf(s, "%d ", val); val = 0; ipmi_light_setting_get_off_time(e, i, &val); s += sprintf(s, "%d", val); *s = ':'; s++; } if (s != str) { /* Remove the final colon. */ s--; *s = '\0'; } else { *s = '\0'; } return str; } static void handle_control_cb(ipmi_control_t *control, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref control_ref; control_ref = swig_make_ref(control, ipmi_control_t); swig_call_cb(cb, "control_cb", "%p", &control_ref); swig_free_ref_check(control_ref, ipmi_control_t); } static void control_val_set_handler(ipmi_control_t *control, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref control_ref; control_ref = swig_make_ref(control, ipmi_control_t); swig_call_cb(cb, "control_set_val_cb", "%p%d", &control_ref, err); swig_free_ref_check(control_ref, ipmi_control_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void control_val_get_handler(ipmi_control_t *control, int err, int *val, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref control_ref; control_ref = swig_make_ref(control, ipmi_control_t); if (err) { /* On err, value may be NULL */ int dummy; swig_call_cb(cb, "control_get_val_cb", "%p%d%*p", &control_ref, err, 1, &dummy); } else { swig_call_cb(cb, "control_get_val_cb", "%p%d%*p", &control_ref, err, ipmi_control_get_num_vals(control), val); } swig_free_ref_check(control_ref, ipmi_control_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void control_val_get_light_handler(ipmi_control_t *control, int err, ipmi_light_setting_t *val, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref control_ref; char *str; control_ref = swig_make_ref(control, ipmi_control_t); str = light_setting_to_str(val); if (!str) str = "err"; swig_call_cb(cb, "control_get_light_cb", "%p%d%s", &control_ref, err, str); swig_free_ref_check(control_ref, ipmi_control_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void control_val_get_id_handler(ipmi_control_t *control, int err, unsigned char *val, int length, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref control_ref; control_ref = swig_make_ref(control, ipmi_control_t); swig_call_cb(cb, "control_get_id_cb", "%p%d%*s", &control_ref, err, length, val); swig_free_ref_check(control_ref, ipmi_control_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static int control_val_event_handler(ipmi_control_t *control, int *valid_vals, int *val, void *cb_data, ipmi_event_t *event) { swig_cb_val *cb = cb_data; swig_ref control_ref; swig_ref event_ref; int rv = IPMI_EVENT_NOT_HANDLED; control_ref = swig_make_ref(control, ipmi_control_t); event_ref = swig_make_ref_destruct(ipmi_event_dup(event), ipmi_event_t); swig_call_cb_rv('I', &rv, cb, "control_event_val_cb", "%p%p%*p%*p", &control_ref, &event_ref, ipmi_control_get_num_vals(control), valid_vals, ipmi_control_get_num_vals(control), val); swig_free_ref_check(control_ref, ipmi_control_t); swig_free_ref(event_ref); return rv; } static void control_val_event_handler_cl(ipmi_control_val_event_cb handler, void *handler_data, void *cb_data) { if (handler != control_val_event_handler) return; swig_cb_val *handler_val = handler_data; deref_swig_cb_val(handler_val); } static void lanparm_get_parm(ipmi_lanparm_t *lanparm, int err, unsigned char *data, unsigned int data_len, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref lanparm_ref; lanparm_ref = swig_make_ref_destruct(lanparm, ipmi_lanparm_t); swig_call_cb(cb, "lanparm_got_parm_cb", "%p%d%*s", &lanparm_ref, err, data_len, (char *) data); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(lanparm_ref); } static void lanparm_set_parm(ipmi_lanparm_t *lanparm, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref lanparm_ref; if (cb) { lanparm_ref = swig_make_ref_destruct(lanparm, ipmi_lanparm_t); swig_call_cb(cb, "lanparm_set_parm_cb", "%p%d", &lanparm_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(lanparm_ref); } } static void lanparm_get_config(ipmi_lanparm_t *lanparm, int err, ipmi_lan_config_t *config, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref lanparm_ref; swig_ref config_ref; lanparm_ref = swig_make_ref_destruct(lanparm, ipmi_lanparm_t); config_ref = swig_make_ref_destruct(config, ipmi_lan_config_t); swig_call_cb(cb, "lanparm_got_config_cb", "%p%d%p", &lanparm_ref, err, &config_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(lanparm_ref); swig_free_ref(config_ref); } static void lanparm_set_config(ipmi_lanparm_t *lanparm, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref lanparm_ref; if (cb) { lanparm_ref = swig_make_ref_destruct(lanparm, ipmi_lanparm_t); swig_call_cb(cb, "lanparm_set_config_cb", "%p%d", &lanparm_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(lanparm_ref); } } static void lanparm_clear_lock(ipmi_lanparm_t *lanparm, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref lanparm_ref; if (cb) { lanparm_ref = swig_make_ref_destruct(lanparm, ipmi_lanparm_t); swig_call_cb(cb, "lanparm_clear_lock_cb", "%p%d", &lanparm_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(lanparm_ref); } } static void get_pef(ipmi_pef_t *pef, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pef_ref; pef_ref = swig_make_ref_destruct(pef, ipmi_pef_t); ipmi_pef_ref(pef); swig_call_cb(cb, "got_pef_cb", "%p%d", &pef_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pef_ref); } static void pef_get_parm(ipmi_pef_t *pef, int err, unsigned char *data, unsigned int data_len, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pef_ref; pef_ref = swig_make_ref_destruct(pef, ipmi_pef_t); swig_call_cb(cb, "pef_got_parm_cb", "%p%d%*s", &pef_ref, err, data_len, (char *) data); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pef_ref); } static void pef_set_parm(ipmi_pef_t *pef, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pef_ref; if (cb) { pef_ref = swig_make_ref_destruct(pef, ipmi_pef_t); swig_call_cb(cb, "pef_set_parm_cb", "%p%d", &pef_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pef_ref); } } static void pef_get_config(ipmi_pef_t *pef, int err, ipmi_pef_config_t *config, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pef_ref; swig_ref config_ref; pef_ref = swig_make_ref_destruct(pef, ipmi_pef_t); config_ref = swig_make_ref_destruct(config, ipmi_pef_config_t); swig_call_cb(cb, "pef_got_config_cb", "%p%d%p", &pef_ref, err, &config_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pef_ref); swig_free_ref(config_ref); } static void pef_set_config(ipmi_pef_t *pef, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pef_ref; if (cb) { pef_ref = swig_make_ref_destruct(pef, ipmi_pef_t); swig_call_cb(cb, "pef_set_config_cb", "%p%d", &pef_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pef_ref); } } static void pef_clear_lock(ipmi_pef_t *pef, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pef_ref; if (cb) { pef_ref = swig_make_ref_destruct(pef, ipmi_pef_t); swig_call_cb(cb, "pef_clear_lock_cb", "%p%d", &pef_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pef_ref); } } static void get_pet(ipmi_pet_t *pet, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref pet_ref; pet_ref = swig_make_ref_destruct(pet, ipmi_pet_t); ipmi_pet_ref(pet); swig_call_cb(cb, "got_pet_cb", "%p%d", &pet_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(pet_ref); } static void event_deleted_handler(ipmi_domain_t *domain, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "event_delete_cb", "%p%d", &domain_ref, err); swig_free_ref_check(domain_ref, ipmi_domain_t); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); } static void sol_connection_state_change_cb(ipmi_sol_conn_t *conn, ipmi_sol_state state, int error, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_connection_state_change", "%p%d%d", &conn_ref, state, error); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); } static int sol_data_received_cb(ipmi_sol_conn_t *conn, const void *buf, size_t count, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; int rv = 0; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb_rv('i', &rv, cb, "sol_data_received", "%p%*s", &conn_ref, count, buf); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); return rv; } static void sol_break_detected_cb(ipmi_sol_conn_t *conn, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_break_detected", "%p", &conn_ref); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); } static void sol_bmc_transmit_overrun_cb(ipmi_sol_conn_t *conn, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_bmc_transmit_overrun", "%p", &conn_ref); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); } static void sol_write_complete_cb(ipmi_sol_conn_t *conn, int error, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_write_complete", "%p%d", &conn_ref, error); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); /* One-time callback */ deref_swig_cb_val(cb); } static void sol_send_break_cb(ipmi_sol_conn_t *conn, int error, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_send_break", "%p%d", &conn_ref, error); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); /* One-time callback */ deref_swig_cb_val(cb); } static void sol_set_CTS_assertable_cb(ipmi_sol_conn_t *conn, int error, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_set_CTS_assertable", "%p%d", &conn_ref, error); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); /* One-time callback */ deref_swig_cb_val(cb); } static void sol_set_DCD_DSR_asserted_cb(ipmi_sol_conn_t *conn, int error, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_set_DCD_DSR_asserted", "%p%d", &conn_ref, error); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); /* One-time callback */ deref_swig_cb_val(cb); } static void sol_set_RI_asserted_cb(ipmi_sol_conn_t *conn, int error, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_set_RI_asserted", "%p%d", &conn_ref, error); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); /* One-time callback */ deref_swig_cb_val(cb); } static void sol_flush_complete_cb(ipmi_sol_conn_t *conn, int error, int queue_selectors_flushed, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref conn_ref; conn_ref = swig_make_ref(conn, ipmi_sol_conn_t); swig_call_cb(cb, "sol_flush_complete", "%p%d%d", &conn_ref, error, queue_selectors_flushed); swig_free_ref_check(conn_ref, ipmi_sol_conn_t); /* One-time callback */ deref_swig_cb_val(cb); } static void solparm_get_parm(ipmi_solparm_t *solparm, int err, unsigned char *data, unsigned int data_len, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref solparm_ref; solparm_ref = swig_make_ref_destruct(solparm, ipmi_solparm_t); swig_call_cb(cb, "solparm_got_parm_cb", "%p%d%*s", &solparm_ref, err, data_len, (char *) data); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(solparm_ref); } static void solparm_set_parm(ipmi_solparm_t *solparm, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref solparm_ref; if (cb) { solparm_ref = swig_make_ref_destruct(solparm, ipmi_solparm_t); swig_call_cb(cb, "solparm_set_parm_cb", "%p%d", &solparm_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(solparm_ref); } } static void solparm_get_config(ipmi_solparm_t *solparm, int err, ipmi_sol_config_t *config, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref solparm_ref; swig_ref config_ref; solparm_ref = swig_make_ref_destruct(solparm, ipmi_solparm_t); config_ref = swig_make_ref_destruct(config, ipmi_sol_config_t); swig_call_cb(cb, "solparm_got_config_cb", "%p%d%p", &solparm_ref, err, &config_ref); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(solparm_ref); swig_free_ref(config_ref); } static void solparm_set_config(ipmi_solparm_t *solparm, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref solparm_ref; if (cb) { solparm_ref = swig_make_ref_destruct(solparm, ipmi_solparm_t); swig_call_cb(cb, "solparm_set_config_cb", "%p%d", &solparm_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(solparm_ref); } } static void solparm_clear_lock(ipmi_solparm_t *solparm, int err, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref solparm_ref; if (cb) { solparm_ref = swig_make_ref_destruct(solparm, ipmi_solparm_t); swig_call_cb(cb, "solparm_clear_lock_cb", "%p%d", &solparm_ref, err); /* One-time call, get rid of the CB. */ deref_swig_cb_val(cb); swig_free_ref(solparm_ref); } } #if defined(HAVE_GLIB) || defined(HAVE_GLIB12) #include static void glib_handle_log(const char *domain, const char *pfx, const char *message) { swig_cb_val *handler = swig_log_handler; if (! handler) return; swig_call_cb(handler, "log", "%s%s", pfx, message); } #if defined(HAVE_GLIB) && defined(HAVE_GLIB12) #include #endif /* * Initialize the OS handler with the glib version. */ os_handler_t * init_glib_shim(char *ver) { os_handler_t *swig_os_hnd; #if defined(HAVE_GLIB) && defined(HAVE_GLIB12) /* Two versions of glib. Go through special machinations to make this work right. We can't directly link with glib, we have to dlopen it to get the right version. */ static char *olibst = "libOpenIPMIglib%s.so"; char dummy[1]; char *name; void *hndl; os_handler_t *(*get)(int); void (*setlog)(void (*hndlr)(const char *domain, const char *pfx, const char *msg)); int len; len = snprintf(dummy, 1, olibst, ver); name = malloc(len+1); if (!name) { fprintf(stderr, "Unable to allocation memory for glib\n"); abort(); } snprintf(name, len+1, olibst, ver); hndl = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); if (!hndl) { fprintf(stderr, "Unable to open the glib library: %s: %s\n", name, dlerror()); free(name); abort(); } free(name); get = dlsym(hndl, "ipmi_glib_get_os_handler"); if (!get) { fprintf(stderr, "Could not find glib function: ipmi_glib_get_os_handler: %s\n", dlerror()); abort(); } setlog = dlsym(hndl, "ipmi_glib_set_log_handler"); if (!setlog) { fprintf(stderr, "Could not find glib function: ipmi_glib_set_log_handler: %s\n", dlerror()); abort(); } swig_os_hnd = get(0); swig_os_hnd->set_log_handler(swig_os_hnd, openipmi_swig_vlog); ipmi_init(swig_os_hnd); ipmi_cmdlang_init(swig_os_hnd); setlog(glib_handle_log); #else swig_os_hnd = ipmi_glib_get_os_handler(0); swig_os_hnd->set_log_handler(swig_os_hnd, openipmi_swig_vlog); ipmi_init(swig_os_hnd); ipmi_cmdlang_init(swig_os_hnd); ipmi_glib_set_log_handler(glib_handle_log); #endif return swig_os_hnd; } #endif %} typedef struct { } ipmi_domain_t; typedef struct { } ipmi_domain_id_t; typedef struct { } ipmi_args_t; typedef struct { } ipmi_entity_t; typedef struct { } ipmi_entity_id_t; typedef struct { } ipmi_fru_t; typedef struct { } ipmi_fru_node_t; typedef struct { } ipmi_mc_t; typedef struct { } ipmi_mcid_t; typedef struct { } ipmi_event_t; typedef struct { } ipmi_sensor_t; typedef struct { } ipmi_sensor_id_t; typedef struct { } ipmi_control_t; typedef struct { } ipmi_control_id_t; typedef struct { } ipmi_channel_info_t; typedef struct { } ipmi_channel_access_t; typedef struct { } ipmi_user_t; typedef struct { } ipmi_lanparm_t; typedef struct { } ipmi_lan_config_t; typedef struct { } ipmi_pef_t; typedef struct { } ipmi_pef_config_t; typedef struct { } ipmi_pet_t; typedef struct { } ipmi_cmdlang_t; typedef struct { } ipmi_cmdlang_event_t; typedef struct { } ipmi_sol_conn_t; typedef struct { } ipmi_sol_config_t; typedef struct { } ipmi_solparm_t; %inline %{ void enable_debug_malloc() { if (!swig_os_hnd) { DEBUG_MALLOC_ENABLE(); } } void enable_debug_msg() { DEBUG_MSG_ENABLE(); } void disable_debug_msg() { DEBUG_MSG_DISABLE(); } void enable_debug_rawmsg() { DEBUG_RAWMSG_ENABLE(); } void disable_debug_rawmsg() { DEBUG_RAWMSG_DISABLE(); } int init_glib(void) { #ifdef HAVE_GLIB if (swig_os_hnd) return 0; #ifdef OpenIPMI_HAVE_INIT_LANG init_lang(); #endif swig_os_hnd = init_glib_shim(""); return 0; #else return ENOSYS; #endif } int init_glib12(void) { #ifdef HAVE_GLIB12 if (swig_os_hnd) return 0; #ifdef OpenIPMI_HAVE_INIT_LANG init_lang(); #endif swig_os_hnd = init_glib_shim("12"); return 0; #else return ENOSYS; #endif } #if defined(HAVE_TCL) #include #endif int init_tcl(void) { #ifdef HAVE_TCL if (swig_os_hnd) return 0; #ifdef OpenIPMI_HAVE_INIT_LANG init_lang(); #endif swig_os_hnd = ipmi_tcl_get_os_handler(0); swig_os_hnd->set_log_handler(swig_os_hnd, openipmi_swig_vlog); ipmi_init(swig_os_hnd); ipmi_cmdlang_init(swig_os_hnd); return 0; #else return ENOSYS; #endif } /* * Initialize the OS handler and use the POSIX version. */ int init_posix(void) { if (swig_os_hnd) return 0; #ifdef OpenIPMI_HAVE_INIT_LANG init_lang(); #endif #ifdef USE_POSIX_THREADS swig_os_hnd = ipmi_posix_thread_setup_os_handler(SIGUSR1); #else swig_os_hnd = ipmi_posix_setup_os_handler(); #endif swig_os_hnd->set_log_handler(swig_os_hnd, openipmi_swig_vlog); ipmi_init(swig_os_hnd); ipmi_cmdlang_init(swig_os_hnd); return 0; } /* * Initialize the OS handler with the default version. This is glib * if it is present, POSIX if it is not. */ int init(void) { int rv; if (rv = init_glib()) rv = init_posix(); return rv; } /* * Free up all the memory used by OpenIPMI. */ void shutdown_everything() { IPMI_SWIG_C_CB_ENTRY ipmi_cmdlang_cleanup(); ipmi_shutdown(); swig_os_hnd->free_os_handler(swig_os_hnd); swig_os_hnd = NULL; #ifdef OpenIPMI_HAVE_CLEANUP_LANG void cleanup_lang(); #endif IPMI_SWIG_C_CB_EXIT } /* * Perform one operation. The first parameter is a timeout in * milliseconds. */ void wait_io(int timeout) { struct timeval tv = { (timeout / 1000), ((timeout + 999) % 1000) }; IPMI_SWIG_C_BLOCK_ENTRY swig_os_hnd->perform_one_op(swig_os_hnd, &tv); IPMI_SWIG_C_BLOCK_EXIT } %} /* * Error return constants returned by OpenIPMI. */ %constant int ebadf = EBADF; %constant int einval = EINVAL; %constant int e2big = E2BIG; %constant int enomem = ENOMEM; %constant int enoent = ENOENT; %constant int ecanceled = ECANCELED; %constant int enosys = ENOSYS; %constant int eexist = EEXIST; %constant int eagain = EAGAIN; %constant int eperm = EPERM; /* * Return values for event handlers */ %constant int EVENT_NOT_HANDLED = IPMI_EVENT_NOT_HANDLED; %constant int EVENT_HANDLED = IPMI_EVENT_HANDLED; %constant int EVENT_HANDLED_PASS = IPMI_EVENT_HANDLED_PASS; /* These two defines simplify the functions that do addition/removal of callbacks. The type is the object type (domain, entity, etc) and the name is the stuff in the middle of the name, ie (ipmi__add__handler. The function that will be called with the info is __handler. */ #define cb_add(type, name, func) \ int rv; \ swig_cb_val *handler_val; \ IPMI_SWIG_C_CB_ENTRY \ if (! valid_swig_cb(handler, func)) \ rv = EINVAL; \ else { \ handler_val = ref_swig_cb(handler, func); \ rv = ipmi_ ## type ## _add_ ## name ## _handler \ (self, type ## _ ## name ## _handler, handler_val); \ if (rv) \ deref_swig_cb_val(handler_val); \ } \ IPMI_SWIG_C_CB_EXIT \ return rv; #define cb_rm(type, name, func) \ int rv; \ swig_cb_val *handler_val; \ IPMI_SWIG_C_CB_ENTRY \ if (! valid_swig_cb(handler, func)) \ rv = EINVAL; \ else { \ handler_val = get_swig_cb(handler, func); \ rv = ipmi_ ## type ## _remove_ ## name ##_handler \ (self, type ## _ ## name ## _handler, handler_val); \ if (!rv) \ deref_swig_cb_val(handler_val); \ } \ IPMI_SWIG_C_CB_EXIT \ return rv; /* * A bug in swig (default parameters not used in inline) causes this * to have to not be in an inline and done the hard way. */ %{ static void domain_cleanup_add(ipmi_domain_t *domain, void *cb_data) { ipmi_domain_add_connect_change_handler_cl (domain, domain_connect_change_handler_cl, NULL); } static ipmi_domain_id_t * open_domain(char *name, argarray *args, swig_cb *done, swig_cb *up) { int i, j; int num_options = 0; ipmi_open_option_t options[10]; int set = 0; ipmi_args_t *con_parms[2]; ipmi_con_t *con[2]; ipmi_domain_id_t *nd; int rv; swig_cb_val *done_val = NULL; swig_cb_val *up_val = NULL; ipmi_domain_con_cb con_change = NULL; ipmi_domain_ptr_cb domain_up = NULL; IPMI_SWIG_C_CB_ENTRY nd = malloc(sizeof(*nd)); for (i=0; ilen; i++) { if (num_options >= 10) { free(nd); nd = NULL; goto out_err; } if (! ipmi_parse_options(options+num_options, args->val[i])) num_options++; else break; } rv = ipmi_parse_args(&i, args->len, args->val, &con_parms[set]); if (rv) { free(nd); nd = NULL; goto out_err; } set++; if (i < args->len) { rv = ipmi_parse_args(&i, args->len, args->val, &con_parms[set]); if (rv) { ipmi_free_args(con_parms[0]); free(nd); nd = NULL; goto out_err; } set++; } for (i=0; iclose_connection(con[j]); free(nd); nd = NULL; goto out; } } if (!nil_swig_cb(up)) { if (valid_swig_cb(up, domain_up_cb)) { up_val = ref_swig_cb(up, domain_up_cb); domain_up = domain_fully_up; } else { free(nd); nd = NULL; goto out; } } if (!nil_swig_cb(done)){ if (valid_swig_cb(done, conn_change_cb)) { done_val = ref_swig_cb(done, conn_change_cb); con_change = domain_connect_change_handler; } else { if (domain_up) deref_swig_cb(up); free(nd); nd = NULL; goto out; } } rv = ipmi_open_domain(name, con, set, con_change, done_val, domain_up, up_val, options, num_options, nd); if (rv) { if (domain_up) deref_swig_cb(up); if (con_change) deref_swig_cb(done); for (i=0; iclose_connection(con[i]); free(nd); nd = NULL; goto out; } ipmi_domain_pointer_cb(*nd, domain_cleanup_add, NULL); out: for (i=0; ilen; i++) { if (num_options >= 10) { free(nd); nd = NULL; goto out_err; } if (! ipmi_parse_options(options+num_options, args->val[i])) num_options++; else break; } rv = ipmi_parse_args2(&i, args->len, args->val, &con_parms[set]); if (rv) { free(nd); nd = NULL; goto out_err; } set++; if (i < args->len) { rv = ipmi_parse_args2(&i, args->len, args->val, &con_parms[set]); if (rv) { ipmi_free_args(con_parms[0]); free(nd); nd = NULL; goto out_err; } set++; } for (i=0; iclose_connection(con[j]); free(nd); nd = NULL; goto out; } } if (!nil_swig_cb(up)) { if (valid_swig_cb(up, domain_up_cb)) { up_val = ref_swig_cb(up, domain_up_cb); domain_up = domain_fully_up; } else { free(nd); nd = NULL; goto out; } } if (!nil_swig_cb(done)){ if (valid_swig_cb(done, conn_change_cb)) { done_val = ref_swig_cb(done, conn_change_cb); con_change = domain_connect_change_handler; } else { if (domain_up) deref_swig_cb(up); free(nd); nd = NULL; goto out; } } rv = ipmi_open_domain(name, con, set, con_change, done_val, domain_up, up_val, options, num_options, nd); if (rv) { if (domain_up) deref_swig_cb(up); if (con_change) deref_swig_cb(done); for (i=0; iclose_connection(con[i]); free(nd); nd = NULL; goto out; } ipmi_domain_pointer_cb(*nd, domain_cleanup_add, NULL); out: for (i=0; ilen; i++) { if (num_options >= 10) { free(nd); nd = NULL; goto out_err; } if (! ipmi_parse_options(options+num_options, ioptions->val[i])) num_options++; else break; } for (i=0; ilen; i++) { rv = ipmi_args_setup_con(args->val[i], swig_os_hnd, NULL, &con[i]); if (rv) { for (j=0; jclose_connection(con[j]); free(nd); nd = NULL; goto out; } set++; } if (!nil_swig_cb(up)) { if (valid_swig_cb(up, domain_up_cb)) { up_val = ref_swig_cb(up, domain_up_cb); domain_up = domain_fully_up; } else { free(nd); nd = NULL; goto out; } } if (!nil_swig_cb(done)){ if (valid_swig_cb(done, conn_change_cb)) { done_val = ref_swig_cb(done, conn_change_cb); con_change = domain_connect_change_handler; } else { if (domain_up) deref_swig_cb(up); free(nd); nd = NULL; goto out; } } rv = ipmi_open_domain(name, con, set, con_change, done_val, domain_up, up_val, options, num_options, nd); if (rv) { if (domain_up) deref_swig_cb(up); if (con_change) deref_swig_cb(done); for (i=0; iclose_connection(con[i]); free(nd); nd = NULL; goto out; } ipmi_domain_pointer_cb(*nd, domain_cleanup_add, NULL); out: out_err: IPMI_SWIG_C_CB_EXIT return nd; } static void set_log_handler(swig_cb *handler) { swig_cb_val *old_handler = swig_log_handler; IPMI_SWIG_C_CB_ENTRY if (valid_swig_cb(handler, log)) swig_log_handler = ref_swig_cb(handler, log); else swig_log_handler = NULL; if (old_handler) deref_swig_cb_val(old_handler); IPMI_SWIG_C_CB_EXIT } static const char * color_string(int color) { return ipmi_get_color_string(color); } static const char * lanparm_parm_to_str(int parm) { return ipmi_lanconfig_parm_to_str(parm); } static int lanconfig_enum_val(int parm, int val, int *nval, const char **sval) { return ipmi_lanconfig_enum_val(parm, val, nval, sval); } static int lanconfig_enum_idx(int parm, int idx, const char **sval) { return ipmi_lanconfig_enum_idx(parm, idx, sval); } static int lanparm_str_to_parm(char *str) { return ipmi_lanconfig_str_to_parm(str); } static const char * pef_parm_to_str(int parm) { return ipmi_pefconfig_parm_to_str(parm); } static int pef_str_to_parm(char *str) { return ipmi_pefconfig_str_to_parm(str); } static int pefconfig_enum_val(int parm, int val, int *nval, const char **sval) { return ipmi_lanconfig_enum_val(parm, val, nval, sval); } static int pefconfig_enum_idx(int parm, int idx, const char **sval) { return ipmi_pefconfig_enum_idx(parm, idx, sval); } static const char * get_threshold_access_support_string(int val) { return ipmi_get_threshold_access_support_string(val); } static const char * get_hysteresis_support_string(int val) { return ipmi_get_hysteresis_support_string(val); } static const char * get_event_support_string(int val) { return ipmi_get_event_support_string(val); } static const char * channel_medium_string(int val) { return ipmi_channel_medium_string(val); } static const char * channel_protocol_string(int val) { return ipmi_channel_protocol_string(val); } static const char * channel_session_support_string(int val) { return ipmi_channel_session_support_string(val); } static const char * channel_access_mode_string(int val) { return ipmi_channel_access_mode_string(val); } static const char * privilege_string(int val) { return ipmi_privilege_string(val); } static const char * authtype_string(int val) { return ipmi_authtype_string(val); } static const char * solparm_parm_to_str(int parm) { return ipmi_solconfig_parm_to_str(parm); } static int solparm_str_to_parm(char *str) { return ipmi_solconfig_str_to_parm(str); } static int solconfig_enum_val(int parm, int val, int *nval, const char **sval) { return ipmi_solconfig_enum_val(parm, val, nval, sval); } static int solconfig_enum_idx(int parm, int idx, const char **sval) { return ipmi_solconfig_enum_idx(parm, idx, sval); } static char * get_error_string(unsigned int err) { int len; char *buf; len = ipmi_get_error_string_len(err); buf = malloc(len); if (!buf) return NULL; ipmi_get_error_string(err, buf, len); return buf; } static void domain_change_handler(ipmi_domain_t *domain, enum ipmi_update_e op, void *cb_data) { swig_cb_val *cb = cb_data; swig_ref domain_ref; domain_ref = swig_make_ref(domain, ipmi_domain_t); swig_call_cb(cb, "domain_change_cb", "%s%p", ipmi_update_e_string(op), &domain_ref); swig_free_ref_check(domain_ref, ipmi_domain_t); } int add_domain_change_handler(swig_cb *handler) { int rv; swig_cb_val *handler_val; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_change_cb)) { rv = EINVAL; goto out_err; } handler_val = ref_swig_cb(handler, domain_change_cb); rv = ipmi_domain_add_domain_change_handler(domain_change_handler, handler_val); if (rv) deref_swig_cb_val(handler_val); out_err: IPMI_SWIG_C_CB_EXIT return rv; } int remove_domain_change_handler(swig_cb *handler) { int rv; swig_cb_val *handler_val; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_change_cb)) { rv = EINVAL; goto out_err; } handler_val = get_swig_cb(handler, domain_change_cb); rv = ipmi_domain_remove_domain_change_handler(domain_change_handler, handler_val); if (!rv) deref_swig_cb_val(handler_val); out_err: IPMI_SWIG_C_CB_EXIT return rv; } %} %newobject open_domain; %newobject open_domain2; %newobject open_domain3; /* * Create a new domain. The domain will be named with the first parm, * the startup arguments are in a reference to a list in the second * parm (\@args), the third parm is a callback object whose * conn_change_cb method will be called when the domain has connected * (but it may not be fully up yet). The fourth parameter's * domain_up_cb method will be called when the domain is completely up * Note that the done method will be kept around and will continue to * be called on connection changes. If you don't want it any more, * it must be deregistered with remove_connect_change_handler. * Passing in a reference to an undefined value will cause the handlers * to not be called. * The domain_up_cb methods is called with the following parmeters: * * The parameters of the connection change handler are defined in * the domain->add_connect_change_handler method. * The third and fourth parameters are optional, if not provided * or undefined the handler will be ignored. * * The format of the arguments is the same as described in the * ipmi_cmdlang.7 man page for domain open, except the -wait_til_up * option is not supported. See that for more details. These options * allow you to turn on and off various automatic operations that * OpenIPMI does, such as scanning SDRs, fetching the SEL, etc. */ ipmi_domain_id_t *open_domain(char *name, argarray *args, swig_cb *done = NULL, swig_cb *up = NULL); /* * Like open_domain, but takes the new parameter types and is more * flexible. This is required for RMCP+. */ ipmi_domain_id_t *open_domain2(char *name, argarray *args, swig_cb *done = NULL, swig_cb *up = NULL); /* * Like open_domain2, but takes ipmi_args_t. Works with RMCP+. */ ipmi_domain_id_t *open_domain3(char *name, argarray *options, iargarray *args, swig_cb *done = NULL, swig_cb *up = NULL); /* * Iterate through the help for the various connection types used with * open_domain2() and open_domain3() and argument parsing and * allocating. This will call the parse_args_iter_help_cb method on * the supplied object for each registered connection type. The * parameters are . This can also be used to find * the names of all registered connections. */ void parse_args_iter_help(swig_cb *help_cb); %{ static void parse_args_iter_help(swig_cb *help_cb) { int rv; swig_cb_val *handler_val; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(help_cb, parse_args_iter_help_cb)) rv = EINVAL; else { handler_val = get_swig_cb(help_cb, parse_args_iter_help_cb); ipmi_parse_args_iter_help(parse_args_iter_help_hnd, handler_val); } IPMI_SWIG_C_CB_EXIT } %} const char *parse_option_help(); %{ static const char *parse_option_help(void) { return ipmi_parse_options_help(); } %} /* * Add a handler whose domain_change_cb method will be called whenever * a domain is added or removed. The handler will be called with the * following parameters: added|deleted|changed */ int add_domain_change_handler(swig_cb *handler); /* * Remove a previously registered domain handler. */ int remove_domain_change_handler(swig_cb *handler); /* * Set the handler for OpenIPMI logs. This is a global value and * there is only one, setting it replaces the old one. The logs will * be sent to the "log" method of the first parameter. The log method * will receive the following parameters: , , and . If the log method is undefined or * not provided, the current log handler will be removed. */ void set_log_handler(swig_cb *handler = NULL); /* * Convert the given color to a string. */ char *color_string(int color); /* Convert between lanparm string names and parm numbers. */ char *lanparm_parm_to_str(int parm); int lanparm_str_to_parm(char *str); /* Used to discover enum values for lanparms. */ int lanconfig_enum_val(int parm, int val, int *nval, const char **sval); int lanconfig_enum_idx(int parm, int idx, const char **sval); /* Convert between pef string names and parm numbers. */ char *pef_parm_to_str(int parm); int pef_str_to_parm(char *str); /* Used to discover enum values for lanparms. */ int pefconfig_enum_val(int parm, int val, int *nval, const char **sval); int pefconfig_enum_idx(int parm, int idx, const char **sval); /* Convert between SoL string names and parm numbers. */ char *solparm_parm_to_str(int parm); int solparm_str_to_parm(char *str); /* Used to discover enum values for solparms. */ int solconfig_enum_val(int parm, int val, int *nval, const char **sval); int solconfig_enum_idx(int parm, int idx, const char **sval); /* Convert various sensor values to strings. */ char *get_threshold_access_support_string(int val); char *get_hysteresis_support_string(int val); char *get_event_support_string(int val); /* Convert various channel/mc values to strings. */ char *channel_medium_string(int val); char *channel_protocol_string(int val); char *channel_session_support_string(int val); char *channel_access_mode_string(int val); char *privilege_string(int val); char *authtype_string(int val); %newobject get_error_string; char *get_error_string(unsigned int val); %constant long long TIMEOUT_FOREVER = IPMI_TIMEOUT_FOREVER; /* * A domain id object. This object is guaranteed to be valid and * can be converted into a domain pointer later. */ %extend ipmi_domain_id_t { ~ipmi_domain_id_t() { free(self); } /* Compare self with other, return -1 if selfother. */ int cmp(ipmi_domain_id_t *other) { return ipmi_cmp_domain_id(*self, *other); } /* * Convert a domain id to a domain pointer. The "domain_cb" method * will be called on the first parameter with the following parameters: * */ int to_domain(swig_cb *handler) { int rv; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_cb)) rv = EINVAL; else rv = ipmi_domain_pointer_cb(*self, handle_domain_cb, get_swig_cb(handler, domain_cb)); IPMI_SWIG_C_CB_EXIT return rv; } } /* * A domain object. */ %extend ipmi_domain_t { %newobject get_name; /* * Get the name of the domain. */ char *get_name() { char name[IPMI_DOMAIN_NAME_LEN]; ipmi_domain_get_name(self, name, sizeof(name)); return strdup(name); } %newobject get_id; /* * Get the ID of the domain so you can hold on to the reference. */ ipmi_domain_id_t *get_id() { ipmi_domain_id_t *rv = malloc(sizeof(*rv)); if (rv) *rv = ipmi_domain_convert_to_id(self); return rv; } %newobject get_guid; /* * Get the system GUID for the domain. Returns NULL if it is not * supported. */ char *get_guid() { char *str = NULL; unsigned char guid[16]; if (ipmi_domain_get_guid(self, guid) == 0) { str = malloc(16 * 3); if (str) { char *s = str; int i; s += sprintf(s, "%2.2x", guid[0]); for (i=1; i<16; i++) s += sprintf(s, " %2.2x", guid[i]); } } return str; } /* * Shut down the connections to the domain and free it up. The * domain_close_done_cb method for the handler object will be * called with the following parameters: */ int close(swig_cb *handler) { int rv; swig_cb_val *handler_val; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_close_done_cb)) rv = EINVAL; else { handler_val = ref_swig_cb(handler, domain_close_done_cb); rv = ipmi_domain_close(self, domain_close_done, handler_val); if (rv) deref_swig_cb_val(handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Add a handler to be called when the connection changes status. * The conn_change_cb method on the first parameter will be * called when the connection changes status with the following * parameters: , , , , * , . */ int add_connect_change_handler(swig_cb *handler) { /* cleanup handler is added when the domain is added. */ cb_add(domain, connect_change, conn_change_cb); } /* * Remove the connection change handler. */ int remove_connect_change_handler(swig_cb *handler) { cb_rm(domain, connect_change, conn_change_cb); } /* * Iterate through all the connections in the object. The * domain_iter_connection_cb method will be called on the first * parameter for each connection in the domain. The parameters it * receives will be: , , . */ int iterate_connections(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_iter_connection_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, domain_iter_connection_cb); ipmi_domain_iterate_connections(self, domain_iterate_connections_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Attempt to activate the given connection. */ int activate_connection(int connection) { int rv; IPMI_SWIG_C_CB_ENTRY rv = ipmi_domain_activate_connection(self, connection); IPMI_SWIG_C_CB_EXIT return rv; } /* * Parm 1 is a connection number. Sets the second parameter to * true if the connection is active, false if not. Returns an * error value. */ int is_connection_active(int connection, unsigned int *active) { return ipmi_domain_is_connection_active(self, connection, active); } /* * Parm 1 is a connection number. Sets the second parameter to true * if the connection is up, false if not. Returns an error value. */ int is_connection_up(int connection, unsigned int *up) { return ipmi_domain_is_connection_up(self, connection, up); } /* * Parm 1 is a connection number. Sets the second parameter to * the number of ports in the connection. A connection may have * multiple ports (ie, multiple IP addresses to the same BMC, * whereas a separate connection is a connection to a different * BMC); these functions let you check their status. Returns an * error value. */ int num_connection_ports(int connection, unsigned int *ports) { return ipmi_domain_num_connection_ports(self, connection, ports); } /* * Parm 1 is a connection number, parm 2 is a port number. Sets * parm 3 to true if the given port is up, false if not. Returns * an error value. */ int is_connection_port_up(int connection, int port, unsigned int *up) { return ipmi_domain_is_connection_port_up(self, connection, port, up); } %newobject get_port_info; char *get_port_info(int connection, int port) { int rv; char buf[256]; int len = sizeof(buf); rv = ipmi_domain_get_port_info(self, connection, port, buf, &len); if (rv) return NULL; return strdup(buf); } %newobject get_connection_args; ipmi_args_t *get_connection_args(int connection) { return ipmi_domain_get_connection_args(self, connection); } char *get_connection_type(int connection) { return ipmi_domain_get_connection_type(self, connection); } /* * Add a handler to be called when an entity is added, updated, or * removed. When the entity is updated the entity_update_cb * method on the first parameter will be called with the following * parameters: , added|deleted|changed , . */ int add_entity_update_handler(swig_cb *handler) { ipmi_domain_add_entity_update_handler_cl (self, domain_entity_update_handler_cl, NULL); cb_add(domain, entity_update, entity_update_cb); } /* * Remove the entity change handler. */ int remove_entity_update_handler(swig_cb *handler) { cb_rm(domain, entity_update, entity_update_cb); } /* * Iterate through all the entities in the object. The * domain_iter_entities_cb method will be called on the first * parameter for each entity in the domain. The parameters it * receives will be: . */ int iterate_entities(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_iter_entities_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, domain_iter_entities_cb); ipmi_domain_iterate_entities(self, domain_iterate_entities_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Add a handler to be called when an MC is added, updated, or * removed. When the mc is updated the mc_update_cb method on the * first parameter will be called with the following parameters: * , added|deleted|changed , . */ int add_mc_update_handler(swig_cb *handler) { ipmi_domain_add_mc_updated_handler_cl (self, domain_mc_updated_handler_cl, NULL); cb_add(domain, mc_updated, mc_update_cb); } /* * Remove the mc change handler. */ int remove_mc_update_handler(swig_cb *handler) { cb_rm(domain, mc_updated, mc_update_cb); } /* * Iterate through all the MCs in the object. The * domain_iter_mc_cb method will be called on the first parameter for * each mc in the domain. The parameters it receives will be: * . */ int iterate_mcs(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, domain_iter_mc_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, domain_iter_mc_cb); ipmi_domain_iterate_mcs(self, domain_iterate_mcs_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Return the type of the domain, either unknown, mxp, or atca. * Others may be added later. */ const char *get_type() { return ipmi_domain_get_type_string(ipmi_domain_get_type(self)); } /* * Scan all the addresses on the given channel (parm 1) between * (and including) start_addr (parm 2) and end_addr (parm 3) and * call the "domain_ipmb_mc_scan_cb" method on the handler (parm4) * with the following parms (if the parm is provided and defined): * , , */ int start_ipmb_mc_scan(int channel, int start_addr, int end_addr, swig_cb *handler = NULL) { int rv; swig_cb_val *handler_val = NULL; ipmi_domain_cb domain_cb = NULL; IPMI_SWIG_C_CB_ENTRY if (!nil_swig_cb(handler)) { if (!valid_swig_cb(handler, domain_ipmb_mc_scan_cb)) { rv = EINVAL; goto out_err; } domain_cb = ipmb_mc_scan_handler; handler_val = ref_swig_cb(handler, domain_ipmb_mc_scan_cb); } rv = ipmi_start_ipmb_mc_scan(self, channel, start_addr, end_addr, domain_cb, handler_val); if (rv && handler_val) deref_swig_cb_val(handler_val); out_err: IPMI_SWIG_C_CB_EXIT return rv; } /* Scan all IPMB busses for new/lost MCs. */ void start_full_ipmb_scan() { ipmi_domain_start_full_ipmb_scan(self); } /* * Send a command to a given address (parm 1) with the given lun * (parm 2), netfn (parm 3), command (parm 4). Parm 5 is the * message data in an array reference. Parm 6 is the handler, it * will be called with the response. The addr_cmd_cb method will * be called on the handler handler if it is provided and defined; * its parameters are: * */ int send_command_addr(char *addr, int lun, int netfn, int cmd, intarray msg_data, swig_cb *handler = NULL) { int rv; swig_cb_val *handler_val = NULL; ipmi_addr_response_handler_t msg_cb = NULL; ipmi_addr_t iaddr; unsigned int addr_len; ipmi_msg_t msg; unsigned char data[MAX_IPMI_DATA_SIZE]; unsigned int data_len; IPMI_SWIG_C_CB_ENTRY rv = parse_ipmi_addr(addr, lun, &iaddr, &addr_len); if (rv) goto out_err; msg.netfn = netfn; msg.cmd = cmd; msg.data = data; rv = parse_ipmi_data(msg_data, data, sizeof(data), &data_len); msg.data_len = data_len; if (rv) goto out_err; if (!nil_swig_cb(handler)) { if (!valid_swig_cb(handler, addr_cmd_cb)) { rv = EINVAL; goto out_err; } msg_cb = domain_msg_cb; handler_val = ref_swig_cb(handler, addr_cmd_cb); } rv = ipmi_send_command_addr(self, &iaddr, addr_len, &msg, msg_cb, handler_val, NULL); if (rv && handler_val) deref_swig_cb_val(handler_val); out_err: IPMI_SWIG_C_CB_EXIT return rv; } /* * Cause the domain to start detecting presence changes. If parm * 1 is supplied, it tells whether to force all entities to have * their presence checked (if true) or just detect entity presence * for ones that might have changed. */ int detect_presence_changes(int force = 0) { return ipmi_detect_domain_presence_changes(self, force); } /* * Set the time (in seconds) between SEL rescans for all * SELs in the domain */ void set_sel_rescan_time(int seconds) { return ipmi_domain_set_sel_rescan_time(self, seconds); } /* * Get the default SEL rescan time for the domain. */ int get_sel_rescan_time() { return ipmi_domain_get_sel_rescan_time(self); } /* * Set the time (in seconds) between IPMB bus rescans for the * domain. */ void set_ipmb_rescan_time(int seconds) { return ipmi_domain_set_ipmb_rescan_time(self, seconds); } /* * Get the default IPMB rescan time for the domain. */ int get_ipmb_rescan_time() { return ipmi_domain_get_ipmb_rescan_time(self); } /* * Add a handler to be called when a new unhandled event comes * into the domain. When the event comes in, the event_cb method * on the first parameter will be called with the following * parameters: , , */ int add_event_handler(swig_cb *handler) { ipmi_domain_add_event_handler_cl (self, domain_event_handler_cl, NULL); cb_add(domain, event, event_cb); } /* * Remove the event handler. */ int remove_event_handler(swig_cb *handler) { cb_rm(domain, event, event_cb); } %newobject first_event; /* * Retrieve the first event from the domain. Return NULL (undef) * if the event does not exist. */ ipmi_event_t *first_event() { return ipmi_domain_first_event(self); } %newobject last_event; /* * Retrieve the last event from the domain. */ ipmi_event_t *last_event() { return ipmi_domain_last_event(self); } %newobject next_event; /* * Retrieve the event after the given event from the domain. */ ipmi_event_t *next_event(ipmi_event_t *event) { return ipmi_domain_next_event(self, event); } %newobject prev_event; /* * Retrieve the event before the given event from the domain. */ ipmi_event_t *prev_event(ipmi_event_t *event) { return ipmi_domain_prev_event(self, event); } /* * Number of live entries in the local SEL copy. */ int sel_count() { int rv; unsigned int count; rv = ipmi_domain_sel_count(self, &count); if (rv) return 0; else return count; } /* * Number of entries in the the remote SEL. If an entry has been * deleted in the local copy of the SEL but has not yet finished * being deleted in the remote copy, it will be counted here. */ int sel_entries_used() { int rv; unsigned int count; rv = ipmi_domain_sel_entries_used(self, &count); if (rv) return 0; else return count; } /* * Reread all SELs in the domain. The domain_reread_sels_cb * method on the first parameter (if supplied) will be called with * the following values: */ int reread_sels(swig_cb *handler = NULL) { int rv; swig_cb_val *handler_val = NULL; ipmi_domain_cb domain_cb = NULL; IPMI_SWIG_C_CB_ENTRY if (!nil_swig_cb(handler)) { if (!valid_swig_cb(handler, domain_reread_sels_cb)) { rv = EINVAL; goto out_err; } domain_cb = domain_reread_sels_handler; handler_val = ref_swig_cb(handler, domain_reread_sels_cb); } rv = ipmi_domain_reread_sels(self, domain_cb, handler_val); if (rv && handler_val) deref_swig_cb_val(handler_val); out_err: IPMI_SWIG_C_CB_EXIT return rv; } /* * Fetch a FRU with the given parameters. The first parameter (the object) * is the domain, successive parameters are: * is_logical - do a logical or physical FRU fetch. * device_address - The IPMB address of the FRU device. * device_id - The particular FRU device id to fetch. * LUN - The LUN to talk to for the device. * private_bus - for physical FRUs, the bus it is on. * channel - The channel where the device is located. * If the handler is supplied, then the fru_fetched method on that * will be called upon completion with the handler object as the first * parameter, the domain as the second, the FRU as the third, and an * error value as the fourth. * This returns the FRU, or undefined if a failure occurred. */ %newobject fru_alloc; ipmi_fru_t *fru_alloc(int is_logical, int device_address, int device_id, int lun, int private_bus, int channel, swig_cb *handler = NULL) { ipmi_fru_t *fru = NULL; int rv; swig_cb_val *handler_val = NULL; ipmi_fru_cb cb_handler = NULL; IPMI_SWIG_C_CB_ENTRY if (!nil_swig_cb(handler)) { if (!valid_swig_cb(handler, fru_fetched)) goto out_err; cb_handler = fru_fetched; handler_val = ref_swig_cb(handler, fru_fetched); } rv = ipmi_domain_fru_alloc(self, is_logical, device_address, device_id, lun, private_bus, channel, cb_handler, handler_val, &fru); if (rv) { if (handler_val) deref_swig_cb_val(handler_val); fru = NULL; } else { /* We have one ref for the callback already, add a ref for the returned value. */ if (handler_val) ipmi_fru_ref(fru); } out_err: IPMI_SWIG_C_CB_EXIT return fru; } /* * Allocate a pet object for the domain over the given connection. * The pet is returned. The ninth parameter is an optional * callback object, the got_pet_cb method will be called on it * when the PET fetch is complete. It will have the following * parameters: . The parameters are: * int connection: the connection to the domain to set up the PET for * int channel: the channel number to set the PET for * char ip_addr: the address to send the traps to * char mac_addr: the mac address to send the traps to * The rest are the selectors in the various tables, you have to * read the spec and know your system to know how to set them. * int eft_sel: * int policy_num: * int apt_sel: * int lan_dest_sel: * * Note that you must keep a reference to the pet around, or it will * be automatically destroyed by the garbage collector. */ %newobject get_pet; ipmi_pet_t *get_pet(int connection, int channel, char *ip_addr, char *mac_addr, int eft_sel, int policy_num, int apt_sel, int lan_dest_sel, swig_cb *handler = NULL) { int rv; ipmi_pet_t *pet = NULL; swig_cb_val *handler_val = NULL; struct in_addr ip; unsigned char mac[6]; ipmi_pet_done_cb done = NULL; IPMI_SWIG_C_CB_ENTRY rv = parse_ip_addr(ip_addr, &ip); if (rv) goto out_err; rv = parse_mac_addr(mac_addr, mac); if (rv) goto out_err; if (!nil_swig_cb(handler)) { if (!valid_swig_cb(handler, got_pet_cb)) goto out_err; handler_val = ref_swig_cb(handler, got_pet_cb); done = get_pet; } rv = ipmi_pet_create(self, connection, channel, ip, mac, eft_sel, policy_num, apt_sel, lan_dest_sel, get_pet, handler_val, &pet); if (rv && handler_val) deref_swig_cb_val(handler_val); out_err: IPMI_SWIG_C_CB_EXIT return pet; } /* * Allocate a SoL object using the given domain's connection. * Note that this does not cause a connection, it just creates an * object for doing an SoL connection. * * The handler val will handle all events from the SOL session. * this means it must implement the following callbacks: * * sol_connection_state_change * sol_data_received * sol_break_detected * sol_bmc_transmit_overrun */ %newobject create_sol; ipmi_sol_conn_t *create_sol(int connection, swig_cb *handler) { ipmi_con_t *con; ipmi_sol_conn_t *scon; int rv; swig_cb_val *handler_val; if (nil_swig_cb(handler)) return NULL; if (!valid_swig_cb(handler, sol_connection_state_change)) return NULL; if (!valid_swig_cb(handler, sol_data_received)) return NULL; if (!valid_swig_cb(handler, sol_break_detected)) return NULL; if (!valid_swig_cb(handler, sol_bmc_transmit_overrun)) return NULL; con = ipmi_domain_get_connection(self, connection); if (!con) return NULL; rv = ipmi_sol_create(con, &scon); if (rv) { con->close_connection(con); return NULL; } handler_val = ref_swig_gencb(handler); rv = ipmi_sol_register_connection_state_callback (scon, sol_connection_state_change_cb, handler_val); if (rv) goto out_err; rv = ipmi_sol_register_data_received_callback (scon, sol_data_received_cb, handler_val); if (rv) goto out_err; rv = ipmi_sol_register_break_detected_callback (scon, sol_break_detected_cb, handler_val); if (rv) goto out_err; rv = ipmi_sol_register_bmc_transmit_overrun_callback (scon, sol_bmc_transmit_overrun_cb, handler_val); if (rv) goto out_err; return scon; out_err: deref_swig_cb_val(handler_val); ipmi_sol_free(scon); return NULL; } } /* * Allocate an args structure of the given connection type, generally * "smi" or Lan". */ %newobject alloc_empty_args; ipmi_args_t *alloc_empty_args(char *con_type); %{ static ipmi_args_t * alloc_empty_args(char *con_type) { int rv; ipmi_args_t *argv; rv = ipmi_args_alloc(con_type, &argv); if (rv) return NULL; return argv; } %} /* * Parse the array of arguments. The arguments is a list/array of * strings and parsed using the standard algorithms. */ %newobject alloc_parse_args; ipmi_args_t *alloc_parse_args(argarray *args); %{ static ipmi_args_t * alloc_parse_args(argarray *args) { int rv; ipmi_args_t *argv; int i = 0; rv = ipmi_parse_args(&i, args->len, args->val, &argv); if (rv) return NULL; return argv; } %} %extend ipmi_args_t { ~ipmi_args_t() { ipmi_free_args(self); } /* * Return the type of connection, generally "lan" or "smi". */ const char *get_type() { return ipmi_args_get_type(self); } /* * An args is a set of fields indexed by argnum. Fetching an * argument returns the name, type, help string, and value. E2BIG * is returned if argnum is larger than the number of fields. * Type will be either "str" for a string or integer or IP address * or other field like that, "bool" for a boolean, and "enum" for * an enumeration type. The "str" type, obviously, may have * semantics behind it. The "bool" value will be either "true" or * "false". For enums, an array of strings is returned as "range" * and the value will be one of these strings. */ int get_val(int argnum, const char **name, const char **type, const char **help, char **value, strconstarray *range) { int rv; const char **irange = NULL; char *ivalue = NULL; rv = ipmi_args_get_val(self, argnum, name, type, help, &ivalue, &irange); if (rv) return rv; if (ivalue) { /* Convert it to a normal malloc() so char ** will work. */ char *ivalue2 = strdup(ivalue); ipmi_args_free_str(self, ivalue); ivalue = ivalue2; } *value = ivalue; if (irange) { int len; for (len=0; irange[len]; len++) ; range->len = len; range->val = irange; } return 0; } /* * Set the given field. If name is not NULL, then find the field * by name. If name is NULL, then argnum is used for the field. * If the value does not match the semantics of the field, an * error is returned. */ int set_val(int argnum, const char *name, const char *value) { return ipmi_args_set_val(self, argnum, name, value); } } /* * A entity id object. This object is guaranteed to be valid and * can be converted into a entity pointer later. */ %extend ipmi_entity_id_t { ~ipmi_entity_id_t() { free(self); } /* Compare self with other, return -1 if selfother. */ int cmp(ipmi_entity_id_t *other) { return ipmi_cmp_entity_id(*self, *other); } /* * Convert a entity id to a entity pointer. The "entity_cb" method * will be called on the first parameter with the following parameters: * */ int to_entity(swig_cb *handler) { int rv; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, entity_cb)) rv = EINVAL; else rv = ipmi_entity_pointer_cb(*self, handle_entity_cb, get_swig_cb(handler, entity_cb)); IPMI_SWIG_C_CB_EXIT return rv; } } %constant int ENTITY_ID_UNSPECIFIED = IPMI_ENTITY_ID_UNSPECIFIED; %constant int ENTITY_ID_OTHER = IPMI_ENTITY_ID_OTHER; %constant int ENTITY_ID_UNKOWN = IPMI_ENTITY_ID_UNKOWN; %constant int ENTITY_ID_PROCESSOR = IPMI_ENTITY_ID_PROCESSOR; %constant int ENTITY_ID_DISK = IPMI_ENTITY_ID_DISK; %constant int ENTITY_ID_PERIPHERAL = IPMI_ENTITY_ID_PERIPHERAL; %constant int ENTITY_ID_SYSTEM_MANAGEMENT_MODULE = IPMI_ENTITY_ID_SYSTEM_MANAGEMENT_MODULE; %constant int ENTITY_ID_SYSTEM_BOARD = IPMI_ENTITY_ID_SYSTEM_BOARD; %constant int ENTITY_ID_MEMORY_MODULE = IPMI_ENTITY_ID_MEMORY_MODULE; %constant int ENTITY_ID_PROCESSOR_MODULE = IPMI_ENTITY_ID_PROCESSOR_MODULE; %constant int ENTITY_ID_POWER_SUPPLY = IPMI_ENTITY_ID_POWER_SUPPLY; %constant int ENTITY_ID_ADD_IN_CARD = IPMI_ENTITY_ID_ADD_IN_CARD; %constant int ENTITY_ID_FRONT_PANEL_BOARD = IPMI_ENTITY_ID_FRONT_PANEL_BOARD; %constant int ENTITY_ID_BACK_PANEL_BOARD = IPMI_ENTITY_ID_BACK_PANEL_BOARD; %constant int ENTITY_ID_POWER_SYSTEM_BOARD = IPMI_ENTITY_ID_POWER_SYSTEM_BOARD; %constant int ENTITY_ID_DRIVE_BACKPLANE = IPMI_ENTITY_ID_DRIVE_BACKPLANE; %constant int ENTITY_ID_SYSTEM_INTERNAL_EXPANSION_BOARD = IPMI_ENTITY_ID_SYSTEM_INTERNAL_EXPANSION_BOARD; %constant int ENTITY_ID_OTHER_SYSTEM_BOARD = IPMI_ENTITY_ID_OTHER_SYSTEM_BOARD; %constant int ENTITY_ID_PROCESSOR_BOARD = IPMI_ENTITY_ID_PROCESSOR_BOARD; %constant int ENTITY_ID_POWER_UNIT = IPMI_ENTITY_ID_POWER_UNIT; %constant int ENTITY_ID_POWER_MODULE = IPMI_ENTITY_ID_POWER_MODULE; %constant int ENTITY_ID_POWER_MANAGEMENT_BOARD = IPMI_ENTITY_ID_POWER_MANAGEMENT_BOARD; %constant int ENTITY_ID_CHASSIS_BACK_PANEL_BOARD = IPMI_ENTITY_ID_CHASSIS_BACK_PANEL_BOARD; %constant int ENTITY_ID_SYSTEM_CHASSIS = IPMI_ENTITY_ID_SYSTEM_CHASSIS; %constant int ENTITY_ID_SUB_CHASSIS = IPMI_ENTITY_ID_SUB_CHASSIS; %constant int ENTITY_ID_OTHER_CHASSIS_BOARD = IPMI_ENTITY_ID_OTHER_CHASSIS_BOARD; %constant int ENTITY_ID_DISK_DRIVE_BAY = IPMI_ENTITY_ID_DISK_DRIVE_BAY; %constant int ENTITY_ID_PERIPHERAL_BAY = IPMI_ENTITY_ID_PERIPHERAL_BAY; %constant int ENTITY_ID_DEVICE_BAY = IPMI_ENTITY_ID_DEVICE_BAY; %constant int ENTITY_ID_FAN_COOLING = IPMI_ENTITY_ID_FAN_COOLING; %constant int ENTITY_ID_COOLING_UNIT = IPMI_ENTITY_ID_COOLING_UNIT; %constant int ENTITY_ID_CABLE_INTERCONNECT = IPMI_ENTITY_ID_CABLE_INTERCONNECT; %constant int ENTITY_ID_MEMORY_DEVICE = IPMI_ENTITY_ID_MEMORY_DEVICE; %constant int ENTITY_ID_SYSTEM_MANAGEMENT_SOFTWARE = IPMI_ENTITY_ID_SYSTEM_MANAGEMENT_SOFTWARE; %constant int ENTITY_ID_BIOS = IPMI_ENTITY_ID_BIOS; %constant int ENTITY_ID_OPERATING_SYSTEM = IPMI_ENTITY_ID_OPERATING_SYSTEM; %constant int ENTITY_ID_SYSTEM_BUS = IPMI_ENTITY_ID_SYSTEM_BUS; %constant int ENTITY_ID_GROUP = IPMI_ENTITY_ID_GROUP; %constant int ENTITY_ID_REMOTE_MGMT_COMM_DEVICE = IPMI_ENTITY_ID_REMOTE_MGMT_COMM_DEVICE; %constant int ENTITY_ID_EXTERNAL_ENVIRONMENT = IPMI_ENTITY_ID_EXTERNAL_ENVIRONMENT; %constant int ENTITY_ID_BATTERY = IPMI_ENTITY_ID_BATTERY; %constant int ENTITY_ID_PROCESSING_BLADE = IPMI_ENTITY_ID_PROCESSING_BLADE; %constant int ENTITY_ID_CONNECTIVITY_SWITCH = IPMI_ENTITY_ID_CONNECTIVITY_SWITCH; %constant int ENTITY_ID_PROCESSOR_MEMORY_MODULE = IPMI_ENTITY_ID_PROCESSOR_MEMORY_MODULE; %constant int ENTITY_ID_IO_MODULE = IPMI_ENTITY_ID_IO_MODULE; %constant int ENTITY_ID_PROCESSOR_IO_MODULE = IPMI_ENTITY_ID_PROCESSOR_IO_MODULE; %constant int ENTITY_ID_MGMT_CONTROLLER_FIRMWARE = IPMI_ENTITY_ID_MGMT_CONTROLLER_FIRMWARE; %constant int ENTITY_ID_IPMI_CHANNEL = IPMI_ENTITY_ID_IPMI_CHANNEL; %constant int ENTITY_ID_PCI_BUS = IPMI_ENTITY_ID_PCI_BUS; %constant int ENTITY_ID_PCI_EXPRESS_BUS = IPMI_ENTITY_ID_PCI_EXPRESS_BUS; %constant int ENTITY_ID_SCSI_BUS = IPMI_ENTITY_ID_SCSI_BUS; %constant int ENTITY_ID_SATA_SAS_BUS = IPMI_ENTITY_ID_SATA_SAS_BUS; %constant int ENTITY_ID_PROCESSOR_FRONT_SIDE_BUS = IPMI_ENTITY_ID_PROCESSOR_FRONT_SIDE_BUS; /* * An entity object. */ %extend ipmi_entity_t { /* * Get the domain the entity belongs to. */ ipmi_domain_t *get_domain() { return ipmi_entity_get_domain(self); } %newobject get_name; /* * Get the name of an entity. */ char *get_name() { char name[IPMI_ENTITY_NAME_LEN]; ipmi_entity_get_name(self, name, sizeof(name)); return strdup(name); } %newobject get_id; /* * Get the id for the entity. */ ipmi_entity_id_t *get_id() { ipmi_entity_id_t *rv = malloc(sizeof(*rv)); if (rv) *rv = ipmi_entity_convert_to_id(self); return rv; } /* * Iterate through all the entity's children. The * entity_iter_entities_cb method will be called on the first * parameter for each child entity of the parent. The parameters * it receives will be: . */ int iterate_children(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, entity_iter_entities_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, entity_iter_entities_cb); ipmi_entity_iterate_children(self, entity_iterate_entities_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Iterate through all the entity's parents. The * entity_iter_entities_cb method will be called on the first * parameter for each parent entity of the child. The parameters * it receives will be: . */ int iterate_parents(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, entity_iter_entities_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, entity_iter_entities_cb); ipmi_entity_iterate_parents(self, entity_iterate_entities_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Iterate through all the entity's sensors. The * entity_iter_sensors_cb method will be called on the first * parameter for each sensor of the entity. The parameters * it receives will be: . */ int iterate_sensors(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, entity_iter_sensors_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, entity_iter_sensors_cb); ipmi_entity_iterate_sensors(self, entity_iterate_sensors_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Iterate through all the entity's controls. The * entity_iter_controls_cb method will be called on the first * parameter for each control of the entity. The parameters * it receives will be: . */ int iterate_controls(swig_cb *handler) { swig_cb_val *handler_val; int rv = 0; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, entity_iter_controls_cb)) rv = EINVAL; else { handler_val = get_swig_cb(handler, entity_iter_controls_cb); ipmi_entity_iterate_controls(self, entity_iterate_controls_handler, handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* * Add a handler to be called when an entity's presence * changes. When the presence changes the entity_presence_cb * method on the first parameter will be called with the following * parameters: . * The event is optional and may not be present. */ int add_presence_handler(swig_cb *handler) { ipmi_entity_add_presence_handler_cl (self, entity_presence_handler_cl, NULL); cb_add(entity, presence, entity_presence_cb); } /* * Remove the presence handler. */ int remove_presence_handler(swig_cb *handler) { cb_rm(entity, presence, entity_presence_cb); } /* * Add a handler to be called when a sensor in the entity is * added, deleted, or updated. When the sensor changes the * entity_sensor_update_cb method on the first parameter will be * called with the following parameters: * added|deleted|changed . */ int add_sensor_update_handler(swig_cb *handler) { ipmi_entity_add_sensor_update_handler_cl (self, entity_sensor_update_handler_cl, NULL); cb_add(entity, sensor_update, entity_sensor_update_cb); } /* * Remove the sensor update handler. */ int remove_sensor_update_handler(swig_cb *handler) { cb_rm(entity, sensor_update, entity_sensor_update_cb); } /* * Add a handler to be called when a control in the entity is * added, deleted, or updated. When the control changes the * entity_control_update_cb method on the first parameter will be * called with the following parameters: * added|deleted|changed . */ int add_control_update_handler(swig_cb *handler) { ipmi_entity_add_control_update_handler_cl (self, entity_control_update_handler_cl, NULL); cb_add(entity, control_update, entity_control_update_cb); } /* * Remove the control update handler. */ int remove_control_update_handler(swig_cb *handler) { cb_rm(entity, control_update, entity_control_update_cb); } /* * Add a handler to be called when the FRU data in the entity is * added, deleted, or updated. When the FRU data changes the * entity_fru_update_cb method on the first parameter will be * called with the following parameters: * added|deleted|changed . * * Deprecated, use the werr version below so you can get errors * reported. */ int add_fru_update_handler(swig_cb *handler) { ipmi_entity_add_fru_update_handler_cl (self, entity_fru_update_handler_cl, NULL); cb_add(entity, fru_update, entity_fru_update_cb); } /* * Remove the FRU data update handler. */ int remove_fru_update_handler(swig_cb *handler) { cb_rm(entity, fru_update, entity_fru_update_cb); } /* * Add a handler to be called when the FRU data in the entity is * added, deleted, or updated. When the FRU data changes the * entity_fru_update_werr_cb method on the first parameter will be * called with the following parameters: * added|deleted|changed|error . */ int add_fru_update_werr_handler(swig_cb *handler) { ipmi_entity_add_fru_update_werr_handler_cl (self, entity_fru_update_werr_handler_cl, NULL); cb_add(entity, fru_update_werr, entity_fru_update_werr_cb); } /* * Remove the FRU data update handler. */ int remove_fru_update_werr_handler(swig_cb *handler) { cb_rm(entity, fru_update_werr, entity_fru_update_werr_cb); } /* * Get the entities type, return "mc", "fru", "generic", or "unknown". */ char *get_type() { switch (ipmi_entity_get_type(self)) { case IPMI_ENTITY_MC: return "mc"; case IPMI_ENTITY_FRU: return "fru"; case IPMI_ENTITY_GENERIC: return "generic"; default: return "unknown"; } } /* * Returns if the entity has FRU data or not. */ int is_fru() { return ipmi_entity_get_is_fru(self); } %newobject get_id_string; /* * Get the ID string from the SDR */ char *get_id_string() { int length = ipmi_entity_get_id_length(self); char *str; if (length < 2) return NULL; str = malloc(length); if (!str) return NULL; ipmi_entity_get_id(self, str, length); return str; } /* * Get the entity id for the entity */ int get_entity_id() { return ipmi_entity_get_entity_id(self); } /* * Get the string representation of the entity id */ const char *get_entity_id_string() { return ipmi_entity_get_entity_id_string(self); } /* * Get the entity instance for the entity */ int get_entity_instance() { return ipmi_entity_get_entity_instance(self); } /* * Get the channel for the entity. Only valid if the entity * instance is 0x60 or larger. */ int get_entity_device_channel() { return ipmi_entity_get_device_channel(self); } /* * Get the address for the entity. Only valid if the entity * instance is 0x60 or larger. */ int get_entity_device_address() { return ipmi_entity_get_device_address(self); } /* * Get the FRU data for the entity. Note that you cannot hold the * FRU data pointer outside the context of where the entity pointer * is valid. */ %newobject get_fru; ipmi_fru_t *get_fru() { ipmi_fru_t *fru = ipmi_entity_get_fru(self); if (fru) ipmi_fru_ref(fru); return fru; } /* * If this returns true, then the presence sensor is always there * for this entity. */ int get_presence_sensor_always_there() { return ipmi_entity_get_presence_sensor_always_there(self); } /* * Returns if the entity has a parent. */ int is_child() { return ipmi_entity_get_is_child(self); } /* * Returns if the entity has a child. */ int is_parent() { return ipmi_entity_get_is_parent(self); } /* * Return the channel from the device locator record. Valid for * all entities except unknown. */ int get_channel() { return ipmi_entity_get_channel(self); } /* * Return the LUN from the device locator record. Valid for * all entities except unknown. */ int get_lun() { return ipmi_entity_get_lun(self); } /* * Return the OEM byte from the device locator record. Valid for * all entities except unknown. */ int get_oem() { return ipmi_entity_get_oem(self); } /* * Return the access address from the device locator record. Valid for * FRU and generic entities. */ int get_access_address() { return ipmi_entity_get_access_address(self); } /* * Return the private bus id from the device locator record. Valid for * FRU and generic entities. */ int get_private_bus_id() { return ipmi_entity_get_private_bus_id(self); } /* * Return the device type from the device locator record. Valid for * FRU and generic entities. */ int get_device_type() { return ipmi_entity_get_device_type(self); } /* * Return the device modifier from the device locator record. * Valid for FRU and generic entities. */ int get_device_modifier() { return ipmi_entity_get_device_modifier(self); } /* * Return the slave address from the device locator record. Valid for * MC and generic entities. */ int get_slave_address() { return ipmi_entity_get_slave_address(self); } %newobject get_mc_id; ipmi_mcid_t *get_mc_id() { ipmi_mcid_t *mc_id = malloc(sizeof(*mc_id)); int rv; rv = ipmi_entity_get_mc_id(self, mc_id); if (rv) { free(mc_id); mc_id = NULL; } return mc_id; } /* * Return if the FRU is logical (from the device locator record). * Valid for FRU entities. */ int get_is_logical_fru() { return ipmi_entity_get_is_logical_fru(self); } /* * Return the device id from the device locator record. Valid for * FRU entities. */ int get_fru_device_id() { return ipmi_entity_get_fru_device_id(self); } /* * Return the ACPI system power notify required bit from the * device locator record. Valid for MC entities. */ int get_ACPI_system_power_notify_required() { return ipmi_entity_get_ACPI_system_power_notify_required(self); } /* * Return the ACPI device power notify required bit from the * device locator record. Valid for MC entities. */ int get_ACPI_device_power_notify_required() { return ipmi_entity_get_ACPI_device_power_notify_required(self); } /* * Return the controller logs init agent errors bit from the * device locator record. Valid for MC entities. */ int get_controller_logs_init_agent_errors() { return ipmi_entity_get_controller_logs_init_agent_errors(self); } /* * Return the log init agent errors accessing bit from the * device locator record. Valid for MC entities. */ int get_log_init_agent_errors_accessing() { return ipmi_entity_get_log_init_agent_errors_accessing(self); } /* * Return the global init bit from the * device locator record. Valid for MC entities. */ int get_global_init() { return ipmi_entity_get_global_init(self); } /* * Return the chassis device bit from the * device locator record. Valid for MC entities. */ int get_chassis_device() { return ipmi_entity_get_chassis_device(self); } /* * Return the !bridge bit from the * device locator record. Valid for MC entities. */ int get_bridge() { return ipmi_entity_get_bridge(self); } /* * Return the IPMB event generator bit from the * device locator record. Valid for MC entities. */ int get_IPMB_event_generator() { return ipmi_entity_get_IPMB_event_generator(self); } /* * Return the IPMB event receiver bit from the * device locator record. Valid for MC entities. */ int get_IPMB_event_receiver() { return ipmi_entity_get_IPMB_event_receiver(self); } /* * Return the FRU inventory device bit from the * device locator record. Valid for MC entities. */ int get_FRU_inventory_device() { return ipmi_entity_get_FRU_inventory_device(self); } /* * Return the SEL device bit from the * device locator record. Valid for MC entities. */ int get_SEL_device() { return ipmi_entity_get_SEL_device(self); } /* * Return the SDR repository device bit from the * device locator record. Valid for MC entities. */ int get_SDR_repository_device() { return ipmi_entity_get_SDR_repository_device(self); } /* * Return the sensor device bit from the * device locator record. Valid for MC entities. */ int get_sensor_device() { return ipmi_entity_get_sensor_device(self); } /* * Return the address span from the device locator record. Valid * for generic entities. */ int get_address_span() { return ipmi_entity_get_address_span(self); } %newobject get_dlr_id; /* * Return the id string from the DLR. */ char *get_dlr_id() { /* FIXME - no unicode handling. */ int len = ipmi_entity_get_id_length(self) + 1; char *id = malloc(len); ipmi_entity_get_id(self, id, len); return id; } /* * Returns true if the entity is present, false if not. */ int is_present() { return ipmi_entity_is_present(self); } /* * Returns the physical slot number, or -1 if there is not * a slot number. */ int get_physical_slot_num() { unsigned int num; if (ipmi_entity_get_physical_slot_num(self, &num) == 0) return num; else return -1; } /* * Returns true if the entity is hot-swappable, false if not. */ int is_hot_swappable() { return ipmi_entity_hot_swappable(self); } int supports_managed_hot_swap() { return ipmi_entity_supports_managed_hot_swap(self); } /* * Add a handler to be called when the hot-swap state for the * entity changes. When the hot-swap state changes the * entity_hot_swap_update_cb method on the first parameter will be * called with the following parameters: . The event is optional and may not * be present. */ int add_hot_swap_handler(swig_cb *handler) { ipmi_entity_add_hot_swap_handler_cl (self, entity_hot_swap_handler_cl, NULL); cb_add(entity, hot_swap, entity_hot_swap_update_cb); } /* * Remove the hot-swap update handler. */ int remove_hot_swap_handler(swig_cb *handler) { cb_rm(entity, hot_swap, entity_hot_swap_update_cb); } /* * Get the current hot-swap state for the entity. The * entity_hot_swap_cb handler will be called with the following * parameters: */ int get_hot_swap_state(swig_cb *handler) { swig_cb_val *handler_val; int rv; IPMI_SWIG_C_CB_ENTRY if (! valid_swig_cb(handler, entity_hot_swap_cb)) rv = EINVAL; else { handler_val = ref_swig_cb(handler, entity_hot_swap_cb); rv = ipmi_entity_get_hot_swap_state(self, entity_get_hot_swap_handler, handler_val); if (rv) deref_swig_cb_val(handler_val); } IPMI_SWIG_C_CB_EXIT return rv; } /* Returns if the entity supports auto-activate. */ int supports_auto_activate_time() { return ipmi_entity_supports_auto_activate_time(self); } /* * Get the current hot-swap activation time for the entity. The * entity_hot_swap_get_time_cb handler will be called with the * following parameters: