cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

smbios_type_38.c (3153B)


      1/*
      2 * IPMI SMBIOS 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
     10#include "qemu/osdep.h"
     11#include "hw/ipmi/ipmi.h"
     12#include "hw/firmware/smbios.h"
     13#include "qemu/error-report.h"
     14#include "smbios_build.h"
     15
     16/* SMBIOS type 38 - IPMI */
     17struct smbios_type_38 {
     18    struct smbios_structure_header header;
     19    uint8_t interface_type;
     20    uint8_t ipmi_spec_revision;
     21    uint8_t i2c_slave_address;
     22    uint8_t nv_storage_device_address;
     23    uint64_t base_address;
     24    uint8_t base_address_modifier;
     25    uint8_t interrupt_number;
     26} QEMU_PACKED;
     27
     28static void smbios_build_one_type_38(IPMIFwInfo *info)
     29{
     30    uint64_t baseaddr = info->base_address;
     31    SMBIOS_BUILD_TABLE_PRE(38, 0x3000, true);
     32
     33    t->interface_type = info->interface_type;
     34    t->ipmi_spec_revision = ((info->ipmi_spec_major_revision << 4)
     35                             | info->ipmi_spec_minor_revision);
     36    t->i2c_slave_address = info->i2c_slave_address;
     37    t->nv_storage_device_address = 0;
     38
     39    assert(info->ipmi_spec_minor_revision <= 15);
     40    assert(info->ipmi_spec_major_revision <= 15);
     41
     42    /* or 1 to set it to I/O space */
     43    switch (info->memspace) {
     44    case IPMI_MEMSPACE_IO:
     45        baseaddr |= 1;
     46        break;
     47    case IPMI_MEMSPACE_MEM32:
     48    case IPMI_MEMSPACE_MEM64:
     49        break;
     50    case IPMI_MEMSPACE_SMBUS:
     51        baseaddr <<= 1;
     52        break;
     53    }
     54
     55    t->base_address = cpu_to_le64(baseaddr);
     56
     57    t->base_address_modifier = 0;
     58    if (info->irq_type == IPMI_LEVEL_IRQ) {
     59        t->base_address_modifier |= 1;
     60    }
     61    switch (info->register_spacing) {
     62    case 1:
     63        break;
     64    case 4:
     65        t->base_address_modifier |= 1 << 6;
     66        break;
     67    case 16:
     68        t->base_address_modifier |= 2 << 6;
     69        break;
     70    default:
     71        error_report("IPMI register spacing %d is not compatible with"
     72                     " SMBIOS, ignoring this entry.", info->register_spacing);
     73        return;
     74    }
     75    t->interrupt_number = info->interrupt_number;
     76
     77    SMBIOS_BUILD_TABLE_POST;
     78}
     79
     80static void smbios_add_ipmi_devices(BusState *bus)
     81{
     82    BusChild *kid;
     83
     84    QTAILQ_FOREACH(kid, &bus->children,  sibling) {
     85        DeviceState *dev = kid->child;
     86        Object *obj = object_dynamic_cast(OBJECT(dev), TYPE_IPMI_INTERFACE);
     87        BusState *childbus;
     88
     89        if (obj) {
     90            IPMIInterface *ii;
     91            IPMIInterfaceClass *iic;
     92            IPMIFwInfo info;
     93
     94            ii = IPMI_INTERFACE(obj);
     95            iic = IPMI_INTERFACE_GET_CLASS(obj);
     96            memset(&info, 0, sizeof(info));
     97            if (!iic->get_fwinfo) {
     98                continue;
     99            }
    100            iic->get_fwinfo(ii, &info);
    101            smbios_build_one_type_38(&info);
    102            continue;
    103        }
    104
    105        QLIST_FOREACH(childbus, &dev->child_bus, sibling) {
    106            smbios_add_ipmi_devices(childbus);
    107        }
    108    }
    109}
    110
    111void smbios_build_type_38_table(void)
    112{
    113    BusState *bus;
    114
    115    bus = sysbus_get_default();
    116    if (bus) {
    117        smbios_add_ipmi_devices(bus);
    118    }
    119}