Skip to content

Commit 0db27b6

Browse files
author
Nick Miles
committed
Added
1 parent 648b7be commit 0db27b6

File tree

1 file changed

+279
-0
lines changed

1 file changed

+279
-0
lines changed

read_nvs.py

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
import sys
2+
import json
3+
import struct
4+
import sys
5+
import os
6+
import base64
7+
import binascii
8+
from hexdump import hexdump
9+
import argparse
10+
11+
nvs_types = {
12+
0x01: "U8",
13+
0x11: "I8",
14+
0x02: "U16",
15+
0x12: "I16",
16+
0x04: "U32",
17+
0x14: "I32",
18+
0x08: "U64",
19+
0x18: "I64",
20+
0x21: "STR",
21+
0x41: "BLOB",
22+
0x42: "BLOB_DATA",
23+
0x48: "BLOB_IDX",
24+
0xFF: "ANY"
25+
}
26+
27+
entry_state_descs = {
28+
3: "Empty",
29+
2: "Written",
30+
0: "Erased"
31+
}
32+
33+
nvs_sector_states = {
34+
0xFFFFFFFF : "EMTPY",
35+
0xFFFFFFFE : "ACTIVE",
36+
0xFFFFFFFC : "FULL",
37+
0xFFFFFFF8 : "FREEING",
38+
0xFFFFFFF0 : "CORRUPT"
39+
}
40+
41+
namespaces = {}
42+
43+
def parse_entries(entries, entry_state_bitmap):
44+
entries_out = []
45+
i = 0
46+
while i < 126:
47+
entry_data = {}
48+
print(" Entry %d" % (i))
49+
print(" Bitmap State : %s" % (entry_state_descs[int(entry_state_bitmap[i])]))
50+
entry_data["entry_state"] = entry_state_descs[int(entry_state_bitmap[i])]
51+
52+
entry = entries[i]
53+
state = entry_state_bitmap[i]
54+
55+
entry_ns = entry[0]
56+
entry_type = entry[1]
57+
entry_span = entry[2]
58+
chunk_index = entry[3]
59+
60+
key = entry[8:24]
61+
62+
data = entry[24:]
63+
if(entry_type == 0):
64+
i += 1
65+
continue
66+
67+
if(nvs_types[entry_type] == "ANY"):
68+
i += 1
69+
continue
70+
71+
decoded_key = ''
72+
for c in key:
73+
if(c == 0):
74+
break
75+
decoded_key += chr(c)
76+
77+
key = decoded_key
78+
79+
print(" Written Entry %d" % (i))
80+
print(" NS Index : %d" % (entry_ns))
81+
entry_data["entry_ns_index"] = entry_ns
82+
83+
if(entry_ns != 0 and entry_ns in namespaces):
84+
print(" NS : %s" % (namespaces[entry_ns]))
85+
entry_data["entry_ns"] = namespaces[entry_ns]
86+
87+
print(" Type : %s" % (nvs_types[entry_type]))
88+
print(" Span : %d" % (entry_span))
89+
print(" ChunkIndex : %d" % (chunk_index))
90+
print(" Key : " + key)
91+
entry_data["entry_type"] = nvs_types[entry_type]
92+
entry_data["entry_span"] = entry_span
93+
entry_data["entry_chunk_index"] = chunk_index
94+
entry_data["entry_key"] = key
95+
96+
97+
if(nvs_types[entry_type] == "U8"):
98+
data = struct.unpack("<B", data[0:1])[0]
99+
print(" Data (U8) : %d" % (data))
100+
if(entry_ns == 0):
101+
namespaces[data] = key
102+
entry_data["entry_data_type"] = "U8"
103+
entry_data["entry_data"] = data
104+
105+
elif(nvs_types[entry_type] == "I8"):
106+
data = struct.unpack("<b", data[0:1])[0]
107+
print(" Data (I8) : %d" % (data))
108+
entry_data["entry_data_type"] = "I8"
109+
entry_data["entry_data"] = data
110+
111+
elif(nvs_types[entry_type] == "U16"):
112+
data = struct.unpack("<H", data[0:2])[0]
113+
print(" Data (U16) : %d" % (data))
114+
entry_data["entry_data_type"] = "U16"
115+
entry_data["entry_data"] = data
116+
117+
elif(nvs_types[entry_type] == "I16"):
118+
data = struct.unpack("<h", data[0:2])[0]
119+
print(" Data (I16) : %d" % (data))
120+
entry_data["entry_data_type"] = "I16"
121+
entry_data["entry_data"] = data
122+
123+
elif(nvs_types[entry_type] == "U32"):
124+
data = struct.unpack("<I", data[0:4])[0]
125+
print(" Data (U32) : %d" % (data))
126+
entry_data["entry_data_type"] = "U32"
127+
entry_data["entry_data"] = data
128+
129+
elif(nvs_types[entry_type] == "I32"):
130+
data = struct.unpack("<i", data[0:4])[0]
131+
print(" Data (I32) : %d" % (data))
132+
entry_data["entry_data_type"] = "I32"
133+
entry_data["entry_data"] = data
134+
135+
elif(nvs_types[entry_type] == "STR"):
136+
str_size = struct.unpack("<H", data[0:2])[0]
137+
print(" String :")
138+
entry_data["entry_data_type"] = "STR"
139+
print(" Size : %d " % (str_size))
140+
entry_data["entry_data_size"] = str_size
141+
data = b''
142+
for x in range(1, entry_span):
143+
i += 1
144+
data += entries[i]
145+
data = data[0:str_size-1].decode('ascii')
146+
print(" Data : %s" % (data))
147+
entry_data["entry_data"] = str(data)
148+
149+
elif(nvs_types[entry_type] == "BLOB_DATA"):
150+
blob_data_size = struct.unpack("<H", data[0:2])[0]
151+
print(" Blob Data :")
152+
entry_data["entry_data_type"] = "BLOB_DATA"
153+
print(" Size : %d " % (blob_data_size))
154+
entry_data["entry_data_size"] = blob_data_size
155+
data = b''
156+
for x in range(1, entry_span):
157+
i += 1
158+
data += entries[i]
159+
print(" Data :")
160+
hexdump(data[:blob_data_size])
161+
entry_data["entry_data"] = base64.b64encode(data[:blob_data_size]).decode('ascii')
162+
163+
elif(nvs_types[entry_type] == "BLOB"):
164+
blob_size = struct.unpack("<H", data[0:2])[0]
165+
print(" Data (Blob) :")
166+
entry_data["entry_data_type"] = "BLOB"
167+
print(" Size : %d " % (blob_size))
168+
entry_data["entry_data_size"] = blob_size
169+
data = b''
170+
for x in range(1, entry_span):
171+
i += 1
172+
data += entries[i]
173+
print(" Data :")
174+
hexdump(data[:blob_size])
175+
entry_data["entry_data"] = base64.b64encode(data[:blob_size]).decode('ascii')
176+
177+
elif(nvs_types[entry_type] == "BLOB_IDX"):
178+
idx_size = struct.unpack("<I", data[0:4])[0]
179+
chunk_count = struct.unpack("<B", data[5:6])[0]
180+
chunk_start = struct.unpack("<B", data[6:7])[0]
181+
print(" Blob IDX :")
182+
entry_data["entry_data_type"] = "BLOB_IDX"
183+
print(" Size : %d " % (idx_size))
184+
print(" Chunk Count : %d " % (chunk_count))
185+
print(" Chunk Start : %d " % (chunk_start))
186+
entry_data["entry_data_size"] = idx_size
187+
entry_data["entry_data_chunk_count"] = chunk_count
188+
entry_data["entry_data_chunk_start"] = chunk_start
189+
190+
else:
191+
print(" Data : %s" % (str(data)))
192+
entry_data["entry_data"] = str(data)
193+
194+
entries_out.append(entry_data)
195+
i += 1
196+
print("")
197+
return entries_out
198+
199+
def read_pages(fh):
200+
pages = []
201+
fh.seek(0, os.SEEK_END)
202+
file_len = fh.tell()
203+
204+
sector_pos = 0
205+
x = 0
206+
while(sector_pos < file_len):
207+
page_data = {}
208+
209+
fh.seek(sector_pos)
210+
page_state = nvs_sector_states[struct.unpack("<I", fh.read(4))[0]]
211+
seq_no = struct.unpack("<I", fh.read(4))[0]
212+
version = (ord(fh.read(1)) ^ 0xff) + 1
213+
214+
print("Page %d" % (x))
215+
print(" page state : %s" % (page_state))
216+
print(" page seq no. : %d" % (seq_no))
217+
print(" page version : %d" % (version))
218+
219+
page_data["page_state"] = page_state
220+
page_data["page_seq_no"] = seq_no
221+
page_data["page_version"] = version
222+
223+
fh.read(19) # unused
224+
225+
crc_32 = struct.unpack("<I", fh.read(4))[0]
226+
print(" crc 32 : %d" % (crc_32))
227+
page_data["page_crc_32"] = crc_32
228+
229+
entry_state_bitmap = fh.read(32)
230+
entry_state_bitmap_decoded = ''
231+
232+
for entry_num in range(0, 126):
233+
bitnum = entry_num * 2
234+
byte_index = int(bitnum / 8)
235+
temp = entry_state_bitmap[byte_index]
236+
237+
temp = temp >> (6 - (bitnum % 8))
238+
temp = temp & 3
239+
entry_state_bitmap_decoded = entry_state_bitmap_decoded + str(temp)
240+
241+
print(" page entry state bitmape (decoded) : %s" % (entry_state_bitmap_decoded))
242+
page_data["page_entry_state_bitmap"] = entry_state_bitmap_decoded
243+
sector_pos += 4096
244+
x += 1
245+
246+
entries = []
247+
entry_data = ''
248+
for entry in entry_state_bitmap_decoded:
249+
entry_data = fh.read(32)
250+
entries.append(entry_data)
251+
252+
page_data["entries"] = parse_entries(entries, entry_state_bitmap_decoded)
253+
254+
print("")
255+
print("")
256+
print("------------------------------------------------------------------------------")
257+
print("")
258+
pages.append(page_data)
259+
260+
print("")
261+
return pages
262+
263+
parser = argparse.ArgumentParser()
264+
parser.add_argument("nvs_bin_file", help="nvs partition binary file", type=str)
265+
parser.add_argument("-output_type", help="output type", type=str, choices=["text", "json"], default="text")
266+
267+
args = parser.parse_args()
268+
269+
with open(args.nvs_bin_file, 'rb') as fh:
270+
if(args.output_type != "text"):
271+
sys.stdout = open(os.devnull, 'w') # block print()
272+
273+
pages = read_pages(fh)
274+
275+
sys.stdout = sys.stdout = sys.__stdout__ # re-enable print()
276+
277+
if(args.output_type == "json"):
278+
print(json.dumps(pages))
279+

0 commit comments

Comments
 (0)