parent
422ef6ae51
commit
eb41dd93db
@ -0,0 +1,81 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include <shell.h> |
||||||
|
|
||||||
|
struct cmd main_cmds[] = { |
||||||
|
{ "flash", do_flash_cmd }, |
||||||
|
{ NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
static char *prompt(const char *prefix) |
||||||
|
{ |
||||||
|
char *alloc, *line, *s; |
||||||
|
size_t nbytes = 0, nalloc_bytes = 16; |
||||||
|
char c; |
||||||
|
|
||||||
|
printf(prefix); |
||||||
|
|
||||||
|
if (!(line = malloc(nalloc_bytes))) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
s = line; |
||||||
|
|
||||||
|
while ((c = getchar()) && c != '\n') { |
||||||
|
putchar(c); |
||||||
|
|
||||||
|
if (nbytes + 1 >= nalloc_bytes) { |
||||||
|
nalloc_bytes *= 2; |
||||||
|
|
||||||
|
if (!(alloc = realloc(line, nalloc_bytes))) |
||||||
|
goto err_free_line; |
||||||
|
|
||||||
|
line = alloc; |
||||||
|
} |
||||||
|
|
||||||
|
*s++ = c; |
||||||
|
nbytes++; |
||||||
|
} |
||||||
|
|
||||||
|
printf("\n"); |
||||||
|
*s = '\0'; |
||||||
|
|
||||||
|
return line; |
||||||
|
|
||||||
|
err_free_line: |
||||||
|
free(line); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
void cmd_exec(struct cmd *cmds, const char *line) |
||||||
|
{ |
||||||
|
struct cmd *cmd; |
||||||
|
const char *args; |
||||||
|
char *key; |
||||||
|
size_t n; |
||||||
|
|
||||||
|
n = strcspn(line, " \n"); |
||||||
|
key = strndup(line, n); |
||||||
|
|
||||||
|
args = line + n; |
||||||
|
args += strspn(args, " \n"); |
||||||
|
|
||||||
|
for (cmd = cmds; cmd->key; ++cmd) { |
||||||
|
if (strcmp(cmd->key, key) == 0) { |
||||||
|
cmd->exec(args); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void cmd_loop(const char *show) |
||||||
|
{ |
||||||
|
char *line; |
||||||
|
|
||||||
|
while (1) { |
||||||
|
line = prompt(show); |
||||||
|
cmd_exec(main_cmds, line); |
||||||
|
free(line); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,210 @@ |
|||||||
|
#include <ctype.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include <errno.h> |
||||||
|
|
||||||
|
#include <flash.h> |
||||||
|
#include <macros.h> |
||||||
|
#include <shell.h> |
||||||
|
|
||||||
|
static void do_flash_probe(const char *s); |
||||||
|
static void do_flash_read(const char *s); |
||||||
|
static void do_flash_write(const char *s); |
||||||
|
static void do_flash_erase(const char *s); |
||||||
|
|
||||||
|
static struct cmd flash_cmds[] = { |
||||||
|
{ "probe", do_flash_probe }, |
||||||
|
{ "read", do_flash_read }, |
||||||
|
{ "write", do_flash_write }, |
||||||
|
{ "erase", do_flash_erase }, |
||||||
|
{ NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
static struct flash_dev *flash = NULL; |
||||||
|
|
||||||
|
/* TODO: implement a parser for hex arrays that is more user-friendly.
|
||||||
|
* Also implement dry runs for programmers. */ |
||||||
|
static void parse_hex(FILE *fp, char *buf, size_t len) |
||||||
|
{ |
||||||
|
size_t i; |
||||||
|
char s[3]; |
||||||
|
|
||||||
|
for (i = 0; i < len; ++i) { |
||||||
|
memset(s, '\0', 3); |
||||||
|
|
||||||
|
while ((s[0] = getc(fp)) && !isxdigit(s[0])) |
||||||
|
putchar(s[0]); |
||||||
|
|
||||||
|
putchar(s[0]); |
||||||
|
|
||||||
|
while ((s[1] = getc(fp)) && !isxdigit(s[1])) |
||||||
|
putchar(s[1]); |
||||||
|
|
||||||
|
putchar(s[1]); |
||||||
|
|
||||||
|
*buf++ = strtoul(s, NULL, 16); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void print_hex_ascii(const char *buf, size_t len) |
||||||
|
{ |
||||||
|
size_t n, i; |
||||||
|
uint8_t c; |
||||||
|
|
||||||
|
for (; len; buf += n, len -= n) { |
||||||
|
n = min(len, 16); |
||||||
|
|
||||||
|
for (i = 0; i < 16; ++i) { |
||||||
|
c = (i < n) ? buf[i] : 0; |
||||||
|
printf("%x", c); |
||||||
|
} |
||||||
|
|
||||||
|
printf(" "); |
||||||
|
|
||||||
|
for (i = 0; i < 16; ++i) { |
||||||
|
c = (i < n) ? buf[i] : 0; |
||||||
|
printf("%c", isalnum(c) ? c : '.'); |
||||||
|
} |
||||||
|
|
||||||
|
printf("\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void do_flash_probe(const char *s) |
||||||
|
{ |
||||||
|
(void)s; |
||||||
|
|
||||||
|
flash = flash_probe(); |
||||||
|
} |
||||||
|
|
||||||
|
static void do_flash_read(const char *s) |
||||||
|
{ |
||||||
|
char buf[256], *end = NULL; |
||||||
|
size_t addr, len, nbytes; |
||||||
|
|
||||||
|
if (!flash) { |
||||||
|
fprintf(stderr, "error: no flash device probed.\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (strncmp(s, "0x", 2) == 0) |
||||||
|
s += 2; |
||||||
|
|
||||||
|
addr = strtoull(s, &end, 16); |
||||||
|
s = end; |
||||||
|
|
||||||
|
if (errno == EINVAL || errno == ERANGE) |
||||||
|
return; |
||||||
|
|
||||||
|
s += strspn(s, " \n"); |
||||||
|
|
||||||
|
if (strncmp(s, "0x", 2) == 0) |
||||||
|
s += 2; |
||||||
|
|
||||||
|
len = strtoull(s, &end, 16); |
||||||
|
s = end; |
||||||
|
|
||||||
|
if (errno == EINVAL || errno == ERANGE) |
||||||
|
return; |
||||||
|
|
||||||
|
if (!len) |
||||||
|
return; |
||||||
|
|
||||||
|
while (len) { |
||||||
|
nbytes = min(len, 256); |
||||||
|
flash_read(flash, addr, buf, nbytes); |
||||||
|
print_hex_ascii(buf, nbytes); |
||||||
|
|
||||||
|
addr += nbytes; |
||||||
|
len -= nbytes; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void do_flash_write(const char *s) |
||||||
|
{ |
||||||
|
char buf[256], *end = NULL; |
||||||
|
size_t addr, len, nbytes; |
||||||
|
|
||||||
|
if (!flash) { |
||||||
|
fprintf(stderr, "error: no flash device probed.\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (strncmp(s, "0x", 2) == 0) |
||||||
|
s += 2; |
||||||
|
|
||||||
|
addr = strtoull(s, &end, 16); |
||||||
|
s = end; |
||||||
|
|
||||||
|
if (errno == EINVAL || errno == ERANGE) |
||||||
|
return; |
||||||
|
|
||||||
|
s += strspn(s, " \n"); |
||||||
|
|
||||||
|
if (strncmp(s, "0x", 2) == 0) |
||||||
|
s += 2; |
||||||
|
|
||||||
|
len = strtoull(s, &end, 16); |
||||||
|
s = end; |
||||||
|
|
||||||
|
if (errno == EINVAL || errno == ERANGE) |
||||||
|
return; |
||||||
|
|
||||||
|
if (!len) |
||||||
|
return; |
||||||
|
|
||||||
|
while (len) { |
||||||
|
nbytes = (len > 256) ? 256 : len; |
||||||
|
parse_hex(stdin, buf, nbytes); |
||||||
|
printf("\n"); |
||||||
|
print_hex_ascii(buf, nbytes); |
||||||
|
flash_write(flash, addr, buf, nbytes); |
||||||
|
|
||||||
|
addr += nbytes; |
||||||
|
len -= nbytes; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void do_flash_erase(const char *s) |
||||||
|
{ |
||||||
|
char *end = NULL; |
||||||
|
size_t addr, len; |
||||||
|
|
||||||
|
if (!flash) { |
||||||
|
fprintf(stderr, "error: no flash device probed.\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (strncmp(s, "0x", 2) == 0) |
||||||
|
s += 2; |
||||||
|
|
||||||
|
addr = strtoull(s, &end, 16); |
||||||
|
s = end; |
||||||
|
|
||||||
|
if (errno == EINVAL || errno == ERANGE) |
||||||
|
return; |
||||||
|
|
||||||
|
s += strspn(s, " \n"); |
||||||
|
|
||||||
|
if (strncmp(s, "0x", 2) == 0) |
||||||
|
s += 2; |
||||||
|
|
||||||
|
len = strtoull(s, &end, 16); |
||||||
|
s = end; |
||||||
|
|
||||||
|
if (errno == EINVAL || errno == ERANGE) |
||||||
|
return; |
||||||
|
|
||||||
|
if (!len) |
||||||
|
return; |
||||||
|
|
||||||
|
flash_erase(flash, addr, len); |
||||||
|
} |
||||||
|
|
||||||
|
void do_flash_cmd(const char *line) |
||||||
|
{ |
||||||
|
cmd_exec(flash_cmds, line); |
||||||
|
} |
Loading…
Reference in new issue