BcmProgramHeader * kerSysImageTagGet(void) { extern int get_part_offset(void); static unsigned char pgmHdr1[sizeof(BcmProgramHeader)]; /* for image 1 */ int sect; unsigned int fromaddr; #if defined(CONFIG_BCM_RAMDISK) memcpy(&pgmHdr1[0], (void *)0x87A00000, sizeof(BcmProgramHeader)); #else /* Get flash offset from which Linux image starts */ fromaddr = get_part_offset(); /* Conver to sector */ fromaddr += FLASH_BASE; sect = flash_get_blk((int) fromaddr); flash_read_buf( sect, 0, &pgmHdr1[0], sizeof(BcmProgramHeader) ); #endif #if 0 for(sect = 0; sect < sizeof(BcmProgramHeader); sect+=4) { printk("%08lx\n", *(unsigned long *)(pgmHdr1 + 4 * sect)); } printk("\n\n"); for(sect = 0; sect < sizeof(BcmProgramHeader); sect+=4) { printk("%08lx\n", *(unsigned long *)(0xBFC20000 + 4 * sect)); } #endif return (BcmProgramHeader *)pgmHdr1; }
unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr, unsigned long len ) { int sect = flash_get_blk((int) fromaddr); unsigned char *start = flash_get_memptr(sect); flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len ); return( len ); }
BcmProgramHeader * kerAppImageTagGet(void) { static unsigned char pgmHdr1[sizeof(BcmProgramHeader)]; int sect; unsigned int fromaddr; fromaddr = FLASH_BASE + 0x1000000; sect = flash_get_blk((int) fromaddr); flash_read_buf( sect, 0, &pgmHdr1[0], sizeof(BcmProgramHeader) ); return (BcmProgramHeader *)pgmHdr1; }
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; }
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 }