2 * IPMI SMBIOS firmware handling
4 * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, LLC
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
11 #include "hw/ipmi/ipmi.h"
12 #include "hw/smbios/ipmi.h"
13 #include "hw/smbios/smbios.h"
14 #include "qemu/error-report.h"
15 #include "smbios_build.h"
17 /* SMBIOS type 38 - IPMI */
18 struct smbios_type_38
{
19 struct smbios_structure_header header
;
20 uint8_t interface_type
;
21 uint8_t ipmi_spec_revision
;
22 uint8_t i2c_slave_address
;
23 uint8_t nv_storage_device_address
;
24 uint64_t base_address
;
25 uint8_t base_address_modifier
;
26 uint8_t interrupt_number
;
29 static void smbios_build_one_type_38(IPMIFwInfo
*info
)
31 uint64_t baseaddr
= info
->base_address
;
32 SMBIOS_BUILD_TABLE_PRE(38, 0x3000, true);
34 t
->interface_type
= info
->interface_type
;
35 t
->ipmi_spec_revision
= ((info
->ipmi_spec_major_revision
<< 4)
36 | info
->ipmi_spec_minor_revision
);
37 t
->i2c_slave_address
= info
->i2c_slave_address
;
38 t
->nv_storage_device_address
= 0;
40 assert(info
->ipmi_spec_minor_revision
<= 15);
41 assert(info
->ipmi_spec_major_revision
<= 15);
43 /* or 1 to set it to I/O space */
44 switch (info
->memspace
) {
45 case IPMI_MEMSPACE_IO
:
48 case IPMI_MEMSPACE_MEM32
:
49 case IPMI_MEMSPACE_MEM64
:
51 case IPMI_MEMSPACE_SMBUS
:
56 t
->base_address
= cpu_to_le64(baseaddr
);
58 t
->base_address_modifier
= 0;
59 if (info
->irq_type
== IPMI_LEVEL_IRQ
) {
60 t
->base_address_modifier
|= 1;
62 switch (info
->register_spacing
) {
66 t
->base_address_modifier
|= 1 << 6;
69 t
->base_address_modifier
|= 2 << 6;
72 error_report("IPMI register spacing %d is not compatible with"
73 " SMBIOS, ignoring this entry.", info
->register_spacing
);
76 t
->interrupt_number
= info
->interrupt_number
;
78 SMBIOS_BUILD_TABLE_POST
;
81 static void smbios_add_ipmi_devices(BusState
*bus
)
85 QTAILQ_FOREACH(kid
, &bus
->children
, sibling
) {
86 DeviceState
*dev
= kid
->child
;
87 Object
*obj
= object_dynamic_cast(OBJECT(dev
), TYPE_IPMI_INTERFACE
);
92 IPMIInterfaceClass
*iic
;
95 ii
= IPMI_INTERFACE(obj
);
96 iic
= IPMI_INTERFACE_GET_CLASS(obj
);
97 memset(&info
, 0, sizeof(info
));
98 iic
->get_fwinfo(ii
, &info
);
99 smbios_build_one_type_38(&info
);
103 QLIST_FOREACH(childbus
, &dev
->child_bus
, sibling
) {
104 smbios_add_ipmi_devices(childbus
);
109 void smbios_build_type_38_table(void)
113 bus
= sysbus_get_default();
115 smbios_add_ipmi_devices(bus
);