This commit add read operation in device sub command. The arbitrary range of address in on-board flash memory is read and the content is dump in stdout. Signed-off-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx> --- efw-downloader/src/meson.build | 1 + efw-downloader/src/op-device-read.c | 104 ++++++++++++++++++++++++++++ efw-downloader/src/subcmd-device.c | 4 ++ efw-downloader/src/subcmds.h | 4 ++ 4 files changed, 113 insertions(+) create mode 100644 efw-downloader/src/op-device-read.c diff --git a/efw-downloader/src/meson.build b/efw-downloader/src/meson.build index 73a0f36..8738d76 100644 --- a/efw-downloader/src/meson.build +++ b/efw-downloader/src/meson.build @@ -18,6 +18,7 @@ sources = [ 'node-dispatcher.c', 'efw-commands.c', 'subcmd-device.c', + 'op-device-read.c', ] headers = [ diff --git a/efw-downloader/src/op-device-read.c b/efw-downloader/src/op-device-read.c new file mode 100644 index 0000000..a1fa0cf --- /dev/null +++ b/efw-downloader/src/op-device-read.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2020 Takashi Sakamoto +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "efw-commands.h" + +static void print_help() +{ + printf("Usage\n" + " efw-downloader device CDEV read OFFSET LENGTH [OPTIONS]\n" + "\n" + "where:\n" + " CDEV: The firewire character device corresponding to the node for proto\n" + " OFFSET: The hexadecimal offset address in on-board flash memory\n" + " LENGTH: The hexadecimal number to read. The value is finally aligned to quadlet.\n" + " OPTIONS:\n" + " --help, -h: Print this help message and exit.\n" + " --debug: Output debug message to stderr\n"); +} + +static int parse_args(int argc, char **argv, size_t *offset, size_t *quads, gboolean *help) +{ + unsigned long val; + char *end; + int i; + + if (argc < 4) + return -EINVAL; + assert(strncmp(argv[3], "read", sizeof("read")) == 0); + + if (argc < 5) + return -EINVAL; + val = strtol(argv[4], &end, 16); + if (*end != '\0') { + printf("Invalid argument for offset address.\n"); + return -EINVAL; + } + *offset = (size_t)val; + + if (argc < 6) + return -EINVAL; + val = strtol(argv[5], &end, 16); + if (*end != '\0') { + printf("Invalid argument for quadlet count.\n"); + return -EINVAL; + } + *quads = (size_t)(val + 3) / 4; + + *help = FALSE; + for (i = 0; i < argc; ++i) { + if (strncmp(argv[i], "--help", sizeof("--help")) == 0 || + strncmp(argv[i], "-h", sizeof("-h")) == 0) { + *help = TRUE; + } + } + + return 0; +} + +void op_device_read(int argc, char **argv, EfwProto *proto, GError **error) +{ + size_t offset; + size_t quads; + guint32 *buf; + gboolean help; + int err; + int i; + + err = parse_args(argc, argv, &offset, &quads, &help); + if (err < 0) { + print_help(); + g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "Invalid arguments"); + return; + } + + if (help) { + print_help(); + return; + } + + buf = g_try_malloc0_n(quads, sizeof(*buf)); + if (buf == NULL) { + fprintf(stderr, "Memory allocation fails.\n"); + g_set_error_literal(error, G_FILE_ERROR, G_FILE_ERROR_NOSPC, "Memory allocation error"); + return; + } + + efw_flash_recursive_read(proto, offset, buf, quads, error); + if (*error != NULL) { + fprintf(stderr, + "Fail to read contents of flash memory: %s %d %s\n", + g_quark_to_string((*error)->domain), (*error)->code, (*error)->message); + goto end; + } + + for (i = 0; i < quads; ++i) + printf(" %08lx: %08x\n", offset + 4 * i, buf[i]); +end: + g_free(buf); +} diff --git a/efw-downloader/src/subcmd-device.c b/efw-downloader/src/subcmd-device.c index 329eef0..a11450c 100644 --- a/efw-downloader/src/subcmd-device.c +++ b/efw-downloader/src/subcmd-device.c @@ -9,6 +9,8 @@ #include "config-rom.h" #include "node-dispatcher.h" +#include "subcmds.h" + #define report_error(error, msg) \ fprintf(stderr, "Fail to %s: %s %d %s\n", \ msg, g_quark_to_string(error->domain), error->code, error->message) @@ -21,6 +23,7 @@ static int print_help() "where:\n" " CDEV: The firewire character device corresponding to the node for transaction\n" " OPERATION:\n" + " read: read from on-board flash memory\n" " help: print this help message\n" " ARGUMENTS:\n" " depending on OPERATION\n" @@ -84,6 +87,7 @@ int subcmd_device(int argc, char **argv) size_t size; void (*op)(int argc, char **argv, EfwProto *proto, GError **error); } *entry, entries[] = { + { "read", sizeof("read"), op_device_read }, }; GError *error = NULL; gboolean debug; diff --git a/efw-downloader/src/subcmds.h b/efw-downloader/src/subcmds.h index f10c420..70cbb5a 100644 --- a/efw-downloader/src/subcmds.h +++ b/efw-downloader/src/subcmds.h @@ -3,6 +3,10 @@ #ifndef __SUBCMDS_H__ #define __SUBCMDS_H__ +#include "efw-proto.h" + int subcmd_device(int argc, char **argv); +void op_device_read(int argc, char **argv, EfwProto *proto, GError **error); + #endif -- 2.25.1