Mercurial > ecos
comparison packages/redboot/current/src/flash.c @ 1740:0031b615f51c
Add support for reverse endianess of fis and config data
| author | msalter |
|---|---|
| date | Wed, 01 Sep 2004 21:21:30 +0000 |
| parents | 9091309eb665 |
| children | ecd76f498508 |
comparison
equal
deleted
inserted
replaced
| 1739:5ee8bd19b4f5 | 1740:0031b615f51c |
|---|---|
| 6 // | 6 // |
| 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, 2004 Red Hat, Inc. |
| 12 // Copyright (C) 2003, 2004 Gary Thomas | 12 // Copyright (C) 2003, 2004 Gary Thomas |
| 13 // | 13 // |
| 14 // 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 |
| 15 // 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 |
| 16 // 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. |
| 59 #include <sib.h> | 59 #include <sib.h> |
| 60 #include <cyg/infra/cyg_ass.h> // assertion macros | 60 #include <cyg/infra/cyg_ass.h> // assertion macros |
| 61 | 61 |
| 62 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG | 62 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG |
| 63 // Note horrid intertwining of functions, to save precious FLASH | 63 // Note horrid intertwining of functions, to save precious FLASH |
| 64 extern void conf_endian_fixup(void *p); | |
| 64 #endif | 65 #endif |
| 65 | 66 |
| 66 // Round a quantity up | 67 // Round a quantity up |
| 67 #define _rup(n,s) ((((n)+(s-1))/s)*s) | 68 #define _rup(n,s) ((((n)+(s-1))/s)*s) |
| 68 | 69 |
| 189 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat)); | 190 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat)); |
| 190 diag_printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); | 191 diag_printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); |
| 191 } | 192 } |
| 192 | 193 |
| 193 #ifdef CYGOPT_REDBOOT_FIS | 194 #ifdef CYGOPT_REDBOOT_FIS |
| 195 | |
| 196 // fis_endian_fixup() is used to swap endianess if required. | |
| 197 // | |
| 198 static inline void fis_endian_fixup(void *addr) | |
| 199 { | |
| 200 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER | |
| 201 struct fis_image_desc *p = addr; | |
| 202 int cnt = fisdir_size / sizeof(struct fis_image_desc); | |
| 203 | |
| 204 while (cnt-- > 0) { | |
| 205 p->flash_base = CYG_SWAP32(p->flash_base); | |
| 206 p->mem_base = CYG_SWAP32(p->mem_base); | |
| 207 p->size = CYG_SWAP32(p->size); | |
| 208 p->entry_point = CYG_SWAP32(p->entry_point); | |
| 209 p->data_length = CYG_SWAP32(p->data_length); | |
| 210 p->desc_cksum = CYG_SWAP32(p->desc_cksum); | |
| 211 p->file_cksum = CYG_SWAP32(p->file_cksum); | |
| 212 p++; | |
| 213 } | |
| 214 #endif | |
| 215 } | |
| 216 | |
| 217 void | |
| 218 fis_read_directory(void) | |
| 219 { | |
| 220 void *err_addr; | |
| 221 | |
| 222 FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | |
| 223 fis_endian_fixup(fis_work_block); | |
| 224 } | |
| 225 | |
| 194 struct fis_image_desc * | 226 struct fis_image_desc * |
| 195 fis_lookup(char *name, int *num) | 227 fis_lookup(char *name, int *num) |
| 196 { | 228 { |
| 197 int i; | 229 int i; |
| 198 struct fis_image_desc *img; | 230 struct fis_image_desc *img; |
| 199 void *err_addr; | 231 |
| 200 | 232 fis_read_directory(); |
| 201 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 233 |
| 202 img = (struct fis_image_desc *)fis_work_block; | 234 img = (struct fis_image_desc *)fis_work_block; |
| 203 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { | 235 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { |
| 204 if ((img->name[0] != (unsigned char)0xFF) && | 236 if ((img->name[0] != (unsigned char)0xFF) && |
| 205 (strcasecmp(name, img->name) == 0)) { | 237 (strcasecmp(name, img->name) == 0)) { |
| 206 if (num) *num = i; | 238 if (num) *num = i; |
| 214 fis_update_directory(void) | 246 fis_update_directory(void) |
| 215 { | 247 { |
| 216 int stat; | 248 int stat; |
| 217 void *err_addr; | 249 void *err_addr; |
| 218 | 250 |
| 251 fis_endian_fixup(fis_work_block); | |
| 219 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG | 252 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG |
| 220 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); | 253 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); |
| 254 conf_endian_fixup((char *)fis_work_block+fisdir_size); | |
| 221 #endif | 255 #endif |
| 222 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL | 256 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL |
| 223 // Ensure [quietly] that the directory is unlocked before trying to update | 257 // Ensure [quietly] that the directory is unlocked before trying to update |
| 224 flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr); | 258 flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr); |
| 225 #endif | 259 #endif |
| 226 if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) { | 260 if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) { |
| 227 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); | 261 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); |
| 228 } else { | 262 } else { |
| 229 if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size, | 263 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block, |
| 230 (void **)&err_addr)) != 0) { | 264 flash_block_size, (void **)&err_addr)) != 0) { |
| 231 diag_printf("Error writing FIS directory at %p: %s\n", | 265 diag_printf("Error writing FIS directory at %p: %s\n", |
| 232 err_addr, flash_errmsg(stat)); | 266 err_addr, flash_errmsg(stat)); |
| 233 } | 267 } |
| 234 } | 268 } |
| 235 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL | 269 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL |
| 236 // Ensure [quietly] that the directory is locked after the update | 270 // Ensure [quietly] that the directory is locked after the update |
| 237 flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr); | 271 flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr); |
| 238 #endif | 272 #endif |
| 273 fis_endian_fixup(fis_work_block); | |
| 239 } | 274 } |
| 240 | 275 |
| 241 static void | 276 static void |
| 242 fis_init(int argc, char *argv[]) | 277 fis_init(int argc, char *argv[]) |
| 243 { | 278 { |
| 448 struct fis_image_desc *img; | 483 struct fis_image_desc *img; |
| 449 int i, image_indx; | 484 int i, image_indx; |
| 450 bool show_cksums = false; | 485 bool show_cksums = false; |
| 451 bool show_datalen = false; | 486 bool show_datalen = false; |
| 452 struct option_info opts[2]; | 487 struct option_info opts[2]; |
| 453 void *err_addr; | |
| 454 unsigned long last_addr, lowest_addr; | 488 unsigned long last_addr, lowest_addr; |
| 455 bool image_found; | 489 bool image_found; |
| 456 | 490 |
| 457 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB | 491 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB |
| 458 // FIXME: this is somewhat half-baked | 492 // FIXME: this is somewhat half-baked |
| 471 i = 1; | 505 i = 1; |
| 472 #endif | 506 #endif |
| 473 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) { | 507 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) { |
| 474 return; | 508 return; |
| 475 } | 509 } |
| 476 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 510 fis_read_directory(); |
| 511 | |
| 477 // Let diag_printf do the formatting in both cases, rather than counting | 512 // Let diag_printf do the formatting in both cases, rather than counting |
| 478 // cols by hand.... | 513 // cols by hand.... |
| 479 diag_printf("%-16s %-10s %-10s %-10s %-s\n", | 514 diag_printf("%-16s %-10s %-10s %-10s %-s\n", |
| 480 "Name","FLASH addr", | 515 "Name","FLASH addr", |
| 481 show_cksums ? "Checksum" : "Mem addr", | 516 show_cksums ? "Checksum" : "Mem addr", |
| 521 | 556 |
| 522 static int | 557 static int |
| 523 find_free(struct free_chunk *chunks) | 558 find_free(struct free_chunk *chunks) |
| 524 { | 559 { |
| 525 CYG_ADDRESS *fis_ptr, *fis_end; | 560 CYG_ADDRESS *fis_ptr, *fis_end; |
| 526 void *err_addr; | |
| 527 struct fis_image_desc *img; | 561 struct fis_image_desc *img; |
| 528 int i, idx; | 562 int i, idx; |
| 529 int num_chunks = 1; | 563 int num_chunks = 1; |
| 530 | 564 |
| 531 // Do not search the area reserved for pre-RedBoot systems: | 565 // Do not search the area reserved for pre-RedBoot systems: |
| 533 CYGNUM_REDBOOT_FLASH_RESERVED_BASE + | 567 CYGNUM_REDBOOT_FLASH_RESERVED_BASE + |
| 534 CYGBLD_REDBOOT_MIN_IMAGE_SIZE); | 568 CYGBLD_REDBOOT_MIN_IMAGE_SIZE); |
| 535 fis_end = (CYG_ADDRESS *)flash_end; | 569 fis_end = (CYG_ADDRESS *)flash_end; |
| 536 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; | 570 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; |
| 537 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; | 571 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; |
| 538 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 572 fis_read_directory(); |
| 539 img = (struct fis_image_desc *) fis_work_block; | 573 img = (struct fis_image_desc *) fis_work_block; |
| 540 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { | 574 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { |
| 541 if (img->name[0] != (unsigned char)0xFF) { | 575 if (img->name[0] != (unsigned char)0xFF) { |
| 542 // Figure out which chunk this is in and split it | 576 // Figure out which chunk this is in and split it |
| 543 for (idx = 0; idx < num_chunks; idx++) { | 577 for (idx = 0; idx < num_chunks; idx++) { |
| 726 { | 760 { |
| 727 fis_usage("invalid arguments"); | 761 fis_usage("invalid arguments"); |
| 728 return; | 762 return; |
| 729 } | 763 } |
| 730 | 764 |
| 731 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 765 fis_read_directory(); |
| 732 defaults_assumed = false; | 766 defaults_assumed = false; |
| 733 if (name) { | 767 if (name) { |
| 734 // Search existing files to acquire defaults for params not specified: | 768 // Search existing files to acquire defaults for params not specified: |
| 735 img = fis_lookup(name, NULL); | 769 img = fis_lookup(name, NULL); |
| 736 if (img) { | 770 if (img) { |
| 886 prog_ok = false; | 920 prog_ok = false; |
| 887 } | 921 } |
| 888 } | 922 } |
| 889 if (prog_ok) { | 923 if (prog_ok) { |
| 890 // Now program it | 924 // Now program it |
| 891 if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { | 925 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { |
| 892 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); | 926 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); |
| 893 prog_ok = false; | 927 prog_ok = false; |
| 894 } | 928 } |
| 895 } | 929 } |
| 896 } | 930 } |
| 1054 | 1088 |
| 1055 // Set load address/top | 1089 // Set load address/top |
| 1056 load_address = mem_addr; | 1090 load_address = mem_addr; |
| 1057 load_address_end = (unsigned long)p->out_buf; | 1091 load_address_end = (unsigned long)p->out_buf; |
| 1058 | 1092 |
| 1059 // Reload fis directory | 1093 // Reload fis directory |
| 1060 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 1094 fis_read_directory(); |
| 1061 } else // dangling block | 1095 } else // dangling block |
| 1062 #endif | 1096 #endif |
| 1063 { | 1097 { |
| 1064 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr); | 1098 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr); |
| 1065 | 1099 |
| 1154 prog_ok = false; | 1188 prog_ok = false; |
| 1155 } | 1189 } |
| 1156 } | 1190 } |
| 1157 if (prog_ok) { | 1191 if (prog_ok) { |
| 1158 // Now program it | 1192 // Now program it |
| 1159 if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { | 1193 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { |
| 1160 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); | 1194 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); |
| 1161 prog_ok = false; | 1195 prog_ok = false; |
| 1162 } | 1196 } |
| 1163 } | 1197 } |
| 1164 } | 1198 } |
| 1225 | 1259 |
| 1226 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, | 1260 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, |
| 1227 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 1261 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 1228 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, | 1262 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, |
| 1229 (void *)&length, (bool *)&length_set, "length"); | 1263 (void *)&length, (bool *)&length_set, "length"); |
| 1230 if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) | 1264 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) |
| 1231 { | 1265 { |
| 1232 fis_usage("invalid arguments"); | 1266 fis_usage("invalid arguments"); |
| 1233 return; | 1267 return; |
| 1234 } | 1268 } |
| 1235 | 1269 |
| 1272 | 1306 |
| 1273 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, | 1307 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, |
| 1274 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 1308 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 1275 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, | 1309 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, |
| 1276 (void *)&length, (bool *)&length_set, "length"); | 1310 (void *)&length, (bool *)&length_set, "length"); |
| 1277 if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) | 1311 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) |
| 1278 { | 1312 { |
| 1279 fis_usage("invalid arguments"); | 1313 fis_usage("invalid arguments"); |
| 1280 return; | 1314 return; |
| 1281 } | 1315 } |
| 1282 | 1316 |
| 1319 | 1353 |
| 1320 bool | 1354 bool |
| 1321 do_flash_init(void) | 1355 do_flash_init(void) |
| 1322 { | 1356 { |
| 1323 int stat; | 1357 int stat; |
| 1324 void *err_addr; | |
| 1325 | 1358 |
| 1326 if (!__flash_init) { | 1359 if (!__flash_init) { |
| 1327 __flash_init = 1; | 1360 __flash_init = 1; |
| 1328 if ((stat = flash_init(diag_printf)) != 0) { | 1361 if ((stat = flash_init(diag_printf)) != 0) { |
| 1329 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); | 1362 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); |
| 1355 } | 1388 } |
| 1356 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { | 1389 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { |
| 1357 diag_printf("FIS directory doesn't fit\n"); | 1390 diag_printf("FIS directory doesn't fit\n"); |
| 1358 return false; | 1391 return false; |
| 1359 } | 1392 } |
| 1360 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 1393 fis_read_directory(); |
| 1361 #endif | 1394 #endif |
| 1362 } | 1395 } |
| 1363 return true; | 1396 return true; |
| 1364 } | 1397 } |
| 1365 | 1398 |
