Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sbin/mount_qemufwcfg Add virtual filesystem for QEMU Firmwar...



details:   https://anonhg.NetBSD.org/src/rev/79425c2ddc5e
branches:  trunk
changeset: 828060:79425c2ddc5e
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Nov 25 23:23:39 2017 +0000

description:
Add virtual filesystem for QEMU Firmware Configuration interface.

diffstat:

 sbin/mount_qemufwcfg/Makefile  |   12 +
 sbin/mount_qemufwcfg/defs.h    |   88 +++++++++++++
 sbin/mount_qemufwcfg/fwcfg.c   |  259 +++++++++++++++++++++++++++++++++++++++++
 sbin/mount_qemufwcfg/virtdir.c |  226 +++++++++++++++++++++++++++++++++++
 sbin/mount_qemufwcfg/virtdir.h |   81 ++++++++++++
 5 files changed, 666 insertions(+), 0 deletions(-)

diffs (truncated from 686 to 300 lines):

diff -r b807db6c2d87 -r 79425c2ddc5e sbin/mount_qemufwcfg/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sbin/mount_qemufwcfg/Makefile     Sat Nov 25 23:23:39 2017 +0000
@@ -0,0 +1,12 @@
+# $NetBSD: Makefile,v 1.1 2017/11/25 23:23:39 jmcneill Exp $
+
+PROG=  mount_qemufwcfg
+SRCS=  fwcfg.c virtdir.c
+DPADD+=        ${LIBREFUSE}
+LDADD= -lrefuse
+NOMAN= # defined
+WARNS= 3
+
+CPPFLAGS+=     -D_KERNTYPES
+
+.include <bsd.prog.mk>
diff -r b807db6c2d87 -r 79425c2ddc5e sbin/mount_qemufwcfg/defs.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sbin/mount_qemufwcfg/defs.h       Sat Nov 25 23:23:39 2017 +0000
@@ -0,0 +1,88 @@
+/* $NetBSD: defs.h,v 1.1 2017/11/25 23:23:39 jmcneill Exp $ */
+
+/*
+ * Copyright (c) 1999-2005 Alistair Crooks.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DEFS_H_
+#define DEFS_H_
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NEWARRAY(type,ptr,size,where,action) do {                      \
+       if ((ptr = (type *) calloc(sizeof(type), (unsigned)(size))) == NULL) { \
+               (void) fprintf(stderr, "%s: can't allocate %lu bytes\n", \
+                       where, (unsigned long)(size * sizeof(type)));   \
+               action;                                                 \
+       }                                                               \
+} while( /* CONSTCOND */ 0)
+
+#define RENEW(type,ptr,size,where,action) do {                         \
+       type *_newptr;                                                  \
+       if ((_newptr = (type *) realloc(ptr, sizeof(type) * (size))) == NULL) { \
+               (void) fprintf(stderr, "%s: can't realloc %lu bytes\n", \
+                       where, (unsigned long)(size * sizeof(type)));   \
+               action;                                                 \
+       } else {                                                        \
+               ptr = _newptr;                                          \
+       }                                                               \
+} while( /* CONSTCOND */ 0)
+
+#define NEW(type, ptr, where, action)  NEWARRAY(type, ptr, 1, where, action)
+
+#define FREE(ptr)      (void) free(ptr)
+
+#define ALLOC(type, v, size, c, init, incr, where, action) do {                \
+       uint32_t        _newsize = size;                                \
+       if (size == 0) {                                                \
+               _newsize = init;                                        \
+               NEWARRAY(type, v, _newsize, where ": new", action);     \
+       } else if (c == size) {                                         \
+               _newsize = size + incr;                                 \
+               RENEW(type, v, _newsize, where ": renew", action);      \
+       }                                                               \
+       size = _newsize;                                                \
+} while( /* CONSTCOND */ 0)
+
+/*             (void) memset(&v[size], 0x0, sizeof(type) * incr);      \*/
+
+#define DEFINE_ARRAY(name, type)                                       \
+typedef struct name {                                                  \
+       uint32_t        c;                                              \
+       uint32_t        size;                                           \
+       type           *v;                                              \
+} name
+
+#endif /* !DEFS_H_ */
diff -r b807db6c2d87 -r 79425c2ddc5e sbin/mount_qemufwcfg/fwcfg.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sbin/mount_qemufwcfg/fwcfg.c      Sat Nov 25 23:23:39 2017 +0000
@@ -0,0 +1,259 @@
+/* $NetBSD: fwcfg.c,v 1.1 2017/11/25 23:23:39 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: fwcfg.c,v 1.1 2017/11/25 23:23:39 jmcneill Exp $");
+
+#include <sys/ioctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fuse.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dev/ic/qemufwcfgio.h>
+
+#include "virtdir.h"
+
+#define _PATH_FWCFG    "/dev/qemufwcfg"
+
+struct fwcfg_file {
+       uint32_t size;
+       uint16_t select;
+       uint16_t reserved;
+       char name[56];
+};
+
+static int fwcfg_fd;
+static mode_t fwcfg_dir_mask = 0555;
+static mode_t fwcfg_file_mask = 0444;
+static uid_t fwcfg_uid;
+static gid_t fwcfg_gid;
+
+static virtdir_t fwcfg_virtdir;
+
+static void
+set_index(uint16_t index)
+{
+       if (ioctl(fwcfg_fd, FWCFGIO_SET_INDEX, &index) != 0)
+               err(EXIT_FAILURE, "failed to set index 0x%04x", index);
+}
+
+static void
+read_data(void *buf, size_t buflen)
+{
+       if (read(fwcfg_fd, buf, buflen) != (ssize_t)buflen)
+               err(EXIT_FAILURE, "failed to read data");
+}
+
+static int
+fwcfg_getattr(const char *path, struct stat *st)
+{
+       virt_dirent_t *ep;
+
+       if (strcmp(path, "/") == 0) {
+               memset(st, 0, sizeof(*st));
+               st->st_mode = S_IFDIR | fwcfg_dir_mask;
+               st->st_nlink = 2;
+               return 0;
+       }
+
+       if ((ep = virtdir_find(&fwcfg_virtdir, path, strlen(path))) == NULL)
+               return -ENOENT;
+
+       switch (ep->type) {
+       case 'f':
+               memcpy(st, &fwcfg_virtdir.file, sizeof(*st));
+               st->st_size = ep->tgtlen;
+               st->st_mode = S_IFREG | fwcfg_file_mask;
+               break;
+       case 'd':
+               memcpy(st, &fwcfg_virtdir.dir, sizeof(*st));
+               st->st_mode = S_IFDIR | fwcfg_dir_mask;
+               break;
+       }
+       st->st_ino = virtdir_offset(&fwcfg_virtdir, ep) + 10;
+
+       return 0;
+}
+
+static int
+fwcfg_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+    off_t offset, struct fuse_file_info *fi)
+{
+       static VIRTDIR *dirp;
+       virt_dirent_t *dp;
+
+       if (offset == 0) {
+               if ((dirp = openvirtdir(&fwcfg_virtdir, path)) == NULL)
+                       return 0;
+               filler(buf, ".", NULL, 0);
+               filler(buf, "..", NULL, 0);
+       }
+       while ((dp = readvirtdir(dirp)) != NULL) {
+               if (filler(buf, dp->d_name, NULL, 0) != 0)
+                       return 0;
+       }
+       closevirtdir(dirp);
+       dirp = NULL;
+
+       return 0;
+}
+
+static int
+fwcfg_open(const char *path, struct fuse_file_info *fi)
+{
+       return 0;
+}
+
+static int
+fwcfg_read(const char *path, char *buf, size_t size, off_t offset,
+    struct fuse_file_info *fi)
+{
+       virt_dirent_t *ep;
+       uint8_t tmp[64];
+
+       if ((ep = virtdir_find(&fwcfg_virtdir, path, strlen(path))) == NULL)
+               return -ENOENT;
+
+       if (ep->select == 0)
+               return -ENOENT;
+
+       set_index(ep->select);
+
+       /* Seek to correct offset */
+       while (offset > 0) {
+               const int len = MIN(sizeof(tmp), (size_t)offset);
+               read_data(tmp, len);
+               offset -= len;
+       }
+
+       /* Read the data */
+       read_data(buf, size);
+
+       return size;
+}
+
+static int
+fwcfg_statfs(const char *path, struct statvfs *st)
+{
+       uint32_t count;
+
+       set_index(FW_CFG_FILE_DIR);
+       read_data(&count, sizeof(count));
+
+       memset(st, 0, sizeof(*st));
+       st->f_files = be32toh(count);
+
+       return 0;
+}
+
+static struct fuse_operations fwcfg_ops = {
+       .getattr = fwcfg_getattr,
+       .readdir = fwcfg_readdir,
+       .open = fwcfg_open,
+       .read = fwcfg_read,
+       .statfs = fwcfg_statfs,
+};
+
+static void



Home | Main Index | Thread Index | Old Index