Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F97414759
D36607.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D36607.diff
View Options
diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile
--- a/stand/kboot/Makefile
+++ b/stand/kboot/Makefile
@@ -25,6 +25,7 @@
host_syscalls.c \
hostcons.c \
hostdisk.c \
+ hostfs.c \
init.c \
kbootfdt.c \
main.c \
diff --git a/stand/kboot/conf.c b/stand/kboot/conf.c
--- a/stand/kboot/conf.c
+++ b/stand/kboot/conf.c
@@ -35,6 +35,7 @@
#endif
extern struct devsw hostdisk;
+extern struct devsw host_dev;
/*
* We could use linker sets for some or all of these, but
@@ -53,9 +54,12 @@
#if defined(LOADER_NET_SUPPORT)
&netdev,
#endif
+ &host_dev,
NULL
};
+extern struct fs_ops hostfs_fsops;
+
struct fs_ops *file_system[] = {
#if defined(LOADER_UFS_SUPPORT)
&ufs_fsops,
@@ -79,6 +83,7 @@
&bzipfs_fsops,
#endif
&dosfs_fsops,
+ &hostfs_fsops,
NULL
};
diff --git a/stand/kboot/hostfs.c b/stand/kboot/hostfs.c
new file mode 100644
--- /dev/null
+++ b/stand/kboot/hostfs.c
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 2022 Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/types.h>
+#include "stand.h"
+#include "host_syscall.h"
+#include "kboot.h"
+
+#define HOST_PATH_MAX 1025
+
+extern struct devsw host_dev;
+
+const char *hostfs_root = "/";
+
+enum FTYPE {
+ regular,
+ dir,
+};
+
+typedef struct _hostfs_file {
+ enum FTYPE hf_type;
+ int hf_fd;
+ /* The following are only used for FTYPE == dir */
+ char hf_dents[2048];
+ char *hf_curdent;
+ int hf_dentlen; /* Valid part of hf_dents */
+} hostfs_file;
+
+static hostfs_file *
+hostfs_alloc(void)
+{
+ hostfs_file *hf;
+
+ hf = malloc(sizeof(*hf));
+ if (hf != NULL)
+ memset(hf, 0, sizeof(*hf));
+ return (hf);
+}
+
+static void
+hostfs_free(hostfs_file *hf)
+{
+ free(hf);
+}
+
+static int
+hostfs_open(const char *fn, struct open_file *f)
+{
+ hostfs_file *hf;
+ struct host_kstat ksb;
+ char path[HOST_PATH_MAX];
+
+ if (f->f_dev != &host_dev) {
+ return (EINVAL);
+ }
+
+ /*
+ * Normally, we root everything at hostfs_root. However, there are two
+ * exceptions that make it easier to write code. First is /sys and /proc
+ * are special Linux filesystems, so we pass those paths
+ * through. Second, if the path starts with //, then we strip off the
+ * first / and pass it through (in a weird way, this is actually in
+ * POSIX: hosts are allowed to do specail things with paths that start
+ * with two //, but one or three or more are required to be treated as
+ * one).
+ */
+ if (strncmp("/sys/", fn, 5) == 0 || strncmp("/proc/", fn, 6) == 0)
+ strlcpy(path, fn, sizeof(path));
+ else if (fn[0] == '/' && fn[1] == '/' && fn[2] != '/')
+ strlcpy(path, fn + 1, sizeof(path));
+ else
+ snprintf(path, sizeof(path), "%s/%s", hostfs_root, fn);
+ hf = hostfs_alloc();
+ hf->hf_fd = host_open(path, HOST_O_RDONLY, 0);
+ if (hf->hf_fd < 0) {
+ hostfs_free(hf);
+ return (EINVAL);
+ }
+
+ if (host_fstat(hf->hf_fd, &ksb) < 0) {
+ hostfs_free(hf);
+ return (EINVAL);
+ }
+ if (S_ISDIR(hf->hf_fd)) {
+ hf->hf_type = dir;
+ } else {
+ hf->hf_type = regular;
+ }
+ f->f_fsdata = hf;
+ return (0);
+}
+
+static int
+hostfs_close(struct open_file *f)
+{
+ hostfs_file *hf = f->f_fsdata;
+
+ host_close(hf->hf_fd);
+ hostfs_free(hf);
+ f->f_fsdata = NULL;
+
+ return (0);
+}
+
+static int
+hostfs_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+ hostfs_file *hf = f->f_fsdata;
+ ssize_t sz;
+
+ sz = host_read(hf->hf_fd, start, size);
+ if (sz < 0) {
+ return (EINVAL);
+ }
+ *resid = size - sz;
+
+ return (0);
+}
+
+static off_t
+hostfs_seek(struct open_file *f, off_t offset, int whence)
+{
+ hostfs_file *hf = f->f_fsdata;
+ uint32_t offl, offh;
+ int err;
+ uint64_t res;
+
+ /*
+ * Assumes Linux host with 'reduced' system call wrappers. Also assume
+ * host and libstand have same whence encoding (safe since it all comes
+ * from V7 later ISO-C). Also assumes we have to support powerpc still,
+ * it's interface is weird for legacy reasons....
+ */
+ offl = offset & 0xffffffff;
+ offh = (offset >> 32) & 0xffffffff;
+ err = host_llseek(hf->hf_fd, offh, offl, &res, whence);
+ if (err < 0)
+ return (err);
+ return (res);
+}
+
+static int
+hostfs_stat(struct open_file *f, struct stat *sb)
+{
+ struct host_kstat ksb;
+ hostfs_file *hf = f->f_fsdata;
+
+ if (host_fstat(hf->hf_fd, &ksb) < 0)
+ return (EINVAL);
+ /*
+ * Translate Linux stat info to lib stand's notion (which uses FreeBSD's
+ * stat structure, missing fields are zero and commented below).
+ */
+ memset(sb, 0, sizeof(*sb));
+ sb->st_dev = ksb.st_dev;
+ sb->st_ino = ksb.st_ino;
+ sb->st_nlink = ksb.st_nlink;
+ sb->st_mode = ksb.st_mode;
+ sb->st_uid = ksb.st_uid;
+ sb->st_gid = ksb.st_gid;
+ sb->st_rdev = ksb.st_rdev;
+ /* No st_?time_ext on i386 */
+ sb->st_atim.tv_sec = ksb.st_atime_sec;
+ sb->st_atim.tv_nsec = ksb.st_atime_nsec;
+ sb->st_mtim.tv_sec = ksb.st_mtime_sec;
+ sb->st_mtim.tv_nsec = ksb.st_mtime_nsec;
+ sb->st_ctim.tv_sec = ksb.st_ctime_sec;
+ sb->st_ctim.tv_nsec = ksb.st_ctime_nsec;
+ /* No st_birthtim */
+ sb->st_size = ksb.st_size;
+ sb->st_blocks = ksb.st_blocks;
+ sb->st_blksize = ksb.st_blksize;
+ /* no st_flags */
+ /* no st_get */
+
+ return (0);
+}
+
+static int
+hostfs_readdir(struct open_file *f, struct dirent *d)
+{
+ hostfs_file *hf = f->f_fsdata;
+ int dentlen;
+ struct host_dirent64 *dent;
+
+ if (hf->hf_curdent == NULL) {
+ dentlen = host_getdents64(hf->hf_fd, hf->hf_dents, sizeof(hf->hf_dents));
+ if (dentlen <= 0)
+ return (EINVAL);
+ hf->hf_dentlen = dentlen;
+ hf->hf_curdent = hf->hf_dents;
+ }
+ dent = (struct host_dirent64 *)hf->hf_curdent;
+ d->d_fileno = dent->d_ino;
+ d->d_type = dent->d_type; /* HOST_DT_XXXX == DX_XXXX for all values */
+ strlcpy(d->d_name, dent->d_name, sizeof(d->d_name)); /* d_name is NUL terminated */
+ d->d_namlen = strlen(d->d_name);
+ hf->hf_curdent += dent->d_reclen;
+ if (hf->hf_curdent >= hf->hf_dents + hf->hf_dentlen) {
+ hf->hf_curdent = NULL;
+ hf->hf_dentlen = 0;
+ }
+
+ return (0);
+}
+
+struct fs_ops hostfs_fsops = {
+ .fs_name = "host",
+ .fo_open = hostfs_open,
+ .fo_close = hostfs_close,
+ .fo_read = hostfs_read,
+ .fo_write = null_write,
+ .fo_seek = hostfs_seek,
+ .fo_stat = hostfs_stat,
+ .fo_readdir = hostfs_readdir
+};
+
+/*
+ * Generic "null" host device. This goes hand and hand with the host fs object
+ *
+ * XXXX This and userboot for bhyve both use exactly the same code, modulo some
+ * formatting nits. Make them common. We mostly use it to 'gate' the open of the
+ * filesystem to only this device.
+ */
+
+static int
+host_dev_init(void)
+{
+ return (0);
+}
+
+static int
+host_dev_print(int verbose)
+{
+ char line[80];
+
+ printf("%s devices:", host_dev.dv_name);
+ if (pager_output("\n") != 0)
+ return (1);
+
+ snprintf(line, sizeof(line), " host%d: Host filesystem\n", 0);
+ return (pager_output(line));
+}
+
+/*
+ * 'Open' the host device.
+ */
+static int
+host_dev_open(struct open_file *f, ...)
+{
+ return (0);
+}
+
+static int
+host_dev_close(struct open_file *f)
+{
+ return (0);
+}
+
+static int
+host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
+ char *buf, size_t *rsize)
+{
+ return (ENOSYS);
+}
+
+struct devsw host_dev = {
+ .dv_name = "host",
+ .dv_type = DEVT_NET,
+ .dv_init = host_dev_init,
+ .dv_strategy = host_dev_strategy,
+ .dv_open = host_dev_open,
+ .dv_close = host_dev_close,
+ .dv_ioctl = noioctl,
+ .dv_print = host_dev_print,
+ .dv_cleanup = NULL
+};
diff --git a/stand/kboot/kboot.h b/stand/kboot/kboot.h
--- a/stand/kboot/kboot.h
+++ b/stand/kboot/kboot.h
@@ -11,6 +11,8 @@
void do_init(void);
+extern const char *hostfs_root;
+
/* Per-platform fdt fixup */
void fdt_arch_fixups(void *fdtp);
diff --git a/stand/kboot/main.c b/stand/kboot/main.c
--- a/stand/kboot/main.c
+++ b/stand/kboot/main.c
@@ -120,8 +120,10 @@
bootdev = argv[1];
else
bootdev = "";
+ if (argc > 2)
+ hostfs_root = argv[2];
- printf("Boot device: %s\n", bootdev);
+ printf("Boot device: %s with hostfs_root %s\n", bootdev, hostfs_root);
archsw.arch_getdev = kboot_getdev;
archsw.arch_copyin = kboot_copyin;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 30, 4:18 AM (21 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13168382
Default Alt Text
D36607.diff (7 KB)
Attached To
Mode
D36607: kboot: Add hostfs
Attached
Detach File
Event Timeline
Log In to Comment