tbm-mcu/source/shell/flash.c

263 lines
4.8 KiB
C
Raw Normal View History

2017-03-12 00:33:09 +00:00
#include <ctype.h>
#include <inttypes.h>
2017-03-12 00:33:09 +00:00
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
2017-07-24 17:57:13 +02:00
#include <console.h>
2017-03-12 00:33:09 +00:00
#include <flash.h>
#include <macros.h>
#include <shell.h>
struct flash_dev *flash = NULL;
2017-03-12 00:33:09 +00:00
static void parse_hex(struct console *con, char *buf, size_t len)
2017-03-12 00:33:09 +00:00
{
size_t i;
char s[3];
for (i = 0; i < len; ++i) {
memset(s, '\0', 3);
while (console_getc(s + 0, con) && !isxdigit(s[0]));
while (console_getc(s + 1, con) && !isxdigit(s[1]));
2017-03-12 00:33:09 +00:00
*buf++ = strtoul(s, NULL, 16);
}
}
2017-07-24 17:57:13 +02:00
static void print_hex_ascii(FILE *fp, uint32_t offset, const char *buf, size_t len)
2017-03-12 00:33:09 +00:00
{
size_t n, i;
uint8_t c;
for (; len; buf += n, len -= n) {
n = min(len, 16);
2017-06-16 17:13:45 +02:00
2017-07-24 17:57:13 +02:00
fprintf(fp, "%08" PRIx32 ": ", offset);
2017-06-16 17:13:45 +02:00
2017-03-12 00:33:09 +00:00
for (i = 0; i < 16; ++i) {
c = (i < n) ? buf[i] : 0;
2017-07-24 17:57:13 +02:00
fprintf(fp, "%02x", c);
2017-03-12 00:33:09 +00:00
}
2017-07-24 17:57:13 +02:00
fprintf(fp, " ");
2017-03-12 00:33:09 +00:00
for (i = 0; i < 16; ++i) {
c = (i < n) ? buf[i] : 0;
2017-07-24 17:57:13 +02:00
fprintf(fp, "%c", isalnum(c) ? c : '.');
2017-03-12 00:33:09 +00:00
}
2017-07-24 17:57:13 +02:00
fprintf(fp, "\n");
2017-06-16 17:13:45 +02:00
offset += n;
2017-03-12 00:33:09 +00:00
}
}
2017-07-27 11:54:31 +02:00
static int do_flash_probe(struct console *con, size_t argc, const char **argv)
2017-03-12 00:33:09 +00:00
{
(void)argv;
(void)argc;
2017-03-12 00:33:09 +00:00
if (flash) {
flash_release(flash);
flash = NULL;
}
if (!(flash = flash_probe())) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "error: unable to probe the flash device.\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
}
2017-07-27 11:54:31 +02:00
static int do_flash_release(struct console *con, size_t argc, const char **argv)
{
(void)argv;
(void)argc;
if (!flash) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "no flash device currently active.\n");
2017-07-27 11:54:31 +02:00
return -1;
}
flash_release(flash);
flash = NULL;
2017-07-27 11:54:31 +02:00
return 0;
}
2017-07-27 11:54:31 +02:00
static int do_flash_info(struct console *con, size_t argc, const char **argv)
{
size_t size, capacity;
(void)argv;
(void)argc;
if (!flash) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "error: no flash device probed.\n");
2017-07-27 11:54:31 +02:00
return -1;
}
size = flash_get_size(flash);
capacity = flash_get_capacity(flash);
2017-07-24 17:57:13 +02:00
fprintf(con->fp, " size: %" PRSZu "/%" PRSZu " bytes (%" PRSZu "%% usage)\n",
size, capacity, 100 * size / capacity);
2017-07-27 11:54:31 +02:00
return 0;
}
2017-07-27 11:54:31 +02:00
static int do_flash_read(struct console *con, size_t argc, const char **argv)
2017-03-12 00:33:09 +00:00
{
char buf[256];
2017-03-12 00:33:09 +00:00
size_t addr, len, nbytes;
if (argc < 2) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "usage: flash read <addr> <len>\n");
2017-07-27 11:54:31 +02:00
return -1;
2017-03-12 00:33:09 +00:00
}
if (!flash) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "error: no flash device probed.\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
addr = strtoull(argv[0], NULL, 0);
2017-03-12 00:33:09 +00:00
if (errno == EINVAL || errno == ERANGE) {
fprintf(con->fp, "error: expected integer value for addr\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
len = strtoull(argv[1], NULL, 0);
2017-03-12 00:33:09 +00:00
if (errno == EINVAL || errno == ERANGE) {
fprintf(con->fp, "error: expected integer value for len\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
if (!len)
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
while (len) {
nbytes = min(len, 256);
flash_read(flash, addr, buf, nbytes);
2017-07-24 17:57:13 +02:00
print_hex_ascii(con->fp, addr, buf, nbytes);
2017-03-12 00:33:09 +00:00
addr += nbytes;
len -= nbytes;
}
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
}
2017-07-27 11:54:31 +02:00
static int do_flash_write(struct console *con, size_t argc, const char **argv)
2017-03-12 00:33:09 +00:00
{
char buf[256];
2017-03-12 00:33:09 +00:00
size_t addr, len, nbytes;
if (argc < 2) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "usage: flash write <addr> <len>\n");
2017-07-27 11:54:31 +02:00
return -1;
2017-03-12 00:33:09 +00:00
}
if (!flash) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "error: no flash device probed.\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
addr = strtoull(argv[0], NULL, 0);
2017-03-12 00:33:09 +00:00
if (errno == EINVAL || errno == ERANGE) {
fprintf(con->fp, "error: expected integer value for addr\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
len = strtoull(argv[1], NULL, 0);
2017-03-12 00:33:09 +00:00
if (errno == EINVAL || errno == ERANGE) {
fprintf(con->fp, "error: expected integer value for len\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
if (!len)
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
while (len) {
2017-03-17 13:37:30 +00:00
nbytes = min(len, 256);
parse_hex(con, buf, nbytes);
2017-03-12 00:33:09 +00:00
printf("\n");
2017-07-24 17:57:13 +02:00
print_hex_ascii(con->fp, addr, buf, nbytes);
2017-03-12 00:33:09 +00:00
flash_write(flash, addr, buf, nbytes);
addr += nbytes;
len -= nbytes;
}
2017-07-24 17:57:13 +02:00
flash_sync(flash);
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
}
2017-07-27 11:54:31 +02:00
static int do_flash_erase(struct console *con, size_t argc, const char **argv)
2017-03-12 00:33:09 +00:00
{
size_t addr, len;
if (argc < 2) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "usage: flash erase <addr> <len>\n");
2017-07-27 11:54:31 +02:00
return -1;
2017-03-12 00:33:09 +00:00
}
if (!flash) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "error: no flash device probed.\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
addr = strtoull(argv[0], NULL, 0);
2017-03-12 00:33:09 +00:00
if (errno == EINVAL || errno == ERANGE) {
fprintf(con->fp, "error: expected integer value for addr\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
len = strtoull(argv[1], NULL, 0);
2017-03-12 00:33:09 +00:00
if (errno == EINVAL || errno == ERANGE) {
fprintf(con->fp, "error: expected integer value for len\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-03-12 00:33:09 +00:00
if (!len)
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
flash_erase(flash, addr, len);
2017-07-27 11:54:31 +02:00
return 0;
2017-03-12 00:33:09 +00:00
}
static struct cmd flash_cmds[] = {
{ "probe", NULL, do_flash_probe },
{ "release", NULL, do_flash_release },
{ "info", NULL, do_flash_info },
{ "read", NULL, do_flash_read },
{ "write", NULL, do_flash_write },
{ "erase", NULL, do_flash_erase },
{ NULL, NULL, NULL },
};
2017-07-27 11:54:31 +02:00
int do_flash_cmd(struct console *con, size_t argc, const char **argv)
2017-03-12 00:33:09 +00:00
{
if (argc < 1) {
2017-07-24 17:57:13 +02:00
fprintf(con->fp, "usage: flash <command>\n");
2017-07-27 11:54:31 +02:00
return -1;
}
2017-07-27 11:54:31 +02:00
return cmd_exec(flash_cmds, con, argc, argv);
2017-03-12 00:33:09 +00:00
}