xref: /openbmc/qemu/hw/ipmi/ipmi.c (revision 23076bb34b049f5908fefae19266d3f25f55fd3e)
1*23076bb3SCorey Minyard /*
2*23076bb3SCorey Minyard  * QEMU IPMI emulation
3*23076bb3SCorey Minyard  *
4*23076bb3SCorey Minyard  * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
5*23076bb3SCorey Minyard  *
6*23076bb3SCorey Minyard  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*23076bb3SCorey Minyard  * of this software and associated documentation files (the "Software"), to deal
8*23076bb3SCorey Minyard  * in the Software without restriction, including without limitation the rights
9*23076bb3SCorey Minyard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*23076bb3SCorey Minyard  * copies of the Software, and to permit persons to whom the Software is
11*23076bb3SCorey Minyard  * furnished to do so, subject to the following conditions:
12*23076bb3SCorey Minyard  *
13*23076bb3SCorey Minyard  * The above copyright notice and this permission notice shall be included in
14*23076bb3SCorey Minyard  * all copies or substantial portions of the Software.
15*23076bb3SCorey Minyard  *
16*23076bb3SCorey Minyard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*23076bb3SCorey Minyard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*23076bb3SCorey Minyard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*23076bb3SCorey Minyard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*23076bb3SCorey Minyard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*23076bb3SCorey Minyard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22*23076bb3SCorey Minyard  * THE SOFTWARE.
23*23076bb3SCorey Minyard  */
24*23076bb3SCorey Minyard 
25*23076bb3SCorey Minyard #include "hw/hw.h"
26*23076bb3SCorey Minyard #include "hw/ipmi/ipmi.h"
27*23076bb3SCorey Minyard #include "sysemu/sysemu.h"
28*23076bb3SCorey Minyard #include "qmp-commands.h"
29*23076bb3SCorey Minyard #include "qom/object_interfaces.h"
30*23076bb3SCorey Minyard #include "qapi/visitor.h"
31*23076bb3SCorey Minyard 
32*23076bb3SCorey Minyard static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
33*23076bb3SCorey Minyard {
34*23076bb3SCorey Minyard     switch (op) {
35*23076bb3SCorey Minyard     case IPMI_RESET_CHASSIS:
36*23076bb3SCorey Minyard         if (checkonly) {
37*23076bb3SCorey Minyard             return 0;
38*23076bb3SCorey Minyard         }
39*23076bb3SCorey Minyard         qemu_system_reset_request();
40*23076bb3SCorey Minyard         return 0;
41*23076bb3SCorey Minyard 
42*23076bb3SCorey Minyard     case IPMI_POWEROFF_CHASSIS:
43*23076bb3SCorey Minyard         if (checkonly) {
44*23076bb3SCorey Minyard             return 0;
45*23076bb3SCorey Minyard         }
46*23076bb3SCorey Minyard         qemu_system_powerdown_request();
47*23076bb3SCorey Minyard         return 0;
48*23076bb3SCorey Minyard 
49*23076bb3SCorey Minyard     case IPMI_SEND_NMI:
50*23076bb3SCorey Minyard         if (checkonly) {
51*23076bb3SCorey Minyard             return 0;
52*23076bb3SCorey Minyard         }
53*23076bb3SCorey Minyard         qemu_mutex_lock_iothread();
54*23076bb3SCorey Minyard         qmp_inject_nmi(NULL);
55*23076bb3SCorey Minyard         qemu_mutex_unlock_iothread();
56*23076bb3SCorey Minyard         return 0;
57*23076bb3SCorey Minyard 
58*23076bb3SCorey Minyard     case IPMI_POWERCYCLE_CHASSIS:
59*23076bb3SCorey Minyard     case IPMI_PULSE_DIAG_IRQ:
60*23076bb3SCorey Minyard     case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
61*23076bb3SCorey Minyard     case IPMI_POWERON_CHASSIS:
62*23076bb3SCorey Minyard     default:
63*23076bb3SCorey Minyard         return IPMI_CC_COMMAND_NOT_SUPPORTED;
64*23076bb3SCorey Minyard     }
65*23076bb3SCorey Minyard }
66*23076bb3SCorey Minyard 
67*23076bb3SCorey Minyard static void ipmi_interface_class_init(ObjectClass *class, void *data)
68*23076bb3SCorey Minyard {
69*23076bb3SCorey Minyard     IPMIInterfaceClass *ik = IPMI_INTERFACE_CLASS(class);
70*23076bb3SCorey Minyard 
71*23076bb3SCorey Minyard     ik->do_hw_op = ipmi_do_hw_op;
72*23076bb3SCorey Minyard }
73*23076bb3SCorey Minyard 
74*23076bb3SCorey Minyard static TypeInfo ipmi_interface_type_info = {
75*23076bb3SCorey Minyard     .name = TYPE_IPMI_INTERFACE,
76*23076bb3SCorey Minyard     .parent = TYPE_INTERFACE,
77*23076bb3SCorey Minyard     .class_size = sizeof(IPMIInterfaceClass),
78*23076bb3SCorey Minyard     .class_init = ipmi_interface_class_init,
79*23076bb3SCorey Minyard };
80*23076bb3SCorey Minyard 
81*23076bb3SCorey Minyard static void isa_ipmi_bmc_check(Object *obj, const char *name,
82*23076bb3SCorey Minyard                                Object *val, Error **errp)
83*23076bb3SCorey Minyard {
84*23076bb3SCorey Minyard     IPMIBmc *bmc = IPMI_BMC(val);
85*23076bb3SCorey Minyard 
86*23076bb3SCorey Minyard     if (bmc->intf)
87*23076bb3SCorey Minyard         error_setg(errp, "BMC object is already in use");
88*23076bb3SCorey Minyard }
89*23076bb3SCorey Minyard 
90*23076bb3SCorey Minyard void ipmi_bmc_find_and_link(Object *obj, Object **bmc)
91*23076bb3SCorey Minyard {
92*23076bb3SCorey Minyard     object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc,
93*23076bb3SCorey Minyard                              isa_ipmi_bmc_check,
94*23076bb3SCorey Minyard                              OBJ_PROP_LINK_UNREF_ON_RELEASE,
95*23076bb3SCorey Minyard                              &error_abort);
96*23076bb3SCorey Minyard }
97*23076bb3SCorey Minyard 
98*23076bb3SCorey Minyard static Property ipmi_bmc_properties[] = {
99*23076bb3SCorey Minyard     DEFINE_PROP_UINT8("slave_addr",  IPMIBmc, slave_addr, 0x20),
100*23076bb3SCorey Minyard     DEFINE_PROP_END_OF_LIST(),
101*23076bb3SCorey Minyard };
102*23076bb3SCorey Minyard 
103*23076bb3SCorey Minyard static void bmc_class_init(ObjectClass *oc, void *data)
104*23076bb3SCorey Minyard {
105*23076bb3SCorey Minyard     DeviceClass *dc = DEVICE_CLASS(oc);
106*23076bb3SCorey Minyard 
107*23076bb3SCorey Minyard     dc->props = ipmi_bmc_properties;
108*23076bb3SCorey Minyard }
109*23076bb3SCorey Minyard 
110*23076bb3SCorey Minyard static TypeInfo ipmi_bmc_type_info = {
111*23076bb3SCorey Minyard     .name = TYPE_IPMI_BMC,
112*23076bb3SCorey Minyard     .parent = TYPE_DEVICE,
113*23076bb3SCorey Minyard     .instance_size = sizeof(IPMIBmc),
114*23076bb3SCorey Minyard     .abstract = true,
115*23076bb3SCorey Minyard     .class_size = sizeof(IPMIBmcClass),
116*23076bb3SCorey Minyard     .class_init = bmc_class_init,
117*23076bb3SCorey Minyard };
118*23076bb3SCorey Minyard 
119*23076bb3SCorey Minyard static void ipmi_register_types(void)
120*23076bb3SCorey Minyard {
121*23076bb3SCorey Minyard     type_register_static(&ipmi_interface_type_info);
122*23076bb3SCorey Minyard     type_register_static(&ipmi_bmc_type_info);
123*23076bb3SCorey Minyard }
124*23076bb3SCorey Minyard 
125*23076bb3SCorey Minyard type_init(ipmi_register_types)
126