2014-04-07 05:06:40 +00:00
|
|
|
/*
|
|
|
|
* bhyve_capabilities.c: bhyve capabilities module
|
|
|
|
*
|
|
|
|
* Copyright (C) 2014 Roman Bogorodskiy
|
2014-04-07 15:21:59 +00:00
|
|
|
* Copyright (C) 2014 Semihalf
|
2020-05-06 13:35:54 +00:00
|
|
|
* Copyright (C) 2020 Fabian Freyer
|
2014-04-07 05:06:40 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <sys/utsname.h>
|
2016-07-08 17:51:12 +00:00
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/types.h>
|
2014-04-07 05:06:40 +00:00
|
|
|
|
|
|
|
#include "viralloc.h"
|
2014-11-11 15:35:06 +00:00
|
|
|
#include "virfile.h"
|
2014-04-07 05:06:40 +00:00
|
|
|
#include "virlog.h"
|
|
|
|
#include "virstring.h"
|
|
|
|
#include "cpu/cpu.h"
|
|
|
|
#include "domain_conf.h"
|
|
|
|
#include "vircommand.h"
|
|
|
|
#include "bhyve_capabilities.h"
|
2017-03-11 16:19:03 +00:00
|
|
|
#include "bhyve_conf.h"
|
2014-04-07 05:06:40 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_BHYVE
|
|
|
|
|
|
|
|
VIR_LOG_INIT("bhyve.bhyve_capabilities");
|
|
|
|
|
|
|
|
|
|
|
|
virCapsPtr
|
|
|
|
virBhyveCapsBuild(void)
|
|
|
|
{
|
|
|
|
virCapsPtr caps;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
if ((caps = virCapabilitiesNew(virArchFromHost(),
|
2014-07-14 12:56:13 +00:00
|
|
|
false, false)) == NULL)
|
2014-04-07 05:06:40 +00:00
|
|
|
return NULL;
|
|
|
|
|
2015-04-17 22:09:16 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM,
|
2014-04-07 05:06:40 +00:00
|
|
|
VIR_ARCH_X86_64,
|
|
|
|
"bhyve",
|
|
|
|
NULL, 0, NULL)) == NULL)
|
|
|
|
goto error;
|
|
|
|
|
2015-04-17 22:38:10 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_BHYVE,
|
|
|
|
NULL, NULL, 0, NULL) == NULL)
|
2014-04-07 05:06:40 +00:00
|
|
|
goto error;
|
|
|
|
|
2017-03-15 08:07:38 +00:00
|
|
|
if (!(caps->host.cpu = virCPUProbeHost(caps->host.arch)))
|
|
|
|
VIR_WARN("Failed to get host CPU");
|
2014-04-07 05:06:40 +00:00
|
|
|
|
|
|
|
return caps;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virObjectUnref(caps);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-11-11 15:35:06 +00:00
|
|
|
|
2017-03-18 20:17:13 +00:00
|
|
|
int
|
|
|
|
virBhyveDomainCapsFill(virDomainCapsPtr caps,
|
|
|
|
unsigned int bhyvecaps,
|
|
|
|
virDomainCapsStringValuesPtr firmwares)
|
|
|
|
{
|
2019-02-08 23:03:20 +00:00
|
|
|
caps->disk.supported = VIR_TRISTATE_BOOL_YES;
|
2019-03-06 23:20:09 +00:00
|
|
|
caps->disk.diskDevice.report = true;
|
|
|
|
caps->disk.bus.report = true;
|
|
|
|
caps->disk.model.report = true;
|
2017-03-18 20:17:13 +00:00
|
|
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->disk.diskDevice,
|
|
|
|
VIR_DOMAIN_DISK_DEVICE_DISK,
|
|
|
|
VIR_DOMAIN_DISK_DEVICE_CDROM);
|
|
|
|
|
|
|
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->disk.bus,
|
|
|
|
VIR_DOMAIN_DISK_BUS_SATA,
|
|
|
|
VIR_DOMAIN_DISK_BUS_VIRTIO);
|
|
|
|
|
2019-02-08 23:03:20 +00:00
|
|
|
caps->os.supported = VIR_TRISTATE_BOOL_YES;
|
2017-03-18 20:17:13 +00:00
|
|
|
|
2019-02-19 19:28:52 +00:00
|
|
|
caps->os.loader.supported = VIR_TRISTATE_BOOL_NO;
|
2017-03-18 20:17:13 +00:00
|
|
|
if (bhyvecaps & BHYVE_CAP_LPC_BOOTROM) {
|
2019-03-06 23:20:09 +00:00
|
|
|
caps->os.loader.type.report = true;
|
|
|
|
caps->os.loader.readonly.report = true;
|
2019-02-08 23:03:20 +00:00
|
|
|
caps->os.loader.supported = VIR_TRISTATE_BOOL_YES;
|
2017-03-18 20:17:13 +00:00
|
|
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->os.loader.type,
|
|
|
|
VIR_DOMAIN_LOADER_TYPE_PFLASH);
|
|
|
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->os.loader.readonly,
|
|
|
|
VIR_TRISTATE_BOOL_YES);
|
|
|
|
|
|
|
|
caps->os.loader.values.values = firmwares->values;
|
|
|
|
caps->os.loader.values.nvalues = firmwares->nvalues;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-19 19:28:52 +00:00
|
|
|
caps->graphics.supported = VIR_TRISTATE_BOOL_NO;
|
|
|
|
caps->video.supported = VIR_TRISTATE_BOOL_NO;
|
2017-03-18 20:17:13 +00:00
|
|
|
if (bhyvecaps & BHYVE_CAP_FBUF) {
|
2019-02-08 23:03:20 +00:00
|
|
|
caps->graphics.supported = VIR_TRISTATE_BOOL_YES;
|
2019-03-06 23:20:09 +00:00
|
|
|
caps->graphics.type.report = true;
|
2019-02-08 23:03:20 +00:00
|
|
|
caps->video.supported = VIR_TRISTATE_BOOL_YES;
|
2019-03-06 23:20:09 +00:00
|
|
|
caps->video.modelType.report = true;
|
2017-03-18 20:17:13 +00:00
|
|
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->graphics.type, VIR_DOMAIN_GRAPHICS_TYPE_VNC);
|
|
|
|
VIR_DOMAIN_CAPS_ENUM_SET(caps->video.modelType, VIR_DOMAIN_VIDEO_TYPE_GOP);
|
|
|
|
}
|
2019-02-19 19:28:52 +00:00
|
|
|
|
|
|
|
caps->hostdev.supported = VIR_TRISTATE_BOOL_NO;
|
2019-11-21 08:52:24 +00:00
|
|
|
caps->features[VIR_DOMAIN_CAPS_FEATURE_IOTHREADS] = VIR_TRISTATE_BOOL_NO;
|
|
|
|
caps->features[VIR_DOMAIN_CAPS_FEATURE_VMCOREINFO] = VIR_TRISTATE_BOOL_NO;
|
|
|
|
caps->features[VIR_DOMAIN_CAPS_FEATURE_GENID] = VIR_TRISTATE_BOOL_NO;
|
2019-02-19 19:28:52 +00:00
|
|
|
caps->gic.supported = VIR_TRISTATE_BOOL_NO;
|
|
|
|
|
2017-03-18 20:17:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-08 18:53:33 +00:00
|
|
|
virDomainCapsPtr
|
2017-03-11 16:19:03 +00:00
|
|
|
virBhyveDomainCapsBuild(bhyveConnPtr conn,
|
|
|
|
const char *emulatorbin,
|
2016-07-08 18:53:33 +00:00
|
|
|
const char *machine,
|
|
|
|
virArch arch,
|
|
|
|
virDomainVirtType virttype)
|
|
|
|
{
|
|
|
|
virDomainCapsPtr caps = NULL;
|
2016-07-16 21:03:33 +00:00
|
|
|
unsigned int bhyve_caps = 0;
|
2020-10-25 21:50:51 +00:00
|
|
|
g_autoptr(DIR) dir = NULL;
|
2016-07-08 17:51:12 +00:00
|
|
|
struct dirent *entry;
|
|
|
|
size_t firmwares_alloc = 0;
|
2017-03-11 16:19:03 +00:00
|
|
|
virBhyveDriverConfigPtr cfg = virBhyveDriverGetConfig(conn);
|
|
|
|
const char *firmware_dir = cfg->firmwareDir;
|
2017-03-18 20:17:13 +00:00
|
|
|
virDomainCapsStringValuesPtr firmwares = NULL;
|
2016-07-08 18:53:33 +00:00
|
|
|
|
|
|
|
if (!(caps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-07-16 21:03:33 +00:00
|
|
|
if (virBhyveProbeCaps(&bhyve_caps)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("failed probing capabilities"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2020-09-23 18:43:58 +00:00
|
|
|
firmwares = g_new0(virDomainCapsStringValues, 1);
|
2016-07-08 17:51:12 +00:00
|
|
|
|
|
|
|
if (virDirOpenIfExists(&dir, firmware_dir) > 0) {
|
|
|
|
while ((virDirRead(dir, &entry, firmware_dir)) > 0) {
|
2017-03-18 20:17:13 +00:00
|
|
|
if (VIR_RESIZE_N(firmwares->values,
|
|
|
|
firmwares_alloc, firmwares->nvalues, 1) < 0)
|
2016-07-08 17:51:12 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
firmwares->values[firmwares->nvalues] = g_strdup_printf("%s/%s",
|
|
|
|
firmware_dir, entry->d_name);
|
2017-03-18 20:17:13 +00:00
|
|
|
firmwares->nvalues++;
|
2016-07-08 17:51:12 +00:00
|
|
|
}
|
2017-03-11 16:19:03 +00:00
|
|
|
} else {
|
|
|
|
VIR_WARN("Cannot open firmware directory %s", firmware_dir);
|
2016-07-08 17:51:12 +00:00
|
|
|
}
|
2017-03-11 16:19:03 +00:00
|
|
|
|
2017-03-18 20:17:13 +00:00
|
|
|
if (virBhyveDomainCapsFill(caps, bhyve_caps, firmwares) < 0)
|
|
|
|
goto cleanup;
|
2016-07-08 18:53:33 +00:00
|
|
|
|
|
|
|
cleanup:
|
2017-03-18 20:17:13 +00:00
|
|
|
VIR_FREE(firmwares);
|
2017-03-11 16:19:03 +00:00
|
|
|
virObjectUnref(cfg);
|
2016-07-08 18:53:33 +00:00
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
|
2014-11-11 15:35:06 +00:00
|
|
|
int
|
|
|
|
virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps)
|
|
|
|
{
|
|
|
|
char *binary, *help;
|
|
|
|
virCommandPtr cmd;
|
|
|
|
int ret, exit;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
*caps = 0;
|
|
|
|
cmd = NULL;
|
|
|
|
help = NULL;
|
|
|
|
|
|
|
|
binary = virFindFileInPath("grub-bhyve");
|
|
|
|
if (binary == NULL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
cmd = virCommandNew(binary);
|
|
|
|
virCommandAddArg(cmd, "--help");
|
|
|
|
virCommandSetOutputBuffer(cmd, &help);
|
|
|
|
if (virCommandRun(cmd, &exit) < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strstr(help, "--cons-dev") != NULL)
|
|
|
|
*caps |= BHYVE_GRUB_CAP_CONSDEV;
|
|
|
|
|
|
|
|
out:
|
|
|
|
VIR_FREE(help);
|
|
|
|
virCommandFree(cmd);
|
|
|
|
VIR_FREE(binary);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-07-19 08:20:35 +00:00
|
|
|
|
2017-01-05 12:21:52 +00:00
|
|
|
static int
|
2017-03-19 13:40:52 +00:00
|
|
|
bhyveProbeCapsDeviceHelper(unsigned int *caps,
|
|
|
|
char *binary,
|
|
|
|
const char *bus,
|
|
|
|
const char *device,
|
|
|
|
const char *errormsg,
|
|
|
|
unsigned int flag)
|
2015-07-19 08:20:35 +00:00
|
|
|
{
|
2017-03-19 13:40:52 +00:00
|
|
|
char *error;
|
2015-07-19 08:20:35 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
2017-03-19 13:40:52 +00:00
|
|
|
int ret = -1, exit;
|
2015-07-19 08:20:35 +00:00
|
|
|
|
|
|
|
cmd = virCommandNew(binary);
|
2017-03-19 13:40:52 +00:00
|
|
|
virCommandAddArgList(cmd, bus, device, NULL);
|
|
|
|
virCommandSetErrorBuffer(cmd, &error);
|
|
|
|
if (virCommandRun(cmd, &exit) < 0)
|
|
|
|
goto cleanup;
|
2015-07-19 08:20:35 +00:00
|
|
|
|
2017-03-19 13:40:52 +00:00
|
|
|
if (strstr(error, errormsg) == NULL)
|
|
|
|
*caps |= flag;
|
2015-07-19 08:20:35 +00:00
|
|
|
|
2017-03-19 13:40:52 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(error);
|
2015-07-19 08:20:35 +00:00
|
|
|
virCommandFree(cmd);
|
2017-01-05 12:21:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-06-07 13:20:53 +00:00
|
|
|
bhyveProbeCapsFromHelp(unsigned int *caps, char *binary)
|
2017-01-05 12:21:52 +00:00
|
|
|
{
|
2017-03-19 13:40:52 +00:00
|
|
|
char *help;
|
2017-01-05 12:21:52 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
int ret = 0, exit;
|
|
|
|
|
|
|
|
cmd = virCommandNew(binary);
|
2017-03-19 13:40:52 +00:00
|
|
|
virCommandAddArg(cmd, "-h");
|
|
|
|
virCommandSetErrorBuffer(cmd, &help);
|
2017-01-05 12:21:52 +00:00
|
|
|
if (virCommandRun(cmd, &exit) < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2017-03-19 13:40:52 +00:00
|
|
|
if (strstr(help, "-u:") != NULL)
|
|
|
|
*caps |= BHYVE_CAP_RTC_UTC;
|
2017-01-05 12:21:52 +00:00
|
|
|
|
2018-05-21 14:53:36 +00:00
|
|
|
/* "-c vcpus" was there before CPU topology support was introduced,
|
|
|
|
* then it became
|
|
|
|
* "-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n] */
|
|
|
|
if (strstr(help, "-c vcpus") == NULL)
|
|
|
|
*caps |= BHYVE_CAP_CPUTOPOLOGY;
|
|
|
|
|
2017-01-05 12:21:52 +00:00
|
|
|
out:
|
2017-03-19 13:40:52 +00:00
|
|
|
VIR_FREE(help);
|
2017-01-05 12:21:52 +00:00
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-08-27 12:30:34 +00:00
|
|
|
static int
|
2017-03-19 13:40:52 +00:00
|
|
|
bhyveProbeCapsAHCI32Slot(unsigned int *caps, char *binary)
|
2016-08-27 12:30:34 +00:00
|
|
|
{
|
2017-03-19 13:40:52 +00:00
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,ahci",
|
|
|
|
"pci slot 0:0: unknown device \"ahci\"",
|
|
|
|
BHYVE_CAP_AHCI32SLOT);
|
|
|
|
}
|
2016-08-27 12:30:34 +00:00
|
|
|
|
|
|
|
|
2017-03-19 13:40:52 +00:00
|
|
|
static int
|
|
|
|
bhyveProbeCapsNetE1000(unsigned int *caps, char *binary)
|
|
|
|
{
|
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,e1000",
|
|
|
|
"pci slot 0:0: unknown device \"e1000\"",
|
|
|
|
BHYVE_CAP_NET_E1000);
|
2016-08-27 12:30:34 +00:00
|
|
|
}
|
2017-01-05 12:21:52 +00:00
|
|
|
|
2016-05-24 13:30:56 +00:00
|
|
|
static int
|
|
|
|
bhyveProbeCapsLPC_Bootrom(unsigned int *caps, char *binary)
|
|
|
|
{
|
2017-03-19 13:40:52 +00:00
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-l",
|
|
|
|
"bootrom",
|
|
|
|
"bhyve: invalid lpc device configuration 'bootrom'",
|
|
|
|
BHYVE_CAP_LPC_BOOTROM);
|
2016-05-24 13:30:56 +00:00
|
|
|
}
|
|
|
|
|
2016-07-16 21:03:33 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
bhyveProbeCapsFramebuffer(unsigned int *caps, char *binary)
|
|
|
|
{
|
2017-03-19 13:40:52 +00:00
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,fbuf",
|
|
|
|
"pci slot 0:0: unknown device \"fbuf\"",
|
|
|
|
BHYVE_CAP_FBUF);
|
2016-07-16 21:03:33 +00:00
|
|
|
}
|
|
|
|
|
2017-03-20 13:58:51 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
bhyveProbeCapsXHCIController(unsigned int *caps, char *binary)
|
|
|
|
{
|
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,xhci",
|
|
|
|
"pci slot 0:0: unknown device \"xhci\"",
|
|
|
|
BHYVE_CAP_FBUF);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-14 14:44:13 +00:00
|
|
|
static int
|
|
|
|
bhyveProbeCapsSoundHda(unsigned int *caps, char *binary)
|
|
|
|
{
|
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,hda",
|
|
|
|
"pci slot 0:0: unknown device \"hda\"",
|
|
|
|
BHYVE_CAP_SOUND_HDA);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-06 13:35:54 +00:00
|
|
|
static int
|
|
|
|
bhyveProbeCapsVNCPassword(unsigned int *caps, char *binary)
|
|
|
|
{
|
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,fbuf,password=",
|
|
|
|
"Invalid fbuf emulation \"password\"",
|
|
|
|
BHYVE_CAP_VNC_PASSWORD);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-07 16:07:04 +00:00
|
|
|
static int
|
|
|
|
bhyveProbeCapsVirtio9p(unsigned int *caps, char *binary)
|
|
|
|
{
|
|
|
|
return bhyveProbeCapsDeviceHelper(caps, binary,
|
|
|
|
"-s",
|
|
|
|
"0,virtio-9p",
|
|
|
|
"pci slot 0:0: unknown device \"hda\"",
|
|
|
|
BHYVE_CAP_VIRTIO_9P);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-05 12:21:52 +00:00
|
|
|
int
|
|
|
|
virBhyveProbeCaps(unsigned int *caps)
|
|
|
|
{
|
|
|
|
char *binary;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
binary = virFindFileInPath("bhyve");
|
|
|
|
if (binary == NULL)
|
|
|
|
goto out;
|
|
|
|
|
2018-06-07 13:20:53 +00:00
|
|
|
if ((ret = bhyveProbeCapsFromHelp(caps, binary)))
|
2017-01-05 12:21:52 +00:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
if ((ret = bhyveProbeCapsAHCI32Slot(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2016-08-27 12:30:34 +00:00
|
|
|
if ((ret = bhyveProbeCapsNetE1000(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2016-05-24 13:30:56 +00:00
|
|
|
if ((ret = bhyveProbeCapsLPC_Bootrom(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2016-07-16 21:03:33 +00:00
|
|
|
if ((ret = bhyveProbeCapsFramebuffer(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2017-03-20 13:58:51 +00:00
|
|
|
if ((ret = bhyveProbeCapsXHCIController(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2020-07-14 14:44:13 +00:00
|
|
|
if ((ret = bhyveProbeCapsSoundHda(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2020-05-06 13:35:54 +00:00
|
|
|
if ((ret = bhyveProbeCapsVNCPassword(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2020-10-07 16:07:04 +00:00
|
|
|
if ((ret = bhyveProbeCapsVirtio9p(caps, binary)))
|
|
|
|
goto out;
|
|
|
|
|
2017-01-05 12:21:52 +00:00
|
|
|
out:
|
2015-07-19 08:20:35 +00:00
|
|
|
VIR_FREE(binary);
|
|
|
|
return ret;
|
|
|
|
}
|