📄 flash.c
字号:
if (!do_flash_init()) return;
if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__,
argv[1])) != (struct cmd *)0) {
(cmd->fun)(argc, argv);
return;
}
fis_usage("unrecognized command");
}
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
#include <flash_config.h>
// Configuration data, saved in FLASH, used to set/update RedBoot
// normal "configuration" data items.
struct _config config;
static bool config_ok;
#define CONFIG_KEY1 0x0BADFACE
#define CONFIG_KEY2 0xDEADDEAD
#define CONFIG_DONE 0
#define CONFIG_ABORT -1
#define CONFIG_CHANGED 1
#define CONFIG_OK 2
#define CONFIG_BACK 3
#define CONFIG_BAD 4
// Note: the following options are related. If 'boot_script' is false, then
// the other values are used in the configuration. Because of the way
// that configuration tables are generated, they should have names which
// are related. The configuration options will show up lexicographically
// ordered, thus the peculiar naming.
RedBoot_config_option("Run script at boot",
boot_script,
ALWAYS_ENABLED, true,
CONFIG_BOOL,
false
);
RedBoot_config_option("Boot script",
boot_script_data,
"boot_script", true,
CONFIG_SCRIPT,
""
);
// Some preprocessor magic for building the [constant] prompt string
#define __cat(s1,c2,s3) s1 #c2 s3
#define _cat(s1,c2,s3) __cat(s1,c2,s3)
RedBoot_config_option(_cat("Boot script timeout (",
CYGNUM_REDBOOT_BOOT_SCRIPT_TIMEOUT_RESOLUTION,
"ms resolution)"),
boot_script_timeout,
"boot_script", true,
CONFIG_INT,
0
);
#undef __cat
#undef _cat
#ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
RedBoot_config_option("Console baud rate",
console_baud_rate,
ALWAYS_ENABLED, true,
CONFIG_INT,
CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD
);
#endif
CYG_HAL_TABLE_BEGIN( __CONFIG_options_TAB__, RedBoot_config_options);
CYG_HAL_TABLE_END( __CONFIG_options_TAB_END__, RedBoot_config_options);
extern struct config_option __CONFIG_options_TAB__[], __CONFIG_options_TAB_END__[];
//
// Layout of config data
// Each data item is variable length, with the name, type and dependencies
// encoded into the object.
// offset contents
// 0 data type
// 1 length of name (N)
// 2 enable sense
// 3 length of enable key (M)
// 4 key name
// N+4 enable key
// M+N+4 data value
//
#define CONFIG_OBJECT_TYPE(dp) (dp)[0]
#define CONFIG_OBJECT_KEYLEN(dp) (dp)[1]
#define CONFIG_OBJECT_ENABLE_SENSE(dp) (dp)[2]
#define CONFIG_OBJECT_ENABLE_KEYLEN(dp) (dp)[3]
#define CONFIG_OBJECT_KEY(dp) ((dp)+4)
#define CONFIG_OBJECT_ENABLE_KEY(dp) ((dp)+4+CONFIG_OBJECT_KEYLEN(dp))
#define CONFIG_OBJECT_VALUE(dp) ((dp)+4+CONFIG_OBJECT_KEYLEN(dp)+CONFIG_OBJECT_ENABLE_KEYLEN(dp))
#define LIST_OPT_LIST_ONLY (1)
#define LIST_OPT_NICKNAMES (2)
#define LIST_OPT_FULLNAMES (4)
static void config_init(void);
static int
get_config(unsigned char *dp, char *title, int list_opt, char *newvalue )
{
char line[256], *sp, *lp;
int ret;
bool hold_bool_val, new_bool_val, enable;
unsigned long hold_int_val, new_int_val;
#ifdef CYGPKG_REDBOOT_NETWORKING
in_addr_t hold_ip_val, new_ip_val;
enet_addr_t hold_esa_val;
int esa_ptr;
char *esp;
#endif
void *val_ptr;
int type;
if (CONFIG_OBJECT_ENABLE_KEYLEN(dp)) {
flash_get_config(CONFIG_OBJECT_ENABLE_KEY(dp), &enable, CONFIG_BOOL);
if (((bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && !enable) ||
(!(bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && enable)) {
return CONFIG_OK; // Disabled field
}
}
val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
if (LIST_OPT_NICKNAMES & list_opt)
printf("%s: ", CONFIG_OBJECT_KEY(dp));
if (LIST_OPT_FULLNAMES & list_opt) {
if (title != (char *)NULL) {
printf("%s: ", title);
} else {
printf("%s: ", CONFIG_OBJECT_KEY(dp));
}
}
switch (type = CONFIG_OBJECT_TYPE(dp)) {
case CONFIG_BOOL:
memcpy(&hold_bool_val, val_ptr, sizeof(bool));
printf("%s ", hold_bool_val ? "true" : "false");
break;
case CONFIG_INT:
memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
printf("%ld ", hold_int_val);
break;
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
printf("%s ", inet_ntoa((in_addr_t *)val_ptr));
break;
case CONFIG_ESA:
for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) {
printf("0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
if (esa_ptr < (sizeof(enet_addr_t)-1)) printf(":");
}
printf(" ");
break;
#endif
case CONFIG_STRING:
printf("%s ", (unsigned char *)val_ptr);
break;
case CONFIG_SCRIPT:
printf("\n");
sp = lp = (unsigned char *)val_ptr;
while (*sp) {
while (*lp != '\n') lp++;
*lp = '\0';
printf(".. %s\n", sp);
*lp++ = '\n';
sp = lp;
}
break;
}
if (LIST_OPT_LIST_ONLY & list_opt) {
printf("\n");
return CONFIG_OK;
}
if (type != CONFIG_SCRIPT) {
if (NULL != newvalue) {
ret = strlen(newvalue);
if (ret > sizeof(line))
return CONFIG_BAD;
strcpy(line, newvalue);
printf("Setting to %s\n", newvalue);
}
else // read from terminal
ret = gets(line, sizeof(line), 0);
if (ret < 0) return CONFIG_ABORT;
if (strlen(line) == 0) return CONFIG_OK; // Just a CR - leave value untouched
if (line[0] == '.') return CONFIG_DONE;
if (line[0] == '^') return CONFIG_BACK;
}
switch (type) {
case CONFIG_BOOL:
memcpy(&hold_bool_val, val_ptr, sizeof(bool));
if (!parse_bool(line, &new_bool_val)) {
return CONFIG_BAD;
}
if (hold_bool_val != new_bool_val) {
memcpy(val_ptr, &new_bool_val, sizeof(bool));
return CONFIG_CHANGED;
} else {
return CONFIG_OK;
}
break;
case CONFIG_INT:
memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
if (!parse_num(line, &new_int_val, 0, 0)) {
return CONFIG_BAD;
}
if (hold_int_val != new_int_val) {
memcpy(val_ptr, &new_int_val, sizeof(unsigned long));
return CONFIG_CHANGED;
} else {
return CONFIG_OK;
}
break;
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
memcpy(&hold_ip_val.s_addr, &((in_addr_t *)val_ptr)->s_addr, sizeof(in_addr_t));
if (!inet_aton(line, &new_ip_val)) {
return CONFIG_BAD;
}
if (hold_ip_val.s_addr != new_ip_val.s_addr) {
memcpy(val_ptr, &new_ip_val, sizeof(in_addr_t));
return CONFIG_CHANGED;
} else {
return CONFIG_OK;
}
break;
case CONFIG_ESA:
memcpy(&hold_esa_val, val_ptr, sizeof(enet_addr_t));
esp = line;
for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) {
unsigned long esa_byte;
if (!parse_num(esp, &esa_byte, &esp, ":")) {
memcpy(val_ptr, &hold_esa_val, sizeof(enet_addr_t));
return CONFIG_BAD;
}
((unsigned char *)val_ptr)[esa_ptr] = esa_byte;
}
return CONFIG_CHANGED;
break;
#endif
case CONFIG_SCRIPT:
// Assume it always changes
sp = (unsigned char *)val_ptr;
printf("Enter script, terminate with empty line\n");
while (true) {
*sp = '\0';
printf(">> ");
ret = gets(line, sizeof(line), 0);
if (ret < 0) return CONFIG_ABORT;
if (strlen(line) == 0) break;
lp = line;
while (*lp) {
*sp++ = *lp++;
}
*sp++ = '\n';
}
break;
case CONFIG_STRING:
if (strlen(line) >= MAX_STRING_LENGTH) {
printf("Sorry, value is too long\n");
return CONFIG_BAD;
}
strcpy((unsigned char *)val_ptr, line);
break;
}
return CONFIG_CHANGED;
}
//
// Manage configuration information with the FLASH
//
static int
config_length(int type)
{
switch (type) {
case CONFIG_BOOL:
return sizeof(bool);
case CONFIG_INT:
return sizeof(unsigned long);
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
return sizeof(in_addr_t);
case CONFIG_ESA:
// Would like this to be sizeof(enet_addr_t), but that causes much
// pain since it fouls the alignment of data which follows.
return 8;
#endif
case CONFIG_STRING:
return MAX_STRING_LENGTH;
case CONFIG_SCRIPT:
return MAX_SCRIPT_LENGTH;
default:
return 0;
}
}
static cmd_fun do_flash_config;
RedBoot_cmd("fconfig",
"Manage configuration kept in FLASH memory",
"[-i] [-l] [-n] [-f] | nickname [value]",
do_flash_config
);
static void
do_flash_config(int argc, char *argv[])
{
bool need_update = false;
struct config_option *optend = __CONFIG_options_TAB_END__;
struct config_option *opt = __CONFIG_options_TAB__;
struct _config hold_config;
struct option_info opts[4];
bool list_only;
bool nicknames;
bool fullnames;
int list_opt = 0;
unsigned char *dp;
int len, ret;
char *title;
char *onlyone = NULL;
char *onevalue = NULL;
bool doneone = false;
bool init = false;
if (!do_flash_init()) return;
memcpy(&hold_config, &config, sizeof(config));
script = (unsigned char *)0;
init_opts(&opts[0], 'l', false, OPTION_ARG_TYPE_FLG,
(void **)&list_only, (bool *)0, "list configuration only");
init_opts(&opts[1], 'n', false, OPTION_ARG_TYPE_FLG,
(void **)&nicknames, (bool *)0, "show nicknames");
init_opts(&opts[2], 'f', false, OPTION_ARG_TYPE_FLG,
(void **)&fullnames, (bool *)0, "show full names");
init_opts(&opts[3], 'i', false, OPTION_ARG_TYPE_FLG,
(void **)&init, (bool *)0, "initialize configuration database");
// First look to see if we are setting or getting a single option
// by just quoting its nickname
if ( (2 == argc && '-' != argv[1][0]) ||
(3 == argc && '-' != argv[1][0] && '-' != argv[2][0])) {
// then the command was "fconfig foo [value]"
onlyone = argv[1];
onevalue = (3 == argc) ? argv[2] : NULL;
list_opt = LIST_OPT_NICKNAMES;
}
else {
if (!scan_opts(argc, argv, 1, opts, 4, 0, 0, ""))
return;
list_opt |= list_only ? LIST_OPT_LIST_ONLY : 0;
list_opt |= nicknames ? LIST_OPT_NICKNAMES : LIST_OPT_FULLNAMES;
list_opt |= fullnames ? LIST_OPT_FULLNAMES : 0;
}
if (init && verify_action("Initialize non-volatile configuration")) {
config_init();
}
dp = &config.config_data[0];
while (dp < &config.config_data[sizeof(config.config_data)]) {
if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {
break;
}
len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
config_length(CONFIG_OBJECT_TYPE(dp));
// Provide a title for well known [i.e. builtin] objects
title = (char *)NULL;
opt = __CONFIG_options_TAB__;
while (opt != optend) {
if (strcmp(opt->key, CONFIG_OBJECT_KEY(dp)) == 0) {
title = opt->title;
break;
}
opt++;
}
if ( onlyone && 0 != strcmp(CONFIG_OBJECT_KEY(dp), onlyone) )
ret = CONFIG_OK; // skip this entry
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -