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 }