Mercurial > nand-ecoscentric
diff packages/redboot/current/src/flash.c @ 1223:dbcfe4e0dbd2
New platform - TAMS MOAB - and generic changes to support it
| author | gthomas |
|---|---|
| date | Fri, 19 Sep 2003 17:11:18 +0000 |
| parents | 517229d4051f |
| children | dc8c964619a0 |
line wrap: on
line diff
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -9,6 +9,7 @@ // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// Copyright (C) 2003 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -64,23 +65,6 @@ // Round a quantity up #define _rup(n,s) ((((n)+(s-1))/s)*s) -#ifdef CYGSEM_REDBOOT_FLASH_CONFIG -#include <flash_config.h> - -// Configuration data, saved in FLASH, used to set/update RedBoot -// normal "configuration" data items. -static struct _config { - unsigned long len; - unsigned long key1; - unsigned char config_data[MAX_CONFIG_DATA-(4*4)]; - unsigned long key2; - unsigned long cksum; -} *config, *backup_config; -#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK -static struct _config *readonly_config; -#endif -#endif - #ifdef CYGOPT_REDBOOT_FIS // Image management functions local_cmd_entry("init", @@ -178,18 +162,17 @@ RedBoot_nested_cmd("fis", ); // Local data used by these routines -static void *flash_start, *flash_end; -static int flash_block_size, flash_num_blocks; +void *flash_start, *flash_end; +int flash_block_size, flash_num_blocks; #ifdef CYGOPT_REDBOOT_FIS -static void *fis_work_block; -static void *fis_addr; -static int fisdir_size; // Size of FIS directory. +void *fis_work_block; +void *fis_addr; +int fisdir_size; // Size of FIS directory. #endif #ifdef CYGSEM_REDBOOT_FLASH_CONFIG -static void *cfg_base; // Location in Flash of config data -static int cfg_size; // Length of config data - rounded to Flash block size -// Prototypes for local functions -static unsigned char *flash_lookup_config(char *key); +extern void *cfg_base; // Location in Flash of config data +extern int cfg_size; // Length of config data - rounded to Flash block size +extern struct _config *config; #endif static void @@ -212,7 +195,9 @@ fis_lookup(char *name, int *num) { int i; struct fis_image_desc *img; + void *err_addr; + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); img = (struct fis_image_desc *)fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { if ((img->name[0] != (unsigned char)0xFF) && @@ -224,7 +209,7 @@ fis_lookup(char *name, int *num) return (struct fis_image_desc *)0; } -static void +void fis_update_directory(void) { int stat; @@ -324,7 +309,7 @@ fis_init(int argc, char *argv[]) img++; redboot_flash_start += redboot_image_size; #endif -#ifdef CYGSEM_REDBOOT_FLASH_CONFIG +#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) // And a descriptor for the configuration data memset(img, 0, sizeof(*img)); strcpy(img->name, "RedBoot config"); @@ -402,7 +387,9 @@ fis_init(int argc, char *argv[]) erase_start = redboot_flash_start; // high water of created images // Now the empty bits between the end of Redboot and the cfg and dir // blocks. -#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG) +#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \ + defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \ + !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG) if (fis_addr > cfg_base) { erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data } else { @@ -456,6 +443,7 @@ fis_list(int argc, char *argv[]) bool show_cksums = false; bool show_datalen = false; struct option_info opts[2]; + void *err_addr; #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB // FIXME: this is somewhat half-baked @@ -477,7 +465,8 @@ fis_list(int argc, char *argv[]) { return; } - img = (struct fis_image_desc *) fis_addr; + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + img = (struct fis_image_desc *) fis_work_block; // Let diag_printf do the formatting in both cases, rather than counting // cols by hand.... diag_printf("%-16s %-10s %-10s %-10s %-s\n", @@ -506,9 +495,11 @@ fis_free(int argc, char *argv[]) { unsigned long *fis_ptr, *fis_end; unsigned long *area_start; + void *err_addr; // Do not search the area reserved for pre-RedBoot systems: - fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_ptr = (unsigned long *)((CYG_ADDRESS)fis_work_block + CYGNUM_REDBOOT_FLASH_RESERVED_BASE + CYGBLD_REDBOOT_MIN_IMAGE_SIZE); fis_end = (unsigned long *)(CYG_ADDRESS)flash_end; @@ -545,9 +536,11 @@ fis_find_free(CYG_ADDRESS *addr, unsigne { unsigned long *fis_ptr, *fis_end; unsigned long *area_start; + void *err_addr; // Do not search the area reserved for pre-RedBoot systems: - fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_ptr = (unsigned long *)((CYG_ADDRESS)fis_work_block + CYGNUM_REDBOOT_FLASH_RESERVED_BASE + CYGBLD_REDBOOT_MIN_IMAGE_SIZE); fis_end = (unsigned long *)(CYG_ADDRESS)flash_end; @@ -623,7 +616,7 @@ fis_create(int argc, char *argv[]) return; } - memcpy(fis_work_block, fis_addr, fisdir_size); + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); defaults_assumed = false; if (name) { // Search existing files to acquire defaults for params not specified: @@ -779,7 +772,12 @@ fis_create(int argc, char *argv[]) img->size = length; img->data_length = img_size; #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK - img->file_cksum = cyg_crc32((unsigned char *)flash_addr, img_size); + if (!no_copy) { + img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size); + } else { + // No way to compute this, sorry + img->file_cksum = 0; + } #endif fis_update_directory(); } @@ -825,7 +823,6 @@ fis_delete(int argc, char *argv[]) num_reserved++; #endif - memcpy(fis_work_block, fis_addr, fisdir_size); img = fis_lookup(name, &i); if (img) { if (i < num_reserved) { @@ -864,6 +861,7 @@ fis_load(int argc, char *argv[]) #ifdef CYGPKG_COMPRESS_ZLIB bool decompress = false; #endif + void *err_addr; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address"); @@ -881,7 +879,6 @@ fis_load(int argc, char *argv[]) fis_usage("invalid arguments"); return; } - memcpy(fis_work_block, fis_addr, fisdir_size); if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { diag_printf("No image '%s' found\n", name); return; @@ -891,9 +888,8 @@ fis_load(int argc, char *argv[]) } // Load image from FLASH into RAM #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS - if ((mem_addr < (CYG_ADDRESS)user_ram_start) || - ((mem_addr+img->data_length) >= (CYG_ADDRESS)user_ram_end)) { - diag_printf("Not a loadable image\n"); + if (!valid_address((void *)mem_addr)) { + diag_printf("Not a loadable image - try using -b ADDRESS option\n"); return; } #endif @@ -927,11 +923,11 @@ fis_load(int argc, char *argv[]) load_address_end = (unsigned long)p->out_buf; // Reload fis directory - memcpy(fis_work_block, fis_addr, fisdir_size); + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); } else // dangling block #endif { - memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length); + flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr); // Set load address/top load_address = mem_addr; @@ -949,6 +945,7 @@ fis_load(int argc, char *argv[]) if (cksum != img->file_cksum) { diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n", img->file_cksum, cksum); + entry_address = NO_MEMORY; } } #endif @@ -1105,7 +1102,6 @@ fis_lock(int argc, char *argv[]) /* Get parameters from image if specified */ if (name) { struct fis_image_desc *img; - memcpy(fis_work_block, fis_addr, fisdir_size); if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { diag_printf("No image '%s' found\n", name); return; @@ -1152,7 +1148,6 @@ fis_unlock(int argc, char *argv[]) if (name) { struct fis_image_desc *img; - memcpy(fis_work_block, fis_addr, fisdir_size); if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { diag_printf("No image '%s' found\n", name); return; @@ -1178,7 +1173,7 @@ fis_unlock(int argc, char *argv[]) #endif // This is set non-zero if the FLASH subsystem has successfully been initialized -static int __flash_init = 0; +int __flash_init = 0; void _flash_info(void) @@ -1188,10 +1183,11 @@ void flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size); } -static bool +bool do_flash_init(void) { int stat; + void *err_addr; if (!__flash_init) { if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), @@ -1224,7 +1220,7 @@ do_flash_init(void) fis_addr = (void *)((CYG_ADDRESS)flash_start + (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); } - memcpy(fis_work_block, fis_addr, flash_block_size); + flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); #endif __flash_init = 1; } @@ -1263,907 +1259,4 @@ do_fis(int argc, char *argv[]) fis_usage("unrecognized command"); } -#ifdef CYGSEM_REDBOOT_FLASH_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) -#define LIST_OPT_DUMBTERM (8) - -static void config_init(void); - -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; - - 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; - } - 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; - 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; - - if (!__flash_init) { - diag_printf("Sorry, no FLASH memory is available\n"); - return; - } - 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", 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) -{ - 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(void) -{ -#ifndef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG - int stat; - void *err_addr; -#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 (verify_action("Update RedBoot non-volatile configuration")) { -#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG - memcpy(fis_work_block, fis_addr, fisdir_size); - fis_update_directory(); -#else // CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG -#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 - } -} - -// -// 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; -} - -// -// 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; -#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"); - return flash_get_config(key, val, type); - } - } -#endif - 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(); - } - 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; - } - } - 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; - - config_ok = false; - script = (unsigned char *)0; - if (!do_flash_init()) return; - config = (struct _config *)(workspace_end-sizeof(struct _config)); - backup_config = (struct _config *)((CYG_ADDRESS)config-sizeof(struct _config)); - workspace_end = (unsigned char *)backup_config; - cfg_size = (flash_block_size > sizeof(struct _config)) ? - sizeof(struct _config) : - _rup(sizeof(struct _config), flash_block_size); -#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG - cfg_size = _rup(cfg_size, sizeof(struct fis_image_desc)); - if ((flash_block_size-cfg_size) < 8*sizeof(struct fis_image_desc)) { - // Too bad this can't be checked at compile/build time - diag_printf("Sorry, FLASH config exceeds available space in FIS directory\n"); - return; - } - fisdir_size = flash_block_size - cfg_size; - cfg_base = (void *)(((CYG_ADDRESS)fis_addr + flash_block_size) - cfg_size); -#else - 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 -#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK - readonly_config = cfg_base; -#endif - memcpy(config, cfg_base, sizeof(struct _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_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_FIRST); - -#endif // CYGSEM_REDBOOT_FLASH_CONFIG - // EOF flash.c
