Beispiel #1
0
int FlashIAP::erase(uint32_t addr, uint32_t size)
{
    uint32_t current_sector_size;
    uint32_t flash_size = flash_get_size(&_flash);
    uint32_t flash_start_addr = flash_get_start_address(&_flash);
    uint32_t flash_end_addr = flash_start_addr + flash_size;
    uint32_t erase_end_addr = addr + size;

    if (erase_end_addr > flash_end_addr) {
        return -1;
    } else if (erase_end_addr < flash_end_addr){
        uint32_t following_sector_size = flash_get_sector_size(&_flash, erase_end_addr);
        if (!is_aligned(erase_end_addr, following_sector_size)) {
            return -1;
        }
    }

    int32_t ret = 0;
    _mutex->lock();
    while (size) {
        ret = flash_erase_sector(&_flash, addr);
        if (ret != 0) {
            ret = -1;
            break;
        }
        current_sector_size = flash_get_sector_size(&_flash, addr);
        size -= current_sector_size;
        addr += current_sector_size;
    }
    _mutex->unlock();
    return ret;
}
// Initialize the flash and fill out the fInfo structure
void kerSysEarlyFlashInit( void )
{
    flash_init();
    bootFromNand = 0;

#if defined(CONFIG_BCM96368)
    if( ((GPIO->StrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >>
        MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND)
        bootFromNand = 1;
#elif defined(CONFIG_BCM96362) || defined(CONFIG_BCM96328) || defined(CONFIG_BCM93329)
    if( ((MISC->miscStrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >>
        MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND )
        bootFromNand = 1;
#endif

#if defined(CONFIG_BCM96368) || defined(CONFIG_BCM96362) || defined(CONFIG_BCM96328) || defined(CONFIG_BCM93329)
    if( bootFromNand == 1 )
    {
        NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x101;
        NAND->NandCsNandXor = 1;

        memcpy((unsigned char *)&bootCfeVersion, (unsigned char *)
            FLASH_BASE + CFE_VERSION_OFFSET, sizeof(bootCfeVersion));
        memcpy((unsigned char *)&bootNvramData, (unsigned char *)
            FLASH_BASE + NVRAM_DATA_OFFSET, sizeof(NVRAM_DATA));

        NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x2;
        NAND->NandCsNandXor = 0;
    }
    else
#endif
    {
        fInfo.flash_rootfs_start_offset = flash_get_sector_size(0);
        if( fInfo.flash_rootfs_start_offset < FLASH_LENGTH_BOOT_ROM )
            fInfo.flash_rootfs_start_offset = FLASH_LENGTH_BOOT_ROM;
     
        flash_read_buf (NVRAM_SECTOR, CFE_VERSION_OFFSET,
            (unsigned char *)&bootCfeVersion, sizeof(bootCfeVersion));

        /* Read the flash contents into NVRAM buffer */
        flash_read_buf (NVRAM_SECTOR, NVRAM_DATA_OFFSET,
            (unsigned char *)&bootNvramData, sizeof (NVRAM_DATA)) ;
    }

#if 1 //defined(DEBUG_FLASH)
    printk("reading nvram into bootNvramData\n");
    printk("ulPsiSize 0x%x\n", (unsigned int)bootNvramData.ulPsiSize);
    printk("backupPsi 0x%x\n", (unsigned int)bootNvramData.backupPsi);
    printk("ulSyslogSize 0x%x\n", (unsigned int)bootNvramData.ulSyslogSize);
    printk("Rootfs1 Off 0x%x\n", (unsigned int) bootNvramData.ulNandPartOfsKb[NP_ROOTFS_1]);
    printk("Rootfs1 Size 0x%x\n", (unsigned int) bootNvramData.ulNandPartSizeKb[NP_ROOTFS_1]);
#endif

    if ((BpSetBoardId(bootNvramData.szBoardId) != BP_SUCCESS))
        printk("\n*** Board is not initialized properly ***\n\n");
}
Beispiel #3
0
bool FlashIAP::is_aligned_to_sector(uint32_t addr, uint32_t size)
{
    uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
    if (!is_aligned(size, current_sector_size) ||
        !is_aligned(addr, current_sector_size)) {
        return false;
    } else {
        return true;
    }
}
// get shared blks into *** pTempBuf *** which has to be released bye the caller!
// return: if pTempBuf != NULL, poits to the data with the dataSize of the buffer
// !NULL -- ok
// NULL  -- fail
static char *getSharedBlks(int start_blk, int num_blks)
{
    int i = 0;
    int usedBlkSize = 0;
    int sect_size = 0;
    char *pTempBuf = NULL;
    char *pBuf = NULL;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
    /* not allowed to ignore the return of down_interruptible in new kernel */
    if (down_interruptible(&semflash) )
    {
        return NULL;
    }
#else
    down_interruptible(&semflash);
#endif

    for (i = start_blk; i < (start_blk + num_blks); i++)
        usedBlkSize += flash_get_sector_size((unsigned short) i);

    if ((pTempBuf = (char *) retriedKmalloc(usedBlkSize)) == NULL)
    {
        printk("failed to allocate memory with size: %d\n", usedBlkSize);
        up(&semflash);
        return pTempBuf;
    }
    
    pBuf = pTempBuf;
    for (i = start_blk; i < (start_blk + num_blks); i++)
    {
        sect_size = flash_get_sector_size((unsigned short) i);

#if defined(DEBUG_FLASH)
        printk("getSharedBlks: blk=%d, sect_size=%d\n", i, sect_size);
#endif
        flash_read_buf((unsigned short)i, 0, pBuf, sect_size);
        pBuf += sect_size;
    }
    up(&semflash);
    
    return pTempBuf;
}
Beispiel #5
0
int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
{
    uint32_t page_size = get_page_size();
    uint32_t flash_size = flash_get_size(&_flash);
    uint32_t flash_start_addr = flash_get_start_address(&_flash);
    uint32_t chunk, prog_size;
    const uint8_t *buf = (uint8_t *) buffer;
    const uint8_t *prog_buf;

    // addr should be aligned to page size
    if (!is_aligned(addr, page_size) || (!buffer) ||
        ((addr + size) > (flash_start_addr + flash_size))) {
        return -1;
    }

    int ret = 0;
    _mutex->lock();
    while (size) {
        uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
        bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf);
        chunk = std::min(current_sector_size - (addr % current_sector_size), size);
        // Need to use the internal page buffer in any of these two cases:
        // 1. Size is not page aligned
        // 2. Source buffer is not aligned to uint32_t. This is not supported by many targets (although
        //    the pointer they accept is of uint8_t).
        if (unaligned_src || (chunk < page_size)) {
            chunk = std::min(chunk, page_size);
            memcpy(_page_buf, buf, chunk);
            if (chunk < page_size) {
                memset(_page_buf + chunk, 0xFF, page_size - chunk);
            }
            prog_buf = _page_buf;
            prog_size = page_size;
        } else {
            chunk = chunk / page_size * page_size;
            prog_buf = buf;
            prog_size = chunk;
        }
        if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
            ret = -1;
            break;
        }
        size -= chunk;
        addr += chunk;
        buf += chunk;
    }
    _mutex->unlock();

    return ret;
}
// wipe out the scratchPad
// return:
//  0 - ok
//  -1 - fail
int kerSysScratchPadClearAll(void)
{ 
    int sts = -1;
    char *pShareBuf = NULL;
   int j ;
   int usedBlkSize = 0;

   // printk ("kerSysScratchPadClearAll.... \n") ;

    if( bootFromNand )
    {
        if((pShareBuf = getScratchPad(fInfo.flash_scratch_pad_length)) == NULL)
            return sts;

        memset(pShareBuf, 0x00, fInfo.flash_scratch_pad_length);

        setScratchPad(pShareBuf, fInfo.flash_scratch_pad_length);
    }
    else
    {
        if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
            fInfo.flash_scratch_pad_number_blk)) == NULL )
            return sts;

        if (fInfo.flash_scratch_pad_number_blk == 1)
            memset(pShareBuf + fInfo.flash_scratch_pad_blk_offset, 0x00, fInfo.flash_scratch_pad_length) ;
        else
        {
            for (j = fInfo.flash_scratch_pad_start_blk;
                j < (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk);
                j++)
            {
                usedBlkSize += flash_get_sector_size((unsigned short) j);
            }

            memset(pShareBuf, 0x00, usedBlkSize) ;
        }

        sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,    
            fInfo.flash_scratch_pad_number_blk,  pShareBuf);
    }

   retriedKfree(pShareBuf);

   //printk ("kerSysScratchPadClearAll Done.... \n") ;
   return sts;
}
Beispiel #7
0
unsigned int flash_get_reserved_bytes_at_end(const FLASH_ADDR_INFO *fInfo)
{
    unsigned int reserved=0;
    int i = fInfo->flash_meta_start_blk;
    int totalBlks = flash_get_numsectors();

    while (i < totalBlks)
    {
        reserved += flash_get_sector_size((unsigned short) i);
        i++;
    }

#if defined(DEBUG_FLASH)
    printk("reserved at bottom=%dKB\n", reserved/1024);
#endif

    return reserved;
}
// Set the pTempBuf to flash from start_blk for num_blks
// return:
// 0 -- ok
// -1 -- fail
static int setSharedBlks(int start_blk, int num_blks, char *pTempBuf)
{
    int i = 0;
    int sect_size = 0;
    int sts = 0;
    char *pBuf = pTempBuf;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
    /* not allowed to ignore the return of down_interruptible in new kernel */
    if (down_interruptible(&semflash) )
    {
        return -1;
    }
#else
    down_interruptible(&semflash);
#endif

    for (i = start_blk; i < (start_blk + num_blks); i++)
    {
        sect_size = flash_get_sector_size((unsigned short) i);
        flash_sector_erase_int(i);

        if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size)
        {
            printk("Error writing flash sector %d.", i);
            sts = -1;
            break;
        }

#if defined(DEBUG_FLASH)
        printk("setShareBlks: blk=%d, sect_size=%d\n", i, sect_size);
#endif

        pBuf += sect_size;
    }

    up(&semflash);

    return sts;
}
Beispiel #9
0
int flash_get_blk(int addr)
{
    int blk_start, i;
    int last_blk = flash_get_numsectors();
    int relative_addr = addr - (int) FLASH_BASE_ADDR_REG;

    for(blk_start=0, i=0; i < relative_addr && blk_start < last_blk; blk_start++)
        i += flash_get_sector_size(blk_start);

    if( i > relative_addr )
    {
        blk_start--;        // last blk, dec by 1
    }
    else
        if( blk_start == last_blk )
        {
            printk("Address is too big.\n");
            blk_start = -1;
        }

    return( blk_start );
}
Beispiel #10
0
/***************************************************************************
 * Function Name: display_flash_info
 * Description  : Displays information about the flash part.
 * Returns      : None.
 ***************************************************************************/
static void display_flash_info(int ret, flash_device_info_t *flash_info)
{
    switch (flash_info->flash_type) {
    case FLASH_IFC_PARALLEL:
        printk( "Parallel flash device");
        break;

    case FLASH_IFC_SPI:
        printk( "Serial flash device");
        break;

    case FLASH_IFC_HS_SPI:
        printk( "HS Serial flash device");
        break;

    case FLASH_IFC_NAND:
        printk( "NAND flash device");
        break;
    }

    if( ret == FLASH_API_OK ) {
        printk(": name %s, id 0x%4.4x",
            flash_info->flash_device_name, flash_info->flash_device_id);
#if (INC_SPI_PROG_NAND==1)
        printk(" block %dKB", flash_info->fn_flash_get_sector_size(0) / 1024);
        printk(" size %luKB", (unsigned long )
            flash_info->fn_flash_get_total_size() / 1024);
#else
        if (flash_info->flash_type == FLASH_IFC_NAND)
            printk(" block %dKB", flash_get_sector_size(0) / 1024);
        printk(" size %luKB", flash_get_total_size() / 1024);
#endif
        printk("\n");
    }
    else {
        printk( " id %4.4x is not supported.\n", flash_info->flash_device_id );
    }
} /* display_flash_info */
Beispiel #11
0
uint32_t FlashIAP::get_sector_size(uint32_t addr) const
{
    return flash_get_sector_size(&_flash, addr);
}
Beispiel #12
0
void main(void)
{
  byte test;
  byte manuf_id;
  word device_id;
  byte far *str;
  word test2,i;
  dword sec_size=0;
  long count=0;

  printf("Beginning test.....\n\n");

  /* First, poke around the memory map to see what kind of
     flash is installed in the socket...assume a DL800B */

  /* The purpose of init_flash is to perform any system memory
     mapping required, and to set up pointers to those region(s).
     init_flash() also selects the proper sector organization
     table defined in flash.c 
     Note: init_flash() will need to be provided by users of
     the flash.c routines */

  if(!init_flash(AM29DL800B)) {
	 exit(1);
  }

  /* Verify the manufacturer code is indeed 0x01 for AMD */
  manuf_id = flash_get_manuf_code(0);

  switch(manuf_id)
  {
	case AMDPART: printf("AMD Flash found in socket...\n");
   		      break;
	default: printf("Non AMD part found in socket...exiting.\n");
		 exit(1);
		 break;
  }

  /* Poll the device id so that the proper sector layout table
     is used for the device in the socket */

  printf("Polling part for Device ID...");

  /* Retrieve the device ID for this AMD flash part.  All device
     id's are stored in flash.h */

  device_id = flash_get_device_id(0);

  switch(device_id)
  {
	case ID_AM29DL800T: 	printf("found an Am29DL800T\n");
				if(!init_flash(AM29DL800T)) exit(1);
				break;

	case ID_AM29DL800B:  	printf("found an Am29DL800B\n");
				if(!init_flash(AM29DL800B)) exit(1);
				break;

	case ID_AM29LV800T:  	printf("found an Am29LV800T\n");
				if(!init_flash(AM29LV800T)) exit(1);
				break;

	case ID_AM29LV800B:  	printf("found an Am29LV800B\n");
				if(!init_flash(AM29LV800B)) exit(1);
				break;

	case ID_AM29LV160B:  	printf(  "found an Am29LV160B\n");
				if(!init_flash(AM29LV160B)) exit(1);
				break;

	case ID_AM29LV400B:  	printf(  "found an Am29LV400B\n");
				if(!init_flash(AM29LV400B)) exit(1);
				break;

	default: printf("error reading Device ID...exiting.\n");
		 exit(1);
		 break;
  }

  randomize();

  /* flash_get_status uses DQ7, DQ5, and DQ2 polling to get the
     status of the flash.  All status codes are defined in flash.h
     Also note that for the DL parts, status is bank dependent */

  printf("Checking current flash status...flash is ");
  test = flash_get_status(0);
  switch(test)
  {
	 case STATUS_READY: 	printf("[Ready]\n");break;
	 case STATUS_BUSY: 	printf("[Busy]\n");break;
	 case STATUS_ERSUSP: 	printf("[Erase Suspended]\n");break;
	 case STATUS_TIMEOUT: 	printf("[Timed Out]\n");break;
	 default: 		printf("Error!\n"); exit(1);break;
  }

  printf("Performing API tests...\n\n");

  /* flash_sector_erase_int() is the function which erases a single
     sector.  It is different from flash_sector_erase() in that it
     'interrupts' execution of the program until the erase is completed.
     For erasing a sector without pausing use flash_sector_erase(). */

  flash_reset(); /* Quick safe check */

  printf("Erasing sector 8...");
  flash_sector_erase_int(8);
  printf("done.\n");

  printf("Verifying erase...");

  flash_get_sector_size(8, &sec_size); /* Get # of byte */

  /* A simple test which reads every word from the flash, and checks
     to see if every word contains the data 0xFFFF, which indicates
     an erased word. */

  for (count=0 ; count < (sec_size/2); count++) {
	 if(count%2048 == 0)
		printf("."); /*print out some dots to show the program hasn't frozen */
	 if (flash_read_word(8,count) != 0xFFFF) {
		printf("erase not completed sucessfully!\n");
		exit(1);
	 }
  }
  printf("erase successful.\n");

  /* flash_write_word() takes word data and programs it to the flash
     at the indicated offset.  Note that this data must be *word aligned*,
     or else programming errors can result.
     It is also good to check the word for 0xFFFF data before programming. */
  
  printf("Writing a single word [0xABCD]\n");
  flash_write_word(8,0,0xABCD);

  /* flash_read_word() returns a single word of data at the specified
     sector/offset .  Must also be word aligned */
  
  printf("After write(0xABCD): %4x\n", flash_read_word(8,0));

  str = (byte far *) calloc(0x7FFF, sizeof(byte));

  /* Randomize the string with random ASCII characters */
  for(i=0; i<0x7FFF; i++) {
	 str[i] = (byte) (41 + (rand() % 26));
  }

  printf("Erasing sector 9...");
  flash_sector_erase_int(9);
  printf("done.\n");

  /* flash_write_string() is a function to program bulk data from a C
     buffer.  It is a bit faster than looping techniques using
     flash_write_word() because function overhead is eliminated. */
  
  printf("Writing 32 kbyte string...");
  flash_write_string(9,0,str,0x7FFE);

  printf("done.\n\n");

  printf("Testing erase suspend\n");
  printf("Beginning erase...\n");

/* This is an example of flash_sector_erase().  Note that the program will
     simply issue the command, and execution will continue while the
     flash is erasing. */
  
  flash_sector_erase(10);

  /* flash_erase_suspend will suspend an erase in progress.  The application
     can then do any reading of data from that sector, or another sector. */
  
  printf("Suspending erase...");
  flash_erase_suspend(10);
  printf("done.\n");

  /* The current flash status should now be STATUS_ERSUSP */
  printf("Checking current flash status...flash is ");
  test = flash_get_status(10);
  switch(test)
  {
	 case STATUS_READY: printf("[Ready]\n");break;
	 case STATUS_BUSY: printf("[Busy]\n");break;
	 case STATUS_ERSUSP: printf("[Erase Suspended]\n");break;
	 case STATUS_TIMEOUT: printf("[Timed Out]\n");break;
	 default: printf("Error!\n"); exit(1);break;
  }

  /* Now we can resume the erase previously suspended */
  printf("Resuming erase after status check..");
  flash_erase_resume(10);
  printf("done.\n");

  /* Now for a test of unlock bypass mode */
  /* Unlock bypass allows for faster programming of flash data in that
     the number of required bus cycles is cut in half.  The most benefit
     can be realized when programming large amounts of data using
     flash_write_string_ub() */

  printf("Entering unlock bypass mode...\n");
  flash_sector_erase_int(11);
  flash_ub(11); /* Enter unlock bypass mode */

  printf("Programming a string in unlock bypass mode..");
  flash_write_string_ub(11,0,str,0x7FFE);
  printf("done.\n");

  printf("Exiting unlock bypass mode..\n");
  flash_reset_ub();

  flash_reset();

  /* Last thing is a quick loop through all the sectors 
     to check for sector protection. */

  printf("\nVerifying sector protection...\n");

  flash_get_numsectors(&test2);

  printf("This device contains %3i sectors: \n", test2);
  for(i=0; i < test2; i++) {
	 test = flash_sector_protect_verify(i);
	 flash_get_sector_size(i, &size);
	 printf("Verify sector #%2i, size [%-5li]: ",
	          i, size);
	 if (test == 0x01)
		printf("sector is protected[%2i].\n", test);
	 else
		printf("sector is not protected[%2i].\n", test);
	 flash_reset();
  }


  printf("Test drive done!\n");
  free(str);
  exit(0);
}
Beispiel #13
0
void flash_init_info(const NVRAM_DATA *nvRam, FLASH_ADDR_INFO *fInfo)
{
    int i = 0;
    int totalBlks = 0;
    int totalSize = 0;
    int auxFsSize = 0;
    int psiStartAddr = 0;
    int spStartAddr = 0;
    int usedBlkSize = 0;
    int needBytes = 0;
    int sBlk, eBlk;
    int blkSize, sectSize;	/* Size of all blocks in a partition or 0 */
    int totalPartSize;			/* Size in bytes for a partition */
    unsigned long  offset;   	/* Offset calulations */

    if (flash_get_flash_type() == FLASH_IFC_NAND)
    {
        /* When using NAND flash disable Bcm_flash */
        totalSize = 0;
    }
    else {
        totalBlks = flash_get_numsectors();
        totalSize = flash_get_total_size();
        printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
    }

    if (totalSize <= FLASH_LENGTH_BOOT_ROM) {
        /* NAND flash settings. NAND flash does not use raw flash partitioins
         * to store psi, backup psi, scratch pad and syslog.  These data items
         * are stored as files on a JFFS2 file system.
         */
        if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
            fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
        else
            fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;

        fInfo->flash_persistent_start_blk = 0;
        fInfo->flash_rootfs_start_offset = 0;
        fInfo->flash_scratch_pad_length = SP_MAX_LEN;
        fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;

        /* This is a boolean field for NAND flash. */
        fInfo->flash_backup_psi_number_blk = nvRam->backupPsi;
        return;
    }

    /*
    * calculate mandatory primary PSI size and set its fInfo parameters.
    */
    if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
        fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
    else
        fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;

    psiStartAddr = totalSize - fInfo->flash_persistent_length;
    fInfo->flash_persistent_start_blk = flash_get_blk(FLASH_BASE+psiStartAddr);
    fInfo->flash_persistent_number_blk = totalBlks - fInfo->flash_persistent_start_blk;

    usedBlkSize = 0;
    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);
    }
    fInfo->flash_persistent_blk_offset =  usedBlkSize - fInfo->flash_persistent_length;
    fInfo->flash_meta_start_blk = fInfo->flash_persistent_start_blk;

    /*
    * Next is the optional scratch pad, which is on top of the primary PSI.
    * Old code allowed scratch pad to share a sector with primary PSI.
    * That is retained for backward compatibility.  (Although depending on your
    * NOR flash sector sizes, they may still be in different sectors.)
    * If you have a new deployment, consider forcing separate sectors.
    */
    if ((fInfo->flash_persistent_blk_offset > 0) &&
        (fInfo->flash_persistent_blk_offset < SP_MAX_LEN))
    {
        /*
        * there is some room left in the first persistent sector, but it is
        * not big enough for the scratch pad. (Use this line unconditionally
        * if you want to guarentee scratch pad and primary PSI are on different
        * sectors.)
        */
        spStartAddr = psiStartAddr - fInfo->flash_persistent_blk_offset - SP_MAX_LEN;
    }
    else
    {
        /* either the primary PSI starts on a sector boundary, or there is
        * enough room at the top of the first sector for the scratch pad. */
        spStartAddr = psiStartAddr - SP_MAX_LEN ;
    }

    fInfo->flash_scratch_pad_start_blk = flash_get_blk(FLASH_BASE+spStartAddr);
    fInfo->flash_scratch_pad_length = SP_MAX_LEN;

    if (fInfo->flash_persistent_start_blk == fInfo->flash_scratch_pad_start_blk)  // share blk
    {
#if 0 /* do not used scratch pad unless it's in its own sector */
        printk("Scratch pad is not used for this flash part.\n");  
        fInfo->flash_scratch_pad_length = 0;     // no sp
#else /* allow scratch pad to share a sector with another section such as PSI */
        fInfo->flash_scratch_pad_number_blk = 1;
        fInfo->flash_scratch_pad_blk_offset = fInfo->flash_persistent_blk_offset - fInfo->flash_scratch_pad_length;
#endif
    }
    else // on different blk
    {
        fInfo->flash_scratch_pad_number_blk = fInfo->flash_persistent_start_blk - fInfo->flash_scratch_pad_start_blk;
        // find out the offset in the start_blk
        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);
        fInfo->flash_scratch_pad_blk_offset =  usedBlkSize - fInfo->flash_scratch_pad_length;
    }

    if (fInfo->flash_scratch_pad_length > 0) {

        fInfo->flash_meta_start_blk = fInfo->flash_scratch_pad_start_blk;
    }

    /*
    * Next is the optional backup PSI.
    */
    if (nvRam->backupPsi == 0x01)
    {
        needBytes = fInfo->flash_persistent_length;
        i = fInfo->flash_meta_start_blk;
        while (needBytes > 0)
        {
            i--;
            needBytes -= flash_get_sector_size((unsigned short) i);
        }
        fInfo->flash_backup_psi_start_blk = i;
        /* calclate how many blocks we actually consumed */
        needBytes = fInfo->flash_persistent_length;
        fInfo->flash_backup_psi_number_blk = 0;
        while (needBytes > 0)
        {
            needBytes -= flash_get_sector_size((unsigned short) i);
            i++;
            fInfo->flash_backup_psi_number_blk++;
        }

        fInfo->flash_meta_start_blk = fInfo->flash_backup_psi_start_blk;
    }
    else
    {
        fInfo->flash_backup_psi_number_blk = 0;
    }

    /*
    * Next is the optional persistent syslog.
    */
    if (nvRam->ulSyslogSize != 0 && nvRam->ulSyslogSize != -1)
    {
        fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;
        needBytes = fInfo->flash_syslog_length;
        i = fInfo->flash_meta_start_blk;
        while (needBytes > 0)
        {
            i--;
            needBytes -= flash_get_sector_size((unsigned short) i);
        }
        fInfo->flash_syslog_start_blk = i;
        /* calclate how many blocks we actually consumed */
        needBytes = fInfo->flash_syslog_length;
        fInfo->flash_syslog_number_blk = 0;
        while (needBytes > 0)
        {
            needBytes -= flash_get_sector_size((unsigned short) i);
            i++;
            fInfo->flash_syslog_number_blk++;
        }

        fInfo->flash_meta_start_blk = fInfo->flash_syslog_start_blk;
    }
    else
    {
        fInfo->flash_syslog_length = 0;
        fInfo->flash_syslog_number_blk = 0;
    }

#if 1   //for AUXFS 

   if ( (nvRam->ucAuxFSPercent != 0)
    && (nvRam->ucAuxFSPercent <= MAX_AUXFS_PERCENT))
    {
        /* Estimate the Auxillary File System size */
        auxFsSize = (totalSize * (int)nvRam->ucAuxFSPercent)/100;
        
        /* JFFS_AUXFS offset */
        offset = totalSize - auxFsSize - flash_get_reserved_bytes_at_end(fInfo);
		
        sBlk = flash_get_blk(offset+FLASH_BASE);
	  eBlk = fInfo->flash_meta_start_blk;

	  /*
         * Implementation Note:
         * Ensure that we have even number of blocks for
         * ROOTFS+KERNEL to support dual image booting
        */
        if ( ( (sBlk+1) < eBlk)
          && ((((sBlk+1) - flash_get_blk(fInfo->flash_rootfs_start_offset + FLASH_BASE)) % 2) == 0))
        {
            sBlk += 1;	/* Round up */
        }

        blkSize = flash_get_sector_size(sBlk);
        for ( i=sBlk+1, totalPartSize = blkSize; i<eBlk; i++)
        {
            sectSize = flash_get_sector_size(i);
            //if ( blkSize != sectSize ) blkSize = 0;
            if ( blkSize != sectSize ) break;
            totalPartSize += sectSize;
        }
        fAuxFsInfo.sect_size = blkSize;
        auxFsSize = totalPartSize;


        printk("Flash split %d : AuxFS[%d]\n",
               (int)nvRam->ucAuxFSPercent,auxFsSize );
    }
    else
    {
	/*
	 * Implementation Note: When there is no AuxFS Partition.
	 * Total number of rootfs/kernel blocks will always be ODD.
	 * Option: Increase RESERVED section ??? but this would
	 * decrease the space available for a single kernel image
	 */
        sBlk = eBlk = 0;
        fAuxFsInfo.sect_size = 0;
        auxFsSize = 0;
        printk("Flash not used for Auxillary File System\n");
     }


	/*------------*/
	/* JFFS_AUXFS */
	/*------------*/

    sprintf(fAuxFsInfo.name, "JFFS_AUXFS");
    fAuxFsInfo.start_blk = sBlk;
    fAuxFsInfo.number_blk = eBlk - sBlk;
    fAuxFsInfo.blk_offset = 0;
    fAuxFsInfo.total_len = auxFsSize;
    fAuxFsInfo.mem_base = (unsigned long) flash_get_memptr( sBlk )
                                   +  fAuxFsInfo.blk_offset;
    fAuxFsInfo.mem_length = auxFsSize;
    
#endif

#ifdef DEBUG_FLASH_TOO_MUCH
    /* dump sizes of all sectors in flash */
    for (i=0; i<totalBlks; i++)
        printk("blk %03d: %d\n", i, flash_get_sector_size((unsigned short) i));
#endif

#if defined(DEBUG_FLASH)
    printk("FLASH_BASE                    =0x%08x\n\n", (unsigned int)FLASH_BASE);

    printk("fInfo->flash_rootfs_start_offset =0x%08x\n\n", (unsigned int)fInfo->flash_rootfs_start_offset);

    printk("fInfo->flash_meta_start_blk = %d\n\n", fInfo->flash_meta_start_blk);

    printk("fInfo->flash_syslog_start_blk  = %d\n", fInfo->flash_syslog_start_blk);
    printk("fInfo->flash_syslog_number_blk = %d\n", fInfo->flash_syslog_number_blk);
    printk("fInfo->flash_syslog_length=0x%x\n\n", (unsigned int)fInfo->flash_syslog_length);

    printk("fInfo->flash_backup_psi_start_blk = %d\n", fInfo->flash_backup_psi_start_blk);
    printk("fInfo->flash_backup_psi_number_blk = %d\n\n", fInfo->flash_backup_psi_number_blk);

    printk("sp startAddr = %x\n", (unsigned int) (FLASH_BASE+spStartAddr));
    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);
    printk("fInfo->flash_scratch_pad_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_scratch_pad_blk_offset);

    printk("psi startAddr = %x\n", (unsigned int) (FLASH_BASE+psiStartAddr));
    printk("fInfo->flash_persistent_start_blk = %d\n", fInfo->flash_persistent_start_blk);
    printk("fInfo->flash_persistent_number_blk = %d\n", fInfo->flash_persistent_number_blk);
    printk("fInfo->flash_persistent_length=0x%x\n", (unsigned int)fInfo->flash_persistent_length);
    printk("fInfo->flash_persistent_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_persistent_blk_offset);
    printk("AuxFs.start_blk = %d\n",fAuxFsInfo.start_blk );
    printk("AuxFs,number_blk = %d\n", fAuxFsInfo.number_blk);
    printk("AuxFs.total_len = 0x%x\n",fAuxFsInfo.total_len);
    printk("AuxFs.sect_size = 0x%x\n",fAuxFsInfo.sect_size);
#endif
}
// flash bcm image 
// return: 
// 0 - ok
// !0 - the sector number fail to be flashed (should not be 0)
int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
{
    int sts;
    int sect_size;
    int blk_start;
    int savedSize = size;
    int whole_image = 0;

    if( bootFromNand )
        return( nandImageSet( flash_start_addr, string, size ) );

    if (flash_start_addr == FLASH_BASE)
        whole_image = 1;

#if defined(DEBUG_FLASH)
    printk("kerSysBcmImageSet: flash_start_addr=0x%x string=%p len=%d whole_image=%d\n",
           flash_start_addr, string, size, whole_image);
#endif

    blk_start = flash_get_blk(flash_start_addr);
    if( blk_start < 0 )
        return( -1 );

    // Disable other tasks from this point on
#if defined(CONFIG_SMP)
    smp_send_stop();
    udelay(20);
#endif
    local_bh_disable();

    /* write image to flash memory */
    do 
    {
        sect_size = flash_get_sector_size(blk_start);

        flash_sector_erase_int(blk_start);     // erase blk before flash

        if (sect_size > size) 
        {
            if (size & 1) 
                size++;
            sect_size = size;
        }
        
        if (flash_write_buf(blk_start, 0, string, sect_size) != sect_size) {
            break;
        }

        printk(".");
        blk_start++;
        string += sect_size;
        size -= sect_size; 
    } while (size > 0);

    if (whole_image && savedSize > fInfo.flash_rootfs_start_offset)
    {
        // If flashing a whole image, erase to end of flash.
        int total_blks = flash_get_numsectors();
        while( blk_start < total_blks )
        {
            flash_sector_erase_int(blk_start);
            printk(".");
            blk_start++;
        }
    }

    printk("\n\n");

    if( size == 0 ) 
        sts = 0;  // ok
    else  
        sts = blk_start;    // failed to flash this sector

    local_bh_enable();

    return sts;
}
int kerSysSyslogSet(char *string, int strLen, int offset)
{
    int i;
    int sts = 0;
    int usedBlkSize = 0;
    char *pBuf = NULL;

    if( bootFromNand )
    {
        /* Root file system is on a writable NAND flash.  Write PSI to
         * a file on the NAND flash.
         */
        struct file *fp;
        mm_segment_t fs;

        fp = filp_open(PSI_FILE_NAME, O_RDWR | O_TRUNC | O_CREAT,
            S_IRUSR | S_IWUSR);

        if (!IS_ERR(fp) && fp->f_op && fp->f_op->write)
        {
            fs = get_fs();
            set_fs(get_ds());

            fp->f_pos = 0;

            if((int) fp->f_op->write(fp, (void *) string, strLen,
               &fp->f_pos) != strLen)
                printk("Failed to write psi to '%s'.\n", PSI_FILE_NAME);

            filp_close(fp, NULL);
            set_fs(fs);
        }
        else
            printk("Unable to open '%s'.\n", PSI_FILE_NAME);

        return 0;
    }

    if (fInfo.flash_syslog_number_blk <= 0)
    {
        printk("No syslog blks allocated, change it in CFE\n");
        return -1;
    }
    
    if (strLen > fInfo.flash_syslog_length)
        return -1;

    /*
     * The syslog does not share its blocks with anybody else, so I don't have
     * to read the flash first.  But now I have to make sure I allocate a buffer
     * big enough to cover all blocks that the syslog spans.
     */
    for (i=fInfo.flash_syslog_start_blk;
         i < (fInfo.flash_syslog_start_blk + fInfo.flash_syslog_number_blk); i++)
    {
        usedBlkSize += flash_get_sector_size((unsigned short) i);
    }

    if ((pBuf = (char *) retriedKmalloc(usedBlkSize)) == NULL)
    {
       printk("failed to allocate memory with size: %d\n", usedBlkSize);
       return -1;
    }

    memset(pBuf, 0, usedBlkSize);

    // set string to the memory buffer
    memcpy((pBuf + offset), string, strLen);

    if (setSharedBlks(fInfo.flash_syslog_start_blk, 
        (fInfo.flash_syslog_start_blk + fInfo.flash_syslog_number_blk), pBuf) != 0)
        sts = -1;

    retriedKfree(pBuf);

    return sts;
}
Beispiel #16
0
void flash_init_info(const NVRAM_DATA *nvRam, FLASH_ADDR_INFO *fInfo)
{
    int i = 0;
    int totalBlks = 0;
    int totalSize = 0;
    int psiStartAddr = 0;
    int spStartAddr = 0;
    int usedBlkSize = 0;
    int needBytes = 0;

    if (flash_get_flash_type() == FLASH_IFC_NAND)
    {
        /* When using NAND flash disable Bcm_flash */
        totalSize = 0;
    }
    else {
        totalBlks = flash_get_numsectors();
        totalSize = flash_get_total_size();
        printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
    }

    if (totalSize <= FLASH_LENGTH_BOOT_ROM) {
        /* NAND flash settings. NAND flash does not use raw flash partitioins
         * to store psi, backup psi, scratch pad and syslog.  These data items
         * are stored as files on a JFFS2 file system.
         */
        if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
            fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
        else
            fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;

        fInfo->flash_persistent_start_blk = 0;
        fInfo->flash_rootfs_start_offset = 0;
        fInfo->flash_scratch_pad_length = SP_MAX_LEN;
        fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;

        /* This is a boolean field for NAND flash. */
        fInfo->flash_backup_psi_number_blk = nvRam->backupPsi;
        return;
    }

    /*
    * calculate mandatory primary PSI size and set its fInfo parameters.
    */
    if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
        fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
    else
        fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;

    psiStartAddr = totalSize - fInfo->flash_persistent_length;
    fInfo->flash_persistent_start_blk = flash_get_blk(FLASH_BASE+psiStartAddr);
    fInfo->flash_persistent_number_blk = totalBlks - fInfo->flash_persistent_start_blk;

    usedBlkSize = 0;
    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);
    }
    fInfo->flash_persistent_blk_offset =  usedBlkSize - fInfo->flash_persistent_length;
    fInfo->flash_meta_start_blk = fInfo->flash_persistent_start_blk;

    /*
    * Next is the optional scratch pad, which is on top of the primary PSI.
    * Old code allowed scratch pad to share a sector with primary PSI.
    * That is retained for backward compatibility.  (Although depending on your
    * NOR flash sector sizes, they may still be in different sectors.)
    * If you have a new deployment, consider forcing separate sectors.
    */
    if ((fInfo->flash_persistent_blk_offset > 0) &&
            (fInfo->flash_persistent_blk_offset < SP_MAX_LEN))
    {
        /*
        * there is some room left in the first persistent sector, but it is
        * not big enough for the scratch pad. (Use this line unconditionally
        * if you want to guarentee scratch pad and primary PSI are on different
        * sectors.)
        */
        spStartAddr = psiStartAddr - fInfo->flash_persistent_blk_offset - SP_MAX_LEN;
    }
    else
    {
        /* either the primary PSI starts on a sector boundary, or there is
        * enough room at the top of the first sector for the scratch pad. */
        spStartAddr = psiStartAddr - SP_MAX_LEN ;
    }

    fInfo->flash_scratch_pad_start_blk = flash_get_blk(FLASH_BASE+spStartAddr);
    fInfo->flash_scratch_pad_length = SP_MAX_LEN;

    if (fInfo->flash_persistent_start_blk == fInfo->flash_scratch_pad_start_blk)  // share blk
    {
#if 0 /* do not used scratch pad unless it's in its own sector */
        printk("Scratch pad is not used for this flash part.\n");
        fInfo->flash_scratch_pad_length = 0;     // no sp
#else /* allow scratch pad to share a sector with another section such as PSI */
        fInfo->flash_scratch_pad_number_blk = 1;
        fInfo->flash_scratch_pad_blk_offset = fInfo->flash_persistent_blk_offset - fInfo->flash_scratch_pad_length;
#endif
    }
    else // on different blk
    {
        fInfo->flash_scratch_pad_number_blk = fInfo->flash_persistent_start_blk - fInfo->flash_scratch_pad_start_blk;
        // find out the offset in the start_blk
        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);
        fInfo->flash_scratch_pad_blk_offset =  usedBlkSize - fInfo->flash_scratch_pad_length;
    }

    if (fInfo->flash_scratch_pad_length > 0) {

        fInfo->flash_meta_start_blk = fInfo->flash_scratch_pad_start_blk;
    }

    /*
    * Next is the optional backup PSI.
    */
    if (nvRam->backupPsi == 0x01)
    {
        needBytes = fInfo->flash_persistent_length;
        i = fInfo->flash_meta_start_blk;
        while (needBytes > 0)
        {
            i--;
            needBytes -= flash_get_sector_size((unsigned short) i);
        }
        fInfo->flash_backup_psi_start_blk = i;
        /* calclate how many blocks we actually consumed */
        needBytes = fInfo->flash_persistent_length;
        fInfo->flash_backup_psi_number_blk = 0;
        while (needBytes > 0)
        {
            needBytes -= flash_get_sector_size((unsigned short) i);
            i++;
            fInfo->flash_backup_psi_number_blk++;
        }

        fInfo->flash_meta_start_blk = fInfo->flash_backup_psi_start_blk;
    }
    else
    {
        fInfo->flash_backup_psi_number_blk = 0;
    }

    /*
    * Next is the optional persistent syslog.
    */
    if (nvRam->ulSyslogSize != 0 && nvRam->ulSyslogSize != -1)
    {
        fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;
        needBytes = fInfo->flash_syslog_length;
        i = fInfo->flash_meta_start_blk;
        while (needBytes > 0)
        {
            i--;
            needBytes -= flash_get_sector_size((unsigned short) i);
        }
        fInfo->flash_syslog_start_blk = i;
        /* calclate how many blocks we actually consumed */
        needBytes = fInfo->flash_syslog_length;
        fInfo->flash_syslog_number_blk = 0;
        while (needBytes > 0)
        {
            needBytes -= flash_get_sector_size((unsigned short) i);
            i++;
            fInfo->flash_syslog_number_blk++;
        }

        fInfo->flash_meta_start_blk = fInfo->flash_syslog_start_blk;
    }
    else
    {
        fInfo->flash_syslog_length = 0;
        fInfo->flash_syslog_number_blk = 0;
    }

#ifdef DEBUG_FLASH_TOO_MUCH
    /* dump sizes of all sectors in flash */
    for (i=0; i<totalBlks; i++)
        printk("blk %03d: %d\n", i, flash_get_sector_size((unsigned short) i));
#endif

#if defined(DEBUG_FLASH)
    printk("FLASH_BASE                    =0x%08x\n\n", (unsigned int)FLASH_BASE);

    printk("fInfo->flash_rootfs_start_offset =0x%08x\n\n", (unsigned int)fInfo->flash_rootfs_start_offset);

    printk("fInfo->flash_meta_start_blk = %d\n\n", fInfo->flash_meta_start_blk);

    printk("fInfo->flash_syslog_start_blk  = %d\n", fInfo->flash_syslog_start_blk);
    printk("fInfo->flash_syslog_number_blk = %d\n", fInfo->flash_syslog_number_blk);
    printk("fInfo->flash_syslog_length=0x%x\n\n", (unsigned int)fInfo->flash_syslog_length);

    printk("fInfo->flash_backup_psi_start_blk = %d\n", fInfo->flash_backup_psi_start_blk);
    printk("fInfo->flash_backup_psi_number_blk = %d\n\n", fInfo->flash_backup_psi_number_blk);

    printk("sp startAddr = %x\n", (unsigned int) (FLASH_BASE+spStartAddr));
    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);
    printk("fInfo->flash_scratch_pad_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_scratch_pad_blk_offset);

    printk("psi startAddr = %x\n", (unsigned int) (FLASH_BASE+psiStartAddr));
    printk("fInfo->flash_persistent_start_blk = %d\n", fInfo->flash_persistent_start_blk);
    printk("fInfo->flash_persistent_number_blk = %d\n", fInfo->flash_persistent_number_blk);
    printk("fInfo->flash_persistent_length=0x%x\n", (unsigned int)fInfo->flash_persistent_length);
    printk("fInfo->flash_persistent_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_persistent_blk_offset);
#endif
}