flash.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #!/usr/bin/env python3
  2. import logging
  3. import argparse
  4. import sys
  5. import os
  6. from flipper.app import App
  7. from flipper.cube import CubeProgrammer
  8. STATEMENT = "AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE"
  9. class Main(App):
  10. def init(self):
  11. self.subparsers = self.parser.add_subparsers(help="sub-command help")
  12. # Wipe
  13. self.parser_wipe = self.subparsers.add_parser("wipe", help="Wipe MCU Flash")
  14. self._addArgsSWD(self.parser_wipe)
  15. self.parser_wipe.set_defaults(func=self.wipe)
  16. # Core 1 boot
  17. self.parser_core1bootloader = self.subparsers.add_parser(
  18. "core1bootloader", help="Flash Core1 Bootloader"
  19. )
  20. self._addArgsSWD(self.parser_core1bootloader)
  21. self.parser_core1bootloader.add_argument(
  22. "bootloader", type=str, help="Bootloader binary"
  23. )
  24. self.parser_core1bootloader.set_defaults(func=self.core1bootloader)
  25. # Core 1 firmware
  26. self.parser_core1firmware = self.subparsers.add_parser(
  27. "core1firmware", help="Flash Core1 Firmware"
  28. )
  29. self._addArgsSWD(self.parser_core1firmware)
  30. self.parser_core1firmware.add_argument(
  31. "firmware", type=str, help="Firmware binary"
  32. )
  33. self.parser_core1firmware.set_defaults(func=self.core1firmware)
  34. # Core 1 all
  35. self.parser_core1 = self.subparsers.add_parser(
  36. "core1", help="Flash Core1 Bootloader and Firmware"
  37. )
  38. self._addArgsSWD(self.parser_core1)
  39. self.parser_core1.add_argument("bootloader", type=str, help="Bootloader binary")
  40. self.parser_core1.add_argument("firmware", type=str, help="Firmware binary")
  41. self.parser_core1.set_defaults(func=self.core1)
  42. # Core 2 fus
  43. self.parser_core2fus = self.subparsers.add_parser(
  44. "core2fus", help="Flash Core2 Firmware Update Service"
  45. )
  46. self._addArgsSWD(self.parser_core2fus)
  47. self.parser_core2fus.add_argument(
  48. "--statement",
  49. type=str,
  50. help="NEVER FLASH FUS, IT WILL ERASE CRYPTO ENCLAVE",
  51. required=True,
  52. )
  53. self.parser_core2fus.add_argument(
  54. "fus_address", type=str, help="Firmware Update Service Address"
  55. )
  56. self.parser_core2fus.add_argument(
  57. "fus", type=str, help="Firmware Update Service Binary"
  58. )
  59. self.parser_core2fus.set_defaults(func=self.core2fus)
  60. # Core 2 radio stack
  61. self.parser_core2radio = self.subparsers.add_parser(
  62. "core2radio", help="Flash Core2 Radio stack"
  63. )
  64. self._addArgsSWD(self.parser_core2radio)
  65. self.parser_core2radio.add_argument(
  66. "radio_address", type=str, help="Radio Stack Binary Address"
  67. )
  68. self.parser_core2radio.add_argument(
  69. "radio", type=str, help="Radio Stack Binary"
  70. )
  71. self.parser_core2radio.set_defaults(func=self.core2radio)
  72. def _addArgsSWD(self, parser):
  73. parser.add_argument(
  74. "--port", type=str, help="Port to connect: swd or usb1", default="swd"
  75. )
  76. parser.add_argument("--serial", type=str, help="ST-Link Serial Number")
  77. def _getCubeParams(self):
  78. return {
  79. "port": self.args.port,
  80. "serial": self.args.serial,
  81. }
  82. def wipe(self):
  83. self.logger.info(f"Wiping flash")
  84. cp = CubeProgrammer(self._getCubeParams())
  85. self.logger.info(f"Setting RDP to 0xBB")
  86. cp.setOptionBytes({"RDP": ("0xBB", "rw")})
  87. self.logger.info(f"Verifying RDP")
  88. r = cp.checkOptionBytes({"RDP": ("0xBB", "rw")})
  89. assert r == True
  90. self.logger.info(f"Result: {r}")
  91. self.logger.info(f"Setting RDP to 0xAA")
  92. cp.setOptionBytes({"RDP": ("0xAA", "rw")})
  93. self.logger.info(f"Verifying RDP")
  94. r = cp.checkOptionBytes({"RDP": ("0xAA", "rw")})
  95. assert r == True
  96. self.logger.info(f"Result: {r}")
  97. self.logger.info(f"Complete")
  98. return 0
  99. def core1bootloader(self):
  100. self.logger.info(f"Flashing bootloader")
  101. cp = CubeProgrammer(self._getCubeParams())
  102. cp.flashBin("0x08000000", self.args.bootloader)
  103. self.logger.info(f"Complete")
  104. cp.resetTarget()
  105. return 0
  106. def core1firmware(self):
  107. self.logger.info(f"Flashing firmware")
  108. cp = CubeProgrammer(self._getCubeParams())
  109. cp.flashBin("0x08008000", self.args.firmware)
  110. self.logger.info(f"Complete")
  111. cp.resetTarget()
  112. return 0
  113. def core1(self):
  114. self.logger.info(f"Flashing bootloader")
  115. cp = CubeProgrammer(self._getCubeParams())
  116. cp.flashBin("0x08000000", self.args.bootloader)
  117. self.logger.info(f"Flashing firmware")
  118. cp.flashBin("0x08008000", self.args.firmware)
  119. cp.resetTarget()
  120. self.logger.info(f"Complete")
  121. return 0
  122. def core2fus(self):
  123. if self.args.statement != STATEMENT:
  124. self.logger.error(
  125. f"PLEASE DON'T. THIS FEATURE INTENDED ONLY FOR FACTORY FLASHING"
  126. )
  127. return 1
  128. self.logger.info(f"Flashing Firmware Update Service")
  129. cp = CubeProgrammer(self._getCubeParams())
  130. cp.flashCore2(self.args.fus_address, self.args.fus)
  131. self.logger.info(f"Complete")
  132. return 0
  133. def core2radio(self):
  134. if int(self.args.radio_address, 16) > 0x080E0000:
  135. self.logger.error(f"I KNOW WHAT YOU DID LAST SUMMER")
  136. return 1
  137. cp = CubeProgrammer(self._getCubeParams())
  138. self.logger.info(f"Removing Current Radio Stack")
  139. cp.deleteCore2RadioStack()
  140. self.logger.info(f"Flashing Radio Stack")
  141. cp.flashCore2(self.args.radio_address, self.args.radio)
  142. self.logger.info(f"Complete")
  143. return 0
  144. if __name__ == "__main__":
  145. Main()()