Message ID | 1447354953-18893-3-git-send-email-minyard@acm.org |
---|---|
State | Superseded |
Headers | show |
I haven't heard any more comments on this series, should I resubmit with the one shutdown change? -corey On Nov 12, 2015 1:02 PM, <minyard@acm.org> wrote: > From: Corey Minyard <cminyard@mvista.com> > > Add the basic IPMI types and infrastructure to QEMU. Low-level > interfaces and simulation interfaces will register with this; it's > kind of the go-between to tie them together. > > Signed-off-by: Corey Minyard <cminyard@mvista.com> > --- > default-configs/i386-softmmu.mak | 1 + > default-configs/x86_64-softmmu.mak | 1 + > hw/Makefile.objs | 1 + > hw/ipmi/Makefile.objs | 1 + > hw/ipmi/ipmi.c | 125 ++++++++++++++++++++++++++ > include/hw/ipmi/ipmi.h | 178 > +++++++++++++++++++++++++++++++++++++ > qemu-doc.texi | 2 + > 7 files changed, 309 insertions(+) > create mode 100644 hw/ipmi/Makefile.objs > create mode 100644 hw/ipmi/ipmi.c > create mode 100644 include/hw/ipmi/ipmi.h > > diff --git a/default-configs/i386-softmmu.mak > b/default-configs/i386-softmmu.mak > index 43c96d1..8fa751a 100644 > --- a/default-configs/i386-softmmu.mak > +++ b/default-configs/i386-softmmu.mak > @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y > CONFIG_VMWARE_VGA=y > CONFIG_VIRTIO_VGA=y > CONFIG_VMMOUSE=y > +CONFIG_IPMI=y > CONFIG_SERIAL=y > CONFIG_PARALLEL=y > CONFIG_I8254=y > diff --git a/default-configs/x86_64-softmmu.mak > b/default-configs/x86_64-softmmu.mak > index dfb8095..6767f4f 100644 > --- a/default-configs/x86_64-softmmu.mak > +++ b/default-configs/x86_64-softmmu.mak > @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y > CONFIG_VMWARE_VGA=y > CONFIG_VIRTIO_VGA=y > CONFIG_VMMOUSE=y > +CONFIG_IPMI=y > CONFIG_SERIAL=y > CONFIG_PARALLEL=y > CONFIG_I8254=y > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > index 7e7c241..4a07ed4 100644 > --- a/hw/Makefile.objs > +++ b/hw/Makefile.objs > @@ -13,6 +13,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += ide/ > devices-dirs-$(CONFIG_SOFTMMU) += input/ > devices-dirs-$(CONFIG_SOFTMMU) += intc/ > devices-dirs-$(CONFIG_IPACK) += ipack/ > +devices-dirs-$(CONFIG_IPMI) += ipmi/ > devices-dirs-$(CONFIG_SOFTMMU) += isa/ > devices-dirs-$(CONFIG_SOFTMMU) += misc/ > devices-dirs-$(CONFIG_SOFTMMU) += net/ > diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs > new file mode 100644 > index 0000000..65bde11 > --- /dev/null > +++ b/hw/ipmi/Makefile.objs > @@ -0,0 +1 @@ > +common-obj-$(CONFIG_IPMI) += ipmi.o > diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c > new file mode 100644 > index 0000000..7d17469 > --- /dev/null > +++ b/hw/ipmi/ipmi.c > @@ -0,0 +1,125 @@ > +/* > + * QEMU IPMI emulation > + * > + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC > + * > + * Permission is hereby granted, free of charge, to any person obtaining > a copy > + * of this software and associated documentation files (the "Software"), > to deal > + * in the Software without restriction, including without limitation the > rights > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or > sell > + * copies of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be > included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR > OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > IN > + * THE SOFTWARE. > + */ > + > +#include "hw/hw.h" > +#include "hw/ipmi/ipmi.h" > +#include "sysemu/sysemu.h" > +#include "qmp-commands.h" > +#include "qom/object_interfaces.h" > +#include "qapi/visitor.h" > + > +static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly) > +{ > + switch (op) { > + case IPMI_RESET_CHASSIS: > + if (checkonly) { > + return 0; > + } > + qemu_system_reset_request(); > + return 0; > + > + case IPMI_POWEROFF_CHASSIS: > + if (checkonly) { > + return 0; > + } > + qemu_system_powerdown_request(); > + return 0; > + > + case IPMI_SEND_NMI: > + if (checkonly) { > + return 0; > + } > + qemu_mutex_lock_iothread(); > + qmp_inject_nmi(NULL); > + qemu_mutex_unlock_iothread(); > + return 0; > + > + case IPMI_POWERCYCLE_CHASSIS: > + case IPMI_PULSE_DIAG_IRQ: > + case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP: > + case IPMI_POWERON_CHASSIS: > + default: > + return IPMI_CC_COMMAND_NOT_SUPPORTED; > + } > +} > + > +static void ipmi_interface_class_init(ObjectClass *class, void *data) > +{ > + IPMIInterfaceClass *ik = IPMI_INTERFACE_CLASS(class); > + > + ik->do_hw_op = ipmi_do_hw_op; > +} > + > +static TypeInfo ipmi_interface_type_info = { > + .name = TYPE_IPMI_INTERFACE, > + .parent = TYPE_INTERFACE, > + .class_size = sizeof(IPMIInterfaceClass), > + .class_init = ipmi_interface_class_init, > +}; > + > +static void isa_ipmi_bmc_check(Object *obj, const char *name, > + Object *val, Error **errp) > +{ > + IPMIBmc *bmc = IPMI_BMC(val); > + > + if (bmc->intf) > + error_setg(errp, "BMC object is already in use"); > +} > + > +void ipmi_bmc_find_and_link(Object *obj, Object **bmc) > +{ > + object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc, > + isa_ipmi_bmc_check, > + OBJ_PROP_LINK_UNREF_ON_RELEASE, > + &error_abort); > +} > + > +static Property ipmi_bmc_properties[] = { > + DEFINE_PROP_UINT8("slave_addr", IPMIBmc, slave_addr, 0x20), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void bmc_class_init(ObjectClass *oc, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(oc); > + > + dc->props = ipmi_bmc_properties; > +} > + > +static TypeInfo ipmi_bmc_type_info = { > + .name = TYPE_IPMI_BMC, > + .parent = TYPE_DEVICE, > + .instance_size = sizeof(IPMIBmc), > + .abstract = true, > + .class_size = sizeof(IPMIBmcClass), > + .class_init = bmc_class_init, > +}; > + > +static void ipmi_register_types(void) > +{ > + type_register_static(&ipmi_interface_type_info); > + type_register_static(&ipmi_bmc_type_info); > +} > + > +type_init(ipmi_register_types) > diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h > new file mode 100644 > index 0000000..e4f7738 > --- /dev/null > +++ b/include/hw/ipmi/ipmi.h > @@ -0,0 +1,178 @@ > +/* > + * IPMI base class > + * > + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC > + * > + * Permission is hereby granted, free of charge, to any person obtaining > a copy > + * of this software and associated documentation files (the "Software"), > to deal > + * in the Software without restriction, including without limitation the > rights > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or > sell > + * copies of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be > included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR > OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > IN > + * THE SOFTWARE. > + */ > + > +#ifndef HW_IPMI_H > +#define HW_IPMI_H > + > +#include "exec/memory.h" > +#include "qemu-common.h" > +#include "hw/qdev.h" > + > +#define MAX_IPMI_MSG_SIZE 300 > + > +enum ipmi_op { > + IPMI_RESET_CHASSIS, > + IPMI_POWEROFF_CHASSIS, > + IPMI_POWERON_CHASSIS, > + IPMI_POWERCYCLE_CHASSIS, > + IPMI_PULSE_DIAG_IRQ, > + IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, > + IPMI_SEND_NMI > +}; > + > +#define IPMI_CC_INVALID_CMD 0xc1 > +#define IPMI_CC_COMMAND_INVALID_FOR_LUN 0xc2 > +#define IPMI_CC_TIMEOUT 0xc3 > +#define IPMI_CC_OUT_OF_SPACE 0xc4 > +#define IPMI_CC_INVALID_RESERVATION 0xc5 > +#define IPMI_CC_REQUEST_DATA_TRUNCATED 0xc6 > +#define IPMI_CC_REQUEST_DATA_LENGTH_INVALID 0xc7 > +#define IPMI_CC_PARM_OUT_OF_RANGE 0xc9 > +#define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES 0xca > +#define IPMI_CC_REQ_ENTRY_NOT_PRESENT 0xcb > +#define IPMI_CC_INVALID_DATA_FIELD 0xcc > +#define IPMI_CC_BMC_INIT_IN_PROGRESS 0xd2 > +#define IPMI_CC_COMMAND_NOT_SUPPORTED 0xd5 > + > +#define IPMI_NETFN_APP 0x06 > + > +#define IPMI_DEBUG 1 > + > +/* Specified in the SMBIOS spec. */ > +#define IPMI_SMBIOS_KCS 0x01 > +#define IPMI_SMBIOS_SMIC 0x02 > +#define IPMI_SMBIOS_BT 0x03 > +#define IPMI_SMBIOS_SSIF 0x04 > + > +/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */ > +#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-" > + > +/* > + * An IPMI Interface, the interface for talking between the target > + * and the BMC. > + */ > +#define TYPE_IPMI_INTERFACE "ipmi-interface" > +#define IPMI_INTERFACE(obj) \ > + INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE) > +#define IPMI_INTERFACE_CLASS(class) \ > + OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE) > +#define IPMI_INTERFACE_GET_CLASS(class) \ > + OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE) > + > +typedef struct IPMIInterface { > + Object parent; > +} IPMIInterface; > + > +typedef struct IPMIInterfaceClass { > + InterfaceClass parent; > + > + void (*init)(struct IPMIInterface *s, Error **errp); > + > + /* > + * Perform various operations on the hardware. If checkonly is > + * true, it will return if the operation can be performed, but it > + * will not do the operation. > + */ > + int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int > checkonly); > + > + /* > + * Enable/disable irqs on the interface when the BMC requests this. > + */ > + void (*set_irq_enable)(struct IPMIInterface *s, int val); > + > + /* > + * Handle an event that occurred on the interface, generally the. > + * target writing to a register. > + */ > + void (*handle_if_event)(struct IPMIInterface *s); > + > + /* > + * The interfaces use this to perform certain ops > + */ > + void (*set_atn)(struct IPMIInterface *s, int val, int irq); > + > + /* > + * Got an IPMI warm/cold reset. > + */ > + void (*reset)(struct IPMIInterface *s, bool is_cold); > + > + /* > + * Handle a response from the bmc. > + */ > + void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id, > + unsigned char *rsp, unsigned int rsp_len); > + > + /* > + * Set by the owner to hold the backend data for the interface. > + */ > + void *(*get_backend_data)(struct IPMIInterface *s); > +} IPMIInterfaceClass; > + > +/* > + * Define a BMC simulator (or perhaps a connection to a real BMC) > + */ > +#define TYPE_IPMI_BMC "ipmi-bmc" > +#define IPMI_BMC(obj) \ > + OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC) > +#define IPMI_BMC_CLASS(obj_class) \ > + OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC) > +#define IPMI_BMC_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC) > + > +typedef struct IPMIBmc { > + DeviceState parent; > + > + uint8_t slave_addr; > + > + IPMIInterface *intf; > +} IPMIBmc; > + > +typedef struct IPMIBmcClass { > + DeviceClass parent; > + > + /* Called when the system resets to report to the bmc. */ > + void (*handle_reset)(struct IPMIBmc *s); > + > + /* > + * Handle a command to the bmc. > + */ > + void (*handle_command)(struct IPMIBmc *s, > + uint8_t *cmd, unsigned int cmd_len, > + unsigned int max_cmd_len, > + uint8_t msg_id); > +} IPMIBmcClass; > + > +/* > + * Add a link property to obj that points to a BMC. > + */ > +void ipmi_bmc_find_and_link(Object *obj, Object **bmc); > + > +#ifdef IPMI_DEBUG > +#define ipmi_debug(fs, ...) \ > + fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__) > +#else > +#define ipmi_debug(fs, ...) > +#endif > + > +#endif > diff --git a/qemu-doc.texi b/qemu-doc.texi > index 460ab71..3c82d30 100644 > --- a/qemu-doc.texi > +++ b/qemu-doc.texi > @@ -195,6 +195,8 @@ PCI and ISA network adapters > @item > Serial ports > @item > +IPMI BMC, either and internal or external one > +@item > Creative SoundBlaster 16 sound card > @item > ENSONIQ AudioPCI ES1370 sound card > -- > 1.8.3.1 > >
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 43c96d1..8fa751a 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y CONFIG_VMWARE_VGA=y CONFIG_VIRTIO_VGA=y CONFIG_VMMOUSE=y +CONFIG_IPMI=y CONFIG_SERIAL=y CONFIG_PARALLEL=y CONFIG_I8254=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index dfb8095..6767f4f 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -9,6 +9,7 @@ CONFIG_VGA_CIRRUS=y CONFIG_VMWARE_VGA=y CONFIG_VIRTIO_VGA=y CONFIG_VMMOUSE=y +CONFIG_IPMI=y CONFIG_SERIAL=y CONFIG_PARALLEL=y CONFIG_I8254=y diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 7e7c241..4a07ed4 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -13,6 +13,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += ide/ devices-dirs-$(CONFIG_SOFTMMU) += input/ devices-dirs-$(CONFIG_SOFTMMU) += intc/ devices-dirs-$(CONFIG_IPACK) += ipack/ +devices-dirs-$(CONFIG_IPMI) += ipmi/ devices-dirs-$(CONFIG_SOFTMMU) += isa/ devices-dirs-$(CONFIG_SOFTMMU) += misc/ devices-dirs-$(CONFIG_SOFTMMU) += net/ diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs new file mode 100644 index 0000000..65bde11 --- /dev/null +++ b/hw/ipmi/Makefile.objs @@ -0,0 +1 @@ +common-obj-$(CONFIG_IPMI) += ipmi.o diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c new file mode 100644 index 0000000..7d17469 --- /dev/null +++ b/hw/ipmi/ipmi.c @@ -0,0 +1,125 @@ +/* + * QEMU IPMI emulation + * + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/hw.h" +#include "hw/ipmi/ipmi.h" +#include "sysemu/sysemu.h" +#include "qmp-commands.h" +#include "qom/object_interfaces.h" +#include "qapi/visitor.h" + +static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly) +{ + switch (op) { + case IPMI_RESET_CHASSIS: + if (checkonly) { + return 0; + } + qemu_system_reset_request(); + return 0; + + case IPMI_POWEROFF_CHASSIS: + if (checkonly) { + return 0; + } + qemu_system_powerdown_request(); + return 0; + + case IPMI_SEND_NMI: + if (checkonly) { + return 0; + } + qemu_mutex_lock_iothread(); + qmp_inject_nmi(NULL); + qemu_mutex_unlock_iothread(); + return 0; + + case IPMI_POWERCYCLE_CHASSIS: + case IPMI_PULSE_DIAG_IRQ: + case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP: + case IPMI_POWERON_CHASSIS: + default: + return IPMI_CC_COMMAND_NOT_SUPPORTED; + } +} + +static void ipmi_interface_class_init(ObjectClass *class, void *data) +{ + IPMIInterfaceClass *ik = IPMI_INTERFACE_CLASS(class); + + ik->do_hw_op = ipmi_do_hw_op; +} + +static TypeInfo ipmi_interface_type_info = { + .name = TYPE_IPMI_INTERFACE, + .parent = TYPE_INTERFACE, + .class_size = sizeof(IPMIInterfaceClass), + .class_init = ipmi_interface_class_init, +}; + +static void isa_ipmi_bmc_check(Object *obj, const char *name, + Object *val, Error **errp) +{ + IPMIBmc *bmc = IPMI_BMC(val); + + if (bmc->intf) + error_setg(errp, "BMC object is already in use"); +} + +void ipmi_bmc_find_and_link(Object *obj, Object **bmc) +{ + object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc, + isa_ipmi_bmc_check, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &error_abort); +} + +static Property ipmi_bmc_properties[] = { + DEFINE_PROP_UINT8("slave_addr", IPMIBmc, slave_addr, 0x20), + DEFINE_PROP_END_OF_LIST(), +}; + +static void bmc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->props = ipmi_bmc_properties; +} + +static TypeInfo ipmi_bmc_type_info = { + .name = TYPE_IPMI_BMC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(IPMIBmc), + .abstract = true, + .class_size = sizeof(IPMIBmcClass), + .class_init = bmc_class_init, +}; + +static void ipmi_register_types(void) +{ + type_register_static(&ipmi_interface_type_info); + type_register_static(&ipmi_bmc_type_info); +} + +type_init(ipmi_register_types) diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h new file mode 100644 index 0000000..e4f7738 --- /dev/null +++ b/include/hw/ipmi/ipmi.h @@ -0,0 +1,178 @@ +/* + * IPMI base class + * + * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_IPMI_H +#define HW_IPMI_H + +#include "exec/memory.h" +#include "qemu-common.h" +#include "hw/qdev.h" + +#define MAX_IPMI_MSG_SIZE 300 + +enum ipmi_op { + IPMI_RESET_CHASSIS, + IPMI_POWEROFF_CHASSIS, + IPMI_POWERON_CHASSIS, + IPMI_POWERCYCLE_CHASSIS, + IPMI_PULSE_DIAG_IRQ, + IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, + IPMI_SEND_NMI +}; + +#define IPMI_CC_INVALID_CMD 0xc1 +#define IPMI_CC_COMMAND_INVALID_FOR_LUN 0xc2 +#define IPMI_CC_TIMEOUT 0xc3 +#define IPMI_CC_OUT_OF_SPACE 0xc4 +#define IPMI_CC_INVALID_RESERVATION 0xc5 +#define IPMI_CC_REQUEST_DATA_TRUNCATED 0xc6 +#define IPMI_CC_REQUEST_DATA_LENGTH_INVALID 0xc7 +#define IPMI_CC_PARM_OUT_OF_RANGE 0xc9 +#define IPMI_CC_CANNOT_RETURN_REQ_NUM_BYTES 0xca +#define IPMI_CC_REQ_ENTRY_NOT_PRESENT 0xcb +#define IPMI_CC_INVALID_DATA_FIELD 0xcc +#define IPMI_CC_BMC_INIT_IN_PROGRESS 0xd2 +#define IPMI_CC_COMMAND_NOT_SUPPORTED 0xd5 + +#define IPMI_NETFN_APP 0x06 + +#define IPMI_DEBUG 1 + +/* Specified in the SMBIOS spec. */ +#define IPMI_SMBIOS_KCS 0x01 +#define IPMI_SMBIOS_SMIC 0x02 +#define IPMI_SMBIOS_BT 0x03 +#define IPMI_SMBIOS_SSIF 0x04 + +/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */ +#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-" + +/* + * An IPMI Interface, the interface for talking between the target + * and the BMC. + */ +#define TYPE_IPMI_INTERFACE "ipmi-interface" +#define IPMI_INTERFACE(obj) \ + INTERFACE_CHECK(IPMIInterface, (obj), TYPE_IPMI_INTERFACE) +#define IPMI_INTERFACE_CLASS(class) \ + OBJECT_CLASS_CHECK(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE) +#define IPMI_INTERFACE_GET_CLASS(class) \ + OBJECT_GET_CLASS(IPMIInterfaceClass, (class), TYPE_IPMI_INTERFACE) + +typedef struct IPMIInterface { + Object parent; +} IPMIInterface; + +typedef struct IPMIInterfaceClass { + InterfaceClass parent; + + void (*init)(struct IPMIInterface *s, Error **errp); + + /* + * Perform various operations on the hardware. If checkonly is + * true, it will return if the operation can be performed, but it + * will not do the operation. + */ + int (*do_hw_op)(struct IPMIInterface *s, enum ipmi_op op, int checkonly); + + /* + * Enable/disable irqs on the interface when the BMC requests this. + */ + void (*set_irq_enable)(struct IPMIInterface *s, int val); + + /* + * Handle an event that occurred on the interface, generally the. + * target writing to a register. + */ + void (*handle_if_event)(struct IPMIInterface *s); + + /* + * The interfaces use this to perform certain ops + */ + void (*set_atn)(struct IPMIInterface *s, int val, int irq); + + /* + * Got an IPMI warm/cold reset. + */ + void (*reset)(struct IPMIInterface *s, bool is_cold); + + /* + * Handle a response from the bmc. + */ + void (*handle_rsp)(struct IPMIInterface *s, uint8_t msg_id, + unsigned char *rsp, unsigned int rsp_len); + + /* + * Set by the owner to hold the backend data for the interface. + */ + void *(*get_backend_data)(struct IPMIInterface *s); +} IPMIInterfaceClass; + +/* + * Define a BMC simulator (or perhaps a connection to a real BMC) + */ +#define TYPE_IPMI_BMC "ipmi-bmc" +#define IPMI_BMC(obj) \ + OBJECT_CHECK(IPMIBmc, (obj), TYPE_IPMI_BMC) +#define IPMI_BMC_CLASS(obj_class) \ + OBJECT_CLASS_CHECK(IPMIBmcClass, (obj_class), TYPE_IPMI_BMC) +#define IPMI_BMC_GET_CLASS(obj) \ + OBJECT_GET_CLASS(IPMIBmcClass, (obj), TYPE_IPMI_BMC) + +typedef struct IPMIBmc { + DeviceState parent; + + uint8_t slave_addr; + + IPMIInterface *intf; +} IPMIBmc; + +typedef struct IPMIBmcClass { + DeviceClass parent; + + /* Called when the system resets to report to the bmc. */ + void (*handle_reset)(struct IPMIBmc *s); + + /* + * Handle a command to the bmc. + */ + void (*handle_command)(struct IPMIBmc *s, + uint8_t *cmd, unsigned int cmd_len, + unsigned int max_cmd_len, + uint8_t msg_id); +} IPMIBmcClass; + +/* + * Add a link property to obj that points to a BMC. + */ +void ipmi_bmc_find_and_link(Object *obj, Object **bmc); + +#ifdef IPMI_DEBUG +#define ipmi_debug(fs, ...) \ + fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__) +#else +#define ipmi_debug(fs, ...) +#endif + +#endif diff --git a/qemu-doc.texi b/qemu-doc.texi index 460ab71..3c82d30 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -195,6 +195,8 @@ PCI and ISA network adapters @item Serial ports @item +IPMI BMC, either and internal or external one +@item Creative SoundBlaster 16 sound card @item ENSONIQ AudioPCI ES1370 sound card