Repository navigation
Expand file tree
/
Copy pathprobe.py
More file actions
executable file
·113 lines (94 loc) · 4.19 KB
/
Copy pathprobe.py
File metadata and controls
executable file
·113 lines (94 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
import sys
import argparse
import os
def detect_spare_type(file_size):
if file_size in (17301504, 69206016):
return 512, 16
elif file_size in (67108864, 268435456, 536870912):
return 0, 0
elif file_size in (276824064, 553648128):
return 2048, 64
return 0, 0
def read_logical_bytes(file_path, logical_offset, length, data_page_size, spare_page_size):
with open(file_path, 'rb') as f:
if data_page_size == 0 or spare_page_size == 0:
f.seek(logical_offset)
return f.read(length), logical_offset
full_page_size = data_page_size + spare_page_size
out = bytearray()
cur_logical = logical_offset
first_phys_offset = None
while len(out) < length:
page_index = cur_logical // data_page_size
page_offset = cur_logical % data_page_size
phys_offset = page_index * full_page_size + page_offset
if first_phys_offset is None:
first_phys_offset = phys_offset
bytes_in_this_page = min(length - len(out), data_page_size - page_offset)
f.seek(phys_offset)
chunk = f.read(bytes_in_this_page)
if not chunk:
break
out.extend(chunk)
cur_logical += len(chunk)
return bytes(out), first_phys_offset
def parse_int(val):
if isinstance(val, str):
val = val.strip()
if val.lower().startswith('0x'):
return int(val, 16)
return int(val)
return int(val)
def main():
parser = argparse.ArgumentParser(description="Read value at logical offset excluding spare data")
parser.add_argument("file", help="Path to input NAND / binary file")
parser.add_argument("offset", help="Logical offset (hex like 0x3B1 or decimal)")
parser.add_argument("length", nargs="?", default="1", help="Number of bytes to read (default: 1)")
parser.add_argument("--page", type=str, default=None, help="Data page size (default: auto-detected, 512 for small block)")
parser.add_argument("--spare", type=str, default=None, help="Spare size per page (default: auto-detected, 16 for small block)")
args = parser.parse_args()
if not os.path.exists(args.file):
print(f"Error: File not found: {args.file}", file=sys.stderr)
sys.exit(1)
file_size = os.path.getsize(args.file)
logical_offset = parse_int(args.offset)
length = parse_int(args.length)
if args.page is not None and args.spare is not None:
data_page = parse_int(args.page)
spare_size = parse_int(args.spare)
else:
data_page, spare_size = detect_spare_type(file_size)
data, phys_offset = read_logical_bytes(args.file, logical_offset, length, data_page, spare_size)
if not data:
print("Error: Could not read data (EOF or invalid offset)", file=sys.stderr)
sys.exit(1)
hex_str = data.hex()
print(f"File: {args.file}")
print(f"Logical Offset: 0x{logical_offset:X} ({logical_offset})")
if phys_offset is not None and phys_offset != logical_offset:
print(f"Physical Offset: 0x{phys_offset:X} ({phys_offset})")
print(f"Length: {len(data)} byte(s)")
print(f"Hex: 0x{hex_str.upper()} ({hex_str})")
if len(data) == 1:
val = data[0]
print(f"Dec (uint8): {val}")
elif len(data) == 2:
val_be = int.from_bytes(data, 'big')
val_le = int.from_bytes(data, 'little')
print(f"Dec (BE uint16): {val_be} (0x{val_be:04X})")
print(f"Dec (LE uint16): {val_le} (0x{val_le:04X})")
elif len(data) == 4:
val_be = int.from_bytes(data, 'big')
val_le = int.from_bytes(data, 'little')
print(f"Dec (BE uint32): {val_be} (0x{val_be:08X})")
print(f"Dec (LE uint32): {val_le} (0x{val_le:08X})")
elif len(data) == 8:
val_be = int.from_bytes(data, 'big')
val_le = int.from_bytes(data, 'little')
print(f"Dec (BE uint64): {val_be} (0x{val_be:016X})")
print(f"Dec (LE uint64): {val_le} (0x{val_le:016X})")
ascii_repr = "".join(chr(b) if 32 <= b <= 126 else "." for b in data)
print(f"ASCII: {ascii_repr}")
if __name__ == "__main__":
main()