[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:
@@ -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
34
scripts/ob_custradio.data
Normal 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
|
@@ -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
|
||||
|
Reference in New Issue
Block a user