http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / bcmdrivers / opensource / char / board / bcm963xx / impl1 / bcm63xx_flash.c
index 5b90057..b03133b 100755 (executable)
@@ -50,6 +50,29 @@ extern PFILE_TAG kerSysImageTagGet(void);
 static FLASH_ADDR_INFO fInfo;
 static int flashInitialized = 0;
 
+/*Michael: for fix crash when push reset button */
+void *retriedKmallocRESET(size_t size)
+{
+       void *pBuf;
+    int tryCount = 0;
+
+    // try 1000 times before quit
+/*Michael: for fix crash when push reset button */
+/* if we kill pppd and do reset button push, it goes fine. This method provided by viclin */
+//    while (((pBuf = kmalloc(size, GFP_KERNEL)) == NULL) && (tryCount++ < 1000)){
+    while (((pBuf = kmalloc(size, GFP_ATOMIC)) == NULL) && (tryCount++ < 1000)){
+               current->state   = TASK_INTERRUPTIBLE;
+               schedule_timeout(HZ/10);
+       }
+    if (tryCount >= 1000)
+        pBuf = NULL;
+    else
+       memset(pBuf, 0, size);
+
+    return pBuf;
+}
+
+
 void *retriedKmalloc(size_t size)
 {
        void *pBuf;
@@ -113,6 +136,157 @@ unsigned long get_scratch_pad_start_addr(void)
         (flash_get_memptr(fInfo.flash_scratch_pad_start_blk) + fInfo.flash_scratch_pad_blk_offset));
 }
 
+
+#if defined(CONFIG_BCM96348)  
+/*  *********************************************************************
+    *  kerSysImageTagGet()
+    *   Get the image tag
+    *  Input parameters:
+    *      none
+    *  Return value:
+    *      point to tag -- Found
+    *      NULL -- failed
+    ********************************************************************* */
+PFILE_TAG kerSysImageTagGet(void)
+{
+    int i,startblock;
+    int totalBlks = flash_get_numsectors();
+    int totalSize = flash_get_total_size();
+    UINT32 crc;
+    unsigned char *sectAddr;
+    PFILE_TAG pTag;
+    unsigned char   nbootflag,*bootflag;
+
+    bootflag=flash_get_memptr((byte) 0);
+    
+    if (totalSize == 0x800000) {nbootflag=*bootflag;}
+    else nbootflag=1;
+    
+    if (nbootflag == 2) nbootflag = 0; /*binfs is valid to boot from bfc00000*/
+    startblock = (nbootflag?1:(totalBlks>>1)+1);
+#if defined(DEBUG_FLASH)
+    printk("totalblks in tagGet=%d\n", totalBlks);
+#endif
+
+
+    // start blk, assume 1st one is always CFE
+    for (i = startblock; i < startblock + (totalBlks>>1); i++)
+    {
+        sectAddr =  flash_get_memptr((byte) i);
+        crc = CRC32_INIT_VALUE;
+        crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
+        pTag = (PFILE_TAG) sectAddr;
+
+#if defined(DEBUG_FLASH)
+        printk("Check Tag crc on blk [%d]\n", i);
+#endif
+
+        if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+            return pTag;
+    }
+
+    return (PFILE_TAG) NULL;
+}
+
+PFILE_TAG kerSysImageTagGet2(void)
+{
+    int i,startblock;
+    int totalBlks = flash_get_numsectors();
+    int totalSize = flash_get_total_size();
+    UINT32 crc;
+    unsigned char *sectAddr;
+    PFILE_TAG pTag;
+    unsigned char   nbootflag,*bootflag;
+
+    bootflag=flash_get_memptr((byte) 0);
+    
+    if (totalSize == 0x800000)  nbootflag=1; /*always get from bf800000 */
+    else return (PFILE_TAG) NULL;
+    
+    startblock = (nbootflag?1:(totalBlks>>1)+1);
+#if defined(DEBUG_FLASH)
+    printk("totalblks in tagGet=%d\n", totalBlks);
+#endif
+
+
+    // start blk, assume 1st one is always CFE
+    for (i = startblock; i < startblock + (totalBlks>>1); i++)
+    {
+        sectAddr =  flash_get_memptr((byte) i);
+        crc = CRC32_INIT_VALUE;
+        crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
+        pTag = (PFILE_TAG) sectAddr;
+
+        if (*((unsigned char*) pTag->kernelLen) == 0x30 ) {
+               
+#if defined(DEBUG_FLASH)
+        printk("Check Tag crc on blk [%d]\n", i);
+#endif
+
+            if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+                return pTag;
+        }
+    }
+
+    return  (PFILE_TAG) NULL;
+}
+
+
+#endif
+
+#if defined(CONFIG_BCM96338)
+PFILE_TAG kerSysImageTagGet(void)
+{
+    int i,startblock;
+    int totalBlks = flash_get_numsectors();
+    int totalSize = flash_get_total_size();
+    UINT32 crc;
+    unsigned char *sectAddr;
+    PFILE_TAG pTag;
+    unsigned char bootf1,bootf2,nbootflag=0;
+
+    
+if (totalSize == 0x400000) {
+    bootf1 = *(unsigned char*) (0xbfe00000 -1); /*see design note 4MB flash layout*/
+    bootf2 = *(unsigned char*) (0xbfff0000 -1);
+    if ((bootf1 >> 2) == 0 && bootf1 ) {
+        if ((bootf2 >> 2) == 0 && bootf2 ) { /* both are valid */
+          if ((bootf1+1) == bootf2 || ((bootf1+1) >>2 == bootf2) ) nbootflag=1; /*bank2*/
+          if ((bootf2+1) == bootf1 || ((bootf2+1) >>2 == bootf1) ) nbootflag=0; /*bank1*/ 
+        } else nbootflag = 0; /* bank2 invalid bank1 valid */
+    }
+    else  if ((bootf2 >> 2) == 0 && bootf2) nbootflag =1; /*bank 1 invalid,bank 2 valid*/
+    else  nbootflag=0; /* bank1 bank2 both invalid */
+    
+    printk("bootf1=%x bootf2=%x\n", bootf1,bootf2);
+}
+else nbootflag=0; 
+    
+    startblock = nbootflag?flash_get_blk(0xbfe00000):1;
+#if defined(DEBUG_FLASH)
+    printk("totalblks in tagGet=%d\n", totalBlks);
+#endif
+
+
+    // start blk, assume 1st one is always CFE
+    for (i = startblock; i < startblock + (totalBlks>>1); i++)
+    {
+        sectAddr =  flash_get_memptr((byte) i);
+        crc = CRC32_INIT_VALUE;
+        crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
+        pTag = (PFILE_TAG) sectAddr;
+
+#if defined(DEBUG_FLASH)
+        printk("Check Tag crc on blk [%d]\n", i);
+#endif
+
+        if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+            return pTag;
+    }
+
+    return (PFILE_TAG) NULL;   
+}  
+#endif
 // Initialize the flash and fill out the fInfo structure
 void kerSysFlashInit( void )
 {
@@ -140,7 +314,8 @@ void kerSysFlashInit( void )
 
     /* nvram is always at the end of flash */
     fInfo.flash_nvram_length = NVRAM_LENGTH;
-    fInfo.flash_nvram_start_blk = 0;  /* always the first block */
+  printk("FLASH_BASE %x,blk %d\n",FLASH_BASE,flash_get_blk(FLASH_BASE));
+    fInfo.flash_nvram_start_blk = flash_get_blk(FLASH_BASE);   /* denny 09/13/04' modified, set the nvram locate at boot loader sector */
     fInfo.flash_nvram_number_blk = 1; /*always fits in the first block */
     fInfo.flash_nvram_blk_offset = NVRAM_DATA_OFFSET;
  
@@ -172,7 +347,12 @@ void kerSysFlashInit( void )
 
     fInfo.flash_persistent_length *= ONEK;
     startAddr = totalSize - fInfo.flash_persistent_length;
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)      
+    fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+get_flash_base(0));
+#endif
+#if defined (CONFIG_BCM96358)
     fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+FLASH_BASE);
+#endif
     fInfo.flash_persistent_number_blk = totalBlks - fInfo.flash_persistent_start_blk;
     // save abs SP address (Scratch Pad). it is before PSI 
     spAddr = startAddr - SP_MAX_LEN ;
@@ -181,7 +361,7 @@ void kerSysFlashInit( void )
     for (i = fInfo.flash_persistent_start_blk; 
         i < (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk); i++)
     {
-        usedBlkSize += flash_get_sector_size((unsigned short) i);
+        usedBlkSize += flash_get_sector_size( i);
     }
     fInfo.flash_persistent_blk_offset =  usedBlkSize - fInfo.flash_persistent_length;
 
@@ -194,8 +374,15 @@ void kerSysFlashInit( void )
     kernelEndAddr = (unsigned long)simple_strtoul(pTag->kernelAddress,NULL,10)+ \
         (unsigned long) simple_strtoul(pTag->kernelLen, NULL, 10) + BOOT_OFFSET;
 
+
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
+    fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+get_flash_base(0));
+#endif
+
+#if defined (CONFIG_BCM96358)
     // make suer sp does not share kernel block
     fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+FLASH_BASE);
+#endif
     if (fInfo.flash_scratch_pad_start_blk != flash_get_blk(kernelEndAddr))
     {
         fInfo.flash_scratch_pad_length = SP_MAX_LEN;
@@ -217,7 +404,7 @@ void kerSysFlashInit( void )
             usedBlkSize = 0;
             for (i = fInfo.flash_scratch_pad_start_blk; 
                 i < (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk); i++)
-                usedBlkSize += flash_get_sector_size((unsigned short) i);
+                usedBlkSize += flash_get_sector_size(i);
                 fInfo.flash_scratch_pad_blk_offset =  usedBlkSize - fInfo.flash_scratch_pad_length;
         }
     }
@@ -227,7 +414,83 @@ void kerSysFlashInit( void )
         fInfo.flash_scratch_pad_length = 0;     // no sp
     }
 
+    /*==== add by Andrew (2004/09/14) ====*/
+#if defined(CFG_XFER_TO_FACDEFLT)
+    // save abs factdeflt address (Factory Default). it is before SP
+    unsigned long dfAddr;
+
+       if(fInfo.flash_scratch_pad_length>0) {
+        dfAddr = spAddr - NVRAM_PSI_DEFAULT*ONEK;
+        // make sure factdeflt does not share kernel block
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
+        fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+get_flash_base(0));
+#endif
+#if defined (CONFIG_BCM96358)
+               fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+FLASH_BASE);
+#endif
+        if (fInfo.flash_factdeflt_start_blk != flash_get_blk(kernelEndAddr)) {
+            fInfo.flash_factdeflt_length = NVRAM_PSI_DEFAULT*ONEK;
+            if (fInfo.flash_factdeflt_start_blk == fInfo.flash_scratch_pad_start_blk)  // share blk
+            {
+                fInfo.flash_factdeflt_number_blk = 1;
+                fInfo.flash_factdeflt_blk_offset = fInfo.flash_scratch_pad_blk_offset - fInfo.flash_factdeflt_length;
+            } else { // on different blk
+                fInfo.flash_factdeflt_number_blk = fInfo.flash_scratch_pad_start_blk - fInfo.flash_factdeflt_start_blk;
+                // find out the offset in the start_blk
+                usedBlkSize = 0;
+                for (i = fInfo.flash_factdeflt_start_blk; 
+                    i < (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk); i++)
+                    usedBlkSize += flash_get_sector_size( i);
+                fInfo.flash_factdeflt_blk_offset =  usedBlkSize - fInfo.flash_factdeflt_length;
+            }
+        } else {
+            printk("Not enough flash space to store factory default setting!\n");  
+            fInfo.flash_factdeflt_length = 0;     // no df
+        }
+    } else {
+           dfAddr = startAddr - NVRAM_PSI_DEFAULT*ONEK;
+        // make sure factdeflt does not share kernel block
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
+        fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+get_flash_base(0));
+#endif
+#if defined (CONFIG_BCM96358)
+               fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+FLASH_BASE);
+#endif
+        if (fInfo.flash_factdeflt_start_blk != flash_get_blk(kernelEndAddr)) {
+            fInfo.flash_factdeflt_length = NVRAM_PSI_DEFAULT*ONEK;
+            if (fInfo.flash_factdeflt_start_blk == fInfo.flash_persistent_start_blk)  // share blk
+            {
+                fInfo.flash_factdeflt_number_blk = 1;
+                fInfo.flash_factdeflt_blk_offset = fInfo.flash_persistent_blk_offset - fInfo.flash_factdeflt_length;
+            } else { // on different blk
+                fInfo.flash_factdeflt_number_blk = fInfo.flash_persistent_start_blk - fInfo.flash_factdeflt_start_blk;
+                // find out the offset in the start_blk
+                usedBlkSize = 0;
+                for (i = fInfo.flash_factdeflt_start_blk; 
+                    i < (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk); i++)
+                    usedBlkSize += flash_get_sector_size( i);
+                fInfo.flash_factdeflt_blk_offset =  usedBlkSize - fInfo.flash_factdeflt_length;
+            }
+        } else {
+            printk("Not enough flash space to store factory default setting!\n");  
+            fInfo.flash_factdeflt_length = 0;     // no df
+        }
+    }
+#endif
+    /*==== end ====*/
 #if defined(DEBUG_FLASH)
+  #if defined(CFG_XFER_TO_FACDEFLT)
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
+    printk("dfAddr = %x\n", dfAddr+get_flash_base(0));
+#endif
+#if defined (CONFIG_BCM96358)
+       printk("dfAddr = %x\n", dfAddr+FLASH_BASE);
+#endif
+    printk("fInfo.flash_factdeflt_start_blk = %d\n", fInfo.flash_factdeflt_start_blk);
+    printk("fInfo.flash_factdeflt_number_blk = %d\n", fInfo.flash_factdeflt_number_blk);
+    printk("fInfo.flash_factdeflt_length = 0x%x\n", fInfo.flash_factdeflt_length);
+    printk("fInfo.flash_factdeflt_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_factdeflt_blk_offset);
+  #endif
     printk("fInfo.flash_scratch_pad_start_blk = %d\n", fInfo.flash_scratch_pad_start_blk);
     printk("fInfo.flash_scratch_pad_number_blk = %d\n", fInfo.flash_scratch_pad_number_blk);
     printk("fInfo.flash_scratch_pad_length = 0x%x\n", fInfo.flash_scratch_pad_length);
@@ -236,8 +499,12 @@ void kerSysFlashInit( void )
     printk("fInfo.flash_nvram_start_blk = %d\n", fInfo.flash_nvram_start_blk);
     printk("fInfo.flash_nvram_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_nvram_blk_offset);
     printk("fInfo.flash_nvram_number_blk = %d\n", fInfo.flash_nvram_number_blk);
-
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
+    printk("psi startAddr = %x\n", startAddr+get_flash_base(0));
+#endif
+#if defined (CONFIG_BCM96358)
     printk("psi startAddr = %x\n", startAddr+FLASH_BASE);
+#endif
     printk("fInfo.flash_persistent_start_blk = %d\n", fInfo.flash_persistent_start_blk);
     printk("fInfo.flash_persistent_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_persistent_blk_offset);
     printk("fInfo.flash_persistent_number_blk = %d\n", fInfo.flash_persistent_number_blk);
@@ -280,7 +547,7 @@ static char *getSharedBlks(int start_blk, int end_blk)
     char *pBuf = NULL;
 
     for (i = start_blk; i < end_blk; i++)
-        usedBlkSize += flash_get_sector_size((unsigned short) i);
+        usedBlkSize += flash_get_sector_size( i);
 
 #if defined(DEBUG_FLASH)
     printk("usedBlkSize = %d\n", usedBlkSize);
@@ -295,18 +562,53 @@ static char *getSharedBlks(int start_blk, int end_blk)
     pBuf = pTempBuf;
     for (i = start_blk; i < end_blk; i++)
     {
-        sect_size = flash_get_sector_size((unsigned short) i);
+        sect_size = flash_get_sector_size( i);
 
 #if defined(DEBUG_FLASH)
         printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
 #endif
-        flash_read_buf((unsigned short)i, 0, pBuf, sect_size);
+        flash_read_buf(i, 0, pBuf, sect_size);
         pBuf += sect_size;
     }
     
     return pTempBuf;
 }
 
+/*Michael: for fix crash when push reset button */
+/* We add this because it happen only at 2Mflash 8M SDRAM. */
+static char *getSharedBlksRESET(int start_blk, int end_blk)
+{
+    int i = 0;
+    int usedBlkSize = 0;
+    int sect_size = 0;
+    char *pTempBuf = NULL;
+    char *pBuf = NULL;
+
+    for (i = start_blk; i < end_blk; i++)
+        usedBlkSize += flash_get_sector_size( i);
+
+#if defined(DEBUG_FLASH)
+    printk("usedBlkSize = %d\n", usedBlkSize);
+#endif
+    
+    if ((pTempBuf = (char *) retriedKmallocRESET(usedBlkSize)) == NULL)
+    {
+        printk("failed to allocate memory with size: %d\n", usedBlkSize);
+    return pTempBuf;
+    }
+
+    pBuf = pTempBuf;
+    for (i = start_blk; i < end_blk; i++)
+    {
+        sect_size = flash_get_sector_size( i);
+#if defined(DEBUG_FLASH)
+        printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
+#endif
+        flash_read_buf(i, 0, pBuf, sect_size);
+        pBuf += sect_size;
+    }
+    return pTempBuf;
+}
 
 
 // Set the pTempBuf to flash from start_blk to end_blk
@@ -322,7 +624,7 @@ static int setSharedBlks(int start_blk, int end_blk, char *pTempBuf)
 
     for (i = start_blk; i < end_blk; i++)
     {
-        sect_size = flash_get_sector_size((unsigned short) i);
+        sect_size = flash_get_sector_size( i);
         flash_sector_erase_int(i);
         if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size)
         {
@@ -368,7 +670,115 @@ int kerSysNvRamGet(char *string, int strLen, int offset)
     return 0;
 }
 
+#if defined(CONFIG_BCM96348) 
+int kerSysErasePS1()
+{
+       int i,j;
+       i=j=0;
+       
+         do {
+        i+=flash_get_sector_size(j);
+        j++;
+       } while (i<64*1024);
+       
+       flash_sector_erase_int(j);
+
+       
+}
+int kerSysBootFlagSet(char bootflag)
+{
+    int i = 0;
+    int sect_size = 0;
+    int sts = 0;
+    char *pTempBuf = NULL;
+    
+       printk("set bootflag %d\n",bootflag);
+        sect_size = flash_get_sector_size(0);  /* denny 09/13/04' modified */
+        if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL) {
+            printk("failed to allocate memory with size: %d\n", sect_size);
+            return -1;
+        
+        }        
+        flash_read_buf(0, 0, pTempBuf, sect_size);     
+        flash_sector_erase_int(0);
+        *((char *) pTempBuf) = bootflag;
+        if (flash_write_buf(0, 0, pTempBuf, sect_size) != sect_size)
+        {
+            printk("Error writing flash sector %d.\n", i);
+            sts = -1;
+        }
+        retriedKfree(pTempBuf);        
+        return sts;
+}
+#endif
+
+#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
+int kerSysErasePS1()
+{
+       int j;
+#if defined(CONFIG_BCM96338)   
+    if (flash_get_total_size() == 0x400000) {
+        j=flash_get_blk(0xbfe00000);
+       flash_sector_erase_int(j); /*erase the first block of bank 2*/
+       j=flash_get_blk(0xbffe0000);
+       flash_sector_erase_int(j); /*erase the bootflag of bank 2*/
+    }
+#endif
+#if defined(CONFIG_BCM96358)
+    if (flash_get_total_size() == 0x800000) {
+        j=flash_get_blk(0xbe400000);
+       flash_sector_erase_int(j); /*erase the first block of bank 2*/
+       j=flash_get_blk(0xbe7e0000);
+       flash_sector_erase_int(j); /*erase the bootflag of bank 2*/
+    }
+#endif 
+}
+
+/* bootflag will indicate which bank will be set */
+int kerSysBootFlagSet(char bootflag)
+{
+    int i = 0;
+    int sect_size = 0;
+    int sts = 0;
+    char *pTempBuf = NULL;
+    unsigned char bootnum;
+    int sector;
+    
+    unsigned int totalSize = (unsigned int) flash_get_total_size();
+
+#if 1    
+sector =bootflag?flash_get_blk(FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1):flash_get_blk(FLASH_BASE+(totalSize/2)-1);
+bootnum=bootflag?*(unsigned char*) (FLASH_BASE+(totalSize/2)-1):*(unsigned char*) (FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1);  /*flash bank1 get bootnum from bank2*/  
+#else
+sector =bootflag?flash_get_blk(0xbffe0000):flash_get_blk(0xbfdf0000);
+bootnum=bootflag?*(unsigned char*) (0xbfe00000-1):*(unsigned char*) (0xbfff0000-1);  /*flash bank1 get bootnum from bank2*/  
+#endif
 
+if ((bootnum >> 2)==0 && bootnum) {
+    bootnum=(bootnum+1);
+    if (bootnum>>2) bootnum>>=2;
+}
+else bootnum = 1;
+   
+        sect_size = flash_get_sector_size(sector);     /* denny 09/13/04' modified */
+        if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL) {
+            printk("failed to allocate memory with size: %d\n", sect_size);
+            return -1;
+        
+        }        
+        flash_read_buf(sector, 0, pTempBuf, sect_size);        
+        flash_sector_erase_int(sector);
+        *((char *) (pTempBuf+sect_size-1)) = bootnum;
+        if (flash_write_buf(sector, 0, pTempBuf, sect_size) != sect_size)
+        {
+            printk("Error writing flash sector %d.\n", i);
+            sts = -1;
+        }
+        retriedKfree(pTempBuf);        
+        printk("Next bbank %d/flag %d\n",bootflag,bootnum);
+        return sts;
+}
+#endif
 // set nvram 
 // return:
 //  0 - ok
@@ -422,7 +832,55 @@ int kerSysEraseNvRam(void)
     return sts;
 }
 
+/*==== add by Andrew (2004/09/14) ====*/
+#if defined(CFG_XFER_TO_FACDEFLT)
+int kerSysFactDefltGet(char *string, int strLen, int offset)
+{
+    char *pBuf = NULL;
+
+    if (strLen > fInfo.flash_factdeflt_length)
+        return -1;
+
+    if ((pBuf = getSharedBlks(fInfo.flash_factdeflt_start_blk,
+        (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk))) == NULL)
+        return -1;
+
+    // get string off the memory buffer
+    memcpy(string, (pBuf + fInfo.flash_factdeflt_blk_offset + offset), strLen);
+
+    retriedKfree(pBuf);
+
+    return 0;
+}
+
+
+// set factdeflt
+// return:
+//  0 - ok
+//  -1 - fail
+int kerSysFactDefltSet(char *string, int strLen, int offset)
+{
+    int sts = 0;
+    char *pBuf = NULL;
+
+    if (strLen > fInfo.flash_factdeflt_length)
+        return -1;
+
+    if ((pBuf = getSharedBlks(fInfo.flash_factdeflt_start_blk,
+        (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk))) == NULL)
+        return -1;
+
+    // set string to the memory buffer
+    memcpy((pBuf + fInfo.flash_factdeflt_blk_offset + offset), string, strLen);
+    if (setSharedBlks(fInfo.flash_factdeflt_start_blk, 
+        (fInfo.flash_factdeflt_number_blk + fInfo.flash_factdeflt_start_blk), pBuf) != 0)
+        sts = -1;
+    retriedKfree(pBuf);
 
+    return sts;
+}
+#endif
+/*==== end ====*/
 /*******************************************************************************
  * PSI functions
  *******************************************************************************/
@@ -468,10 +926,7 @@ int kerSysPersistentSet(char *string, int strLen, int offset)
 
     // set string to the memory buffer
     memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
-    // USR9108 add two terminating zeros to the end of the string
-    if ( strLen <= fInfo.flash_persistent_length - 2 )
-        memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset + strLen), "\0\0", 2);
-       
+
     if (setSharedBlks(fInfo.flash_persistent_start_blk, 
         (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
         sts = -1;
@@ -481,6 +936,27 @@ int kerSysPersistentSet(char *string, int strLen, int offset)
     return sts;
 }
 
+/*Michael: for fix crash when push reset button */
+/* We add this because it happen only at 2Mflash 8M SDRAM. */
+int kerSysPersistentSetRESET()
+{
+    int sts = 0;
+    char *pBuf = NULL;
+
+//    if (strLen > fInfo.flash_persistent_length)
+//        return -1;
+    if ((pBuf = getSharedBlksRESET(fInfo.flash_persistent_start_blk,
+        (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
+        return -1;
+    // set string to the memory buffer
+    memset((pBuf + fInfo.flash_persistent_blk_offset), 0xff, fInfo.flash_persistent_length);
+    // memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
+    if (setSharedBlks(fInfo.flash_persistent_start_blk,
+        (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
+        sts = -1;
+    retriedKfree(pBuf);
+    return sts;
+}
 
 // flash bcm image 
 // return: 
@@ -525,7 +1001,7 @@ int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
                printk("Failed to allocate memory with size: %d.  Reset the router...\n", sect_size);
                kerSysMipsSoftReset();     // reset the board right away.
             }
-            flash_read_buf((unsigned short)blk_start, 0, pTempBuf, sect_size);
+            flash_read_buf(blk_start, 0, pTempBuf, sect_size);
             if (copy_from_user((void *)pTempBuf,(void *)string, size) != 0)
                 break;  // failed ?
             flash_sector_erase_int(blk_start);     // erase blk before flash
@@ -573,6 +1049,67 @@ int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
     return sts;
 }
 
+/***********************************************************************
+ * Function Name: kerSysErasePersistent
+ * Description  : Erase the Psi storage section of flash memory.
+ * Returns      : 1 -- ok, 0 -- fail
+ ***********************************************************************/
+
+/* This funtion ONLY called by user when reset to default button is pressed */
+
+
+int kerSysErasePersistent(void)
+{
+    int sts = 1;
+    char *tempStorage = NULL;
+    int i, size=0, unit = fInfo.flash_persistent_length/8;
+    
+#if 0    
+
+    printk("psi 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_persistent_start_blk,fInfo.flash_persistent_number_blk,fInfo.flash_persistent_length,fInfo.flash_persistent_blk_offset);
+    printk("pad 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_scratch_pad_start_blk,fInfo.flash_scratch_pad_number_blk,fInfo.flash_scratch_pad_length,fInfo.flash_scratch_pad_blk_offset);
+    printk("nvram 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_nvram_start_blk,fInfo.flash_nvram_number_blk,fInfo.flash_nvram_length,fInfo.flash_nvram_blk_offset);
+
+    printk("\nErasing PSI storage section of flash memory....\n");
+    for(i=0;i<7;i++) {
+        tempStorage = retriedKmallocRESET(unit);
+       // just write the whole buf with '0xff' to the flash
+       if (!tempStorage) {
+          sts = 0;
+       } else {
+          memset(tempStorage, 0xff, unit);
+          if(kerSysPersistentSetRESET(tempStorage, unit, size) != 0)
+              sts = 0;
+          retriedKfree(tempStorage);
+       }
+       size += unit;
+       if(!sts) {printk("Cannot alloc %d\n",i); return sts;}
+       else printk("success in %d\n",i);
+    }
+
+    unit = fInfo.flash_persistent_length - size;
+    printk("try to alloc %d\n",unit);
+    tempStorage = retriedKmalloc(unit);
+    if (!tempStorage) {
+       sts = 0;
+    } else {
+       printk("success in last\n");
+       memset(tempStorage, 0xff, unit);
+       if(kerSysPersistentSet(tempStorage, unit, size) != 0)
+           sts = 0;
+       retriedKfree(tempStorage);
+    }
+#else
+   printk("\nErasing PSI....\n");
+   if (kerSysPersistentSetRESET() != 0)
+              sts = 0;
+#endif
+    printk("\nRebooting ADSL router.........");
+    return sts;
+}
+
+
+
 /*******************************************************************************
  * SP functions
  *******************************************************************************/
@@ -634,7 +1171,7 @@ int kerSysScratchPadGet(char *tokenId, char *tokBuf, int bufLen)
                 printk("The length %d of token %s is greater than buffer len %d.\n", pToken->tokenLen, pToken->tokenName, bufLen);
                 break;
             } else             
-                sts = pToken->tokenLen;
+            sts = pToken->tokenLen;
             memcpy(tokBuf, startPtr + sizeof(SP_TOKEN), sts);
             break;
         }
@@ -818,7 +1355,7 @@ int kerSysScratchPadClearAll(void)
     pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;  
     memset(pBuf, 0x00,  fInfo.flash_scratch_pad_length);
     sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,    
-               (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk),  pShareBuf);
+               (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk),  pBuf);
 
    retriedKfree(pShareBuf);
        
@@ -845,3 +1382,63 @@ unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr,
     return( len );
 }
 
+/*This function is copied from V2.10.1 to fix the bug SDRAM change from 16M to 8M 
+  during upgrade include CFE */
+/***********************************************************************
+ * Function Name: kerSysMemoryTypeSet
+ * Description  : set the memory type 4 bytes
+ * Returns      : 1 -- ok, 0 -- fail
+ ***********************************************************************/
+int kerSysMemoryTypeSet(int flash_start_addr, char *string, int size)
+{
+    int sect_size;
+    int blk_start;
+    char *pTempBuf;
+
+    blk_start = flash_get_blk(flash_start_addr);
+    sect_size = flash_get_sector_size(blk_start);
+    if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL)
+    {
+        printk("Failed to allocate memory with size: %d\n", sect_size);
+        return 0;
+    }
+    flash_read_buf(blk_start, 0, pTempBuf, sect_size);
+    memcpy(pTempBuf+SDRAM_TYPE_ADDRESS_OFFSET, string, size);
+    flash_sector_erase_int(blk_start);     // erase blk before flash
+//    flash_ub(0);
+    if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) != sect_size)
+        printk("Failed to flash the memory type\n");
+//    flash_reset_ub();
+    return 1;
+}
+
+/*This function is copied from V2.10.1 to fix the bug SDRAM change from 16M to 8M 
+  during upgrade include CFE */
+/***********************************************************************
+ * Function Name: kerSysMemoryTypeSet
+ * Description  : set the memory type 4 bytes
+ * Returns      : 1 -- ok, 0 -- fail
+ ***********************************************************************/
+int kerSysThreadNumSet(int flash_start_addr, char *string, int size)
+{
+    int sect_size;
+    int blk_start;
+    char *pTempBuf;
+
+    blk_start = flash_get_blk(flash_start_addr);
+    sect_size = flash_get_sector_size(blk_start);
+    if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL)
+    {
+        printk("Failed to allocate memory with size: %d\n", sect_size);
+        return 0;
+    }
+    flash_read_buf(blk_start, 0, pTempBuf, sect_size);
+    memcpy(pTempBuf+THREAD_NUM_ADDRESS_OFFSET, string, size);
+    flash_sector_erase_int(blk_start);     // erase blk before flash
+//    flash_ub(0);
+    if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) != sect_size)
+        printk("Failed to flash the thread num\n");
+//    flash_reset_ub();
+    return 1;
+}
+