unleashed-firmware/scripts/flash.py
hedger 7ce305fca3
[FL-2269] Core2 OTA (#1144)
* C2OTA: wip
* Update Cube to 1.13.3
* Fixed prio
* Functional Core2 updater
* Removed hardware CRC usage; code cleanup & linter fixes
* Moved hardcoded stack params to copro.mk
* Fixing CI bundling of core2 fw
* Removed last traces of hardcoded radio stack
* OB processing draft
* Python scripts cleanup
* Support for comments in ob data
* Sacrificed SD card icon in favor of faster update. Waiting for Storage fix
* Additional handling for OB mismatched values
* Description for new furi_hal apis; spelling fixes
* Rework of OB write, WIP
* Properly restarting OB verification loop
* Split update_task_workers.c
* Checking OBs after enabling post-update mode
* Moved OB verification before flashing
* Removed ob.data for custom stacks
* Fixed progress calculation for OB
* Removed unnecessary OB mask cast

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2022-04-27 18:53:48 +03:00

179 lines
6.4 KiB
Python
Executable file

#!/usr/bin/env python3
import logging
import argparse
import sys
import os
from flipper.app import App
from flipper.cube import CubeProgrammer
from flipper.assets.coprobin import CoproBinary
STATEMENT = "AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE"
class Main(App):
def init(self):
self.subparsers = self.parser.add_subparsers(help="sub-command help")
# Wipe
self.parser_wipe = self.subparsers.add_parser("wipe", help="Wipe MCU Flash")
self._addArgsSWD(self.parser_wipe)
self.parser_wipe.set_defaults(func=self.wipe)
# Core 1 boot
self.parser_core1bootloader = self.subparsers.add_parser(
"core1bootloader", help="Flash Core1 Bootloader"
)
self._addArgsSWD(self.parser_core1bootloader)
self.parser_core1bootloader.add_argument(
"bootloader", type=str, help="Bootloader binary"
)
self.parser_core1bootloader.set_defaults(func=self.core1bootloader)
# Core 1 firmware
self.parser_core1firmware = self.subparsers.add_parser(
"core1firmware", help="Flash Core1 Firmware"
)
self._addArgsSWD(self.parser_core1firmware)
self.parser_core1firmware.add_argument(
"firmware", type=str, help="Firmware binary"
)
self.parser_core1firmware.set_defaults(func=self.core1firmware)
# Core 1 all
self.parser_core1 = self.subparsers.add_parser(
"core1", help="Flash Core1 Bootloader and Firmware"
)
self._addArgsSWD(self.parser_core1)
self.parser_core1.add_argument("bootloader", type=str, help="Bootloader binary")
self.parser_core1.add_argument("firmware", type=str, help="Firmware binary")
self.parser_core1.set_defaults(func=self.core1)
# Core 2 fus
self.parser_core2fus = self.subparsers.add_parser(
"core2fus", help="Flash Core2 Firmware Update Service"
)
self._addArgsSWD(self.parser_core2fus)
self.parser_core2fus.add_argument(
"--statement",
type=str,
help="NEVER FLASH FUS, IT WILL ERASE CRYPTO ENCLAVE",
required=True,
)
self.parser_core2fus.add_argument(
"fus_address", type=str, help="Firmware Update Service Address"
)
self.parser_core2fus.add_argument(
"fus", type=str, help="Firmware Update Service Binary"
)
self.parser_core2fus.set_defaults(func=self.core2fus)
# Core 2 radio stack
self.parser_core2radio = self.subparsers.add_parser(
"core2radio", help="Flash Core2 Radio stack"
)
self._addArgsSWD(self.parser_core2radio)
self.parser_core2radio.add_argument(
"radio", type=str, help="Radio Stack Binary"
)
self.parser_core2radio.add_argument(
"--addr",
dest="radio_address",
help="Radio Stack Binary Address, as per release_notes",
type=lambda x: int(x, 16),
default=0,
required=False,
)
self.parser_core2radio.set_defaults(func=self.core2radio)
def _addArgsSWD(self, parser):
parser.add_argument(
"--port", type=str, help="Port to connect: swd or usb1", default="swd"
)
parser.add_argument("--serial", type=str, help="ST-Link Serial Number")
def _getCubeParams(self):
return {
"port": self.args.port,
"serial": self.args.serial,
}
def wipe(self):
self.logger.info(f"Wiping flash")
cp = CubeProgrammer(self._getCubeParams())
self.logger.info(f"Setting RDP to 0xBB")
cp.setOptionBytes({"RDP": ("0xBB", "rw")})
self.logger.info(f"Verifying RDP")
r = cp.checkOptionBytes({"RDP": ("0xBB", "rw")})
assert r == True
self.logger.info(f"Result: {r}")
self.logger.info(f"Setting RDP to 0xAA")
cp.setOptionBytes({"RDP": ("0xAA", "rw")})
self.logger.info(f"Verifying RDP")
r = cp.checkOptionBytes({"RDP": ("0xAA", "rw")})
assert r == True
self.logger.info(f"Result: {r}")
self.logger.info(f"Complete")
return 0
def core1bootloader(self):
self.logger.info(f"Flashing bootloader")
cp = CubeProgrammer(self._getCubeParams())
cp.flashBin("0x08000000", self.args.bootloader)
self.logger.info(f"Complete")
cp.resetTarget()
return 0
def core1firmware(self):
self.logger.info(f"Flashing firmware")
cp = CubeProgrammer(self._getCubeParams())
cp.flashBin("0x08008000", self.args.firmware)
self.logger.info(f"Complete")
cp.resetTarget()
return 0
def core1(self):
self.logger.info(f"Flashing bootloader")
cp = CubeProgrammer(self._getCubeParams())
cp.flashBin("0x08000000", self.args.bootloader)
self.logger.info(f"Flashing firmware")
cp.flashBin("0x08008000", self.args.firmware)
cp.resetTarget()
self.logger.info(f"Complete")
return 0
def core2fus(self):
if self.args.statement != STATEMENT:
self.logger.error(
f"PLEASE DON'T. THIS FEATURE INTENDED ONLY FOR FACTORY FLASHING"
)
return 1
self.logger.info(f"Flashing Firmware Update Service")
cp = CubeProgrammer(self._getCubeParams())
cp.flashCore2(self.args.fus_address, self.args.fus)
self.logger.info(f"Complete")
return 0
def core2radio(self):
stack_info = CoproBinary(self.args.radio)
if not stack_info.is_stack():
self.logger.error("Not a Radio Stack")
return 1
self.logger.info(f"Will flash {stack_info.img_sig.get_version()}")
radio_address = self.args.radio_address
if not radio_address:
radio_address = stack_info.get_flash_load_addr()
self.logger.warning(
f"Radio address not provided, guessed as 0x{radio_address:X}"
)
if radio_address > 0x080E0000:
self.logger.error(f"I KNOW WHAT YOU DID LAST SUMMER")
return 1
cp = CubeProgrammer(self._getCubeParams())
self.logger.info(f"Removing Current Radio Stack")
cp.deleteCore2RadioStack()
self.logger.info(f"Flashing Radio Stack")
cp.flashCore2(radio_address, self.args.radio)
self.logger.info(f"Complete")
return 0
if __name__ == "__main__":
Main()()