diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2022-03-30 18:15:49 +0100 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2022-09-19 15:09:51 -0400 |
commit | dcc4e54b77b3122e8772d45830a5879f0cd3022b (patch) | |
tree | 9233bb3229834d5da9b5da881a338d5a99ca1abe | |
parent | f82f3044a7fc0fd31e824f29ce3b48377fb80af4 (diff) | |
download | rockbox-dcc4e54b77b3122e8772d45830a5879f0cd3022b.tar.gz rockbox-dcc4e54b77b3122e8772d45830a5879f0cd3022b.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.c | 78 |
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 @@ | |||
101 | #define PARANOIA_CHECK_LENGTH (1 << 0) | 101 | #define PARANOIA_CHECK_LENGTH (1 << 0) |
102 | #define PARANOIA_CHECK_HANDLE (1 << 1) | 102 | #define PARANOIA_CHECK_HANDLE (1 << 1) |
103 | #define PARANOIA_CHECK_BLOCK_HANDLE (1 << 2) | 103 | #define PARANOIA_CHECK_BLOCK_HANDLE (1 << 2) |
104 | #define PARANOIA_CHECK_CRC (1 << 3) | ||
104 | /* Bitmask of enabled paranoia checks */ | 105 | /* Bitmask of enabled paranoia checks */ |
105 | #define BUFLIB_PARANOIA 0 | 106 | #define BUFLIB_PARANOIA 0 |
106 | 107 | ||
@@ -166,6 +167,16 @@ static void check_handle(struct buflib_context *ctx, | |||
166 | static void check_block_handle(struct buflib_context *ctx, | 167 | static void check_block_handle(struct buflib_context *ctx, |
167 | union buflib_data *block); | 168 | union buflib_data *block); |
168 | 169 | ||
170 | /* Update the block's CRC checksum if CRCs are enabled. */ | ||
171 | static void update_block_crc(struct buflib_context *ctx, | ||
172 | union buflib_data *block, | ||
173 | union buflib_data *block_end); | ||
174 | |||
175 | /* Check the block's CRC if CRCs are enabled. */ | ||
176 | static void check_block_crc(struct buflib_context *ctx, | ||
177 | union buflib_data *block, | ||
178 | union buflib_data *block_end); | ||
179 | |||
169 | /* Initialize buffer manager */ | 180 | /* Initialize buffer manager */ |
170 | void | 181 | void |
171 | buflib_init(struct buflib_context *ctx, void *buf, size_t size) | 182 | 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) | |||
334 | return handle != old_last; | 345 | return handle != old_last; |
335 | } | 346 | } |
336 | 347 | ||
337 | static uint32_t calc_block_crc(union buflib_data *block, | ||
338 | union buflib_data *block_end) | ||
339 | { | ||
340 | union buflib_data *crc_slot = &block_end[-bidx_CRC]; | ||
341 | const size_t size = (crc_slot - block) * sizeof(*block); | ||
342 | return crc_32(block, size, 0xffffffff); | ||
343 | } | ||
344 | |||
345 | /* If shift is non-zero, it represents the number of places to move | 348 | /* If shift is non-zero, it represents the number of places to move |
346 | * blocks in memory. Calculate the new address for this block, | 349 | * blocks in memory. Calculate the new address for this block, |
347 | * update its entry in the handle table, and then move its contents. | 350 | * 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) | |||
358 | check_block_handle(ctx, block); | 361 | check_block_handle(ctx, block); |
359 | union buflib_data *h_entry = block[fidx_HANDLE].handle; | 362 | union buflib_data *h_entry = block[fidx_HANDLE].handle; |
360 | union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry); | 363 | union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry); |
361 | 364 | check_block_crc(ctx, block, block_end); | |
362 | uint32_t crc = calc_block_crc(block, block_end); | ||
363 | if (crc != block_end[-bidx_CRC].crc) | ||
364 | buflib_panic(ctx, "buflib metadata corrupted, crc: 0x%08x, expected: 0x%08x", | ||
365 | (unsigned int)crc, (unsigned int)block_end[-bidx_CRC].crc); | ||
366 | 365 | ||
367 | if (!IS_MOVABLE(block)) | 366 | if (!IS_MOVABLE(block)) |
368 | return false; | 367 | return false; |
@@ -722,13 +721,12 @@ buffer_alloc: | |||
722 | size_t bsize = BUFLIB_NUM_FIELDS + name_len/sizeof(union buflib_data); | 721 | size_t bsize = BUFLIB_NUM_FIELDS + name_len/sizeof(union buflib_data); |
723 | union buflib_data *block_end = block + bsize; | 722 | union buflib_data *block_end = block + bsize; |
724 | block_end[-bidx_BSIZE].val = bsize; | 723 | block_end[-bidx_BSIZE].val = bsize; |
725 | block_end[-bidx_CRC].crc = calc_block_crc(block, block_end); | 724 | update_block_crc(ctx, block, block_end); |
726 | 725 | ||
727 | handle->alloc = (char*)&block_end[-bidx_USER]; | 726 | handle->alloc = (char*)&block_end[-bidx_USER]; |
728 | 727 | ||
729 | BDEBUGF("buflib_alloc_ex: size=%d handle=%p clb=%p crc=0x%0x name=\"%s\"\n", | 728 | BDEBUGF("buflib_alloc_ex: size=%d handle=%p clb=%p name=\"%s\"\n", |
730 | (unsigned int)size, (void *)handle, (void *)ops, | 729 | (unsigned int)size, (void *)handle, (void *)ops, name ? name : ""); |
731 | (unsigned int)block_end[-bidx_CRC].crc, name ? name : ""); | ||
732 | 730 | ||
733 | block += size; | 731 | block += size; |
734 | /* alloc_end must be kept current if we're taking the last block. */ | 732 | /* 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 | |||
1000 | /* update crc of the metadata */ | 998 | /* update crc of the metadata */ |
1001 | union buflib_data *new_h_entry = new_block[fidx_HANDLE].handle; | 999 | union buflib_data *new_h_entry = new_block[fidx_HANDLE].handle; |
1002 | union buflib_data *new_block_end = h_entry_to_block_end(ctx, new_h_entry); | 1000 | union buflib_data *new_block_end = h_entry_to_block_end(ctx, new_h_entry); |
1003 | new_block_end[-bidx_CRC].crc = calc_block_crc(new_block, new_block_end); | 1001 | update_block_crc(ctx, new_block, new_block_end); |
1004 | 1002 | ||
1005 | /* Now deal with size changes that create free blocks after the allocation */ | 1003 | /* Now deal with size changes that create free blocks after the allocation */ |
1006 | if (old_next_block != new_next_block) | 1004 | if (old_next_block != new_next_block) |
@@ -1055,12 +1053,7 @@ void buflib_check_valid(struct buflib_context *ctx) | |||
1055 | check_block_handle(ctx, block); | 1053 | check_block_handle(ctx, block); |
1056 | union buflib_data *h_entry = block[fidx_HANDLE].handle; | 1054 | union buflib_data *h_entry = block[fidx_HANDLE].handle; |
1057 | union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry); | 1055 | union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry); |
1058 | uint32_t crc = calc_block_crc(block, block_end); | 1056 | check_block_crc(ctx, block, block_end); |
1059 | if (crc != block_end[-bidx_CRC].crc) | ||
1060 | { | ||
1061 | buflib_panic(ctx, "crc mismatch: 0x%08x, expected: 0x%08x", | ||
1062 | (unsigned int)crc, (unsigned int)block_end[-bidx_CRC].crc); | ||
1063 | } | ||
1064 | } | 1057 | } |
1065 | } | 1058 | } |
1066 | #endif | 1059 | #endif |
@@ -1217,3 +1210,40 @@ static void check_block_handle(struct buflib_context *ctx, | |||
1217 | } | 1210 | } |
1218 | } | 1211 | } |
1219 | } | 1212 | } |
1213 | |||
1214 | static uint32_t calc_block_crc(union buflib_data *block, | ||
1215 | union buflib_data *block_end) | ||
1216 | { | ||
1217 | union buflib_data *crc_slot = &block_end[-bidx_CRC]; | ||
1218 | const size_t size = (crc_slot - block) * sizeof(*block); | ||
1219 | return crc_32(block, size, 0xffffffff); | ||
1220 | } | ||
1221 | |||
1222 | static void update_block_crc(struct buflib_context *ctx, | ||
1223 | union buflib_data *block, | ||
1224 | union buflib_data *block_end) | ||
1225 | { | ||
1226 | (void)ctx; | ||
1227 | |||
1228 | if (BUFLIB_PARANOIA & PARANOIA_CHECK_CRC) | ||
1229 | { | ||
1230 | block_end[-bidx_CRC].crc = calc_block_crc(block, block_end); | ||
1231 | } | ||
1232 | } | ||
1233 | |||
1234 | static void check_block_crc(struct buflib_context *ctx, | ||
1235 | union buflib_data *block, | ||
1236 | union buflib_data *block_end) | ||
1237 | { | ||
1238 | if (BUFLIB_PARANOIA & PARANOIA_CHECK_CRC) | ||
1239 | { | ||
1240 | uint32_t crc = calc_block_crc(block, block_end); | ||
1241 | if (block_end[-bidx_CRC].crc != crc) | ||
1242 | { | ||
1243 | buflib_panic(ctx, "buflib crc mismatch [%p]=%08lx, got %08lx", | ||
1244 | &block_end[-bidx_CRC], | ||
1245 | (unsigned long)block_end[-bidx_CRC].crc, | ||
1246 | (unsigned long)crc); | ||
1247 | } | ||
1248 | } | ||
1249 | } | ||