virDomainDeviceInfoFormat(virBufferPtr buf,
                          virDomainDeviceInfoPtr info,
                          unsigned int flags)
{
    g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
    g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);

    if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
        virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);

        if (info->loadparm)
            virBufferAsprintf(buf, " loadparm='%s'", info->loadparm);

        virBufferAddLit(buf, "/>\n");
    }

    if (info->alias)
        virBufferAsprintf(buf, "<alias name='%s'/>\n", info->alias);

    if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
        virBufferAsprintf(buf, "<master startport='%d'/>\n",
                          info->master.usb.startport);
    }

    if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM) &&
        (info->romenabled != VIR_TRISTATE_BOOL_ABSENT ||
         info->rombar != VIR_TRISTATE_SWITCH_ABSENT ||
         info->romfile)) {

        virBufferAddLit(buf, "<rom");
        if (info->romenabled != VIR_TRISTATE_BOOL_ABSENT) {
            const char *romenabled = virTristateBoolTypeToString(info->romenabled);

            if (romenabled)
                virBufferAsprintf(buf, " enabled='%s'", romenabled);
        }
        if (info->rombar != VIR_TRISTATE_SWITCH_ABSENT) {
            const char *rombar = virTristateSwitchTypeToString(info->rombar);

            if (rombar)
                virBufferAsprintf(buf, " bar='%s'", rombar);
        }
        if (info->romfile)
            virBufferEscapeString(buf, " file='%s'", info->romfile);
        virBufferAddLit(buf, "/>\n");
    }

    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
        info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390)
        /* We're done here */
        return 0;

    virBufferAsprintf(&attrBuf, " type='%s'",
                      virDomainDeviceAddressTypeToString(info->type));

    switch ((virDomainDeviceAddressType) info->type) {
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
        if (!virPCIDeviceAddressIsEmpty(&info->addr.pci)) {
            virBufferAsprintf(&attrBuf, " domain='0x%04x' bus='0x%02x' "
                              "slot='0x%02x' function='0x%d'",
                              info->addr.pci.domain,
                              info->addr.pci.bus,
                              info->addr.pci.slot,
                              info->addr.pci.function);
        }
        if (info->addr.pci.multi) {
            virBufferAsprintf(&attrBuf, " multifunction='%s'",
                              virTristateSwitchTypeToString(info->addr.pci.multi));
        }

        if (!virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci)) {
            virBufferAsprintf(&childBuf,
                              "<zpci uid='0x%.4x' fid='0x%.8x'/>\n",
                              info->addr.pci.zpci.uid,
                              info->addr.pci.zpci.fid);
        }
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
        virBufferAsprintf(&attrBuf, " controller='%d' bus='%d' target='%d' unit='%d'",
                          info->addr.drive.controller,
                          info->addr.drive.bus,
                          info->addr.drive.target,
                          info->addr.drive.unit);
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
        virBufferAsprintf(&attrBuf, " controller='%d' bus='%d' port='%d'",
                          info->addr.vioserial.controller,
                          info->addr.vioserial.bus,
                          info->addr.vioserial.port);
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
        virBufferAsprintf(&attrBuf, " controller='%d' slot='%d'",
                          info->addr.ccid.controller,
                          info->addr.ccid.slot);
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
        virBufferAsprintf(&attrBuf, " bus='%d'", info->addr.usb.bus);
        if (virDomainUSBAddressPortIsValid(info->addr.usb.port)) {
            virBufferAddLit(&attrBuf, " port='");
            virDomainUSBAddressPortFormatBuf(&attrBuf, info->addr.usb.port);
            virBufferAddLit(&attrBuf, "'");
        }
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
        if (info->addr.spaprvio.has_reg)
            virBufferAsprintf(&attrBuf, " reg='0x%08llx'", info->addr.spaprvio.reg);
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
        virBufferAsprintf(&attrBuf, " cssid='0x%x' ssid='0x%x' devno='0x%04x'",
                          info->addr.ccw.cssid,
                          info->addr.ccw.ssid,
                          info->addr.ccw.devno);
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
        if (info->addr.isa.iobase > 0)
            virBufferAsprintf(&attrBuf, " iobase='0x%x'", info->addr.isa.iobase);
        if (info->addr.isa.irq > 0)
            virBufferAsprintf(&attrBuf, " irq='0x%x'", info->addr.isa.irq);
        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
        virBufferAsprintf(&attrBuf, " slot='%u'", info->addr.dimm.slot);
        if (info->addr.dimm.base)
            virBufferAsprintf(&attrBuf, " base='0x%llx'", info->addr.dimm.base);

        break;

    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
    case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
        break;
    }

    virXMLFormatElement(buf, "address", &attrBuf, &childBuf);

    return 0;
}