diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c index 01db731..f230d9a 100644 --- a/arch/arm/mach-mxs/ocotp.c +++ b/arch/arm/mach-mxs/ocotp.c @@ -174,7 +174,6 @@ static struct cdev_operations mxs_ocotp_ops = { .read = mxs_ocotp_cdev_read, - .lseek = dev_lseek_default, }; static int mxs_ocotp_probe(struct device_d *dev) diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c index 3fc1503..745f078 100644 --- a/arch/sandbox/board/hostfile.c +++ b/arch/sandbox/board/hostfile.c @@ -67,7 +67,6 @@ static struct cdev_operations hf_fops = { .read = hf_read, .write = hf_write, - .lseek = dev_lseek_default, }; static int hf_probe(struct device_d *dev) diff --git a/commands/Kconfig b/commands/Kconfig index 1de4b9d..c14332c 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -14,11 +14,6 @@ help Turns on compilation of digest.c -config COMPILE_MEMORY - bool - help - Turns on compilation of mem.c - menu "Commands" @@ -1493,7 +1488,7 @@ config CMD_MD tristate default y - select COMPILE_MEMORY + select DEV_MEM prompt "md" help Memory display @@ -1517,7 +1512,7 @@ config CMD_MEMCMP tristate default y - select COMPILE_MEMORY + select DEV_MEM prompt "memcmp" help Memory compare @@ -1539,7 +1534,7 @@ config CMD_MEMCPY tristate default y - select COMPILE_MEMORY + select DEV_MEM prompt "memcpy" help Memory copy @@ -1558,7 +1553,7 @@ config CMD_MEMSET tristate default y - select COMPILE_MEMORY + select DEV_MEM prompt "memset" help Memory fill @@ -1591,7 +1586,7 @@ config CMD_MM tristate - select COMPILE_MEMORY + select DEV_MEM prompt "memory modify (mm)" help Memory modify with mask @@ -1609,7 +1604,7 @@ config CMD_MW tristate default y - select COMPILE_MEMORY + select DEV_MEM prompt "mw" help Memory write diff --git a/commands/Makefile b/commands/Makefile index eb47963..358671b 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -1,7 +1,6 @@ obj-$(CONFIG_STDDEV) += stddev.o obj-$(CONFIG_CMD_DIGEST) += digest.o obj-$(CONFIG_COMPILE_HASH) += hashsum.o -obj-$(CONFIG_COMPILE_MEMORY) += mem.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_UIMAGE) += uimage.o obj-$(CONFIG_CMD_LINUX16) += linux16.o diff --git a/commands/md.c b/commands/md.c index a495fc8..2389c12 100644 --- a/commands/md.c +++ b/commands/md.c @@ -34,8 +34,6 @@ #include #include -extern char *mem_rw_buf; - static int do_mem_md(int argc, char *argv[]) { loff_t start = 0, size = 0x100; @@ -46,6 +44,7 @@ int mode = O_RWSIZE_4; int swab = 0; void *map; + void *buf = NULL; if (argc < 2) return COMMAND_ERROR_USAGE; @@ -74,9 +73,11 @@ goto out; } + buf = xmalloc(RW_BUF_SIZE); + do { now = min(size, (loff_t)RW_BUF_SIZE); - r = read(fd, mem_rw_buf, now); + r = read(fd, buf, now); if (r < 0) { perror("read"); goto out; @@ -84,8 +85,8 @@ if (!r) goto out; - if ((ret = memory_display(mem_rw_buf, start, r, - mode >> O_RWSIZE_SHIFT, swab))) + if ((ret = memory_display(buf, start, r, + mode >> O_RWSIZE_SHIFT, swab))) goto out; start += r; @@ -93,6 +94,7 @@ } while (size); out: + free(buf); close(fd); return ret ? 1 : 0; diff --git a/commands/mem.c b/commands/mem.c deleted file mode 100644 index a9e12f3..0000000 --- a/commands/mem.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2011 Sascha Hauer , Pengutronix - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * 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. - * - */ - -/* - * Memory Functions - * - * Copied from FADS ROM, Dan Malek (dmalek@jlc.net) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CMD_MEM_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif - -char *mem_rw_buf; - -/* - * Common function for parsing options for the 'md', 'mw', 'memcpy', 'memcmp' - * commands. - */ -int mem_parse_options(int argc, char *argv[], char *optstr, int *mode, - char **sourcefile, char **destfile, int *swab) -{ - int opt; - - while((opt = getopt(argc, argv, optstr)) > 0) { - switch(opt) { - case 'b': - *mode = O_RWSIZE_1; - break; - case 'w': - *mode = O_RWSIZE_2; - break; - case 'l': - *mode = O_RWSIZE_4; - break; - case 'q': - *mode = O_RWSIZE_8; - break; - case 's': - *sourcefile = optarg; - break; - case 'd': - *destfile = optarg; - break; - case 'x': - *swab = 1; - break; - default: - return COMMAND_ERROR_USAGE; - } - } - - return 0; -} - -static struct cdev_operations memops = { - .read = mem_read, - .write = mem_write, - .memmap = generic_memmap_rw, - .lseek = dev_lseek_default, -}; - -static int mem_probe(struct device_d *dev) -{ - struct cdev *cdev; - - cdev = xzalloc(sizeof (*cdev)); - dev->priv = cdev; - - cdev->name = (char*)dev->resource[0].name; - cdev->size = min_t(unsigned long long, resource_size(&dev->resource[0]), - S64_MAX); - cdev->ops = &memops; - cdev->dev = dev; - - devfs_create(cdev); - - return 0; -} - -static struct driver_d mem_drv = { - .name = "mem", - .probe = mem_probe, -}; - -static int mem_init(void) -{ - mem_rw_buf = malloc(RW_BUF_SIZE); - if(!mem_rw_buf) - return -ENOMEM; - - add_mem_device("mem", 0, ~0, IORESOURCE_MEM_WRITEABLE); - return platform_driver_register(&mem_drv); -} -device_initcall(mem_init); diff --git a/commands/memcmp.c b/commands/memcmp.c index 981c8cb..48957b4 100644 --- a/commands/memcmp.c +++ b/commands/memcmp.c @@ -34,8 +34,6 @@ #include #include -extern char *mem_rw_buf; - static char *devmem = "/dev/mem"; static int do_memcmp(int argc, char *argv[]) @@ -45,7 +43,7 @@ char *sourcefile = devmem; char *destfile = devmem; int sourcefd, destfd; - char *rw_buf1; + char *buf, *source_data, *dest_data; int ret = 1; int offset = 0; struct stat statbuf; @@ -84,20 +82,22 @@ return 1; } - rw_buf1 = xmalloc(RW_BUF_SIZE); + buf = xmalloc(RW_BUF_SIZE + RW_BUF_SIZE); + source_data = buf; + dest_data = buf + RW_BUF_SIZE; while (count > 0) { int now, r1, r2, i; now = min((loff_t)RW_BUF_SIZE, count); - r1 = read_full(sourcefd, mem_rw_buf, now); + r1 = read_full(sourcefd, source_data, now); if (r1 < 0) { perror("read"); goto out; } - r2 = read_full(destfd, rw_buf1, now); + r2 = read_full(destfd, dest_data, now); if (r2 < 0) { perror("read"); goto out; @@ -109,7 +109,7 @@ } for (i = 0; i < now; i++) { - if (mem_rw_buf[i] != rw_buf1[i]) { + if (source_data[i] != dest_data[i]) { printf("files differ at offset %d\n", offset); goto out; } @@ -124,7 +124,7 @@ out: close(sourcefd); close(destfd); - free(rw_buf1); + free(buf); return ret; } diff --git a/commands/memcpy.c b/commands/memcpy.c index 168ef3b..ddaf767 100644 --- a/commands/memcpy.c +++ b/commands/memcpy.c @@ -34,8 +34,6 @@ #include #include -extern char *mem_rw_buf; - static char *devmem = "/dev/mem"; static int do_memcpy(int argc, char *argv[]) @@ -47,6 +45,7 @@ int mode = 0; struct stat statbuf; int ret = 0; + char *buf; if (mem_parse_options(argc, argv, "bwlqs:d:", &mode, &sourcefile, &destfile, NULL) < 0) @@ -82,12 +81,14 @@ return 1; } + buf = xmalloc(RW_BUF_SIZE); + while (count > 0) { int now, r, w, tmp; now = min((loff_t)RW_BUF_SIZE, count); - r = read(sourcefd, mem_rw_buf, now); + r = read(sourcefd, buf, now); if (r < 0) { perror("read"); goto out; @@ -99,7 +100,7 @@ tmp = 0; now = r; while (now) { - w = write(destfd, mem_rw_buf + tmp, now); + w = write(destfd, buf + tmp, now); if (w < 0) { perror("write"); goto out; @@ -123,6 +124,7 @@ } out: + free(buf); close(sourcefd); close(destfd); diff --git a/commands/memset.c b/commands/memset.c index f99bf86..b077015 100644 --- a/commands/memset.c +++ b/commands/memset.c @@ -34,8 +34,6 @@ #include #include -extern char *mem_rw_buf; - static int do_memset(int argc, char *argv[]) { loff_t s, c, n; diff --git a/commands/stddev.c b/commands/stddev.c index 4d1b6f5..2b3d084 100644 --- a/commands/stddev.c +++ b/commands/stddev.c @@ -27,7 +27,6 @@ static struct cdev_operations zeroops = { .read = zero_read, - .lseek = dev_lseek_default, }; static int zero_init(void) @@ -55,7 +54,6 @@ static struct cdev_operations fullops = { .read = full_read, - .lseek = dev_lseek_default, }; static int full_init(void) @@ -82,7 +80,6 @@ static struct cdev_operations nullops = { .write = null_write, - .lseek = dev_lseek_default, }; static int null_init(void) @@ -110,7 +107,6 @@ static struct cdev_operations prngops = { .read = prng_read, - .lseek = dev_lseek_default, }; static int prng_init(void) diff --git a/common/block.c b/common/block.c index 8d0de42..d90c989 100644 --- a/common/block.c +++ b/common/block.c @@ -350,7 +350,6 @@ #endif .close = block_op_close, .flush = block_op_flush, - .lseek = dev_lseek_default, }; int blockdevice_register(struct block_device *blk) diff --git a/common/firmware.c b/common/firmware.c index 250fef5..9d55d73 100644 --- a/common/firmware.c +++ b/common/firmware.c @@ -177,7 +177,7 @@ cdev = &mgr->cdev; cdev->name = xstrdup(fh->id); - cdev->size = FILE_SIZE_STREAM; + cdev->flags = DEVFS_IS_CHARACTER_DEV; cdev->ops = &firmware_ops; cdev->priv = mgr; cdev->dev = fh->dev; diff --git a/common/ratp/md.c b/common/ratp/md.c index ce343d7..a25cbf1 100644 --- a/common/ratp/md.c +++ b/common/ratp/md.c @@ -59,8 +59,6 @@ uint8_t buffer[]; } __packed; -extern char *mem_rw_buf; - static int do_ratp_mem_md(const char *filename, loff_t start, loff_t size, @@ -70,6 +68,7 @@ int ret = 0; int fd; void *map; + char *buf = NULL; fd = open_and_lseek(filename, O_RWSIZE_1 | O_RDONLY, start); if (fd < 0) @@ -81,10 +80,11 @@ goto out; } + buf = xmalloc(RW_BUF_SIZE); t = 0; do { now = min(size, (loff_t)RW_BUF_SIZE); - r = read(fd, mem_rw_buf, now); + r = read(fd, buf, now); if (r < 0) { ret = -errno; perror("read"); @@ -93,13 +93,14 @@ if (!r) goto out; - memcpy(output + t, (uint8_t *)(mem_rw_buf), r); + memcpy(output + t, buf, r); size -= r; t += r; } while (size); out: + free(buf); close(fd); return ret; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 8bbc237..d2f8ec7 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -353,7 +353,6 @@ } static struct cdev_operations regmap_fops = { - .lseek = dev_lseek_default, .read = regmap_cdev_read, .write = regmap_cdev_write, }; diff --git a/drivers/eeprom/at24.c b/drivers/eeprom/at24.c index e79031a..1fd4aea 100644 --- a/drivers/eeprom/at24.c +++ b/drivers/eeprom/at24.c @@ -447,7 +447,6 @@ at24->cdev.priv = at24; at24->cdev.dev = dev; at24->cdev.ops = &at24->fops; - at24->fops.lseek = dev_lseek_default; at24->fops.read = at24_cdev_read, at24->fops.protect = at24_cdev_protect, at24->cdev.size = chip.byte_len; diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c index a9050d6..1c9ef12 100644 --- a/drivers/eeprom/at25.c +++ b/drivers/eeprom/at25.c @@ -235,7 +235,6 @@ static struct cdev_operations at25_fops = { .read = at25_ee_read, .write = at25_ee_write, - .lseek = dev_lseek_default, }; static int at25_np_to_chip(struct device_d *dev, diff --git a/drivers/hw_random/core.c b/drivers/hw_random/core.c index 1c68a37..ee3d5a5 100644 --- a/drivers/hw_random/core.c +++ b/drivers/hw_random/core.c @@ -63,7 +63,6 @@ static struct cdev_operations rng_chrdev_ops = { .read = rng_dev_read, - .lseek = dev_lseek_default, }; static int hwrng_register_cdev(struct hwrng *rng) diff --git a/drivers/mfd/act8846.c b/drivers/mfd/act8846.c index 53ab70f..b7a64c7 100644 --- a/drivers/mfd/act8846.c +++ b/drivers/mfd/act8846.c @@ -117,7 +117,6 @@ } static struct cdev_operations act8846_fops = { - .lseek = dev_lseek_default, .read = act8846_read, .write = act8846_write, }; diff --git a/drivers/mfd/lp3972.c b/drivers/mfd/lp3972.c index 42b2807..3ae9d1a 100644 --- a/drivers/mfd/lp3972.c +++ b/drivers/mfd/lp3972.c @@ -70,7 +70,6 @@ } static struct cdev_operations lp_fops = { - .lseek = dev_lseek_default, .read = lp_read, }; diff --git a/drivers/mfd/mc34704.c b/drivers/mfd/mc34704.c index f15f37e..4aa02b7 100644 --- a/drivers/mfd/mc34704.c +++ b/drivers/mfd/mc34704.c @@ -100,7 +100,6 @@ } static struct cdev_operations mc34704_fops = { - .lseek = dev_lseek_default, .read = mc34704_read, .write = mc34704_write, }; diff --git a/drivers/mfd/mc9sdz60.c b/drivers/mfd/mc9sdz60.c index 2cb38d9..408d746 100644 --- a/drivers/mfd/mc9sdz60.c +++ b/drivers/mfd/mc9sdz60.c @@ -112,7 +112,6 @@ } static struct cdev_operations mc_fops = { - .lseek = dev_lseek_default, .read = mc_read, .write = mc_write, }; diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 084e4b4..f140f1b 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -101,7 +101,6 @@ } static struct cdev_operations stmpe_fops = { - .lseek = dev_lseek_default, .read = stmpe_read, .write = stmpe_write, }; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index fb435f5..c3240b8 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -150,7 +150,6 @@ } struct cdev_operations twl_fops = { - .lseek = dev_lseek_default, .read = twl_read, .write = twl_write, }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6640a70..4c8a769 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -20,4 +20,7 @@ depends on OFDEVICE depends on STATE +config DEV_MEM + bool "Generic memory I/O device (/dev/mem)" + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 487e4b8..d4e616d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_JTAG) += jtag.o obj-$(CONFIG_SRAM) += sram.o obj-$(CONFIG_STATE_DRV) += state.o +obj-$(CONFIG_DEV_MEM) += mem.o diff --git a/drivers/misc/mem.c b/drivers/misc/mem.c new file mode 100644 index 0000000..6dd7f68 --- /dev/null +++ b/drivers/misc/mem.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2011 Sascha Hauer , Pengutronix + */ + +#include +#include +#include + +static struct cdev_operations memops = { + .read = mem_read, + .write = mem_write, + .memmap = generic_memmap_rw, +}; + +static int mem_probe(struct device_d *dev) +{ + struct cdev *cdev; + + cdev = xzalloc(sizeof (*cdev)); + dev->priv = cdev; + + cdev->name = (char*)dev->resource[0].name; + if (dev->resource[0].start == 0 && dev->resource[0].end == ~0) { + /* + * Special case for /dev/mem. We can't express it's size as it's + * outside of our address range. Set DEVFS_IS_CHARACTER_DEV to + * bypass size checks. + */ + cdev->size = 0; + cdev->flags = DEVFS_IS_CHARACTER_DEV; + } else { + cdev->size = resource_size(&dev->resource[0]); + } + + cdev->ops = &memops; + cdev->dev = dev; + + devfs_create(cdev); + + return 0; +} + +static struct driver_d mem_drv = { + .name = "mem", + .probe = mem_probe, +}; + +static int mem_init(void) +{ + struct device_d *dev; + struct resource res = { + .start = 0, + .end = ~0, + .flags = IORESOURCE_MEM, + .name = "mem", + }; + int ret; + + dev = device_alloc("mem", DEVICE_ID_DYNAMIC); + if (!dev) + return -ENOMEM; + + dev->resource = xmemdup(&res, sizeof(res)); + dev->num_resources = 1; + + ret = platform_device_register(dev); + if (ret) + return ret; + + return platform_driver_register(&mem_drv); +} +device_initcall(mem_init); diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index 27b4c68..053b351 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -29,7 +29,6 @@ .read = mem_read, .write = mem_write, .memmap = generic_memmap_rw, - .lseek = dev_lseek_default, }; static int sram_probe(struct device_d *dev) diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index f44c6cf..881b5f4 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -462,7 +462,6 @@ .protect = mtd_op_protect, #endif .ioctl = mtd_ioctl, - .lseek = dev_lseek_default, }; static int mtd_partition_set(struct param_d *p, void *priv) diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c index ffaf950..4aef844 100644 --- a/drivers/mtd/mtdoob.c +++ b/drivers/mtd/mtdoob.c @@ -66,7 +66,6 @@ static struct cdev_operations mtd_ops_oob = { .read = mtd_op_read_oob, .ioctl = mtd_ioctl, - .lseek = dev_lseek_default, }; static int add_mtdoob_device(struct mtd_info *mtd, const char *devname, void **priv) diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c index 6e36dc5..f63da7b 100644 --- a/drivers/mtd/mtdraw.c +++ b/drivers/mtd/mtdraw.c @@ -291,7 +291,6 @@ .read = mtdraw_read, .write = mtdraw_write, .erase = mtdraw_erase, - .lseek = dev_lseek_default, }; static int add_mtdraw_device(struct mtd_info *mtd, const char *devname, void **priv) diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c index 012163e..e578d72 100644 --- a/drivers/mtd/nand/nand-bb.c +++ b/drivers/mtd/nand/nand-bb.c @@ -236,17 +236,16 @@ return 0; } -static loff_t nand_bb_lseek(struct cdev *cdev, loff_t __offset) +static int nand_bb_lseek(struct cdev *cdev, loff_t offset) { struct nand_bb *bb = cdev->priv; loff_t raw_pos = 0; - uint32_t offset = __offset; /* lseek only in readonly mode */ if (bb->flags & O_ACCMODE) return -ENOSYS; while (raw_pos < bb->mtd->size) { - off_t now = min(offset, bb->mtd->erasesize); + off_t now = min_t(loff_t, offset, bb->mtd->erasesize); if (mtd_block_isbad(bb->mtd, raw_pos)) { raw_pos += bb->mtd->erasesize; @@ -257,7 +256,7 @@ if (!offset) { bb->offset = raw_pos; - return __offset; + return 0; } } diff --git a/drivers/mtd/ubi/barebox.c b/drivers/mtd/ubi/barebox.c index 65f5456..781061d 100644 --- a/drivers/mtd/ubi/barebox.c +++ b/drivers/mtd/ubi/barebox.c @@ -151,7 +151,7 @@ return 0; } -static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs) +static int ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs) { struct ubi_volume_cdev_priv *priv = cdev->priv; @@ -159,7 +159,7 @@ if (priv->written) return -EINVAL; - return ofs; + return 0; } static int ubi_volume_cdev_truncate(struct cdev *cdev, size_t size) diff --git a/drivers/net/e1000/eeprom.c b/drivers/net/e1000/eeprom.c index 36d818b..5b34e9b 100644 --- a/drivers/net/e1000/eeprom.c +++ b/drivers/net/e1000/eeprom.c @@ -1326,7 +1326,6 @@ static struct cdev_operations e1000_invm_ops = { .read = e1000_invm_cdev_read, .write = e1000_invm_cdev_write, - .lseek = dev_lseek_default, }; static ssize_t e1000_eeprom_cdev_read(struct cdev *cdev, void *buf, @@ -1351,7 +1350,6 @@ static struct cdev_operations e1000_eeprom_ops = { .read = e1000_eeprom_cdev_read, - .lseek = dev_lseek_default, }; static int e1000_mtd_read_or_write(bool read, diff --git a/drivers/net/ksz8864rmn.c b/drivers/net/ksz8864rmn.c index 4a19dd8..85063ff 100644 --- a/drivers/net/ksz8864rmn.c +++ b/drivers/net/ksz8864rmn.c @@ -113,7 +113,6 @@ static struct cdev_operations micrel_switch_ops = { .read = micel_switch_read, .write = micel_switch_write, - .lseek = dev_lseek_default, }; static int micrel_switch_probe(struct device_d *dev) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index e1dd8f0..3480e2f 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -392,7 +392,6 @@ static struct cdev_operations phydev_ops = { .read = phydev_read, .write = phydev_write, - .lseek = dev_lseek_default, }; static void of_set_phy_supported(struct phy_device *phydev) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 63c0f99..6cf98f6 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -85,7 +85,6 @@ static struct cdev_operations nvmem_chrdev_ops = { .read = nvmem_cdev_read, .write = nvmem_cdev_write, - .lseek = dev_lseek_default, }; static int nvmem_register_cdev(struct nvmem_device *nvmem, const char *name) @@ -96,7 +95,6 @@ alias = of_alias_get(dev->device_node); nvmem->cdev.name = xstrdup(alias ?: name); - nvmem->cdev.flags = DEVFS_IS_CHARACTER_DEV; nvmem->cdev.ops = &nvmem_chrdev_ops; nvmem->cdev.dev = &nvmem->dev; nvmem->cdev.size = nvmem->size; diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 72f33a6..2d82bc0 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -228,7 +228,6 @@ .read = mem_read, .write = mem_write, .memmap = generic_memmap_rw, - .lseek = dev_lseek_default, .ioctl = fb_ioctl, .close = fb_close, .flush = fb_op_flush, diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c index 13691d7..6446f4b 100644 --- a/drivers/w1/slaves/w1_ds2431.c +++ b/drivers/w1/slaves/w1_ds2431.c @@ -260,7 +260,6 @@ static struct cdev_operations ds2431_ops = { .read = ds2431_cdev_read, .write = ds2431_cdev_write, - .lseek = dev_lseek_default, }; static int ds2431_probe(struct w1_device *dev) diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index f521a46..b24fb5b 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -159,7 +159,6 @@ static struct cdev_operations ds2433_ops = { .read = ds2433_cdev_read, .write = ds2433_cdev_write, - .lseek = dev_lseek_default, }; static int ds2433_cdev_create(struct w1_device *dev, int size, int id) diff --git a/fs/bpkfs.c b/fs/bpkfs.c index f1db963..655cde0 100644 --- a/fs/bpkfs.c +++ b/fs/bpkfs.c @@ -192,7 +192,7 @@ } } -static loff_t bpkfs_lseek(struct device_d *dev, FILE *file, loff_t pos) +static int bpkfs_lseek(struct device_d *dev, FILE *file, loff_t pos) { struct bpkfs_handle_data *d = file->priv; @@ -201,7 +201,7 @@ d->pos = pos; - return pos; + return 0; } struct somfy_readdir { diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index a3ce354..3cc0fa7 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -166,12 +166,6 @@ return cramfs_read_file(f->f_inode, f->pos, buf, size); } -static loff_t cramfs_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - return f->pos; -} - #if 0 static int cramfs_info (struct device_d *dev) { @@ -491,7 +485,6 @@ static struct fs_driver_d cramfs_driver = { .read = cramfs_read, - .lseek = cramfs_lseek, .drv = { .probe = cramfs_probe, .remove = cramfs_remove, diff --git a/fs/devfs-core.c b/fs/devfs-core.c index f017e1c..2b93a95 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -459,7 +459,6 @@ .read = loop_read, .write = loop_write, .memmap = generic_memmap_rw, - .lseek = dev_lseek_default, }; struct cdev *cdev_create_loop(const char *path, ulong flags, loff_t offset) @@ -512,19 +511,29 @@ free(cdev); } -static void memcpy_sz(void *dst, const void *src, size_t count, int rwsize) +static ssize_t mem_copy(struct device_d *dev, void *dst, const void *src, + resource_size_t count, resource_size_t offset, + unsigned long flags) { + ssize_t size; + int rwsize = flags & O_RWSIZE_MASK; + + if (!dev || dev->num_resources < 1) + return -1; + + count = size = min(count, resource_size(&dev->resource[0]) - offset); + /* no rwsize specification given. Do whatever memcpy likes best */ if (!rwsize) { memcpy(dst, src, count); - return; + goto out; } rwsize = rwsize >> O_RWSIZE_SHIFT; - count /= rwsize; + count = ALIGN_DOWN(count, rwsize); - while (count-- > 0) { + while (count) { switch (rwsize) { case 1: *((u8 *)dst) = *((u8 *)src); @@ -541,41 +550,34 @@ } dst += rwsize; src += rwsize; + count -= rwsize; } +out: + return size; } ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, unsigned long flags) { - unsigned long size; - struct device_d *dev; + struct device_d *dev = cdev->dev; - if (!cdev->dev || cdev->dev->num_resources < 1) + if (!dev) return -1; - dev = cdev->dev; - size = min((resource_size_t)count, - resource_size(&dev->resource[0]) - - (resource_size_t)offset); - memcpy_sz(buf, dev_get_mem_region(dev, 0) + offset, size, flags & O_RWSIZE_MASK); - return size; + return mem_copy(dev, buf, dev_get_mem_region(dev, 0) + offset, + count, offset, flags); } EXPORT_SYMBOL(mem_read); -ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, - unsigned long flags) +ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, + loff_t offset, unsigned long flags) { - unsigned long size; - struct device_d *dev; + struct device_d *dev = cdev->dev; - if (!cdev->dev || cdev->dev->num_resources < 1) + if (!dev) return -1; - dev = cdev->dev; - size = min((resource_size_t)count, - resource_size(&dev->resource[0]) - - (resource_size_t)offset); - memcpy_sz(dev_get_mem_region(dev, 0) + offset, buf, size, flags & O_RWSIZE_MASK); - return size; + return mem_copy(dev, dev_get_mem_region(dev, 0) + offset, buf, + count, offset, flags); } EXPORT_SYMBOL(mem_write); diff --git a/fs/devfs.c b/fs/devfs.c index 81ae2c2..a7400df 100644 --- a/fs/devfs.c +++ b/fs/devfs.c @@ -57,18 +57,18 @@ return cdev_write(cdev, buf, size, f->pos, f->flags); } -static loff_t devfs_lseek(struct device_d *_dev, FILE *f, loff_t pos) +static int devfs_lseek(struct device_d *_dev, FILE *f, loff_t pos) { struct cdev *cdev = f->priv; - loff_t ret = -1; + int ret; - if (cdev->ops->lseek) + if (cdev->ops->lseek) { ret = cdev->ops->lseek(cdev, pos + cdev->offset); + if (ret < 0) + return ret; + } - if (ret != -1) - f->pos = pos; - - return ret - cdev->offset; + return 0; } static int devfs_erase(struct device_d *_dev, FILE *f, loff_t count, loff_t offset) @@ -168,18 +168,14 @@ return cdev_ioctl(cdev, request, buf); } -static int devfs_truncate(struct device_d *dev, FILE *f, ulong size) +static int devfs_truncate(struct device_d *dev, FILE *f, loff_t size) { struct cdev *cdev = f->priv; if (cdev->ops->truncate) return cdev->ops->truncate(cdev, size); - if (f->fsdev->dev.num_resources < 1) - return -ENOSPC; - if (size > resource_size(&f->fsdev->dev.resource[0])) - return -ENOSPC; - return 0; + return -EPERM; } static struct inode *devfs_alloc_inode(struct super_block *sb) diff --git a/fs/efi.c b/fs/efi.c index 692556b..81c1ffe 100644 --- a/fs/efi.c +++ b/fs/efi.c @@ -292,22 +292,20 @@ return bufsize; } -static loff_t efifs_lseek(struct device_d *dev, FILE *f, loff_t pos) +static int efifs_lseek(struct device_d *dev, FILE *f, loff_t pos) { struct efifs_file *ufile = f->priv; efi_status_t efiret; - f->pos = pos; - efiret = ufile->entry->set_position(ufile->entry, pos); if (EFI_ERROR(efiret)) { return -efi_errno(efiret); } - return f->pos; + return 0; } -static int efifs_truncate(struct device_d *dev, FILE *f, unsigned long size) +static int efifs_truncate(struct device_d *dev, FILE *f, loff_t size) { struct efifs_file *ufile = f->priv; efi_status_t efiret; diff --git a/fs/efivarfs.c b/fs/efivarfs.c index bf7351e..a911eac 100644 --- a/fs/efivarfs.c +++ b/fs/efivarfs.c @@ -288,7 +288,7 @@ return insize; } -static int efivarfs_truncate(struct device_d *dev, FILE *f, ulong size) +static int efivarfs_truncate(struct device_d *dev, FILE *f, loff_t size) { struct efivars_file *efile = f->priv; efi_status_t efiret; @@ -307,13 +307,6 @@ return 0; } -static loff_t efivarfs_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - - return f->pos; -} - static DIR *efivarfs_opendir(struct device_d *dev, const char *pathname) { struct efivarfs_priv *priv = dev->priv; @@ -437,7 +430,6 @@ .read = efivarfs_read, .write = efivarfs_write, .truncate = efivarfs_truncate, - .lseek = efivarfs_lseek, .opendir = efivarfs_opendir, .readdir = efivarfs_readdir, .closedir = efivarfs_closedir, diff --git a/fs/ext4/ext_barebox.c b/fs/ext4/ext_barebox.c index 1e7da2a..82d4c58 100644 --- a/fs/ext4/ext_barebox.c +++ b/fs/ext4/ext_barebox.c @@ -59,13 +59,6 @@ return ext4fs_read_file(node, f->pos, insize, buf); } -static loff_t ext_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - - return f->pos; -} - static struct inode *ext_alloc_inode(struct super_block *sb) { struct fs_device_d *fsdev = container_of(sb, struct fs_device_d, sb); @@ -304,7 +297,6 @@ static struct fs_driver_d ext_driver = { .read = ext_read, - .lseek = ext_lseek, .type = filetype_ext, .flags = 0, .drv = { diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 49cd78f..394c75f 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -177,7 +177,7 @@ return outsize; } -static int fat_truncate(struct device_d *dev, FILE *f, ulong size) +static int fat_truncate(struct device_d *dev, FILE *f, loff_t size) { FIL *f_file = f->priv; unsigned long lastofs; @@ -268,7 +268,7 @@ return outsize; } -static loff_t fat_lseek(struct device_d *dev, FILE *f, loff_t pos) +static int fat_lseek(struct device_d *dev, FILE *f, loff_t pos) { FIL *f_file = f->priv; int ret; @@ -277,8 +277,7 @@ if (ret) return ret; - f->pos = pos; - return pos; + return 0; } static DIR* fat_opendir(struct device_d *dev, const char *pathname) diff --git a/fs/fs.c b/fs/fs.c index a304bf1..1f6b3d3 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -213,11 +213,16 @@ f = &files[fd]; + if (f->size == FILE_SIZE_STREAM) + return 0; + fsdrv = f->fsdev->driver; ret = fsdrv->truncate(&f->fsdev->dev, f, length); - if (ret) + if (ret) { + errno = -ret; return ret; + } f->size = length; @@ -413,41 +418,36 @@ f = &files[fildes]; fsdrv = f->fsdev->driver; - if (!fsdrv->lseek) { - ret = -ENOSYS; - goto out; - } ret = -EINVAL; switch (whence) { case SEEK_SET: - if (f->size != FILE_SIZE_STREAM && offset > f->size) - goto out; - if (IS_ERR_VALUE(offset)) - goto out; - pos = offset; + pos = 0; break; case SEEK_CUR: - if (f->size != FILE_SIZE_STREAM && offset + f->pos > f->size) - goto out; - pos = f->pos + offset; + pos = f->pos; break; case SEEK_END: - if (offset > 0) - goto out; - pos = f->size + offset; + pos = f->size; break; default: goto out; } - pos = fsdrv->lseek(&f->fsdev->dev, f, pos); - if (IS_ERR_VALUE(pos)) { - errno = -pos; - return -1; + pos += offset; + + if (f->size != FILE_SIZE_STREAM && (pos < 0 || pos > f->size)) + goto out; + + if (fsdrv->lseek) { + ret = fsdrv->lseek(&f->fsdev->dev, f, pos); + if (ret < 0) + goto out; } + f->pos = pos; + return pos; out: diff --git a/fs/nfs.c b/fs/nfs.c index d7f1566..43476d1 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -928,7 +928,7 @@ nfs_len = len; } -static int nfs_truncate(struct device_d *dev, FILE *f, ulong size) +static int nfs_truncate(struct device_d *dev, FILE *f, loff_t size) { return -ENOSYS; } @@ -1060,14 +1060,13 @@ return kfifo_get(priv->fifo, buf, insize); } -static loff_t nfs_lseek(struct device_d *dev, FILE *file, loff_t pos) +static int nfs_lseek(struct device_d *dev, FILE *file, loff_t pos) { struct file_priv *priv = file->priv; - file->pos = pos; kfifo_reset(priv->fifo); - return file->pos; + return 0; } static int nfs_iterate(struct file *file, struct dir_context *ctx) diff --git a/fs/omap4_usbbootfs.c b/fs/omap4_usbbootfs.c index b35f411..169cde7 100644 --- a/fs/omap4_usbbootfs.c +++ b/fs/omap4_usbbootfs.c @@ -57,7 +57,7 @@ return -ENOSYS; } -static int omap4_usbbootfs_truncate(struct device_d *dev, FILE *f, ulong size) +static int omap4_usbbootfs_truncate(struct device_d *dev, FILE *f, loff_t size) { return -ENOSYS; } @@ -149,12 +149,6 @@ return size; } -static loff_t omap4_usbbootfs_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - return pos; -} - static DIR *omap4_usbbootfs_opendir(struct device_d *dev, const char *pathname) { return NULL; @@ -191,7 +185,6 @@ .open = omap4_usbbootfs_open, .close = omap4_usbbootfs_close, .read = omap4_usbbootfs_read, - .lseek = omap4_usbbootfs_lseek, .opendir = omap4_usbbootfs_opendir, .stat = omap4_usbbootfs_stat, /* diff --git a/fs/pstore/fs.c b/fs/pstore/fs.c index a879a68..9a7e0b5 100644 --- a/fs/pstore/fs.c +++ b/fs/pstore/fs.c @@ -172,13 +172,13 @@ return insize; } -static loff_t pstore_lseek(struct device_d *dev, FILE *file, loff_t pos) +static int pstore_lseek(struct device_d *dev, FILE *file, loff_t pos) { struct pstore_private *d = file->priv; d->pos = pos; - return pos; + return 0; } static DIR *pstore_opendir(struct device_d *dev, const char *pathname) diff --git a/fs/ramfs.c b/fs/ramfs.c index 84ecfa0..4fba40d 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -347,13 +347,7 @@ return insize; } -static loff_t ramfs_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - return f->pos; -} - -static int ramfs_truncate(struct device_d *dev, FILE *f, ulong size) +static int ramfs_truncate(struct device_d *dev, FILE *f, loff_t size) { struct inode *inode = f->f_inode; struct ramfs_inode *node = to_ramfs_inode(inode); @@ -448,7 +442,6 @@ static struct fs_driver_d ramfs_driver = { .read = ramfs_read, .write = ramfs_write, - .lseek = ramfs_lseek, .truncate = ramfs_truncate, .flags = FS_DRIVER_NO_DEV, .drv = { diff --git a/fs/ratpfs.c b/fs/ratpfs.c index 902289b..b6857c6 100644 --- a/fs/ratpfs.c +++ b/fs/ratpfs.c @@ -77,7 +77,7 @@ } static int ratpfs_truncate(struct device_d __always_unused *dev, - FILE *f, ulong size) + FILE *f, loff_t size) { int len_tx = 1 /* type */ + 4 /* handle */ @@ -284,14 +284,6 @@ 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) { @@ -450,7 +442,6 @@ .open = ratpfs_open, .close = ratpfs_close, .read = ratpfs_read, - .lseek = ratpfs_lseek, .opendir = ratpfs_opendir, .readdir = ratpfs_readdir, .closedir = ratpfs_closedir, diff --git a/fs/smhfs.c b/fs/smhfs.c index f1b6d6b..2e99b05 100644 --- a/fs/smhfs.c +++ b/fs/smhfs.c @@ -56,7 +56,7 @@ static int smhfs_truncate(struct device_d __always_unused *dev, FILE __always_unused *f, - ulong __always_unused size) + loff_t __always_unused size) { return 0; } @@ -109,15 +109,13 @@ return -semihosting_errno(); } -static loff_t smhfs_lseek(struct device_d __always_unused *dev, +static int smhfs_lseek(struct device_d __always_unused *dev, FILE *f, loff_t pos) { - if (semihosting_seek(file_to_fd(f), pos)) { + if (semihosting_seek(file_to_fd(f), pos)) return -semihosting_errno(); - } else { - f->pos = pos; - return f->pos; - } + + return 0; } static DIR* smhfs_opendir(struct device_d __always_unused *dev, diff --git a/fs/squashfs/squashfs.c b/fs/squashfs/squashfs.c index d9049b7..38aff6d 100644 --- a/fs/squashfs/squashfs.c +++ b/fs/squashfs/squashfs.c @@ -231,13 +231,6 @@ return insize; } -static loff_t squashfs_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - - return pos; -} - struct squashfs_dir { struct file file; struct dentry dentry; @@ -253,7 +246,6 @@ .open = squashfs_open, .close = squashfs_close, .read = squashfs_read, - .lseek = squashfs_lseek, .type = filetype_squashfs, .drv = { .probe = squashfs_probe, diff --git a/fs/tftp.c b/fs/tftp.c index 1b50ba8..4329327 100644 --- a/fs/tftp.c +++ b/fs/tftp.c @@ -93,7 +93,7 @@ IPaddr_t server; }; -static int tftp_truncate(struct device_d *dev, FILE *f, ulong size) +static int tftp_truncate(struct device_d *dev, FILE *f, loff_t size) { return 0; } @@ -573,15 +573,17 @@ return outsize; } -static loff_t tftp_lseek(struct device_d *dev, FILE *f, loff_t pos) +static int tftp_lseek(struct device_d *dev, FILE *f, loff_t pos) { /* We cannot seek backwards without reloading or caching the file */ - if (pos >= f->pos) { - loff_t ret; + loff_t f_pos = f->pos; + + if (pos >= f_pos) { + int ret = 0; char *buf = xmalloc(1024); - while (pos > f->pos) { - size_t len = min_t(size_t, 1024, pos - f->pos); + while (pos > f_pos) { + size_t len = min_t(size_t, 1024, pos - f_pos); ret = tftp_read(dev, f, buf, len); @@ -591,14 +593,21 @@ if (ret < 0) goto out_free; - f->pos += ret; + f_pos += ret; } - ret = pos; - out_free: free(buf); - return ret; + if (ret < 0) { + /* + * Update f->pos even if the overall request + * failed since we can't move backwards + */ + f->pos = f_pos; + return ret; + } + + return 0; } return -ENOSYS; diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 7545dd4..494b1f2 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -394,13 +394,6 @@ return insize; } -static loff_t ubifs_lseek(struct device_d *dev, FILE *f, loff_t pos) -{ - f->pos = pos; - - return pos; -} - static void ubifs_set_rootarg(struct ubifs_priv *priv, struct fs_device_d *fsdev) { struct ubi_volume_info vi = {}; @@ -477,7 +470,6 @@ .open = ubifs_open, .close = ubifs_close, .read = ubifs_read, - .lseek = ubifs_lseek, .type = filetype_ubifs, .flags = 0, .drv = { diff --git a/fs/uimagefs.c b/fs/uimagefs.c index c120944..e5ada82 100644 --- a/fs/uimagefs.c +++ b/fs/uimagefs.c @@ -116,7 +116,7 @@ } } -static loff_t uimagefs_lseek(struct device_d *dev, FILE *file, loff_t pos) +static int uimagefs_lseek(struct device_d *dev, FILE *file, loff_t pos) { struct uimagefs_handle_data *d = file->priv; @@ -125,7 +125,7 @@ d->pos = pos; - return pos; + return 0; } static DIR *uimagefs_opendir(struct device_d *dev, const char *pathname) diff --git a/include/driver.h b/include/driver.h index 7da184d..a8e046e 100644 --- a/include/driver.h +++ b/include/driver.h @@ -360,11 +360,6 @@ int generic_memmap_ro(struct cdev *dev, void **map, int flags); int generic_memmap_rw(struct cdev *dev, void **map, int flags); -static inline loff_t dev_lseek_default(struct cdev *cdev, loff_t ofs) -{ - return ofs; -} - static inline int dev_open_default(struct device_d *dev, struct filep *f) { return 0; @@ -439,7 +434,7 @@ ssize_t (*write)(struct cdev*, const void* buf, size_t count, loff_t offset, ulong flags); int (*ioctl)(struct cdev*, int, void *); - loff_t (*lseek)(struct cdev*, loff_t); + int (*lseek)(struct cdev*, loff_t); int (*open)(struct cdev*, unsigned long flags); int (*close)(struct cdev*); int (*flush)(struct cdev*); diff --git a/include/fs.h b/include/fs.h index f1514af..38debfc 100644 --- a/include/fs.h +++ b/include/fs.h @@ -46,14 +46,14 @@ int (*unlink)(struct device_d *dev, const char *pathname); /* Truncate a file to given size */ - int (*truncate)(struct device_d *dev, FILE *f, ulong size); + int (*truncate)(struct device_d *dev, FILE *f, loff_t size); int (*open)(struct device_d *dev, FILE *f, const char *pathname); int (*close)(struct device_d *dev, FILE *f); int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size); int (*write)(struct device_d *dev, FILE *f, const void *buf, size_t size); int (*flush)(struct device_d *dev, FILE *f); - loff_t (*lseek)(struct device_d *dev, FILE *f, loff_t pos); + int (*lseek)(struct device_d *dev, FILE *f, loff_t pos); int (*ioctl)(struct device_d *dev, FILE *f, int request, void *buf); int (*erase)(struct device_d *dev, FILE *f, loff_t count, diff --git a/lib/libfile.c b/lib/libfile.c index 8f2aed2..9a223d2 100644 --- a/lib/libfile.c +++ b/lib/libfile.c @@ -556,8 +556,7 @@ } } - ret = lseek(fd, pos, SEEK_SET); - if (ret == -1) { + if (lseek(fd, pos, SEEK_SET) != pos) { perror("lseek"); close(fd); return -errno; diff --git a/lib/misc.c b/lib/misc.c index 1d20e1b..cd420a5 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -23,6 +23,7 @@ #include #include #include +#include /* * Like simple_strtoull() but handles an optional G, M, K or k @@ -129,3 +130,44 @@ return 0; } EXPORT_SYMBOL(parse_area_spec); + +/* + * Common function for parsing options for the 'md', 'mw', 'memcpy', 'memcmp' + * commands. + */ +int mem_parse_options(int argc, char *argv[], char *optstr, int *mode, + char **sourcefile, char **destfile, int *swab) +{ + int opt; + + while((opt = getopt(argc, argv, optstr)) > 0) { + switch(opt) { + case 'b': + *mode = O_RWSIZE_1; + break; + case 'w': + *mode = O_RWSIZE_2; + break; + case 'l': + *mode = O_RWSIZE_4; + break; + case 'q': + *mode = O_RWSIZE_8; + break; + case 's': + *sourcefile = optarg; + break; + case 'd': + *destfile = optarg; + break; + case 'x': + *swab = 1; + break; + default: + return -EINVAL; + } + } + + return 0; +} +