diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index dd2ae76a1..858efb9fe 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -104,7 +104,7 @@ void animation_manager_set_dummy_mode_state(AnimationManager* animation_manager, } } -static void animation_manager_check_blocking_callback(const void* message, void* context) { +static void animation_manager_storage_callback(const void* message, void* context) { const StorageEvent* storage_event = message; switch(storage_event->type) { @@ -123,6 +123,22 @@ static void animation_manager_check_blocking_callback(const void* message, void* } } +static void animation_manager_dolphin_callback(const void* message, void* context) { + const DolphinPubsubEvent* dolphin_event = message; + + switch(*dolphin_event) { + case DolphinPubsubEventUpdate: + furi_assert(context); + AnimationManager* animation_manager = context; + if(animation_manager->check_blocking_callback) { + animation_manager->check_blocking_callback(animation_manager->context); + } + break; + default: + break; + } +} + static void animation_manager_timer_callback(void* context) { furi_assert(context); AnimationManager* animation_manager = context; @@ -300,12 +316,12 @@ AnimationManager* animation_manager_alloc(void) { Storage* storage = furi_record_open(RECORD_STORAGE); animation_manager->pubsub_subscription_storage = furi_pubsub_subscribe( - storage_get_pubsub(storage), animation_manager_check_blocking_callback, animation_manager); + storage_get_pubsub(storage), animation_manager_storage_callback, animation_manager); furi_record_close(RECORD_STORAGE); Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); animation_manager->pubsub_subscription_dolphin = furi_pubsub_subscribe( - dolphin_get_pubsub(dolphin), animation_manager_check_blocking_callback, animation_manager); + dolphin_get_pubsub(dolphin), animation_manager_dolphin_callback, animation_manager); furi_record_close(RECORD_DOLPHIN); animation_manager->blocking_shown_sd_ok = true; diff --git a/applications/services/dolphin/dolphin.c b/applications/services/dolphin/dolphin.c index dd2ecd2ba..501e37c3c 100644 --- a/applications/services/dolphin/dolphin.c +++ b/applications/services/dolphin/dolphin.c @@ -204,8 +204,8 @@ static bool dolphin_process_event(FuriEventLoopObject* object, void* context) { if(event.type == DolphinEventTypeDeed) { dolphin_state_on_deed(dolphin->state, event.deed); - DolphinPubsubEvent event = DolphinPubsubEventUpdate; - furi_pubsub_publish(dolphin->pubsub, &event); + DolphinPubsubEvent pubsub_event = DolphinPubsubEventUpdate; + furi_pubsub_publish(dolphin->pubsub, &pubsub_event); furi_event_loop_timer_start(dolphin->butthurt_timer, BUTTHURT_INCREASE_PERIOD_TICKS); furi_event_loop_timer_start(dolphin->flush_timer, FLUSH_TIMEOUT_TICKS); diff --git a/scripts/imglint.py b/scripts/imglint.py index fc63f3355..f25fea4f5 100644 --- a/scripts/imglint.py +++ b/scripts/imglint.py @@ -4,7 +4,7 @@ import os from pathlib import Path from flipper.app import App -from PIL import Image, ImageOps +from PIL import Image _logger = logging.getLogger(__name__) diff --git a/scripts/update.py b/scripts/update.py index e880bced8..47a5eeb27 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import io import math import os import shutil @@ -8,7 +7,6 @@ import tarfile import zlib from os.path import exists, join -import heatshrink2 from flipper.app import App from flipper.assets.coprobin import CoproBinary, get_stack_type from flipper.assets.heatshrink_stream import HeatshrinkDataStreamHeader @@ -35,7 +33,12 @@ class Main(App): ) FLASH_BASE = 0x8000000 - MIN_LFS_PAGES = 6 + FLASH_PAGE_SIZE = 4 * 1024 + MIN_GAP_PAGES = 2 + + # Update stage file larger than that is not loadable without fix + # https://github.com/flipperdevices/flipperzero-firmware/pull/3676 + UPDATER_SIZE_THRESHOLD = 128 * 1024 HEATSHRINK_WINDOW_SIZE = 13 HEATSHRINK_LOOKAHEAD_SIZE = 6 @@ -117,7 +120,7 @@ class Main(App): self.logger.error( f"You are trying to bundle a non-standard stack type '{self.args.radiotype}'." ) - self.disclaimer() + self.show_disclaimer() return 1 if radio_addr == 0: @@ -130,7 +133,9 @@ class Main(App): if not exists(self.args.directory): os.makedirs(self.args.directory) + updater_stage_size = os.stat(self.args.stage).st_size 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 @@ -146,10 +151,10 @@ class Main(App): ): return 3 - if not self.layout_check(dfu_size, radio_addr): + if not self.layout_check(updater_stage_size, dfu_size, radio_addr): self.logger.warn("Memory layout looks suspicious") - if not self.args.disclaimer == "yes": - self.disclaimer() + if self.args.disclaimer != "yes": + self.show_disclaimer() return 2 if self.args.splash: @@ -198,22 +203,33 @@ class Main(App): return 0 - def layout_check(self, fw_size, radio_addr): + def layout_check(self, stage_size, fw_size, radio_addr): + if stage_size > self.UPDATER_SIZE_THRESHOLD: + self.logger.warn( + f"Updater size {stage_size}b > {self.UPDATER_SIZE_THRESHOLD}b and is not loadable on older firmwares!" + ) + 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: + fw2stack_gap = radio_addr - self.FLASH_BASE - fw_size + self.logger.debug(f"Expected reserved space size: {fw2stack_gap}") + fw2stack_gap_pages = fw2stack_gap / self.FLASH_PAGE_SIZE + if fw2stack_gap_pages < 0: self.logger.warn( - f"Expected LFS size is too small (~{int(lfs_span_pages)} pages)" + f"Firmware image overlaps C2 region and is not programmable!" + ) + return False + + elif fw2stack_gap_pages < self.MIN_GAP_PAGES: + self.logger.warn( + f"Expected reserved flash size is too small (~{int(fw2stack_gap_pages)} page(s), need >={self.MIN_GAP_PAGES} page(s))" ) return False return True - def disclaimer(self): + def show_disclaimer(self): self.logger.error( "You might brick your device into a state in which you'd need an SWD programmer to fix it." )