Files
xen/tools/libs/devicemodel/common.c
T
Roger Pau Monne bbf71e99f0 libs/devicemodel: add dm_op support for FreeBSD
The FreeBSD ioctls have the same fields has the Linux ones, so the
same file can be shared between both OSes.

No functional change for OSes different than FreeBSD.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Wei Liu <wl@xen.org>
2021-01-05 12:33:55 +00:00

139 lines
3.1 KiB
C

/*
* Copyright (c) 2017 Citrix Systems Inc.
*
* 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;
* version 2.1 of the License.
*
* 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 <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <xen/xen.h>
#include <xen/sys/privcmd.h>
#include "private.h"
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
int osdep_xendevicemodel_open(xendevicemodel_handle *dmod)
{
int fd = open("/dev/xen/privcmd", O_RDWR | O_CLOEXEC);
privcmd_dm_op_t uop;
int rc;
if (fd < 0) {
/*
* If the 'new' privcmd interface doesn't exist then don't treat
* this as an error, but an old privcmd clearly won't implement
* IOCTL_PRIVCMD_DM_OP so don't bother trying to open it.
*/
if (errno == ENOENT || errno == ENXIO || errno == ENODEV)
goto out;
PERROR("Could not obtain handle on privileged command interface");
return -1;
}
/*
* Check to see if IOCTL_PRIVCMD_DM_OP is implemented as we want to
* use that in preference to libxencall.
*/
uop.dom = DOMID_INVALID;
uop.num = 0;
uop.ubufs = NULL;
rc = ioctl(fd, IOCTL_PRIVCMD_DM_OP, &uop);
if (rc < 0) {
close(fd);
fd = -1;
}
out:
dmod->fd = fd;
return 0;
}
int osdep_xendevicemodel_close(xendevicemodel_handle *dmod)
{
if (dmod->fd < 0)
return 0;
return close(dmod->fd);
}
int osdep_xendevicemodel_op(xendevicemodel_handle *dmod,
domid_t domid, unsigned int nr_bufs,
struct xendevicemodel_buf bufs[])
{
privcmd_dm_op_buf_t *ubufs;
privcmd_dm_op_t uop;
unsigned int i;
int rc;
if (dmod->fd < 0)
return xendevicemodel_xcall(dmod, domid, nr_bufs, bufs);
ubufs = calloc(nr_bufs, sizeof (*ubufs));
if (!ubufs)
return -1;
for (i = 0; i < nr_bufs; i++) {
ubufs[i].uptr = bufs[i].ptr;
ubufs[i].size = bufs[i].size;
}
uop.dom = domid;
uop.num = nr_bufs;
uop.ubufs = ubufs;
rc = ioctl(dmod->fd, IOCTL_PRIVCMD_DM_OP, &uop);
free(ubufs);
if (rc < 0)
return -1;
return 0;
}
int osdep_xendevicemodel_restrict(xendevicemodel_handle *dmod,
domid_t domid)
{
if (dmod->fd < 0) {
errno = EOPNOTSUPP;
return -1;
}
return ioctl(dmod->fd, IOCTL_PRIVCMD_RESTRICT, &domid);
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/