From nobody Thu Oct 27 17:56:41 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4MytfK4d3Sz4gdtG; Thu, 27 Oct 2022 17:56:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MytfK49KLz41R3; Thu, 27 Oct 2022 17:56:41 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1666893401; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0RjykJgeZUVe588wOGwWNK8c7G7G7dRzHJ/aKz80j6s=; b=Y1vbvWKJyxVEGaoaQRyxtI+S25+uvZvy0m/kkMhRXudYGUrK2BwjPRBY+ljr4IUEMWvDYJ jvs+rGPZ8Go+Uifap76whsDXn9DSAaapJICAgzxl9OopVVgJTxfer288igpRC+7WbICls3 mTT7ndi8xADc8fGY8/jKi94qVwFG/Djxx4YBNnXVwl/NQd/StwmIVK6oac7V3NtC+cFJdV OL8An6xE0d2HWjxqj+JDErMP9NlvhRBvMr6A4s5zeYUb9Q/WVguRcuDKK07DFJ2cSzmecF 8Wosk1iYMueNAaNjFzkT9aP+43KGN5oyEVP8SxpJEF2StwWHkHD2RRId83hxCQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4MytfK3H4dz16QK; Thu, 27 Oct 2022 17:56:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 29RHufNl018720; Thu, 27 Oct 2022 17:56:41 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 29RHufVW018719; Thu, 27 Oct 2022 17:56:41 GMT (envelope-from git) Date: Thu, 27 Oct 2022 17:56:41 GMT Message-Id: <202210271756.29RHufVW018719@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: 02dba4f75f86 - main - kboot: Add hostfs List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 02dba4f75f86f3d5ae5a6a438b5bcfdc667929bb Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1666893401; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0RjykJgeZUVe588wOGwWNK8c7G7G7dRzHJ/aKz80j6s=; b=bezs/70klLOzw2pa46NNGBE3MdUGM7NnYhN7wbf1FDq6HIXy4ZjA5K+y14kC7fmap7l80Q StP0NVwNsottC0xozuqq7ZoL3tJ/v8rQaQeZToPBmyG1byryRh9IFi9Yl0596prOW6Kgcv ne30KTmDW+z/+/u5kEq4fSLOHJ6maxnIM98do7ilWHLYCkSIUw3MhSR+SSeGEBWzck+Ep3 bqXeMp4ZHoJm2BV3hx7V75Xc36VNMIR2sGs9YlZ+NcPdPqVchQtSdupb5v3uuvqat1O4g0 hx0XgpeNBBgtqpn501nsTCWwMLC4XSwcVl/Tdx8wcdEpdY6j86jbPje614D8vg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1666893401; a=rsa-sha256; cv=none; b=sdP9kHRLaBJ+uJ09YYcuaq1DJ2HvPxmx50Sv00j2b3o64LYy+XKr/1fGzRylmHi992IdkI H8pFb2DyhWtcFQfM2k91IrmONccFXqYlMJTQ+ztNjIj6y4q3Okt59CiCZUR5OWNPuVmVni wWj1Xm9VK+F5xUqJGrJSw+ade3/kEpvvrqBkgEtPgTbLVYHSgKSKhpH+u3AL7x+rMu89p0 GYl10UzpMzng160u8OnFqhsshGvOBTCjRfRlTbgNEUPPXjRQBDzJnBphPfI2aa3SymY2na rQYUh34Bh9c/kkQ+DL/+nSxOFHSY/XuveDJBQ/nvy+ZB0ix+gQeDgh9xg+Nrew== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=02dba4f75f86f3d5ae5a6a438b5bcfdc667929bb commit 02dba4f75f86f3d5ae5a6a438b5bcfdc667929bb Author: Warner Losh AuthorDate: 2022-10-27 17:37:54 +0000 Commit: Warner Losh CommitDate: 2022-10-27 17:37:54 +0000 kboot: Add hostfs Add hostfs for the Linux environment. We can't use the userboot one that's kinda similar because the Linux system calls we have in kboot are not quite POSIX compliant (Linux takes care of providing the POSIX interface in libc), so we have to cope with a number of quirks in that area. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D36607 --- stand/kboot/Makefile | 1 + stand/kboot/conf.c | 5 + stand/kboot/hostfs.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++ stand/kboot/kboot.h | 2 + stand/kboot/main.c | 4 +- 5 files changed, 291 insertions(+), 1 deletion(-) diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile index 518e945a596e..c8bd313d1d1d 100644 --- a/stand/kboot/Makefile +++ b/stand/kboot/Makefile @@ -25,6 +25,7 @@ SRCS= \ 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 index b840d008a347..26788342c4b9 100644 --- a/stand/kboot/conf.c +++ b/stand/kboot/conf.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #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 @@ struct devsw *devsw[] = { #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 @@ struct fs_ops *file_system[] = { &bzipfs_fsops, #endif &dosfs_fsops, + &hostfs_fsops, NULL }; diff --git a/stand/kboot/hostfs.c b/stand/kboot/hostfs.c new file mode 100644 index 000000000000..08f532999abe --- /dev/null +++ b/stand/kboot/hostfs.c @@ -0,0 +1,280 @@ +/*- + * Copyright (c) 2022 Netflix, Inc + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#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 index 81bd18faa893..5441c90eaecc 100644 --- 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 index 10dd6b05194b..23211ce9df4c 100644 --- a/stand/kboot/main.c +++ b/stand/kboot/main.c @@ -120,8 +120,10 @@ main(int argc, const char **argv) 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;