2
0

ipmi.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * IPMI ACPI firmware handling
  3. *
  4. * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, LLC
  5. *
  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.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "hw/ipmi/ipmi.h"
  11. #include "hw/acpi/aml-build.h"
  12. #include "hw/acpi/acpi.h"
  13. #include "hw/acpi/ipmi.h"
  14. static Aml *aml_ipmi_crs(IPMIFwInfo *info, const char *resource)
  15. {
  16. Aml *crs = aml_resource_template();
  17. /*
  18. * The base address is fixed and cannot change. That may be different
  19. * if someone does PCI, but we aren't there yet.
  20. */
  21. switch (info->memspace) {
  22. case IPMI_MEMSPACE_IO:
  23. aml_append(crs, aml_io(AML_DECODE16, info->base_address,
  24. info->base_address + info->register_length - 1,
  25. info->register_spacing, info->register_length));
  26. break;
  27. case IPMI_MEMSPACE_MEM32:
  28. aml_append(crs,
  29. aml_dword_memory(AML_POS_DECODE,
  30. AML_MIN_FIXED, AML_MAX_FIXED,
  31. AML_NON_CACHEABLE, AML_READ_WRITE,
  32. 0xffffffff,
  33. info->base_address,
  34. info->base_address + info->register_length - 1,
  35. info->register_spacing, info->register_length));
  36. break;
  37. case IPMI_MEMSPACE_MEM64:
  38. aml_append(crs,
  39. aml_qword_memory(AML_POS_DECODE,
  40. AML_MIN_FIXED, AML_MAX_FIXED,
  41. AML_NON_CACHEABLE, AML_READ_WRITE,
  42. 0xffffffffffffffffULL,
  43. info->base_address,
  44. info->base_address + info->register_length - 1,
  45. info->register_spacing, info->register_length));
  46. break;
  47. case IPMI_MEMSPACE_SMBUS:
  48. aml_append(crs, aml_i2c_serial_bus_device(info->base_address,
  49. resource));
  50. break;
  51. default:
  52. abort();
  53. }
  54. if (info->interrupt_number) {
  55. aml_append(crs, aml_irq_no_flags(info->interrupt_number));
  56. }
  57. return crs;
  58. }
  59. static Aml *aml_ipmi_device(IPMIFwInfo *info, const char *resource)
  60. {
  61. Aml *dev;
  62. uint16_t version = ((info->ipmi_spec_major_revision << 8)
  63. | (info->ipmi_spec_minor_revision << 4));
  64. assert(info->ipmi_spec_minor_revision <= 15);
  65. dev = aml_device("MI%d", info->uuid);
  66. aml_append(dev, aml_name_decl("_HID", aml_eisaid("IPI0001")));
  67. aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s",
  68. info->interface_name)));
  69. aml_append(dev, aml_name_decl("_UID", aml_int(info->uuid)));
  70. aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info, resource)));
  71. aml_append(dev, aml_name_decl("_IFT", aml_int(info->interface_type)));
  72. aml_append(dev, aml_name_decl("_SRV", aml_int(version)));
  73. return dev;
  74. }
  75. void build_acpi_ipmi_devices(Aml *scope, BusState *bus, const char *resource)
  76. {
  77. BusChild *kid;
  78. QTAILQ_FOREACH(kid, &bus->children, sibling) {
  79. IPMIInterface *ii;
  80. IPMIInterfaceClass *iic;
  81. IPMIFwInfo info;
  82. Object *obj = object_dynamic_cast(OBJECT(kid->child),
  83. TYPE_IPMI_INTERFACE);
  84. if (!obj) {
  85. continue;
  86. }
  87. ii = IPMI_INTERFACE(obj);
  88. iic = IPMI_INTERFACE_GET_CLASS(obj);
  89. memset(&info, 0, sizeof(info));
  90. iic->get_fwinfo(ii, &info);
  91. aml_append(scope, aml_ipmi_device(&info, resource));
  92. }
  93. }