diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-04-17 11:13:55 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-04-17 13:37:14 +0200 |
commit | 67c6eeda9e5dea544cdeddb666f141c8467ab8d4 (patch) | |
tree | 922204f7ce006e731fb8eff27a69f460749b3e89 /commands/mm.c | |
parent | e10c1845b2351099c2097fe29629983002b63a37 (diff) | |
download | barebox-67c6eeda9e5dea544cdeddb666f141c8467ab8d4.tar.gz barebox-67c6eeda9e5dea544cdeddb666f141c8467ab8d4.tar.xz |
Add memory modify command (mm)
As of now we have no way to manipulate individual bits of registers on the
command line. This introduces a memory modify command which allows this. It
has the syntax:
mm [OPTIONS] <adr> <val> <mask>
With [OPTIONS] being the usual memory command options (-b, -w, -l, -d <file>).
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'commands/mm.c')
-rw-r--r-- | commands/mm.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/commands/mm.c b/commands/mm.c new file mode 100644 index 0000000000..f51fd27cb0 --- /dev/null +++ b/commands/mm.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, 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. + * + */ + +#include <common.h> +#include <command.h> +#include <init.h> +#include <driver.h> +#include <malloc.h> +#include <errno.h> +#include <fs.h> +#include <fcntl.h> +#include <getopt.h> +#include <linux/stat.h> +#include <xfuncs.h> + +static int do_mem_mm(int argc, char *argv[]) +{ + int ret = 0; + int fd; + char *filename = "/dev/mem"; + int mode = O_RWSIZE_4; + loff_t adr; + int swab = 0; + u8 val8; + u16 val16; + u32 val32; + u32 value, mask; + + if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &filename, + &swab) < 0) + return 1; + + if (optind + 2 >= argc) + return COMMAND_ERROR_USAGE; + + adr = strtoull_suffix(argv[optind++], NULL, 0); + value = simple_strtoul(argv[optind++], NULL, 0); + mask = simple_strtoul(argv[optind++], NULL, 0); + + fd = open_and_lseek(filename, mode | O_RDWR, adr); + if (fd < 0) + return 1; + + switch (mode) { + case O_RWSIZE_1: + ret = pread(fd, &val8, 1, adr); + if (ret < 0) + goto out_read; + val8 &= ~mask; + val8 |= (value & mask); + ret = pwrite(fd, &val8, 1, adr); + if (ret < 0) + goto out_write; + break; + case O_RWSIZE_2: + ret = pread(fd, &val16, 2, adr); + if (ret < 0) + goto out_read; + val16 &= ~mask; + val16 |= (value & mask); + ret = pwrite(fd, &val16, 2, adr); + if (ret < 0) + goto out_write; + break; + case O_RWSIZE_4: + if (ret < 0) + goto out_read; + ret = pread(fd, &val32, 4, adr); + val32 &= ~mask; + val32 |= (value & mask); + ret = pwrite(fd, &val32, 4, adr); + if (ret < 0) + goto out_write; + break; + } + + close(fd); + + return 0; + +out_read: + perror("read"); + close(fd); + return 1; + +out_write: + perror("write"); + close(fd); + return 1; +} + +static const __maybe_unused char cmd_mm_help[] = +"Usage: mm [OPTIONS] <adr> <val> <mask>\n" +"set/clear bits specified with <mask> in <adr> to <value>\n" +"options:\n" +" -b, -w, -l use byte, halfword, or word accesses\n" +" -d <file> write file (default /dev/mem)\n"; + +BAREBOX_CMD_START(mm) + .cmd = do_mem_mm, + .usage = "memory modify write with mask", + BAREBOX_CMD_HELP(cmd_mm_help) +BAREBOX_CMD_END |