summaryrefslogtreecommitdiff
path: root/firmware/buflib.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/buflib.c')
-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 @@
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,
166static void check_block_handle(struct buflib_context *ctx, 167static 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. */
171static 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. */
176static 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 */
170void 181void
171buflib_init(struct buflib_context *ctx, void *buf, size_t size) 182buflib_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
337static 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
1214static 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
1222static 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
1234static 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}