Esempio n. 1
0
//
// 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;
}
Esempio n. 2
0
// Change endianness of config data
void
conf_endian_fixup(void *ptr)
{
#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
    struct _config *p = (struct _config *)ptr;
    unsigned char *dp = p->config_data;
    void *val_ptr;
    int len;
    cyg_uint16 u16;
    cyg_uint32 u32;

    p->len = CYG_SWAP32(p->len);
    p->key1 = CYG_SWAP32(p->key1);
    p->key2 = CYG_SWAP32(p->key2);
    p->cksum = CYG_SWAP32(p->cksum);

    while (dp < &p->config_data[sizeof(config->config_data)]) {
        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
            config_length(CONFIG_OBJECT_TYPE(dp));
        val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);

        switch (CONFIG_OBJECT_TYPE(dp)) {
            // Note: the data may be unaligned in the configuration data
        case CONFIG_BOOL:
            if (sizeof(bool) == 2) {
                memcpy(&u16, val_ptr, 2);
                u16 = CYG_SWAP16(u16);
                memcpy(val_ptr, &u16, 2);
            } else if (sizeof(bool) == 4) {
                memcpy(&u32, val_ptr, 4);
                u32 = CYG_SWAP32(u32);
                memcpy(val_ptr, &u32, 4);
            }
            break;
        case CONFIG_INT:
            if (sizeof(unsigned long) == 2) {
                memcpy(&u16, val_ptr, 2);
                u16 = CYG_SWAP16(u16);
                memcpy(val_ptr, &u16, 2);
            } else if (sizeof(unsigned long) == 4) {
                memcpy(&u32, val_ptr, 4);
                u32 = CYG_SWAP32(u32);
                memcpy(val_ptr, &u32, 4);
            }
            break;
        }

        dp += len;
    }
#endif
}
Esempio n. 3
0
//
// 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;
}
Esempio n. 4
0
//
// 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;
}
Esempio n. 5
0
//
// 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;
    }
//    diag_printf("Can't find config data for '%s'\n", key);
    return false;
}
Esempio n. 6
0
//
// 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;
    }
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
static int
get_config(unsigned char *dp, char *title, int list_opt, char *newvalue )
{
    char line[256], hold_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, script_len;

    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
        }
    }
    lp = line;  *lp = '\0';
    val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
    if (LIST_OPT_NICKNAMES & list_opt)
        diag_printf("%s: ", CONFIG_OBJECT_KEY(dp));
    if (LIST_OPT_FULLNAMES & list_opt) {
        if (title != (char *)NULL) {
            diag_printf("%s: ", title);
        } else {
            diag_printf("%s: ", CONFIG_OBJECT_KEY(dp));
        }
    }
    switch (type = CONFIG_OBJECT_TYPE(dp)) {
    case CONFIG_BOOL:
        memcpy(&hold_bool_val, val_ptr, sizeof(bool));
        lp += diag_sprintf(lp, "%s", hold_bool_val ? "true" : "false");
        break;
    case CONFIG_INT:
        memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
        lp += diag_sprintf(lp, "%ld", hold_int_val);
        break;
#ifdef CYGPKG_REDBOOT_NETWORKING
    case CONFIG_IP:
        lp += diag_sprintf(lp, "%s", inet_ntoa((in_addr_t *)val_ptr));
        if (0 == strcmp("0.0.0.0", line) && !(LIST_OPT_LIST_ONLY & list_opt)) {
            // then we have a deeply unhelpful starting text - kill it off
            // (unless we are just listing all values)
            lp = line;  *lp = '\0';
        }
        break;
    case CONFIG_ESA:
        for (esa_ptr = 0;  esa_ptr < sizeof(enet_addr_t);  esa_ptr++) {
            lp += diag_sprintf(lp, "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
            if (esa_ptr < (sizeof(enet_addr_t)-1)) lp += diag_sprintf(lp, ":");
        }
        break;
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
    case CONFIG_NETPORT:
        lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr);
        break;
#endif
#endif
    case CONFIG_STRING:
        lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr);
        break;
    case CONFIG_SCRIPT:
        diag_printf("\n");
        sp = lp = (unsigned char *)val_ptr;
        while (*sp) {
            while (*lp != '\n') lp++;
            *lp = '\0';
            diag_printf(".. %s\n", sp);
            *lp++ = '\n';
            sp = lp;
        }
        break;
    }
    if (LIST_OPT_LIST_ONLY & list_opt) {
        diag_printf("%s\n", line);
        return CONFIG_OK;
    }
    if (type != CONFIG_SCRIPT) {
        if (NULL != newvalue) {
            ret = strlen(newvalue);
            if (ret > sizeof(line))
                return CONFIG_BAD;
            strcpy(hold_line, line); // Hold the old value for comparison
            strcpy(line, newvalue);
            diag_printf("Setting to %s\n", newvalue);
        } else {
            // read from terminal
            strcpy(hold_line, line);
            if (LIST_OPT_DUMBTERM & list_opt) {
                diag_printf( (CONFIG_STRING == type ?
                              "%s > " :
                              "%s ? " ), line);
                *line = '\0';
            }
            ret = _rb_gets_preloaded(line, sizeof(line), 0);
        }
        if (ret < 0) return CONFIG_ABORT;
        // empty input - leave value untouched (else DNS goes away for a
        // minute to try to look it up) but we must accept empty value for strings.
        if (0 == line[0] && CONFIG_STRING != type) return CONFIG_OK; 
        if (strcmp(line, hold_line) == 0) return CONFIG_OK;  // Just a CR - leave value untouched
        lp = &line[strlen(line)-1];
        if (*lp == '.') return CONFIG_DONE;
        if (*lp == '^') 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 (!_gethostbyname(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;
        }
#ifdef CYGSEM_REDBOOT_PLF_ESA_VALIDATE
        if (!cyg_plf_redboot_esa_validate(val_ptr)) {
            memcpy(val_ptr, &hold_esa_val, sizeof(enet_addr_t));
            return CONFIG_BAD;
        }
#endif
        return CONFIG_CHANGED;
        break;
#if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
    case CONFIG_NETPORT:
	if (strlen(line) >= MAX_STRING_LENGTH || net_devindex(line) < 0) {
	    int index;
	    const char *name;
	    diag_printf("Sorry, Port name must be one of:\n");
	    for (index = 0; (name = net_devname(index)) != NULL; index++)
		diag_printf("    %s\n", name);
            return CONFIG_BAD;
	}
        strcpy((unsigned char *)val_ptr, line);
	break;
#endif
#endif
    case CONFIG_SCRIPT:
        // Assume it always changes
        sp = (unsigned char *)val_ptr;
	script_len = 0;
        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;
	    script_len += strlen(line) + 1;
	    if (script_len > config_length(CONFIG_SCRIPT)) {
		diag_printf("script longer than %d not allowed!\n", 
				config_length(CONFIG_SCRIPT));
		return CONFIG_ABORT;
	    }
            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;
}