int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset, FAR uint16_t *datlen) { struct nxffs_data_s blkhdr; uint32_t ecrc; uint32_t crc; uint16_t doffset; uint16_t dlen; int ret; /* Make sure that the block containing the data block header is in the cache */ nxffs_ioseek(volume, offset); ret = nxffs_rdcache(volume, volume->ioblock); if (ret < 0) { fdbg("ERROR: Failed to read data into cache: %d\n", ret); return ret; } /* Read the header at the FLASH offset */ doffset = volume->iooffset; memcpy(&blkhdr, &volume->cache[doffset], SIZEOF_NXFFS_DATA_HDR); /* Extract the data length */ dlen = nxffs_rdle16(blkhdr.datlen); /* Get the offset to the beginning of the data */ doffset += SIZEOF_NXFFS_DATA_HDR; /* Make sure that all of the data fits within the block */ if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize) { fdbg("ERROR: Data length=%d is unreasonable at offset=%d\n", dlen, doffset); return -EIO; } /* Extract the expected CRC and calculate the CRC of the data block */ ecrc = nxffs_rdle32(blkhdr.crc); nxffs_wrle32(blkhdr.crc, 0); crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR); crc = crc32part(&volume->cache[doffset], dlen, crc); if (crc != ecrc) { fdbg("ERROR: CRC failure\n"); return -EIO; } /* Looks good! Return the data length and success */ *datlen = dlen; return OK; }
static inline ssize_t nxffs_analyzedata(FAR struct nxffs_blkinfo_s *blkinfo, int offset) { struct nxffs_data_s dathdr; uint32_t ecrc; uint16_t datlen; uint32_t crc; /* Copy and unpack the data block header */ memcpy(&dathdr, &blkinfo->buffer[offset], SIZEOF_NXFFS_DATA_HDR); ecrc = nxffs_rdle32(dathdr.crc); datlen = nxffs_rdle16(dathdr.datlen); /* Sanity checks */ if (offset + SIZEOF_NXFFS_DATA_HDR + datlen > blkinfo->geo.blocksize) { /* Data does not fit in within the block, this can't be a data block */ return ERROR; } /* Calculate the CRC */ nxffs_wrle32(dathdr.crc, 0); crc = crc32((FAR const uint8_t *)&dathdr, SIZEOF_NXFFS_DATA_HDR); crc = crc32part(&blkinfo->buffer[offset + SIZEOF_NXFFS_DATA_HDR], datlen, crc); if (crc != ecrc) { syslog(LOG_NOTICE, g_format, blkinfo->block, offset, "DATA ", "CRC BAD", datlen); return ERROR; } /* If must be a good header */ if (blkinfo->verbose) { syslog(LOG_NOTICE, g_format, blkinfo->block, offset, "DATA ", "OK ", datlen); } return SIZEOF_NXFFS_DATA_HDR + datlen; }