[PATCH 3/8] fs: Add RATP fs support
Andrey Smirnov
andrew.smirnov at gmail.com
Sun Jan 17 17:10:31 PST 2016
On Fri, Jan 8, 2016 at 3:13 AM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> From: Jan Luebbe <jlu at pengutronix.de>
>
> This adds file transfer support over RATP. The host can export a
> directory using the bbremote tool which can then be mounted under
> barebox as a filesystem.
>
> Signed-off-by: Jan Luebbe <jlu at pengutronix.de>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Tested-by: Andrey Smirnov <andrew.smirnov at gmail.com>
> ---
> fs/Kconfig | 8 +
> fs/Makefile | 2 +-
> fs/ratpfs.c | 476 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 485 insertions(+), 1 deletion(-)
> create mode 100644 fs/ratpfs.c
>
> diff --git a/fs/Kconfig b/fs/Kconfig
> index 9217bc8..9cfeb37 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -89,4 +89,12 @@ config FS_SMHFS
> located on a debugging host connected to the target running
> Barebox
>
> +config FS_RATP
> + bool
> + depends on CONSOLE_RATP
> + prompt "RATP filesystem support"
> + help
> + This enables support for transferring files over RATP. A host can
> + export a directory which can then be mounted under barebox.
> +
> endmenu
> diff --git a/fs/Makefile b/fs/Makefile
> index befbdf2..714acb4 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -14,4 +14,4 @@ obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
> obj-$(CONFIG_FS_EFI) += efi.o
> obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
> obj-$(CONFIG_FS_SMHFS) += smhfs.o
> -obj-$(CONFIG_RATP) += ratpfs.o
> +obj-$(CONFIG_FS_RATP) += ratpfs.o
> diff --git a/fs/ratpfs.c b/fs/ratpfs.c
> new file mode 100644
> index 0000000..902289b
> --- /dev/null
> +++ b/fs/ratpfs.c
> @@ -0,0 +1,476 @@
> +/*
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; version 2.
> + *
> + * This program 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
> + * General Public License for more details.
> + */
> +
> +#define pr_fmt(fmt) "barebox-ratpfs: " fmt
> +
> +#include <common.h>
> +#include <command.h>
> +#include <init.h>
> +#include <malloc.h>
> +#include <fs.h>
> +#include <errno.h>
> +#include <linux/stat.h>
> +#include <asm/unaligned.h>
> +#include <ratp_bb.h>
> +
> +#define RATPFS_TYPE_MOUNT_CALL 1
> +#define RATPFS_TYPE_MOUNT_RETURN 2
> +#define RATPFS_TYPE_READDIR_CALL 3
> +#define RATPFS_TYPE_READDIR_RETURN 4
> +#define RATPFS_TYPE_STAT_CALL 5
> +#define RATPFS_TYPE_STAT_RETURN 6
> +#define RATPFS_TYPE_OPEN_CALL 7
> +#define RATPFS_TYPE_OPEN_RETURN 8
> +#define RATPFS_TYPE_READ_CALL 9
> +#define RATPFS_TYPE_READ_RETURN 10
> +#define RATPFS_TYPE_WRITE_CALL 11
> +#define RATPFS_TYPE_WRITE_RETURN 12
> +#define RATPFS_TYPE_CLOSE_CALL 13
> +#define RATPFS_TYPE_CLOSE_RETURN 14
> +#define RATPFS_TYPE_TRUNCATE_CALL 15
> +#define RATPFS_TYPE_TRUNCATE_RETURN 16
> +
> +struct ratpfs_file {
> + uint32_t handle;
> +};
> +
> +struct ratpfs_dir {
> + char *entries;
> + int len, off;
> + DIR dir;
> +};
> +
> +static int ratpfs_create(struct device_d __always_unused *dev,
> + const char __always_unused *pathname,
> + mode_t __always_unused mode)
> +{
> + pr_debug("%s\n", __func__);
> +
> + return 0;
> +}
> +
> +static int ratpfs_mkdir(struct device_d __always_unused *dev,
> + const char __always_unused *pathname)
> +{
> + pr_debug("%s\n", __func__);
> +
> + return -ENOSYS;
> +}
> +
> +static int ratpfs_rm(struct device_d __always_unused *dev,
> + const char *pathname)
> +{
> + pr_debug("%s\n", __func__);
> +
> + /* Get rid of leading '/' */
> + pathname = &pathname[1];
> +
> + return 0;
> +}
> +
> +static int ratpfs_truncate(struct device_d __always_unused *dev,
> + FILE *f, ulong size)
> +{
> + int len_tx = 1 /* type */
> + + 4 /* handle */
> + + 4 /* size */;
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx)+len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + struct ratpfs_file *rfile = f->priv;
> + int ret;
> +
> + pr_debug("%s: len_tx=%i handle=%i size=%i\n", __func__,
> + len_tx, rfile->handle, (int)size);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_TRUNCATE_CALL;
> + put_unaligned_be32(rfile->handle, &pkt_tx->data[1]);
> + put_unaligned_be32(size, &pkt_tx->data[5]);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> +
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_TRUNCATE_RETURN) {
> + pr_err("invalid truncate response\n");
> + ret = -EIO;
> + goto out;
> + }
> +
> +out:
> + free(pkt_rx);
> + return ret;
> +}
> +
> +static int ratpfs_open(struct device_d __always_unused *dev,
> + FILE *file, const char *filename)
> +{
> + int len_name = strlen(filename);
> + int len_tx = 1 /* type */
> + + 4 /* flags */
> + + len_name /* path */;
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + struct ratpfs_file *rfile = xzalloc(sizeof(*rfile));
> + int ret;
> +
> + pr_debug("%s: len_tx=%i filename='%s'\n", __func__, len_tx, filename);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_OPEN_CALL;
> + put_unaligned_be32(file->flags, &pkt_tx->data[1]);
> + memcpy(&pkt_tx->data[5], filename, len_name);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret) {
> + ret = -EIO;
> + goto err;
> + }
> +
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_OPEN_RETURN) {
> + pr_err("invalid open response\n");
> + ret = -EIO;
> + goto err;
> + }
> + rfile->handle = get_unaligned_be32(&pkt_rx->data[1]);
> + if (rfile->handle == 0) {
> + ret = -get_unaligned_be32(&pkt_rx->data[5]); /* errno */
> + goto err;
> + }
> + file->priv = rfile;
> + file->size = get_unaligned_be32(&pkt_rx->data[5]);
> +
> + goto out;
> +
> +err:
> + file->priv = NULL;
> + free(rfile);
> +out:
> + free(pkt_rx);
> + return ret;
> +}
> +
> +static int ratpfs_close(struct device_d __always_unused *dev,
> + FILE *f)
> +{
> + int len_tx = 1 /* type */
> + + 4 /* handle */;
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + struct ratpfs_file *rfile = f->priv;
> + int ret;
> +
> + pr_debug("%s: len_tx=%i handle=%i\n", __func__,
> + len_tx, rfile->handle);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_CLOSE_CALL;
> + put_unaligned_be32(rfile->handle, &pkt_tx->data[1]);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> +
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_CLOSE_RETURN) {
> + pr_err("invalid close response\n");
> + goto out;
> + }
> +
> +out:
> + free(pkt_rx);
> + return ret;
> +}
> +
> +static int ratpfs_write(struct device_d __always_unused *dev,
> + FILE *f, const void *buf, size_t orig_size)
> +{
> + int size = min((int)orig_size, 4096);
> + int len_tx = 1 /* type */
> + + 4 /* handle */
> + + 4 /* pos */
> + + size /* data */;
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + struct ratpfs_file *rfile = f->priv;
> + int ret;
> +
> + pr_debug("%s: len_tx=%i handle=%i pos=%i size=%i\n", __func__,
> + len_tx, rfile->handle, (int)f->pos, size);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_WRITE_CALL;
> + put_unaligned_be32(rfile->handle, &pkt_tx->data[1]);
> + put_unaligned_be32(f->pos, &pkt_tx->data[5]);
> + memcpy(&pkt_tx->data[9], buf, size);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> +
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_WRITE_RETURN) {
> + pr_err("invalid write response\n");
> + ret = -EIO;
> + goto out;
> + }
> +
> + ret = size;
> +out:
> + free(pkt_rx);
> +
> + return ret;
> +}
> +
> +static int ratpfs_read(struct device_d __always_unused *dev,
> + FILE *f, void *buf, size_t orig_size)
> +{
> + int size = min((int)orig_size, 4096);
> + int len_tx = 1 /* type */
> + + 4 /* handle */
> + + 4 /* pos */
> + + 4 /* size */;
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + struct ratpfs_file *rfile = f->priv;
> + int ret;
> +
> + pr_debug("%s: len_tx=%i handle=%i pos=%i size=%i\n", __func__,
> + len_tx, rfile->handle, (int)f->pos, size);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_READ_CALL;
> + put_unaligned_be32(rfile->handle, &pkt_tx->data[1]);
> + put_unaligned_be32(f->pos, &pkt_tx->data[5]);
> + put_unaligned_be32(size, &pkt_tx->data[9]);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_READ_RETURN) {
> + pr_err("invalid read response\n");
> + ret = -EIO;
> + goto out;
> + }
> + size = pkt_rx->len - 1;
> + memcpy(buf, &pkt_rx->data[1], size);
> + ret = size;
> +
> +out:
> + free(pkt_rx);
> + return ret;
> +}
> +
> +static loff_t ratpfs_lseek(struct device_d __always_unused *dev,
> + FILE *f, loff_t pos)
> +{
> + pr_debug("%s\n", __func__);
> + f->pos = pos;
> + return f->pos;
> +}
> +
> +static DIR* ratpfs_opendir(struct device_d __always_unused *dev,
> + const char *pathname)
> +{
> + int len_name = strlen(pathname);
> + int len_tx = 1 /* type */
> + + len_name /* path */;
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx)+len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + struct ratpfs_dir *rdir = xzalloc(sizeof(*rdir));
> + int ret;
> +
> + pr_debug("%s: len_tx=%i pathname='%s'\n", __func__, len_tx, pathname);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_READDIR_CALL;
> + memcpy(&pkt_tx->data[1], pathname, len_name);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (!ret) {
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_READDIR_RETURN) {
> + pr_err("invalid readdir response\n");
> + free(pkt_rx);
> + return NULL;
> + }
> + rdir->len = pkt_rx->len - 1;
> + rdir->entries = xmemdup(&pkt_rx->data[1], rdir->len);
> + free(pkt_rx);
> + return &rdir->dir;
> + } else {
> + return NULL;
> + }
> +}
> +
> +static struct dirent *ratpfs_readdir(struct device_d *dev, DIR *dir)
> +{
> + struct ratpfs_dir *rdir = container_of(dir, struct ratpfs_dir, dir);
> + int i;
> +
> + pr_debug("%s\n", __func__);
> +
> + if (rdir->len <= rdir->off)
> + return NULL;
> +
> + for (i = 0; rdir->off < rdir->len; rdir->off++, i++) {
> + dir->d.d_name[i] = rdir->entries[rdir->off];
> + if (dir->d.d_name[i] == 0)
> + break;
> + }
> + rdir->off++;
> +
> + return &dir->d;
> +}
> +
> +static int ratpfs_closedir(struct device_d *dev, DIR *dir)
> +{
> + struct ratpfs_dir *rdir = container_of(dir, struct ratpfs_dir, dir);
> +
> + pr_debug("%s\n", __func__);
> +
> + free(rdir->entries);
> + free(rdir);
> +
> + return 0;
> +}
> +
> +static int ratpfs_stat(struct device_d __always_unused *dev,
> + const char *filename, struct stat *s)
> +{
> + int len_name = strlen(filename);
> + int len_tx = 1 /* type */
> + + len_name; /* path */
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + int ret;
> +
> + pr_debug("%s: len_tx=%i filename='%s'\n", __func__, len_tx, filename);
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_STAT_CALL;
> + memcpy(&pkt_tx->data[1], filename, len_name);
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret) {
> + ret = -EIO;
> + goto out;
> + }
> +
> + pr_debug("%s: len_rx=%i\n", __func__, pkt_rx->len);
> + if (pkt_rx->len < 6 || pkt_rx->data[0] != RATPFS_TYPE_STAT_RETURN) {
> + pr_err("invalid stat response\n");
> + goto out;
> + }
> + switch (pkt_rx->data[1]) {
> + case 0:
> + ret = -ENOENT;
> + break;
> + case 1:
> + s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
> + break;
> + case 2:
> + s->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
> + break;
> + }
> + s->st_size = get_unaligned_be32(&pkt_rx->data[2]);
> +
> +out:
> + free(pkt_rx);
> + return ret;
> +}
> +
> +static int ratpfs_probe(struct device_d *dev)
> +{
> + int len_tx = 1; /* type */
> + struct ratp_bb_pkt *pkt_tx = xzalloc(sizeof(*pkt_tx) + len_tx);
> + struct ratp_bb_pkt *pkt_rx = NULL;
> + int ret;
> + struct fs_device_d *fsdev = dev_to_fs_device(dev);
> +
> + pr_debug("%s\n", __func__);
> +
> + ret = barebox_ratp_fs_mount(fsdev->path);
> + if (ret)
> + return ret;
> +
> + pkt_tx->len = len_tx;
> + pkt_tx->data[0] = RATPFS_TYPE_MOUNT_CALL;
> +
> + ret = barebox_ratp_fs_call(pkt_tx, &pkt_rx);
> + if (ret)
> + goto out;
> +
> + if (pkt_rx->len < 1 || pkt_rx->data[0] != RATPFS_TYPE_MOUNT_RETURN) {
> + pr_err("invalid mount response\n");
> + ret = -EINVAL;
> + goto out;
> + }
> +
> +out:
> + free(pkt_rx);
> +
> + if (ret)
> + barebox_ratp_fs_mount(NULL);
> +
> + return ret;
> +}
> +
> +static void ratpfs_remove(struct device_d __always_unused *dev)
> +{
> + pr_debug("%s\n", __func__);
> +
> + barebox_ratp_fs_mount(NULL);
> +}
> +
> +static struct fs_driver_d ratpfs_driver = {
> + .open = ratpfs_open,
> + .close = ratpfs_close,
> + .read = ratpfs_read,
> + .lseek = ratpfs_lseek,
> + .opendir = ratpfs_opendir,
> + .readdir = ratpfs_readdir,
> + .closedir = ratpfs_closedir,
> + .stat = ratpfs_stat,
> + .create = ratpfs_create,
> + .unlink = ratpfs_rm,
> + .mkdir = ratpfs_mkdir,
> + .rmdir = ratpfs_rm,
> + .write = ratpfs_write,
> + .truncate = ratpfs_truncate,
> + .flags = FS_DRIVER_NO_DEV,
> + .drv = {
> + .probe = ratpfs_probe,
> + .remove = ratpfs_remove,
> + .name = "ratpfs",
> + }
> +};
> +
> +static int ratpfs_init(void)
> +{
> + return register_fs_driver(&ratpfs_driver);
> +}
> +coredevice_initcall(ratpfs_init);
> \ No newline at end of file
> --
> 2.6.4
>
>
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
More information about the barebox
mailing list