Mercurial > ecos
comparison packages/redboot/current/src/flash.c @ 2631:13376f3cfc60 jifl-post-flashv2-merge-20081118
Merge flashv2 branch to trunk, with eCosCentric additions
| author | jlarmour |
|---|---|
| date | Tue, 18 Nov 2008 01:28:11 +0000 |
| parents | 82aabda670f8 |
| children | 74dbf4c3f2e1 |
comparison
equal
deleted
inserted
replaced
| 2630:3e8e26d3183a | 2631:13376f3cfc60 |
|---|---|
| 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) 2004, 2005, 2006, 2007, 2008 eCosCentric Limited | |
| 11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | 12 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. |
| 12 // Copyright (C) 2003, 2004 Gary Thomas | 13 // Copyright (C) 2003, 2004 Gary Thomas |
| 13 // | 14 // |
| 14 // eCos is free software; you can redistribute it and/or modify it under | 15 // 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 | 16 // the terms of the GNU General Public License as published by the Free |
| 31 // License. However the source code for this file must still be made available | 32 // License. However the source code for this file must still be made available |
| 32 // in accordance with section (3) of the GNU General Public License. | 33 // in accordance with section (3) of the GNU General Public License. |
| 33 // | 34 // |
| 34 // This exception does not invalidate any other reasons why a work based on | 35 // This exception does not invalidate any other reasons why a work based on |
| 35 // this file might be covered by the GNU General Public License. | 36 // this file might be covered by the GNU General Public License. |
| 36 // | |
| 37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. | |
| 38 // at http://sources.redhat.com/ecos/ecos-license/ | |
| 39 // ------------------------------------------- | 37 // ------------------------------------------- |
| 40 //####ECOSGPLCOPYRIGHTEND#### | 38 //####ECOSGPLCOPYRIGHTEND#### |
| 41 //========================================================================== | 39 //========================================================================== |
| 42 //#####DESCRIPTIONBEGIN#### | 40 //#####DESCRIPTIONBEGIN#### |
| 43 // | 41 // |
| 162 do_fis, | 160 do_fis, |
| 163 __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__ | 161 __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__ |
| 164 ); | 162 ); |
| 165 | 163 |
| 166 // Local data used by these routines | 164 // Local data used by these routines |
| 167 void *flash_start, *flash_end; | 165 cyg_flashaddr_t flash_start, flash_end; |
| 168 int flash_block_size, flash_num_blocks; | 166 size_t flash_block_size; |
| 167 cyg_uint32 flash_num_blocks; | |
| 169 #ifdef CYGOPT_REDBOOT_FIS | 168 #ifdef CYGOPT_REDBOOT_FIS |
| 170 void *fis_work_block; | 169 void *fis_work_block; |
| 171 void *fis_addr; | 170 cyg_flashaddr_t fis_addr; |
| 172 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS | 171 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS |
| 173 void *redundant_fis_addr; | 172 void *redundant_fis_addr; |
| 174 #endif | 173 #endif |
| 175 int fisdir_size; // Size of FIS directory. | 174 int fisdir_size; // Size of FIS directory. |
| 176 #endif | 175 #endif |
| 177 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG | 176 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG |
| 178 extern void *cfg_base; // Location in Flash of config data | 177 extern cyg_flashaddr_t cfg_base; // Location in Flash of config data |
| 179 extern int cfg_size; // Length of config data - rounded to Flash block size | 178 extern size_t cfg_size; // Length of config data - rounded to Flash block size |
| 180 extern struct _config *config; | 179 extern struct _config *config; |
| 181 #endif | 180 #endif |
| 182 | 181 |
| 183 static void | 182 static void |
| 184 fis_usage(char *why) | 183 fis_usage(char *why) |
| 188 } | 187 } |
| 189 | 188 |
| 190 static void | 189 static void |
| 191 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat) | 190 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat) |
| 192 { | 191 { |
| 193 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat)); | 192 cyg_uint32 i=0; |
| 194 diag_printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); | 193 cyg_flash_info_t info; |
| 194 int ret; | |
| 195 | |
| 196 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, | |
| 197 cyg_flash_errmsg(stat)); | |
| 198 do { | |
| 199 ret = cyg_flash_get_info(i, &info); | |
| 200 if (ret == CYG_FLASH_ERR_OK) { | |
| 201 diag_printf(" valid range is %p - %p\n", (void*)info.start, (void*)info.end); | |
| 202 } | |
| 203 i++; | |
| 204 } while (ret != CYG_FLASH_ERR_INVALID); | |
| 205 } | |
| 206 | |
| 207 // Avoid overwriting the current executable. This is not a complete | |
| 208 // implementation, there may be code outside the text region, but it | |
| 209 // is generally good enough. If either the start of the text region or | |
| 210 // the end of the text region is within the specified range then at | |
| 211 // least some of the code is in the area of flash about to be erased | |
| 212 // or programmed. | |
| 213 static cyg_bool | |
| 214 check_code_overlaps(cyg_flashaddr_t start, cyg_flashaddr_t end) | |
| 215 { | |
| 216 extern char _stext[], _etext[]; | |
| 217 | |
| 218 return ((((unsigned long)&_stext >= (unsigned long)start) && | |
| 219 ((unsigned long)&_stext < (unsigned long)end)) | |
| 220 || | |
| 221 (((unsigned long)&_etext >= (unsigned long)start) && | |
| 222 ((unsigned long)&_etext < (unsigned long)end))); | |
| 195 } | 223 } |
| 196 | 224 |
| 197 #ifdef CYGOPT_REDBOOT_FIS | 225 #ifdef CYGOPT_REDBOOT_FIS |
| 198 | 226 |
| 199 // fis_endian_fixup() is used to swap endianess if required. | 227 // fis_endian_fixup() is used to swap endianess if required. |
| 218 } | 246 } |
| 219 | 247 |
| 220 void | 248 void |
| 221 fis_read_directory(void) | 249 fis_read_directory(void) |
| 222 { | 250 { |
| 223 void *err_addr; | 251 cyg_flashaddr_t err_addr; |
| 224 | 252 |
| 225 FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); | 253 cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr); |
| 226 fis_endian_fixup(fis_work_block); | 254 fis_endian_fixup(fis_work_block); |
| 227 } | 255 } |
| 228 | 256 |
| 229 struct fis_image_desc * | 257 struct fis_image_desc * |
| 230 fis_lookup(char *name, int *num) | 258 fis_lookup(char *name, int *num) |
| 234 | 262 |
| 235 fis_read_directory(); | 263 fis_read_directory(); |
| 236 | 264 |
| 237 img = (struct fis_image_desc *)fis_work_block; | 265 img = (struct fis_image_desc *)fis_work_block; |
| 238 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { | 266 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { |
| 239 if ((img->u.name[0] != (unsigned char)0xFF) && | 267 if ((img->u.name[0] != '\xFF') && |
| 240 (strcasecmp(name, img->u.name) == 0)) { | 268 (strcasecmp(name, img->u.name) == 0)) { |
| 241 if (num) *num = i; | 269 if (num) *num = i; |
| 242 return img; | 270 return img; |
| 243 } | 271 } |
| 244 } | 272 } |
| 256 int do_autolock=autolock; | 284 int do_autolock=autolock; |
| 257 #endif | 285 #endif |
| 258 #endif | 286 #endif |
| 259 | 287 |
| 260 struct fis_image_desc* img=NULL; | 288 struct fis_image_desc* img=NULL; |
| 261 void* err_addr=NULL; | 289 cyg_flashaddr_t err_addr=NULL; |
| 262 void* tmp_fis_addr=NULL; | 290 cyg_flashaddr_t tmp_fis_addr=NULL; |
| 291 int stat; | |
| 263 | 292 |
| 264 /*exchange old and new valid fis tables*/ | 293 /*exchange old and new valid fis tables*/ |
| 265 tmp_fis_addr=fis_addr; | 294 tmp_fis_addr=fis_addr; |
| 266 fis_addr=redundant_fis_addr; | 295 fis_addr=redundant_fis_addr; |
| 267 redundant_fis_addr=tmp_fis_addr; | 296 redundant_fis_addr=tmp_fis_addr; |
| 275 img->u.valid_info.version_count=img->u.valid_info.version_count+1; | 304 img->u.valid_info.version_count=img->u.valid_info.version_count+1; |
| 276 | 305 |
| 277 //ready to go.... | 306 //ready to go.... |
| 278 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | 307 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING |
| 279 if (do_autolock) | 308 if (do_autolock) |
| 280 flash_unlock((void *)fis_addr, fisdir_size, (void **)&err_addr); | 309 cyg_flash_unlock(fis_addr, fisdir_size, &err_addr); |
| 281 #endif | 310 #endif |
| 282 | 311 |
| 283 flash_erase(fis_addr, fisdir_size, (void **)&err_addr); | 312 if ((stat = cyg_flash_erase(fis_addr, fisdir_size, &err_addr)) != 0) { |
| 313 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, cyg_flash_errmsg(stat)); | |
| 314 return 1; | |
| 315 } | |
| 284 //now magic is 0xffffffff | 316 //now magic is 0xffffffff |
| 285 fis_endian_fixup(fis_work_block); | 317 fis_endian_fixup(fis_work_block); |
| 286 flash_program(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr); | 318 if ((stat = cyg_flash_program(fis_addr, fis_work_block, flash_block_size, &err_addr)) != 0) { |
| 319 diag_printf("Error writing FIS directory at %p: %s\n", | |
| 320 err_addr, cyg_flash_errmsg(stat)); | |
| 321 return 1; | |
| 322 } | |
| 287 fis_endian_fixup(fis_work_block); | 323 fis_endian_fixup(fis_work_block); |
| 288 //now magic is 0xff1234ff, valid is IN_PROGRESS, version_count is the old one +1 | 324 //now magic is 0xff1234ff, valid is IN_PROGRESS, version_count is the old one +1 |
| 289 | 325 |
| 290 #else | 326 #else |
| 291 /* nothing to do here without redundant fis */ | 327 /* nothing to do here without redundant fis */ |
| 295 } | 331 } |
| 296 | 332 |
| 297 int | 333 int |
| 298 fis_update_directory(int autolock, int error) | 334 fis_update_directory(int autolock, int error) |
| 299 { | 335 { |
| 300 void* err_addr=0; | 336 cyg_flashaddr_t err_addr; |
| 337 int stat; | |
| 301 | 338 |
| 302 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | 339 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING |
| 303 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL | 340 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL |
| 304 // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards | 341 // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards |
| 305 int do_autolock=1; | 342 int do_autolock=1; |
| 332 void* tmp_fis_addr=(void *)((CYG_ADDRESS)fis_addr+CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH); | 369 void* tmp_fis_addr=(void *)((CYG_ADDRESS)fis_addr+CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH); |
| 333 | 370 |
| 334 img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID; | 371 img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID; |
| 335 img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID; | 372 img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID; |
| 336 | 373 |
| 337 flash_program(tmp_fis_addr, img->u.valid_info.valid_flag, sizeof(img->u.valid_info.valid_flag), (void **)&err_addr); | 374 if ((stat = cyg_flash_program(tmp_fis_addr, img->u.valid_info.valid_flag, |
| 375 sizeof(img->u.valid_info.valid_flag), &err_addr)) != 0) { | |
| 376 diag_printf("Error writing FIS directory at %p: %s\n", | |
| 377 err_addr, cyg_flash_errmsg(stat)); | |
| 378 } | |
| 338 } | 379 } |
| 339 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | 380 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING |
| 340 if (do_autolock) | 381 if (do_autolock) |
| 341 flash_lock((void *)fis_addr, fisdir_size, (void **)&err_addr); | 382 flash_lock((void *)fis_addr, fisdir_size, (void **)&err_addr); |
| 342 #endif | 383 #endif |
| 343 | 384 |
| 344 #else // CYGOPT_REDBOOT_REDUNDANT_FIS | 385 #else // CYGOPT_REDBOOT_REDUNDANT_FIS |
| 345 int blk_size = fisdir_size; | 386 int blk_size = fisdir_size; |
| 346 int stat; | |
| 347 | 387 |
| 348 fis_endian_fixup(fis_work_block); | 388 fis_endian_fixup(fis_work_block); |
| 349 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG | 389 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG |
| 350 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); | 390 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); |
| 351 conf_endian_fixup((char *)fis_work_block+fisdir_size); | 391 conf_endian_fixup((char *)fis_work_block+fisdir_size); |
| 352 blk_size += cfg_size; | 392 blk_size += cfg_size; |
| 353 #endif | 393 #endif |
| 354 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | 394 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING |
| 355 if (do_autolock) | 395 if (do_autolock) |
| 356 flash_unlock((void *)fis_addr, blk_size, (void **)&err_addr); | 396 cyg_flash_unlock(fis_addr, blk_size, &err_addr); |
| 357 #endif | 397 #endif |
| 358 | 398 |
| 359 if ((stat = flash_erase(fis_addr, blk_size, (void **)&err_addr)) != 0) { | 399 if ((stat = cyg_flash_erase(fis_addr, blk_size, &err_addr)) != 0) { |
| 360 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); | 400 diag_printf("Error erasing FIS directory at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat)); |
| 361 } else { | 401 } else { |
| 362 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block, | 402 if ((stat = cyg_flash_program(fis_addr, fis_work_block, blk_size, |
| 363 blk_size, (void **)&err_addr)) != 0) { | 403 &err_addr)) != 0) { |
| 364 diag_printf("Error writing FIS directory at %p: %s\n", | 404 diag_printf("Error writing FIS directory at %p: %s\n", |
| 365 err_addr, flash_errmsg(stat)); | 405 (void*)err_addr, cyg_flash_errmsg(stat)); |
| 366 } | 406 } |
| 367 } | 407 } |
| 368 fis_endian_fixup(fis_work_block); | 408 fis_endian_fixup(fis_work_block); |
| 369 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | 409 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING |
| 370 if (do_autolock) | 410 if (do_autolock) |
| 371 flash_lock((void *)fis_addr, blk_size, (void **)&err_addr); | 411 cyg_flash_lock(fis_addr, blk_size, &err_addr); |
| 372 #endif | 412 #endif |
| 373 | 413 |
| 374 #endif // CYGOPT_REDBOOT_REDUNDANT_FIS | 414 #endif // CYGOPT_REDBOOT_REDUNDANT_FIS |
| 375 | 415 |
| 376 return 0; | 416 return 0; |
| 426 void *err_addr; | 466 void *err_addr; |
| 427 | 467 |
| 428 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL | 468 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL |
| 429 // Ensure [quietly] that the directory is unlocked before trying | 469 // Ensure [quietly] that the directory is unlocked before trying |
| 430 // to update | 470 // to update |
| 431 flash_unlock((void *)redundant_fis_addr, fisdir_size, | 471 cyg_flash_unlock(redundant_fis_addr, fisdir_size, |
| 432 (void **)&err_addr); | 472 &err_addr); |
| 433 #endif | 473 #endif |
| 434 if ((stat = flash_erase(redundant_fis_addr, fisdir_size, | 474 if ((stat = cyg_flash_erase(redundant_fis_addr, fisdir_size, |
| 435 (void **)&err_addr)) != 0) { | 475 &err_addr)) != 0) { |
| 436 diag_printf("Error erasing FIS directory at %p: %s\n", | 476 diag_printf("Error erasing FIS directory at %p: %s\n", |
| 437 err_addr, flash_errmsg(stat)); | 477 err_addr, cyg_flash_errmsg(stat)); |
| 438 } | 478 } |
| 439 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL | 479 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL |
| 440 // Ensure [quietly] that the directory is locked after the update | 480 // Ensure [quietly] that the directory is locked after the update |
| 441 flash_lock((void *)redundant_fis_addr, fisdir_size, (void **)&err_addr); | 481 cyg_flash_lock(redundant_fis_addr, fisdir_size, &err_addr); |
| 442 #endif | 482 #endif |
| 443 } | 483 } |
| 444 #endif | 484 #endif |
| 445 | 485 |
| 446 static void | 486 static void |
| 447 fis_init(int argc, char *argv[]) | 487 fis_init(int argc, char *argv[]) |
| 448 { | 488 { |
| 449 int stat; | 489 int stat; |
| 450 struct fis_image_desc *img; | 490 struct fis_image_desc *img; |
| 451 void *err_addr; | 491 cyg_flashaddr_t err_addr; |
| 452 bool full_init = false; | 492 bool full_init = false; |
| 453 struct option_info opts[1]; | 493 struct option_info opts[1]; |
| 454 CYG_ADDRESS redboot_flash_start; | 494 CYG_ADDRESS redboot_flash_start; |
| 455 unsigned long redboot_image_size; | 495 unsigned long redboot_image_size; |
| 456 | 496 |
| 470 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE | 510 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE |
| 471 redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? | 511 redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? |
| 472 flash_block_size : MIN_REDBOOT_IMAGE_SIZE; | 512 flash_block_size : MIN_REDBOOT_IMAGE_SIZE; |
| 473 | 513 |
| 474 img = (struct fis_image_desc *)fis_work_block; | 514 img = (struct fis_image_desc *)fis_work_block; |
| 475 memset(img, 0xFF, fisdir_size); // Start with erased data | 515 memset(img, '\xFF', fisdir_size); // Start with erased data |
| 476 | 516 |
| 477 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS | 517 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS |
| 478 //create the valid flag entry | 518 //create the valid flag entry |
| 479 memset(img, 0, sizeof(struct fis_image_desc)); | 519 memset(img, 0, sizeof(struct fis_image_desc)); |
| 480 strcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC); | 520 strcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC); |
| 489 memset(img, 0, sizeof(*img)); | 529 memset(img, 0, sizeof(*img)); |
| 490 strcpy(img->u.name, "(reserved)"); | 530 strcpy(img->u.name, "(reserved)"); |
| 491 img->flash_base = (CYG_ADDRESS)flash_start; | 531 img->flash_base = (CYG_ADDRESS)flash_start; |
| 492 img->mem_base = (CYG_ADDRESS)flash_start; | 532 img->mem_base = (CYG_ADDRESS)flash_start; |
| 493 img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE; | 533 img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE; |
| 534 img->data_length = img->size; | |
| 494 img++; | 535 img++; |
| 495 #endif | 536 #endif |
| 496 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; | 537 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; |
| 497 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT | 538 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT |
| 498 memset(img, 0, sizeof(*img)); | 539 memset(img, 0, sizeof(*img)); |
| 499 strcpy(img->u.name, "RedBoot"); | 540 strcpy(img->u.name, "RedBoot"); |
| 500 img->flash_base = redboot_flash_start; | 541 img->flash_base = redboot_flash_start; |
| 501 img->mem_base = redboot_flash_start; | 542 img->mem_base = redboot_flash_start; |
| 502 img->size = redboot_image_size; | 543 img->size = redboot_image_size; |
| 544 img->data_length = img->size; | |
| 503 img++; | 545 img++; |
| 504 redboot_flash_start += redboot_image_size; | 546 redboot_flash_start += redboot_image_size; |
| 505 #endif | 547 #endif |
| 506 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST | 548 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST |
| 507 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET | 549 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET |
| 511 memset(img, 0, sizeof(*img)); | 553 memset(img, 0, sizeof(*img)); |
| 512 strcpy(img->u.name, "RedBoot[post]"); | 554 strcpy(img->u.name, "RedBoot[post]"); |
| 513 img->flash_base = redboot_flash_start; | 555 img->flash_base = redboot_flash_start; |
| 514 img->mem_base = redboot_flash_start; | 556 img->mem_base = redboot_flash_start; |
| 515 img->size = redboot_image_size; | 557 img->size = redboot_image_size; |
| 558 img->data_length = img->size; | |
| 516 img++; | 559 img++; |
| 517 redboot_flash_start += redboot_image_size; | 560 redboot_flash_start += redboot_image_size; |
| 518 #endif | 561 #endif |
| 519 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP | 562 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP |
| 520 // And a backup image | 563 // And a backup image |
| 521 memset(img, 0, sizeof(*img)); | 564 memset(img, 0, sizeof(*img)); |
| 522 strcpy(img->u.name, "RedBoot[backup]"); | 565 strcpy(img->u.name, "RedBoot[backup]"); |
| 523 img->flash_base = redboot_flash_start; | 566 img->flash_base = redboot_flash_start; |
| 524 img->mem_base = redboot_flash_start; | 567 img->mem_base = redboot_flash_start; |
| 525 img->size = redboot_image_size; | 568 img->size = redboot_image_size; |
| 569 img->data_length = img->size; | |
| 526 img++; | 570 img++; |
| 527 redboot_flash_start += redboot_image_size; | 571 redboot_flash_start += redboot_image_size; |
| 528 #endif | 572 #endif |
| 529 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) | 573 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) |
| 530 // And a descriptor for the configuration data | 574 // And a descriptor for the configuration data |
| 531 memset(img, 0, sizeof(*img)); | 575 memset(img, 0, sizeof(*img)); |
| 532 strcpy(img->u.name, "RedBoot config"); | 576 strcpy(img->u.name, "RedBoot config"); |
| 533 img->flash_base = (CYG_ADDRESS)cfg_base; | 577 img->flash_base = (CYG_ADDRESS)cfg_base; |
| 534 img->mem_base = (CYG_ADDRESS)cfg_base; | 578 img->mem_base = (CYG_ADDRESS)cfg_base; |
| 535 img->size = cfg_size; | 579 img->size = cfg_size; |
| 580 img->data_length = img->size; | |
| 536 img++; | 581 img++; |
| 537 #endif | 582 #endif |
| 538 // And a descriptor for the descriptor table itself | 583 // And a descriptor for the descriptor table itself |
| 539 memset(img, 0, sizeof(*img)); | 584 memset(img, 0, sizeof(*img)); |
| 540 strcpy(img->u.name, "FIS directory"); | 585 strcpy(img->u.name, "FIS directory"); |
| 541 img->flash_base = (CYG_ADDRESS)fis_addr; | 586 img->flash_base = (CYG_ADDRESS)fis_addr; |
| 542 img->mem_base = (CYG_ADDRESS)fis_addr; | 587 img->mem_base = (CYG_ADDRESS)fis_addr; |
| 543 img->size = fisdir_size; | 588 img->size = fisdir_size; |
| 589 img->data_length = img->size; | |
| 544 img++; | 590 img++; |
| 545 | 591 |
| 546 //create the entry for the redundant fis table | 592 //create the entry for the redundant fis table |
| 547 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS | 593 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS |
| 548 memset(img, 0, sizeof(*img)); | 594 memset(img, 0, sizeof(*img)); |
| 601 #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE) | 647 #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE) |
| 602 erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE; | 648 erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE; |
| 603 erase_size = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; | 649 erase_size = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; |
| 604 if ( erase_size > erase_start ) { | 650 if ( erase_size > erase_start ) { |
| 605 erase_size -= erase_start; | 651 erase_size -= erase_start; |
| 606 if ((stat = flash_erase((void *)erase_start, erase_size, | 652 if ((stat = cyg_flash_erase((void *)erase_start, erase_size, |
| 607 (void **)&err_addr)) != 0) { | 653 &err_addr)) != 0) { |
| 608 diag_printf(" initialization failed at %p: %s\n", | 654 diag_printf(" initialization failed at %p: %s\n", |
| 609 err_addr, flash_errmsg(stat)); | 655 err_addr, cyg_flash_errmsg(stat)); |
| 610 } | 656 } |
| 611 } | 657 } |
| 612 #endif | 658 #endif |
| 613 // second deal with the larger part in the main: | 659 // second deal with the larger part in the main: |
| 614 erase_start = redboot_flash_start; // high water of created images | 660 erase_start = redboot_flash_start; // high water of created images |
| 620 if (fis_addr > cfg_base) { | 666 if (fis_addr > cfg_base) { |
| 621 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data | 667 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data |
| 622 } else { | 668 } else { |
| 623 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data | 669 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data |
| 624 } | 670 } |
| 625 if ((stat = flash_erase((void *)erase_start, erase_size, | 671 if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) { |
| 626 (void **)&err_addr)) != 0) { | |
| 627 diag_printf(" initialization failed %p: %s\n", | 672 diag_printf(" initialization failed %p: %s\n", |
| 628 err_addr, flash_errmsg(stat)); | 673 err_addr, cyg_flash_errmsg(stat)); |
| 629 } | 674 } |
| 630 erase_start += (erase_size + flash_block_size); | 675 erase_start += (erase_size + flash_block_size); |
| 631 if (fis_addr > cfg_base) { | 676 if (fis_addr > cfg_base) { |
| 632 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data | 677 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data |
| 633 } else { | 678 } else { |
| 634 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data | 679 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data |
| 635 } | 680 } |
| 636 if ((stat = flash_erase((void *)erase_start, erase_size, | 681 if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) { |
| 637 (void **)&err_addr)) != 0) { | |
| 638 diag_printf(" initialization failed %p: %s\n", | 682 diag_printf(" initialization failed %p: %s\n", |
| 639 err_addr, flash_errmsg(stat)); | 683 err_addr, cyg_flash_errmsg(stat)); |
| 640 } | 684 } |
| 641 erase_start += (erase_size + flash_block_size); | 685 erase_start += (erase_size + flash_block_size); |
| 642 #else // !CYGSEM_REDBOOT_FLASH_CONFIG | 686 #else // !CYGSEM_REDBOOT_FLASH_CONFIG |
| 643 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data | 687 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data |
| 644 if ((stat = flash_erase((void *)erase_start, erase_size, | 688 if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) { |
| 645 (void **)&err_addr)) != 0) { | |
| 646 diag_printf(" initialization failed %p: %s\n", | 689 diag_printf(" initialization failed %p: %s\n", |
| 647 err_addr, flash_errmsg(stat)); | 690 (void*)err_addr, cyg_flash_errmsg(stat)); |
| 648 } | 691 } |
| 649 erase_start += (erase_size + flash_block_size); | 692 erase_start += (erase_size + flash_block_size); |
| 650 #endif | 693 #endif |
| 651 // Lastly, anything at the end, if there is any | 694 // Lastly, anything at the end |
| 652 if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) { | 695 erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1; |
| 653 erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1; | 696 if ((erase_size > 0) && |
| 654 if ((stat = flash_erase((void *)erase_start, erase_size, | 697 ((stat = cyg_flash_erase(erase_start, erase_size, |
| 655 (void **)&err_addr)) != 0) { | 698 &err_addr))) != 0) { |
| 656 diag_printf(" initialization failed at %p: %s\n", | 699 diag_printf(" initialization failed at %p: %s\n", |
| 657 err_addr, flash_errmsg(stat)); | 700 (void*)err_addr, cyg_flash_errmsg(stat)); |
| 658 } | |
| 659 } | 701 } |
| 660 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS | 702 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS |
| 661 // In this case, 'fis free' works by scanning for erased blocks. Since the | 703 // In this case, 'fis free' works by scanning for erased blocks. Since the |
| 662 // "-f" option was not supplied, there may be areas which are not used but | 704 // "-f" option was not supplied, there may be areas which are not used but |
| 663 // don't appear to be free since they are not erased - thus the warning | 705 // don't appear to be free since they are not erased - thus the warning |
| 716 do { | 758 do { |
| 717 image_found = false; | 759 image_found = false; |
| 718 lowest_addr = 0xFFFFFFFF; | 760 lowest_addr = 0xFFFFFFFF; |
| 719 img = (struct fis_image_desc *) fis_work_block; | 761 img = (struct fis_image_desc *) fis_work_block; |
| 720 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { | 762 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { |
| 721 if (img->u.name[0] != (unsigned char)0xFF) { | 763 if (img->u.name[0] != '\xFF') { |
| 722 if ((img->flash_base >= last_addr) && (img->flash_base < lowest_addr)) { | 764 if ((img->flash_base >= last_addr) && (img->flash_base < lowest_addr)) { |
| 723 lowest_addr = img->flash_base; | 765 lowest_addr = img->flash_base; |
| 724 image_found = true; | 766 image_found = true; |
| 725 image_indx = i; | 767 image_indx = i; |
| 726 } | 768 } |
| 742 } | 784 } |
| 743 last_addr = lowest_addr + 1; | 785 last_addr = lowest_addr + 1; |
| 744 } while (image_found == true); | 786 } while (image_found == true); |
| 745 } | 787 } |
| 746 | 788 |
| 789 #ifdef CYGNUM_REDBOOT_FLASH_RESERVED_DEVICES | |
| 790 static CYG_ADDRESS flash_reserved_devices[] = { CYGNUM_REDBOOT_FLASH_RESERVED_DEVICES, 0xFFFFFFFF }; | |
| 791 | |
| 792 static cyg_bool flash_reserved( CYG_ADDRESS start ) | |
| 793 { | |
| 794 int i; | |
| 795 for( i = 0; flash_reserved_devices[i] != 0xFFFFFFFF; i++ ) | |
| 796 if( start == flash_reserved_devices[i] ) | |
| 797 return true; | |
| 798 return false; | |
| 799 } | |
| 800 #else | |
| 801 #define flash_reserved(__start) false | |
| 802 #endif | |
| 803 | |
| 747 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS | 804 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS |
| 748 struct free_chunk { | 805 struct free_chunk { |
| 749 CYG_ADDRESS start, end; | 806 CYG_ADDRESS start, end; |
| 750 }; | 807 }; |
| 751 | 808 |
| 752 static int | 809 static int |
| 753 find_free(struct free_chunk *chunks) | 810 find_free(struct free_chunk *chunks) |
| 754 { | 811 { |
| 755 CYG_ADDRESS *fis_ptr, *fis_end; | 812 cyg_flash_info_t info; |
| 756 struct fis_image_desc *img; | 813 struct fis_image_desc *img; |
| 757 int i, idx; | 814 int i=0, idx; |
| 758 int num_chunks = 1; | 815 int num_chunks = 0; |
| 759 | 816 int ret; |
| 760 // Do not search the area reserved for pre-RedBoot systems: | 817 |
| 761 fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start + | 818 do { |
| 762 CYGNUM_REDBOOT_FLASH_RESERVED_BASE); | 819 // get info for each flash device |
| 763 fis_end = (CYG_ADDRESS *)flash_end; | 820 ret = cyg_flash_get_info(i, &info); |
| 764 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; | 821 |
| 765 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; | 822 if (ret == CYG_FLASH_ERR_OK && !flash_reserved( info.start )) { |
| 823 | |
| 824 #ifdef CYGNUM_REDBOOT_FLASH_BASE | |
| 825 if ( CYGNUM_REDBOOT_FLASH_BASE == info.start ) | |
| 826 #else | |
| 827 if (i == 0 ) | |
| 828 #endif | |
| 829 { | |
| 830 // Do not search the area reserved for pre-RedBoot systems: | |
| 831 chunks[num_chunks].start = (info.start + | |
| 832 CYGNUM_REDBOOT_FLASH_RESERVED_BASE); | |
| 833 chunks[num_chunks].end = info.end; | |
| 834 num_chunks++; | |
| 835 } else { // Contiguous flash? If so collapse the chunks together. | |
| 836 if (chunks[num_chunks-1].end == (info.start -1)) { | |
| 837 chunks[num_chunks-1].end = info.end; | |
| 838 } else { | |
| 839 chunks[num_chunks].start = info.start; | |
| 840 chunks[num_chunks].end = info.end; | |
| 841 num_chunks++; | |
| 842 } | |
| 843 } | |
| 844 } | |
| 845 i++; | |
| 846 } while (ret != CYG_FLASH_ERR_INVALID); | |
| 847 | |
| 766 fis_read_directory(); | 848 fis_read_directory(); |
| 767 img = (struct fis_image_desc *) fis_work_block; | 849 img = (struct fis_image_desc *) fis_work_block; |
| 768 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { | 850 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { |
| 769 if (img->u.name[0] != (unsigned char)0xFF) { | 851 if (img->u.name[0] != '\xFF') { |
| 770 // Figure out which chunk this is in and split it | 852 // Figure out which chunk this is in and split it |
| 771 for (idx = 0; idx < num_chunks; idx++) { | 853 for (idx = 0; idx < num_chunks; idx++) { |
| 772 if ((img->flash_base >= chunks[idx].start) && | 854 if ((img->flash_base >= chunks[idx].start) && |
| 773 (img->flash_base <= chunks[idx].end)) { | 855 (img->flash_base <= chunks[idx].end)) { |
| 774 if (img->flash_base == chunks[idx].start) { | 856 if (img->flash_base == chunks[idx].start) { |
| 775 chunks[idx].start += img->size; | 857 chunks[idx].start += img->size; |
| 776 if (chunks[idx].start >= chunks[idx].end) { | 858 if (chunks[idx].start >= chunks[idx].end) { |
| 777 // This free chunk has collapsed | 859 // This free chunk has collapsed |
| 778 while (idx < (num_chunks-1)) { | 860 num_chunks--; |
| 861 while (idx < num_chunks) { | |
| 779 chunks[idx] = chunks[idx+1]; | 862 chunks[idx] = chunks[idx+1]; |
| 780 idx++; | 863 idx++; |
| 781 } | 864 } |
| 782 num_chunks--; | |
| 783 } | 865 } |
| 784 } else if ((img->flash_base+img->size) == chunks[idx].end) { | 866 } else if ((img->flash_base+img->size-1) >= chunks[idx].end) { |
| 785 chunks[idx].end = img->flash_base; | 867 chunks[idx].end = img->flash_base - 1; |
| 786 } else { | 868 } else { |
| 787 // Split chunk into two parts | 869 // Split chunk into two parts |
| 788 if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) { | 870 int idxtmp; |
| 789 int j; | 871 |
| 790 // make room for new chunk | 872 // shift chunks along one so we insert the new one |
| 791 for (j = num_chunks; j > (idx+1); j--) | 873 for (idxtmp=num_chunks; idxtmp > (idx+1); idxtmp--) |
| 792 chunks[j] = chunks[j-1]; | 874 { |
| 793 chunks[idx+1].start = img->flash_base + img->size; | 875 chunks[idxtmp] = chunks[idxtmp-1]; |
| 794 chunks[idx+1].end = chunks[idx].end; | |
| 795 if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) { | |
| 796 diag_printf("Warning: too many free chunks\n"); | |
| 797 return num_chunks; | |
| 798 } | |
| 799 } | 876 } |
| 800 chunks[idx].end = img->flash_base; | 877 |
| 878 chunks[idx+1].start = img->flash_base + img->size; | |
| 879 chunks[idx+1].end = chunks[idx].end; | |
| 880 chunks[idx].end = img->flash_base - 1; | |
| 881 if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) { | |
| 882 diag_printf("Warning: too many free chunks\n"); | |
| 883 return num_chunks; | |
| 884 } | |
| 801 } | 885 } |
| 802 break; | 886 break; |
| 803 } | 887 } |
| 804 } | 888 } |
| 805 } | 889 } |
| 809 #endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS | 893 #endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS |
| 810 | 894 |
| 811 static void | 895 static void |
| 812 fis_free(int argc, char *argv[]) | 896 fis_free(int argc, char *argv[]) |
| 813 { | 897 { |
| 814 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS | 898 #if !defined(CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) |
| 815 unsigned long *fis_ptr, *fis_end, flash_data; | 899 cyg_uint32 flash_data; |
| 816 unsigned long *area_start; | 900 cyg_flashaddr_t area_start; |
| 817 void *err_addr; | 901 cyg_flashaddr_t err_addr; |
| 818 | 902 cyg_uint32 flash_dev_no; |
| 819 // Do not search the area reserved for pre-RedBoot systems: | 903 int flash_err; |
| 820 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + | 904 cyg_flash_info_t flash_info; |
| 821 CYGNUM_REDBOOT_FLASH_RESERVED_BASE); | 905 cyg_uint32 curr_block, curr_block_info; |
| 822 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end; | 906 cyg_flashaddr_t curr_flash_addr, next_flash_addr; |
| 823 area_start = fis_ptr; | 907 |
| 824 while (fis_ptr < fis_end) { | 908 // For each flash device |
| 825 flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr); | 909 for (flash_dev_no=0;; flash_dev_no++) |
| 826 if (flash_data != (unsigned long)0xFFFFFFFF) { | 910 { |
| 827 if (area_start != fis_ptr) { | 911 flash_err = cyg_flash_get_info( flash_dev_no, &flash_info ); |
| 828 // Assume that this is something | 912 if ( CYG_FLASH_ERR_OK != flash_err ) // assume all done |
| 829 diag_printf(" 0x%08lX .. 0x%08lX\n", | 913 break; |
| 830 (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr); | 914 |
| 831 } | 915 if( flash_reserved( flash_info.start ) ) // Ignore reserved devices |
| 832 // Find next blank block | 916 continue; |
| 833 area_start = fis_ptr; | 917 |
| 834 while (area_start < fis_end) { | 918 // Once more, from the top... |
| 835 flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr); | 919 curr_flash_addr = area_start = flash_info.start; |
| 836 if (flash_data == (unsigned long)0xFFFFFFFF) { | 920 |
| 837 break; | 921 // We must not search the area reserved for pre-RedBoot systems, |
| 922 // but this is only the case for the first flash device, or | |
| 923 // the one corresponding to CYGNUM_REDBOOT_FLASH_BASE. | |
| 924 // FIXME: this is insufficiently generic by design - can only | |
| 925 // reserve on one flash. | |
| 926 #ifdef CYGNUM_REDBOOT_FLASH_BASE | |
| 927 if ( CYGNUM_REDBOOT_FLASH_BASE == area_start ) | |
| 928 #else | |
| 929 if ( 0 == flash_dev_no ) | |
| 930 #endif | |
| 931 { | |
| 932 //cyg_flashaddr_t asold = area_start; | |
| 933 area_start += CYGNUM_REDBOOT_FLASH_RESERVED_BASE; | |
| 934 //diag_printf("area_start was %08x now %08x\n", asold, area_start ); | |
| 935 } | |
| 936 // For each region of blocks | |
| 937 for ( curr_block_info = 0; | |
| 938 curr_block_info < flash_info.num_block_infos; | |
| 939 curr_block_info++ ) | |
| 940 { | |
| 941 // For each individual block | |
| 942 for ( curr_block = 0; | |
| 943 curr_block < flash_info.block_info[curr_block_info].blocks; | |
| 944 curr_flash_addr = next_flash_addr, curr_block++ ) | |
| 945 { | |
| 946 cyg_ucount32 i; | |
| 947 cyg_bool is_blank = true; // until proved otherwise | |
| 948 size_t amount_to_check; | |
| 949 | |
| 950 // determine this now to avoid recalculating it later in this block, so we know the | |
| 951 // end of this block | |
| 952 next_flash_addr = curr_flash_addr + flash_info.block_info[curr_block_info].block_size; | |
| 953 | |
| 954 // If area_start got adjusted further up, skip until we reach it | |
| 955 if ( curr_flash_addr < area_start ) | |
| 956 continue; | |
| 957 | |
| 958 //diag_printf("block region %d, block %d, flashaddr %08x\n",curr_block_info,curr_block,curr_flash_addr); | |
| 959 | |
| 960 // check 32 bytes at most. Reading it all will take too long on many devices. | |
| 961 // Perhaps this should be a config option. | |
| 962 amount_to_check = 32; | |
| 963 if ( amount_to_check > flash_info.block_info[curr_block_info].block_size ) // paranoia | |
| 964 amount_to_check = flash_info.block_info[curr_block_info].block_size; | |
| 965 | |
| 966 for ( i=0; i<amount_to_check; i += sizeof(cyg_uint32) ) | |
| 967 { | |
| 968 flash_err = cyg_flash_read(curr_flash_addr+i, &flash_data, sizeof(cyg_uint32), &err_addr); | |
| 969 if ( (CYG_FLASH_ERR_OK != flash_err) || (flash_data != 0xffffffff) ) | |
| 970 { | |
| 971 is_blank = false; | |
| 972 break; // no point continuing | |
| 973 } | |
| 974 } // for | |
| 975 | |
| 976 if (!is_blank) | |
| 977 { | |
| 978 /* If not blank, output the preceding region if any */ | |
| 979 if ( curr_flash_addr != area_start ) | |
| 980 { | |
| 981 diag_printf(" 0x%08lX .. 0x%08lX\n", | |
| 982 area_start, | |
| 983 next_flash_addr-1 ); | |
| 984 } | |
| 985 area_start = next_flash_addr; | |
| 838 } | 986 } |
| 839 area_start += flash_block_size / sizeof(CYG_ADDRESS); | 987 } // for block |
| 840 } | 988 } // for block region |
| 841 fis_ptr = area_start; | 989 |
| 842 } else { | 990 /* If the blank region extended to the very end of the device, we need to do one |
| 843 fis_ptr += flash_block_size / sizeof(CYG_ADDRESS); | 991 * final check at the end of the device. |
| 844 } | 992 */ |
| 845 } | 993 if ( curr_flash_addr != area_start ) |
| 846 if (area_start != fis_ptr) { | 994 { |
| 847 diag_printf(" 0x%08lX .. 0x%08lX\n", | 995 diag_printf(" 0x%08lX .. 0x%08lX\n", |
| 848 (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr); | 996 area_start, |
| 849 } | 997 next_flash_addr-1 ); |
| 998 } | |
| 999 } // for flash device | |
| 850 #else | 1000 #else |
| 851 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; | 1001 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; |
| 852 int idx, num_chunks; | 1002 int idx, num_chunks; |
| 853 | 1003 |
| 854 num_chunks = find_free(chunks); | 1004 num_chunks = find_free(chunks); |
| 863 // Find the first unused area of flash which is long enough | 1013 // Find the first unused area of flash which is long enough |
| 864 static bool | 1014 static bool |
| 865 fis_find_free(CYG_ADDRESS *addr, unsigned long length) | 1015 fis_find_free(CYG_ADDRESS *addr, unsigned long length) |
| 866 { | 1016 { |
| 867 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS | 1017 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS |
| 868 unsigned long *fis_ptr, *fis_end, flash_data; | 1018 cyg_uint32 flash_data; |
| 869 unsigned long *area_start; | 1019 cyg_flashaddr_t area_start; |
| 870 void *err_addr; | 1020 cyg_flashaddr_t err_addr; |
| 871 | 1021 cyg_uint32 flash_dev_no; |
| 872 // Do not search the area reserved for pre-RedBoot systems: | 1022 int flash_err; |
| 873 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + | 1023 cyg_flash_info_t flash_info; |
| 874 CYGNUM_REDBOOT_FLASH_RESERVED_BASE); | 1024 cyg_uint32 curr_block, curr_block_info; |
| 875 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end; | 1025 cyg_flashaddr_t curr_flash_addr, next_flash_addr; |
| 876 area_start = fis_ptr; | 1026 |
| 877 while (fis_ptr < fis_end) { | 1027 // For each flash device |
| 878 flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr); | 1028 for (flash_dev_no=0;; flash_dev_no++) |
| 879 if (flash_data != (unsigned long)0xFFFFFFFF) { | 1029 { |
| 880 if (area_start != fis_ptr) { | 1030 flash_err = cyg_flash_get_info( flash_dev_no, &flash_info ); |
| 881 // Assume that this is something | 1031 if ( CYG_FLASH_ERR_OK != flash_err ) // assume all done |
| 882 if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) { | 1032 break; |
| 883 *addr = (CYG_ADDRESS)area_start; | 1033 |
| 884 return true; | 1034 if( flash_reserved( flash_info.start ) ) // Ignore reserved devices |
| 1035 continue; | |
| 1036 | |
| 1037 // Once more, from the top... | |
| 1038 curr_flash_addr = area_start = flash_info.start; | |
| 1039 | |
| 1040 // We must not search the area reserved for pre-RedBoot systems, | |
| 1041 // but this is only the case for the first flash device, or | |
| 1042 // the one corresponding to CYGNUM_REDBOOT_FLASH_BASE. | |
| 1043 // FIXME: this is insufficiently generic by design - can only | |
| 1044 // reserve on one flash. | |
| 1045 #ifdef CYGNUM_REDBOOT_FLASH_BASE | |
| 1046 if ( CYGNUM_REDBOOT_FLASH_BASE == area_start ) | |
| 1047 #else | |
| 1048 if ( 0 == flash_dev_no ) | |
| 1049 #endif | |
| 1050 { | |
| 1051 //cyg_flashaddr_t asold = area_start; | |
| 1052 area_start += CYGNUM_REDBOOT_FLASH_RESERVED_BASE; | |
| 1053 //diag_printf("area_start was %08x now %08x\n", asold, area_start ); | |
| 1054 } | |
| 1055 // For each region of blocks | |
| 1056 for ( curr_block_info = 0; | |
| 1057 curr_block_info < flash_info.num_block_infos; | |
| 1058 curr_block_info++ ) | |
| 1059 { | |
| 1060 // For each individual block | |
| 1061 for ( curr_block = 0; | |
| 1062 curr_block < flash_info.block_info[curr_block_info].blocks; | |
| 1063 curr_flash_addr = next_flash_addr, curr_block++ ) | |
| 1064 { | |
| 1065 cyg_ucount32 i; | |
| 1066 cyg_bool is_blank = true; // until proved otherwise | |
| 1067 size_t amount_to_check; | |
| 1068 | |
| 1069 // determine this now to avoid recalculating it later in this block, so we know the | |
| 1070 // end of this block | |
| 1071 next_flash_addr = curr_flash_addr + flash_info.block_info[curr_block_info].block_size; | |
| 1072 | |
| 1073 // If area_start got adjusted further up, skip until we reach it | |
| 1074 if ( curr_flash_addr < area_start ) | |
| 1075 continue; | |
| 1076 | |
| 1077 //diag_printf("block region %d, block %d, flashaddr %08x\n",curr_block_info,curr_block,curr_flash_addr); | |
| 1078 | |
| 1079 // check 32 bytes at most. Reading it all will take too long on many devices. | |
| 1080 // Perhaps this should be a config option. | |
| 1081 amount_to_check = 32; | |
| 1082 if ( amount_to_check > flash_info.block_info[curr_block_info].block_size ) // paranoia | |
| 1083 amount_to_check = flash_info.block_info[curr_block_info].block_size; | |
| 1084 | |
| 1085 for ( i=0; i<amount_to_check; i += sizeof(cyg_uint32) ) | |
| 1086 { | |
| 1087 flash_err = cyg_flash_read(curr_flash_addr+i, &flash_data, sizeof(cyg_uint32), &err_addr); | |
| 1088 if ( (CYG_FLASH_ERR_OK != flash_err) || (flash_data != 0xffffffff) ) | |
| 1089 { | |
| 1090 is_blank = false; | |
| 1091 break; // no point continuing | |
| 1092 } | |
| 1093 } // for | |
| 1094 | |
| 1095 if (!is_blank) | |
| 1096 { | |
| 1097 /* If not blank, output the preceding region if any */ | |
| 1098 if ( curr_flash_addr != area_start ) | |
| 1099 { | |
| 1100 if ( length <= (next_flash_addr - area_start) ) | |
| 1101 { | |
| 1102 *addr = (CYG_ADDRESS)area_start; | |
| 1103 return true; | |
| 1104 } | |
| 1105 } | |
| 1106 area_start = next_flash_addr; | |
| 885 } | 1107 } |
| 886 } | 1108 } // for block |
| 887 // Find next blank block | 1109 } // for block region |
| 888 area_start = fis_ptr; | 1110 |
| 889 while (area_start < fis_end) { | 1111 /* If the blank region extended to the very end of the device, we need to do one |
| 890 flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr); | 1112 * final check at the end of the device. |
| 891 if (flash_data == (unsigned long)0xFFFFFFFF) { | 1113 */ |
| 892 break; | 1114 if ( curr_flash_addr != area_start ) |
| 893 } | 1115 { |
| 894 area_start += flash_block_size / sizeof(CYG_ADDRESS); | 1116 if ( length <= (next_flash_addr - area_start) ) |
| 895 } | 1117 { |
| 896 fis_ptr = area_start; | 1118 *addr = (CYG_ADDRESS)area_start; |
| 897 } else { | 1119 return true; |
| 898 fis_ptr += flash_block_size / sizeof(CYG_ADDRESS); | 1120 } |
| 899 } | 1121 } |
| 900 } | 1122 } // for flash device |
| 901 if (area_start != fis_ptr) { | |
| 902 if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) { | |
| 903 *addr = (CYG_ADDRESS)area_start; | |
| 904 return true; | |
| 905 } | |
| 906 } | |
| 907 return false; | |
| 908 #else | 1123 #else |
| 909 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; | 1124 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; |
| 910 int idx, num_chunks; | 1125 int idx, num_chunks; |
| 911 | 1126 |
| 912 num_chunks = find_free(chunks); | 1127 num_chunks = find_free(chunks); |
| 913 for (idx = 0; idx < num_chunks; idx++) { | 1128 for (idx = 0; idx < num_chunks; idx++) { |
| 914 if ((chunks[idx].end - chunks[idx].start) >= length) { | 1129 if ((chunks[idx].end - chunks[idx].start + 1) >= length) { |
| 915 *addr = (CYG_ADDRESS)chunks[idx].start; | 1130 *addr = (CYG_ADDRESS)chunks[idx].start; |
| 916 return true; | 1131 return true; |
| 917 } | 1132 } |
| 918 } | 1133 } |
| 1134 #endif | |
| 919 return false; | 1135 return false; |
| 920 #endif | |
| 921 } | 1136 } |
| 922 | 1137 |
| 923 static void | 1138 static void |
| 924 fis_create(int argc, char *argv[]) | 1139 fis_create(int argc, char *argv[]) |
| 925 { | 1140 { |
| 926 int i, stat; | 1141 int i, stat; |
| 927 unsigned long length, img_size; | 1142 unsigned long length, img_size; |
| 928 CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr; | 1143 CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr, flash_offset; |
| 929 char *name; | 1144 char *name; |
| 930 bool mem_addr_set = false; | 1145 bool mem_addr_set = false; |
| 931 bool exec_addr_set = false; | 1146 bool exec_addr_set = false; |
| 932 bool entry_addr_set = false; | 1147 bool entry_addr_set = false; |
| 933 bool flash_addr_set = false; | 1148 bool flash_addr_set = false; |
| 934 bool length_set = false; | 1149 bool length_set = false; |
| 935 bool img_size_set = false; | 1150 bool img_size_set = false; |
| 936 bool no_copy = false; | 1151 bool no_copy = false; |
| 937 void *err_addr; | 1152 cyg_flashaddr_t err_addr; |
| 938 struct fis_image_desc *img = NULL; | 1153 struct fis_image_desc *img = NULL; |
| 939 bool defaults_assumed; | 1154 bool defaults_assumed; |
| 940 struct option_info opts[7]; | 1155 struct option_info opts[7]; |
| 941 bool prog_ok = true; | 1156 bool prog_ok = true; |
| 942 | 1157 size_t block_size; |
| 1158 | |
| 943 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, | 1159 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, |
| 944 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); | 1160 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); |
| 945 init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, | 1161 init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, |
| 946 (void *)&exec_addr, (bool *)&exec_addr_set, "ram base address"); | 1162 (void *)&exec_addr, (bool *)&exec_addr_set, "ram base address"); |
| 947 init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, | 1163 init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, |
| 972 length = img->size; | 1188 length = img->size; |
| 973 defaults_assumed = true; | 1189 defaults_assumed = true; |
| 974 } | 1190 } |
| 975 } | 1191 } |
| 976 } | 1192 } |
| 977 if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) && | 1193 if ((!mem_addr_set || mem_addr == load_address) && !no_copy && (load_address >= (CYG_ADDRESS)ram_start) && |
| 978 (load_address_end) < (CYG_ADDRESS)ram_end) { | 1194 (load_address_end) < (CYG_ADDRESS)ram_end) { |
| 979 mem_addr = load_address; | 1195 mem_addr = load_address; |
| 980 mem_addr_set = true; | 1196 mem_addr_set = true; |
| 981 defaults_assumed = true; | 1197 defaults_assumed = true; |
| 982 // Get entry address from loader, unless overridden | 1198 // Get entry address from loader, unless overridden |
| 983 if (!entry_addr_set) | 1199 if (!entry_addr_set) { |
| 984 entry_addr = entry_address; | 1200 entry_addr = entry_address; |
| 1201 entry_addr_set = true; | |
| 1202 } | |
| 985 if (!length_set) { | 1203 if (!length_set) { |
| 986 length = load_address_end - load_address; | 1204 length = load_address_end - load_address; |
| 987 length_set = true; | 1205 length_set = true; |
| 988 } else if (defaults_assumed && !img_size_set) { | 1206 } else if (defaults_assumed && !img_size_set) { |
| 989 /* We got length from the FIS table, so the size of the | 1207 /* We got length from the FIS table, so the size of the |
| 1004 flash_addr = img->flash_base; | 1222 flash_addr = img->flash_base; |
| 1005 defaults_assumed = true; | 1223 defaults_assumed = true; |
| 1006 } | 1224 } |
| 1007 } | 1225 } |
| 1008 | 1226 |
| 1009 if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) || | 1227 if ((!no_copy && !mem_addr_set) || |
| 1010 !length_set || !name) { | 1228 !length_set || !name) { |
| 1011 fis_usage("required parameter missing"); | 1229 fis_usage("required parameter missing"); |
| 1012 return; | 1230 return; |
| 1013 } | 1231 } |
| 1014 if (!img_size_set) { | 1232 if (!img_size_set) { |
| 1015 img_size = length; | 1233 img_size = length; |
| 1016 } | 1234 } |
| 1017 // 'length' is size of FLASH image, 'img_size' is actual data size | |
| 1018 // Round up length to FLASH block size | |
| 1019 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken | |
| 1020 length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size; | |
| 1021 if (length < img_size) { | 1235 if (length < img_size) { |
| 1022 diag_printf("Invalid FLASH image size/length combination\n"); | 1236 diag_printf("Invalid FLASH image size/length combination\n"); |
| 1023 return; | 1237 return; |
| 1024 } | 1238 } |
| 1025 #endif | 1239 |
| 1240 if (strlen(name) >= sizeof(img->u.name)) { | |
| 1241 diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->u.name)); | |
| 1242 return; | |
| 1243 } | |
| 1244 | |
| 1026 if (flash_addr_set && | 1245 if (flash_addr_set && |
| 1027 ((stat = flash_verify_addr((void *)flash_addr)) || | 1246 ((stat = flash_verify_addr((void *)flash_addr)) || |
| 1028 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { | 1247 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { |
| 1029 _show_invalid_flash_address(flash_addr, stat); | 1248 _show_invalid_flash_address(flash_addr, stat); |
| 1030 return; | |
| 1031 } | |
| 1032 if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) { | |
| 1033 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); | |
| 1034 diag_printf(" must be 0x%x aligned\n", flash_block_size); | |
| 1035 return; | |
| 1036 } | |
| 1037 if (strlen(name) >= sizeof(img->u.name)) { | |
| 1038 diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->u.name)); | |
| 1039 return; | 1249 return; |
| 1040 } | 1250 } |
| 1041 if (!no_copy) { | 1251 if (!no_copy) { |
| 1042 if ((mem_addr < (CYG_ADDRESS)ram_start) || | 1252 if ((mem_addr < (CYG_ADDRESS)ram_start) || |
| 1043 ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) { | 1253 ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) { |
| 1044 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); | 1254 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); |
| 1045 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); | 1255 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); |
| 1046 } | 1256 } |
| 1047 if (!flash_addr_set && !fis_find_free(&flash_addr, length)) { | 1257 } |
| 1048 diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length); | 1258 if (!flash_addr_set && !fis_find_free(&flash_addr, length)) { |
| 1049 return; | 1259 diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length); |
| 1050 } | 1260 return; |
| 1051 } | 1261 } |
| 1262 flash_addr_set = true; | |
| 1263 | |
| 1264 block_size = cyg_flash_block_size(flash_addr + length); | |
| 1265 length = ((length + block_size - 1) / block_size) * block_size; | |
| 1266 if (length < img_size) { | |
| 1267 diag_printf("Invalid FLASH image size/length combination\n"); | |
| 1268 return; | |
| 1269 } | |
| 1270 if ((stat = cyg_flash_verify_addr(flash_addr)) || | |
| 1271 (stat = cyg_flash_verify_addr((flash_addr+length-1)))) { | |
| 1272 _show_invalid_flash_address(flash_addr, stat); | |
| 1273 return; | |
| 1274 } | |
| 1275 block_size = cyg_flash_block_size(flash_addr); | |
| 1276 flash_offset = (flash_addr-flash_start)/block_size; | |
| 1277 if( flash_start + (flash_offset * block_size) != flash_addr ) { | |
| 1278 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); | |
| 1279 diag_printf(" must be 0x%x aligned\n", (unsigned int)flash_block_size); | |
| 1280 return; | |
| 1281 } | |
| 1282 | |
| 1052 // First, see if the image by this name has agreable properties | 1283 // First, see if the image by this name has agreable properties |
| 1053 if (img) { | 1284 if (img) { |
| 1054 if (flash_addr_set && (img->flash_base != flash_addr)) { | 1285 if (img->flash_base != flash_addr) { |
| 1055 diag_printf("Image found, but flash address (%p)\n" | 1286 diag_printf("Image found, but flash address (%p)\n" |
| 1056 " is incorrect (present image location %p)\n", | 1287 " is incorrect (present image location %p)\n", |
| 1057 (void*)flash_addr, (void*)img->flash_base); | 1288 (void*)flash_addr, (void*)img->flash_base); |
| 1058 | 1289 |
| 1059 return; | 1290 return; |
| 1077 } | 1308 } |
| 1078 } | 1309 } |
| 1079 } else { | 1310 } else { |
| 1080 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS | 1311 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS |
| 1081 // Make sure that any FLASH address specified directly is truly free | 1312 // Make sure that any FLASH address specified directly is truly free |
| 1082 if (flash_addr_set && !no_copy) { | 1313 if (!no_copy) { |
| 1083 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; | 1314 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; |
| 1084 int idx, num_chunks; | 1315 int idx, num_chunks; |
| 1085 bool is_free = false; | 1316 bool is_free = false; |
| 1086 | 1317 |
| 1087 num_chunks = find_free(chunks); | 1318 num_chunks = find_free(chunks); |
| 1088 for (idx = 0; idx < num_chunks; idx++) { | 1319 for (idx = 0; idx < num_chunks; idx++) { |
| 1320 //diag_printf("addr %08x, length %d chunk start %08x, end %08x\n",flash_addr, length, chunks[idx].start, chunks[idx].end); | |
| 1089 if ((flash_addr >= chunks[idx].start) && | 1321 if ((flash_addr >= chunks[idx].start) && |
| 1090 ((flash_addr+length-1) <= chunks[idx].end)) { | 1322 ((flash_addr+length-1) <= chunks[idx].end)) { |
| 1091 is_free = true; | 1323 is_free = true; |
| 1092 } | 1324 } |
| 1093 } | 1325 } |
| 1095 diag_printf("Invalid FLASH address - not free!\n"); | 1327 diag_printf("Invalid FLASH address - not free!\n"); |
| 1096 return; | 1328 return; |
| 1097 } | 1329 } |
| 1098 } | 1330 } |
| 1099 #endif | 1331 #endif |
| 1100 // If not image by that name, try and find an empty slot | 1332 // If no image by that name, try and find an empty slot |
| 1101 img = (struct fis_image_desc *)fis_work_block; | 1333 img = (struct fis_image_desc *)fis_work_block; |
| 1102 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { | 1334 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { |
| 1103 if (img->u.name[0] == (unsigned char)0xFF) { | 1335 if (img->u.name[0] == '\xFF') { |
| 1104 break; | 1336 break; |
| 1105 } | 1337 } |
| 1106 } | 1338 } |
| 1107 if (i >= fisdir_size/sizeof(*img)) { | 1339 if (i >= fisdir_size/sizeof(*img)) { |
| 1108 diag_printf("Can't find an empty slot in FIS directory!\n"); | 1340 diag_printf("Can't find an empty slot in FIS directory!\n"); |
| 1109 return; | 1341 return; |
| 1110 } | 1342 } |
| 1111 } | 1343 } |
| 1112 if (!no_copy) { | 1344 if (!no_copy) { |
| 1113 // Safety check - make sure the address range is not within the code we're running | 1345 // Safety check - make sure the address range is not within the code we're running |
| 1114 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) { | 1346 if (check_code_overlaps(flash_addr, (flash_addr+img_size-1))) { |
| 1115 diag_printf("Can't program this region - contains code in use!\n"); | 1347 diag_printf("Can't program this region - contains code in use!\n"); |
| 1116 return; | 1348 return; |
| 1117 } | 1349 } |
| 1350 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | |
| 1351 if (prog_ok) { | |
| 1352 // Unlock area to be programmed | |
| 1353 if ((stat = cyg_flash_unlock((cyg_flashaddr_t)flash_addr, length, &err_addr)) != 0) { | |
| 1354 diag_printf("Can't unlock region at %p: %s\n", (void*)err_addr, flash_errmsg(stat)); | |
| 1355 prog_ok = false; | |
| 1356 } | |
| 1357 } | |
| 1358 #endif | |
| 1118 if (prog_ok) { | 1359 if (prog_ok) { |
| 1119 // Erase area to be programmed | 1360 // Erase area to be programmed |
| 1120 if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) { | 1361 if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) { |
| 1121 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat)); | 1362 diag_printf("Can't erase region at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat)); |
| 1122 prog_ok = false; | 1363 prog_ok = false; |
| 1123 } | 1364 } |
| 1124 } | 1365 } |
| 1125 if (prog_ok) { | 1366 if (prog_ok) { |
| 1126 // Now program it | 1367 // Now program it |
| 1127 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { | 1368 if ((stat = cyg_flash_program(flash_addr, (void *)mem_addr, img_size, |
| 1128 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); | 1369 &err_addr)) != 0) { |
| 1370 diag_printf("Can't program region at %p: %s\n", (void*)err_addr, | |
| 1371 cyg_flash_errmsg(stat)); | |
| 1129 prog_ok = false; | 1372 prog_ok = false; |
| 1130 } | 1373 } |
| 1131 } | 1374 } |
| 1375 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | |
| 1376 if (prog_ok) { | |
| 1377 // Lock area programmed | |
| 1378 if ((stat = cyg_flash_lock((cyg_flashaddr_t)flash_addr, length, &err_addr)) != 0) { | |
| 1379 diag_printf("Can't lock region at %p: %s\n", (void*)err_addr, flash_errmsg(stat)); | |
| 1380 prog_ok = false; | |
| 1381 } | |
| 1382 } | |
| 1383 #endif | |
| 1132 } | 1384 } |
| 1133 if (prog_ok) { | 1385 if (prog_ok) { |
| 1134 // Update directory | 1386 // Update directory |
| 1135 memset(img, 0, sizeof(*img)); | 1387 memset(img, 0, sizeof(*img)); |
| 1136 strcpy(img->u.name, name); | 1388 strcpy(img->u.name, name); |
| 1156 static void | 1408 static void |
| 1157 fis_delete(int argc, char *argv[]) | 1409 fis_delete(int argc, char *argv[]) |
| 1158 { | 1410 { |
| 1159 char *name; | 1411 char *name; |
| 1160 int num_reserved, i, stat; | 1412 int num_reserved, i, stat; |
| 1161 void *err_addr; | 1413 cyg_flashaddr_t err_addr; |
| 1162 struct fis_image_desc *img; | 1414 struct fis_image_desc *img; |
| 1163 | 1415 |
| 1164 if (!scan_opts(argc, argv, 2, 0, 0, (void *)&name, OPTION_ARG_TYPE_STR, "image name")) | 1416 if (!scan_opts(argc, argv, 2, 0, 0, (void *)&name, OPTION_ARG_TYPE_STR, "image name")) |
| 1165 { | 1417 { |
| 1166 fis_usage("invalid arguments"); | 1418 fis_usage("invalid arguments"); |
| 1204 } else { | 1456 } else { |
| 1205 diag_printf("No image '%s' found\n", name); | 1457 diag_printf("No image '%s' found\n", name); |
| 1206 return; | 1458 return; |
| 1207 } | 1459 } |
| 1208 // Erase Data blocks (free space) | 1460 // Erase Data blocks (free space) |
| 1209 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) { | 1461 if ((stat = cyg_flash_erase(img->flash_base, img->size, &err_addr)) != 0) { |
| 1210 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat)); | 1462 diag_printf("Error erasing at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat)); |
| 1211 } else { | 1463 } else { |
| 1212 img->u.name[0] = (unsigned char)0xFF; | 1464 img->u.name[0] = '\xFF'; |
| 1213 fis_start_update_directory(0); | 1465 fis_start_update_directory(0); |
| 1214 fis_update_directory(0, 0); | 1466 fis_update_directory(0, 0); |
| 1215 } | 1467 } |
| 1216 } | 1468 } |
| 1217 | 1469 |
| 1229 #endif | 1481 #endif |
| 1230 int num_options; | 1482 int num_options; |
| 1231 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) || defined(CYGSEM_REDBOOT_FIS_CRC_CHECK) | 1483 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) || defined(CYGSEM_REDBOOT_FIS_CRC_CHECK) |
| 1232 bool decompress = false; | 1484 bool decompress = false; |
| 1233 #endif | 1485 #endif |
| 1234 void *err_addr; | 1486 cyg_flashaddr_t err_addr; |
| 1235 | 1487 |
| 1236 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, | 1488 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, |
| 1237 (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address"); | 1489 (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address"); |
| 1238 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, | 1490 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, |
| 1239 (void *)&show_cksum, (bool *)0, "display checksum"); | 1491 (void *)&show_cksum, (bool *)0, "display checksum"); |
| 1297 // Reload fis directory | 1549 // Reload fis directory |
| 1298 fis_read_directory(); | 1550 fis_read_directory(); |
| 1299 } else // dangling block | 1551 } else // dangling block |
| 1300 #endif | 1552 #endif |
| 1301 { | 1553 { |
| 1302 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr); | 1554 cyg_flash_read(img->flash_base, (void *)mem_addr, img->data_length, |
| 1555 &err_addr); | |
| 1303 | 1556 |
| 1304 // Set load address/top | 1557 // Set load address/top |
| 1305 load_address = mem_addr; | 1558 load_address = mem_addr; |
| 1306 load_address_end = mem_addr + img->data_length; | 1559 load_address_end = mem_addr + img->data_length; |
| 1307 } | 1560 } |
| 1327 static void | 1580 static void |
| 1328 fis_write(int argc, char *argv[]) | 1581 fis_write(int argc, char *argv[]) |
| 1329 { | 1582 { |
| 1330 int stat; | 1583 int stat; |
| 1331 unsigned long length; | 1584 unsigned long length; |
| 1332 CYG_ADDRESS mem_addr, flash_addr; | 1585 CYG_ADDRESS mem_addr, flash_addr, flash_offset; |
| 1333 bool mem_addr_set = false; | 1586 bool mem_addr_set = false; |
| 1334 bool flash_addr_set = false; | 1587 bool flash_addr_set = false; |
| 1335 bool length_set = false; | 1588 bool length_set = false; |
| 1336 void *err_addr; | 1589 cyg_flashaddr_t err_addr; |
| 1337 struct option_info opts[3]; | 1590 struct option_info opts[3]; |
| 1338 bool prog_ok; | 1591 bool prog_ok; |
| 1339 | 1592 size_t block_size; |
| 1593 | |
| 1340 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, | 1594 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, |
| 1341 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); | 1595 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); |
| 1342 init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, | 1596 init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, |
| 1343 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 1597 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 1344 init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM, | 1598 init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM, |
| 1353 fis_usage("required parameter missing"); | 1607 fis_usage("required parameter missing"); |
| 1354 return; | 1608 return; |
| 1355 } | 1609 } |
| 1356 | 1610 |
| 1357 // Round up length to FLASH block size | 1611 // Round up length to FLASH block size |
| 1358 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken | 1612 block_size = cyg_flash_block_size(flash_addr + length); |
| 1359 length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size; | 1613 length = ((length + block_size - 1) / block_size) * block_size; |
| 1360 #endif | 1614 if ((stat = cyg_flash_verify_addr(flash_addr)) || |
| 1361 if (flash_addr_set && | 1615 (stat = cyg_flash_verify_addr((flash_addr+length-1)))) { |
| 1362 ((stat = flash_verify_addr((void *)flash_addr)) || | |
| 1363 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { | |
| 1364 _show_invalid_flash_address(flash_addr, stat); | 1616 _show_invalid_flash_address(flash_addr, stat); |
| 1365 return; | 1617 return; |
| 1366 } | 1618 } |
| 1367 if (flash_addr_set && flash_addr & (flash_block_size-1)) { | 1619 |
| 1620 block_size = cyg_flash_block_size(flash_addr); | |
| 1621 flash_offset = (flash_addr-flash_start)/block_size; | |
| 1622 if( flash_start + (flash_offset * block_size) != flash_addr ) { | |
| 1368 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); | 1623 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); |
| 1369 diag_printf(" must be 0x%x aligned\n", flash_block_size); | 1624 diag_printf(" must be 0x%x aligned\n", (unsigned int)block_size); |
| 1370 return; | 1625 return; |
| 1371 } | 1626 } |
| 1372 if ((mem_addr < (CYG_ADDRESS)ram_start) || | 1627 if ((mem_addr < (CYG_ADDRESS)ram_start) || |
| 1373 ((mem_addr+length) >= (CYG_ADDRESS)ram_end)) { | 1628 ((mem_addr+length) >= (CYG_ADDRESS)ram_end)) { |
| 1374 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); | 1629 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); |
| 1375 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); | 1630 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); |
| 1376 } | 1631 } |
| 1377 // Safety check - make sure the address range is not within the code we're running | 1632 // Safety check - make sure the address range is not within the code we're running |
| 1378 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) { | 1633 if (check_code_overlaps(flash_addr, (flash_addr+length-1))) { |
| 1379 diag_printf("Can't program this region - contains code in use!\n"); | 1634 diag_printf("Can't program this region - contains code in use!\n"); |
| 1380 return; | 1635 return; |
| 1381 } | 1636 } |
| 1382 if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p", | 1637 if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p", |
| 1383 (void *)flash_addr, (void *)(flash_addr+length-1), | 1638 (void *)flash_addr, (void *)(flash_addr+length-1), |
| 1385 return; // The guy gave up | 1640 return; // The guy gave up |
| 1386 } | 1641 } |
| 1387 prog_ok = true; | 1642 prog_ok = true; |
| 1388 if (prog_ok) { | 1643 if (prog_ok) { |
| 1389 // Erase area to be programmed | 1644 // Erase area to be programmed |
| 1390 if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) { | 1645 if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) { |
| 1391 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat)); | 1646 diag_printf("Can't erase region at %p: %s\n", (void*)err_addr, |
| 1647 cyg_flash_errmsg(stat)); | |
| 1392 prog_ok = false; | 1648 prog_ok = false; |
| 1393 } | 1649 } |
| 1394 } | 1650 } |
| 1395 if (prog_ok) { | 1651 if (prog_ok) { |
| 1396 // Now program it | 1652 // Now program it |
| 1397 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { | 1653 if ((stat = cyg_flash_program(flash_addr, (void *)mem_addr, length, |
| 1398 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); | 1654 &err_addr)) != 0) { |
| 1655 diag_printf("Can't program region at %p: %s\n", (void*)err_addr, | |
| 1656 cyg_flash_errmsg(stat)); | |
| 1399 prog_ok = false; | 1657 prog_ok = false; |
| 1400 } | 1658 } |
| 1401 } | 1659 } |
| 1402 } | 1660 } |
| 1403 | 1661 |
| 1404 static void | 1662 static void |
| 1405 fis_erase(int argc, char *argv[]) | 1663 fis_erase(int argc, char *argv[]) |
| 1406 { | 1664 { |
| 1407 int stat; | 1665 int stat; |
| 1408 unsigned long length; | 1666 unsigned long length; |
| 1409 CYG_ADDRESS flash_addr; | 1667 CYG_ADDRESS flash_addr, flash_offset; |
| 1410 bool flash_addr_set = false; | 1668 bool flash_addr_set = false; |
| 1411 bool length_set = false; | 1669 bool length_set = false; |
| 1412 void *err_addr; | 1670 cyg_flashaddr_t err_addr; |
| 1413 struct option_info opts[2]; | 1671 struct option_info opts[2]; |
| 1672 size_t block_size; | |
| 1673 | |
| 1414 | 1674 |
| 1415 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, | 1675 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, |
| 1416 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 1676 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 1417 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, | 1677 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, |
| 1418 (void *)&length, (bool *)&length_set, "length"); | 1678 (void *)&length, (bool *)&length_set, "length"); |
| 1425 if (!flash_addr_set || !length_set) { | 1685 if (!flash_addr_set || !length_set) { |
| 1426 fis_usage("missing argument"); | 1686 fis_usage("missing argument"); |
| 1427 return; | 1687 return; |
| 1428 } | 1688 } |
| 1429 if (flash_addr_set && | 1689 if (flash_addr_set && |
| 1430 ((stat = flash_verify_addr((void *)flash_addr)) || | 1690 ((stat = cyg_flash_verify_addr(flash_addr)) || |
| 1431 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { | 1691 (stat = cyg_flash_verify_addr((flash_addr+length-1))))) { |
| 1432 _show_invalid_flash_address(flash_addr, stat); | 1692 _show_invalid_flash_address(flash_addr, stat); |
| 1433 return; | 1693 return; |
| 1434 } | 1694 } |
| 1435 if (flash_addr_set && flash_addr & (flash_block_size-1)) { | 1695 block_size = cyg_flash_block_size(flash_addr); |
| 1696 flash_offset = (flash_addr-flash_start)/block_size; | |
| 1697 if( flash_addr_set && (flash_start + (flash_offset * block_size) != flash_addr) ) { | |
| 1436 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); | 1698 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); |
| 1437 diag_printf(" must be 0x%x aligned\n", flash_block_size); | 1699 diag_printf(" must be 0x%x aligned\n", (unsigned int)flash_block_size); |
| 1438 return; | 1700 return; |
| 1439 } | 1701 } |
| 1440 // Safety check - make sure the address range is not within the code we're running | 1702 // Safety check - make sure the address range is not within the code we're running |
| 1441 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) { | 1703 if (check_code_overlaps(flash_addr, (flash_addr+length-1))) { |
| 1442 diag_printf("Can't erase this region - contains code in use!\n"); | 1704 diag_printf("Can't erase this region - contains code in use!\n"); |
| 1443 return; | 1705 return; |
| 1444 } | 1706 } |
| 1445 if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) { | 1707 if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) { |
| 1446 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat)); | 1708 diag_printf("Error erasing at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat)); |
| 1447 } | 1709 } |
| 1448 } | 1710 } |
| 1449 | 1711 |
| 1450 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING | 1712 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING |
| 1451 | 1713 |
| 1456 int stat; | 1718 int stat; |
| 1457 unsigned long length; | 1719 unsigned long length; |
| 1458 CYG_ADDRESS flash_addr; | 1720 CYG_ADDRESS flash_addr; |
| 1459 bool flash_addr_set = false; | 1721 bool flash_addr_set = false; |
| 1460 bool length_set = false; | 1722 bool length_set = false; |
| 1461 void *err_addr; | 1723 cyg_flashaddr_t err_addr; |
| 1462 struct option_info opts[2]; | 1724 struct option_info opts[2]; |
| 1463 | 1725 |
| 1464 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, | 1726 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, |
| 1465 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 1727 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 1466 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, | 1728 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, |
| 1486 if (!flash_addr_set || !length_set) { | 1748 if (!flash_addr_set || !length_set) { |
| 1487 fis_usage("missing argument"); | 1749 fis_usage("missing argument"); |
| 1488 return; | 1750 return; |
| 1489 } | 1751 } |
| 1490 if (flash_addr_set && | 1752 if (flash_addr_set && |
| 1491 ((stat = flash_verify_addr((void *)flash_addr)) || | 1753 ((stat = cyg_flash_verify_addr(flash_addr)) || |
| 1492 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { | 1754 (stat = cyg_flash_verify_addr((flash_addr+length-1))))) { |
| 1493 _show_invalid_flash_address(flash_addr, stat); | 1755 _show_invalid_flash_address(flash_addr, stat); |
| 1494 return; | 1756 return; |
| 1495 } | 1757 } |
| 1496 if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) { | 1758 if ((stat = cyg_flash_lock(flash_addr, length, &err_addr)) != 0) { |
| 1497 diag_printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat)); | 1759 diag_printf("Error locking at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat)); |
| 1498 } | 1760 } |
| 1499 } | 1761 } |
| 1500 | 1762 |
| 1501 static void | 1763 static void |
| 1502 fis_unlock(int argc, char *argv[]) | 1764 fis_unlock(int argc, char *argv[]) |
| 1505 int stat; | 1767 int stat; |
| 1506 unsigned long length; | 1768 unsigned long length; |
| 1507 CYG_ADDRESS flash_addr; | 1769 CYG_ADDRESS flash_addr; |
| 1508 bool flash_addr_set = false; | 1770 bool flash_addr_set = false; |
| 1509 bool length_set = false; | 1771 bool length_set = false; |
| 1510 void *err_addr; | 1772 cyg_flashaddr_t err_addr; |
| 1511 struct option_info opts[2]; | 1773 struct option_info opts[2]; |
| 1512 | 1774 |
| 1513 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, | 1775 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, |
| 1514 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 1776 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 1515 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, | 1777 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, |
| 1534 if (!flash_addr_set || !length_set) { | 1796 if (!flash_addr_set || !length_set) { |
| 1535 fis_usage("missing argument"); | 1797 fis_usage("missing argument"); |
| 1536 return; | 1798 return; |
| 1537 } | 1799 } |
| 1538 if (flash_addr_set && | 1800 if (flash_addr_set && |
| 1539 ((stat = flash_verify_addr((void *)flash_addr)) || | 1801 ((stat = cyg_flash_verify_addr(flash_addr)) || |
| 1540 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { | 1802 (stat = cyg_flash_verify_addr((flash_addr+length-1))))) { |
| 1541 _show_invalid_flash_address(flash_addr, stat); | 1803 _show_invalid_flash_address(flash_addr, stat); |
| 1542 return; | 1804 return; |
| 1543 } | 1805 } |
| 1544 | 1806 |
| 1545 if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) { | 1807 if ((stat = cyg_flash_unlock(flash_addr, length, &err_addr)) != 0) { |
| 1546 diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat)); | 1808 diag_printf("Error unlocking at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat)); |
| 1547 } | 1809 } |
| 1548 } | 1810 } |
| 1549 #endif | 1811 #endif |
| 1550 | 1812 |
| 1551 // This is set non-zero if the FLASH subsystem has successfully been initialized | 1813 // This is set non-zero if the FLASH subsystem has successfully been initialized |
| 1552 int __flash_init = 0; | 1814 int __flash_init; |
| 1553 | 1815 |
| 1554 void | 1816 void |
| 1555 _flash_info(void) | 1817 _flash_info(void) |
| 1556 { | 1818 { |
| 1819 cyg_uint32 i=0,j; | |
| 1820 cyg_flash_info_t info; | |
| 1821 int ret; | |
| 1822 | |
| 1557 if (!__flash_init) return; | 1823 if (!__flash_init) return; |
| 1558 diag_printf("FLASH: %p - 0x%x, %d blocks of %p bytes each.\n", | 1824 |
| 1559 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size); | 1825 do { |
| 1826 ret = cyg_flash_get_info(i, &info); | |
| 1827 if (ret == CYG_FLASH_ERR_OK) { | |
| 1828 diag_printf("FLASH: %p-%p", (void*)info.start, (void*)info.end); | |
| 1829 for (j=0;j < info.num_block_infos; j++) { | |
| 1830 diag_printf(", %d x 0x%x blocks", | |
| 1831 info.block_info[j].blocks, | |
| 1832 (unsigned int)info.block_info[j].block_size); | |
| 1833 } | |
| 1834 diag_printf("\n"); | |
| 1835 } | |
| 1836 i++; | |
| 1837 } while (ret != CYG_FLASH_ERR_INVALID); | |
| 1560 } | 1838 } |
| 1561 | 1839 |
| 1562 /* Returns -1 on failure, 0 on success, 1 if it was successfull | 1840 /* Returns -1 on failure, 0 on success, 1 if it was successfull |
| 1563 but a failed fis update was detected */ | 1841 but a failed fis update was detected */ |
| 1564 int | 1842 int |
| 1565 do_flash_init(void) | 1843 do_flash_init(void) |
| 1566 { | 1844 { |
| 1567 int stat; | 1845 int stat, i; |
| 1846 cyg_flash_info_t info; | |
| 1568 | 1847 |
| 1569 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS | 1848 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS |
| 1570 struct fis_image_desc img0; | 1849 struct fis_image_desc img0; |
| 1571 struct fis_image_desc img1; | 1850 struct fis_image_desc img1; |
| 1572 int fis_update_was_interrupted=0; | 1851 int fis_update_was_interrupted=0; |
| 1573 void *err_addr; | 1852 cyg_flashaddr_t err_addr; |
| 1574 | 1853 |
| 1575 //check the size of fis_valid_info | 1854 //check the size of fis_valid_info |
| 1576 CYG_ASSERT((sizeof(struct fis_valid_info)<=sizeof(img0.u.name)), "fis_valid_info size mismatch"); | 1855 CYG_ASSERT((sizeof(struct fis_valid_info)<=sizeof(img0.u.name)), "fis_valid_info size mismatch"); |
| 1577 //try to check the alignment of version_count | 1856 //try to check the alignment of version_count |
| 1578 CYG_ASSERT((((unsigned long)&img0.u.valid_info.version_count - (unsigned long)&img0) % sizeof(unsigned long) == 0), "alignment problem"); | 1857 CYG_ASSERT((((unsigned long)&img0.u.valid_info.version_count - (unsigned long)&img0) % sizeof(unsigned long) == 0), "alignment problem"); |
| 1580 | 1859 |
| 1581 | 1860 |
| 1582 | 1861 |
| 1583 if (!__flash_init) { | 1862 if (!__flash_init) { |
| 1584 __flash_init = 1; | 1863 __flash_init = 1; |
| 1585 if ((stat = flash_init(diag_printf)) != 0) { | 1864 |
| 1586 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); | 1865 if ((stat = cyg_flash_init(diag_printf)) != 0) { |
| 1866 diag_printf("FLASH: driver init failed: %s\n", cyg_flash_errmsg(stat)); | |
| 1587 return -1; | 1867 return -1; |
| 1588 } | 1868 } |
| 1589 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end); | 1869 |
| 1590 // Keep 'end' address as last valid location, to avoid wrap around problems | 1870 #ifdef CYGNUM_REDBOOT_FLASH_BASE |
| 1591 flash_end = (void *)((CYG_ADDRESS)flash_end - 1); | 1871 stat = cyg_flash_get_info_addr(CYGNUM_REDBOOT_FLASH_BASE, &info); |
| 1592 flash_get_block_info(&flash_block_size, &flash_num_blocks); | 1872 #else |
| 1873 stat = cyg_flash_get_info(0, &info); | |
| 1874 #endif | |
| 1875 if (stat != CYG_FLASH_ERR_OK) { | |
| 1876 diag_printf("FLASH: driver init failed: %s\n", | |
| 1877 cyg_flash_errmsg(stat)); | |
| 1878 return false; | |
| 1879 } | |
| 1880 flash_start = info.start; | |
| 1881 flash_end = info.end; | |
| 1882 | |
| 1883 // No bootblock support yet, so we merge any bootblocks we might | |
| 1884 // find into full size blocks | |
| 1885 for (i=0; i < info.num_block_infos; i++) { | |
| 1886 if (info.block_info[i].block_size > flash_block_size) { | |
| 1887 flash_block_size = info.block_info[i].block_size; | |
| 1888 } | |
| 1889 } | |
| 1890 flash_num_blocks = 0; | |
| 1891 for (i=0; i < info.num_block_infos; i++) { | |
| 1892 flash_num_blocks += (info.block_info[i].block_size * | |
| 1893 info.block_info[i].blocks) / | |
| 1894 flash_block_size; | |
| 1895 } | |
| 1896 | |
| 1593 #ifdef CYGOPT_REDBOOT_FIS | 1897 #ifdef CYGOPT_REDBOOT_FIS |
| 1594 fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE; | 1898 fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE; |
| 1595 fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size; | 1899 fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size; |
| 1596 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER) | 1900 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER) |
| 1597 fis_work_block = fis_zlib_common_buffer; | 1901 fis_work_block = fis_zlib_common_buffer; |
| 1601 } | 1905 } |
| 1602 # else | 1906 # else |
| 1603 workspace_end = (unsigned char *)(workspace_end-fisdir_size); | 1907 workspace_end = (unsigned char *)(workspace_end-fisdir_size); |
| 1604 fis_work_block = workspace_end; | 1908 fis_work_block = workspace_end; |
| 1605 # endif | 1909 # endif |
| 1910 | |
| 1606 if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) { | 1911 if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) { |
| 1607 fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 + | 1912 fis_addr = ((CYG_ADDRESS)flash_end + 1 + |
| 1608 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); | 1913 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); |
| 1609 } else { | 1914 } else { |
| 1610 fis_addr = (void *)((CYG_ADDRESS)flash_start + | 1915 fis_addr = ((CYG_ADDRESS)flash_start + |
| 1611 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); | 1916 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); |
| 1612 } | 1917 } |
| 1613 | 1918 |
| 1614 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { | 1919 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { |
| 1615 diag_printf("FIS directory doesn't fit\n"); | 1920 diag_printf("FIS directory doesn't fit\n"); |
| 1616 return -1; | 1921 return -1; |
| 1627 | 1932 |
| 1628 if (((CYG_ADDRESS)redundant_fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { | 1933 if (((CYG_ADDRESS)redundant_fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { |
| 1629 diag_printf("Redundant FIS directory doesn't fit\n"); | 1934 diag_printf("Redundant FIS directory doesn't fit\n"); |
| 1630 return -1; | 1935 return -1; |
| 1631 } | 1936 } |
| 1632 FLASH_READ(fis_addr, &img0, sizeof(img0), (void **)&err_addr); | 1937 cyg_flash_read(fis_addr, &img0, sizeof(img0), &err_addr); |
| 1633 FLASH_READ(redundant_fis_addr, &img1, sizeof(img1), (void **)&err_addr); | 1938 cyg_flash_read(redundant_fis_addr, &img1, sizeof(img1), &err_addr); |
| 1634 | 1939 |
| 1635 if (strncmp(img0.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0) | 1940 if (strncmp(img0.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0) |
| 1636 { | 1941 { |
| 1637 memset(&img0, 0, sizeof(img0)); | 1942 memset(&img0, 0, sizeof(img0)); |
| 1638 } | 1943 } |
