From 1c9cc63994e8622b0f20d6bfee60a97472496719 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 1 May 2024 09:59:43 -0500 Subject: [PATCH] Adopted crc32c xor trick to avoid masking valid bits Turns out these are equivalent: cksum' = crc32c([d & ~0x80], cksum) cksum' = crc32c([d], cksum ^ (d & 0x80)) Which is quite nice. The second form is a bit cheaper and works better in situations where you may have an immutable buffer. I took the long way to find this and may or may not have brute forced an xor mask for the valid bit: crc32c(62 95 e3 fd 00) => c7844d4d crc32c(00 00 00 00 80) => c7844d4d But this is equivalent to 00000080 after xoring in the init junk. If you look at the naive lfs_crc32c impl, the first step is to xor the first byte, so really xoring any byte will cancel it out of our crc32c. Code changes, thought this would save more because we can reuse bd checksumming a bit better... Oh well, at least the theory works: code stack before: 33916 2824 after: 33908 (-0.0%) 2824 (+0.0%) --- lfs.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lfs.c b/lfs.c index 8c316fe7..e9399407 100644 --- a/lfs.c +++ b/lfs.c @@ -1087,9 +1087,10 @@ static lfs_ssize_t lfsr_bd_readtag_(lfs_t *lfs, LFS_ASSERT(size <= 0x0fffffff); d += d_; - // ignore the valid bit when calculating optional checksum - tag_buf[0] &= ~0x80; + // optional checksum if (cksum_) { + // ignore the valid bit when calculating checksums + *cksum_ ^= tag_buf[0] & 0x80; *cksum_ = lfs_crc32c(*cksum_, tag_buf, d); } @@ -1146,19 +1147,17 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, } d += d_; + // ignore the valid bit when calculating checksums + if (cksum_) { + *cksum_ ^= tag_buf[0] & 0x80; + } int err = lfsr_bd_prog(lfs, block, off, &tag_buf, d, - NULL); + cksum_); if (err) { LFS_ASSERT(err < 0); return err; } - // ignore the valid bit when calculating optional checksum - tag_buf[0] &= ~0x80; - if (cksum_) { - *cksum_ = lfs_crc32c(*cksum_, tag_buf, d); - } - return d; }