示例#1
0
static int nxffs_badblocks(FAR struct nxffs_volume_s *volume)
{
  FAR uint8_t *blkptr;   /* Pointer to next block data */
  off_t eblock;          /* Erase block number */
  off_t lblock;          /* Logical block number */
  ssize_t nxfrd;         /* Number of blocks transferred */
  bool good;             /* TRUE: block is good */
  bool modified;         /* TRUE: The erase block has been modified */
  int i;

  /* Read and verify each erase block */

  for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++)
    {
      /* Read the entire erase block */

      lblock = eblock * volume->blkper;
      nxfrd  = MTD_BREAD(volume->mtd, lblock, volume->blkper, volume->pack);
      if (nxfrd != volume->blkper)
        {
          fdbg("Read erase block %d failed: %d\n", lblock, nxfrd);
          return -EIO;
        }

      /* Process each logical block */

      modified = false;
      for (blkptr = volume->pack, i = 0;
           i < volume->blkper;
           blkptr += volume->geo.blocksize, i++)
        {
          FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr;

          /* Check block header */

          good = true;
          if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0 ||
              blkhdr->state != BLOCK_STATE_GOOD)
            {
              good = false;
            }

          /* Check that block data is erased */

          else
            {
              size_t blocksize = volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR;
              size_t erasesize = nxffs_erased(&blkptr[SIZEOF_NXFFS_BLOCK_HDR], blocksize);
              good = (blocksize == erasesize);
            }

          /* If the block is bad, attempt to re-write the block header indicating
           * a bad block (of course, if the block has failed, this may not be
           * possible, depending upon failure modes.
           */

          if (!good)
            {
              memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE);
              blkhdr->state = BLOCK_STATE_BAD;
              modified = true;
            }
        }

      /* If the erase block was modified, then re-write it */

      if (modified)
        {
          nxfrd = MTD_BWRITE(volume->mtd, lblock, volume->blkper, volume->pack);
          if (nxfrd != volume->blkper)
            {
              fdbg("Write erase block %d failed: %d\n", lblock, nxfrd);
              return -EIO;
            }
        }
    }

  return OK;
}
示例#2
0
static inline void nxffs_analyze(FAR struct nxffs_blkinfo_s *blkinfo)
{
  FAR struct nxffs_block_s *blkhdr;
  ssize_t nbytes;
  int hdrndx;
  int datndx;
  int inndx;
  int i;

  /* Verify that there is a header on the block */

  blkhdr = (FAR struct nxffs_block_s *)blkinfo->buffer;
  if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0)
    {
      fdbg(g_format, blkinfo->block, 0, "BLOCK", "NO FRMT",
           blkinfo->geo.blocksize);
    }
  else if (blkhdr->state == BLOCK_STATE_GOOD)
    {
      size_t datsize = blkinfo->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR;
      size_t nerased = nxffs_erased(blkinfo->buffer + SIZEOF_NXFFS_BLOCK_HDR, datsize);
      if (nerased == datsize)
        {
          if (blkinfo->verbose)
            {
              fdbg(g_format, blkinfo->block, 0, "BLOCK", "ERASED ",
                   blkinfo->geo.blocksize);
            }
          return;
        }
#if 0 /* Too much output, to little information */
      else
        {
          fdbg(g_format, blkinfo->block, 0, "BLOCK", "IN USE ",
               blkinfo->geo.blocksize);
        }
#endif
    }
  else if (blkhdr->state == BLOCK_STATE_BAD)
    {
      fdbg(g_format, blkinfo->block, 0, "BLOCK", "BAD    ",
           blkinfo->geo.blocksize);
    }
  else
    {
      fdbg(g_format, blkinfo->block, 0, "BLOCK", "CORRUPT",
           blkinfo->geo.blocksize);
    }

  /* Serach for Inode and data block headers.  */

  inndx = 0;
  datndx = 0;

  for (i = SIZEOF_NXFFS_BLOCK_HDR; i < blkinfo->geo.blocksize; i++)
    {
      uint8_t ch = blkinfo->buffer[i];

      if (ch == g_inodemagic[inndx])
        {
          inndx++;
          datndx = 0;

          if (inndx == NXFFS_MAGICSIZE)
            {
              hdrndx = i - NXFFS_MAGICSIZE + 1;
              nbytes = nxffs_analyzeinode(blkinfo, hdrndx);
              if (nbytes > 0)
                {
                  i = hdrndx + nbytes - 1;
                }
              inndx = 0;
            }
        }
      else if (ch == g_datamagic[datndx])
        {
          datndx++;
          inndx = 0;

          if (datndx == NXFFS_MAGICSIZE)
            {
              hdrndx = i - NXFFS_MAGICSIZE + 1;
              nbytes = nxffs_analyzedata(blkinfo, hdrndx);
              if (nbytes > 0)
                {
                  i = hdrndx + nbytes - 1;
                }
              datndx = 0;
            }
        }
    }

}
static inline ssize_t nxffs_wrappend(FAR struct nxffs_volume_s *volume,
                                     FAR struct nxffs_wrfile_s *wrfile,
                                     FAR const char *buffer, size_t buflen)
{
  ssize_t maxsize;
  size_t nbytestowrite;
  ssize_t nbytesleft;
  off_t offset;
  int ret;

  /* Get the offset to the start of unwritten data */

  offset = volume->iooffset + wrfile->datlen + SIZEOF_NXFFS_DATA_HDR;

  /* Determine that maximum amount of data that can be written to this
   * block.
   */

  maxsize = volume->geo.blocksize - offset;
  DEBUGASSERT(maxsize > 0);

  /* But don't try to write over any unerased bytes */

  maxsize = nxffs_erased(&volume->cache[offset], maxsize);

  /* Write as many bytes as we can into the data buffer */

  nbytestowrite = MIN(maxsize, buflen);
  nbytesleft    = maxsize - nbytestowrite;

  if (nbytestowrite > 0)
    {
      /* Copy the data into the volume write cache */

      memcpy(&volume->cache[offset], buffer, nbytestowrite);

      /* Increment the number of bytes written to the data block */

      wrfile->datlen += nbytestowrite;

      /* Re-calculate the CRC */

      offset = volume->iooffset + SIZEOF_NXFFS_DATA_HDR;
      wrfile->crc = crc32(&volume->cache[offset], wrfile->datlen);

      /* And write the partial write block to FLASH -- unless the data
       * block is full.  In that case, the block will be written below.
       */

      if (nbytesleft > 0)
        {
          ret = nxffs_wrcache(volume);
          if (ret < 0)
            {
              fdbg("ERROR: nxffs_wrcache failed: %d\n", -ret);
              return ret;
            }
        }
    }

  /* Check if the data block is now full */

  if (nbytesleft <= 0)
    {
      /* The data block is full, write the block to FLASH */

      ret = nxffs_wrblkhdr(volume, wrfile);
      if (ret < 0)
        {
          fdbg("ERROR: nxffs_wrblkdhr failed: %d\n", -ret);
          return ret;
        }
    }

  /* Return the number of bytes written to FLASH this time */

  return nbytestowrite;
}