mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-11 06:09:08 -07:00
Merge branch 'dev' of https://github.com/Flipper-XFW/Xtreme-Firmware into new-app-system
This commit is contained in:
6
.github/workflow_data/devbuild.py
vendored
6
.github/workflow_data/devbuild.py
vendored
@@ -12,6 +12,12 @@ if __name__ == "__main__":
|
|||||||
event = json.load(f)
|
event = json.load(f)
|
||||||
|
|
||||||
client = nextcloud_client.Client(os.environ["NC_HOST"])
|
client = nextcloud_client.Client(os.environ["NC_HOST"])
|
||||||
|
_session = requests.session
|
||||||
|
def session(*args, **kwargs):
|
||||||
|
s = _session(*args, **kwargs)
|
||||||
|
s.headers["User-Agent"] = os.environ["NC_USERAGENT"]
|
||||||
|
return s
|
||||||
|
requests.session = session
|
||||||
client.login(os.environ["NC_USER"], os.environ["NC_PASS"])
|
client.login(os.environ["NC_USER"], os.environ["NC_PASS"])
|
||||||
|
|
||||||
for file in (
|
for file in (
|
||||||
|
|||||||
2
.github/workflow_data/webhook.py
vendored
2
.github/workflow_data/webhook.py
vendored
@@ -36,7 +36,7 @@ if __name__ == "__main__":
|
|||||||
for i, commit in enumerate(event["commits"]):
|
for i, commit in enumerate(event["commits"]):
|
||||||
msg = commit['message'].splitlines()[0].replace("`", "")
|
msg = commit['message'].splitlines()[0].replace("`", "")
|
||||||
msg = msg[:50] + ("..." if len(msg) > 50 else "")
|
msg = msg[:50] + ("..." if len(msg) > 50 else "")
|
||||||
desc += f"\n[`{commit['id'][:7]}`]({commit['url']}): {msg} - [__{commit['author']['username']}__](https://github.com/{commit['author']['username']})"
|
desc += f"\n[`{commit['id'][:7]}`]({commit['url']}): {msg} - [__{commit['author'].get('username')}__](https://github.com/{commit['author'].get('username')})"
|
||||||
if len(desc) > 2020:
|
if len(desc) > 2020:
|
||||||
desc = desc.rsplit("\n", 1)[0] + f"\n+ {count - i} more commits"
|
desc = desc.rsplit("\n", 1)[0] + f"\n+ {count - i} more commits"
|
||||||
break
|
break
|
||||||
|
|||||||
7
.github/workflow_data/webupdater.py
vendored
7
.github/workflow_data/webupdater.py
vendored
@@ -1,9 +1,16 @@
|
|||||||
import nextcloud_client
|
import nextcloud_client
|
||||||
|
import requests
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
client = nextcloud_client.Client(os.environ["NC_HOST"])
|
client = nextcloud_client.Client(os.environ["NC_HOST"])
|
||||||
|
_session = requests.session
|
||||||
|
def session(*args, **kwargs):
|
||||||
|
s = _session(*args, **kwargs)
|
||||||
|
s.headers["User-Agent"] = os.environ["NC_USERAGENT"]
|
||||||
|
return s
|
||||||
|
requests.session = session
|
||||||
client.login(os.environ["NC_USER"], os.environ["NC_PASS"])
|
client.login(os.environ["NC_USER"], os.environ["NC_PASS"])
|
||||||
|
|
||||||
file = os.environ["ARTIFACT_TGZ"]
|
file = os.environ["ARTIFACT_TGZ"]
|
||||||
|
|||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -16,6 +16,7 @@ concurrency:
|
|||||||
env:
|
env:
|
||||||
TARGETS: f7
|
TARGETS: f7
|
||||||
DEFAULT_TARGET: f7
|
DEFAULT_TARGET: f7
|
||||||
|
FBT_GIT_SUBMODULE_SHALLOW: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -57,6 +58,7 @@ jobs:
|
|||||||
if: "github.event_name == 'push' && github.ref_name == 'dev' && !contains(github.event.head_commit.message, '--nobuild')"
|
if: "github.event_name == 'push' && github.ref_name == 'dev' && !contains(github.event.head_commit.message, '--nobuild')"
|
||||||
env:
|
env:
|
||||||
NC_HOST: "https://cloud.cynthialabs.net/"
|
NC_HOST: "https://cloud.cynthialabs.net/"
|
||||||
|
NC_USERAGENT: "${{ secrets.NC_USERAGENT }}"
|
||||||
NC_USER: "${{ secrets.NC_USER }}"
|
NC_USER: "${{ secrets.NC_USER }}"
|
||||||
NC_PASS: "${{ secrets.NC_PASS }}"
|
NC_PASS: "${{ secrets.NC_PASS }}"
|
||||||
BUILD_WEBHOOK: ${{ secrets.BUILD_WEBHOOK }}
|
BUILD_WEBHOOK: ${{ secrets.BUILD_WEBHOOK }}
|
||||||
|
|||||||
1
.github/workflows/hotfix.yml
vendored
1
.github/workflows/hotfix.yml
vendored
@@ -59,6 +59,7 @@ jobs:
|
|||||||
- name: "Upload to webupdater"
|
- name: "Upload to webupdater"
|
||||||
env:
|
env:
|
||||||
NC_HOST: "https://cloud.cynthialabs.net/"
|
NC_HOST: "https://cloud.cynthialabs.net/"
|
||||||
|
NC_USERAGENT: "${{ secrets.NC_USERAGENT }}"
|
||||||
NC_USER: "${{ secrets.NC_USER }}"
|
NC_USER: "${{ secrets.NC_USER }}"
|
||||||
NC_PASS: "${{ secrets.NC_PASS }}"
|
NC_PASS: "${{ secrets.NC_PASS }}"
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -55,6 +55,7 @@ jobs:
|
|||||||
- name: "Upload to webupdater"
|
- name: "Upload to webupdater"
|
||||||
env:
|
env:
|
||||||
NC_HOST: "https://cloud.cynthialabs.net/"
|
NC_HOST: "https://cloud.cynthialabs.net/"
|
||||||
|
NC_USERAGENT: "${{ secrets.NC_USERAGENT }}"
|
||||||
NC_USER: "${{ secrets.NC_USER }}"
|
NC_USER: "${{ secrets.NC_USER }}"
|
||||||
NC_PASS: "${{ secrets.NC_PASS }}"
|
NC_PASS: "${{ secrets.NC_PASS }}"
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ void power_settings_scene_power_off_on_enter(void* context) {
|
|||||||
dialog, " I will be\nwaiting for\n you here", 78, 16, AlignLeft, AlignTop);
|
dialog, " I will be\nwaiting for\n you here", 78, 16, AlignLeft, AlignTop);
|
||||||
}
|
}
|
||||||
dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52);
|
dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52);
|
||||||
dialog_ex_set_left_button_text(dialog, "Back");
|
dialog_ex_set_left_button_text(dialog, "Battery");
|
||||||
dialog_ex_set_right_button_text(dialog, "OFF");
|
dialog_ex_set_right_button_text(dialog, "OFF");
|
||||||
dialog_ex_set_result_callback(dialog, power_settings_scene_power_off_dialog_callback);
|
dialog_ex_set_result_callback(dialog, power_settings_scene_power_off_dialog_callback);
|
||||||
dialog_ex_set_context(dialog, app);
|
dialog_ex_set_context(dialog, app);
|
||||||
@@ -34,10 +34,7 @@ bool power_settings_scene_power_off_on_event(void* context, SceneManagerEvent ev
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == DialogExResultLeft) {
|
if(event.event == DialogExResultLeft) {
|
||||||
if(!scene_manager_previous_scene(app->scene_manager)) {
|
scene_manager_next_scene(app->scene_manager, PowerSettingsAppSceneBatteryInfo);
|
||||||
scene_manager_stop(app->scene_manager);
|
|
||||||
view_dispatcher_stop(app->view_dispatcher);
|
|
||||||
}
|
|
||||||
} else if(event.event == DialogExResultRight) {
|
} else if(event.event == DialogExResultRight) {
|
||||||
power_off(app->power);
|
power_off(app->power);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,10 @@ static bool battery_info_input_callback(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
BatteryInfo* battery_info = context;
|
BatteryInfo* battery_info = context;
|
||||||
|
|
||||||
if(event->type == InputTypeShort) {
|
bool about_battery;
|
||||||
|
with_view_model(
|
||||||
|
battery_info->view, BatteryInfoModel * model, { about_battery = model->alt; }, false);
|
||||||
|
if(about_battery && event->type == InputTypeShort) {
|
||||||
if(event->key == InputKeyLeft) {
|
if(event->key == InputKeyLeft) {
|
||||||
event->key = InputKeyBack;
|
event->key = InputKeyBack;
|
||||||
} else if(event->key == InputKeyRight) {
|
} else if(event->key == InputKeyRight) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ typedef struct {
|
|||||||
bool left_mouse_held;
|
bool left_mouse_held;
|
||||||
bool right_mouse_pressed;
|
bool right_mouse_pressed;
|
||||||
bool connected;
|
bool connected;
|
||||||
|
uint8_t acceleration;
|
||||||
HidTransport transport;
|
HidTransport transport;
|
||||||
} HidMouseModel;
|
} HidMouseModel;
|
||||||
|
|
||||||
@@ -119,6 +120,11 @@ static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) {
|
|||||||
hid_mouse->view,
|
hid_mouse->view,
|
||||||
HidMouseModel * model,
|
HidMouseModel * model,
|
||||||
{
|
{
|
||||||
|
model->acceleration = (event->type == InputTypePress) ? 1 :
|
||||||
|
(event->type == InputTypeRelease) ? 0 :
|
||||||
|
(model->acceleration >= 20) ? 20 :
|
||||||
|
model->acceleration + 1;
|
||||||
|
|
||||||
if(event->key == InputKeyBack) {
|
if(event->key == InputKeyBack) {
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_RIGHT);
|
hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_RIGHT);
|
||||||
@@ -150,7 +156,8 @@ static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) {
|
|||||||
model->right_pressed = true;
|
model->right_pressed = true;
|
||||||
hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_SHORT, 0);
|
hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_SHORT, 0);
|
||||||
} else if(event->type == InputTypeRepeat) {
|
} else if(event->type == InputTypeRepeat) {
|
||||||
hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_LONG, 0);
|
for(uint8_t i = model->acceleration; i > 1; i -= 2)
|
||||||
|
hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_LONG, 0);
|
||||||
} else if(event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
model->right_pressed = false;
|
model->right_pressed = false;
|
||||||
}
|
}
|
||||||
@@ -159,7 +166,8 @@ static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) {
|
|||||||
model->left_pressed = true;
|
model->left_pressed = true;
|
||||||
hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_SHORT, 0);
|
hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_SHORT, 0);
|
||||||
} else if(event->type == InputTypeRepeat) {
|
} else if(event->type == InputTypeRepeat) {
|
||||||
hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_LONG, 0);
|
for(uint8_t i = model->acceleration; i > 1; i -= 2)
|
||||||
|
hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_LONG, 0);
|
||||||
} else if(event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
model->left_pressed = false;
|
model->left_pressed = false;
|
||||||
}
|
}
|
||||||
@@ -168,7 +176,9 @@ static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) {
|
|||||||
model->down_pressed = true;
|
model->down_pressed = true;
|
||||||
hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_SHORT);
|
hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_SHORT);
|
||||||
} else if(event->type == InputTypeRepeat) {
|
} else if(event->type == InputTypeRepeat) {
|
||||||
hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_LONG);
|
for(uint8_t i = model->acceleration; i > 1; i -= 2)
|
||||||
|
hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_LONG);
|
||||||
|
|
||||||
} else if(event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
model->down_pressed = false;
|
model->down_pressed = false;
|
||||||
}
|
}
|
||||||
@@ -177,7 +187,8 @@ static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) {
|
|||||||
model->up_pressed = true;
|
model->up_pressed = true;
|
||||||
hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_SHORT);
|
hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_SHORT);
|
||||||
} else if(event->type == InputTypeRepeat) {
|
} else if(event->type == InputTypeRepeat) {
|
||||||
hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_LONG);
|
for(uint8_t i = model->acceleration; i > 1; i -= 2)
|
||||||
|
hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_LONG);
|
||||||
} else if(event->type == InputTypeRelease) {
|
} else if(event->type == InputTypeRelease) {
|
||||||
model->up_pressed = false;
|
model->up_pressed = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,21 +201,30 @@ bool subrem_view_remote_input(InputEvent* event, void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubRemViewRemote* subrem_view_remote = context;
|
SubRemViewRemote* subrem_view_remote = context;
|
||||||
|
|
||||||
if(event->key == InputKeyBack && event->type == InputTypeLong) {
|
if(event->key == InputKeyBack && event->type == InputTypePress) {
|
||||||
subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context);
|
bool is_stopping = false;
|
||||||
return true;
|
|
||||||
} else if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subrem_view_remote->view,
|
subrem_view_remote->view,
|
||||||
SubRemViewRemoteModel * model,
|
SubRemViewRemoteModel * model,
|
||||||
{ model->pressed_btn = 0; },
|
{
|
||||||
|
if(model->state == SubRemViewRemoteStateSending) {
|
||||||
|
is_stopping = true;
|
||||||
|
model->pressed_btn = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
true);
|
true);
|
||||||
subrem_view_remote->callback(
|
|
||||||
SubRemCustomEventViewRemoteForcedStop, subrem_view_remote->context);
|
//Cant send exit the app inside that with_model,locks the model and the app will hang and not unload!
|
||||||
return true;
|
if(is_stopping)
|
||||||
} else if(event->key == InputKeyBack) {
|
subrem_view_remote->callback(
|
||||||
|
SubRemCustomEventViewRemoteForcedStop, subrem_view_remote->context);
|
||||||
|
else
|
||||||
|
subrem_view_remote->callback(
|
||||||
|
SubRemCustomEventViewRemoteBack, subrem_view_remote->context);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BACK button processing end
|
// BACK button processing end
|
||||||
|
|
||||||
if(event->key == InputKeyUp && event->type == InputTypePress) {
|
if(event->key == InputKeyUp && event->type == InputTypePress) {
|
||||||
|
|||||||
11
fbt
11
fbt
@@ -5,7 +5,8 @@
|
|||||||
set -eu;
|
set -eu;
|
||||||
|
|
||||||
# private variables
|
# private variables
|
||||||
N_GIT_THREADS="$(getconf _NPROCESSORS_ONLN)";
|
N_CORES="$(getconf _NPROCESSORS_ONLN)";
|
||||||
|
N_GIT_THREADS="$(($N_CORES * 2))";
|
||||||
SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd -P)";
|
SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd -P)";
|
||||||
SCONS_DEFAULT_FLAGS="--warn=target-not-built";
|
SCONS_DEFAULT_FLAGS="--warn=target-not-built";
|
||||||
SCONS_EP="python3 -m SCons";
|
SCONS_EP="python3 -m SCons";
|
||||||
@@ -15,6 +16,7 @@ FBT_NOENV="${FBT_NOENV:-""}";
|
|||||||
FBT_NO_SYNC="${FBT_NO_SYNC:-""}";
|
FBT_NO_SYNC="${FBT_NO_SYNC:-""}";
|
||||||
FBT_TOOLCHAIN_PATH="${FBT_TOOLCHAIN_PATH:-$SCRIPT_PATH}";
|
FBT_TOOLCHAIN_PATH="${FBT_TOOLCHAIN_PATH:-$SCRIPT_PATH}";
|
||||||
FBT_VERBOSE="${FBT_VERBOSE:-""}";
|
FBT_VERBOSE="${FBT_VERBOSE:-""}";
|
||||||
|
FBT_GIT_SUBMODULE_SHALLOW="${FBT_GIT_SUBMODULE_SHALLOW:-""}";
|
||||||
|
|
||||||
if [ -z "$FBT_NOENV" ]; then
|
if [ -z "$FBT_NOENV" ]; then
|
||||||
FBT_VERBOSE="$FBT_VERBOSE" . "$SCRIPT_PATH/scripts/toolchain/fbtenv.sh";
|
FBT_VERBOSE="$FBT_VERBOSE" . "$SCRIPT_PATH/scripts/toolchain/fbtenv.sh";
|
||||||
@@ -29,7 +31,12 @@ if [ -z "$FBT_NO_SYNC" ]; then
|
|||||||
echo "\".git\" directory not found, please clone repo via \"git clone\"";
|
echo "\".git\" directory not found, please clone repo via \"git clone\"";
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
git submodule update --init --recursive --jobs "$N_GIT_THREADS";
|
_FBT_CLONE_FLAGS="--jobs $N_GIT_THREADS";
|
||||||
|
if [ ! -z "$FBT_GIT_SUBMODULE_SHALLOW" ]; then
|
||||||
|
_FBT_CLONE_FLAGS="$_FBT_CLONE_FLAGS --depth 1";
|
||||||
|
fi
|
||||||
|
|
||||||
|
git submodule update --init --recursive --recursive $_FBT_CLONE_FLAGS;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$SCONS_EP $SCONS_DEFAULT_FLAGS "$@"
|
$SCONS_EP $SCONS_DEFAULT_FLAGS "$@"
|
||||||
|
|||||||
12
fbt.cmd
12
fbt.cmd
@@ -4,10 +4,18 @@ call "%~dp0scripts\toolchain\fbtenv.cmd" env
|
|||||||
set SCONS_EP=python -m SCons
|
set SCONS_EP=python -m SCons
|
||||||
|
|
||||||
if [%FBT_NO_SYNC%] == [] (
|
if [%FBT_NO_SYNC%] == [] (
|
||||||
|
set _FBT_CLONE_FLAGS=--jobs %NUMBER_OF_PROCESSORS%
|
||||||
|
if not [%FBT_GIT_SUBMODULE_SHALLOW%] == [] (
|
||||||
|
set _FBT_CLONE_FLAGS=%_FBT_CLONE_FLAGS% --depth 1
|
||||||
|
)
|
||||||
if exist ".git" (
|
if exist ".git" (
|
||||||
git submodule update --init --recursive --depth 1 --jobs %NUMBER_OF_PROCESSORS%
|
git submodule update --init --recursive --recursive %_FBT_CLONE_FLAGS%
|
||||||
|
if %ERRORLEVEL% neq 0 (
|
||||||
|
echo Failed to update submodules, set FBT_NO_SYNC to skip
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
) else (
|
) else (
|
||||||
echo Not in a git repo, please clone with "git clone"
|
echo .git not found, please clone repo with "git clone"
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -613,10 +613,31 @@ static Elf32_Addr elf_address_of_by_hash(ELFFile* elf, uint32_t hash) {
|
|||||||
return ELF_INVALID_ADDRESS;
|
return ELF_INVALID_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool elf_file_find_string_by_hash(ELFFile* elf, uint32_t hash, FuriString* out) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
FuriString* symbol_name = furi_string_alloc();
|
||||||
|
Elf32_Sym sym;
|
||||||
|
for(size_t i = 0; i < elf->symbol_count; i++) {
|
||||||
|
furi_string_reset(symbol_name);
|
||||||
|
if(elf_read_symbol(elf, i, &sym, symbol_name)) {
|
||||||
|
if(elf_symbolname_hash(furi_string_get_cstr(symbol_name)) == hash) {
|
||||||
|
furi_string_set(out, symbol_name);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
furi_string_free(symbol_name);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static bool elf_relocate_fast(ELFFile* elf, ELFSection* s) {
|
static bool elf_relocate_fast(ELFFile* elf, ELFSection* s) {
|
||||||
UNUSED(elf);
|
UNUSED(elf);
|
||||||
const uint8_t* start = s->fast_rel->data;
|
const uint8_t* start = s->fast_rel->data;
|
||||||
const uint8_t version = *start;
|
const uint8_t version = *start;
|
||||||
|
bool no_errors = true;
|
||||||
|
|
||||||
if(version != FAST_RELOCATION_VERSION) {
|
if(version != FAST_RELOCATION_VERSION) {
|
||||||
FURI_LOG_E(TAG, "Unsupported fast relocation version %d", version);
|
FURI_LOG_E(TAG, "Unsupported fast relocation version %d", version);
|
||||||
@@ -664,16 +685,30 @@ static bool elf_relocate_fast(ELFFile* elf, ELFSection* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(address == ELF_INVALID_ADDRESS) {
|
if(address == ELF_INVALID_ADDRESS) {
|
||||||
FURI_LOG_E(TAG, "Failed to resolve address for hash %lX", hash_or_section_index);
|
FuriString* symbol_name = furi_string_alloc();
|
||||||
return false;
|
if(elf_file_find_string_by_hash(elf, hash_or_section_index, symbol_name)) {
|
||||||
}
|
FURI_LOG_E(
|
||||||
|
TAG,
|
||||||
|
"Failed to resolve address for symbol %s (hash %lX)",
|
||||||
|
furi_string_get_cstr(symbol_name),
|
||||||
|
hash_or_section_index);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG,
|
||||||
|
"Failed to resolve address for hash %lX (string not found)",
|
||||||
|
hash_or_section_index);
|
||||||
|
}
|
||||||
|
furi_string_free(symbol_name);
|
||||||
|
|
||||||
for(uint32_t j = 0; j < offsets_count; j++) {
|
no_errors = false;
|
||||||
uint32_t offset = *((uint32_t*)start) & 0x00FFFFFF;
|
start += 3 * offsets_count;
|
||||||
start += 3;
|
} else {
|
||||||
// FURI_LOG_I(TAG, " Fast relocation offset %ld: %ld", j, offset);
|
for(uint32_t j = 0; j < offsets_count; j++) {
|
||||||
Elf32_Addr relAddr = ((Elf32_Addr)s->data) + offset;
|
uint32_t offset = *((uint32_t*)start) & 0x00FFFFFF;
|
||||||
elf_relocate_symbol(elf, relAddr, type, address);
|
start += 3;
|
||||||
|
Elf32_Addr relAddr = ((Elf32_Addr)s->data) + offset;
|
||||||
|
elf_relocate_symbol(elf, relAddr, type, address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,7 +716,7 @@ static bool elf_relocate_fast(ELFFile* elf, ELFSection* s) {
|
|||||||
free(s->fast_rel);
|
free(s->fast_rel);
|
||||||
s->fast_rel = NULL;
|
s->fast_rel = NULL;
|
||||||
|
|
||||||
return true;
|
return no_errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool elf_relocate_section(ELFFile* elf, ELFSection* section) {
|
static bool elf_relocate_section(ELFFile* elf, ELFSection* section) {
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ class FlipperApplication:
|
|||||||
def is_default_deployable(self):
|
def is_default_deployable(self):
|
||||||
return self.apptype != FlipperAppType.DEBUG and self.fap_category != "Examples"
|
return self.apptype != FlipperAppType.DEBUG and self.fap_category != "Examples"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def do_strict_import_checks(self):
|
||||||
|
return self.apptype != FlipperAppType.PLUGIN
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if self.apptype == FlipperAppType.PLUGIN:
|
if self.apptype == FlipperAppType.PLUGIN:
|
||||||
self.stack_size = 0
|
self.stack_size = 0
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class AppBuilder:
|
|||||||
self.ext_apps_work_dir = env["EXT_APPS_WORK_DIR"]
|
self.ext_apps_work_dir = env["EXT_APPS_WORK_DIR"]
|
||||||
self.app_work_dir = self.get_app_work_dir(env, app)
|
self.app_work_dir = self.get_app_work_dir(env, app)
|
||||||
self.app_alias = f"fap_{self.app.appid}"
|
self.app_alias = f"fap_{self.app.appid}"
|
||||||
|
self.icons_src = None
|
||||||
self.externally_built_files = []
|
self.externally_built_files = []
|
||||||
self.private_libs = []
|
self.private_libs = []
|
||||||
|
|
||||||
@@ -93,6 +94,7 @@ class AppBuilder:
|
|||||||
)
|
)
|
||||||
self.app_env.Alias("_fap_icons", fap_icons)
|
self.app_env.Alias("_fap_icons", fap_icons)
|
||||||
self.fw_env.Append(_APP_ICONS=[fap_icons])
|
self.fw_env.Append(_APP_ICONS=[fap_icons])
|
||||||
|
self.icons_src = next(filter(lambda n: n.path.endswith(".c"), fap_icons))
|
||||||
|
|
||||||
def _build_private_libs(self):
|
def _build_private_libs(self):
|
||||||
for lib_def in self.app.fap_private_libs:
|
for lib_def in self.app.fap_private_libs:
|
||||||
@@ -160,6 +162,10 @@ class AppBuilder:
|
|||||||
if not app_sources:
|
if not app_sources:
|
||||||
raise UserError(f"No source files found for {self.app.appid}")
|
raise UserError(f"No source files found for {self.app.appid}")
|
||||||
|
|
||||||
|
# Ensure that icons are included in the build, regardless of user-configured sources
|
||||||
|
if self.icons_src and not self.icons_src in app_sources:
|
||||||
|
app_sources.append(self.icons_src)
|
||||||
|
|
||||||
## Uncomment for debug
|
## Uncomment for debug
|
||||||
# print(f"App sources for {self.app.appid}: {list(f.path for f in app_sources)}")
|
# print(f"App sources for {self.app.appid}: {list(f.path for f in app_sources)}")
|
||||||
|
|
||||||
@@ -180,7 +186,9 @@ class AppBuilder:
|
|||||||
self.app._assets_dirs.append(self.app_work_dir.Dir("assets"))
|
self.app._assets_dirs.append(self.app_work_dir.Dir("assets"))
|
||||||
|
|
||||||
app_artifacts.validator = self.app_env.ValidateAppImports(
|
app_artifacts.validator = self.app_env.ValidateAppImports(
|
||||||
app_artifacts.compact
|
app_artifacts.compact,
|
||||||
|
_CHECK_APP=self.app.do_strict_import_checks
|
||||||
|
and self.app_env.get("STRICT_FAP_IMPORT_CHECK"),
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
if self.app.apptype == FlipperAppType.PLUGIN:
|
if self.app.apptype == FlipperAppType.PLUGIN:
|
||||||
@@ -300,7 +308,10 @@ def validate_app_imports(target, source, env):
|
|||||||
+ fg.brightmagenta(f"{disabled_api_syms}")
|
+ fg.brightmagenta(f"{disabled_api_syms}")
|
||||||
+ fg.brightyellow(")")
|
+ fg.brightyellow(")")
|
||||||
)
|
)
|
||||||
SCons.Warnings.warn(SCons.Warnings.LinkWarning, warning_msg),
|
if env.get("_CHECK_APP"):
|
||||||
|
raise UserError(warning_msg)
|
||||||
|
else:
|
||||||
|
SCons.Warnings.warn(SCons.Warnings.LinkWarning, warning_msg),
|
||||||
|
|
||||||
|
|
||||||
def GetExtAppByIdOrPath(env, app_dir):
|
def GetExtAppByIdOrPath(env, app_dir):
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ def GlobRecursive(env, pattern, node=".", exclude=[]):
|
|||||||
source=True,
|
source=True,
|
||||||
exclude=exclude,
|
exclude=exclude,
|
||||||
)
|
)
|
||||||
# Otherwise, just check if that's an existing file path
|
# Otherwise, just assume that file at path exists
|
||||||
# NB: still creates "virtual" nodes as part of existence check
|
else:
|
||||||
elif (file_node := node.File(pattern)).exists() or file_node.rexists():
|
results.append(node.File(pattern))
|
||||||
results.append(file_node)
|
|
||||||
# print(f"Glob result for {pattern} from {node}: {results}")
|
# print(f"Glob result for {pattern} from {node}: {results}")
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ vars.AddVariables(
|
|||||||
"CDC Port of Flipper to use, if multiple are connected",
|
"CDC Port of Flipper to use, if multiple are connected",
|
||||||
"auto",
|
"auto",
|
||||||
),
|
),
|
||||||
|
BoolVariable(
|
||||||
|
"STRICT_FAP_IMPORT_CHECK",
|
||||||
|
help="Enable strict import check for .faps",
|
||||||
|
default=True,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
Return("vars")
|
Return("vars")
|
||||||
|
|||||||
@@ -270,6 +270,11 @@ vars.AddVariables(
|
|||||||
"clangd",
|
"clangd",
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
BoolVariable(
|
||||||
|
"STRICT_FAP_IMPORT_CHECK",
|
||||||
|
help="Enable strict import check for .faps",
|
||||||
|
default=True,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
Return("vars")
|
Return("vars")
|
||||||
|
|||||||
Reference in New Issue
Block a user