summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-03-30 18:15:49 +0100
committerAidan MacDonald <amachronic@protonmail.com>2022-09-19 15:09:51 -0400
commitdcc4e54b77b3122e8772d45830a5879f0cd3022b (patch)
tree9233bb3229834d5da9b5da881a338d5a99ca1abe
parentf82f3044a7fc0fd31e824f29ce3b48377fb80af4 (diff)
downloadrockbox-dcc4e54b77.tar.gz
rockbox-dcc4e54b77.zip
buflib: refactor CRC checks as paranoia
Move CRC checking and updating behind a paranoia bit, like the other checks, so it can be enabled and disabled. Change-Id: Icff66c842cbd5af2d99aa91e6c40447a64e6d4b2
-rw-r--r--firmware/buflib.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/firmware/buflib.c b/firmware/buflib.c
index 6734f21036..6ddd96e7df 100644
--- a/firmware/buflib.c
+++ b/firmware/buflib.c
@@ -101,6 +101,7 @@
#define PARANOIA_CHECK_LENGTH (1 << 0)
#define PARANOIA_CHECK_HANDLE (1 << 1)
#define PARANOIA_CHECK_BLOCK_HANDLE (1 << 2)
+#define PARANOIA_CHECK_CRC (1 << 3)
/* Bitmask of enabled paranoia checks */
#define BUFLIB_PARANOIA 0
@@ -166,6 +167,16 @@ static void check_handle(struct buflib_context *ctx,
static void check_block_handle(struct buflib_context *ctx,
union buflib_data *block);
+/* Update the block's CRC checksum if CRCs are enabled. */
+static void update_block_crc(struct buflib_context *ctx,
+ union buflib_data *block,
+ union buflib_data *block_end);
+
+/* Check the block's CRC if CRCs are enabled. */
+static void check_block_crc(struct buflib_context *ctx,
+ union buflib_data *block,
+ union buflib_data *block_end);
+
/* Initialize buffer manager */
void
buflib_init(struct buflib_context *ctx, void *buf, size_t size)
@@ -334,14 +345,6 @@ static inline bool handle_table_shrink(struct buflib_context *ctx)
return handle != old_last;
}
-static uint32_t calc_block_crc(union buflib_data *block,
- union buflib_data *block_end)
-{
- union buflib_data *crc_slot = &block_end[-bidx_CRC];
- const size_t size = (crc_slot - block) * sizeof(*block);
- return crc_32(block, size, 0xffffffff);
-}
-
/* If shift is non-zero, it represents the number of places to move
* blocks in memory. Calculate the new address for this block,
* update its entry in the handle table, and then move its contents.
@@ -358,11 +361,7 @@ move_block(struct buflib_context* ctx, union buflib_data* block, int shift)
check_block_handle(ctx, block);
union buflib_data *h_entry = block[fidx_HANDLE].handle;
union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry);
-
- uint32_t crc = calc_block_crc(block, block_end);
- if (crc != block_end[-bidx_CRC].crc)
- buflib_panic(ctx, "buflib metadata corrupted, crc: 0x%08x, expected: 0x%08x",
- (unsigned int)crc, (unsigned int)block_end[-bidx_CRC].crc);
+ check_block_crc(ctx, block, block_end);
if (!IS_MOVABLE(block))
return false;
@@ -722,13 +721,12 @@ buffer_alloc:
size_t bsize = BUFLIB_NUM_FIELDS + name_len/sizeof(union buflib_data);
union buflib_data *block_end = block + bsize;
block_end[-bidx_BSIZE].val = bsize;
- block_end[-bidx_CRC].crc = calc_block_crc(block, block_end);
+ update_block_crc(ctx, block, block_end);
handle->alloc = (char*)&block_end[-bidx_USER];
- BDEBUGF("buflib_alloc_ex: size=%d handle=%p clb=%p crc=0x%0x name=\"%s\"\n",
- (unsigned int)size, (void *)handle, (void *)ops,
- (unsigned int)block_end[-bidx_CRC].crc, name ? name : "");
+ BDEBUGF("buflib_alloc_ex: size=%d handle=%p clb=%p name=\"%s\"\n",
+ (unsigned int)size, (void *)handle, (void *)ops, name ? name : "");
block += size;
/* alloc_end must be kept current if we're taking the last block. */
@@ -1000,7 +998,7 @@ buflib_shrink(struct buflib_context* ctx, int handle, void* new_start, size_t ne
/* update crc of the metadata */
union buflib_data *new_h_entry = new_block[fidx_HANDLE].handle;
union buflib_data *new_block_end = h_entry_to_block_end(ctx, new_h_entry);
- new_block_end[-bidx_CRC].crc = calc_block_crc(new_block, new_block_end);
+ update_block_crc(ctx, new_block, new_block_end);
/* Now deal with size changes that create free blocks after the allocation */
if (old_next_block != new_next_block)
@@ -1055,12 +1053,7 @@ void buflib_check_valid(struct buflib_context *ctx)
check_block_handle(ctx, block);
union buflib_data *h_entry = block[fidx_HANDLE].handle;
union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry);
- uint32_t crc = calc_block_crc(block, block_end);
- if (crc != block_end[-bidx_CRC].crc)
- {
- buflib_panic(ctx, "crc mismatch: 0x%08x, expected: 0x%08x",
- (unsigned int)crc, (unsigned int)block_end[-bidx_CRC].crc);
- }
+ check_block_crc(ctx, block, block_end);
}
}
#endif
@@ -1217,3 +1210,40 @@ static void check_block_handle(struct buflib_context *ctx,
}
}
}
+
+static uint32_t calc_block_crc(union buflib_data *block,
+ union buflib_data *block_end)
+{
+ union buflib_data *crc_slot = &block_end[-bidx_CRC];
+ const size_t size = (crc_slot - block) * sizeof(*block);
+ return crc_32(block, size, 0xffffffff);
+}
+
+static void update_block_crc(struct buflib_context *ctx,
+ union buflib_data *block,
+ union buflib_data *block_end)
+{
+ (void)ctx;
+
+ if (BUFLIB_PARANOIA & PARANOIA_CHECK_CRC)
+ {
+ block_end[-bidx_CRC].crc = calc_block_crc(block, block_end);
+ }
+}
+
+static void check_block_crc(struct buflib_context *ctx,
+ union buflib_data *block,
+ union buflib_data *block_end)
+{
+ if (BUFLIB_PARANOIA & PARANOIA_CHECK_CRC)
+ {
+ uint32_t crc = calc_block_crc(block, block_end);
+ if (block_end[-bidx_CRC].crc != crc)
+ {
+ buflib_panic(ctx, "buflib crc mismatch [%p]=%08lx, got %08lx",
+ &block_end[-bidx_CRC],
+ (unsigned long)block_end[-bidx_CRC].crc,
+ (unsigned long)crc);
+ }
+ }
+}