From 1b7b131adc417318f18b66ecef5b5736003dfbcc Mon Sep 17 00:00:00 2001 From: Chad Attermann Date: Tue, 5 Mar 2024 17:14:52 -0700 Subject: [PATCH 1/2] Added support for alternate firmware download URL New command line option `--fw-url` accepts an alternate URL to use for downloading firmware images. Note this feature is moderately opinionated when it comes to directory structure. The intent is to be compatible with GitHub releases, so the latest version info is expected to be found at "{fw-url}latest/download/release.json" and firmware images at "{fw-url}download/{version}/{firmware_file.zip}". --- RNS/Utilities/rnodeconf.py | 43 ++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/RNS/Utilities/rnodeconf.py b/RNS/Utilities/rnodeconf.py index c20f242..86ea861 100755 --- a/RNS/Utilities/rnodeconf.py +++ b/RNS/Utilities/rnodeconf.py @@ -53,6 +53,7 @@ rnode_baudrate = 115200 known_keys = [["unsigned.io", "30819f300d06092a864886f70d010101050003818d0030818902818100bf831ebd99f43b477caf1a094bec829389da40653e8f1f83fc14bf1b98a3e1cc70e759c213a43f71e5a47eb56a9ca487f241335b3e6ff7cdde0ee0a1c75c698574aeba0485726b6a9dfc046b4188e3520271ee8555a8f405cf21f81f2575771d0b0887adea5dd53c1f594f72c66b5f14904ffc2e72206a6698a490d51ba1105b0203010001"], ["unsigned.io", "30819f300d06092a864886f70d010101050003818d0030818902818100e5d46084e445595376bf7efd9c6ccf19d39abbc59afdb763207e4ff68b8d00ebffb63847aa2fe6dd10783d3ea63b55ac66f71ad885c20e223709f0d51ed5c6c0d0b093be9e1d165bb8a483a548b67a3f7a1e4580f50e75b306593fa6067ae259d3e297717bd7ff8c8f5b07f2bed89929a9a0321026cf3699524db98e2d18fb2d020300ff39"]] firmware_update_url = "https://github.com/markqvist/RNode_Firmware/releases/download/" fw_filename = None +fw_url = None mapped_model = None class KISS(): @@ -1002,8 +1003,33 @@ def ensure_firmware_file(fw_filename): if not upd_nocheck: try: try: - urlretrieve(firmware_version_url+fw_filename, UPD_DIR+"/"+fw_filename+".version.latest") + # if custom firmware url, download latest release + if fw_url != None: + try: + RNS.log("Retrieving latest version from custom url "+fw_url+"latest/download/release.json") + urlretrieve(fw_url+"latest/download/release.json", UPD_DIR+"/fallback_release_info.json") + import json + with open(UPD_DIR+"/fallback_release_info.json", "rb") as rif: + rdat = json.loads(rif.read()) + variant = rdat[fw_filename] + with open(UPD_DIR+"/"+fw_filename+".version.latest", "wb") as verf: + inf_str = str(variant["version"])+" "+str(variant["hash"]) + verf.write(inf_str.encode("utf-8")) + + except Exception as e: + RNS.log("Error while trying custom URL: "+str(e)) + raise e + else: + urlretrieve(firmware_version_url+fw_filename, UPD_DIR+"/"+fw_filename+".version.latest") except Exception as e: + # if custom firmware url, don't fallback + if fw_url != None: + RNS.log("Failed to retrive latest version information for your board from the specified url.") + RNS.log("Check your internet connection and try again.") + RNS.log("If you don't have Internet access currently, use the --fw-version option to manually specify a version.") + RNS.log("You can also use --extract to copy the firmware from a known-good RNode of the same model.") + exit() + RNS.log("") RNS.log("WARNING!") RNS.log("Failed to retrieve latest version information for your board from the default server") @@ -1051,7 +1077,12 @@ def ensure_firmware_file(fw_filename): RNS.log("use the --fw-version option to manually specify a version.") exit(98) - update_target_url = firmware_update_url+selected_version+"/"+fw_filename + # if custom firmware url, use it + if fw_url != None: + update_target_url = fw_url+"download/"+selected_version+"/"+fw_filename + RNS.log("Retrieving firmware from custom url "+update_target_url) + else: + update_target_url = firmware_update_url+selected_version+"/"+fw_filename try: if not os.path.isdir(UPD_DIR+"/"+selected_version): @@ -1128,7 +1159,7 @@ device_signer = None force_update = False upd_nocheck = False def main(): - global mapped_product, mapped_model, fw_filename, selected_version, force_update, upd_nocheck, device_signer + global mapped_product, mapped_model, fw_filename, fw_url, selected_version, force_update, upd_nocheck, device_signer try: if not util.find_spec("serial"): @@ -1160,6 +1191,7 @@ def main(): parser.add_argument("-u", "--update", action="store_true", help="Update firmware to the latest version") parser.add_argument("-U", "--force-update", action="store_true", help="Update to specified firmware even if version matches or is older than installed version") parser.add_argument("--fw-version", action="store", metavar="version", default=None, help="Use a specific firmware version for update or autoinstall") + parser.add_argument("--fw-url", action="store", metavar="url", default=None, help="Use an alternate firmware download URL") parser.add_argument("--nocheck", action="store_true", help="Don't check for firmware updates online") parser.add_argument("-e", "--extract", action="store_true", help="Extract firmware from connected RNode for later use") parser.add_argument("-E", "--use-extracted", action="store_true", help="Use the extracted firmware for autoinstallation or update") @@ -1232,6 +1264,9 @@ def main(): RNS.log("Selected version \""+selected_version+"\" does not appear to be a number.") exit() + if args.fw_url != None: + fw_url = args.fw_url + if args.force_update: force_update = True @@ -1922,7 +1957,7 @@ def main(): except Exception as e: print("That ESP32 board does not exist, exiting now.") exit() - + if fw_filename == None: print("") print("Sorry, no firmware for your board currently exists.") From 55653492551a5d04d4d709005ce70fdd0fa45c68 Mon Sep 17 00:00:00 2001 From: Chad Attermann Date: Tue, 5 Mar 2024 19:02:47 -0700 Subject: [PATCH 2/2] Fixed installation of alternate firmware version Required version info was not being downloaded when alternate (not latest) version is selected rsulting in the error "Could not read locally cached release information." --- RNS/Utilities/rnodeconf.py | 138 +++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/RNS/Utilities/rnodeconf.py b/RNS/Utilities/rnodeconf.py index 86ea861..5266dd8 100755 --- a/RNS/Utilities/rnodeconf.py +++ b/RNS/Utilities/rnodeconf.py @@ -999,83 +999,85 @@ def ensure_firmware_file(fw_filename): else: try: - if selected_version == None: - if not upd_nocheck: - try: - try: - # if custom firmware url, download latest release - if fw_url != None: - try: - RNS.log("Retrieving latest version from custom url "+fw_url+"latest/download/release.json") - urlretrieve(fw_url+"latest/download/release.json", UPD_DIR+"/fallback_release_info.json") - import json - with open(UPD_DIR+"/fallback_release_info.json", "rb") as rif: - rdat = json.loads(rif.read()) - variant = rdat[fw_filename] - with open(UPD_DIR+"/"+fw_filename+".version.latest", "wb") as verf: - inf_str = str(variant["version"])+" "+str(variant["hash"]) - verf.write(inf_str.encode("utf-8")) - - except Exception as e: - RNS.log("Error while trying custom URL: "+str(e)) - raise e + if not upd_nocheck: + try: + # if custom firmware url, download latest release + if selected_version == None and fw_url == None: + version_url = firmware_version_url+fw_filename + RNS.log("Retrieving latest version info from "+version_url) + urlretrieve(firmware_version_url+fw_filename, UPD_DIR+"/"+fw_filename+".version.latest") + else: + if fw_url != None: + if selected_version == None: + version_url = fw_url+"latest/download/release.json" else: - urlretrieve(firmware_version_url+fw_filename, UPD_DIR+"/"+fw_filename+".version.latest") + version_url = fw_url+"download/"+selected_version+"/release.json" + else: + version_url = firmware_update_url+selected_version+"/release.json" + try: + RNS.log("Retrieving specified version info from "+version_url) + urlretrieve(version_url, UPD_DIR+"/version_release_info.json") + import json + with open(UPD_DIR+"/version_release_info.json", "rb") as rif: + rdat = json.loads(rif.read()) + variant = rdat[fw_filename] + with open(UPD_DIR+"/"+fw_filename+".version.latest", "wb") as verf: + inf_str = str(variant["version"])+" "+str(variant["hash"]) + verf.write(inf_str.encode("utf-8")) except Exception as e: - # if custom firmware url, don't fallback - if fw_url != None: - RNS.log("Failed to retrive latest version information for your board from the specified url.") - RNS.log("Check your internet connection and try again.") - RNS.log("If you don't have Internet access currently, use the --fw-version option to manually specify a version.") - RNS.log("You can also use --extract to copy the firmware from a known-good RNode of the same model.") - exit() - - RNS.log("") - RNS.log("WARNING!") - RNS.log("Failed to retrieve latest version information for your board from the default server") - RNS.log("Will retry using the following fallback URL: "+fallback_firmware_version_url) - RNS.log("") - RNS.log("Hit enter if you want to proceed") - input() - try: - urlretrieve(fallback_firmware_version_url, UPD_DIR+"/fallback_release_info.json") - import json - with open(UPD_DIR+"/fallback_release_info.json", "rb") as rif: - rdat = json.loads(rif.read()) - variant = rdat[fw_filename] - with open(UPD_DIR+"/"+fw_filename+".version.latest", "wb") as verf: - inf_str = str(variant["version"])+" "+str(variant["hash"]) - verf.write(inf_str.encode("utf-8")) - - except Exception as e: - RNS.log("Error while trying fallback URL: "+str(e)) - raise e - - except Exception as e: - RNS.log("Failed to retrive latest version information for your board.") + RNS.log("Failed to retrive version information for your board.") + RNS.log("Check your internet connection and try again.") + RNS.log("If you don't have Internet access currently, use the --fw-version option to manually specify a version.") + RNS.log("You can also use --extract to copy the firmware from a known-good RNode of the same model.") + exit() + except Exception as e: + # if custom firmware url, don't fallback + if fw_url != None: + RNS.log("Failed to retrive version information for your board from the specified url.") RNS.log("Check your internet connection and try again.") RNS.log("If you don't have Internet access currently, use the --fw-version option to manually specify a version.") RNS.log("You can also use --extract to copy the firmware from a known-good RNode of the same model.") exit() - import shutil - file = open(UPD_DIR+"/"+fw_filename+".version.latest", "rb") - release_info = file.read().decode("utf-8").strip() - selected_version = release_info.split()[0] - if selected_version == "not": - RNS.log("No valid version found for this board, exiting.") - exit(199) + RNS.log("") + RNS.log("WARNING!") + RNS.log("Failed to retrieve latest version information for your board from the default server.") + RNS.log("Will retry using the following fallback URL: "+fallback_firmware_version_url) + RNS.log("") + RNS.log("Hit enter if you want to proceed") + input() + try: + urlretrieve(fallback_firmware_version_url, UPD_DIR+"/fallback_release_info.json") + import json + with open(UPD_DIR+"/fallback_release_info.json", "rb") as rif: + rdat = json.loads(rif.read()) + variant = rdat[fw_filename] + with open(UPD_DIR+"/"+fw_filename+".version.latest", "wb") as verf: + inf_str = str(variant["version"])+" "+str(variant["hash"]) + verf.write(inf_str.encode("utf-8")) - selected_hash = release_info.split()[1] - if not os.path.isdir(UPD_DIR+"/"+selected_version): - os.makedirs(UPD_DIR+"/"+selected_version) - shutil.copy(UPD_DIR+"/"+fw_filename+".version.latest", UPD_DIR+"/"+selected_version+"/"+fw_filename+".version") - RNS.log("The latest firmware for this board is version "+selected_version) + except Exception as e: + RNS.log("Error while trying fallback URL: "+str(e)) + raise e - else: - RNS.log("Online firmware version check was disabled, but no firmware version specified for install.") - RNS.log("use the --fw-version option to manually specify a version.") - exit(98) + import shutil + file = open(UPD_DIR+"/"+fw_filename+".version.latest", "rb") + release_info = file.read().decode("utf-8").strip() + selected_version = release_info.split()[0] + if selected_version == "not": + RNS.log("No valid version found for this board, exiting.") + exit(199) + + selected_hash = release_info.split()[1] + if not os.path.isdir(UPD_DIR+"/"+selected_version): + os.makedirs(UPD_DIR+"/"+selected_version) + shutil.copy(UPD_DIR+"/"+fw_filename+".version.latest", UPD_DIR+"/"+selected_version+"/"+fw_filename+".version") + RNS.log("The selected firmware for this board is version "+selected_version) + + else: + RNS.log("Online firmware version check was disabled, but no firmware version specified for install.") + RNS.log("use the --fw-version option to manually specify a version.") + exit(98) # if custom firmware url, use it if fw_url != None: