[FL-2580] FuriHal: add more supported radio stacks (#1301)

* FuriHal: add more supported radio stacks
* Bt: correct ble stack enum value
* Bt: update cli testing commands implementation
* Scripts: always emitting ob data to update manifest; added ob_custradio.data for non-light radio stacks
* Scripts: added stack type whitelist & disclaimer message
* ble: remove scanner
* ble: remove HCI and advances ble stacks support
* bt: correctly close RPC session before bt reinit
* Scripts: update bundler: estimating flash layout & refusing to build dangerous packages; app frame: not adding redundant log handlers
* Docs: additional details on bundling updates; fixed updater error codes
* Docs: wording fixes for OTA.md

Co-authored-by: hedger <hedger@nanode.su>
Co-authored-by: gornekich <n.gorbadey@gmail.com>
Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
あく
2022-06-09 18:07:42 +09:00
committed by GitHub
parent 2bd4efd044
commit 936a2f64b2
18 changed files with 280 additions and 192 deletions

View File

@@ -15,16 +15,20 @@ class App:
# Application specific initialization
self.init()
def __call__(self, args=None):
def __call__(self, args=None, skip_logger_init=False):
self.args, self.other_args = self.parser.parse_known_args(args=args)
# configure log output
# if skip_logger_init:
self.log_level = logging.DEBUG if self.args.debug else logging.INFO
self.logger.setLevel(self.log_level)
self.handler = logging.StreamHandler(sys.stdout)
self.handler.setLevel(self.log_level)
self.formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
self.handler.setFormatter(self.formatter)
self.logger.addHandler(self.handler)
if not self.logger.hasHandlers():
self.handler = logging.StreamHandler(sys.stdout)
self.handler.setLevel(self.log_level)
self.formatter = logging.Formatter(
"%(asctime)s [%(levelname)s] %(message)s"
)
self.handler.setFormatter(self.formatter)
self.logger.addHandler(self.handler)
# execute requested function
self.before()

34
scripts/ob_custradio.data Normal file
View File

@@ -0,0 +1,34 @@
RDP:0xAA:r
BOR_LEV:0x4:rw
nBOOT0:0x1:r
nBOOT1:0x1:rw
nSWBOOT0:0x1:rw
SRAM2RST:0x0:rw
SRAM2PE:0x1:rw
nRST_STOP:0x1:rw
nRST_STDBY:0x1:rw
nRSTSHDW:0x1:rw
WWDGSW:0x1:rw
IWGDSTDBY:0x1:rw
IWDGSTOP:0x1:rw
IWDGSW:0x1:rw
IPCCDBA:0x0:rw
ESE:0x1:r
#SFSA:0xD7:r
FSD:0x0:r
DDS:0x1:r
#C2OPT:0x1:r
#NBRSD:0x0:r
#SNBRSA:0xD:r
#BRSD:0x0:r
#SBRSA:0x12:r
#SBRV:0x35C00:r
PCROP1A_STRT:0x1FF:r
PCROP1A_END:0x0:r
PCROP_RDP:0x1:rw
PCROP1B_STRT:0x1FF:r
PCROP1B_END:0x0:r
WRP1A_STRT:0xFF:r
WRP1A_END:0x0:r
WRP1B_STRT:0xFF:r
WRP1B_END:0x0:r

View File

@@ -3,7 +3,7 @@
from flipper.app import App
from flipper.utils.fff import FlipperFormatFile
from flipper.assets.coprobin import CoproBinary, get_stack_type
from flipper.assets.obdata import OptionBytesData
from flipper.assets.obdata import OptionBytesData, ObReferenceValues
from os.path import basename, join, exists
import os
import shutil
@@ -21,6 +21,16 @@ class Main(App):
RESOURCE_TAR_FORMAT = tarfile.USTAR_FORMAT
RESOURCE_FILE_NAME = "resources.tar"
WHITELISTED_STACK_TYPES = set(
map(
get_stack_type,
["BLE_FULL", "BLE_LIGHT", "BLE_BASIC"],
)
)
FLASH_BASE = 0x8000000
MIN_LFS_PAGES = 6
def init(self):
self.subparsers = self.parser.add_subparsers(help="sub-command help")
@@ -53,6 +63,9 @@ class Main(App):
)
self.parser_generate.add_argument("--obdata", dest="obdata", required=False)
self.parser_generate.add_argument(
"--I-understand-what-I-am-doing", dest="disclaimer", required=False
)
self.parser_generate.set_defaults(func=self.generate)
@@ -70,10 +83,20 @@ class Main(App):
raise ValueError("Missing --radiotype")
radio_meta = CoproBinary(self.args.radiobin)
radio_version = self.copro_version_as_int(radio_meta, self.args.radiotype)
if (
get_stack_type(self.args.radiotype) not in self.WHITELISTED_STACK_TYPES
and self.args.disclaimer != "yes"
):
self.logger.error(
f"You are trying to bundle a non-standard stack type '{self.args.radiotype}'."
)
self.disclaimer()
return 1
if radio_addr == 0:
radio_addr = radio_meta.get_flash_load_addr()
self.logger.info(
f"Using guessed radio address 0x{radio_addr:X}, verify with Release_Notes"
f"Using guessed radio address 0x{radio_addr:08X}, verify with Release_Notes"
" or specify --radioaddr"
)
@@ -81,7 +104,9 @@ class Main(App):
os.makedirs(self.args.directory)
shutil.copyfile(self.args.stage, join(self.args.directory, stage_basename))
dfu_size = 0
if self.args.dfu:
dfu_size = os.stat(self.args.dfu).st_size
shutil.copyfile(self.args.dfu, join(self.args.directory, dfu_basename))
if radiobin_basename:
shutil.copyfile(
@@ -93,6 +118,12 @@ class Main(App):
self.args.resources, join(self.args.directory, resources_basename)
)
if not self.layout_check(dfu_size, radio_addr):
self.logger.warn("Memory layout looks suspicious")
if not self.args.disclaimer == "yes":
self.disclaimer()
return 2
file = FlipperFormatFile()
file.setHeader(
"Flipper firmware upgrade configuration", self.UPDATE_MANIFEST_VERSION
@@ -111,19 +142,43 @@ class Main(App):
else:
file.writeKey("Radio CRC", self.int2ffhex(0))
file.writeKey("Resources", resources_basename)
file.writeComment(
"NEVER EVER MESS WITH THESE VALUES, YOU WILL BRICK YOUR DEVICE"
)
obvalues = ObReferenceValues((), (), ())
if self.args.obdata:
obd = OptionBytesData(self.args.obdata)
obvalues = obd.gen_values().export()
file.writeKey("OB reference", self.bytes2ffhex(obvalues.reference))
file.writeKey("OB mask", self.bytes2ffhex(obvalues.compare_mask))
file.writeKey("OB write mask", self.bytes2ffhex(obvalues.write_mask))
file.writeComment(
"NEVER EVER MESS WITH THESE VALUES, YOU WILL BRICK YOUR DEVICE"
)
file.writeKey("OB reference", self.bytes2ffhex(obvalues.reference))
file.writeKey("OB mask", self.bytes2ffhex(obvalues.compare_mask))
file.writeKey("OB write mask", self.bytes2ffhex(obvalues.write_mask))
file.save(join(self.args.directory, self.UPDATE_MANIFEST_NAME))
return 0
def layout_check(self, fw_size, radio_addr):
if fw_size == 0 or radio_addr == 0:
self.logger.info("Cannot validate layout for partial package")
return True
lfs_span = radio_addr - self.FLASH_BASE - fw_size
self.logger.debug(f"Expected LFS size: {lfs_span}")
lfs_span_pages = lfs_span / (4 * 1024)
if lfs_span_pages < self.MIN_LFS_PAGES:
self.logger.warn(
f"Expected LFS size is too small (~{int(lfs_span_pages)} pages)"
)
return False
return True
def disclaimer(self):
self.logger.error(
"You might brick you device into a state in which you'd need an SWD programmer to fix it."
)
self.logger.error(
"Please confirm that you REALLY want to do that with --I-understand-what-I-am-doing=yes"
)
def package_resources(self, srcdir: str, dst_name: str):
with tarfile.open(
dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT