flash.py 5.5 KB

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