Change in pysim[master]: commands: conserve write cycles

laforge gerrit-no-reply at lists.osmocom.org
Fri Apr 2 14:33:25 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/23539 )

Change subject: commands: conserve write cycles
......................................................................

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
---
M pySim-shell.py
M pySim/commands.py
M pySim/filesystem.py
3 files changed, 28 insertions(+), 5 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved



diff --git a/pySim-shell.py b/pySim-shell.py
index a8471ff..9468444 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -67,11 +67,17 @@
 		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))
diff --git a/pySim/commands.py b/pySim/commands.py
index 9aed588..65c3891 100644
--- a/pySim/commands.py
+++ b/pySim/commands.py
@@ -144,9 +144,17 @@
 				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 @@
 		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 @@
 				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:
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index cd08699..e959c52 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -566,6 +566,7 @@
             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 @@
     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 @@
     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)

-- 
To view, visit https://gerrit.osmocom.org/c/pysim/+/23539
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Ifd1b80d3ede15a7caa29077a37ac7cf58c9053f1
Gerrit-Change-Number: 23539
Gerrit-PatchSet: 5
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210402/65360a16/attachment.htm>


More information about the gerrit-log mailing list