update.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # greaseweazle/tools/update.py
  2. #
  3. # Greaseweazle control script: Firmware Update.
  4. #
  5. # Written & released by Keir Fraser <keir.xen@gmail.com>
  6. #
  7. # This is free and unencumbered software released into the public domain.
  8. # See the file COPYING for more details, or visit <http://unlicense.org>.
  9. description = "Update the Greaseweazle device firmware to current version."
  10. import sys, serial, struct, os
  11. import crcmod.predefined
  12. from greaseweazle.tools import util
  13. from greaseweazle import version
  14. from greaseweazle import usb as USB
  15. # update_firmware:
  16. # Updates the Greaseweazle firmware using the specified Update File.
  17. def update_firmware(usb, args):
  18. req_type = b'BL' if args.bootloader else b'GW'
  19. filename = args.file
  20. if filename == "auto":
  21. # Get the absolute path to the root Greaseweazle folder.
  22. path = os.path.dirname(os.path.abspath(__file__))
  23. for _ in range(3):
  24. path = os.path.join(path, os.pardir)
  25. path = os.path.normpath(path)
  26. filename = os.path.join(path, "Greaseweazle-v%d.%d.upd"
  27. % (version.major, version.minor))
  28. # Read the entire update catalogue.
  29. with open(filename, "rb") as f:
  30. dat = f.read()
  31. # Search the catalogue for a match on our Weazle's hardware type.
  32. while dat:
  33. upd_len, hw_type = struct.unpack("<2H", dat[:4])
  34. upd_type, = struct.unpack("2s", dat[upd_len-4:upd_len-2])
  35. if hw_type == usb.hw_type and upd_type == req_type:
  36. # Match: Pull out the embedded update file.
  37. dat = dat[4:upd_len+4]
  38. break
  39. # Skip to the next catalogue entry.
  40. dat = dat[upd_len+4:]
  41. if not dat:
  42. print("%s: No match for hardware type %x" % (filename, usb.hw_type))
  43. return
  44. # Check the matching update file's footer.
  45. sig, maj, min, hw_type = struct.unpack("<2s2BH", dat[-8:-2])
  46. if len(dat) & 3 != 0 or sig != req_type or hw_type != usb.hw_type:
  47. print("%s: Bad update file" % (filename))
  48. return
  49. crc16 = crcmod.predefined.Crc('crc-ccitt-false')
  50. crc16.update(dat)
  51. if crc16.crcValue != 0:
  52. print("%s: Bad CRC" % (filename))
  53. return
  54. # Perform the update.
  55. print("Updating %s to v%u.%u..."
  56. % ("Bootloader" if args.bootloader else "Main Firmware", maj, min))
  57. if args.bootloader:
  58. ack = usb.update_bootloader(dat)
  59. if ack != 0:
  60. print("""\
  61. ** UPDATE FAILED: Please retry immediately or your Weazle may need
  62. full reflashing via a suitable programming adapter!""")
  63. return
  64. print("Done.")
  65. else:
  66. ack = usb.update_firmware(dat)
  67. if ack != 0:
  68. print("** UPDATE FAILED: Please retry!")
  69. return
  70. print("Done.")
  71. if usb.hw_type == 7:
  72. util.usb_reopen(usb, is_update=False)
  73. else:
  74. print("** Disconnect Greaseweazle and remove the Programming Jumper.")
  75. def main(argv):
  76. parser = util.ArgumentParser(allow_abbrev=False)
  77. parser.add_argument("file", nargs="?", default="auto",
  78. help="update filename")
  79. parser.add_argument("device", nargs="?", default="auto",
  80. help="serial device")
  81. parser.add_argument("--bootloader", action="store_true",
  82. help="update the bootloader (use with caution!)")
  83. parser.description = description
  84. parser.prog += ' ' + argv[1]
  85. args = parser.parse_args(argv[2:])
  86. try:
  87. usb = util.usb_open(args.device, is_update=not args.bootloader)
  88. update_firmware(usb, args)
  89. except USB.CmdError as error:
  90. print("Command Failed: %s" % error)
  91. if __name__ == "__main__":
  92. main(sys.argv)
  93. # Local variables:
  94. # python-indent: 4
  95. # End: