mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-01 08:29:41 +02:00
Made shell reentrant
This commit is contained in:
parent
f3d7b160a7
commit
a80ec957c6
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ endif
|
||||
|
||||
CC = gcc
|
||||
TARGET = jzboot
|
||||
SOURCES = debug.c devmgr.c ingenic.c main.c shell_lex.c usbdev.c shell.c config.c spl_cmdset.c usbboot_cmdset.c
|
||||
SOURCES = debug.c devmgr.c ingenic.c main.c shell_lex.c usbdev.c shell.c shell_builtins.c config.c spl_cmdset.c usbboot_cmdset.c
|
||||
CFLAGS = --std=gnu99 -Wall -Werror -O2 $(shell pkg-config libusb-1.0 --cflags)
|
||||
LIBS += $(shell pkg-config libusb-1.0 --libs)
|
||||
|
||||
|
14
main.c
14
main.c
@ -146,7 +146,9 @@ int main(int argc, char *argv[]) {
|
||||
goto exit_usb;
|
||||
}
|
||||
|
||||
if(shell_init(ingenic) == -1) {
|
||||
shell_context_t *shell = shell_init(ingenic);
|
||||
|
||||
if(shell == NULL) {
|
||||
perror("shell_init");
|
||||
|
||||
ret = 1;
|
||||
@ -155,7 +157,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if(config)
|
||||
if(shell_source(config) == -1) {
|
||||
if(shell_source(shell, config) == -1) {
|
||||
perror("shell_source");
|
||||
|
||||
ret = 1;
|
||||
@ -164,23 +166,23 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if(cmd != NULL) {
|
||||
if(shell_execute(cmd) == -1) {
|
||||
if(shell_execute(shell, cmd) == -1) {
|
||||
perror("shell_execute");
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
} else if(script != NULL) {
|
||||
if(shell_source(script) == -1) {
|
||||
if(shell_source(shell, script) == -1) {
|
||||
perror("shell_source");
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
} else
|
||||
shell_interactive();
|
||||
shell_interactive(shell);
|
||||
|
||||
exit_shell:
|
||||
shell_fini();
|
||||
shell_fini(shell);
|
||||
|
||||
exit_ingenic:
|
||||
ingenic_close(ingenic);
|
||||
|
343
shell.c
343
shell.c
@ -27,42 +27,9 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "shell_internal.h"
|
||||
#include "debug.h"
|
||||
#include "ingenic.h"
|
||||
#include "config.h"
|
||||
|
||||
static void *device = NULL;
|
||||
static char linebuf[512];
|
||||
char *strval = NULL, *line = NULL;
|
||||
|
||||
int yylex();
|
||||
void yyrestart(FILE *new_file);
|
||||
|
||||
static int builtin_help(int argc, char *argv[]);
|
||||
static int builtin_exit(int argc, char *argv[]);
|
||||
static int builtin_source(int argc, char *argv[]);
|
||||
static int builtin_echo(int argc, char *argv[]);
|
||||
static int builtin_sleep(int argc, char *argv[]);
|
||||
static int builtin_redetect(int argc, char *argv[]);
|
||||
static int builtin_rebuildcfg(int argc, char *argv[]);
|
||||
static int builtin_set(int argc, char *argv[]);
|
||||
static int builtin_safe(int argc, char *argv[]);
|
||||
|
||||
static const shell_command_t commands[] = {
|
||||
{ "help", "- Display this message", builtin_help },
|
||||
{ "exit", "- Batch: stop current script, interactive: end session", builtin_exit },
|
||||
{ "source", "<FILENAME> - run specified script", builtin_source },
|
||||
{ "echo", "<STRING> - output specified string", builtin_echo },
|
||||
{ "sleep", "<MILLISECONDS> - sleep a specified amount of time", builtin_sleep },
|
||||
{ "set", "[VARIABLE] [VALUE] - print or set configuraton variables", builtin_set },
|
||||
{ "safe", "<COMMAND> [ARG]... - run command ignoring errors", builtin_safe },
|
||||
|
||||
{ "redetect", " - Redetect CPU", builtin_redetect },
|
||||
{ "rebuildcfg", " - Rebuild firmware configuration data", builtin_rebuildcfg },
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void shell_update_cmdset(void *arg);
|
||||
|
||||
@ -70,64 +37,106 @@ static const ingenic_callbacks_t shell_callbacks = {
|
||||
shell_update_cmdset,
|
||||
};
|
||||
|
||||
static const shell_command_t *set_cmds = NULL;
|
||||
static int shell_exit = 0;
|
||||
static const struct {
|
||||
int set;
|
||||
const char *name;
|
||||
const shell_command_t *commands;
|
||||
} cmdsets[] = {
|
||||
{ CMDSET_SPL, "SPL", spl_cmdset },
|
||||
{ CMDSET_USBBOOT, "USBBoot", usbboot_cmdset },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
int shell_init(void *ingenic) {
|
||||
shell_context_t *shell_init(void *ingenic) {
|
||||
#ifdef WITH_READLINE
|
||||
rl_initialize();
|
||||
#endif
|
||||
|
||||
debug(LEVEL_DEBUG, "Initializing shell\n");
|
||||
|
||||
device = ingenic;
|
||||
shell_context_t *ctx = malloc(sizeof(shell_context_t));
|
||||
memset(ctx, 0, sizeof(shell_context_t));
|
||||
ctx->device = ingenic;
|
||||
|
||||
ingenic_set_callbacks(ingenic, &shell_callbacks, NULL);
|
||||
ingenic_set_callbacks(ingenic, &shell_callbacks, ctx);
|
||||
|
||||
shell_update_cmdset(NULL);
|
||||
shell_update_cmdset(ctx);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int shell_enumerate_commands(shell_context_t *ctx, int (*callback)(shell_context_t *ctx, const shell_command_t *cmd, void *arg), void *arg) {
|
||||
for(int i = 0; builtin_cmdset[i].cmd != NULL; i++) {
|
||||
int ret = callback(ctx, builtin_cmdset + i, arg);
|
||||
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(ctx->set_cmds)
|
||||
for(int i = 0; ctx->set_cmds[i].cmd != NULL; i++) {
|
||||
int ret = callback(ctx, ctx->set_cmds + i, arg);
|
||||
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define STATE_WANTSTR 0
|
||||
#define STATE_WANTSPACE 1
|
||||
static int shell_run_function(shell_context_t *ctx, const shell_command_t *cmd, void *arg) {
|
||||
shell_run_data_t *data = arg;
|
||||
|
||||
int shell_run(int argc, char *argv[]) {
|
||||
for(int i = 0; commands[i].cmd != NULL; i++)
|
||||
if(strcmp(commands[i].cmd, argv[0]) == 0)
|
||||
return commands[i].handler(argc, argv);
|
||||
if(strcmp(cmd->cmd, data->argv[0]) == 0) {
|
||||
int ret = cmd->handler(ctx, data->argc, data->argv);
|
||||
|
||||
if(set_cmds) {
|
||||
for(int i = 0; set_cmds[i].cmd != NULL; i++)
|
||||
if(strcmp(set_cmds[i].cmd, argv[0]) == 0)
|
||||
return set_cmds[i].handler(argc, argv);
|
||||
}
|
||||
|
||||
debug(LEVEL_ERROR, "Bad command '%s'\n", argv[0]);
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
if(ret == 0)
|
||||
return 1;
|
||||
else
|
||||
return ret;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shell_execute(const char *cmd) {
|
||||
line = strdup(cmd);
|
||||
char *ptr = line;
|
||||
int shell_run(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
shell_run_data_t data = { argc, argv };
|
||||
|
||||
int ret = shell_enumerate_commands(ctx, shell_run_function, &data);
|
||||
|
||||
if(ret != 0) {
|
||||
debug(LEVEL_ERROR, "Bad command '%s'\n", argv[0]);
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
} else if(ret == 1) {
|
||||
return 0;
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
|
||||
int shell_execute(shell_context_t *ctx, const char *cmd) {
|
||||
yyscan_t scanner;
|
||||
if(yylex_init_extra(ctx, &scanner) == -1)
|
||||
return -1;
|
||||
|
||||
ctx->line = strdup(cmd);
|
||||
char *ptr = ctx->line;
|
||||
|
||||
int token;
|
||||
int state = STATE_WANTSTR;
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
|
||||
yyrestart(NULL);
|
||||
int fret = -1;
|
||||
|
||||
do {
|
||||
int noway = 0;
|
||||
|
||||
token = yylex();
|
||||
token = yylex(&scanner);
|
||||
|
||||
if((token == TOK_SEPARATOR || token == TOK_COMMENT || token == 0)) {
|
||||
if(argc > 0) {
|
||||
int ret = shell_run(argc, argv);
|
||||
int ret = shell_run(ctx, argc, argv);
|
||||
|
||||
for(int i = 0; i < argc; i++) {
|
||||
free(argv[i]);
|
||||
@ -139,9 +148,9 @@ int shell_execute(const char *cmd) {
|
||||
argc = 0;
|
||||
|
||||
if(ret == -1) {
|
||||
free(ptr);
|
||||
fret = -1;
|
||||
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +165,7 @@ int shell_execute(const char *cmd) {
|
||||
|
||||
argv = realloc(argv, sizeof(char *) * argc);
|
||||
|
||||
argv[oargc] = strval;
|
||||
argv[oargc] = ctx->strval;
|
||||
|
||||
state = STATE_WANTSPACE;
|
||||
} else {
|
||||
@ -167,7 +176,7 @@ int shell_execute(const char *cmd) {
|
||||
|
||||
case STATE_WANTSPACE:
|
||||
if(token == TOK_STRING) {
|
||||
free(strval);
|
||||
free(ctx->strval);
|
||||
|
||||
noway = 1;
|
||||
} else if(token == TOK_SPACE) {
|
||||
@ -183,9 +192,10 @@ int shell_execute(const char *cmd) {
|
||||
free(argv[i]);
|
||||
|
||||
free(argv);
|
||||
free(ptr);
|
||||
|
||||
return -1;
|
||||
fret = -1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,28 +203,30 @@ int shell_execute(const char *cmd) {
|
||||
|
||||
free(ptr);
|
||||
|
||||
return 0;
|
||||
yylex_destroy(&scanner);
|
||||
|
||||
return fret;
|
||||
}
|
||||
|
||||
int shell_pull(char *buf, int maxlen) {
|
||||
size_t len = strlen(line);
|
||||
int shell_pull(shell_context_t *ctx, char *buf, int maxlen) {
|
||||
size_t len = strlen(ctx->line);
|
||||
|
||||
if(len < maxlen)
|
||||
maxlen = len;
|
||||
|
||||
memcpy(buf, line, maxlen);
|
||||
memcpy(buf, ctx->line, maxlen);
|
||||
|
||||
line += maxlen;
|
||||
ctx->line += maxlen;
|
||||
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
void shell_fini() {
|
||||
device = NULL;
|
||||
void shell_fini(shell_context_t *ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int shell_source(const char *filename) {
|
||||
shell_exit = 0;
|
||||
int shell_source(shell_context_t *ctx, const char *filename) {
|
||||
ctx->shell_exit = 0;
|
||||
|
||||
FILE *file = fopen(filename, "r");
|
||||
|
||||
@ -224,8 +236,8 @@ int shell_source(const char *filename) {
|
||||
|
||||
char *line;
|
||||
|
||||
while((line = fgets(linebuf, sizeof(linebuf), file)) && !shell_exit) {
|
||||
if(shell_execute(line) == -1) {
|
||||
while((line = fgets(ctx->linebuf, sizeof(ctx->linebuf), file)) && !ctx->shell_exit) {
|
||||
if(shell_execute(ctx, line) == -1) {
|
||||
fclose(file);
|
||||
|
||||
return -1;
|
||||
@ -237,38 +249,37 @@ int shell_source(const char *filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shell_interactive() {
|
||||
shell_exit = 0;
|
||||
void shell_interactive(shell_context_t *ctx) {
|
||||
ctx->shell_exit = 0;
|
||||
|
||||
#ifndef WITH_READLINE
|
||||
char *line;
|
||||
|
||||
while(!shell_exit) {
|
||||
while(!ctx->shell_exit) {
|
||||
fputs("jzboot> ", stdout);
|
||||
fflush(stdout);
|
||||
|
||||
line = fgets(linebuf, sizeof(linebuf), stdin);
|
||||
line = fgets(ctx->linebuf, sizeof(ctx->linebuf), stdin);
|
||||
|
||||
if(line == NULL)
|
||||
break;
|
||||
|
||||
shell_execute(line);
|
||||
shell_execute(ctx, line);
|
||||
}
|
||||
#else
|
||||
|
||||
rl_set_signals();
|
||||
|
||||
while(!shell_exit) {
|
||||
while(!ctx->shell_exit) {
|
||||
char *line = readline("jzboot> ");
|
||||
|
||||
if(line == NULL) {
|
||||
printf("line null, EOP\n");
|
||||
break;
|
||||
}
|
||||
|
||||
add_history(line);
|
||||
|
||||
shell_execute(line);
|
||||
shell_execute(ctx, line);
|
||||
|
||||
free(line);
|
||||
}
|
||||
@ -277,153 +288,18 @@ void shell_interactive() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int builtin_help(int argc, char *argv[]) {
|
||||
for(int i = 0; commands[i].cmd != NULL; i++) {
|
||||
printf("%s %s\n", commands[i].cmd, commands[i].description);
|
||||
}
|
||||
|
||||
if(set_cmds) {
|
||||
for(int i = 0; set_cmds[i].cmd != NULL; i++)
|
||||
printf("%s %s\n", set_cmds[i].cmd, set_cmds[i].description);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_exit(int argc, char *argv[]) {
|
||||
shell_exit = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_source(int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: %s <FILENAME>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = shell_source(argv[1]);
|
||||
|
||||
if(ret == -1) {
|
||||
fprintf(stderr, "Error while sourcing file %s: %s\n", argv[1], strerror(errno));
|
||||
}
|
||||
|
||||
shell_exit = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int builtin_echo(int argc, char *argv[]) {
|
||||
if(argc < 2) {
|
||||
printf("Usage: %s <STRING>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; i++) {
|
||||
fputs(argv[i], stdout);
|
||||
|
||||
putchar((i < argc - 1) ? ' ' : '\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_sleep(int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: %s <MILLISECONDS>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t ms = atoi(argv[1]);
|
||||
|
||||
usleep(ms * 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_redetect(int argc, char *argv[]) {
|
||||
if(argc != 1) {
|
||||
printf("Usage: %s\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ingenic_redetect(device) == -1) {
|
||||
perror("ingenic_redetect");
|
||||
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int builtin_set(int argc, char *argv[]) {
|
||||
if(argc == 1 && cfg_environ) {
|
||||
for(int i = 0; cfg_environ[i] != NULL; i++)
|
||||
printf("%s\n", cfg_environ[i]);
|
||||
|
||||
} else if(argc == 2) {
|
||||
cfg_unsetenv(argv[1]);
|
||||
|
||||
} else if(argc == 3) {
|
||||
cfg_setenv(argv[1], argv[2]);
|
||||
|
||||
} else {
|
||||
printf("Usage: %s [VARIABLE] [VALUE]\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int builtin_rebuildcfg(int argc, char *argv[]) {
|
||||
if(argc != 1) {
|
||||
printf("Usage: %s\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ingenic_rebuild(device);
|
||||
}
|
||||
|
||||
static int builtin_safe(int argc, char *argv[]) {
|
||||
if(argc < 2) {
|
||||
printf("Usage: %s <COMMAND> [ARG]...\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(shell_run(argc - 1, argv + 1) == -1)
|
||||
perror("shell_run");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int set;
|
||||
const char *name;
|
||||
const shell_command_t *commands;
|
||||
} cmdsets[] = {
|
||||
{ CMDSET_SPL, "SPL", spl_cmdset },
|
||||
{ CMDSET_USBBOOT, "USBBoot", usbboot_cmdset },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static void shell_update_cmdset(void *arg) {
|
||||
set_cmds = NULL;
|
||||
shell_context_t *ctx = arg;
|
||||
|
||||
int set = ingenic_cmdset(device);
|
||||
ctx->set_cmds = NULL;
|
||||
|
||||
int set = ingenic_cmdset(ctx->device);
|
||||
|
||||
for(int i = 0; cmdsets[i].name != NULL; i++) {
|
||||
if(cmdsets[i].set == set) {
|
||||
printf("Shell: using command set '%s', run 'help' for command list. CPU: %04X\n", cmdsets[i].name, ingenic_type(device));
|
||||
printf("Shell: using command set '%s', run 'help' for command list. CPU: %04X\n", cmdsets[i].name, ingenic_type(ctx->device));
|
||||
|
||||
set_cmds = cmdsets[i].commands;
|
||||
ctx->set_cmds = cmdsets[i].commands;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -432,6 +308,11 @@ static void shell_update_cmdset(void *arg) {
|
||||
debug(LEVEL_ERROR, "Shell: unknown cmdset %d\n", set);
|
||||
}
|
||||
|
||||
void *shell_device() {
|
||||
return device;
|
||||
void *shell_device(shell_context_t *ctx) {
|
||||
return ctx->device;
|
||||
}
|
||||
|
||||
void shell_exit(shell_context_t *ctx, int val) {
|
||||
ctx->shell_exit = val;
|
||||
}
|
||||
|
||||
|
34
shell.h
34
shell.h
@ -19,32 +19,30 @@
|
||||
#ifndef __SHELL__H__
|
||||
#define __SHELL__H__
|
||||
|
||||
typedef struct {
|
||||
#ifndef SHELL_INTERNALS
|
||||
typedef void shell_context_t;
|
||||
#endif
|
||||
|
||||
typedef struct shell_command {
|
||||
const char *cmd;
|
||||
const char *description;
|
||||
int (*handler)(int argc, char *argv[]);
|
||||
int (*handler)(shell_context_t *ctx, int argc, char *argv[]);
|
||||
} shell_command_t;
|
||||
|
||||
int shell_init(void *ingenic);
|
||||
void shell_fini();
|
||||
shell_context_t *shell_init(void *ingenic);
|
||||
void shell_fini(shell_context_t *context);
|
||||
|
||||
void shell_interactive();
|
||||
int shell_source(const char *filename);
|
||||
int shell_execute(const char *input);
|
||||
void shell_interactive(shell_context_t *ctx);
|
||||
int shell_source(shell_context_t *ctx, const char *filename);
|
||||
int shell_execute(shell_context_t *ctx, const char *input);
|
||||
void *shell_device(shell_context_t *ctx);
|
||||
int shell_run(shell_context_t *ctx, int argc, char *argv[]);
|
||||
|
||||
void *shell_device();
|
||||
|
||||
// lexer interface
|
||||
extern char *strval;
|
||||
|
||||
#define TOK_SEPARATOR 1
|
||||
#define TOK_STRING 2
|
||||
#define TOK_SPACE 3
|
||||
#define TOK_COMMENT 4
|
||||
|
||||
int shell_pull(char *buf, int maxlen);
|
||||
void shell_exit(shell_context_t *ctx, int val);
|
||||
int shell_enumerate_commands(shell_context_t *ctx, int (*callback)(shell_context_t *ctx, const shell_command_t *cmd, void *arg), void *arg);
|
||||
|
||||
extern const shell_command_t spl_cmdset[];
|
||||
extern const shell_command_t usbboot_cmdset[];
|
||||
extern const shell_command_t builtin_cmdset[];
|
||||
|
||||
#endif
|
||||
|
181
shell_builtins.c
Normal file
181
shell_builtins.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors.
|
||||
* Copyright (C) 2010 Sergey Gridassov <grindars@gmail.com>,
|
||||
* Peter Zotov <whitequark@whitequark.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "config.h"
|
||||
#include "ingenic.h"
|
||||
|
||||
static int builtin_help(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_exit(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_source(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_echo(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_sleep(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_redetect(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_rebuildcfg(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_set(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int builtin_safe(shell_context_t *ctx, int argc, char *argv[]);
|
||||
|
||||
const shell_command_t builtin_cmdset[] = {
|
||||
{ "help", "- Display this message", builtin_help },
|
||||
{ "exit", "- Batch: stop current script, interactive: end session", builtin_exit },
|
||||
{ "source", "<FILENAME> - run specified script", builtin_source },
|
||||
{ "echo", "<STRING> - output specified string", builtin_echo },
|
||||
{ "sleep", "<MILLISECONDS> - sleep a specified amount of time", builtin_sleep },
|
||||
{ "set", "[VARIABLE] [VALUE] - print or set configuraton variables", builtin_set },
|
||||
{ "safe", "<COMMAND> [ARG]... - run command ignoring errors", builtin_safe },
|
||||
|
||||
{ "redetect", " - Redetect CPU", builtin_redetect },
|
||||
{ "rebuildcfg", " - Rebuild firmware configuration data", builtin_rebuildcfg },
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static int builtin_help(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
/* for(int i = 0; commands[i].cmd != NULL; i++) {
|
||||
printf("%s %s\n", commands[i].cmd, commands[i].description);
|
||||
}
|
||||
|
||||
if(set_cmds) {
|
||||
for(int i = 0; set_cmds[i].cmd != NULL; i++)
|
||||
printf("%s %s\n", set_cmds[i].cmd, set_cmds[i].description);
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_exit(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
shell_exit(ctx, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_source(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: %s <FILENAME>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = shell_source(ctx, argv[1]);
|
||||
|
||||
if(ret == -1) {
|
||||
fprintf(stderr, "Error while sourcing file %s: %s\n", argv[1], strerror(errno));
|
||||
}
|
||||
|
||||
shell_exit(ctx, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int builtin_echo(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc < 2) {
|
||||
printf("Usage: %s <STRING>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; i++) {
|
||||
fputs(argv[i], stdout);
|
||||
|
||||
putchar((i < argc - 1) ? ' ' : '\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_sleep(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: %s <MILLISECONDS>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t ms = atoi(argv[1]);
|
||||
|
||||
usleep(ms * 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_redetect(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 1) {
|
||||
printf("Usage: %s\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ingenic_redetect(shell_device(ctx)) == -1) {
|
||||
perror("ingenic_redetect");
|
||||
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int builtin_set(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc == 1 && cfg_environ) {
|
||||
for(int i = 0; cfg_environ[i] != NULL; i++)
|
||||
printf("%s\n", cfg_environ[i]);
|
||||
|
||||
} else if(argc == 2) {
|
||||
cfg_unsetenv(argv[1]);
|
||||
|
||||
} else if(argc == 3) {
|
||||
cfg_setenv(argv[1], argv[2]);
|
||||
|
||||
} else {
|
||||
printf("Usage: %s [VARIABLE] [VALUE]\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int builtin_rebuildcfg(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 1) {
|
||||
printf("Usage: %s\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ingenic_rebuild(shell_device(ctx));
|
||||
}
|
||||
|
||||
static int builtin_safe(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc < 2) {
|
||||
printf("Usage: %s <COMMAND> [ARG]...\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(shell_run(ctx, argc - 1, argv + 1) == -1)
|
||||
perror("shell_run");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
62
shell_internal.h
Normal file
62
shell_internal.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors.
|
||||
* Copyright (C) 2010 Sergey Gridassov <grindars@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SHELL_INTERNAL__H__
|
||||
#define __SHELL_INTERNAL__H__
|
||||
|
||||
#define SHELL_INTERNALS
|
||||
#define STATE_WANTSTR 0
|
||||
#define STATE_WANTSPACE 1
|
||||
|
||||
#define TOK_SEPARATOR 1
|
||||
#define TOK_STRING 2
|
||||
#define TOK_SPACE 3
|
||||
#define TOK_COMMENT 4
|
||||
|
||||
typedef struct {
|
||||
void *device;
|
||||
char linebuf[512];
|
||||
char *strval;
|
||||
char *line;
|
||||
const struct shell_command *set_cmds;
|
||||
int shell_exit;
|
||||
} shell_context_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int argc;
|
||||
char **argv;
|
||||
} shell_run_data_t;
|
||||
|
||||
int shell_pull(shell_context_t *ctx, char *buf, int maxlen);
|
||||
|
||||
#ifndef FLEX_SCANNER
|
||||
typedef void *yyscan_t;
|
||||
int yylex_init(yyscan_t *ptr_yy_globals);
|
||||
int yylex_init_extra(shell_context_t *user_defined, yyscan_t *ptr_yy_globals);
|
||||
int yylex(yyscan_t yyscanner) ;
|
||||
int yylex_destroy (yyscan_t yyscanner) ;
|
||||
#else
|
||||
#define YY_EXTRA_TYPE shell_context_t *
|
||||
#define YY_INPUT(buf, result, max_size) result = shell_pull(yyextra, buf, max_size);
|
||||
#endif
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#endif
|
||||
|
876
shell_lex.c
876
shell_lex.c
File diff suppressed because it is too large
Load Diff
16
shell_lex.l
16
shell_lex.l
@ -17,12 +17,10 @@
|
||||
*/
|
||||
|
||||
%{
|
||||
#include "shell.h"
|
||||
#include "shell_internal.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define YY_INPUT(buf, result, max_size) result = shell_pull(buf, max_size);
|
||||
|
||||
static char *str_append(char *str, const char *src) {
|
||||
if(str) {
|
||||
size_t newlen = strlen(str) + strlen(src) + 1;
|
||||
@ -39,16 +37,16 @@ static char *str_append(char *str, const char *src) {
|
||||
return strdup(src);
|
||||
}
|
||||
%}
|
||||
%option noyywrap nounput noinput batch
|
||||
%option noyywrap nounput noinput batch reentrant
|
||||
|
||||
%x STR
|
||||
%%
|
||||
["] { strval = NULL; BEGIN(STR); }
|
||||
["] { yyextra->strval = NULL; BEGIN(STR); }
|
||||
; return TOK_SEPARATOR;
|
||||
[[:space:]]+ return TOK_SPACE;
|
||||
[#] return TOK_COMMENT;
|
||||
[^[:space:];"#]+ { strval = strdup(yytext); return TOK_STRING; }
|
||||
<STR>[^\\"]+ strval = str_append(strval, yytext);
|
||||
<STR>\\["] strval = str_append(strval, "\"");
|
||||
<STR>\\ strval = str_append(strval, "\\");
|
||||
[^[:space:];"#]+ { yyextra->strval = strdup(yytext); return TOK_STRING; }
|
||||
<STR>[^\\"]+ yyextra->strval = str_append(yyextra->strval, yytext);
|
||||
<STR>\\["] yyextra->strval = str_append(yyextra->strval, "\"");
|
||||
<STR>\\ yyextra->strval = str_append(yyextra->strval, "\\");
|
||||
<STR>["] { BEGIN(INITIAL); return TOK_STRING; }
|
||||
|
28
spl_cmdset.c
28
spl_cmdset.c
@ -26,9 +26,9 @@
|
||||
#include "config.h"
|
||||
#include "ingenic.h"
|
||||
|
||||
static int spl_memtest(int argc, char *argv[]);
|
||||
static int spl_gpio(int argc, char *argv[]);
|
||||
static int spl_boot(int argc, char *argv[]);
|
||||
static int spl_memtest(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int spl_gpio(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int spl_boot(shell_context_t *ctx, int argc, char *argv[]);
|
||||
|
||||
const shell_command_t spl_cmdset[] = {
|
||||
{ "memtest", "[BASE <SIZE>] - SDRAM test", spl_memtest },
|
||||
@ -37,14 +37,14 @@ const shell_command_t spl_cmdset[] = {
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static int spl_stage1_op(uint32_t op, uint32_t pin, uint32_t base, uint32_t size) {
|
||||
static int spl_stage1_op(shell_context_t *ctx, uint32_t op, uint32_t pin, uint32_t base, uint32_t size) {
|
||||
if(cfg_getenv("STAGE1_FILE") == NULL) {
|
||||
printf("Variable STAGE1_FILE is not set\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = ingenic_stage1_debugop(shell_device(), cfg_getenv("STAGE1_FILE"), op, pin, base, size);
|
||||
int ret = ingenic_stage1_debugop(shell_device(ctx), cfg_getenv("STAGE1_FILE"), op, pin, base, size);
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_stage1_debugop");
|
||||
@ -52,7 +52,7 @@ static int spl_stage1_op(uint32_t op, uint32_t pin, uint32_t base, uint32_t size
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spl_memtest(int argc, char *argv[]) {
|
||||
static int spl_memtest(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 1 && argc != 3) {
|
||||
printf("Usage: %s [BASE <SIZE>]\n", argv[0]);
|
||||
|
||||
@ -66,7 +66,7 @@ static int spl_memtest(int argc, char *argv[]) {
|
||||
size = strtoul(argv[2], NULL, 0);
|
||||
} else {
|
||||
start = SDRAM_BASE;
|
||||
size = ingenic_sdram_size(shell_device());
|
||||
size = ingenic_sdram_size(shell_device(ctx));
|
||||
}
|
||||
|
||||
if(cfg_getenv("STAGE1_FILE") == NULL) {
|
||||
@ -77,7 +77,7 @@ static int spl_memtest(int argc, char *argv[]) {
|
||||
|
||||
uint32_t fail;
|
||||
|
||||
int ret = ingenic_memtest(shell_device(), cfg_getenv("STAGE1_FILE"), start, size, &fail);
|
||||
int ret = ingenic_memtest(shell_device(ctx), cfg_getenv("STAGE1_FILE"), start, size, &fail);
|
||||
|
||||
if(ret == -1) {
|
||||
if(errno == EFAULT) {
|
||||
@ -93,7 +93,7 @@ static int spl_memtest(int argc, char *argv[]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spl_gpio(int argc, char *argv[]) {
|
||||
static int spl_gpio(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 3 || (strcmp(argv[2], "0") && strcmp(argv[2], "1"))) {
|
||||
printf("Usage: %s <PIN> <STATE>\n", argv[0]);
|
||||
printf(" STATE := 0 | 1\n");
|
||||
@ -101,15 +101,15 @@ static int spl_gpio(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return spl_stage1_op(!strcmp(argv[2], "1") ? STAGE1_DEBUG_GPIO_SET : STAGE1_DEBUG_GPIO_CLEAR, atoi(argv[1]), 0, 0);
|
||||
return spl_stage1_op(ctx, !strcmp(argv[2], "1") ? STAGE1_DEBUG_GPIO_SET : STAGE1_DEBUG_GPIO_CLEAR, atoi(argv[1]), 0, 0);
|
||||
}
|
||||
|
||||
static int spl_boot(int argc, char *argv[]) {
|
||||
static int spl_boot(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 1) {
|
||||
printf("Usage: %s\n", argv[0]);
|
||||
}
|
||||
|
||||
int ret = spl_stage1_op(STAGE1_DEBUG_BOOT, 0, 0, 0);
|
||||
int ret = spl_stage1_op(ctx, STAGE1_DEBUG_BOOT, 0, 0, 0);
|
||||
|
||||
if(ret == -1)
|
||||
return -1;
|
||||
@ -120,7 +120,7 @@ static int spl_boot(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ingenic_loadstage(shell_device(), INGENIC_STAGE2, cfg_getenv("STAGE2_FILE"));
|
||||
ret = ingenic_loadstage(shell_device(ctx), INGENIC_STAGE2, cfg_getenv("STAGE2_FILE"));
|
||||
|
||||
if(ret == -1) {
|
||||
perror("ingenic_loadstage");
|
||||
@ -128,7 +128,7 @@ static int spl_boot(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ingenic_configure_stage2(shell_device());
|
||||
ret = ingenic_configure_stage2(shell_device(ctx));
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_configure_stage2");
|
||||
|
@ -25,14 +25,14 @@
|
||||
#include "ingenic.h"
|
||||
#include "config.h"
|
||||
|
||||
static int usbboot_boot(int argc, char *argv[]);
|
||||
static int usbboot_load(int argc, char *argv[]);
|
||||
static int usbboot_go(int argc, char *argv[]);
|
||||
static int usbboot_nquery(int argc, char *argv[]);
|
||||
static int usbboot_ndump(int argc, char *argv[]);
|
||||
static int usbboot_nerase(int argc, char *argv[]);
|
||||
static int usbboot_nprogram(int argc, char *argv[]);
|
||||
static int usbboot_nload(int argc, char *argv[]);
|
||||
static int usbboot_boot(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_load(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_go(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_nquery(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_ndump(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_nerase(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_nprogram(shell_context_t *ctx, int argc, char *argv[]);
|
||||
static int usbboot_nload(shell_context_t *ctx, int argc, char *argv[]);
|
||||
|
||||
const shell_command_t usbboot_cmdset[] = {
|
||||
|
||||
@ -51,8 +51,8 @@ const shell_command_t usbboot_cmdset[] = {
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static int usbboot_boot(int argc, char *argv[]) {
|
||||
int ret = ingenic_configure_stage2(shell_device());
|
||||
static int usbboot_boot(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
int ret = ingenic_configure_stage2(shell_device(ctx));
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_configure_stage2");
|
||||
@ -60,14 +60,14 @@ static int usbboot_boot(int argc, char *argv[]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbboot_load(int argc, char *argv[]) {
|
||||
static int usbboot_load(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 3) {
|
||||
printf("Usage: %s <FILE> <BASE>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = ingenic_load_sdram_file(shell_device(), strtoul(argv[2], NULL, 0), argv[1]);
|
||||
int ret = ingenic_load_sdram_file(shell_device(ctx), strtoul(argv[2], NULL, 0), argv[1]);
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_load_sdram_file");
|
||||
@ -75,14 +75,14 @@ static int usbboot_load(int argc, char *argv[]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbboot_go(int argc, char *argv[]) {
|
||||
static int usbboot_go(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: %s <ADDRESS>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = ingenic_go(shell_device(), strtoul(argv[1], NULL, 0));
|
||||
int ret = ingenic_go(shell_device(ctx), strtoul(argv[1], NULL, 0));
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_go");
|
||||
@ -90,7 +90,7 @@ static int usbboot_go(int argc, char *argv[]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbboot_nquery(int argc, char *argv[]) {
|
||||
static int usbboot_nquery(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
printf("Usage: %s <DEVICE>\n", argv[0]);
|
||||
|
||||
@ -99,7 +99,7 @@ static int usbboot_nquery(int argc, char *argv[]) {
|
||||
|
||||
nand_info_t info;
|
||||
|
||||
int ret = ingenic_query_nand(shell_device(), atoi(argv[1]), &info);
|
||||
int ret = ingenic_query_nand(shell_device(ctx), atoi(argv[1]), &info);
|
||||
|
||||
if(ret == -1) {
|
||||
perror("ingenic_query_nand");
|
||||
@ -119,7 +119,7 @@ static int usbboot_nquery(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbboot_ndump(int argc, char *argv[]) {
|
||||
static int usbboot_ndump(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 5) {
|
||||
printf("Usage: %s <DEVICE> <STARTPAGE> <PAGES> <FILE>\n", argv[0]);
|
||||
|
||||
@ -131,7 +131,7 @@ static int usbboot_ndump(int argc, char *argv[]) {
|
||||
if(cfg_getenv("NAND_RAW"))
|
||||
type |= NAND_RAW;
|
||||
|
||||
int ret = ingenic_dump_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), type, argv[4]);
|
||||
int ret = ingenic_dump_nand(shell_device(ctx), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), type, argv[4]);
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_dump_nand");
|
||||
@ -139,14 +139,14 @@ static int usbboot_ndump(int argc, char *argv[]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbboot_nerase(int argc, char *argv[]) {
|
||||
static int usbboot_nerase(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 4) {
|
||||
printf("Usage: %s <DEVICE> <STARTBLOCK> <BLOCKS>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = ingenic_erase_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
|
||||
int ret = ingenic_erase_nand(shell_device(ctx), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_erase_nand");
|
||||
@ -155,7 +155,7 @@ static int usbboot_nerase(int argc, char *argv[]) {
|
||||
|
||||
}
|
||||
|
||||
static int usbboot_nprogram(int argc, char *argv[]) {
|
||||
static int usbboot_nprogram(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 4) {
|
||||
printf("Usage: %s <DEVICE> <STARTPAGE> <FILE>\n", argv[0]);
|
||||
|
||||
@ -172,7 +172,7 @@ static int usbboot_nprogram(int argc, char *argv[]) {
|
||||
} else
|
||||
type = NO_OOB;
|
||||
|
||||
int ret = ingenic_program_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), type, argv[3]);
|
||||
int ret = ingenic_program_nand(shell_device(ctx), atoi(argv[1]), atoi(argv[2]), type, argv[3]);
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_program_nand");
|
||||
@ -180,14 +180,14 @@ static int usbboot_nprogram(int argc, char *argv[]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbboot_nload(int argc, char *argv[]) {
|
||||
static int usbboot_nload(shell_context_t *ctx, int argc, char *argv[]) {
|
||||
if(argc != 5) {
|
||||
printf("Usage: %s <DEVICE> <STARTPAGE> <PAGES> <BASE>\n", argv[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = ingenic_load_nand(shell_device(), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), strtoul(argv[4], NULL, 0));
|
||||
int ret = ingenic_load_nand(shell_device(ctx), atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), strtoul(argv[4], NULL, 0));
|
||||
|
||||
if(ret == -1)
|
||||
perror("ingenic_load_nand");
|
||||
|
Loading…
Reference in New Issue
Block a user