update.py 3.6 KB

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