From 84cc298dd2f4c4e20ae0ad123af5875b26d04d37 Mon Sep 17 00:00:00 2001 From: Mitchell Scott <10804314+rmitchellscott@users.noreply.github.com> Date: Fri, 5 Dec 2025 17:05:05 -0700 Subject: [PATCH 1/2] simplify swupdate install to fix partition switching on 3.22+ --- codexctl/device.py | 70 ++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 46 deletions(-) diff --git a/codexctl/device.py b/codexctl/device.py index 4cd75b0..42bcda2 100644 --- a/codexctl/device.py +++ b/codexctl/device.py @@ -679,8 +679,6 @@ def install_sw_update(self, version_file: str, bootloader_files: dict[str, bytes SystemExit: If there was an error installing the update """ - command = f'/usr/bin/swupdate -v -i VERSION_FILE -k /usr/share/swupdate/swupdate-payload-key-pub.pem -H "{self.hardware.swupdate_hw}:1.0" -e "stable,copy1"' - if self.client: ftp_client = self.client.open_sftp() @@ -693,25 +691,15 @@ def install_sw_update(self, version_file: str, bootloader_files: dict[str, bytes print("\nDone! Running swupdate (PLEASE BE PATIENT, ~5 MINUTES)") - command = command.replace("VERSION_FILE", out_location) - - for num in (1, 2): - command = command.replace( - "stable,copy1", f"stable,copy{num}" - ) # terrible hack but it works - self.logger.debug(command) - _stdin, stdout, _stderr = self.client.exec_command(command) - - self.logger.debug(f"Stdout of swupdate checking: {stdout.readlines()}") + command = f"/usr/sbin/swupdate-from-image-file {out_location}" + self.logger.debug(command) + _stdin, stdout, _stderr = self.client.exec_command(command) - exit_status = stdout.channel.recv_exit_status() + exit_status = stdout.channel.recv_exit_status() - if exit_status != 0: - if "over our current root" in "".join(_stderr.readlines()): - continue - else: - print("".join(_stderr.readlines())) - raise SystemError("Update failed!") + if exit_status != 0: + print("".join(_stderr.readlines())) + raise SystemError("Update failed!") if bootloader_files: print("\nApplying bootloader update...") @@ -749,34 +737,24 @@ def install_sw_update(self, version_file: str, bootloader_files: dict[str, bytes else: print("Running swupdate") - command = command.replace("VERSION_FILE", version_file) - - for num in (1, 2): - command = command.replace( - "stable,copy1", f"stable,copy{num}" - ) # terrible hack but it works - self.logger.debug(command) - - with subprocess.Popen( - command, - text=True, - shell=True, # Being lazy... - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={"PATH": "/bin:/usr/bin:/sbin"}, - ) as process: - if process.wait() != 0: - if "installing over our current root" in "".join( - process.stderr.readlines() - ): - continue - else: - print("".join(process.stderr.readlines())) - raise SystemError("Update failed") + command = f"/usr/sbin/swupdate-from-image-file {version_file}" + self.logger.debug(command) - self.logger.debug( - f"Stdout of update checking service is {''.join(process.stdout.readlines())}" - ) + with subprocess.Popen( + command, + text=True, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env={"PATH": "/bin:/usr/bin:/sbin:/usr/sbin"}, + ) as process: + if process.wait() != 0: + print("".join(process.stderr.readlines())) + raise SystemError("Update failed") + + self.logger.debug( + f"Stdout of swupdate: {''.join(process.stdout.readlines())}" + ) print("Update complete and device rebooting") os.system("reboot") From a9f986f169e2fb303ed641eaf02c6fc25172d2a0 Mon Sep 17 00:00:00 2001 From: Mitchell Scott <10804314+rmitchellscott@users.noreply.github.com> Date: Fri, 5 Dec 2025 19:05:47 -0700 Subject: [PATCH 2/2] use subprocess.check_output --- codexctl/device.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/codexctl/device.py b/codexctl/device.py index 42bcda2..74464c7 100644 --- a/codexctl/device.py +++ b/codexctl/device.py @@ -737,24 +737,20 @@ def install_sw_update(self, version_file: str, bootloader_files: dict[str, bytes else: print("Running swupdate") - command = f"/usr/sbin/swupdate-from-image-file {version_file}" + command = ["/usr/sbin/swupdate-from-image-file", version_file] self.logger.debug(command) - with subprocess.Popen( - command, - text=True, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={"PATH": "/bin:/usr/bin:/sbin:/usr/sbin"}, - ) as process: - if process.wait() != 0: - print("".join(process.stderr.readlines())) - raise SystemError("Update failed") - - self.logger.debug( - f"Stdout of swupdate: {''.join(process.stdout.readlines())}" + try: + output = subprocess.check_output( + command, + stderr=subprocess.STDOUT, + text=True, + env={"PATH": "/bin:/usr/bin:/sbin:/usr/sbin"}, ) + self.logger.debug(f"Stdout of swupdate: {output}") + except subprocess.CalledProcessError as e: + print(e.output) + raise SystemError("Update failed") print("Update complete and device rebooting") os.system("reboot")