📄 fconfig.c
字号:
dp = &config->config_data[0];
while (dp < &config->config_data[sizeof(config->config_data)]) {
len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
config_length(CONFIG_OBJECT_TYPE(dp));
if (strcmp(key, CONFIG_OBJECT_KEY(dp)) == 0) {
return dp;
}
dp += len;
}
// diag_printf("Can't find config data for '%s'\n", key);
return false;
}
//
// Enumerate the keys from the configuration
//
bool
flash_next_key(char *key, int keylen, int *type, int *offset)
{
unsigned char *dp;
int len;
if (!config_ok) return false;
if ((*offset < 0) || (*offset >= MAX_CONFIG_DATA)) return false;
dp = &config->config_data[*offset];
if ((*type = CONFIG_OBJECT_TYPE(dp)) == CONFIG_EMPTY) return false;
if ((len = CONFIG_OBJECT_KEYLEN(dp)) > keylen) return false;
memcpy(key, CONFIG_OBJECT_KEY(dp), len);
*offset += 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
config_length(CONFIG_OBJECT_TYPE(dp));
return true;
}
//
// Retrieve a data object from the data base (in memory copy)
//
bool
flash_get_config(char *key, void *val, int type)
{
unsigned char *dp;
void *val_ptr;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
struct _config *save_config = 0;
bool res;
#endif
if (!config_ok) return false;
if ((dp = flash_lookup_config(key)) != (unsigned char *)NULL) {
if (CONFIG_OBJECT_TYPE(dp) == type) {
val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
switch (type) {
// Note: the data may be unaligned in the configuration data
case CONFIG_BOOL:
memcpy(val, val_ptr, sizeof(bool));
break;
case CONFIG_INT:
memcpy(val, val_ptr, sizeof(unsigned long));
break;
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
memcpy(val, val_ptr, sizeof(in_addr_t));
break;
case CONFIG_ESA:
memcpy(val, val_ptr, sizeof(enet_addr_t));
break;
#endif
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
case CONFIG_NETPORT:
#endif
case CONFIG_STRING:
case CONFIG_SCRIPT:
// Just return a pointer to the script/line
*(unsigned char **)val = (unsigned char *)val_ptr;
break;
}
} else {
diag_printf("Request for config value '%s' - wrong type\n", key);
}
return true;
}
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
// Did not find key. Is configuration data valid?
// Check to see if the config data is valid, if not, revert to
// readonly mode, by setting config to readonly_config. We
// will set it back before we leave this function.
if ( (config != readonly_config) && ((cyg_crc32((unsigned char *)config,
sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
(config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2))) {
save_config = config;
config = readonly_config;
if ((cyg_crc32((unsigned char *)config,
sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
(config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
diag_printf("FLASH configuration checksum error or invalid key\n");
config = save_config;
return false;
}
else{
diag_printf("Getting config information in READONLY mode\n");
res = flash_get_config(key, val, type);
config = save_config;
return res;
}
}
#endif
return false;
}
//
// Update a data object in the data base (in memory copy & backing store)
//
bool
flash_set_config(char *key, void *val, int type)
{
unsigned char *dp;
void *val_ptr;
if (!config_ok) return false;
if ((dp = flash_lookup_config(key)) != (unsigned char *)NULL) {
if (CONFIG_OBJECT_TYPE(dp) == type) {
val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
switch (type) {
// Note: the data may be unaligned in the configuration data
case CONFIG_BOOL:
memcpy(val_ptr, val, sizeof(bool));
break;
case CONFIG_INT:
memcpy(val_ptr, val, sizeof(unsigned long));
break;
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
memcpy(val_ptr, val, sizeof(in_addr_t));
break;
case CONFIG_ESA:
memcpy(val_ptr, val, sizeof(enet_addr_t));
break;
#endif
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
case CONFIG_NETPORT:
#endif
case CONFIG_STRING:
case CONFIG_SCRIPT:
memcpy(val_ptr, val, config_length(CONFIG_STRING));
break;
}
} else {
diag_printf("Can't set config value '%s' - wrong type\n", key);
return false;
}
flash_write_config(false);
return true;
}
return false;
}
//
// Copy data into the config area
//
static void
flash_config_insert_value(unsigned char *dp, struct config_option *opt)
{
switch (opt->type) {
// Note: the data may be unaligned in the configuration data
case CONFIG_BOOL:
memcpy(dp, (void *)&opt->dflt, sizeof(bool));
break;
case CONFIG_INT:
memcpy(dp, (void *)&opt->dflt, sizeof(unsigned long));
break;
#ifdef CYGPKG_REDBOOT_NETWORKING
case CONFIG_IP:
memcpy(dp, (void *)&opt->dflt, sizeof(in_addr_t));
break;
case CONFIG_ESA:
memcpy(dp, (void *)opt->dflt, sizeof(enet_addr_t));
break;
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
case CONFIG_NETPORT:
// validate dflt and if not acceptable use first port
{
int index;
const char *name;
for (index = 0; (name = net_devname(index)) != NULL; index++)
if (!strcmp((char *)opt->dflt, name))
break;
if (name == NULL)
name = net_devname(0);
memcpy(dp, name, strlen(name) + 1);
}
break;
#endif
#endif
case CONFIG_STRING:
memcpy(dp, (void *)opt->dflt, config_length(CONFIG_STRING));
break;
case CONFIG_SCRIPT:
break;
}
}
//
// Add a new option to the database
//
bool
flash_add_config(struct config_option *opt, bool update)
{
unsigned char *dp, *kp;
int len, elen, size;
// If data item is already present, just update it
// Note: only the data value can be thusly changed
if ((dp = flash_lookup_config(opt->key)) != (unsigned char *)NULL) {
flash_config_insert_value(CONFIG_OBJECT_VALUE(dp), opt);
if (update) {
flash_write_config(true);
}
return true;
}
// Add the data item
dp = &config->config_data[0];
size = 0;
while (size < sizeof(config->config_data)) {
if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {
kp = opt->key;
len = strlen(kp) + 1;
size += len + 2 + 2 + config_length(opt->type);
if (opt->enable) {
elen = strlen(opt->enable) + 1;
size += elen;
} else {
elen = 0;
}
if (size > sizeof(config->config_data)) {
break;
}
CONFIG_OBJECT_TYPE(dp) = opt->type;
CONFIG_OBJECT_KEYLEN(dp) = len;
CONFIG_OBJECT_ENABLE_SENSE(dp) = opt->enable_sense;
CONFIG_OBJECT_ENABLE_KEYLEN(dp) = elen;
dp = CONFIG_OBJECT_KEY(dp);
while (*kp) *dp++ += *kp++;
*dp++ = '\0';
if (elen) {
kp = opt->enable;
while (*kp) *dp++ += *kp++;
*dp++ = '\0';
}
flash_config_insert_value(dp, opt);
if (update) {
flash_write_config(true);
}
return true;
} else {
len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
config_length(CONFIG_OBJECT_TYPE(dp));
dp += len;
size += len;
}
}
diag_printf("No space to add '%s'\n", opt->key);
return false;
}
//
// Reset/initialize configuration data - used only when starting from scratch
//
static void
config_init(void)
{
// Well known option strings
struct config_option *optend = __CONFIG_options_TAB_END__;
struct config_option *opt = __CONFIG_options_TAB__;
memset(config, 0, sizeof(struct _config));
while (opt != optend) {
if (!flash_add_config(opt, false)) {
return;
}
opt++;
}
config_ok = true;
}
//
// Attempt to get configuration information from the FLASH.
// If available (i.e. good checksum, etc), initialize "known"
// values for later use.
//
static void
load_flash_config(void)
{
bool use_boot_script;
unsigned char *cfg_temp = (unsigned char *)workspace_end;
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
void *err_addr;
#endif
config_ok = false;
script = (unsigned char *)0;
cfg_temp -= sizeof(struct _config); // Space for primary config data
config = (struct _config *)cfg_temp;
cfg_temp -= sizeof(struct _config); // Space for backup config data
backup_config = (struct _config *)cfg_temp;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
cfg_temp -= sizeof(struct _config); // Space for readonly copy of config data
readonly_config = (struct _config *)cfg_temp;
#endif
workspace_end = cfg_temp;
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
if (!do_flash_init()) return;
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
cfg_size = _rup(sizeof(struct _config), sizeof(struct fis_image_desc));
if ((fisdir_size-cfg_size) < (CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT *
CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE)) {
// Too bad this can't be checked at compile/build time
diag_printf("Sorry, FLASH config exceeds available space in FIS directory\n");
return;
}
cfg_base = (void *)(((CYG_ADDRESS)fis_addr + fisdir_size) - cfg_size);
fisdir_size -= cfg_size;
#else
cfg_size = (flash_block_size > sizeof(struct _config)) ?
sizeof(struct _config) :
_rup(sizeof(struct _config), flash_block_size);
if (CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK < 0) {
cfg_base = (void *)((CYG_ADDRESS)flash_end + 1 -
_rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
} else {
cfg_base = (void *)((CYG_ADDRESS)flash_start +
_rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
}
#endif
flash_read((void *)cfg_base, (void *)config, sizeof(struct _config), (void **)&err_addr);
#else
read_eeprom(config, sizeof(struct _config)); // into 'config'
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
memcpy(readonly_config, config, sizeof(struct _config));
#endif
if ((cyg_crc32((unsigned char *)config,
sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
(config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
diag_printf("**Warning** FLASH configuration checksum error or invalid key\n");
diag_printf("Use 'fconfig -i' to [re]initialize database\n");
config_init();
return;
}
config_ok = true;
flash_get_config("boot_script", &use_boot_script, CONFIG_BOOL);
if (use_boot_script) {
flash_get_config("boot_script_data", &script, CONFIG_SCRIPT);
flash_get_config("boot_script_timeout", &script_timeout, CONFIG_INT);
}
#ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
if (flash_get_config("console_baud_rate", &console_baud_rate, CONFIG_INT)) {
extern int set_console_baud_rate(int);
set_console_baud_rate(console_baud_rate);
}
#endif
}
RedBoot_init(load_flash_config, RedBoot_INIT_SECOND);
// EOF fconfig.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -