Merge branch 'ofwdev' into 420

This commit is contained in:
RogueMaster
2022-11-05 14:23:42 -04:00
56 changed files with 255 additions and 213 deletions

View File

@@ -43,6 +43,7 @@ distenv = coreenv.Clone(
"jflash",
],
ENV=os.environ,
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
)
firmware_env = distenv.AddFwProject(
@@ -140,21 +141,28 @@ distenv.Default(basic_dist)
dist_dir = distenv.GetProjetDirName()
fap_dist = [
distenv.Install(
f"#/dist/{dist_dir}/apps/debug_elf",
firmware_env["FW_EXTAPPS"]["debug"].values(),
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
list(
app_artifact.debug
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
),
),
*(
distenv.Install(f"#/dist/{dist_dir}/apps/{dist_entry[0]}", dist_entry[1])
for dist_entry in firmware_env["FW_EXTAPPS"]["dist"].values()
distenv.Install(
f"#/dist/{dist_dir}/apps",
"#/assets/resources/apps",
),
]
Depends(fap_dist, firmware_env["FW_EXTAPPS"]["validators"].values())
Depends(
fap_dist,
list(
app_artifact.validator
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
),
)
Alias("fap_dist", fap_dist)
# distenv.Default(fap_dist)
distenv.Depends(
firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"]["resources_dist"]
)
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
# Target for bundling core2 package for qFlipper
@@ -192,6 +200,7 @@ firmware_debug = distenv.PhonyTarget(
source=firmware_env["FW_ELF"],
GDBOPTS="${GDBOPTS_BASE}",
GDBREMOTE="${OPENOCD_GDB_PIPE}",
FBT_FAP_DEBUG_ELF_ROOT=firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT"),
)
distenv.Depends(firmware_debug, firmware_flash)
@@ -201,6 +210,7 @@ distenv.PhonyTarget(
source=firmware_env["FW_ELF"],
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
GDBREMOTE="${BLACKMAGIC_ADDR}",
FBT_FAP_DEBUG_ELF_ROOT=firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT"),
)
# Debug alien elf
@@ -209,7 +219,7 @@ distenv.PhonyTarget(
"${GDBPYCOM}",
GDBOPTS="${GDBOPTS_BASE}",
GDBREMOTE="${OPENOCD_GDB_PIPE}",
GDBPYOPTS='-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ',
GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ',
)
distenv.PhonyTarget(

View File

@@ -14,4 +14,5 @@ App(
fap_category="Main",
fap_icon="badusb_10px.png",
fap_icon_assets="images",
fap_libs=["assets"],
)

View File

@@ -347,10 +347,6 @@ static int32_t
furi_hal_hid_kb_release(key);
return (0);
}
if(error != NULL) {
strncpy(error, "Unknown error", error_len);
}
return SCRIPT_STATE_ERROR;
}
static bool ducky_set_usb_id(BadUsbScript* bad_usb, const char* line) {
@@ -679,7 +675,7 @@ static void bad_usb_script_set_default_keyboard_layout(BadUsbScript* bad_usb) {
BadUsbScript* bad_usb_script_open(FuriString* file_path) {
furi_assert(file_path);
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); //-V773
bad_usb->file_path = furi_string_alloc();
furi_string_set(bad_usb->file_path, file_path);
bad_usb_script_set_default_keyboard_layout(bad_usb);

View File

@@ -168,7 +168,7 @@ static bool fap_loader_select_app(FapLoader* loader) {
}
static FapLoader* fap_loader_alloc(const char* path) {
FapLoader* loader = malloc(sizeof(FapLoader));
FapLoader* loader = malloc(sizeof(FapLoader)); //-V773
char* tmp = malloc(strlen(path) + 1);
strcpy(tmp, path);

View File

@@ -11,4 +11,5 @@ App(
fap_icon="gpioIcon.png",
fap_category="Main",
fap_icon_assets="images",
fap_libs=["assets"],
)

View File

@@ -184,7 +184,7 @@ static int32_t usb_uart_worker(void* context) {
while(1) {
uint32_t events =
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
furi_check((events & FuriFlagError) == 0);
furi_check(!(events & FuriFlagError));
if(events & WorkerEvtStop) break;
if(events & WorkerEvtRxDone) {
size_t len = furi_stream_buffer_receive(
@@ -288,7 +288,7 @@ static int32_t usb_uart_tx_thread(void* context) {
while(1) {
uint32_t events =
furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
furi_check((events & FuriFlagError) == 0);
furi_check(!(events & FuriFlagError));
if(events & WorkerEvtTxStop) break;
if(events & WorkerEvtCdcRx) {
furi_check(furi_mutex_acquire(usb_uart->usb_mutex, FuriWaitForever) == FuriStatusOk);

View File

@@ -14,4 +14,5 @@ App(
fap_icon="iBIcon.png",
fap_category="Main",
fap_icon_assets="images",
fap_libs=["assets"],
)

View File

@@ -15,4 +15,5 @@ App(
fap_category="Main",
fap_icon="ir_10px.png",
fap_icon_assets="images",
fap_libs=["assets"],
)

View File

@@ -15,12 +15,5 @@ App(
fap_category="Main",
fap_icon="125_10px.png",
fap_icon_assets="images",
)
App(
appid="lfrfid_start",
apptype=FlipperAppType.STARTUP,
entry_point="lfrfid_on_system_start",
requires=["lfrfid"],
order=50,
fap_libs=["assets"],
)

View File

@@ -32,7 +32,7 @@ static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
}
static LfRfid* lfrfid_alloc() {
LfRfid* lfrfid = malloc(sizeof(LfRfid));
LfRfid* lfrfid = malloc(sizeof(LfRfid)); //-V773
lfrfid->storage = furi_record_open(RECORD_STORAGE);
lfrfid->dialogs = furi_record_open(RECORD_DIALOGS);

View File

@@ -24,7 +24,7 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) {
widget_add_button_element(
widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc);
FuriString* temp_str;
FuriString* temp_str = NULL;
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
} else {

View File

@@ -31,7 +31,7 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) {
nfc_scene_mf_ultralight_read_success_widget_callback,
nfc);
FuriString* temp_str;
FuriString* temp_str = NULL;
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
} else {

View File

@@ -520,12 +520,6 @@ bool subghz_path_is_file(FuriString* path) {
}
uint32_t subghz_random_serial(void) {
static bool rand_generator_inited = false;
if(!rand_generator_inited) {
srand(DWT->CYCCNT);
rand_generator_inited = true;
}
return (uint32_t)rand();
}

View File

@@ -14,4 +14,5 @@ App(
fap_icon="U2FIcon.png",
fap_category="Main",
fap_icon_assets="images",
fap_libs=["assets"],
)

View File

@@ -203,7 +203,7 @@ static int32_t u2f_hid_worker(void* context) {
WorkerEvtStop | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtRequest,
FuriFlagWaitAny,
FuriWaitForever);
furi_check((flags & FuriFlagError) == 0);
furi_check(!(flags & FuriFlagError));
if(flags & WorkerEvtStop) break;
if(flags & WorkerEvtConnect) {
u2f_set_state(u2f_hid->u2f_instance, 1);

View File

@@ -294,7 +294,6 @@ static void
int32_t snake_game_app(void* p) {
UNUSED(p);
srand(DWT->CYCCNT);
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent));

View File

@@ -200,7 +200,6 @@ void ws_protocol_decoder_ambient_weather_feed(void* context, bool level, uint32_
((instance->decoder.decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) ==
AMBIENT_WEATHER_PACKET_HEADER_2)) {
if(ws_protocol_ambient_weather_check_crc(instance)) {
instance->decoder.decode_data = instance->decoder.decode_data;
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit =
ws_protocol_ambient_weather_const.min_count_bit_for_found;

View File

@@ -61,15 +61,20 @@ static void gpio_print_pins(void) {
}
}
typedef enum { OK, ERR_CMD_SYNTAX, ERR_PIN, ERR_VALUE } GpioParseError;
typedef enum {
GpioParseReturnOk,
GpioParseReturnCmdSyntaxError,
GpioParseReturnPinError,
GpioParseReturnValueError
} GpioParseReturn;
static GpioParseError gpio_command_parse(FuriString* args, size_t* pin_num, uint8_t* value) {
static GpioParseReturn gpio_command_parse(FuriString* args, size_t* pin_num, uint8_t* value) {
FuriString* pin_name;
pin_name = furi_string_alloc();
size_t ws = furi_string_search_char(args, ' ');
if(ws == FURI_STRING_FAILURE) {
return ERR_CMD_SYNTAX;
return GpioParseReturnCmdSyntaxError;
}
furi_string_set_n(pin_name, args, 0, ws);
@@ -78,7 +83,7 @@ static GpioParseError gpio_command_parse(FuriString* args, size_t* pin_num, uint
if(!pin_name_to_int(pin_name, pin_num)) {
furi_string_free(pin_name);
return ERR_PIN;
return GpioParseReturnPinError;
}
furi_string_free(pin_name);
@@ -88,10 +93,10 @@ static GpioParseError gpio_command_parse(FuriString* args, size_t* pin_num, uint
} else if(!furi_string_cmp(args, "1")) {
*value = 1;
} else {
return ERR_VALUE;
return GpioParseReturnValueError;
}
return OK;
return GpioParseReturnOk;
}
void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) {
@@ -101,15 +106,15 @@ void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) {
size_t num = 0;
uint8_t value = 255;
GpioParseError err = gpio_command_parse(args, &num, &value);
GpioParseReturn err = gpio_command_parse(args, &num, &value);
if(ERR_CMD_SYNTAX == err) {
if(err == GpioParseReturnCmdSyntaxError) {
cli_print_usage("gpio mode", "<pin_name> <0|1>", furi_string_get_cstr(args));
return;
} else if(ERR_PIN == err) {
} else if(err == GpioParseReturnPinError) {
gpio_print_pins();
return;
} else if(ERR_VALUE == err) {
} else if(err == GpioParseReturnValueError) {
printf("Value is invalid. Enter 1 for input or 0 for output");
return;
}
@@ -161,15 +166,15 @@ void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) {
size_t num = 0;
uint8_t value = 0;
GpioParseError err = gpio_command_parse(args, &num, &value);
GpioParseReturn err = gpio_command_parse(args, &num, &value);
if(ERR_CMD_SYNTAX == err) {
if(err == GpioParseReturnCmdSyntaxError) {
cli_print_usage("gpio set", "<pin_name> <0|1>", furi_string_get_cstr(args));
return;
} else if(ERR_PIN == err) {
} else if(err == GpioParseReturnPinError) {
gpio_print_pins();
return;
} else if(ERR_VALUE == err) {
} else if(err == GpioParseReturnValueError) {
printf("Value is invalid. Enter 1 for high or 0 for low");
return;
}

View File

@@ -103,7 +103,7 @@ static int32_t vcp_worker(void* context) {
while(1) {
uint32_t flags =
furi_thread_flags_wait(VCP_THREAD_FLAG_ALL, FuriFlagWaitAny, FuriWaitForever);
furi_assert((flags & FuriFlagError) == 0);
furi_assert(!(flags & FuriFlagError));
// VCP session opened
if(flags & VcpEvtConnect) {
@@ -303,7 +303,7 @@ static void vcp_on_cdc_control_line(void* context, uint8_t state) {
static void vcp_on_cdc_rx(void* context) {
UNUSED(context);
uint32_t ret = furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtRx);
furi_check((ret & FuriFlagError) == 0);
furi_check(!(ret & FuriFlagError));
}
static void vcp_on_cdc_tx_complete(void* context) {

View File

@@ -167,7 +167,7 @@ void crypto_cli_decrypt(Cli* cli, FuriString* args) {
void crypto_cli_has_key(Cli* cli, FuriString* args) {
UNUSED(cli);
int key_slot = 0;
uint8_t iv[16];
uint8_t iv[16] = {0};
do {
if(!args_read_int_and_trim(args, &key_slot) || !(key_slot > 0 && key_slot <= 100)) {
@@ -249,7 +249,7 @@ void crypto_cli_store_key(Cli* cli, FuriString* args) {
}
if(key_slot > 0) {
uint8_t iv[16];
uint8_t iv[16] = {0};
if(key_slot > 1) {
if(!furi_hal_crypto_store_load_key(key_slot - 1, iv)) {
printf(

View File

@@ -419,7 +419,7 @@ void gui_add_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, vo
const CanvasCallbackPair p = {callback, context};
gui_lock(gui);
furi_assert(CanvasCallbackPairArray_count(gui->canvas_callback_pair, p) == 0);
furi_assert(!CanvasCallbackPairArray_count(gui->canvas_callback_pair, p));
CanvasCallbackPairArray_push_back(gui->canvas_callback_pair, p);
gui_unlock(gui);

View File

@@ -363,7 +363,7 @@ static int32_t browser_worker(void* context) {
BrowserWorker*
file_browser_worker_alloc(FuriString* path, const char* filter_ext, bool skip_assets) {
BrowserWorker* browser = malloc(sizeof(BrowserWorker));
BrowserWorker* browser = malloc(sizeof(BrowserWorker)); //-V773
idx_last_array_init(browser->idx_last);

View File

@@ -60,7 +60,7 @@ WidgetElement* widget_element_button_create(
ButtonCallback callback,
void* context) {
// Allocate and init model
GuiButtonModel* model = malloc(sizeof(GuiButtonModel));
GuiButtonModel* model = malloc(sizeof(GuiButtonModel)); //-V773
model->button_type = button_type;
model->callback = callback;
model->context = context;

View File

@@ -23,7 +23,7 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) {
gui_remove_view_port(view_dispatcher->gui, view_dispatcher->view_port);
}
// Crash if not all views were freed
furi_assert(ViewDict_size(view_dispatcher->views) == 0);
furi_assert(!ViewDict_size(view_dispatcher->views));
ViewDict_clear(view_dispatcher->views);
// Free ViewPort
@@ -157,7 +157,7 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_
view_dispatcher->ongoing_input_view = NULL;
}
// Remove view
ViewDict_erase(view_dispatcher->views, view_id);
furi_check(ViewDict_erase(view_dispatcher->views, view_id));
view_set_update_callback(view, NULL);
view_set_update_callback_context(view, NULL);

View File

@@ -280,7 +280,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
event.type = LoaderEventTypeApplicationStarted;
furi_pubsub_publish(loader_instance->pubsub, &event);
if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) {
if(!(loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe)) {
furi_hal_power_insomnia_enter();
}
} else if(thread_state == FuriThreadStateStopped) {
@@ -295,7 +295,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
loader_instance->application_arguments = NULL;
}
if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) {
if(!(loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe)) {
furi_hal_power_insomnia_exit();
}
loader_unlock(instance);

View File

@@ -275,7 +275,7 @@ static void storage_cli_read_chunks(Cli* cli, FuriString* path, FuriString* args
uint32_t buffer_size;
int parsed_count = sscanf(furi_string_get_cstr(args), "%lu", &buffer_size);
if(parsed_count == EOF || parsed_count != 1) {
if(parsed_count != 1) {
storage_cli_print_usage();
} else if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint64_t file_size = storage_file_size(file);
@@ -315,7 +315,7 @@ static void storage_cli_write_chunk(Cli* cli, FuriString* path, FuriString* args
uint32_t buffer_size;
int parsed_count = sscanf(furi_string_get_cstr(args), "%lu", &buffer_size);
if(parsed_count == EOF || parsed_count != 1) {
if(parsed_count != 1) {
storage_cli_print_usage();
} else {
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) {

View File

@@ -545,8 +545,8 @@ static FS_Error
FS_Error storage_common_merge(Storage* storage, const char* old_path, const char* new_path) {
FS_Error error;
const char* new_path_tmp;
FuriString* new_path_next;
const char* new_path_tmp = NULL;
FuriString* new_path_next = NULL;
new_path_next = furi_string_alloc();
FileInfo fileinfo;

View File

@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import Tuple, Dict
from typing import Optional, Tuple, Dict, ClassVar
import struct
import posixpath
import os
@@ -22,14 +22,18 @@ class AppState:
debug_link_elf: str = ""
debug_link_crc: int = 0
DEBUG_ELF_ROOT: ClassVar[Optional[str]] = None
def __post_init__(self):
if self.other_sections is None:
self.other_sections = {}
def get_original_elf_path(self, elf_path="build/latest/.extapps") -> str:
def get_original_elf_path(self) -> str:
if self.DEBUG_ELF_ROOT is None:
raise ValueError("DEBUG_ELF_ROOT not set; call fap-set-debug-elf-root")
return (
posixpath.join(elf_path, self.debug_link_elf)
if elf_path
posixpath.join(self.DEBUG_ELF_ROOT, self.debug_link_elf)
if self.DEBUG_ELF_ROOT
else self.debug_link_elf
)
@@ -84,7 +88,9 @@ class AppState:
if debug_link_size := int(app_state["debug_link_info"]["debug_link_size"]):
debug_link_data = (
gdb.selected_inferior()
.read_memory(int(app_state["debug_link_info"]["debug_link"]), debug_link_size)
.read_memory(
int(app_state["debug_link_info"]["debug_link"]), debug_link_size
)
.tobytes()
)
state.debug_link_elf, state.debug_link_crc = AppState.parse_debug_link_data(
@@ -103,6 +109,29 @@ class AppState:
return state
class SetFapDebugElfRoot(gdb.Command):
"""Set path to original ELF files for debug info"""
def __init__(self):
super().__init__(
"fap-set-debug-elf-root", gdb.COMMAND_FILES, gdb.COMPLETE_FILENAME
)
self.dont_repeat()
def invoke(self, arg, from_tty):
AppState.DEBUG_ELF_ROOT = arg
try:
global helper
print(f"Set '{arg}' as debug info lookup path for Flipper external apps")
helper.attach_fw()
gdb.events.stop.connect(helper.handle_stop)
except gdb.error as e:
print(f"Support for Flipper external apps debug is not available: {e}")
SetFapDebugElfRoot()
class FlipperAppDebugHelper:
def __init__(self):
self.app_ptr = None
@@ -149,9 +178,4 @@ class FlipperAppDebugHelper:
helper = FlipperAppDebugHelper()
try:
helper.attach_fw()
print("Support for Flipper external apps debug is enabled")
gdb.events.stop.connect(helper.handle_stop)
except gdb.error as e:
print(f"Support for Flipper external apps debug is not available: {e}")
print("Support for Flipper external apps debug is loaded")

View File

@@ -49,12 +49,12 @@ OPENOCD_OPTS = [
"-c",
"transport select hla_swd",
"-f",
"debug/stm32wbx.cfg",
"${FBT_DEBUG_DIR}/stm32wbx.cfg",
"-c",
"stm32wbx.cpu configure -rtos auto",
]
SVD_FILE = "debug/STM32WB55_CM4.svd"
SVD_FILE = "${FBT_DEBUG_DIR}/STM32WB55_CM4.svd"
# Look for blackmagic probe on serial ports and local network
BLACKMAGIC = "auto"

View File

@@ -20,8 +20,7 @@ env = ENV.Clone(
BUILD_DIR=fw_build_meta["build_dir"],
IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware",
FW_FLAVOR=fw_build_meta["flavor"],
PLUGIN_ELF_DIR="${BUILD_DIR}",
LIB_DIST_DIR="${BUILD_DIR}/lib",
LIB_DIST_DIR=fw_build_meta["build_dir"].Dir("lib"),
LINT_SOURCES=[
"applications",
],
@@ -142,12 +141,14 @@ for app_dir, _ in env["APPDIRS"]:
fwenv.PrepareApplicationsBuild()
# Build external apps
# Build external apps + configure SDK
if env["IS_BASE_FIRMWARE"]:
extapps = fwenv["FW_EXTAPPS"] = SConscript(
"site_scons/extapps.scons", exports={"ENV": fwenv}
fwenv.SetDefault(FBT_FAP_DEBUG_ELF_ROOT="${BUILD_DIR}/.extapps")
fwenv["FW_EXTAPPS"] = SConscript(
"site_scons/extapps.scons",
exports={"ENV": fwenv},
)
fw_artifacts.append(extapps["sdk_tree"])
fw_artifacts.append(fwenv["FW_EXTAPPS"].sdk_tree)
# Add preprocessor definitions for current set of apps

View File

@@ -179,7 +179,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
case EVT_BLUE_GAP_PASS_KEY_REQUEST: {
// Generate random PIN code
uint32_t pin = rand() % 999999;
uint32_t pin = rand() % 999999; //-V1064
aci_gap_pass_key_resp(gap->service.connection_handle, pin);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) {
FURI_LOG_I(TAG, "Pass key request event. Pin: ******");
@@ -478,7 +478,6 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
gap = malloc(sizeof(Gap));
gap->config = config;
srand(DWT->CYCCNT);
// Create advertising timer
gap->advertise_timer = furi_timer_alloc(gap_advetise_timer_callback, FuriTimerTypeOnce, NULL);
// Initialization of GATT & GAP layer

View File

@@ -91,7 +91,7 @@ bool furi_hal_crypto_verify_key(uint8_t key_slot) {
uint8_t keys_nb = 0;
uint8_t valid_keys_nb = 0;
uint8_t last_valid_slot = ENCLAVE_FACTORY_KEY_SLOTS;
uint8_t empty_iv[16];
uint8_t empty_iv[16] = {0};
furi_hal_crypto_verify_enclave(&keys_nb, &valid_keys_nb);
if(key_slot <= ENCLAVE_FACTORY_KEY_SLOTS) { // It's a factory key
if(key_slot > keys_nb) return false;

View File

@@ -46,7 +46,7 @@ FURI_NORETURN void __furi_halt();
/** Check condition and crash if check failed */
#define furi_check(__e) \
do { \
if((__e) == 0) { \
if(!(__e)) { \
furi_crash("furi_check failed\r\n"); \
} \
} while(0)
@@ -55,7 +55,7 @@ FURI_NORETURN void __furi_halt();
#ifdef FURI_DEBUG
#define furi_assert(__e) \
do { \
if((__e) == 0) { \
if(!(__e)) { \
furi_crash("furi_assert failed\r\n"); \
} \
} while(0)

View File

@@ -25,7 +25,7 @@ uint32_t furi_event_flag_set(FuriEventFlag* instance, uint32_t flags) {
uint32_t rflags;
BaseType_t yield;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
yield = pdFALSE;
if(xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
rflags = (uint32_t)FuriStatusErrorResource;
@@ -48,7 +48,7 @@ uint32_t furi_event_flag_clear(FuriEventFlag* instance, uint32_t flags) {
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)instance;
uint32_t rflags;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
rflags = xEventGroupGetBitsFromISR(hEventGroup);
if(xEventGroupClearBitsFromISR(hEventGroup, (EventBits_t)flags) == pdFAIL) {
@@ -73,7 +73,7 @@ uint32_t furi_event_flag_get(FuriEventFlag* instance) {
EventGroupHandle_t hEventGroup = (EventGroupHandle_t)instance;
uint32_t rflags;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
rflags = xEventGroupGetBitsFromISR(hEventGroup);
} else {
rflags = xEventGroupGetBits(hEventGroup);

View File

@@ -150,8 +150,7 @@ void memmgr_heap_disable_thread_trace(FuriThreadId thread_id) {
vTaskSuspendAll();
{
memmgr_heap_thread_trace_depth++;
furi_check(MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id) != NULL);
MemmgrHeapThreadDict_erase(memmgr_heap_thread_dict, (uint32_t)thread_id);
furi_check(MemmgrHeapThreadDict_erase(memmgr_heap_thread_dict, (uint32_t)thread_id));
memmgr_heap_thread_trace_depth--;
}
(void)xTaskResumeAll();
@@ -212,7 +211,8 @@ static inline void traceFREE(void* pointer, size_t size) {
MemmgrHeapAllocDict_t* alloc_dict =
MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id);
if(alloc_dict) {
MemmgrHeapAllocDict_erase(*alloc_dict, (uint32_t)pointer);
// In some cases thread may want to release memory that was not allocated by it
(void)MemmgrHeapAllocDict_erase(*alloc_dict, (uint32_t)pointer);
}
memmgr_heap_thread_trace_depth--;
}

View File

@@ -45,7 +45,7 @@ FuriStatus furi_mutex_acquire(FuriMutex* instance, uint32_t timeout) {
stat = FuriStatusOk;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
stat = FuriStatusErrorISR;
} else if(hMutex == NULL) {
stat = FuriStatusErrorParameter;
@@ -85,7 +85,7 @@ FuriStatus furi_mutex_release(FuriMutex* instance) {
stat = FuriStatusOk;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
stat = FuriStatusErrorISR;
} else if(hMutex == NULL) {
stat = FuriStatusErrorParameter;
@@ -111,7 +111,7 @@ FuriThreadId furi_mutex_get_owner(FuriMutex* instance) {
hMutex = (SemaphoreHandle_t)((uint32_t)instance & ~1U);
if((FURI_IS_IRQ_MODE() != 0U) || (hMutex == NULL)) {
if((FURI_IS_IRQ_MODE()) || (hMutex == NULL)) {
owner = 0;
} else {
owner = (FuriThreadId)xSemaphoreGetMutexHolder(hMutex);

View File

@@ -45,7 +45,7 @@ FuriStatus furi_semaphore_acquire(FuriSemaphore* instance, uint32_t timeout) {
stat = FuriStatusOk;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
if(timeout != 0U) {
stat = FuriStatusErrorParameter;
} else {
@@ -80,7 +80,7 @@ FuriStatus furi_semaphore_release(FuriSemaphore* instance) {
stat = FuriStatusOk;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
yield = pdFALSE;
if(xSemaphoreGiveFromISR(hSemaphore, &yield) != pdTRUE) {
@@ -104,7 +104,7 @@ uint32_t furi_semaphore_get_count(FuriSemaphore* instance) {
SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)instance;
uint32_t count;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
count = (uint32_t)uxSemaphoreGetCountFromISR(hSemaphore);
} else {
count = (uint32_t)uxSemaphoreGetCount(hSemaphore);

View File

@@ -23,7 +23,7 @@ size_t furi_stream_buffer_send(
uint32_t timeout) {
size_t ret;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
BaseType_t yield;
ret = xStreamBufferSendFromISR(stream_buffer, data, length, &yield);
portYIELD_FROM_ISR(yield);
@@ -41,7 +41,7 @@ size_t furi_stream_buffer_receive(
uint32_t timeout) {
size_t ret;
if(FURI_IS_IRQ_MODE() != 0U) {
if(FURI_IS_IRQ_MODE()) {
BaseType_t yield;
ret = xStreamBufferReceiveFromISR(stream_buffer, data, length, &yield);
portYIELD_FROM_ISR(yield);

View File

@@ -29,13 +29,13 @@ FuriString* furi_string_alloc() {
}
FuriString* furi_string_alloc_set(const FuriString* s) {
FuriString* string = malloc(sizeof(FuriString));
FuriString* string = malloc(sizeof(FuriString)); //-V773
string_init_set(string->string, s->string);
return string;
}
FuriString* furi_string_alloc_set_str(const char cstr[]) {
FuriString* string = malloc(sizeof(FuriString));
FuriString* string = malloc(sizeof(FuriString)); //-V773
string_init_set(string->string, cstr);
return string;
}

View File

@@ -50,6 +50,7 @@ static int32_t __furi_thread_stdout_flush(FuriThread* thread);
__attribute__((__noreturn__)) void furi_thread_catch() {
asm volatile("nop"); // extra magic
furi_crash("You are doing it wrong");
__builtin_unreachable();
}
static void furi_thread_set_state(FuriThread* thread, FuriThreadState state) {
@@ -112,6 +113,12 @@ FuriThread* furi_thread_alloc() {
FuriThread* thread = malloc(sizeof(FuriThread));
thread->output.buffer = furi_string_alloc();
thread->is_service = false;
if(furi_thread_get_current_id()) {
FuriThread* parent = pvTaskGetThreadLocalStoragePointer(NULL, 0);
if(parent) thread->heap_trace_enabled = parent->heap_trace_enabled;
}
return thread;
}

View File

@@ -313,7 +313,7 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa
furi_crash("Unknown FF type");
}
if((size_t)(i + 1) < write_data->data_size) {
if(((size_t)i + 1) < write_data->data_size) {
furi_string_cat(value, " ");
}

View File

@@ -85,8 +85,8 @@ static InfraredStatus infrared_common_decode_bits(InfraredCommonDecoder* decoder
if(timings->min_split_time && !level) {
if(timing > timings->min_split_time) {
/* long low timing - check if we're ready for any of protocol modification */
for(size_t i = 0; decoder->protocol->databit_len[i] &&
(i < COUNT_OF(decoder->protocol->databit_len));
for(size_t i = 0; i < COUNT_OF(decoder->protocol->databit_len) &&
decoder->protocol->databit_len[i];
++i) {
if(decoder->protocol->databit_len[i] == decoder->databit_cnt) {
return InfraredStatusReady;
@@ -199,7 +199,7 @@ InfraredMessage* infrared_common_decoder_check_ready(InfraredCommonDecoder* deco
bool found_length = false;
for(size_t i = 0;
decoder->protocol->databit_len[i] && (i < COUNT_OF(decoder->protocol->databit_len));
i < COUNT_OF(decoder->protocol->databit_len) && decoder->protocol->databit_len[i];
++i) {
if(decoder->protocol->databit_len[i] == decoder->databit_cnt) {
found_length = true;

View File

@@ -140,9 +140,8 @@ size_t lfrfid_worker_dict_get_data_size(LFRFIDWorker* worker, LFRFIDProtocol pro
static int32_t lfrfid_worker_thread(void* thread_context) {
LFRFIDWorker* worker = thread_context;
bool running = true;
while(running) {
while(true) {
uint32_t flags = furi_thread_flags_wait(LFRFIDEventAll, FuriFlagWaitAny, FuriWaitForever);
if(flags != FuriFlagErrorTimeout) {
// stop thread

View File

@@ -541,7 +541,7 @@ static size_t _etoa(
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
conv.U = ((uint64_t)exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors

View File

@@ -312,7 +312,6 @@ void subghz_protocol_decoder_power_smart_feed(
if((instance->decoder.decode_data & POWER_SMART_PACKET_HEADER_MASK) ==
POWER_SMART_PACKET_HEADER) {
if(subghz_protocol_power_smart_chek_valid(instance->decoder.decode_data)) {
instance->decoder.decode_data = instance->decoder.decode_data;
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit =
subghz_protocol_power_smart_const.min_count_bit_for_found;

View File

@@ -464,7 +464,7 @@ bool subghz_keystore_raw_encrypted_save(
}
stream_write_cstring(output_stream, encrypted_line);
} while(ret > 0 && result);
} while(result);
flipper_format_free(output_flipper_format);

View File

@@ -5,6 +5,7 @@ import struct
from dataclasses import dataclass, field
from .appmanifest import FlipperApplication
from flipper.assets.icon import file2image
_MANIFEST_MAGIC = 0x52474448
@@ -53,8 +54,6 @@ def assemble_manifest_data(
):
image_data = b""
if app_manifest.fap_icon:
from flipper.assets.icon import file2image
image = file2image(os.path.join(app_manifest._apppath, app_manifest.fap_icon))
if (image.width, image.height) != (10, 10):
raise ValueError(

View File

@@ -89,6 +89,9 @@ class SdkCache:
syms.update(map(lambda e: e.name, self.get_variables()))
return syms
def get_disabled_names(self):
return set(map(lambda e: e.name, self.disabled_entries))
def get_functions(self):
return self._filter_enabled(self.sdk.functions)

View File

@@ -139,7 +139,7 @@ def generate(env):
BUILDERS={
"IconBuilder": Builder(
action=Action(
'${PYTHON3} "${ASSETS_COMPILER}" icons ${ABSPATHGETTERFUNC(SOURCE)} ${TARGET.dir} --filename ${ICON_FILE_NAME}',
'${PYTHON3} "${ASSETS_COMPILER}" icons "${ABSPATHGETTERFUNC(SOURCE)}" "${TARGET.dir}" --filename ${ICON_FILE_NAME}',
"${ICONSCOMSTR}",
),
emitter=icons_emitter,

View File

@@ -1,7 +1,6 @@
from re import search
from SCons.Errors import UserError
from fbt_options import OPENOCD_OPTS
def _get_device_serials(search_str="STLink"):
@@ -20,6 +19,9 @@ def GetDevices(env):
def generate(env, **kw):
env.AddMethod(GetDevices)
env.SetDefault(
FBT_DEBUG_DIR="${ROOT_DIR}/debug",
)
if (adapter_serial := env.subst("$OPENOCD_ADAPTER_SERIAL")) != "auto":
env.Append(
@@ -36,7 +38,7 @@ def generate(env, **kw):
env.SetDefault(
OPENOCD_GDB_PIPE=[
"|openocd -c 'gdb_port pipe; log_output debug/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"
"|openocd -c 'gdb_port pipe; log_output ${FBT_DEBUG_DIR}/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}"
],
GDBOPTS_BASE=[
"-ex",
@@ -58,17 +60,19 @@ def generate(env, **kw):
],
GDBPYOPTS=[
"-ex",
"source debug/FreeRTOS/FreeRTOS.py",
"source ${FBT_DEBUG_DIR}/FreeRTOS/FreeRTOS.py",
"-ex",
"source debug/flipperapps.py",
"source ${FBT_DEBUG_DIR}/flipperapps.py",
"-ex",
"source debug/PyCortexMDebug/PyCortexMDebug.py",
"fap-set-debug-elf-root ${FBT_FAP_DEBUG_ELF_ROOT}",
"-ex",
"source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py",
"-ex",
"svd_load ${SVD_FILE}",
"-ex",
"compare-sections",
],
JFLASHPROJECT="${ROOT_DIR.abspath}/debug/fw.jflash",
JFLASHPROJECT="${FBT_DEBUG_DIR}/fw.jflash",
)

View File

@@ -22,7 +22,7 @@ def GetProjetDirName(env, project=None):
def create_fw_build_targets(env, configuration_name):
flavor = GetProjetDirName(env, configuration_name)
build_dir = env.Dir("build").Dir(flavor).abspath
build_dir = env.Dir("build").Dir(flavor)
return env.SConscript(
"firmware.scons",
variant_dir=build_dir,
@@ -131,7 +131,7 @@ def generate(env):
"UsbInstall": Builder(
action=[
Action(
'${PYTHON3} "${SELFUPDATE_SCRIPT}" dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}/update.fuf'
'${PYTHON3} "${SELFUPDATE_SCRIPT}" ${UPDATE_BUNDLE_DIR}/update.fuf'
),
Touch("${TARGET}"),
]

View File

@@ -1,6 +1,9 @@
from dataclasses import dataclass, field
from typing import Optional
from SCons.Builder import Builder
from SCons.Action import Action
from SCons.Errors import UserError
from SCons.Node import NodeList
import SCons.Warnings
from fbt.elfmanifest import assemble_manifest_data
@@ -16,6 +19,15 @@ import shutil
from ansi.color import fg
@dataclass
class FlipperExternalAppInfo:
app: FlipperApplication
compact: NodeList = field(default_factory=NodeList)
debug: NodeList = field(default_factory=NodeList)
validator: NodeList = field(default_factory=NodeList)
installer: NodeList = field(default_factory=NodeList)
def BuildAppElf(env, app):
ext_apps_work_dir = env.subst("$EXT_APPS_WORK_DIR")
app_work_dir = os.path.join(ext_apps_work_dir, app.appid)
@@ -26,15 +38,7 @@ def BuildAppElf(env, app):
app_alias = f"fap_{app.appid}"
# Deprecation stub
legacy_app_taget_name = f"{app_env['FIRMWARE_BUILD_CFG']}_{app.appid}"
def legacy_app_build_stub(**kw):
raise UserError(
f"Target name '{legacy_app_taget_name}' is deprecated, use '{app_alias}' instead"
)
app_env.PhonyTarget(legacy_app_taget_name, Action(legacy_app_build_stub, None))
app_artifacts = FlipperExternalAppInfo(app)
externally_built_files = []
if app.fap_extbuild:
@@ -115,20 +119,22 @@ def BuildAppElf(env, app):
CPPPATH=env.Dir(app_work_dir),
)
app_elf_raw = app_env.Program(
app_artifacts.debug = app_env.Program(
os.path.join(ext_apps_work_dir, f"{app.appid}_d"),
app_sources,
APP_ENTRY=app.entry_point,
)
app_env.Clean(app_elf_raw, [*externally_built_files, app_env.Dir(app_work_dir)])
app_env.Clean(
app_artifacts.debug, [*externally_built_files, app_env.Dir(app_work_dir)]
)
app_elf_dump = app_env.ObjDump(app_elf_raw)
app_elf_dump = app_env.ObjDump(app_artifacts.debug)
app_env.Alias(f"{app_alias}_list", app_elf_dump)
app_elf_augmented = app_env.EmbedAppMetadata(
app_artifacts.compact = app_env.EmbedAppMetadata(
os.path.join(ext_apps_work_dir, app.appid),
app_elf_raw,
app_artifacts.debug,
APP=app,
)
@@ -139,19 +145,21 @@ def BuildAppElf(env, app):
}
app_env.Depends(
app_elf_augmented,
app_artifacts.compact,
[app_env["SDK_DEFINITION"], app_env.Value(manifest_vals)],
)
if app.fap_icon:
app_env.Depends(
app_elf_augmented,
app_artifacts.compact,
app_env.File(f"{app._apppath}/{app.fap_icon}"),
)
app_elf_import_validator = app_env.ValidateAppImports(app_elf_augmented)
app_env.AlwaysBuild(app_elf_import_validator)
app_env.Alias(app_alias, app_elf_import_validator)
return (app_elf_augmented, app_elf_raw, app_elf_import_validator)
app_artifacts.validator = app_env.ValidateAppImports(app_artifacts.compact)
app_env.AlwaysBuild(app_artifacts.validator)
app_env.Alias(app_alias, app_artifacts.validator)
env["EXT_APPS"][app.appid] = app_artifacts
return app_artifacts
def prepare_app_metadata(target, source, env):
@@ -182,11 +190,17 @@ def validate_app_imports(target, source, env):
app_syms.add(line.split()[0])
unresolved_syms = app_syms - sdk_cache.get_valid_names()
if unresolved_syms:
SCons.Warnings.warn(
SCons.Warnings.LinkWarning,
fg.brightyellow(f"{source[0].path}: app won't run. Unresolved symbols: ")
+ fg.brightmagenta(f"{unresolved_syms}"),
)
warning_msg = fg.brightyellow(
f"{source[0].path}: app won't run. Unresolved symbols: "
) + fg.brightmagenta(f"{unresolved_syms}")
disabled_api_syms = unresolved_syms.intersection(sdk_cache.get_disabled_names())
if disabled_api_syms:
warning_msg += (
fg.brightyellow(" (in API, but disabled: ")
+ fg.brightmagenta(f"{disabled_api_syms}")
+ fg.brightyellow(")")
)
SCons.Warnings.warn(SCons.Warnings.LinkWarning, warning_msg),
def GetExtAppFromPath(env, app_dir):
@@ -208,26 +222,26 @@ def GetExtAppFromPath(env, app_dir):
if not app:
raise UserError(f"Failed to resolve application for given APPSRC={app_dir}")
app_elf = env["_extapps"]["compact"].get(app.appid, None)
if not app_elf:
app_artifacts = env["EXT_APPS"].get(app.appid, None)
if not app_artifacts:
raise UserError(
f"Application {app.appid} is not configured for building as external"
)
app_validator = env["_extapps"]["validators"].get(app.appid, None)
return (app, app_elf[0], app_validator[0])
return app_artifacts
def fap_dist_emitter(target, source, env):
target_dir = target[0]
target = []
for dist_entry in env["_extapps"]["dist"].values():
target.append(target_dir.Dir(dist_entry[0]).File(dist_entry[1][0].name))
for compact_entry in env["_extapps"]["compact"].values():
source.extend(compact_entry)
for _, app_artifacts in env["EXT_APPS"].items():
source.extend(app_artifacts.compact)
target.append(
target_dir.Dir(app_artifacts.app.fap_category).File(
app_artifacts.compact[0].name
)
)
return (target, source)
@@ -244,10 +258,9 @@ def fap_dist_action(target, source, env):
def generate(env, **kw):
env.SetDefault(
EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR"),
EXT_APPS_WORK_DIR="${FBT_FAP_DEBUG_ELF_ROOT}",
APP_RUN_SCRIPT="${FBT_SCRIPT_DIR}/runfap.py",
)
if not env["VERBOSE"]:
env.SetDefault(
FAPDISTCOMSTR="\tFAPDIST\t${TARGET}",
@@ -256,6 +269,10 @@ def generate(env, **kw):
APPCHECK_COMSTR="\tAPPCHK\t${SOURCE}",
)
env.SetDefault(
EXT_APPS={}, # appid -> FlipperExternalAppInfo
)
env.AddMethod(BuildAppElf)
env.AddMethod(GetExtAppFromPath)
env.Append(

View File

@@ -1,7 +1,9 @@
pyserial==3.5
ansi==0.3.6
black==22.6.0
colorlog==6.7.0
heatshrink2==0.11.0
Pillow==9.1.1
grpcio==1.47.0
grpcio-tools==1.47.0
protobuf==3.20.2
protobuf==3.20.1
pyserial==3.5
python3-protobuf==2.5.0
SCons==4.4.0

View File

@@ -152,7 +152,7 @@ vars.AddVariables(
PathVariable(
"SVD_FILE",
help="Path to SVD file",
validator=PathVariable.PathIsFile,
validator=PathVariable.PathAccept,
default="",
),
PathVariable(

View File

@@ -62,8 +62,8 @@ coreenv = VAR_ENV.Clone(
ABSPATHGETTERFUNC=extract_abs_dir_path,
# Setting up temp file parameters - to overcome command line length limits
TEMPFILEARGESCFUNC=tempfile_arg_esc_func,
FBT_SCRIPT_DIR=Dir("#/scripts"),
ROOT_DIR=Dir("#"),
FBT_SCRIPT_DIR="${ROOT_DIR}/scripts",
)
# If DIST_SUFFIX is set in environment, is has precedence (set by CI)

View File

@@ -1,4 +1,6 @@
from dataclasses import dataclass, field
from SCons.Errors import UserError
from SCons.Node import NodeList
Import("ENV")
@@ -7,14 +9,7 @@ from fbt.appmanifest import FlipperAppType
appenv = ENV["APPENV"] = ENV.Clone(
tools=[
(
"fbt_extapps",
{
"EXT_APPS_WORK_DIR": ENV.subst(
"${BUILD_DIR}/.extapps",
)
},
),
"fbt_extapps",
"fbt_assets",
"fbt_sdk",
]
@@ -60,22 +55,11 @@ appenv.AppendUnique(
)
extapps = appenv["_extapps"] = {
"compact": {},
"debug": {},
"validators": {},
"dist": {},
"resources_dist": None,
"sdk_tree": None,
}
def build_app_as_external(env, appdef):
compact_elf, debug_elf, validator = env.BuildAppElf(appdef)
extapps["compact"][appdef.appid] = compact_elf
extapps["debug"][appdef.appid] = debug_elf
extapps["validators"][appdef.appid] = validator
extapps["dist"][appdef.appid] = (appdef.fap_category, compact_elf)
@dataclass
class FlipperExtAppBuildArtifacts:
applications: dict = field(default_factory=dict)
resources_dist: NodeList = field(default_factory=NodeList)
sdk_tree: NodeList = field(default_factory=NodeList)
apps_to_build_as_faps = [
@@ -85,38 +69,39 @@ apps_to_build_as_faps = [
if appenv["DEBUG_TOOLS"]:
apps_to_build_as_faps.append(FlipperAppType.DEBUG)
for apptype in apps_to_build_as_faps:
for app in appenv["APPBUILD"].get_apps_of_type(apptype, True):
build_app_as_external(appenv, app)
known_extapps = [
app
for apptype in apps_to_build_as_faps
for app in appenv["APPBUILD"].get_apps_of_type(apptype, True)
]
# Ugly access to global option
if extra_app_list := GetOption("extra_ext_apps"):
for extra_app in extra_app_list.split(","):
build_app_as_external(appenv, appenv["APPMGR"].get(extra_app))
known_extapps.extend(map(appenv["APPMGR"].get, extra_app_list.split(",")))
for app in known_extapps:
appenv.BuildAppElf(app)
if appenv["FORCE"]:
appenv.AlwaysBuild(extapps["compact"].values())
appenv.AlwaysBuild(
list(app_artifact.compact for app_artifact in appenv["EXT_APPS"].values())
)
# Deprecation stub
def legacy_app_build_stub(**kw):
raise UserError(f"Target name 'firmware_extapps' is deprecated, use 'faps' instead")
Alias(
"faps", list(app_artifact.validator for app_artifact in appenv["EXT_APPS"].values())
)
appenv.PhonyTarget("firmware_extapps", appenv.Action(legacy_app_build_stub, None))
Alias("faps", extapps["compact"].values())
Alias("faps", extapps["validators"].values())
extapps["resources_dist"] = appenv.FapDist(appenv.Dir("#/assets/resources/apps"), [])
extapps = FlipperExtAppBuildArtifacts()
extapps.applications = appenv["EXT_APPS"]
extapps.resources_dist = appenv.FapDist(appenv.Dir("#/assets/resources/apps"), [])
if appsrc := appenv.subst("$APPSRC"):
app_manifest, fap_file, app_validator = appenv.GetExtAppFromPath(appsrc)
appenv.PhonyTarget(
"launch_app",
'${PYTHON3} "${APP_RUN_SCRIPT}" ${SOURCE} --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"',
'${PYTHON3} "${APP_RUN_SCRIPT}" "${SOURCE}" --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"',
source=fap_file,
FAP_CATEGORY=app_manifest.fap_category,
)
@@ -131,12 +116,14 @@ sdk_source = appenv.SDKPrebuilder(
(appenv["SDK_HEADERS"], appenv["FW_ASSETS_HEADERS"]),
)
# Extra deps on headers included in deeper levels
# Available on second and subsequent builds
Depends(sdk_source, appenv.ProcessSdkDepends(f"{sdk_origin_path}.d"))
appenv["SDK_DIR"] = appenv.Dir("${BUILD_DIR}/sdk")
sdk_tree = extapps["sdk_tree"] = appenv.SDKTree(appenv["SDK_DIR"], sdk_origin_path)
sdk_tree = appenv.SDKTree(appenv["SDK_DIR"], sdk_origin_path)
# AlwaysBuild(sdk_tree)
Alias("sdk_tree", sdk_tree)
extapps.sdk_tree = sdk_tree
sdk_apicheck = appenv.SDKSymUpdater(appenv["SDK_DEFINITION"], sdk_origin_path)
Precious(sdk_apicheck)