comparison 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
comparison
equal deleted inserted replaced
1222:f0bd64ec9405 1223:dbcfe4e0dbd2
7 //========================================================================== 7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN#### 8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // ------------------------------------------- 9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System. 10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. 11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
12 // 13 //
13 // eCos is free software; you can redistribute it and/or modify it under 14 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free 15 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version. 16 // Software Foundation; either version 2 or (at your option) any later version.
16 // 17 //
62 #endif 63 #endif
63 64
64 // Round a quantity up 65 // Round a quantity up
65 #define _rup(n,s) ((((n)+(s-1))/s)*s) 66 #define _rup(n,s) ((((n)+(s-1))/s)*s)
66 67
67 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
68 #include <flash_config.h>
69
70 // Configuration data, saved in FLASH, used to set/update RedBoot
71 // normal "configuration" data items.
72 static struct _config {
73 unsigned long len;
74 unsigned long key1;
75 unsigned char config_data[MAX_CONFIG_DATA-(4*4)];
76 unsigned long key2;
77 unsigned long cksum;
78 } *config, *backup_config;
79 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
80 static struct _config *readonly_config;
81 #endif
82 #endif
83
84 #ifdef CYGOPT_REDBOOT_FIS 68 #ifdef CYGOPT_REDBOOT_FIS
85 // Image management functions 69 // Image management functions
86 local_cmd_entry("init", 70 local_cmd_entry("init",
87 "Initialize FLASH Image System [FIS]", 71 "Initialize FLASH Image System [FIS]",
88 "[-f]", 72 "[-f]",
176 do_fis, 160 do_fis,
177 __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__ 161 __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
178 ); 162 );
179 163
180 // Local data used by these routines 164 // Local data used by these routines
181 static void *flash_start, *flash_end; 165 void *flash_start, *flash_end;
182 static int flash_block_size, flash_num_blocks; 166 int flash_block_size, flash_num_blocks;
183 #ifdef CYGOPT_REDBOOT_FIS 167 #ifdef CYGOPT_REDBOOT_FIS
184 static void *fis_work_block; 168 void *fis_work_block;
185 static void *fis_addr; 169 void *fis_addr;
186 static int fisdir_size; // Size of FIS directory. 170 int fisdir_size; // Size of FIS directory.
187 #endif 171 #endif
188 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG 172 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
189 static void *cfg_base; // Location in Flash of config data 173 extern void *cfg_base; // Location in Flash of config data
190 static int cfg_size; // Length of config data - rounded to Flash block size 174 extern int cfg_size; // Length of config data - rounded to Flash block size
191 // Prototypes for local functions 175 extern struct _config *config;
192 static unsigned char *flash_lookup_config(char *key);
193 #endif 176 #endif
194 177
195 static void 178 static void
196 fis_usage(char *why) 179 fis_usage(char *why)
197 { 180 {
210 struct fis_image_desc * 193 struct fis_image_desc *
211 fis_lookup(char *name, int *num) 194 fis_lookup(char *name, int *num)
212 { 195 {
213 int i; 196 int i;
214 struct fis_image_desc *img; 197 struct fis_image_desc *img;
215 198 void *err_addr;
199
200 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
216 img = (struct fis_image_desc *)fis_work_block; 201 img = (struct fis_image_desc *)fis_work_block;
217 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 202 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
218 if ((img->name[0] != (unsigned char)0xFF) && 203 if ((img->name[0] != (unsigned char)0xFF) &&
219 (strcasecmp(name, img->name) == 0)) { 204 (strcasecmp(name, img->name) == 0)) {
220 if (num) *num = i; 205 if (num) *num = i;
222 } 207 }
223 } 208 }
224 return (struct fis_image_desc *)0; 209 return (struct fis_image_desc *)0;
225 } 210 }
226 211
227 static void 212 void
228 fis_update_directory(void) 213 fis_update_directory(void)
229 { 214 {
230 int stat; 215 int stat;
231 void *err_addr; 216 void *err_addr;
232 217
322 img->mem_base = redboot_flash_start; 307 img->mem_base = redboot_flash_start;
323 img->size = redboot_image_size; 308 img->size = redboot_image_size;
324 img++; 309 img++;
325 redboot_flash_start += redboot_image_size; 310 redboot_flash_start += redboot_image_size;
326 #endif 311 #endif
327 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG 312 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
328 // And a descriptor for the configuration data 313 // And a descriptor for the configuration data
329 memset(img, 0, sizeof(*img)); 314 memset(img, 0, sizeof(*img));
330 strcpy(img->name, "RedBoot config"); 315 strcpy(img->name, "RedBoot config");
331 img->flash_base = (CYG_ADDRESS)cfg_base; 316 img->flash_base = (CYG_ADDRESS)cfg_base;
332 img->mem_base = (CYG_ADDRESS)cfg_base; 317 img->mem_base = (CYG_ADDRESS)cfg_base;
400 #endif 385 #endif
401 // second deal with the larger part in the main: 386 // second deal with the larger part in the main:
402 erase_start = redboot_flash_start; // high water of created images 387 erase_start = redboot_flash_start; // high water of created images
403 // Now the empty bits between the end of Redboot and the cfg and dir 388 // Now the empty bits between the end of Redboot and the cfg and dir
404 // blocks. 389 // blocks.
405 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG) 390 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
391 defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \
392 !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
406 if (fis_addr > cfg_base) { 393 if (fis_addr > cfg_base) {
407 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data 394 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data
408 } else { 395 } else {
409 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data 396 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
410 } 397 }
454 struct fis_image_desc *img; 441 struct fis_image_desc *img;
455 int i; 442 int i;
456 bool show_cksums = false; 443 bool show_cksums = false;
457 bool show_datalen = false; 444 bool show_datalen = false;
458 struct option_info opts[2]; 445 struct option_info opts[2];
446 void *err_addr;
459 447
460 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB 448 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
461 // FIXME: this is somewhat half-baked 449 // FIXME: this is somewhat half-baked
462 extern void arm_fis_list(void); 450 extern void arm_fis_list(void);
463 arm_fis_list(); 451 arm_fis_list();
475 #endif 463 #endif
476 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) 464 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, ""))
477 { 465 {
478 return; 466 return;
479 } 467 }
480 img = (struct fis_image_desc *) fis_addr; 468 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
469 img = (struct fis_image_desc *) fis_work_block;
481 // Let diag_printf do the formatting in both cases, rather than counting 470 // Let diag_printf do the formatting in both cases, rather than counting
482 // cols by hand.... 471 // cols by hand....
483 diag_printf("%-16s %-10s %-10s %-10s %-s\n", 472 diag_printf("%-16s %-10s %-10s %-10s %-s\n",
484 "Name","FLASH addr", 473 "Name","FLASH addr",
485 show_cksums ? "Checksum" : "Mem addr", 474 show_cksums ? "Checksum" : "Mem addr",
504 static void 493 static void
505 fis_free(int argc, char *argv[]) 494 fis_free(int argc, char *argv[])
506 { 495 {
507 unsigned long *fis_ptr, *fis_end; 496 unsigned long *fis_ptr, *fis_end;
508 unsigned long *area_start; 497 unsigned long *area_start;
498 void *err_addr;
509 499
510 // Do not search the area reserved for pre-RedBoot systems: 500 // Do not search the area reserved for pre-RedBoot systems:
511 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + 501 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
502 fis_ptr = (unsigned long *)((CYG_ADDRESS)fis_work_block +
512 CYGNUM_REDBOOT_FLASH_RESERVED_BASE + 503 CYGNUM_REDBOOT_FLASH_RESERVED_BASE +
513 CYGBLD_REDBOOT_MIN_IMAGE_SIZE); 504 CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
514 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end; 505 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
515 area_start = fis_ptr; 506 area_start = fis_ptr;
516 while (fis_ptr < fis_end) { 507 while (fis_ptr < fis_end) {
543 static bool 534 static bool
544 fis_find_free(CYG_ADDRESS *addr, unsigned long length) 535 fis_find_free(CYG_ADDRESS *addr, unsigned long length)
545 { 536 {
546 unsigned long *fis_ptr, *fis_end; 537 unsigned long *fis_ptr, *fis_end;
547 unsigned long *area_start; 538 unsigned long *area_start;
539 void *err_addr;
548 540
549 // Do not search the area reserved for pre-RedBoot systems: 541 // Do not search the area reserved for pre-RedBoot systems:
550 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + 542 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
543 fis_ptr = (unsigned long *)((CYG_ADDRESS)fis_work_block +
551 CYGNUM_REDBOOT_FLASH_RESERVED_BASE + 544 CYGNUM_REDBOOT_FLASH_RESERVED_BASE +
552 CYGBLD_REDBOOT_MIN_IMAGE_SIZE); 545 CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
553 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end; 546 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
554 area_start = fis_ptr; 547 area_start = fis_ptr;
555 while (fis_ptr < fis_end) { 548 while (fis_ptr < fis_end) {
621 { 614 {
622 fis_usage("invalid arguments"); 615 fis_usage("invalid arguments");
623 return; 616 return;
624 } 617 }
625 618
626 memcpy(fis_work_block, fis_addr, fisdir_size); 619 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
627 defaults_assumed = false; 620 defaults_assumed = false;
628 if (name) { 621 if (name) {
629 // Search existing files to acquire defaults for params not specified: 622 // Search existing files to acquire defaults for params not specified:
630 img = fis_lookup(name, NULL); 623 img = fis_lookup(name, NULL);
631 if (img) { 624 if (img) {
777 img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr); 770 img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr);
778 img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set 771 img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set
779 img->size = length; 772 img->size = length;
780 img->data_length = img_size; 773 img->data_length = img_size;
781 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK 774 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
782 img->file_cksum = cyg_crc32((unsigned char *)flash_addr, img_size); 775 if (!no_copy) {
776 img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size);
777 } else {
778 // No way to compute this, sorry
779 img->file_cksum = 0;
780 }
783 #endif 781 #endif
784 fis_update_directory(); 782 fis_update_directory();
785 } 783 }
786 } 784 }
787 785
823 #endif 821 #endif
824 #if 1 // And the descriptor for the descriptor table itself 822 #if 1 // And the descriptor for the descriptor table itself
825 num_reserved++; 823 num_reserved++;
826 #endif 824 #endif
827 825
828 memcpy(fis_work_block, fis_addr, fisdir_size);
829 img = fis_lookup(name, &i); 826 img = fis_lookup(name, &i);
830 if (img) { 827 if (img) {
831 if (i < num_reserved) { 828 if (i < num_reserved) {
832 diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->name); 829 diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->name);
833 return; 830 return;
862 #endif 859 #endif
863 int num_options; 860 int num_options;
864 #ifdef CYGPKG_COMPRESS_ZLIB 861 #ifdef CYGPKG_COMPRESS_ZLIB
865 bool decompress = false; 862 bool decompress = false;
866 #endif 863 #endif
864 void *err_addr;
867 865
868 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 866 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
869 (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address"); 867 (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
870 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, 868 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
871 (void **)&show_cksum, (bool *)0, "display checksum"); 869 (void **)&show_cksum, (bool *)0, "display checksum");
879 if (!scan_opts(argc, argv, 2, opts, num_options, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) 877 if (!scan_opts(argc, argv, 2, opts, num_options, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
880 { 878 {
881 fis_usage("invalid arguments"); 879 fis_usage("invalid arguments");
882 return; 880 return;
883 } 881 }
884 memcpy(fis_work_block, fis_addr, fisdir_size);
885 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { 882 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
886 diag_printf("No image '%s' found\n", name); 883 diag_printf("No image '%s' found\n", name);
887 return; 884 return;
888 } 885 }
889 if (!mem_addr_set) { 886 if (!mem_addr_set) {
890 mem_addr = img->mem_base; 887 mem_addr = img->mem_base;
891 } 888 }
892 // Load image from FLASH into RAM 889 // Load image from FLASH into RAM
893 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS 890 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
894 if ((mem_addr < (CYG_ADDRESS)user_ram_start) || 891 if (!valid_address((void *)mem_addr)) {
895 ((mem_addr+img->data_length) >= (CYG_ADDRESS)user_ram_end)) { 892 diag_printf("Not a loadable image - try using -b ADDRESS option\n");
896 diag_printf("Not a loadable image\n");
897 return; 893 return;
898 } 894 }
899 #endif 895 #endif
900 #ifdef CYGPKG_COMPRESS_ZLIB 896 #ifdef CYGPKG_COMPRESS_ZLIB
901 if (decompress) { 897 if (decompress) {
925 // Set load address/top 921 // Set load address/top
926 load_address = mem_addr; 922 load_address = mem_addr;
927 load_address_end = (unsigned long)p->out_buf; 923 load_address_end = (unsigned long)p->out_buf;
928 924
929 // Reload fis directory 925 // Reload fis directory
930 memcpy(fis_work_block, fis_addr, fisdir_size); 926 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
931 } else // dangling block 927 } else // dangling block
932 #endif 928 #endif
933 { 929 {
934 memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length); 930 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
935 931
936 // Set load address/top 932 // Set load address/top
937 load_address = mem_addr; 933 load_address = mem_addr;
938 load_address_end = mem_addr + img->data_length; 934 load_address_end = mem_addr + img->data_length;
939 } 935 }
947 // When decompressing, leave CRC checking to decompressor 943 // When decompressing, leave CRC checking to decompressor
948 if (!decompress && img->file_cksum) { 944 if (!decompress && img->file_cksum) {
949 if (cksum != img->file_cksum) { 945 if (cksum != img->file_cksum) {
950 diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n", 946 diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
951 img->file_cksum, cksum); 947 img->file_cksum, cksum);
948 entry_address = NO_MEMORY;
952 } 949 }
953 } 950 }
954 #endif 951 #endif
955 } 952 }
956 #endif // CYGOPT_REDBOOT_FIS 953 #endif // CYGOPT_REDBOOT_FIS
1103 } 1100 }
1104 1101
1105 /* Get parameters from image if specified */ 1102 /* Get parameters from image if specified */
1106 if (name) { 1103 if (name) {
1107 struct fis_image_desc *img; 1104 struct fis_image_desc *img;
1108 memcpy(fis_work_block, fis_addr, fisdir_size);
1109 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { 1105 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
1110 diag_printf("No image '%s' found\n", name); 1106 diag_printf("No image '%s' found\n", name);
1111 return; 1107 return;
1112 } 1108 }
1113 1109
1150 return; 1146 return;
1151 } 1147 }
1152 1148
1153 if (name) { 1149 if (name) {
1154 struct fis_image_desc *img; 1150 struct fis_image_desc *img;
1155 memcpy(fis_work_block, fis_addr, fisdir_size);
1156 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { 1151 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
1157 diag_printf("No image '%s' found\n", name); 1152 diag_printf("No image '%s' found\n", name);
1158 return; 1153 return;
1159 } 1154 }
1160 1155
1176 } 1171 }
1177 } 1172 }
1178 #endif 1173 #endif
1179 1174
1180 // This is set non-zero if the FLASH subsystem has successfully been initialized 1175 // This is set non-zero if the FLASH subsystem has successfully been initialized
1181 static int __flash_init = 0; 1176 int __flash_init = 0;
1182 1177
1183 void 1178 void
1184 _flash_info(void) 1179 _flash_info(void)
1185 { 1180 {
1186 if (!__flash_init) return; 1181 if (!__flash_init) return;
1187 diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n", 1182 diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n",
1188 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size); 1183 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
1189 } 1184 }
1190 1185
1191 static bool 1186 bool
1192 do_flash_init(void) 1187 do_flash_init(void)
1193 { 1188 {
1194 int stat; 1189 int stat;
1190 void *err_addr;
1195 1191
1196 if (!__flash_init) { 1192 if (!__flash_init) {
1197 if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), 1193 if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE),
1198 FLASH_MIN_WORKSPACE, diag_printf)) != 0) { 1194 FLASH_MIN_WORKSPACE, diag_printf)) != 0) {
1199 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); 1195 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
1222 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); 1218 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1223 } else { 1219 } else {
1224 fis_addr = (void *)((CYG_ADDRESS)flash_start + 1220 fis_addr = (void *)((CYG_ADDRESS)flash_start +
1225 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); 1221 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1226 } 1222 }
1227 memcpy(fis_work_block, fis_addr, flash_block_size); 1223 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
1228 #endif 1224 #endif
1229 __flash_init = 1; 1225 __flash_init = 1;
1230 } 1226 }
1231 return true; 1227 return true;
1232 } 1228 }
1261 return; 1257 return;
1262 } 1258 }
1263 fis_usage("unrecognized command"); 1259 fis_usage("unrecognized command");
1264 } 1260 }
1265 1261
1266 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
1267
1268 static bool config_ok;
1269
1270 #define CONFIG_KEY1 0x0BADFACE
1271 #define CONFIG_KEY2 0xDEADDEAD
1272
1273 #define CONFIG_DONE 0
1274 #define CONFIG_ABORT -1
1275 #define CONFIG_CHANGED 1
1276 #define CONFIG_OK 2
1277 #define CONFIG_BACK 3
1278 #define CONFIG_BAD 4
1279
1280 // Note: the following options are related. If 'boot_script' is false, then
1281 // the other values are used in the configuration. Because of the way
1282 // that configuration tables are generated, they should have names which
1283 // are related. The configuration options will show up lexicographically
1284 // ordered, thus the peculiar naming.
1285 RedBoot_config_option("Run script at boot",
1286 boot_script,
1287 ALWAYS_ENABLED, true,
1288 CONFIG_BOOL,
1289 false
1290 );
1291 RedBoot_config_option("Boot script",
1292 boot_script_data,
1293 "boot_script", true,
1294 CONFIG_SCRIPT,
1295 ""
1296 );
1297 // Some preprocessor magic for building the [constant] prompt string
1298 #define __cat(s1,c2,s3) s1 #c2 s3
1299 #define _cat(s1,c2,s3) __cat(s1,c2,s3)
1300 RedBoot_config_option(_cat("Boot script timeout (",
1301 CYGNUM_REDBOOT_BOOT_SCRIPT_TIMEOUT_RESOLUTION,
1302 "ms resolution)"),
1303 boot_script_timeout,
1304 "boot_script", true,
1305 CONFIG_INT,
1306 0
1307 );
1308 #undef __cat
1309 #undef _cat
1310
1311 #ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
1312 RedBoot_config_option("Console baud rate",
1313 console_baud_rate,
1314 ALWAYS_ENABLED, true,
1315 CONFIG_INT,
1316 CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD
1317 );
1318 #endif
1319
1320 CYG_HAL_TABLE_BEGIN( __CONFIG_options_TAB__, RedBoot_config_options);
1321 CYG_HAL_TABLE_END( __CONFIG_options_TAB_END__, RedBoot_config_options);
1322
1323 extern struct config_option __CONFIG_options_TAB__[], __CONFIG_options_TAB_END__[];
1324
1325 //
1326 // Layout of config data
1327 // Each data item is variable length, with the name, type and dependencies
1328 // encoded into the object.
1329 // offset contents
1330 // 0 data type
1331 // 1 length of name (N)
1332 // 2 enable sense
1333 // 3 length of enable key (M)
1334 // 4 key name
1335 // N+4 enable key
1336 // M+N+4 data value
1337 //
1338
1339 #define CONFIG_OBJECT_TYPE(dp) (dp)[0]
1340 #define CONFIG_OBJECT_KEYLEN(dp) (dp)[1]
1341 #define CONFIG_OBJECT_ENABLE_SENSE(dp) (dp)[2]
1342 #define CONFIG_OBJECT_ENABLE_KEYLEN(dp) (dp)[3]
1343 #define CONFIG_OBJECT_KEY(dp) ((dp)+4)
1344 #define CONFIG_OBJECT_ENABLE_KEY(dp) ((dp)+4+CONFIG_OBJECT_KEYLEN(dp))
1345 #define CONFIG_OBJECT_VALUE(dp) ((dp)+4+CONFIG_OBJECT_KEYLEN(dp)+CONFIG_OBJECT_ENABLE_KEYLEN(dp))
1346
1347 #define LIST_OPT_LIST_ONLY (1)
1348 #define LIST_OPT_NICKNAMES (2)
1349 #define LIST_OPT_FULLNAMES (4)
1350 #define LIST_OPT_DUMBTERM (8)
1351
1352 static void config_init(void);
1353
1354 static int
1355 get_config(unsigned char *dp, char *title, int list_opt, char *newvalue )
1356 {
1357 char line[256], hold_line[256], *sp, *lp;
1358 int ret;
1359 bool hold_bool_val, new_bool_val, enable;
1360 unsigned long hold_int_val, new_int_val;
1361 #ifdef CYGPKG_REDBOOT_NETWORKING
1362 in_addr_t hold_ip_val, new_ip_val;
1363 enet_addr_t hold_esa_val;
1364 int esa_ptr;
1365 char *esp;
1366 #endif
1367 void *val_ptr;
1368 int type;
1369
1370 if (CONFIG_OBJECT_ENABLE_KEYLEN(dp)) {
1371 flash_get_config(CONFIG_OBJECT_ENABLE_KEY(dp), &enable, CONFIG_BOOL);
1372 if (((bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && !enable) ||
1373 (!(bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && enable)) {
1374 return CONFIG_OK; // Disabled field
1375 }
1376 }
1377 lp = line; *lp = '\0';
1378 val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
1379 if (LIST_OPT_NICKNAMES & list_opt)
1380 diag_printf("%s: ", CONFIG_OBJECT_KEY(dp));
1381 if (LIST_OPT_FULLNAMES & list_opt) {
1382 if (title != (char *)NULL) {
1383 diag_printf("%s: ", title);
1384 } else {
1385 diag_printf("%s: ", CONFIG_OBJECT_KEY(dp));
1386 }
1387 }
1388 switch (type = CONFIG_OBJECT_TYPE(dp)) {
1389 case CONFIG_BOOL:
1390 memcpy(&hold_bool_val, val_ptr, sizeof(bool));
1391 lp += diag_sprintf(lp, "%s", hold_bool_val ? "true" : "false");
1392 break;
1393 case CONFIG_INT:
1394 memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
1395 lp += diag_sprintf(lp, "%ld", hold_int_val);
1396 break;
1397 #ifdef CYGPKG_REDBOOT_NETWORKING
1398 case CONFIG_IP:
1399 lp += diag_sprintf(lp, "%s", inet_ntoa((in_addr_t *)val_ptr));
1400 if (0 == strcmp("0.0.0.0", line) && !(LIST_OPT_LIST_ONLY & list_opt)) {
1401 // then we have a deeply unhelpful starting text - kill it off
1402 // (unless we are just listing all values)
1403 lp = line; *lp = '\0';
1404 }
1405 break;
1406 case CONFIG_ESA:
1407 for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) {
1408 lp += diag_sprintf(lp, "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
1409 if (esa_ptr < (sizeof(enet_addr_t)-1)) lp += diag_sprintf(lp, ":");
1410 }
1411 break;
1412 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
1413 case CONFIG_NETPORT:
1414 lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr);
1415 break;
1416 #endif
1417 #endif
1418 case CONFIG_STRING:
1419 lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr);
1420 break;
1421 case CONFIG_SCRIPT:
1422 diag_printf("\n");
1423 sp = lp = (unsigned char *)val_ptr;
1424 while (*sp) {
1425 while (*lp != '\n') lp++;
1426 *lp = '\0';
1427 diag_printf(".. %s\n", sp);
1428 *lp++ = '\n';
1429 sp = lp;
1430 }
1431 break;
1432 }
1433 if (LIST_OPT_LIST_ONLY & list_opt) {
1434 diag_printf("%s\n", line);
1435 return CONFIG_OK;
1436 }
1437 if (type != CONFIG_SCRIPT) {
1438 if (NULL != newvalue) {
1439 ret = strlen(newvalue);
1440 if (ret > sizeof(line))
1441 return CONFIG_BAD;
1442 strcpy(hold_line, line); // Hold the old value for comparison
1443 strcpy(line, newvalue);
1444 diag_printf("Setting to %s\n", newvalue);
1445 } else {
1446 // read from terminal
1447 strcpy(hold_line, line);
1448 if (LIST_OPT_DUMBTERM & list_opt) {
1449 diag_printf( (CONFIG_STRING == type ?
1450 "%s > " :
1451 "%s ? " ), line);
1452 *line = '\0';
1453 }
1454 ret = _rb_gets_preloaded(line, sizeof(line), 0);
1455 }
1456 if (ret < 0) return CONFIG_ABORT;
1457 // empty input - leave value untouched (else DNS goes away for a
1458 // minute to try to look it up) but we must accept empty value for strings.
1459 if (0 == line[0] && CONFIG_STRING != type) return CONFIG_OK;
1460 if (strcmp(line, hold_line) == 0) return CONFIG_OK; // Just a CR - leave value untouched
1461 lp = &line[strlen(line)-1];
1462 if (*lp == '.') return CONFIG_DONE;
1463 if (*lp == '^') return CONFIG_BACK;
1464 }
1465 switch (type) {
1466 case CONFIG_BOOL:
1467 memcpy(&hold_bool_val, val_ptr, sizeof(bool));
1468 if (!parse_bool(line, &new_bool_val)) {
1469 return CONFIG_BAD;
1470 }
1471 if (hold_bool_val != new_bool_val) {
1472 memcpy(val_ptr, &new_bool_val, sizeof(bool));
1473 return CONFIG_CHANGED;
1474 } else {
1475 return CONFIG_OK;
1476 }
1477 break;
1478 case CONFIG_INT:
1479 memcpy(&hold_int_val, val_ptr, sizeof(unsigned long));
1480 if (!parse_num(line, &new_int_val, 0, 0)) {
1481 return CONFIG_BAD;
1482 }
1483 if (hold_int_val != new_int_val) {
1484 memcpy(val_ptr, &new_int_val, sizeof(unsigned long));
1485 return CONFIG_CHANGED;
1486 } else {
1487 return CONFIG_OK;
1488 }
1489 break;
1490 #ifdef CYGPKG_REDBOOT_NETWORKING
1491 case CONFIG_IP:
1492 memcpy(&hold_ip_val.s_addr, &((in_addr_t *)val_ptr)->s_addr, sizeof(in_addr_t));
1493 if (!_gethostbyname(line, &new_ip_val)) {
1494 return CONFIG_BAD;
1495 }
1496 if (hold_ip_val.s_addr != new_ip_val.s_addr) {
1497 memcpy(val_ptr, &new_ip_val, sizeof(in_addr_t));
1498 return CONFIG_CHANGED;
1499 } else {
1500 return CONFIG_OK;
1501 }
1502 break;
1503 case CONFIG_ESA:
1504 memcpy(&hold_esa_val, val_ptr, sizeof(enet_addr_t));
1505 esp = line;
1506 for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) {
1507 unsigned long esa_byte;
1508 if (!parse_num(esp, &esa_byte, &esp, ":")) {
1509 memcpy(val_ptr, &hold_esa_val, sizeof(enet_addr_t));
1510 return CONFIG_BAD;
1511 }
1512 ((unsigned char *)val_ptr)[esa_ptr] = esa_byte;
1513 }
1514 return CONFIG_CHANGED;
1515 break;
1516 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
1517 case CONFIG_NETPORT:
1518 if (strlen(line) >= MAX_STRING_LENGTH || net_devindex(line) < 0) {
1519 int index;
1520 const char *name;
1521 diag_printf("Sorry, Port name must be one of:\n");
1522 for (index = 0; (name = net_devname(index)) != NULL; index++)
1523 diag_printf(" %s\n", name);
1524 return CONFIG_BAD;
1525 }
1526 strcpy((unsigned char *)val_ptr, line);
1527 break;
1528 #endif
1529 #endif
1530 case CONFIG_SCRIPT:
1531 // Assume it always changes
1532 sp = (unsigned char *)val_ptr;
1533 diag_printf("Enter script, terminate with empty line\n");
1534 while (true) {
1535 *sp = '\0';
1536 diag_printf(">> ");
1537 ret = _rb_gets(line, sizeof(line), 0);
1538 if (ret < 0) return CONFIG_ABORT;
1539 if (strlen(line) == 0) break;
1540 lp = line;
1541 while (*lp) {
1542 *sp++ = *lp++;
1543 }
1544 *sp++ = '\n';
1545 }
1546 break;
1547 case CONFIG_STRING:
1548 if (strlen(line) >= MAX_STRING_LENGTH) {
1549 diag_printf("Sorry, value is too long\n");
1550 return CONFIG_BAD;
1551 }
1552 strcpy((unsigned char *)val_ptr, line);
1553 break;
1554 }
1555 return CONFIG_CHANGED;
1556 }
1557
1558 //
1559 // Manage configuration information with the FLASH
1560 //
1561
1562 static int
1563 config_length(int type)
1564 {
1565 switch (type) {
1566 case CONFIG_BOOL:
1567 return sizeof(bool);
1568 case CONFIG_INT:
1569 return sizeof(unsigned long);
1570 #ifdef CYGPKG_REDBOOT_NETWORKING
1571 case CONFIG_IP:
1572 return sizeof(in_addr_t);
1573 case CONFIG_ESA:
1574 // Would like this to be sizeof(enet_addr_t), but that causes much
1575 // pain since it fouls the alignment of data which follows.
1576 return 8;
1577 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
1578 case CONFIG_NETPORT:
1579 return MAX_STRING_LENGTH;
1580 #endif
1581 #endif
1582 case CONFIG_STRING:
1583 return MAX_STRING_LENGTH;
1584 case CONFIG_SCRIPT:
1585 return MAX_SCRIPT_LENGTH;
1586 default:
1587 return 0;
1588 }
1589 }
1590
1591 static cmd_fun do_flash_config;
1592 RedBoot_cmd("fconfig",
1593 "Manage configuration kept in FLASH memory",
1594 "[-i] [-l] [-n] [-f] [-d] | [-d] nickname [value]",
1595 do_flash_config
1596 );
1597
1598 static void
1599 do_flash_config(int argc, char *argv[])
1600 {
1601 bool need_update = false;
1602 struct config_option *optend = __CONFIG_options_TAB_END__;
1603 struct config_option *opt = __CONFIG_options_TAB__;
1604 struct option_info opts[5];
1605 bool list_only;
1606 bool nicknames;
1607 bool fullnames;
1608 bool dumbterminal;
1609 int list_opt = 0;
1610 unsigned char *dp;
1611 int len, ret;
1612 char *title;
1613 char *onlyone = NULL;
1614 char *onevalue = NULL;
1615 bool doneone = false;
1616 bool init = false;
1617
1618 if (!__flash_init) {
1619 diag_printf("Sorry, no FLASH memory is available\n");
1620 return;
1621 }
1622 memcpy(backup_config, config, sizeof(struct _config));
1623 script = (unsigned char *)0;
1624
1625 init_opts(&opts[0], 'l', false, OPTION_ARG_TYPE_FLG,
1626 (void **)&list_only, (bool *)0, "list configuration only");
1627 init_opts(&opts[1], 'n', false, OPTION_ARG_TYPE_FLG,
1628 (void **)&nicknames, (bool *)0, "show nicknames");
1629 init_opts(&opts[2], 'f', false, OPTION_ARG_TYPE_FLG,
1630 (void **)&fullnames, (bool *)0, "show full names");
1631 init_opts(&opts[3], 'i', false, OPTION_ARG_TYPE_FLG,
1632 (void **)&init, (bool *)0, "initialize configuration database");
1633 init_opts(&opts[4], 'd', false, OPTION_ARG_TYPE_FLG,
1634 (void **)&dumbterminal, (bool *)0, "dumb terminal: no clever edits");
1635
1636 // First look to see if we are setting or getting a single option
1637 // by just quoting its nickname
1638 if ( (2 == argc && '-' != argv[1][0]) ||
1639 (3 == argc && '-' != argv[1][0] && '-' != argv[2][0])) {
1640 // then the command was "fconfig foo [value]"
1641 onlyone = argv[1];
1642 onevalue = (3 == argc) ? argv[2] : NULL;
1643 list_opt = LIST_OPT_NICKNAMES;
1644 }
1645 // Next see if we are setting or getting a single option with a dumb
1646 // terminal invoked, ie. no line editing.
1647 else if (3 == argc &&
1648 '-' == argv[1][0] && 'd' == argv[1][1] && 0 == argv[1][2] &&
1649 '-' != argv[2][0]) {
1650 // then the command was "fconfig -d foo"
1651 onlyone = argv[2];
1652 onevalue = NULL;
1653 list_opt = LIST_OPT_NICKNAMES | LIST_OPT_DUMBTERM;
1654 }
1655 else {
1656 if (!scan_opts(argc, argv, 1, opts, 5, 0, 0, ""))
1657 return;
1658 list_opt |= list_only ? LIST_OPT_LIST_ONLY : 0;
1659 list_opt |= nicknames ? LIST_OPT_NICKNAMES : LIST_OPT_FULLNAMES;
1660 list_opt |= fullnames ? LIST_OPT_FULLNAMES : 0;
1661 list_opt |= dumbterminal ? LIST_OPT_DUMBTERM : 0;
1662 }
1663
1664 if (init && verify_action("Initialize non-volatile configuration")) {
1665 config_init();
1666 need_update = true;
1667 }
1668
1669 dp = &config->config_data[0];
1670 while (dp < &config->config_data[sizeof(config->config_data)]) {
1671 if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {
1672 break;
1673 }
1674 len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
1675 config_length(CONFIG_OBJECT_TYPE(dp));
1676 // Provide a title for well known [i.e. builtin] objects
1677 title = (char *)NULL;
1678 opt = __CONFIG_options_TAB__;
1679 while (opt != optend) {
1680 if (strcmp(opt->key, CONFIG_OBJECT_KEY(dp)) == 0) {
1681 title = opt->title;
1682 break;
1683 }
1684 opt++;
1685 }
1686 if ( onlyone && 0 != strcmp(CONFIG_OBJECT_KEY(dp), onlyone) )
1687 ret = CONFIG_OK; // skip this entry
1688 else {
1689 doneone = true;
1690 ret = get_config(dp, title, list_opt, onevalue); // do this opt
1691 }
1692 switch (ret) {
1693 case CONFIG_DONE:
1694 goto done;
1695 case CONFIG_ABORT:
1696 memcpy(config, backup_config, sizeof(struct _config));
1697 return;
1698 case CONFIG_CHANGED:
1699 need_update = true;
1700 case CONFIG_OK:
1701 dp += len;
1702 break;
1703 case CONFIG_BACK:
1704 dp = &config->config_data[0];
1705 continue;
1706 case CONFIG_BAD:
1707 // Nothing - make him do it again
1708 diag_printf ("** invalid entry\n");
1709 onevalue = NULL; // request a good value be typed in - or abort/whatever
1710 }
1711 }
1712
1713 done:
1714 if (NULL != onlyone && !doneone) {
1715 #ifdef CYGSEM_REDBOOT_ALLOW_DYNAMIC_FLASH_CONFIG_DATA
1716 if (verify_action("** entry '%s' not found - add", onlyone)) {
1717 struct config_option opt;
1718 diag_printf("Trying to add value\n");
1719 }
1720 #else
1721 diag_printf("** entry '%s' not found", onlyone);
1722 #endif
1723 }
1724 if (!need_update)
1725 return;
1726 flash_write_config();
1727 }
1728
1729
1730 #ifdef CYGSEM_REDBOOT_FLASH_ALIASES
1731 static cmd_fun do_alias;
1732 RedBoot_cmd("alias",
1733 "Manage aliases kept in FLASH memory",
1734 "name [value]",
1735 do_alias
1736 );
1737
1738 static void
1739 make_alias(char *alias, char *name)
1740 {
1741 diag_sprintf(alias, "alias/%s", name);
1742 }
1743
1744 static void
1745 do_alias(int argc, char *argv[])
1746 {
1747 char name[80];
1748 char *val;
1749 struct config_option opt;
1750
1751 switch (argc) {
1752 case 2:
1753 make_alias(name, argv[1]);
1754 if (flash_get_config(name, &val, CONFIG_STRING)) {
1755 diag_printf("'%s' = '%s'\n", argv[1], val);
1756 } else {
1757 diag_printf("'%s' not found\n", argv[1]);
1758 }
1759 break;
1760 case 3:
1761 if (strlen(argv[2]) >= MAX_STRING_LENGTH) {
1762 diag_printf("Sorry, value is too long\n");
1763 break;
1764 }
1765 make_alias(name, argv[1]);
1766 opt.type = CONFIG_STRING;
1767 opt.enable = (char *)0;
1768 opt.enable_sense = 1;
1769 opt.key = name;
1770 opt.dflt = (CYG_ADDRESS)argv[2];
1771 flash_add_config(&opt, true);
1772 break;
1773 default:
1774 diag_printf("usage: alias name [value]\n");
1775 }
1776 }
1777
1778 // Lookup an alias. First try plain string aliases. If that fails try
1779 // other types so allowing access to all configured values. This allows
1780 // for alias (macro) expansion of normal 'fconfig' data, such as the
1781 // board IP address.
1782 char *
1783 flash_lookup_alias(char *alias, char *alias_buf)
1784 {
1785 char name[80];
1786 char *val;
1787 unsigned char * dp;
1788 void *val_ptr;
1789 int type;
1790 bool hold_bool_val;
1791 long hold_long_val;
1792 #ifdef CYGPKG_REDBOOT_NETWORKING
1793 int esa_ptr;
1794 #endif
1795
1796 make_alias(name, alias);
1797 if (flash_get_config(name, &val, CONFIG_STRING)) {
1798 return val;
1799 } else {
1800 dp = flash_lookup_config(alias);
1801 if (dp) {
1802 val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
1803 switch (type = CONFIG_OBJECT_TYPE(dp)) {
1804 case CONFIG_BOOL:
1805 memcpy(&hold_bool_val, val_ptr, sizeof(bool));
1806 diag_sprintf(alias_buf, "%s", hold_bool_val ? "true" : "false");
1807 break;
1808 case CONFIG_INT:
1809 memcpy(&hold_long_val, val_ptr, sizeof(unsigned long));
1810 diag_sprintf(alias_buf,"%ld", hold_long_val);
1811 break;
1812 #ifdef CYGPKG_REDBOOT_NETWORKING
1813 case CONFIG_IP:
1814 diag_sprintf(alias_buf,"%s", inet_ntoa((in_addr_t *)val_ptr));
1815 break;
1816 case CONFIG_ESA:
1817 for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) {
1818 diag_sprintf(alias_buf+(3*esa_ptr), "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);
1819 if (esa_ptr < (sizeof(enet_addr_t)-1)) diag_printf(":");
1820 }
1821 break;
1822 #endif
1823 case CONFIG_SCRIPT:
1824 return (char *) val_ptr;
1825 break;
1826 default:
1827 return (char *)NULL;
1828 }
1829 return alias_buf;
1830 }
1831 return (char *)NULL;
1832 }
1833 }
1834
1835 #endif // CYGSEM_REDBOOT_FLASH_ALIASES
1836
1837 //
1838 // Write the in-memory copy of the configuration data to the flash device.
1839 //
1840 void
1841 flash_write_config(void)
1842 {
1843 #ifndef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
1844 int stat;
1845 void *err_addr;
1846 #endif
1847
1848 config->len = sizeof(struct _config);
1849 config->key1 = CONFIG_KEY1;
1850 config->key2 = CONFIG_KEY2;
1851 config->cksum = cyg_crc32((unsigned char *)config, sizeof(struct _config)-sizeof(config->cksum));
1852 if (verify_action("Update RedBoot non-volatile configuration")) {
1853 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
1854 memcpy(fis_work_block, fis_addr, fisdir_size);
1855 fis_update_directory();
1856 #else // CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
1857 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
1858 // Insure [quietly] that the config page is unlocked before trying to update
1859 flash_unlock((void *)cfg_base, cfg_size, (void **)&err_addr);
1860 #endif
1861 if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) {
1862 diag_printf(" initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
1863 } else {
1864 if ((stat = flash_program(cfg_base, (void *)config, sizeof(struct _config),
1865 (void **)&err_addr)) != 0) {
1866 diag_printf("Error writing config data at %p: %s\n",
1867 err_addr, flash_errmsg(stat));
1868 }
1869 }
1870 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
1871 // Insure [quietly] that the config data is locked after the update
1872 flash_lock((void *)cfg_base, cfg_size, (void **)&err_addr);
1873 #endif
1874 #endif
1875 }
1876 }
1877
1878 //
1879 // Find the configuration entry for a particular key
1880 //
1881 static unsigned char *
1882 flash_lookup_config(char *key)
1883 {
1884 unsigned char *dp;
1885 int len;
1886
1887 if (!config_ok) return (unsigned char *)NULL;
1888
1889 dp = &config->config_data[0];
1890 while (dp < &config->config_data[sizeof(config->config_data)]) {
1891 len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
1892 config_length(CONFIG_OBJECT_TYPE(dp));
1893 if (strcmp(key, CONFIG_OBJECT_KEY(dp)) == 0) {
1894 return dp;
1895 }
1896 dp += len;
1897 }
1898 // diag_printf("Can't find config data for '%s'\n", key);
1899 return false;
1900 }
1901
1902 //
1903 // Retrieve a data object from the data base (in memory copy)
1904 //
1905 bool
1906 flash_get_config(char *key, void *val, int type)
1907 {
1908 unsigned char *dp;
1909 void *val_ptr;
1910 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
1911 struct _config *save_config = 0;
1912 #endif
1913
1914 if (!config_ok) return false;
1915
1916 if ((dp = flash_lookup_config(key)) != (unsigned char *)NULL) {
1917 if (CONFIG_OBJECT_TYPE(dp) == type) {
1918 val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
1919 switch (type) {
1920 // Note: the data may be unaligned in the configuration data
1921 case CONFIG_BOOL:
1922 memcpy(val, val_ptr, sizeof(bool));
1923 break;
1924 case CONFIG_INT:
1925 memcpy(val, val_ptr, sizeof(unsigned long));
1926 break;
1927 #ifdef CYGPKG_REDBOOT_NETWORKING
1928 case CONFIG_IP:
1929 memcpy(val, val_ptr, sizeof(in_addr_t));
1930 break;
1931 case CONFIG_ESA:
1932 memcpy(val, val_ptr, sizeof(enet_addr_t));
1933 break;
1934 #endif
1935 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
1936 case CONFIG_NETPORT:
1937 #endif
1938 case CONFIG_STRING:
1939 case CONFIG_SCRIPT:
1940 // Just return a pointer to the script/line
1941 *(unsigned char **)val = (unsigned char *)val_ptr;
1942 break;
1943 }
1944 } else {
1945 diag_printf("Request for config value '%s' - wrong type\n", key);
1946 }
1947 return true;
1948 }
1949 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
1950 // Did not find key. Is configuration data valid?
1951 // Check to see if the config data is valid, if not, revert to
1952 // readonly mode, by setting config to readonly_config. We
1953 // will set it back before we leave this function.
1954 if ( (config != readonly_config) && ((cyg_crc32((unsigned char *)config,
1955 sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
1956 (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2))) {
1957 save_config = config;
1958 config = readonly_config;
1959 if ((cyg_crc32((unsigned char *)config,
1960 sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
1961 (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
1962 diag_printf("FLASH configuration checksum error or invalid key\n");
1963 config = save_config;
1964 return false;
1965 }
1966 else{
1967 diag_printf("Getting config information in READONLY mode\n");
1968 return flash_get_config(key, val, type);
1969 }
1970 }
1971 #endif
1972 return false;
1973 }
1974
1975 //
1976 // Copy data into the config area
1977 //
1978 static void
1979 flash_config_insert_value(unsigned char *dp, struct config_option *opt)
1980 {
1981 switch (opt->type) {
1982 // Note: the data may be unaligned in the configuration data
1983 case CONFIG_BOOL:
1984 memcpy(dp, (void *)&opt->dflt, sizeof(bool));
1985 break;
1986 case CONFIG_INT:
1987 memcpy(dp, (void *)&opt->dflt, sizeof(unsigned long));
1988 break;
1989 #ifdef CYGPKG_REDBOOT_NETWORKING
1990 case CONFIG_IP:
1991 memcpy(dp, (void *)&opt->dflt, sizeof(in_addr_t));
1992 break;
1993 case CONFIG_ESA:
1994 memcpy(dp, (void *)opt->dflt, sizeof(enet_addr_t));
1995 break;
1996 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
1997 case CONFIG_NETPORT:
1998 // validate dflt and if not acceptable use first port
1999 {
2000 int index;
2001 const char *name;
2002 for (index = 0; (name = net_devname(index)) != NULL; index++)
2003 if (!strcmp((char *)opt->dflt, name))
2004 break;
2005 if (name == NULL)
2006 name = net_devname(0);
2007 memcpy(dp, name, strlen(name) + 1);
2008 }
2009 break;
2010 #endif
2011 #endif
2012 case CONFIG_STRING:
2013 memcpy(dp, (void *)opt->dflt, config_length(CONFIG_STRING));
2014 break;
2015 case CONFIG_SCRIPT:
2016 break;
2017 }
2018 }
2019
2020 //
2021 // Add a new option to the database
2022 //
2023 bool
2024 flash_add_config(struct config_option *opt, bool update)
2025 {
2026 unsigned char *dp, *kp;
2027 int len, elen, size;
2028
2029 // If data item is already present, just update it
2030 // Note: only the data value can be thusly changed
2031 if ((dp = flash_lookup_config(opt->key)) != (unsigned char *)NULL) {
2032 flash_config_insert_value(CONFIG_OBJECT_VALUE(dp), opt);
2033 if (update) {
2034 flash_write_config();
2035 }
2036 return true;
2037 }
2038 // Add the data item
2039 dp = &config->config_data[0];
2040 size = 0;
2041 while (size < sizeof(config->config_data)) {
2042 if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {
2043 kp = opt->key;
2044 len = strlen(kp) + 1;
2045 size += len + 2 + 2 + config_length(opt->type);
2046 if (opt->enable) {
2047 elen = strlen(opt->enable) + 1;
2048 size += elen;
2049 } else {
2050 elen = 0;
2051 }
2052 if (size > sizeof(config->config_data)) {
2053 break;
2054 }
2055 CONFIG_OBJECT_TYPE(dp) = opt->type;
2056 CONFIG_OBJECT_KEYLEN(dp) = len;
2057 CONFIG_OBJECT_ENABLE_SENSE(dp) = opt->enable_sense;
2058 CONFIG_OBJECT_ENABLE_KEYLEN(dp) = elen;
2059 dp = CONFIG_OBJECT_KEY(dp);
2060 while (*kp) *dp++ += *kp++;
2061 *dp++ = '\0';
2062 if (elen) {
2063 kp = opt->enable;
2064 while (*kp) *dp++ += *kp++;
2065 *dp++ = '\0';
2066 }
2067 flash_config_insert_value(dp, opt);
2068 if (update) {
2069 flash_write_config();
2070 }
2071 return true;
2072 } else {
2073 len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
2074 config_length(CONFIG_OBJECT_TYPE(dp));
2075 dp += len;
2076 size += len;
2077 }
2078 }
2079 diag_printf("No space to add '%s'\n", opt->key);
2080 return false;
2081 }
2082
2083 //
2084 // Reset/initialize configuration data - used only when starting from scratch
2085 //
2086 static void
2087 config_init(void)
2088 {
2089 // Well known option strings
2090 struct config_option *optend = __CONFIG_options_TAB_END__;
2091 struct config_option *opt = __CONFIG_options_TAB__;
2092
2093 memset(config, 0, sizeof(struct _config));
2094 while (opt != optend) {
2095 if (!flash_add_config(opt, false)) {
2096 return;
2097 }
2098 opt++;
2099 }
2100 config_ok = true;
2101 }
2102
2103 //
2104 // Attempt to get configuration information from the FLASH.
2105 // If available (i.e. good checksum, etc), initialize "known"
2106 // values for later use.
2107 //
2108 static void
2109 load_flash_config(void)
2110 {
2111 bool use_boot_script;
2112
2113 config_ok = false;
2114 script = (unsigned char *)0;
2115 if (!do_flash_init()) return;
2116 config = (struct _config *)(workspace_end-sizeof(struct _config));
2117 backup_config = (struct _config *)((CYG_ADDRESS)config-sizeof(struct _config));
2118 workspace_end = (unsigned char *)backup_config;
2119 cfg_size = (flash_block_size > sizeof(struct _config)) ?
2120 sizeof(struct _config) :
2121 _rup(sizeof(struct _config), flash_block_size);
2122 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
2123 cfg_size = _rup(cfg_size, sizeof(struct fis_image_desc));
2124 if ((flash_block_size-cfg_size) < 8*sizeof(struct fis_image_desc)) {
2125 // Too bad this can't be checked at compile/build time
2126 diag_printf("Sorry, FLASH config exceeds available space in FIS directory\n");
2127 return;
2128 }
2129 fisdir_size = flash_block_size - cfg_size;
2130 cfg_base = (void *)(((CYG_ADDRESS)fis_addr + flash_block_size) - cfg_size);
2131 #else
2132 if (CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK < 0) {
2133 cfg_base = (void *)((CYG_ADDRESS)flash_end + 1 -
2134 _rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
2135 } else {
2136 cfg_base = (void *)((CYG_ADDRESS)flash_start +
2137 _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
2138 }
2139 #endif
2140 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
2141 readonly_config = cfg_base;
2142 #endif
2143 memcpy(config, cfg_base, sizeof(struct _config));
2144 if ((cyg_crc32((unsigned char *)config,
2145 sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
2146 (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
2147 diag_printf("FLASH configuration checksum error or invalid key\n");
2148 config_init();
2149 return;
2150 }
2151 config_ok = true;
2152 flash_get_config("boot_script", &use_boot_script, CONFIG_BOOL);
2153 if (use_boot_script) {
2154 flash_get_config("boot_script_data", &script, CONFIG_SCRIPT);
2155 flash_get_config("boot_script_timeout", &script_timeout, CONFIG_INT);
2156 }
2157 #ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
2158 if (flash_get_config("console_baud_rate", &console_baud_rate, CONFIG_INT)) {
2159 extern int set_console_baud_rate(int);
2160 set_console_baud_rate(console_baud_rate);
2161 }
2162 #endif
2163 }
2164
2165 RedBoot_init(load_flash_config, RedBoot_INIT_FIRST);
2166
2167 #endif // CYGSEM_REDBOOT_FLASH_CONFIG
2168
2169 // EOF flash.c 1262 // EOF flash.c