comparison packages/redboot/current/src/flash.c @ 2195:5c5e93c863ac

Redundant FIS table support - from Alexander Neundorf
author gthomas
date Tue, 09 May 2006 15:52:01 +0000
parents 55e180a14a91
children eee88a59c155
comparison
equal deleted inserted replaced
2194:b1a65d90ce72 2195:5c5e93c863ac
167 void *flash_start, *flash_end; 167 void *flash_start, *flash_end;
168 int flash_block_size, flash_num_blocks; 168 int flash_block_size, flash_num_blocks;
169 #ifdef CYGOPT_REDBOOT_FIS 169 #ifdef CYGOPT_REDBOOT_FIS
170 void *fis_work_block; 170 void *fis_work_block;
171 void *fis_addr; 171 void *fis_addr;
172 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
173 void *redundant_fis_addr;
174 #endif
172 int fisdir_size; // Size of FIS directory. 175 int fisdir_size; // Size of FIS directory.
173 #endif 176 #endif
174 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG 177 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
175 extern void *cfg_base; // Location in Flash of config data 178 extern void *cfg_base; // Location in Flash of config data
176 extern int cfg_size; // Length of config data - rounded to Flash block size 179 extern int cfg_size; // Length of config data - rounded to Flash block size
231 234
232 fis_read_directory(); 235 fis_read_directory();
233 236
234 img = (struct fis_image_desc *)fis_work_block; 237 img = (struct fis_image_desc *)fis_work_block;
235 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 238 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
236 if ((img->name[0] != (unsigned char)0xFF) && 239 if ((img->u.name[0] != (unsigned char)0xFF) &&
237 (strcasecmp(name, img->name) == 0)) { 240 (strcasecmp(name, img->u.name) == 0)) {
238 if (num) *num = i; 241 if (num) *num = i;
239 return img; 242 return img;
240 } 243 }
241 } 244 }
242 return (struct fis_image_desc *)0; 245 return (struct fis_image_desc *)0;
243 } 246 }
244 247
245 void 248 int fis_start_update_directory(int autolock)
246 fis_update_directory(void) 249 {
247 { 250 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
248 int blk_size = fisdir_size; 251 // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
252 int do_autolock=1;
253 #else
254 int do_autolock=autolock;
255 #endif
256
257 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
258 struct fis_image_desc* img=NULL;
259 void* err_addr=NULL;
260 void* tmp_fis_addr=NULL;
261
262 /*exchange old and new valid fis tables*/
263 tmp_fis_addr=fis_addr;
264 fis_addr=redundant_fis_addr;
265 redundant_fis_addr=tmp_fis_addr;
266
267 //adjust the contents of the new fis table
268 img=(struct fis_image_desc*)fis_work_block;
269
270 memcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
271 img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_IN_PROGRESS;
272 img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_IN_PROGRESS;
273 img->u.valid_info.version_count=img->u.valid_info.version_count+1;
274
275 //ready to go....
276 if (do_autolock)
277 flash_unlock((void *)fis_addr, fisdir_size, (void **)&err_addr);
278
279 flash_erase(fis_addr, fisdir_size, (void **)&err_addr);
280 //now magic is 0xffffffff
281 fis_endian_fixup(fis_work_block);
282 flash_program(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr);
283 fis_endian_fixup(fis_work_block);
284 //now magic is 0xff1234ff, valid is IN_PROGRESS, version_count is the old one +1
285
286 #else
287 /* nothing to do here without redundant fis */
288 #endif
289 return 0;
290
291 }
292
293 int
294 fis_update_directory(int autolock, int error)
295 {
296 void* err_addr=0;
297
298 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
299 // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
300 int do_autolock=1;
301 #else
302 int do_autolock=autolock;
303 #endif
304
305 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
306
307 struct fis_image_desc* img=(struct fis_image_desc*)fis_work_block;
308
309 // called from invalid state
310 if (img->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_IN_PROGRESS)
311 return -1;
312
313 //if it failed, reset is0Valid to the state before startUpdateDirectory()
314 //g_data.fisTable hasn't been changed yet, so it doesn't have to be reset now
315 //then reread the contents from flash
316 //setting the valid flag of the failed table to "INVALID" might also be not too bad
317 //but IN_PROGRESS is also good enough I think
318 if (error!=0)
319 {
320 void* swap_fis_addr=fis_addr;
321 fis_addr=redundant_fis_addr;
322 redundant_fis_addr=swap_fis_addr;
323 }
324 else //success
325 {
326 void* tmp_fis_addr=(void *)((CYG_ADDRESS)fis_addr+CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
327
328 img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID;
329 img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID;
330
331 flash_program(tmp_fis_addr, img->u.valid_info.valid_flag, sizeof(img->u.valid_info.valid_flag), (void **)&err_addr);
332 }
333 if (do_autolock)
334 flash_lock((void *)fis_addr, fisdir_size, (void **)&err_addr);
335
336 #else // CYGOPT_REDBOOT_REDUNDANT_FIS
337 int blk_size = fisdir_size
249 int stat; 338 int stat;
250 void *err_addr;
251 339
252 fis_endian_fixup(fis_work_block); 340 fis_endian_fixup(fis_work_block);
253 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG 341 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
254 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); 342 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
255 conf_endian_fixup((char *)fis_work_block+fisdir_size); 343 conf_endian_fixup((char *)fis_work_block+fisdir_size);
256 blk_size += cfg_size; 344 blk_size += cfg_size;
257 #endif 345 #endif
258 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL 346 if (do_autolock)
259 // Ensure [quietly] that the directory is unlocked before trying to update
260 flash_unlock((void *)fis_addr, blk_size, (void **)&err_addr); 347 flash_unlock((void *)fis_addr, blk_size, (void **)&err_addr);
261 #endif 348
262 if ((stat = flash_erase(fis_addr, blk_size, (void **)&err_addr)) != 0) { 349 if ((stat = flash_erase(fis_addr, blk_size, (void **)&err_addr)) != 0) {
263 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); 350 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
264 } else { 351 } else {
265 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block, 352 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
266 blk_size, (void **)&err_addr)) != 0) { 353 blk_size, (void **)&err_addr)) != 0) {
267 diag_printf("Error writing FIS directory at %p: %s\n", 354 diag_printf("Error writing FIS directory at %p: %s\n",
268 err_addr, flash_errmsg(stat)); 355 err_addr, flash_errmsg(stat));
269 } 356 }
270 } 357 }
358 fis_endian_fixup(fis_work_block);
359 if (do_autolock)
360 flash_lock((void *)fis_addr, blk_size, (void **)&err_addr);
361
362 #endif // CYGOPT_REDBOOT_REDUNDANT_FIS
363
364 return 0;
365 }
366
367 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
368
369 int
370 fis_get_valid_buf(struct fis_image_desc* img0, struct fis_image_desc* img1, int* update_was_interrupted)
371 {
372 *update_was_interrupted=0;
373 if (strncmp(img1->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0) //buf0 must be valid
374 {
375 if (img0->u.valid_info.version_count>0)
376 {
377 *update_was_interrupted=1;
378 }
379 return 0;
380 }
381 else if (strncmp(img0->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0) //buf1 must be valid
382 {
383 if (img1->u.valid_info.version_count>0)
384 {
385 *update_was_interrupted=1;
386 }
387 return 1;
388 }
389 //magic is ok for both, now check the valid flag
390 if ((img1->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_VALID)
391 || (img1->u.valid_info.valid_flag[1]!=CYG_REDBOOT_RFIS_VALID)) //buf0 must be valid
392 {
393 *update_was_interrupted=1;
394 return 0;
395 }
396 else if ((img0->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_VALID)
397 || (img0->u.valid_info.valid_flag[1]!=CYG_REDBOOT_RFIS_VALID)) //buf1 must be valid
398 {
399 *update_was_interrupted=1;
400 return 1;
401 }
402
403 //now check the version
404 if (img1->u.valid_info.version_count == (img0->u.valid_info.version_count+1)) //buf1 must be valid
405 return 1;
406
407 return 0;
408 }
409
410 void
411 fis_erase_redundant_directory(void)
412 {
413 int stat;
414 void *err_addr;
415
416 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
417 // Ensure [quietly] that the directory is unlocked before trying
418 // to update
419 flash_unlock((void *)redundant_fis_addr, fisdir_size,
420 (void **)&err_addr);
421 #endif
422 if ((stat = flash_erase(redundant_fis_addr, fisdir_size,
423 (void **)&err_addr)) != 0) {
424 diag_printf("Error erasing FIS directory at %p: %s\n",
425 err_addr, flash_errmsg(stat));
426 }
271 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL 427 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
272 // Ensure [quietly] that the directory is locked after the update 428 // Ensure [quietly] that the directory is locked after the update
273 flash_lock((void *)fis_addr, blk_size, (void **)&err_addr); 429 flash_lock((void *)redundant_fis_addr, fisdir_size, (void **)&err_addr);
274 #endif 430 #endif
275 fis_endian_fixup(fis_work_block); 431 }
276 } 432 #endif
277 433
278 static void 434 static void
279 fis_init(int argc, char *argv[]) 435 fis_init(int argc, char *argv[])
280 { 436 {
281 int stat; 437 int stat;
301 457
302 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE 458 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
303 redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? 459 redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ?
304 flash_block_size : MIN_REDBOOT_IMAGE_SIZE; 460 flash_block_size : MIN_REDBOOT_IMAGE_SIZE;
305 461
306 // Create a pseudo image for RedBoot
307 img = (struct fis_image_desc *)fis_work_block; 462 img = (struct fis_image_desc *)fis_work_block;
308 memset(img, 0xFF, fisdir_size); // Start with erased data 463 memset(img, 0xFF, fisdir_size); // Start with erased data
464
465 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
466 //create the valid flag entry
467 memset(img, 0, sizeof(struct fis_image_desc));
468 strcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC);
469 img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID;
470 img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID;
471 img->u.valid_info.version_count=0;
472 img++;
473 #endif
474
475 // Create a pseudo image for RedBoot
309 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE 476 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
310 memset(img, 0, sizeof(*img)); 477 memset(img, 0, sizeof(*img));
311 strcpy(img->name, "(reserved)"); 478 strcpy(img->u.name, "(reserved)");
312 img->flash_base = (CYG_ADDRESS)flash_start; 479 img->flash_base = (CYG_ADDRESS)flash_start;
313 img->mem_base = (CYG_ADDRESS)flash_start; 480 img->mem_base = (CYG_ADDRESS)flash_start;
314 img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE; 481 img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
315 img++; 482 img++;
316 #endif 483 #endif
317 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; 484 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
318 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT 485 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
319 memset(img, 0, sizeof(*img)); 486 memset(img, 0, sizeof(*img));
320 strcpy(img->name, "RedBoot"); 487 strcpy(img->u.name, "RedBoot");
321 img->flash_base = redboot_flash_start; 488 img->flash_base = redboot_flash_start;
322 img->mem_base = redboot_flash_start; 489 img->mem_base = redboot_flash_start;
323 img->size = redboot_image_size; 490 img->size = redboot_image_size;
324 img++; 491 img++;
325 redboot_flash_start += redboot_image_size; 492 redboot_flash_start += redboot_image_size;
328 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET 495 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
329 // Take care to place the POST entry at the right offset: 496 // Take care to place the POST entry at the right offset:
330 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET; 497 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
331 #endif 498 #endif
332 memset(img, 0, sizeof(*img)); 499 memset(img, 0, sizeof(*img));
333 strcpy(img->name, "RedBoot[post]"); 500 strcpy(img->u.name, "RedBoot[post]");
334 img->flash_base = redboot_flash_start; 501 img->flash_base = redboot_flash_start;
335 img->mem_base = redboot_flash_start; 502 img->mem_base = redboot_flash_start;
336 img->size = redboot_image_size; 503 img->size = redboot_image_size;
337 img++; 504 img++;
338 redboot_flash_start += redboot_image_size; 505 redboot_flash_start += redboot_image_size;
339 #endif 506 #endif
340 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP 507 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
341 // And a backup image 508 // And a backup image
342 memset(img, 0, sizeof(*img)); 509 memset(img, 0, sizeof(*img));
343 strcpy(img->name, "RedBoot[backup]"); 510 strcpy(img->u.name, "RedBoot[backup]");
344 img->flash_base = redboot_flash_start; 511 img->flash_base = redboot_flash_start;
345 img->mem_base = redboot_flash_start; 512 img->mem_base = redboot_flash_start;
346 img->size = redboot_image_size; 513 img->size = redboot_image_size;
347 img++; 514 img++;
348 redboot_flash_start += redboot_image_size; 515 redboot_flash_start += redboot_image_size;
349 #endif 516 #endif
350 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) 517 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
351 // And a descriptor for the configuration data 518 // And a descriptor for the configuration data
352 memset(img, 0, sizeof(*img)); 519 memset(img, 0, sizeof(*img));
353 strcpy(img->name, "RedBoot config"); 520 strcpy(img->u.name, "RedBoot config");
354 img->flash_base = (CYG_ADDRESS)cfg_base; 521 img->flash_base = (CYG_ADDRESS)cfg_base;
355 img->mem_base = (CYG_ADDRESS)cfg_base; 522 img->mem_base = (CYG_ADDRESS)cfg_base;
356 img->size = cfg_size; 523 img->size = cfg_size;
357 img++; 524 img++;
358 #endif 525 #endif
359 // And a descriptor for the descriptor table itself 526 // And a descriptor for the descriptor table itself
360 memset(img, 0, sizeof(*img)); 527 memset(img, 0, sizeof(*img));
361 strcpy(img->name, "FIS directory"); 528 strcpy(img->u.name, "FIS directory");
362 img->flash_base = (CYG_ADDRESS)fis_addr; 529 img->flash_base = (CYG_ADDRESS)fis_addr;
363 img->mem_base = (CYG_ADDRESS)fis_addr; 530 img->mem_base = (CYG_ADDRESS)fis_addr;
364 img->size = fisdir_size; 531 img->size = fisdir_size;
365 img++; 532 img++;
533
534 //create the entry for the redundant fis table
535 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
536 memset(img, 0, sizeof(*img));
537 strcpy(img->u.name, "Redundant FIS");
538 img->flash_base = (CYG_ADDRESS)redundant_fis_addr;
539 img->mem_base = (CYG_ADDRESS)redundant_fis_addr;
540 img->size = fisdir_size;
541 img++;
542 #endif
366 543
367 #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID 544 #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID
368 // FIS gets the size of a full block - note, this should be changed 545 // FIS gets the size of a full block - note, this should be changed
369 // if support is added for multi-block FIS structures. 546 // if support is added for multi-block FIS structures.
370 img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size); 547 img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size);
474 // don't appear to be free since they are not erased - thus the warning 651 // don't appear to be free since they are not erased - thus the warning
475 } else { 652 } else {
476 diag_printf(" Warning: device contents not erased, some blocks may not be usable\n"); 653 diag_printf(" Warning: device contents not erased, some blocks may not be usable\n");
477 #endif 654 #endif
478 } 655 }
479 fis_update_directory(); 656 fis_start_update_directory(0);
657 fis_update_directory(0, 0);
658 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
659 fis_erase_redundant_directory();
660 #endif
480 } 661 }
481 662
482 static void 663 static void
483 fis_list(int argc, char *argv[]) 664 fis_list(int argc, char *argv[])
484 { 665 {
523 do { 704 do {
524 image_found = false; 705 image_found = false;
525 lowest_addr = 0xFFFFFFFF; 706 lowest_addr = 0xFFFFFFFF;
526 img = (struct fis_image_desc *) fis_work_block; 707 img = (struct fis_image_desc *) fis_work_block;
527 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 708 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
528 if (img->name[0] != (unsigned char)0xFF) { 709 if (img->u.name[0] != (unsigned char)0xFF) {
529 if ((img->flash_base > last_addr) && (img->flash_base < lowest_addr)) { 710 if ((img->flash_base > last_addr) && (img->flash_base < lowest_addr)) {
530 lowest_addr = img->flash_base; 711 lowest_addr = img->flash_base;
531 image_found = true; 712 image_found = true;
532 image_indx = i; 713 image_indx = i;
533 } 714 }
534 } 715 }
535 } 716 }
536 if (image_found) { 717 if (image_found) {
537 img = (struct fis_image_desc *) fis_work_block; 718 img = (struct fis_image_desc *) fis_work_block;
538 img += image_indx; 719 img += image_indx;
539 diag_printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->name, 720 diag_printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->u.name,
540 (unsigned long)img->flash_base, 721 (unsigned long)img->flash_base,
541 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK 722 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
542 show_cksums ? img->file_cksum : img->mem_base, 723 show_cksums ? img->file_cksum : img->mem_base,
543 show_datalen ? img->data_length : img->size, 724 show_datalen ? img->data_length : img->size,
544 #else 725 #else
571 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; 752 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
572 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; 753 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
573 fis_read_directory(); 754 fis_read_directory();
574 img = (struct fis_image_desc *) fis_work_block; 755 img = (struct fis_image_desc *) fis_work_block;
575 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 756 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
576 if (img->name[0] != (unsigned char)0xFF) { 757 if (img->u.name[0] != (unsigned char)0xFF) {
577 // Figure out which chunk this is in and split it 758 // Figure out which chunk this is in and split it
578 for (idx = 0; idx < num_chunks; idx++) { 759 for (idx = 0; idx < num_chunks; idx++) {
579 if ((img->flash_base >= chunks[idx].start) && 760 if ((img->flash_base >= chunks[idx].start) &&
580 (img->flash_base <= chunks[idx].end)) { 761 (img->flash_base <= chunks[idx].end)) {
581 if (img->flash_base == chunks[idx].start) { 762 if (img->flash_base == chunks[idx].start) {
839 if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) { 1020 if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) {
840 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); 1021 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
841 diag_printf(" must be 0x%x aligned\n", flash_block_size); 1022 diag_printf(" must be 0x%x aligned\n", flash_block_size);
842 return; 1023 return;
843 } 1024 }
844 if (strlen(name) >= sizeof(img->name)) { 1025 if (strlen(name) >= sizeof(img->u.name)) {
845 diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name)); 1026 diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->u.name));
846 return; 1027 return;
847 } 1028 }
848 if (!no_copy) { 1029 if (!no_copy) {
849 if ((mem_addr < (CYG_ADDRESS)ram_start) || 1030 if ((mem_addr < (CYG_ADDRESS)ram_start) ||
850 ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) { 1031 ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) {
905 } 1086 }
906 #endif 1087 #endif
907 // If not image by that name, try and find an empty slot 1088 // If not image by that name, try and find an empty slot
908 img = (struct fis_image_desc *)fis_work_block; 1089 img = (struct fis_image_desc *)fis_work_block;
909 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 1090 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
910 if (img->name[0] == (unsigned char)0xFF) { 1091 if (img->u.name[0] == (unsigned char)0xFF) {
911 break; 1092 break;
912 } 1093 }
913 } 1094 }
914 if (i >= fisdir_size/sizeof(*img)) { 1095 if (i >= fisdir_size/sizeof(*img)) {
915 diag_printf("Can't find an empty slot in FIS directory!\n"); 1096 diag_printf("Can't find an empty slot in FIS directory!\n");
938 } 1119 }
939 } 1120 }
940 if (prog_ok) { 1121 if (prog_ok) {
941 // Update directory 1122 // Update directory
942 memset(img, 0, sizeof(*img)); 1123 memset(img, 0, sizeof(*img));
943 strcpy(img->name, name); 1124 strcpy(img->u.name, name);
944 img->flash_base = flash_addr; 1125 img->flash_base = flash_addr;
945 img->mem_base = exec_addr_set ? exec_addr : (mem_addr_set ? mem_addr : flash_addr); 1126 img->mem_base = exec_addr_set ? exec_addr : (mem_addr_set ? mem_addr : flash_addr);
946 img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set 1127 img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set
947 img->size = length; 1128 img->size = length;
948 img->data_length = img_size; 1129 img->data_length = img_size;
952 } else { 1133 } else {
953 // No way to compute this, sorry 1134 // No way to compute this, sorry
954 img->file_cksum = 0; 1135 img->file_cksum = 0;
955 } 1136 }
956 #endif 1137 #endif
957 fis_update_directory(); 1138 fis_start_update_directory(0);
1139 fis_update_directory(0, 0);
958 } 1140 }
959 } 1141 }
960 1142
961 extern void arm_fis_delete(char *); 1143 extern void arm_fis_delete(char *);
962 static void 1144 static void
999 #endif 1181 #endif
1000 1182
1001 img = fis_lookup(name, &i); 1183 img = fis_lookup(name, &i);
1002 if (img) { 1184 if (img) {
1003 if (i < num_reserved) { 1185 if (i < num_reserved) {
1004 diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->name); 1186 diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->u.name);
1005 return; 1187 return;
1006 } 1188 }
1007 if (!verify_action("Delete image '%s'", name)) { 1189 if (!verify_action("Delete image '%s'", name)) {
1008 return; 1190 return;
1009 } 1191 }
1013 } 1195 }
1014 // Erase Data blocks (free space) 1196 // Erase Data blocks (free space)
1015 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) { 1197 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
1016 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat)); 1198 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
1017 } else { 1199 } else {
1018 img->name[0] = (unsigned char)0xFF; 1200 img->u.name[0] = (unsigned char)0xFF;
1019 fis_update_directory(); 1201 fis_start_update_directory(0);
1202 fis_update_directory(0, 0);
1020 } 1203 }
1021 } 1204 }
1022 1205
1023 static void 1206 static void
1024 fis_load(int argc, char *argv[]) 1207 fis_load(int argc, char *argv[])
1362 if (!__flash_init) return; 1545 if (!__flash_init) return;
1363 diag_printf("FLASH: %p - 0x%x, %d blocks of %p bytes each.\n", 1546 diag_printf("FLASH: %p - 0x%x, %d blocks of %p bytes each.\n",
1364 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size); 1547 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
1365 } 1548 }
1366 1549
1367 bool 1550 /* Returns -1 on failure, 0 on success, 1 if it was successfull
1551 but a failed fis update was detected */
1552 int
1368 do_flash_init(void) 1553 do_flash_init(void)
1369 { 1554 {
1370 int stat; 1555 int stat;
1556
1557 void *err_addr;
1558 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
1559 struct fis_image_desc img0;
1560 struct fis_image_desc img1;
1561 int fis_update_was_interrupted=0;
1562
1563 //check the size of fis_valid_info
1564 CYG_ASSERT((sizeof(struct fis_valid_info)<=sizeof(img0.u.name)), "fis_valid_info size mismatch");
1565 //try to check the alignment of version_count
1566 CYG_ASSERT((((unsigned long)&img0.u.valid_info.version_count - (unsigned long)&img0) % sizeof(unsigned long) == 0), "alignment problem");
1567 #endif
1568
1569
1371 1570
1372 if (!__flash_init) { 1571 if (!__flash_init) {
1373 __flash_init = 1; 1572 __flash_init = 1;
1374 if ((stat = flash_init(diag_printf)) != 0) { 1573 if ((stat = flash_init(diag_printf)) != 0) {
1375 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); 1574 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
1376 return false; 1575 return -1;
1377 } 1576 }
1378 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end); 1577 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
1379 // Keep 'end' address as last valid location, to avoid wrap around problems 1578 // Keep 'end' address as last valid location, to avoid wrap around problems
1380 flash_end = (void *)((CYG_ADDRESS)flash_end - 1); 1579 flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
1381 flash_get_block_info(&flash_block_size, &flash_num_blocks); 1580 flash_get_block_info(&flash_block_size, &flash_num_blocks);
1384 fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size; 1583 fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
1385 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER) 1584 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
1386 fis_work_block = fis_zlib_common_buffer; 1585 fis_work_block = fis_zlib_common_buffer;
1387 if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) { 1586 if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
1388 diag_printf("FLASH: common buffer too small\n"); 1587 diag_printf("FLASH: common buffer too small\n");
1389 return false; 1588 return -1;
1390 } 1589 }
1391 # else 1590 # else
1392 workspace_end = (unsigned char *)(workspace_end-fisdir_size); 1591 workspace_end = (unsigned char *)(workspace_end_init-fisdir_size);
1393 fis_work_block = workspace_end; 1592 fis_work_block = workspace_end;
1394 # endif 1593 # endif
1395 if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) { 1594 if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
1396 fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 + 1595 fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
1397 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); 1596 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1400 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); 1599 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1401 } 1600 }
1402 1601
1403 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { 1602 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1404 diag_printf("FIS directory doesn't fit\n"); 1603 diag_printf("FIS directory doesn't fit\n");
1405 return false; 1604 return -1;
1406 } 1605 }
1606 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
1607
1608 if (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK < 0) {
1609 redundant_fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
1610 (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK*flash_block_size));
1611 } else {
1612 redundant_fis_addr = (void *)((CYG_ADDRESS)flash_start +
1613 (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK*flash_block_size));
1614 }
1615
1616 if (((CYG_ADDRESS)redundant_fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1617 diag_printf("Redundant FIS directory doesn't fit\n");
1618 return -1;
1619 }
1620 FLASH_READ(fis_addr, &img0, sizeof(img0), (void **)&err_addr);
1621 FLASH_READ(redundant_fis_addr, &img1, sizeof(img1), (void **)&err_addr);
1622
1623 if (strncmp(img0.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)
1624 {
1625 memset(&img0, 0, sizeof(img0));
1626 }
1627
1628 if (strncmp(img1.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)
1629 {
1630 memset(&img1, 0, sizeof(img0));
1631 }
1632
1633 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
1634 img0.u.valid_info.version_count = CYG_SWAP32(img0.u.valid_info.version_count);
1635 img1.u.valid_info.version_count = CYG_SWAP32(img1.u.valid_info.version_count);
1636 #endif
1637
1638 if (fis_get_valid_buf(&img0, &img1, &fis_update_was_interrupted)==1)
1639 {
1640 // Valid, so swap primary and secondary
1641 void * tmp;
1642 tmp = fis_addr;
1643 fis_addr = redundant_fis_addr;
1644 redundant_fis_addr = tmp;
1645 }
1646 #endif
1407 fis_read_directory(); 1647 fis_read_directory();
1408 #endif 1648 #endif
1409 } 1649 }
1410 return true; 1650 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
1651 if (fis_update_was_interrupted)
1652 return 1;
1653 else
1654 return 0;
1655 #else
1656 return 0;
1657 #endif
1411 } 1658 }
1412 1659
1413 // Wrapper to avoid compiler warnings 1660 // Wrapper to avoid compiler warnings
1414 static void 1661 static void
1415 _do_flash_init(void) 1662 _do_flash_init(void)
1429 1676
1430 if (argc < 2) { 1677 if (argc < 2) {
1431 fis_usage("too few arguments"); 1678 fis_usage("too few arguments");
1432 return; 1679 return;
1433 } 1680 }
1434 if (!do_flash_init()) { 1681 if (do_flash_init()<0) {
1435 diag_printf("Sorry, no FLASH memory is available\n"); 1682 diag_printf("Sorry, no FLASH memory is available\n");
1436 return; 1683 return;
1437 } 1684 }
1438 if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, 1685 if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__,
1439 argv[1])) != (struct cmd *)0) { 1686 argv[1])) != (struct cmd *)0) {