diff -rbup current.orig/cdl/redboot.cdl current/cdl/redboot.cdl --- current.orig/cdl/redboot.cdl Sun Sep 19 19:49:59 2004 +++ current/cdl/redboot.cdl Tue Oct 19 17:16:18 2004 @@ -638,6 +638,19 @@ cdl_package CYGPKG_REDBOOT { Negative block numbers count backwards from the last block. eg 2 means block 2, -2 means the last but one block." } + + cdl_option CYGNUM_REDBOOT_FIS_ADDITIONAL_DIRECTORY_BLOCK { + display "Flash block containing the backup Directory" + flavor data + default_value (-1) + description " + Which block of flash should hold the directory + information. Positive numbers are absolute block numbers. + Negative block numbers count backwards from the last block. + eg 2 means block 2, -2 means the last but one block." + } + + cdl_option CYGOPT_REDBOOT_FIS_RESERVED_BASE { display "Pseudo-file to describe reserved area" Only in current/cdl: redboot.cdl~ diff -rbup current.orig/include/fis.h current/include/fis.h --- current.orig/include/fis.h Sat Aug 24 13:20:55 2002 +++ current/include/fis.h Tue Oct 19 17:17:02 2004 @@ -73,7 +73,22 @@ struct fis_image_desc { unsigned long file_cksum; // Checksum over image data }; +#define EFIS_MAGIC "$_FisValid_" //exactly 12 bytes + +#define EFIS_VALID (0xa5a5a5a5) +#define EFIS_IN_PROGRESS (0xfdfdfdfd) +#define EFIS_EMPTY (0xffffffff) + +struct fis_valid_info +{ + unsigned char magic_name[12]; + unsigned long valid_flag; + CYG_ADDRESS unused_flash_base; + unsigned long version_count; +}; + struct fis_image_desc *fis_lookup(char *name, int *num); #endif // CYGOPT_REDBOOT_FIS #endif // _FIS_H_ + Only in current/include: fis.h~ diff -rbup current.orig/src/flash.c current/src/flash.c --- current.orig/src/flash.c Wed Sep 1 23:21:30 2004 +++ current/src/flash.c Tue Oct 19 17:15:26 2004 @@ -169,6 +169,8 @@ int flash_block_size, flash_num_blocks; #ifdef CYGOPT_REDBOOT_FIS void *fis_work_block; void *fis_addr; +void *fis_addr0; +void *fis_addr1; int fisdir_size; // Size of FIS directory. #endif #ifdef CYGSEM_REDBOOT_FLASH_CONFIG @@ -278,6 +280,7 @@ fis_init(int argc, char *argv[]) { int stat; struct fis_image_desc *img; + struct fis_valid_info* fvi=NULL; void *err_addr; bool full_init = false; struct option_info opts[1]; @@ -301,9 +304,19 @@ fis_init(int argc, char *argv[]) redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? flash_block_size : MIN_REDBOOT_IMAGE_SIZE; - // Create a pseudo image for RedBoot img = (struct fis_image_desc *)fis_work_block; memset(img, 0xFF, fisdir_size); // Start with erased data + + //create the valid flag entry + fvi=(struct fis_valid_info*)img; + memset(img, 0, sizeof(struct fis_image_desc)); + memcpy(fvi->magic_name, EFIS_MAGIC, 12); + + fvi->valid_flag=EFIS_VALID; + fvi->version_count=0; + img++; + + // Create a pseudo image for RedBoot #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE memset(img, 0, sizeof(*img)); strcpy(img->name, "(reserved)"); @@ -357,8 +370,14 @@ fis_init(int argc, char *argv[]) // And a descriptor for the descriptor table itself memset(img, 0, sizeof(*img)); strcpy(img->name, "FIS directory"); - img->flash_base = (CYG_ADDRESS)fis_addr; - img->mem_base = (CYG_ADDRESS)fis_addr; + img->flash_base = (CYG_ADDRESS)fis_addr0; + img->mem_base = (CYG_ADDRESS)fis_addr0; + img->size = fisdir_size; + img++; + memset(img, 0, sizeof(*img)); + strcpy(img->name, "FIS directory~"); + img->flash_base = (CYG_ADDRESS)fis_addr1; + img->mem_base = (CYG_ADDRESS)fis_addr1; img->size = fisdir_size; img++; @@ -1351,10 +1370,35 @@ _flash_info(void) flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size); } +static int +get_valid_buf(struct fis_valid_info* fvi0, struct fis_valid_info* fvi1) +{ + if (memcmp(fvi0->magic_name, EFIS_MAGIC, 12)!=0) //buf1 must be valid + return 1; + else if (memcmp(fvi1->magic_name, EFIS_MAGIC, 12)!=0) //buf0 must be valid + return 0; + + //magic is ok for both, now check the valid flag + if (fvi0->valid_flag!=EFIS_VALID) //buf1 must be valid + return 1; + else if (fvi1->valid_flag!=EFIS_VALID) //buf0 must be valid + return 0; + + //now check the version + if ((fvi1->version_count > fvi0->version_count) //buf1 must be valid + && (fvi1->version_count != 0xffffffff)) + return 1; + + return 0; +} + bool do_flash_init(void) { int stat; + void *err_addr=0; + struct fis_valid_info fvi0; + struct fis_valid_info fvi1; if (!__flash_init) { __flash_init = 1; @@ -1379,17 +1423,55 @@ do_flash_init(void) workspace_end = (unsigned char *)(workspace_end-fisdir_size); fis_work_block = workspace_end; # endif + + fis_addr0 = NULL; + fis_addr1 = NULL; + if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) { - fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 + + fis_addr0 = (void *)((CYG_ADDRESS)flash_end + 1 + (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); } else { - fis_addr = (void *)((CYG_ADDRESS)flash_start + + fis_addr0 = (void *)((CYG_ADDRESS)flash_start + (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size)); } - if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { + + if (CYGNUM_REDBOOT_FIS_ADDITIONAL_DIRECTORY_BLOCK < 0) { + fis_addr1 = (void *)((CYG_ADDRESS)flash_end + 1 + + (CYGNUM_REDBOOT_FIS_ADDITIONAL_DIRECTORY_BLOCK*flash_block_size)); + } else { + fis_addr1 = (void *)((CYG_ADDRESS)flash_start + + (CYGNUM_REDBOOT_FIS_ADDITIONAL_DIRECTORY_BLOCK*flash_block_size)); + } + + if ((((CYG_ADDRESS)fis_addr0 + fisdir_size - 1) > (CYG_ADDRESS)flash_end) + || (((CYG_ADDRESS)fis_addr1 + fisdir_size - 1) > (CYG_ADDRESS)flash_end) + || (fis_addr0==fis_addr1)) { diag_printf("FIS directory doesn't fit\n"); return false; } + + FLASH_READ(fis_addr0, &fvi0, sizeof(struct fis_valid_info), (void **)&err_addr); + FLASH_READ(fis_addr1, &fvi1, sizeof(struct fis_valid_info), (void **)&err_addr); + +#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER + fvi0.magic=CYG_SWAP32(fvi0.magic); + fvi0.valid_flag=CYG_SWAP32(fvi0.valid_flag); + fvi0.version_count=CYG_SWAP32(fvi0.version_count); + fvi1.magic=CYG_SWAP32(fvi1.magic); + fvi1.valid_flag=CYG_SWAP32(fvi1.valid_flag); + fvi1.version_count=CYG_SWAP32(fvi1.version_count); +#endif + + if ((memcmp(fvi0.magic_name, EFIS_MAGIC, 12)==0) || (memcmp(fvi1.magic_name, EFIS_MAGIC, 12)==0)) { + if (get_valid_buf(&fvi0, &fvi1)==0) + fis_addr=fis_addr0; + else + fis_addr=fis_addr1; + } else { + fis_addr1=NULL; + fis_addr=fis_addr0; + } + fis_read_directory(); #endif } Only in current/src: flash.c~