copro.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import logging
  2. import datetime
  3. import shutil
  4. import json
  5. from os.path import basename
  6. import xml.etree.ElementTree as ET
  7. from flipper.utils import *
  8. from flipper.assets.coprobin import CoproBinary, get_stack_type
  9. CUBE_COPRO_PATH = "Projects/STM32WB_Copro_Wireless_Binaries"
  10. MANIFEST_TEMPLATE = {
  11. "manifest": {"version": 0, "timestamp": 0},
  12. "copro": {
  13. "fus": {"version": {"major": 1, "minor": 2, "sub": 0}, "files": []},
  14. "radio": {
  15. "version": {},
  16. "files": [],
  17. },
  18. },
  19. }
  20. class Copro:
  21. def __init__(self, mcu):
  22. self.mcu = mcu
  23. self.version = None
  24. self.cube_dir = None
  25. self.mcu_copro = None
  26. self.logger = logging.getLogger(self.__class__.__name__)
  27. def loadCubeInfo(self, cube_dir, cube_version):
  28. if not os.path.isdir(cube_dir):
  29. raise Exception(f'"{cube_dir}" doesn\'t exists')
  30. self.cube_dir = cube_dir
  31. self.mcu_copro = os.path.join(self.cube_dir, CUBE_COPRO_PATH, self.mcu)
  32. if not os.path.isdir(self.mcu_copro):
  33. raise Exception(f'"{self.mcu_copro}" doesn\'t exists')
  34. cube_manifest_file = os.path.join(self.cube_dir, "package.xml")
  35. cube_manifest = ET.parse(cube_manifest_file)
  36. cube_package = cube_manifest.find("PackDescription")
  37. if not cube_package:
  38. raise Exception(f"Unknown Cube manifest format")
  39. cube_version = cube_package.get("Patch") or cube_package.get("Release")
  40. if not cube_version or not cube_version.startswith("FW.WB"):
  41. raise Exception(f"Incorrect Cube package or version info")
  42. cube_version = cube_version.replace("FW.WB.", "", 1)
  43. if cube_version != cube_version:
  44. raise Exception(f"Unsupported cube version")
  45. self.version = cube_version
  46. def addFile(self, array, filename, **kwargs):
  47. source_file = os.path.join(self.mcu_copro, filename)
  48. destination_file = os.path.join(self.output_dir, filename)
  49. shutil.copyfile(source_file, destination_file)
  50. array.append(
  51. {"name": filename, "sha256": file_sha256(destination_file), **kwargs}
  52. )
  53. def bundle(self, output_dir, stack_file_name, stack_type, stack_addr=None):
  54. if not os.path.isdir(output_dir):
  55. raise Exception(f'"{output_dir}" doesn\'t exists')
  56. self.output_dir = output_dir
  57. stack_file = os.path.join(self.mcu_copro, stack_file_name)
  58. manifest_file = os.path.join(self.output_dir, "Manifest.json")
  59. # Form Manifest
  60. manifest = dict(MANIFEST_TEMPLATE)
  61. manifest["manifest"]["timestamp"] = timestamp()
  62. copro_bin = CoproBinary(stack_file)
  63. self.logger.info(f"Bundling {copro_bin.img_sig.get_version()}")
  64. stack_type_code = get_stack_type(stack_type)
  65. manifest["copro"]["radio"]["version"].update(
  66. {
  67. "type": stack_type_code,
  68. "major": copro_bin.img_sig.version_major,
  69. "minor": copro_bin.img_sig.version_minor,
  70. "sub": copro_bin.img_sig.version_sub,
  71. "branch": copro_bin.img_sig.version_branch,
  72. "release": copro_bin.img_sig.version_build,
  73. }
  74. )
  75. if not stack_addr:
  76. stack_addr = copro_bin.get_flash_load_addr()
  77. self.logger.info(f"Using guessed flash address 0x{stack_addr:x}")
  78. # Old FUS Update
  79. self.addFile(
  80. manifest["copro"]["fus"]["files"],
  81. "stm32wb5x_FUS_fw_for_fus_0_5_3.bin",
  82. condition="==0.5.3",
  83. address="0x080EC000",
  84. )
  85. # New FUS Update
  86. self.addFile(
  87. manifest["copro"]["fus"]["files"],
  88. "stm32wb5x_FUS_fw.bin",
  89. condition=">0.5.3",
  90. address="0x080EC000",
  91. )
  92. # BLE Full Stack
  93. self.addFile(
  94. manifest["copro"]["radio"]["files"],
  95. stack_file_name,
  96. address=f"0x{stack_addr:X}",
  97. )
  98. # Save manifest to
  99. json.dump(manifest, open(manifest_file, "w"))