⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:
            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, &hold_config, sizeof(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
            printf ("** invalid entry\n");
        }
    }

 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;
            printf("Trying to add value\n");
        }
#else
        printf("** entry '%s' not found", onlyone);
#endif
    }
    if (!need_update)
        return;
    flash_write_config();
}


#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)
{
    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)) {
            printf("'%s' = '%s'\n", argv[1], val);
        } else {
            printf("'%s' not found\n", argv[1]);
        }
        break;
    case 3:
        if (strlen(argv[2]) >= MAX_STRING_LENGTH) {
            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 = (unsigned long)argv[2];
        flash_add_config(&opt, true);
        break;
    default:
        printf("usage: alias name [value]\n");
    }
}

static char *
lookup_alias(char *alias)
{
    char name[80];
    char *val;

    make_alias(name, alias);
    if (flash_get_config(name, &val, CONFIG_STRING)) {
        return val;
    } else {
        return (char *)NULL;
    }
}

bool
_expand_aliases(char *line, int len)
{
    char *lp = line;
    char *ms, *me, *ep;
    char *alias;
    char c;
    int offset, line_len, alias_len;
    bool macro_found = false;

    if ((line_len = strlen(line)) != 0) {
        while (*lp) {
            c = *lp++;
            if ((c == '%') && (*lp == '{')) {
                // Found a macro/alias to expand
                ms = lp+1;
                lp += 2;
                while (*lp && (*lp != '}')) lp++;
                if (!*lp) {
                    printf("Invalid macro/alias '%s'\n", ms);
                    line[0] = '\0';  // Destroy line
                    return false;
                }
                me = lp;
                *me = '\0';
                lp++;
                if ((alias = lookup_alias(ms)) != (char *)NULL) {
                    alias_len = strlen(alias);
                    // See if there is room in the line to expand this macro/alias
                    if ((line_len+alias_len) < len) {
                        // Make a hole by moving data within the line
                        offset = alias_len-strlen(ms)-2;  // Number of bytes being inserted
                        ep = &lp[strlen(lp)-1];
                        me = &ep[offset];
                        while (ep != (lp-1)) {
                            ep[offset-1] = *ep--;
                        }                    
                        *me = '\0';
                        // Insert the macro/alias data
                        lp = ms-2;
                        while (*alias) {
                            if ((alias[0] == '%') && (alias[1] == '{')) macro_found = true;
                            *lp++ = *alias++;
                        }
                        line_len = strlen(line);
                    } else {
                        printf("No room to expand '%s'\n", ms);
                        line[0] = '\0';  // Destroy line
                        return false;
                    }
                } else {
                    printf("Alias '%s' not defined\n", ms);
                    *me = '|';
                }
            } else if (c == '"') {
                // Skip quoted strings
                while (*lp && (*lp != '"')) lp++;
            }            
        }
    }
    return macro_found;
}

void
expand_aliases(char *line, int len)
{
    while (_expand_aliases(line, len)) ;
}
#endif //  CYGSEM_REDBOOT_FLASH_ALIASES

//
// Write the in-memory copy of the configuration data to the flash device.
//
void
flash_write_config(void)
{
    int stat;
    void *err_addr;

	if(!(strap_options_val() & CFG_PROM_BOOT))
		return;

    config.len = sizeof(config);
    config.key1 = CONFIG_KEY1;  
    config.key2 = CONFIG_KEY2;
    config.cksum = crc32((unsigned char *)&config, sizeof(config)-sizeof(config.cksum));
    if (verify_action("Update RedBoot non-volatile configuration")) {
#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) {
            printf("   initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
        } else {
            if ((stat = flash_program(cfg_base, (void *)&config, 
                                      sizeof(config), (void **)&err_addr)) != 0) {
                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
    }
}

//
// 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;

    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;
    }
//    printf("Can't find config data for '%s'\n", key);
    return false;
}

//
// 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;

    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
            case CONFIG_STRING:
            case CONFIG_SCRIPT:
                // Just return a pointer to the script/line
                *(unsigned char **)val = (unsigned char *)val_ptr;
                break;
            }
        } else {
            printf("Request for config value '%s' - wrong type\n", key);
        }
        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;
#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();
        }
        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();
            }
            return true;
        } else {
            len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
                config_length(CONFIG_OBJECT_TYPE(dp));
            dp += len;
            size += len;
        }
    }
    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 optio

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -