update.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #!/usr/bin/env python3
  2. from flipper.app import App
  3. from flipper.utils.fff import FlipperFormatFile
  4. from os.path import basename, join, exists
  5. from os import makedirs
  6. import shutil
  7. import zlib
  8. class Main(App):
  9. def init(self):
  10. self.subparsers = self.parser.add_subparsers(help="sub-command help")
  11. # generate
  12. self.parser_generate = self.subparsers.add_parser(
  13. "generate", help="Generate update description file"
  14. )
  15. self.parser_generate.add_argument("-d", dest="directory", required=True)
  16. self.parser_generate.add_argument("-v", dest="version", required=True)
  17. self.parser_generate.add_argument("-t", dest="target", required=True)
  18. self.parser_generate.add_argument("-dfu", dest="dfu", required=True)
  19. self.parser_generate.add_argument("-stage", dest="stage", required=True)
  20. self.parser_generate.add_argument("-radio", dest="radiobin", required=False)
  21. self.parser_generate.add_argument(
  22. "-radioaddr", dest="radioaddr", required=False
  23. )
  24. self.parser_generate.set_defaults(func=self.generate)
  25. def generate(self):
  26. stage_basename = basename(self.args.stage)
  27. dfu_basename = basename(self.args.dfu)
  28. if not exists(self.args.directory):
  29. makedirs(self.args.directory)
  30. shutil.copyfile(self.args.stage, join(self.args.directory, stage_basename))
  31. shutil.copyfile(self.args.dfu, join(self.args.directory, dfu_basename))
  32. file = FlipperFormatFile()
  33. file.setHeader("Flipper firmware upgrade configuration", 1)
  34. file.writeKey("Info", self.args.version)
  35. file.writeKey("Target", self.args.target[1:]) # dirty 'f' strip
  36. file.writeKey("Loader", stage_basename)
  37. file.writeComment("little-endian hex!")
  38. file.writeKey("Loader CRC", self.int2ffhex(self.crc(self.args.stage)))
  39. file.writeKey("Firmware", dfu_basename)
  40. file.writeKey("Radio", self.args.radiobin or "")
  41. file.writeKey("Radio address", self.int2ffhex(self.args.radioaddr or 0))
  42. file.save("%s/update.fuf" % self.args.directory)
  43. return 0
  44. @staticmethod
  45. def int2ffhex(value: int):
  46. hexstr = "%08X" % value
  47. return " ".join(list(Main.batch(hexstr, 2))[::-1])
  48. @staticmethod
  49. def crc(fileName):
  50. prev = 0
  51. with open(fileName, "rb") as file:
  52. for eachLine in file:
  53. prev = zlib.crc32(eachLine, prev)
  54. return prev & 0xFFFFFFFF
  55. @staticmethod
  56. def batch(iterable, n=1):
  57. l = len(iterable)
  58. for ndx in range(0, l, n):
  59. yield iterable[ndx : min(ndx + n, l)]
  60. if __name__ == "__main__":
  61. Main()()