Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hedger/2627 apisdk #97

Merged
merged 35 commits into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cabed81
fbt: draft SDK generator for external apps
hedger Jul 6, 2022
1cfa794
fbt: reworked API headers processing from scons deps resolver to gcc …
hedger Jul 9, 2022
9c95aeb
Merge remote-tracking branch 'remotes/origin/dev' into hedger/2627-ap…
hedger Jul 9, 2022
40e723c
fbt: api definition generation, v0
hedger Jul 9, 2022
2bfdf25
fbt: always rebuild assets
hedger Jul 9, 2022
83c44ce
loader: ported from 2021
hedger Jul 9, 2022
162f05d
fbt: added initial API autoversioning
hedger Jul 11, 2022
c411c91
fbt: sdk symbol table generator from symbol cache
hedger Jul 12, 2022
4657228
SDK: filtered entries according to debug elf
hedger Jul 12, 2022
a7ed2d3
elf loader: wip; furi_hal: extern guards
hedger Jul 12, 2022
df92b62
scons: increase template depth
DrZlo13 Jul 12, 2022
4504106
toolbox: export api
DrZlo13 Jul 12, 2022
3ee4a69
one_wire: export api
DrZlo13 Jul 12, 2022
b4d268b
uCC: export api
DrZlo13 Jul 12, 2022
a7dbe5f
hmac: export api
DrZlo13 Jul 12, 2022
ef89960
Furi HAL CDC: make public, export api
DrZlo13 Jul 12, 2022
8333229
Furi core: export intrinsic api -_-
DrZlo13 Jul 12, 2022
4a45843
RPC: export api
DrZlo13 Jul 12, 2022
281982b
Notifications: export api
DrZlo13 Jul 12, 2022
f2875a7
Cli: export api
DrZlo13 Jul 12, 2022
728f829
Extapps fbt: force extapps build
DrZlo13 Jul 12, 2022
4507665
elf loader: debug logs, corrected jump to plugin
DrZlo13 Jul 12, 2022
2816344
GUI: export api; widgets module: refactoring
DrZlo13 Jul 12, 2022
efaf1c4
Plugin API: bump
DrZlo13 Jul 12, 2022
21b8998
Core: move intrinsic export to target-specific
DrZlo13 Jul 12, 2022
66bfead
Elf Loader: more logs, increase stack, dump all unresolved symbols to…
DrZlo13 Jul 12, 2022
7a9e0a3
fbt: fixed unmarked entries being treated as approved
hedger Jul 12, 2022
0012fc1
fbt: sdk & symbols generation cleanup and logic fixes
hedger Jul 13, 2022
37be0d9
elf_loader: cleanup; added support for launch from CLI
hedger Jul 13, 2022
2d4c99d
ELF loader: loading message screen
DrZlo13 Jul 13, 2022
4f3471e
ELF loader: loading animation and error message
DrZlo13 Jul 13, 2022
143daef
fbt: embedding .fzdata section with app meta
hedger Jul 13, 2022
809d795
Merge branch 'dev' into hedger/2627-apisdk
hedger Jul 13, 2022
07aed56
fbt: writing correct version to external elf binary
hedger Jul 13, 2022
d9cf554
fbt: moved api csv location to SDK_DEFINITION; added COMSTR for metad…
hedger Jul 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@
[submodule "lib/mbedtls"]
path = lib/mbedtls
url = https://github.com/Mbed-TLS/mbedtls.git
[submodule "lib/cxxheaderparser"]
path = lib/cxxheaderparser
url = https://github.com/robotpy/cxxheaderparser.git
1 change: 1 addition & 0 deletions applications/bt/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ App(
],
stack_size=1 * 1024,
order=20,
sdk_headers=["bt_service/bt.h"],
)

App(
Expand Down
1 change: 1 addition & 0 deletions applications/cli/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ App(
cdefines=["SRV_CLI"],
stack_size=4 * 1024,
order=30,
sdk_headers=["cli.h", "cli_vcp.h"],
)
12 changes: 10 additions & 2 deletions applications/cli/cli_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@
#include <m-bptree.h>
#include <m-array.h>

#include "cli_vcp.h"

#define CLI_LINE_SIZE_MAX
#define CLI_COMMANDS_TREE_RANK 4

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
CliCallback callback;
void* context;
uint32_t flags;
} CliCommand;

typedef struct CliSession CliSession;

struct CliSession {
void (*init)(void);
void (*deinit)(void);
Expand Down Expand Up @@ -57,3 +61,7 @@ void cli_reset(Cli* cli);
void cli_putc(Cli* cli, char c);

void cli_stdout_callback(void* _cookie, const char* data, size_t size);

#ifdef __cplusplus
}
#endif
2 changes: 1 addition & 1 deletion applications/cli/cli_vcp.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <furi_hal_usb_cdc_i.h>
#include <furi_hal_usb_cdc.h>
#include <furi_hal.h>
#include <furi.h>
#include <stream_buffer.h>
Expand Down
4 changes: 2 additions & 2 deletions applications/cli/cli_vcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

#pragma once

#include "cli_i.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct CliSession CliSession;

extern CliSession cli_vcp;

#ifdef __cplusplus
Expand Down
1 change: 1 addition & 0 deletions applications/desktop/helpers/pin_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "../helpers/pin_lock.h"
#include "../desktop_i.h"
#include <cli/cli.h>
#include <cli/cli_vcp.h>

static const NotificationSequence sequence_pin_fail = {
Expand Down
1 change: 1 addition & 0 deletions applications/dialogs/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ App(
requires=["gui"],
stack_size=1 * 1024,
order=40,
sdk_headers=["dialogs.h"],
)
1 change: 1 addition & 0 deletions applications/dolphin/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ App(
cdefines=["SRV_DOLPHIN"],
stack_size=1 * 1024,
order=50,
sdk_headers=["dolphin.h"],
)

App(
Expand Down
11 changes: 11 additions & 0 deletions applications/elf_loader/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
App(
appid="elf_loader",
name="ELF Loader",
apptype=FlipperAppType.APP,
entry_point="elf_loader_app",
# cdefines=["APP_ELF_LOADER"],
requires=["gui", "storage"],
stack_size=10 * 1024,
icon="A_Debug_14",
order=0,
)
99 changes: 99 additions & 0 deletions applications/elf_loader/elf_cpp/compilesort.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma once

#include <iterator>
#include <array>

namespace cstd {

template <typename RAIt>
constexpr RAIt next(RAIt it, typename std::iterator_traits<RAIt>::difference_type n = 1) {
return it + n;
}

template <typename RAIt> constexpr auto distance(RAIt first, RAIt last) {
return last - first;
}

template <class ForwardIt1, class ForwardIt2>
constexpr void iter_swap(ForwardIt1 a, ForwardIt2 b) {
auto temp = std::move(*a);
*a = std::move(*b);
*b = std::move(temp);
}

template <class InputIt, class UnaryPredicate>
constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q) {
for(; first != last; ++first) {
if(!q(*first)) {
return first;
}
}
return last;
}

template <class ForwardIt, class UnaryPredicate>
constexpr ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p) {
first = cstd::find_if_not(first, last, p);
if(first == last) return first;

for(ForwardIt i = cstd::next(first); i != last; ++i) {
if(p(*i)) {
cstd::iter_swap(i, first);
++first;
}
}
return first;
}

}

template <class RAIt, class Compare = std::less<> >
constexpr void quick_sort(RAIt first, RAIt last, Compare cmp = Compare{}) {
auto const N = cstd::distance(first, last);
if(N <= 1) return;
auto const pivot = *cstd::next(first, N / 2);
auto const middle1 =
cstd::partition(first, last, [=](auto const& elem) { return cmp(elem, pivot); });
auto const middle2 =
cstd::partition(middle1, last, [=](auto const& elem) { return !cmp(pivot, elem); });
quick_sort(first, middle1, cmp); // assert(std::is_sorted(first, middle1, cmp));
quick_sort(middle2, last, cmp); // assert(std::is_sorted(middle2, last, cmp));
}

template <typename Range> constexpr auto sort(Range&& range) {
quick_sort(std::begin(range), std::end(range));
return range;
}

template <typename V, typename... T>
constexpr auto array_of(T&&... t) -> std::array<V, sizeof...(T)> {
return {{std::forward<T>(t)...}};
}

template <typename T, typename... N>
constexpr auto my_make_array(N&&... args) -> std::array<T, sizeof...(args)> {
return {std::forward<N>(args)...};
}

namespace traits {
template <typename T, typename... Ts> struct array_type { using type = T; };

template <typename T, typename... Ts> static constexpr bool are_same_type() {
return std::conjunction_v<std::is_same<T, Ts>...>;
}

}

template <typename... T> constexpr auto create_array(const T&&... values) {
using array_type = typename traits::array_type<T...>::type;
static_assert(sizeof...(T) > 0, "an array must have at least one element");
static_assert(traits::are_same_type<T...>(), "all elements must have same type");
return std::array<array_type, sizeof...(T)>{values...};
}

template <typename T, typename... Ts> constexpr auto create_array_t(const Ts&&... values) {
using array_type = T;
static_assert(sizeof...(Ts) > 0, "an array must have at least one element");
static_assert(traits::are_same_type<Ts...>(), "all elements must have same type");
return std::array<array_type, sizeof...(Ts)>{static_cast<T>(values)...};
}
38 changes: 38 additions & 0 deletions applications/elf_loader/elf_cpp/elf_hashtable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "compilesort.hpp"
#include "elf_hashtable.h"
#include "elf_hashtable_entry.h"
#include "elf_hashtable_checks.hpp"

#include <gui/gui.h>
#include <furi.h>

#include <array>
#include <algorithm>

/* Generated table */
#include <symbols.h>

#define TAG "elf_hashtable"

static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!");

extern "C" bool elf_resolve_from_hashtable(const char* name, Elf32_Addr* address) {
bool result = false;
uint32_t gnu_sym_hash = elf_gnu_hash(name);

sym_entry key = {
.hash = gnu_sym_hash,
.address = 0,
};

auto find_res = std::lower_bound(elf_api_table.cbegin(), elf_api_table.cend(), key);
if((find_res == elf_api_table.cend() || (find_res->hash != gnu_sym_hash))) {
FURI_LOG_W(TAG, "Cant find symbol '%s' (hash %x)!", name, gnu_sym_hash);
result = false;
} else {
result = true;
*address = find_res->address;
}

return result;
}
19 changes: 19 additions & 0 deletions applications/elf_loader/elf_cpp/elf_hashtable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#include "../elf_lib/elf.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* Get function address by function name
* @param name function name
* @param address output for function address
* @return true if the table contains a function
*/
bool elf_resolve_from_hashtable(const char* name, Elf32_Addr* address);

#ifdef __cplusplus
}
#endif
23 changes: 23 additions & 0 deletions applications/elf_loader/elf_cpp/elf_hashtable_checks.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @file elf-hashtable-checks.h
* @author https://github.com/hedger/
* @version 1.0
* @date 2021-12-21
*
*
*/

#pragma once
#include <array>
#include "elf_hashtable_entry.h"

template <std::size_t N>
constexpr bool has_hash_collisions(const std::array<sym_entry, N> api_methods) {
for(std::size_t i = 0; i < (N - 1); ++i) {
if(api_methods[i].hash == api_methods[i + 1].hash) {
return true;
}
}

return false;
}
43 changes: 43 additions & 0 deletions applications/elf_loader/elf_cpp/elf_hashtable_entry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

struct sym_entry {
uint32_t hash;
uint32_t address;
};

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
#include <array>
#include <algorithm>

#define API_METHOD(x, ret_type, args_type) \
sym_entry { \
.hash = elf_gnu_hash(#x), .address = (uint32_t)(static_cast<ret_type(*) args_type>(x)) \
}

#define API_VARIABLE(x, var_type) \
sym_entry { \
.hash = elf_gnu_hash(#x), .address = (uint32_t)(&(x)), \
}

constexpr bool operator<(const sym_entry& k1, const sym_entry& k2) {
return k1.hash < k2.hash;
}

constexpr uint32_t elf_gnu_hash(const char* s) {
uint32_t h = 0x1505;
for(unsigned char c = *s; c != '\0'; c = *++s) {
h = (h << 5) + h + c;
}
return h;
}

#endif
Loading