From ad00ca79e26bca6b7c32372f4ace771966bacab1 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 20 Dec 2022 18:59:39 -0600 Subject: [PATCH] Added dbgrbyd.py script, fixed some small things in rbyd commit - We need to actually write the perturb bit - It helps to encode the crc's leb128 length field correctly --- lfs.c | 4 +- scripts/dbgrbyd.py | 225 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 2 deletions(-) create mode 100755 scripts/dbgrbyd.py diff --git a/lfs.c b/lfs.c index 74225e1e..d9875f36 100644 --- a/lfs.c +++ b/lfs.c @@ -1424,13 +1424,13 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, // get around this catch-22 we just always write a fully-expanded leb128 // encoding uint8_t buffer[1+5+4]; - buffer[0] = LFS_MKRTAG(CRC0, 0, 0) << 1; + buffer[0] = (LFS_MKRTAG(CRC0, 0, 0) << 1) | (lfs_popc(crc) & 1); lfs_off_t padding = aligned - (off + 1+5); buffer[1] = 0x80 | (0x7f & (padding >> 0)); buffer[2] = 0x80 | (0x7f & (padding >> 7)); buffer[3] = 0x80 | (0x7f & (padding >> 14)); - buffer[4] = 0x00 | (0x7f & (padding >> 21)); + buffer[4] = 0x80 | (0x7f & (padding >> 21)); buffer[5] = 0x00 | (0x7f & (padding >> 28)); crc = lfs_crc32c(crc, buffer, 1+5); diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py new file mode 100755 index 00000000..dcb48464 --- /dev/null +++ b/scripts/dbgrbyd.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 + +import itertools as it +import math as m +import struct + + +def crc32c(data, crc=0): + crc ^= 0xffffffff + for b in data: + crc ^= b + for j in range(8): + crc = (crc >> 1) ^ ((crc & 1) * 0x82f63b78) + return 0xffffffff ^ crc + +def fromleb128(data): + word = 0 + for i, b in enumerate(data): + word |= ((b & 0x7f) << 7*i) + word &= 0xffffffff + if not b & 0x80: + return word, i+1 + return word, len(data) + +def fromtag(data): + tag, delta1 = fromleb128(data) + size, delta2 = fromleb128(data[delta1:]) + return tag & 1, tag >> 1, size, delta1+delta2 + +def popc(x): + return bin(x).count('1') + +def xxd(data, width=16, crc=False): + for i in range(0, len(data), width): + yield '%-*s %-*s' % ( + 3*width, + ' '.join('%02x' % b for b in data[i:i+width]), + width, + ''.join( + b if b >= ' ' and b <= '~' else '.' + for b in map(chr, data[i:i+width]))) + +def tagrepr(tag, size, off=None): + type1 = tag & 0x7f + type2 = (tag >> 7) & 0xff + id = (tag >> 15) & 0xffff + + if type1 & 1: + return 'alt %s %s x%x %s' % ( + 'r' if type1 & 4 else 'b', + 'gt' if type1 & 2 else 'lt', + tag >> 3, + 'x%x' % (0xffffffff & (off-size)) + if off is not None + else '-%d' % off) + elif type1 == 0x40: + return 'create x%02x id%d %d' % (type2, id, size) + elif type1 == 0x48: + return 'delete x%02x id%d %d' % (type2, id, size) + elif type1 == 0x50: + return 'struct x%02x id%d %d' % (type2, id, size) + elif type1 == 0x60: + return 'uattr x%02x id%d %d' % (type2, id, size) + elif type1 == 0x08: + if type2 == 0: + return 'tail %d' % size + else: + return 'tail x%02x %d' % (type2, size) + elif type1 == 0x10: + return 'gstate x%02x %d' % (type2, size) + elif type1 == 0x02 or type1 == 0x0a: + if type2 == 0: + return 'crc%x %d' % (type1 >> 3, size) + else: + return 'crc%x x%02x %d' % (type1 >> 3, type2, size) + elif type1 == 0x12: + if type2 == 0: + return 'fcrc %d' % (size) + else: + return 'fcrc x%02x %d' % (type2, size) + else: + return 'x%02x x%02x id%d %d' % (type1, type2, id, size) + + +def main(disk, block_size, block1, block2=None, **args): + # read each block + blocks = [block for block in [block1, block2] if block is not None] + with open(disk, 'rb') as f: + datas = [] + for block in blocks: + f.seek(block * block_size) + datas.append(f.read(block_size)) + + # first figure out which block as the most recent revision + def fetch(data): + rev, = struct.unpack('