2 * IPMI ACPI 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/acpi/aml-build.h"
13 #include "hw/acpi/acpi.h"
14 #include "hw/acpi/ipmi.h"
16 static Aml
*aml_ipmi_crs(IPMIFwInfo
*info
)
18 Aml
*crs
= aml_resource_template();
21 * The base address is fixed and cannot change. That may be different
22 * if someone does PCI, but we aren't there yet.
24 switch (info
->memspace
) {
25 case IPMI_MEMSPACE_IO
:
26 aml_append(crs
, aml_io(AML_DECODE16
, info
->base_address
,
27 info
->base_address
+ info
->register_length
- 1,
28 info
->register_spacing
, info
->register_length
));
30 case IPMI_MEMSPACE_MEM32
:
32 aml_dword_memory(AML_POS_DECODE
,
33 AML_MIN_FIXED
, AML_MAX_FIXED
,
34 AML_NON_CACHEABLE
, AML_READ_WRITE
,
37 info
->base_address
+ info
->register_length
- 1,
38 info
->register_spacing
, info
->register_length
));
40 case IPMI_MEMSPACE_MEM64
:
42 aml_qword_memory(AML_POS_DECODE
,
43 AML_MIN_FIXED
, AML_MAX_FIXED
,
44 AML_NON_CACHEABLE
, AML_READ_WRITE
,
45 0xffffffffffffffffULL
,
47 info
->base_address
+ info
->register_length
- 1,
48 info
->register_spacing
, info
->register_length
));
50 case IPMI_MEMSPACE_SMBUS
:
51 aml_append(crs
, aml_return(aml_int(info
->base_address
)));
57 if (info
->interrupt_number
) {
58 aml_append(crs
, aml_irq_no_flags(info
->interrupt_number
));
64 static Aml
*aml_ipmi_device(IPMIFwInfo
*info
)
67 uint16_t version
= ((info
->ipmi_spec_major_revision
<< 8)
68 | (info
->ipmi_spec_minor_revision
<< 4));
70 assert(info
->ipmi_spec_minor_revision
<= 15);
72 dev
= aml_device("MI%d", info
->uuid
);
73 aml_append(dev
, aml_name_decl("_HID", aml_eisaid("IPI0001")));
74 aml_append(dev
, aml_name_decl("_STR", aml_string("ipmi_%s",
75 info
->interface_name
)));
76 aml_append(dev
, aml_name_decl("_UID", aml_int(info
->uuid
)));
77 aml_append(dev
, aml_name_decl("_CRS", aml_ipmi_crs(info
)));
78 aml_append(dev
, aml_name_decl("_IFT", aml_int(info
->interface_type
)));
79 aml_append(dev
, aml_name_decl("_SRV", aml_int(version
)));
84 void build_acpi_ipmi_devices(Aml
*scope
, BusState
*bus
)
89 QTAILQ_FOREACH(kid
, &bus
->children
, sibling
) {
91 IPMIInterfaceClass
*iic
;
93 Object
*obj
= object_dynamic_cast(OBJECT(kid
->child
),
100 ii
= IPMI_INTERFACE(obj
);
101 iic
= IPMI_INTERFACE_GET_CLASS(obj
);
102 memset(&info
, 0, sizeof(info
));
103 iic
->get_fwinfo(ii
, &info
);
104 aml_append(scope
, aml_ipmi_device(&info
));