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