mirror of https://gerrit.osmocom.org/pysim
commands: conserve write cycles
When a record or a binary file is written the card goes throth a full flash/eeprom write cycle at this location, even when the data does not change. This can be optimized by reading before writing in order to compere if the data we are about to write is actually different. Change-Id: Ifd1b80d3ede15a7caa29077a37ac7cf58c9053f1 Related: OS#4963
This commit is contained in:
parent
2b11c32e20
commit
38c74f6d41
|
@ -67,11 +67,17 @@ class PysimApp(cmd2.Cmd):
|
|||
self.numeric_path = False
|
||||
self.add_settable(cmd2.Settable('numeric_path', bool, 'Print File IDs instead of names',
|
||||
onchange_cb=self._onchange_numeric_path))
|
||||
self.conserve_write = True
|
||||
self.add_settable(cmd2.Settable('conserve_write', bool, 'Read and compare before write',
|
||||
onchange_cb=self._onchange_conserve_write))
|
||||
self.update_prompt()
|
||||
|
||||
def _onchange_numeric_path(self, param_name, old, new):
|
||||
self.update_prompt()
|
||||
|
||||
def _onchange_conserve_write(self, param_name, old, new):
|
||||
self.rs.conserve_write = new
|
||||
|
||||
def update_prompt(self):
|
||||
path_list = self.rs.selected_file.fully_qualified_path(not self.numeric_path)
|
||||
self.prompt = 'pySIM-shell (%s)> ' % ('/'.join(path_list))
|
||||
|
|
|
@ -144,9 +144,17 @@ class SimCardCommands(object):
|
|||
raise ValueError('Failed to read (offset %d)' % (offset))
|
||||
return total_data, sw
|
||||
|
||||
def update_binary(self, ef, data, offset=0, verify=False):
|
||||
def update_binary(self, ef, data, offset=0, verify=False, conserve=False):
|
||||
data_length = len(data) // 2
|
||||
|
||||
# Save write cycles by reading+comparing before write
|
||||
if conserve:
|
||||
data_current, sw = self.read_binary(ef, data_length, offset)
|
||||
if data_current == data:
|
||||
return None, sw
|
||||
|
||||
self.select_path(ef)
|
||||
pdu = self.cla_byte + 'd6%04x%02x' % (offset, len(data) // 2) + data
|
||||
pdu = self.cla_byte + 'd6%04x%02x' % (offset, data_length) + data
|
||||
res = self._tp.send_apdu_checksw(pdu)
|
||||
if verify:
|
||||
self.verify_binary(ef, data, offset)
|
||||
|
@ -163,7 +171,7 @@ class SimCardCommands(object):
|
|||
pdu = self.cla_byte + 'b2%02x04%02x' % (rec_no, rec_length)
|
||||
return self._tp.send_apdu(pdu)
|
||||
|
||||
def update_record(self, ef, rec_no, data, force_len=False, verify=False):
|
||||
def update_record(self, ef, rec_no, data, force_len=False, verify=False, conserve=False):
|
||||
r = self.select_path(ef)
|
||||
if not force_len:
|
||||
rec_length = self.__record_len(r)
|
||||
|
@ -171,6 +179,14 @@ class SimCardCommands(object):
|
|||
raise ValueError('Invalid data length (expected %d, got %d)' % (rec_length, len(data) // 2))
|
||||
else:
|
||||
rec_length = len(data) // 2
|
||||
|
||||
# Save write cycles by reading+comparing before write
|
||||
if conserve:
|
||||
data_current, sw = self.read_record(ef, rec_no)
|
||||
data_current = data_current[0:rec_length*2]
|
||||
if data_current == data:
|
||||
return None, sw
|
||||
|
||||
pdu = (self.cla_byte + 'dc%02x04%02x' % (rec_no, rec_length)) + data
|
||||
res = self._tp.send_apdu_checksw(pdu)
|
||||
if verify:
|
||||
|
|
|
@ -566,6 +566,7 @@ class RuntimeState(object):
|
|||
self.mf.add_application(a)
|
||||
for f in self.profile.files_in_mf:
|
||||
self.mf.add_file(f)
|
||||
self.conserve_write = True
|
||||
|
||||
def _match_applications(self):
|
||||
"""match the applications from the profile with applications on the card"""
|
||||
|
@ -699,7 +700,7 @@ class RuntimeState(object):
|
|||
def update_binary(self, data_hex, offset=0):
|
||||
if not isinstance(self.selected_file, TransparentEF):
|
||||
raise TypeError("Only works with TransparentEF")
|
||||
return self.card._scc.update_binary(self.selected_file.fid, data_hex, offset)
|
||||
return self.card._scc.update_binary(self.selected_file.fid, data_hex, offset, conserve=self.conserve_write)
|
||||
|
||||
def update_binary_dec(self, data):
|
||||
data_hex = self.selected_file.encode_hex(data)
|
||||
|
@ -719,7 +720,7 @@ class RuntimeState(object):
|
|||
def update_record(self, rec_nr, data_hex):
|
||||
if not isinstance(self.selected_file, LinFixedEF):
|
||||
raise TypeError("Only works with Linear Fixed EF")
|
||||
return self.card._scc.update_record(self.selected_file.fid, rec_nr, data_hex)
|
||||
return self.card._scc.update_record(self.selected_file.fid, rec_nr, data_hex, conserve=self.conserve_write)
|
||||
|
||||
def update_record_dec(self, rec_nr, data):
|
||||
hex_data = self.selected_file.encode_record_hex(data)
|
||||
|
|
Loading…
Reference in New Issue