shell: separate code
This commit is contained in:
parent
422ef6ae51
commit
eb41dd93db
4 changed files with 296 additions and 2 deletions
3
Makefile
3
Makefile
|
@ -17,7 +17,8 @@ CFLAGS += -Wall -Wundef -Wextra -Wshadow -Wimplicit-function-declaration
|
|||
CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
|
||||
|
||||
obj-y += source/main.o
|
||||
obj-y += source/shell.o
|
||||
obj-y += source/shell/cmd.o
|
||||
obj-y += source/shell/flash.o
|
||||
|
||||
obj-y += source/core/flash.o
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
struct cmd {
|
||||
const char *key;
|
||||
void (* exec)(const char *s);
|
||||
void (* exec)(const char *line);
|
||||
};
|
||||
|
||||
void do_flash_cmd(const char *line);
|
||||
void cmd_exec(struct cmd *cmds, const char *line);
|
||||
void cmd_loop(const char *s);
|
||||
|
|
81
source/shell/cmd.c
Normal file
81
source/shell/cmd.c
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
210
source/shell/flash.c
Normal file
210
source/shell/flash.c
Normal file
|
@ -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…
Add table
Reference in a new issue