/* 写入实际地址add重复写值x,times次后赋值flash_error, 或者在规定重读次数前写入正确的值。*/ void repeat_write(unsigned int add,unsigned char x,unsigned char times) { unsigned char i=0; do { if(i>times) break; flashwrite(add,x); i++; } while(flash_error&write_error); }
int main (void) { register unsigned i; P1DIR |= BIT4; P1OUT |= BIT4; for (i = 0; i < 50; ++i); P1OUT &= ~BIT4; /* time between two GPIO spikes is the time for flashwrite */ flashwrite(); P1OUT |= BIT4; for (i = 0; i < 50; ++i); P1OUT &= ~BIT4; }
void checkAutoFlashing(unsigned long startAddr, int len) { int i=0; unsigned long head_offset=0, srcAddr, burnLen; unsigned short sum=0; unsigned char sum1=0; int skip_header=0; int reboot=0; IMG_HEADER_T Header ; //avoid unalign problem int skip_check_signature=0; unsigned long burn_offset =0; //mark_dual #ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE check_dualbank_setting(0); //must do check image to get current boot_bank....... #endif while( (head_offset + sizeof(IMG_HEADER_T)) < len){ sum=0; sum1=0; memcpy(&Header, ((char *)startAddr + head_offset), sizeof(IMG_HEADER_T)); if (!skip_check_signature) { for(i=0 ;i < MAX_SIG_TBL ; i++) { if(!memcmp(Header.signature, (char *)sign_tbl[i].signature, sign_tbl[i].sig_len)) break; } if(i == MAX_SIG_TBL){ head_offset += Header.len + sizeof(IMG_HEADER_T); continue ; } #ifdef CONFIG_BOOT_CODE_SIZE_CHECK if(!memcmp(Header.signature, BOOT_SIGNATURE, SIG_LEN)){ // - checksum len if((Header.len-2) > CONFIG_BOOT_CODE_SIZE){ prom_printf("bootcode is too big\n"); return; } } #endif skip_header = sign_tbl[i].skip ; if(skip_header){ srcAddr = startAddr + head_offset + sizeof(IMG_HEADER_T); burnLen = Header.len; // +checksum }else{ srcAddr = startAddr + head_offset ; burnLen = Header.len + sizeof(IMG_HEADER_T) ; } reboot |= sign_tbl[i].reboot; prom_printf("\n%s upgrade.\n", sign_tbl[i].comment); } else { if(!memcmp(Header.signature, BOOT_SIGNATURE, SIG_LEN)){ #ifdef CONFIG_BOOT_CODE_SIZE_CHECK // - checksum len if((Header.len-2) > CONFIG_BOOT_CODE_SIZE){ prom_printf("bootcode is too big\n"); return; } #endif skip_header = 1; }else { unsigned char *pRoot =((unsigned char *)startAddr) + head_offset + sizeof(IMG_HEADER_T); if (!memcmp(pRoot, SQSH_SIGNATURE, SIG_LEN)) skip_header = 1; else skip_header = 0; } if(skip_header){ srcAddr = startAddr + head_offset + sizeof(IMG_HEADER_T); burnLen = Header.len ; // +checksum }else{ srcAddr = startAddr + head_offset ; burnLen = Header.len + sizeof(IMG_HEADER_T) ; } } if(skip_check_signature || memcmp(Header.signature, WEB_SIGNATURE, 3)){ //calculate checksum if(!memcmp(Header.signature, ALL1_SIGNATURE, SIG_LEN) || !memcmp(Header.signature, ALL2_SIGNATURE, SIG_LEN)) { for (i=0; i< Header.len+sizeof(IMG_HEADER_T); i+=2) { sum += *((unsigned short *)(startAddr+ head_offset + i)); } } else { unsigned char x=0,y=0; unsigned short temp=0; for (i=0; i< Header.len; i+=2) { #if defined(RTL8196B) || defined(RTL8198) #if 1 //sum +=*((unsigned short *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); memcpy(&temp, (startAddr+ head_offset + sizeof(IMG_HEADER_T) + i), 2); // for alignment issue sum+=temp; #else x=*((unsigned char *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); y=*((unsigned char *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i+1)); sum+=(y|x<<8)&0xFFFF; #endif #else sum += *((unsigned short *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); #endif //#if defined(RTL8196B) || defined(RTL8198) } } if ( sum ) { prom_printf("%s imgage checksum error at %X!\n" , Header.signature, startAddr+head_offset); return ; } if(!memcmp(Header.signature, ALL1_SIGNATURE, SIG_LEN)){ head_offset += sizeof(IMG_HEADER_T); continue; } if(!memcmp(Header.signature, ALL2_SIGNATURE, SIG_LEN)){ skip_check_signature = 1; head_offset += sizeof(IMG_HEADER_T); continue; } }else { //web page use different checksum algorimth for (i=0; i< Header.len; i++) sum1 += *((unsigned char *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); if ( sum1 ) { prom_printf("%s imgage checksum error at %X!\n" , Header.signature, startAddr+head_offset); return ; } } prom_printf("checksum Ok !\n"); prom_printf("burn Addr =0x%x! srcAddr=0x%x len =0x%x \n", Header.burnAddr, srcAddr, burnLen); #ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE if(!memcmp(Header.signature, FW_SIGNATURE, SIG_LEN) || !memcmp(Header.signature, FW_SIGNATURE_WITH_ROOT, SIG_LEN)) { IMG_HEADER_T header_t, *header_p; header_p = &header_t; burn_offset = sel_burnbank_offset(); prom_printf("burn_offset = %x !\n",burn_offset); memcpy(header_p, ((char *)srcAddr), sizeof(IMG_HEADER_T)); header_p->burnAddr = get_next_bank_mark(); //prom_printf("2 header_p->burn = 0x%x \n", header_p->burnAddr); memcpy(((char *)srcAddr), header_p, sizeof(IMG_HEADER_T)); } else if(!memcmp(Header.signature, ROOT_SIGNATURE, SIG_LEN)) { burn_offset = sel_burnbank_offset(); prom_printf("burn_offset = %x !\n",burn_offset); } #endif int trueorfaulse = 0; #ifdef CONFIG_SPI_FLASH #ifdef SUPPORT_SPI_MIO_8198_8196C if(Header.burnAddr+burn_offset+burnLen > spi_flash_info[0].chip_size) { if(spi_flw_image_mio_8198(0,Header.burnAddr+burn_offset, srcAddr, spi_flash_info[0].chip_size-(Header.burnAddr+burn_offset))&& spi_flw_image_mio_8198(1,0, srcAddr+spi_flash_info[0].chip_size-(Header.burnAddr+burn_offset), Header.burnAddr+burn_offset+burnLen-spi_flash_info[0].chip_size)) trueorfaulse = 1; } else if(spi_flw_image_mio_8198(0,Header.burnAddr+burn_offset, srcAddr, burnLen)) trueorfaulse = 1; #else if(spi_flw_image(0,Header.burnAddr+burn_offset, srcAddr, burnLen)) #endif #else if (flashwrite(Header.burnAddr+burn_offset, srcAddr, burnLen)) #endif if(trueorfaulse) prom_printf("\nFlash Write Successed!\n%s", "<RealTek>"); else{ prom_printf("\nFlash Write Failed!\n%s", "<RealTek>"); return ; } head_offset += Header.len + sizeof(IMG_HEADER_T); } //while if(reboot){ autoreboot(); } }