| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * IPMI BMC external connection | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * This is designed to connect with OpenIPMI's lanserv serial interface | 
					
						
							|  |  |  |  * using the "VM" connection type.  See that for details. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 18:17:30 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
											  
											
												hw/ipmi: Replace fprintf(stderr, "*\n" with error_report()
Replace a large number of the fprintf(stderr, "*\n" calls with
error_report(). The functions were renamed with these commands and then
compiler issues where manually fixed.
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
Some lines where then manually tweaked to pass checkpatch.
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2017-11-08 14:57:27 -08:00
										 |  |  | #include "qemu/error-report.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 16:35:07 +02:00
										 |  |  | #include "qemu/module.h"
 | 
					
						
							| 
									
										
											  
											
												include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef.  Since then, we've moved to include qemu/osdep.h
everywhere.  Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h.  That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h.  Include qapi/error.h in .c files that need it and don't
get it now.  Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly.  Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h.  Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third.  Unfortunately, the number depending on
qapi-types.h shrinks only a little.  More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
											
										 
											2016-03-14 09:01:28 +01:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | #include "qemu/timer.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-26 18:26:44 +04:00
										 |  |  | #include "chardev/char-fe.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | #include "hw/ipmi/ipmi.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:51 +02:00
										 |  |  | #include "hw/qdev-properties.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-11 17:05:12 -05:00
										 |  |  | #include "hw/qdev-properties-system.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:45 +02:00
										 |  |  | #include "migration/vmstate.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | #include "qom/object.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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
 | 
					
						
							| 
									
										
										
										
											2016-10-24 15:10:20 -05:00
										 |  |  | #define   VM_CAPABILITIES_GRACEFUL_SHUTDOWN 0x20
 | 
					
						
							|  |  |  | #define VM_CMD_GRACEFUL_SHUTDOWN   0x09
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define TYPE_IPMI_BMC_EXTERN "ipmi-bmc-extern"
 | 
					
						
							| 
									
										
										
										
											2020-09-16 14:25:19 -04:00
										 |  |  | OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcExtern, IPMI_BMC_EXTERN) | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | struct IPMIBmcExtern { | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     IPMIBmc parent; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-22 12:52:51 +03:00
										 |  |  |     CharBackend chr; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool connected; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unsigned char inbuf[MAX_IPMI_MSG_SIZE + 2]; | 
					
						
							|  |  |  |     unsigned int inpos; | 
					
						
							|  |  |  |     bool in_escape; | 
					
						
							|  |  |  |     bool in_too_many; | 
					
						
							|  |  |  |     bool waiting_rsp; | 
					
						
							|  |  |  |     bool sending_cmd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unsigned char outbuf[(MAX_IPMI_MSG_SIZE + 2) * 2 + 1]; | 
					
						
							|  |  |  |     unsigned int outpos; | 
					
						
							|  |  |  |     unsigned int outlen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct QEMUTimer *extern_timer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* A reset event is pending to be sent upstream. */ | 
					
						
							|  |  |  |     bool send_reset; | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | static unsigned char | 
					
						
							|  |  |  | ipmb_checksum(const unsigned char *data, int size, unsigned char start) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |         unsigned char csum = start; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (; size > 0; size--, data++) { | 
					
						
							|  |  |  |                 csum += *data; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return csum; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void continue_send(IPMIBmcExtern *ibe) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-09-06 14:56:02 +01:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     if (ibe->outlen == 0) { | 
					
						
							|  |  |  |         goto check_reset; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |  send: | 
					
						
							| 
									
										
										
										
											2016-10-22 12:52:55 +03:00
										 |  |  |     ret = qemu_chr_fe_write(&ibe->chr, ibe->outbuf + ibe->outpos, | 
					
						
							| 
									
										
										
										
											2016-09-06 14:56:02 +01:00
										 |  |  |                             ibe->outlen - ibe->outpos); | 
					
						
							|  |  |  |     if (ret > 0) { | 
					
						
							|  |  |  |         ibe->outpos += ret; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     if (ibe->outpos < ibe->outlen) { | 
					
						
							|  |  |  |         /* Not fully transmitted, try again in a 10ms */ | 
					
						
							|  |  |  |         timer_mod_ns(ibe->extern_timer, | 
					
						
							|  |  |  |                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 10000000); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* Sent */ | 
					
						
							|  |  |  |         ibe->outlen = 0; | 
					
						
							|  |  |  |         ibe->outpos = 0; | 
					
						
							|  |  |  |         if (!ibe->sending_cmd) { | 
					
						
							|  |  |  |             ibe->waiting_rsp = true; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ibe->sending_cmd = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     check_reset: | 
					
						
							|  |  |  |         if (ibe->connected && ibe->send_reset) { | 
					
						
							|  |  |  |             /* Send the reset */ | 
					
						
							|  |  |  |             ibe->outbuf[0] = VM_CMD_RESET; | 
					
						
							|  |  |  |             ibe->outbuf[1] = VM_CMD_CHAR; | 
					
						
							|  |  |  |             ibe->outlen = 2; | 
					
						
							|  |  |  |             ibe->outpos = 0; | 
					
						
							|  |  |  |             ibe->send_reset = false; | 
					
						
							|  |  |  |             ibe->sending_cmd = true; | 
					
						
							|  |  |  |             goto send; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ibe->waiting_rsp) { | 
					
						
							|  |  |  |             /* Make sure we get a response within 4 seconds. */ | 
					
						
							|  |  |  |             timer_mod_ns(ibe->extern_timer, | 
					
						
							|  |  |  |                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 4000000000ULL); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void extern_timeout(void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = opaque; | 
					
						
							|  |  |  |     IPMIInterface *s = ibe->parent.intf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ibe->connected) { | 
					
						
							|  |  |  |         if (ibe->waiting_rsp && (ibe->outlen == 0)) { | 
					
						
							|  |  |  |             IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); | 
					
						
							|  |  |  |             /* The message response timed out, return an error. */ | 
					
						
							|  |  |  |             ibe->waiting_rsp = false; | 
					
						
							|  |  |  |             ibe->inbuf[1] = ibe->outbuf[1] | 0x04; | 
					
						
							|  |  |  |             ibe->inbuf[2] = ibe->outbuf[2]; | 
					
						
							|  |  |  |             ibe->inbuf[3] = IPMI_CC_TIMEOUT; | 
					
						
							|  |  |  |             k->handle_rsp(s, ibe->outbuf[0], ibe->inbuf + 1, 3); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             continue_send(ibe); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void addchar(IPMIBmcExtern *ibe, unsigned char ch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (ch) { | 
					
						
							|  |  |  |     case VM_MSG_CHAR: | 
					
						
							|  |  |  |     case VM_CMD_CHAR: | 
					
						
							|  |  |  |     case VM_ESCAPE_CHAR: | 
					
						
							|  |  |  |         ibe->outbuf[ibe->outlen] = VM_ESCAPE_CHAR; | 
					
						
							|  |  |  |         ibe->outlen++; | 
					
						
							|  |  |  |         ch |= 0x10; | 
					
						
							| 
									
										
										
										
											2019-07-19 15:14:22 +02:00
										 |  |  |         /* fall through */ | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     default: | 
					
						
							|  |  |  |         ibe->outbuf[ibe->outlen] = ch; | 
					
						
							|  |  |  |         ibe->outlen++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ipmi_bmc_extern_handle_command(IPMIBmc *b, | 
					
						
							|  |  |  |                                        uint8_t *cmd, unsigned int cmd_len, | 
					
						
							|  |  |  |                                        unsigned int max_cmd_len, | 
					
						
							|  |  |  |                                        uint8_t msg_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(b); | 
					
						
							|  |  |  |     IPMIInterface *s = ibe->parent.intf; | 
					
						
							|  |  |  |     uint8_t err = 0, csum; | 
					
						
							|  |  |  |     unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ibe->outlen) { | 
					
						
							|  |  |  |         /* We already have a command queued.  Shouldn't ever happen. */ | 
					
						
							| 
									
										
											  
											
												hw/ipmi: Replace fprintf(stderr, "*\n" with error_report()
Replace a large number of the fprintf(stderr, "*\n" calls with
error_report(). The functions were renamed with these commands and then
compiler issues where manually fixed.
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
find ./* -type f -exec sed -i \
    'N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
    {} +
Some lines where then manually tweaked to pass checkpatch.
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2017-11-08 14:57:27 -08:00
										 |  |  |         error_report("IPMI KCS: Got command when not finished with the" | 
					
						
							|  |  |  |                      " previous command"); | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |         abort(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If it's too short or it was truncated, return an error. */ | 
					
						
							|  |  |  |     if (cmd_len < 2) { | 
					
						
							|  |  |  |         err = IPMI_CC_REQUEST_DATA_LENGTH_INVALID; | 
					
						
							|  |  |  |     } else if ((cmd_len > max_cmd_len) || (cmd_len > MAX_IPMI_MSG_SIZE)) { | 
					
						
							|  |  |  |         err = IPMI_CC_REQUEST_DATA_TRUNCATED; | 
					
						
							|  |  |  |     } else if (!ibe->connected) { | 
					
						
							|  |  |  |         err = IPMI_CC_BMC_INIT_IN_PROGRESS; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); | 
					
						
							|  |  |  |         unsigned char rsp[3]; | 
					
						
							|  |  |  |         rsp[0] = cmd[0] | 0x04; | 
					
						
							|  |  |  |         rsp[1] = cmd[1]; | 
					
						
							|  |  |  |         rsp[2] = err; | 
					
						
							|  |  |  |         ibe->waiting_rsp = false; | 
					
						
							|  |  |  |         k->handle_rsp(s, msg_id, rsp, 3); | 
					
						
							|  |  |  |         goto out; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addchar(ibe, msg_id); | 
					
						
							|  |  |  |     for (i = 0; i < cmd_len; i++) { | 
					
						
							|  |  |  |         addchar(ibe, cmd[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     csum = ipmb_checksum(&msg_id, 1, 0); | 
					
						
							|  |  |  |     addchar(ibe, -ipmb_checksum(cmd, cmd_len, csum)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ibe->outbuf[ibe->outlen] = VM_MSG_CHAR; | 
					
						
							|  |  |  |     ibe->outlen++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Start the transmit */ | 
					
						
							|  |  |  |     continue_send(ibe); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out: | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_hw_op(IPMIBmcExtern *ibe, unsigned char hw_op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIInterface *s = ibe->parent.intf; | 
					
						
							|  |  |  |     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (hw_op) { | 
					
						
							|  |  |  |     case VM_CMD_VERSION: | 
					
						
							|  |  |  |         /* We only support one version at this time. */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_NOATTN: | 
					
						
							|  |  |  |         k->set_atn(s, 0, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_ATTN: | 
					
						
							|  |  |  |         k->set_atn(s, 1, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_ATTN_IRQ: | 
					
						
							|  |  |  |         k->set_atn(s, 1, 1); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_POWEROFF: | 
					
						
							|  |  |  |         k->do_hw_op(s, IPMI_POWEROFF_CHASSIS, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_RESET: | 
					
						
							|  |  |  |         k->do_hw_op(s, IPMI_RESET_CHASSIS, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_ENABLE_IRQ: | 
					
						
							|  |  |  |         k->set_irq_enable(s, 1); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_DISABLE_IRQ: | 
					
						
							|  |  |  |         k->set_irq_enable(s, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case VM_CMD_SEND_NMI: | 
					
						
							|  |  |  |         k->do_hw_op(s, IPMI_SEND_NMI, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:19 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-24 15:10:20 -05:00
										 |  |  |     case VM_CMD_GRACEFUL_SHUTDOWN: | 
					
						
							|  |  |  |         k->do_hw_op(s, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 0); | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:19 -06:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_msg(IPMIBmcExtern *ibe) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(ibe->parent.intf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ibe->in_escape) { | 
					
						
							|  |  |  |         ipmi_debug("msg escape not ended\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ibe->inpos < 5) { | 
					
						
							|  |  |  |         ipmi_debug("msg too short\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ibe->in_too_many) { | 
					
						
							|  |  |  |         ibe->inbuf[3] = IPMI_CC_REQUEST_DATA_TRUNCATED; | 
					
						
							|  |  |  |         ibe->inpos = 4; | 
					
						
							|  |  |  |     } else if (ipmb_checksum(ibe->inbuf, ibe->inpos, 0) != 0) { | 
					
						
							|  |  |  |         ipmi_debug("msg checksum failure\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2023-07-14 14:32:24 +03:00
										 |  |  |         ibe->inpos--; /* Remove checksum */ | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     timer_del(ibe->extern_timer); | 
					
						
							|  |  |  |     ibe->waiting_rsp = false; | 
					
						
							|  |  |  |     k->handle_rsp(ibe->parent.intf, ibe->inbuf[0], ibe->inbuf + 1, ibe->inpos - 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int can_receive(void *opaque) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void receive(void *opaque, const uint8_t *buf, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = opaque; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     unsigned char hw_op; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < size; i++) { | 
					
						
							|  |  |  |         unsigned char ch = buf[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (ch) { | 
					
						
							|  |  |  |         case VM_MSG_CHAR: | 
					
						
							|  |  |  |             handle_msg(ibe); | 
					
						
							|  |  |  |             ibe->in_too_many = false; | 
					
						
							|  |  |  |             ibe->inpos = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case VM_CMD_CHAR: | 
					
						
							|  |  |  |             if (ibe->in_too_many) { | 
					
						
							|  |  |  |                 ipmi_debug("cmd in too many\n"); | 
					
						
							|  |  |  |                 ibe->in_too_many = false; | 
					
						
							|  |  |  |                 ibe->inpos = 0; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (ibe->in_escape) { | 
					
						
							|  |  |  |                 ipmi_debug("cmd in escape\n"); | 
					
						
							|  |  |  |                 ibe->in_too_many = false; | 
					
						
							|  |  |  |                 ibe->inpos = 0; | 
					
						
							|  |  |  |                 ibe->in_escape = false; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ibe->in_too_many = false; | 
					
						
							|  |  |  |             if (ibe->inpos < 1) { | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             hw_op = ibe->inbuf[0]; | 
					
						
							|  |  |  |             ibe->inpos = 0; | 
					
						
							|  |  |  |             goto out_hw_op; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case VM_ESCAPE_CHAR: | 
					
						
							|  |  |  |             ibe->in_escape = true; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             if (ibe->in_escape) { | 
					
						
							|  |  |  |                 ch &= ~0x10; | 
					
						
							|  |  |  |                 ibe->in_escape = false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (ibe->in_too_many) { | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (ibe->inpos >= sizeof(ibe->inbuf)) { | 
					
						
							|  |  |  |                 ibe->in_too_many = true; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ibe->inbuf[ibe->inpos] = ch; | 
					
						
							|  |  |  |             ibe->inpos++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out_hw_op: | 
					
						
							|  |  |  |     handle_hw_op(ibe, hw_op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												chardev: Use QEMUChrEvent enum in IOEventHandler typedef
The Chardev events are listed in the QEMUChrEvent enum.
By using the enum in the IOEventHandler typedef we:
- make the IOEventHandler type more explicit (this handler
  process out-of-band information, while the IOReadHandler
  is in-band),
- help static code analyzers.
This patch was produced with the following spatch script:
  @match@
  expression backend, opaque, context, set_open;
  identifier fd_can_read, fd_read, fd_event, be_change;
  @@
  qemu_chr_fe_set_handlers(backend, fd_can_read, fd_read, fd_event,
                           be_change, opaque, context, set_open);
  @depends on match@
  identifier opaque, event;
  identifier match.fd_event;
  @@
   static
  -void fd_event(void *opaque, int event)
  +void fd_event(void *opaque, QEMUChrEvent event)
   {
   ...
   }
Then the typedef was modified manually in
include/chardev/char-fe.h.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191218172009.8868-15-philmd@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
											
										 
											2019-12-18 18:20:09 +01:00
										 |  |  | static void chr_event(void *opaque, QEMUChrEvent event) | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = opaque; | 
					
						
							|  |  |  |     IPMIInterface *s = ibe->parent.intf; | 
					
						
							|  |  |  |     IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s); | 
					
						
							|  |  |  |     unsigned char v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (event) { | 
					
						
							|  |  |  |     case CHR_EVENT_OPENED: | 
					
						
							|  |  |  |         ibe->connected = true; | 
					
						
							|  |  |  |         ibe->outpos = 0; | 
					
						
							|  |  |  |         ibe->outlen = 0; | 
					
						
							|  |  |  |         addchar(ibe, VM_CMD_VERSION); | 
					
						
							|  |  |  |         addchar(ibe, VM_PROTOCOL_VERSION); | 
					
						
							|  |  |  |         ibe->outbuf[ibe->outlen] = VM_CMD_CHAR; | 
					
						
							|  |  |  |         ibe->outlen++; | 
					
						
							|  |  |  |         addchar(ibe, VM_CMD_CAPABILITIES); | 
					
						
							|  |  |  |         v = VM_CAPABILITIES_IRQ | VM_CAPABILITIES_ATTN; | 
					
						
							|  |  |  |         if (k->do_hw_op(ibe->parent.intf, IPMI_POWEROFF_CHASSIS, 1) == 0) { | 
					
						
							|  |  |  |             v |= VM_CAPABILITIES_POWER; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-10-24 15:10:20 -05:00
										 |  |  |         if (k->do_hw_op(ibe->parent.intf, IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP, 1) | 
					
						
							|  |  |  |             == 0) { | 
					
						
							|  |  |  |             v |= VM_CAPABILITIES_GRACEFUL_SHUTDOWN; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |         if (k->do_hw_op(ibe->parent.intf, IPMI_RESET_CHASSIS, 1) == 0) { | 
					
						
							|  |  |  |             v |= VM_CAPABILITIES_RESET; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (k->do_hw_op(ibe->parent.intf, IPMI_SEND_NMI, 1) == 0) { | 
					
						
							|  |  |  |             v |= VM_CAPABILITIES_NMI; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         addchar(ibe, v); | 
					
						
							|  |  |  |         ibe->outbuf[ibe->outlen] = VM_CMD_CHAR; | 
					
						
							|  |  |  |         ibe->outlen++; | 
					
						
							|  |  |  |         ibe->sending_cmd = false; | 
					
						
							|  |  |  |         continue_send(ibe); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case CHR_EVENT_CLOSED: | 
					
						
							|  |  |  |         if (!ibe->connected) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ibe->connected = false; | 
					
						
							| 
									
										
										
										
											2017-09-19 15:19:26 -05:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * Don't hang the OS trying to handle the ATN bit, other end will | 
					
						
							|  |  |  |          * resend on a reconnect. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         k->set_atn(s, 0, 0); | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |         if (ibe->waiting_rsp) { | 
					
						
							|  |  |  |             ibe->waiting_rsp = false; | 
					
						
							|  |  |  |             ibe->inbuf[1] = ibe->outbuf[1] | 0x04; | 
					
						
							|  |  |  |             ibe->inbuf[2] = ibe->outbuf[2]; | 
					
						
							|  |  |  |             ibe->inbuf[3] = IPMI_CC_BMC_INIT_IN_PROGRESS; | 
					
						
							|  |  |  |             k->handle_rsp(s, ibe->outbuf[0], ibe->inbuf + 1, 3); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2019-12-18 18:19:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case CHR_EVENT_BREAK: | 
					
						
							|  |  |  |     case CHR_EVENT_MUX_IN: | 
					
						
							|  |  |  |     case CHR_EVENT_MUX_OUT: | 
					
						
							|  |  |  |         /* Ignore */ | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ipmi_bmc_extern_handle_reset(IPMIBmc *b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ibe->send_reset = true; | 
					
						
							|  |  |  |     continue_send(ibe); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:11 -06:00
										 |  |  | static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * We don't directly restore waiting_rsp, Instead, we return an | 
					
						
							|  |  |  |      * error on the interface if a response was being waited for. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (ibe->waiting_rsp) { | 
					
						
							|  |  |  |         IPMIInterface *ii = ibe->parent.intf; | 
					
						
							|  |  |  |         IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ibe->waiting_rsp = false; | 
					
						
							|  |  |  |         ibe->inbuf[1] = ibe->outbuf[1] | 0x04; | 
					
						
							|  |  |  |         ibe->inbuf[2] = ibe->outbuf[2]; | 
					
						
							|  |  |  |         ibe->inbuf[3] = IPMI_CC_BMC_INIT_IN_PROGRESS; | 
					
						
							|  |  |  |         iic->handle_rsp(ii, ibe->outbuf[0], ibe->inbuf + 1, 3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const VMStateDescription vmstate_ipmi_bmc_extern = { | 
					
						
							|  |  |  |     .name = TYPE_IPMI_BMC_EXTERN, | 
					
						
							|  |  |  |     .version_id = 1, | 
					
						
							|  |  |  |     .minimum_version_id = 1, | 
					
						
							|  |  |  |     .post_load = ipmi_bmc_extern_post_migrate, | 
					
						
							| 
									
										
										
										
											2023-12-21 14:16:17 +11:00
										 |  |  |     .fields = (const VMStateField[]) { | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:11 -06:00
										 |  |  |         VMSTATE_BOOL(send_reset, IPMIBmcExtern), | 
					
						
							|  |  |  |         VMSTATE_BOOL(waiting_rsp, IPMIBmcExtern), | 
					
						
							|  |  |  |         VMSTATE_END_OF_LIST() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-20 16:55:54 +02:00
										 |  |  | static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!qemu_chr_fe_backend_connected(&ibe->chr)) { | 
					
						
							|  |  |  |         error_setg(errp, "IPMI external bmc requires chardev attribute"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive, | 
					
						
							|  |  |  |                              chr_event, NULL, ibe, NULL, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vmstate_register(NULL, 0, &vmstate_ipmi_bmc_extern, ibe); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | static void ipmi_bmc_extern_init(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ibe->extern_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, extern_timeout, ibe); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-15 10:58:05 +02:00
										 |  |  | static void ipmi_bmc_extern_finalize(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     timer_free(ibe->extern_timer); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | static Property ipmi_bmc_extern_properties[] = { | 
					
						
							|  |  |  |     DEFINE_PROP_CHR("chardev", IPMIBmcExtern, chr), | 
					
						
							|  |  |  |     DEFINE_PROP_END_OF_LIST(), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ipmi_bmc_extern_class_init(ObjectClass *oc, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DeviceClass *dc = DEVICE_CLASS(oc); | 
					
						
							|  |  |  |     IPMIBmcClass *bk = IPMI_BMC_CLASS(oc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bk->handle_command = ipmi_bmc_extern_handle_command; | 
					
						
							|  |  |  |     bk->handle_reset = ipmi_bmc_extern_handle_reset; | 
					
						
							| 
									
										
										
										
											2016-10-24 15:10:15 -05:00
										 |  |  |     dc->hotpluggable = false; | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     dc->realize = ipmi_bmc_extern_realize; | 
					
						
							| 
									
										
										
										
											2020-01-10 19:30:32 +04:00
										 |  |  |     device_class_set_props(dc, ipmi_bmc_extern_properties); | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TypeInfo ipmi_bmc_extern_type = { | 
					
						
							|  |  |  |     .name          = TYPE_IPMI_BMC_EXTERN, | 
					
						
							|  |  |  |     .parent        = TYPE_IPMI_BMC, | 
					
						
							|  |  |  |     .instance_size = sizeof(IPMIBmcExtern), | 
					
						
							|  |  |  |     .instance_init = ipmi_bmc_extern_init, | 
					
						
							| 
									
										
										
										
											2016-07-15 10:58:05 +02:00
										 |  |  |     .instance_finalize = ipmi_bmc_extern_finalize, | 
					
						
							| 
									
										
										
										
											2015-12-17 12:50:06 -06:00
										 |  |  |     .class_init    = ipmi_bmc_extern_class_init, | 
					
						
							|  |  |  |  }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ipmi_bmc_extern_register_types(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     type_register_static(&ipmi_bmc_extern_type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type_init(ipmi_bmc_extern_register_types) |