📄 fconfig.c
字号:
}
strcpy((unsigned char *)val_ptr, line);
break;
#endif
#endif
case CONFIG_SCRIPT:
// Assume it always changes
sp = (unsigned char *)val_ptr;
diag_printf("Enter script, terminate with empty line\n");
while (true) {
*sp = '\0';
diag_printf(">> ");
ret = _rb_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) {
diag_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;
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
case CONFIG_NETPORT:
return MAX_STRING_LENGTH;
#endif
#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] [-d] | [-d] 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 option_info opts[5];
bool list_only;
bool nicknames;
bool fullnames;
bool dumbterminal;
int list_opt = 0;
unsigned char *dp;
int len, ret;
char *title;
char *onlyone = NULL;
char *onevalue = NULL;
bool doneone = false;
bool init = false;
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
if (!__flash_init) {
diag_printf("Sorry, no FLASH memory is available\n");
return;
}
#endif
memcpy(backup_config, config, sizeof(struct _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");
init_opts(&opts[4], 'd', false, OPTION_ARG_TYPE_FLG,
(void *)&dumbterminal, (bool *)0, "dumb terminal: no clever edits");
// 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;
}
// Next see if we are setting or getting a single option with a dumb
// terminal invoked, ie. no line editing.
else if (3 == argc &&
'-' == argv[1][0] && 'd' == argv[1][1] && 0 == argv[1][2] &&
'-' != argv[2][0]) {
// then the command was "fconfig -d foo"
onlyone = argv[2];
onevalue = NULL;
list_opt = LIST_OPT_NICKNAMES | LIST_OPT_DUMBTERM;
}
else {
if (!scan_opts(argc, argv, 1, opts, 5, 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;
list_opt |= dumbterminal ? LIST_OPT_DUMBTERM : 0;
}
if (init && verify_action("Initialize non-volatile configuration")) {
config_init();
need_update = true;
}
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 {
doneone = true;
ret = get_config(dp, title, list_opt, onevalue); // do this opt
}
switch (ret) {
case CONFIG_DONE:
goto done;
case CONFIG_ABORT:
memcpy(config, backup_config, sizeof(struct _config));
return;
case CONFIG_CHANGED:
need_update = true;
case CONFIG_OK:
dp += len;
break;
case CONFIG_BACK:
dp = &config->config_data[0];
continue;
case CONFIG_BAD:
// Nothing - make him do it again
diag_printf ("** invalid entry\n");
onevalue = NULL; // request a good value be typed in - or abort/whatever
}
}
done:
if (NULL != onlyone && !doneone) {
#ifdef CYGSEM_REDBOOT_ALLOW_DYNAMIC_FLASH_CONFIG_DATA
if (verify_action("** entry '%s' not found - add", onlyone)) {
struct config_option opt;
diag_printf("Trying to add value\n");
}
#else
diag_printf("** entry '%s' not found\n", onlyone);
#endif
}
if (!need_update)
return;
flash_write_config(true);
}
#ifdef CYGSEM_REDBOOT_FLASH_ALIASES
static cmd_fun do_alias;
RedBoot_cmd("alias",
"Manage aliases kept in FLASH memory",
"name [value]",
do_alias
);
static void
make_alias(char *alias, char *name)
{
diag_sprintf(alias, "alias/%s", name);
}
static void
do_alias(int argc, char *argv[])
{
char name[80];
char *val;
struct config_option opt;
switch (argc) {
case 2:
make_alias(name, argv[1]);
if (flash_get_config(name, &val, CONFIG_STRING)) {
diag_printf("'%s' = '%s'\n", argv[1], val);
} else {
diag_printf("'%s' not found\n", argv[1]);
}
break;
case 3:
if (strlen(argv[2]) >= MAX_STRING_LENGTH) {
diag_printf("Sorry, value is too long\n");
break;
}
make_alias(name, argv[1]);
opt.type = CONFIG_STRING;
opt.enable = (char *)0;
opt.enable_sense = 1;
opt.key = name;
opt.dflt = (CYG_ADDRESS)argv[2];
flash_add_config(&opt, true);
break;
default:
diag_printf("usage: alias name [value]\n");
}
}
// Lookup an alias. First try plain string aliases. If that fails try
// other types so allowing access to all configured values. This allows
// for alias (macro) expansion of normal 'fconfig' data, such as the
// board IP address.
char *
flash_lookup_alias(char *alias, char *alias_buf)
{
char name[80];
char *val;
unsigned char * dp;
void *val_ptr;
int type;
bool hold_bool_val;
long hold_long_val;
#ifdef CYGPKG_REDBOOT_NETWORKING
int esa_ptr;
#endif
make_alias(name, alias);
if (flash_get_config(name, &val, CONFIG_STRING)) {
return val;
} else {
dp = flash_lookup_config(alias);
if (dp) {
val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
switch (type = CONFIG_OBJECT_TYPE(dp)) {
case CONFIG_BOOL:
memcpy(&hold_bool_val, val_ptr, sizeof(bool));
diag_sprintf(alias_buf, "%s", hold_bool_val ? "true" : "false");
break;
case CONFIG_INT:
memcpy(&hold_long_val, val_ptr, sizeof(unsigned long));
diag_sprintf(alias_buf,"%ld", hold_long_val);
break;
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
diag_sprintf(alias_buf,"%s", inet_ntoa((in_addr_t *)val_ptr));
break;
case CONFIG_ESA:
for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) {
diag_sprintf(alias_buf+(3*esa_ptr), "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
if (esa_ptr < (sizeof(enet_addr_t)-1)) diag_printf(":");
}
break;
#endif
case CONFIG_SCRIPT:
return (char *) val_ptr;
break;
default:
return (char *)NULL;
}
return alias_buf;
}
return (char *)NULL;
}
}
#endif // CYGSEM_REDBOOT_FLASH_ALIASES
//
// Write the in-memory copy of the configuration data to the flash device.
//
void
flash_write_config(bool prompt)
{
#if defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
void *err_addr;
#if !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
int stat;
#endif
#endif
config->len = sizeof(struct _config);
config->key1 = CONFIG_KEY1;
config->key2 = CONFIG_KEY2;
config->cksum = cyg_crc32((unsigned char *)config, sizeof(struct _config)-sizeof(config->cksum));
if (!prompt || verify_action("Update RedBoot non-volatile configuration")) {
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
fis_update_directory();
#else
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
// Insure [quietly] that the config page is unlocked before trying to update
flash_unlock((void *)cfg_base, cfg_size, (void **)&err_addr);
#endif
if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) {
diag_printf(" initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
} else {
if ((stat = flash_program(cfg_base, (void *)config, sizeof(struct _config),
(void **)&err_addr)) != 0) {
diag_printf("Error writing config data at %p: %s\n",
err_addr, flash_errmsg(stat));
}
}
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
// Insure [quietly] that the config data is locked after the update
flash_lock((void *)cfg_base, cfg_size, (void **)&err_addr);
#endif
#endif // CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
#else // CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
write_eeprom(config, sizeof(struct _config)); // into 'config'
#endif
}
}
//
// Find the configuration entry for a particular key
//
static unsigned char *
flash_lookup_config(char *key)
{
unsigned char *dp;
int len;
if (!config_ok) return (unsigned char *)NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -