Embed assets in elf file (#2466)

* FBT: file_assets generator
* Elf file: process manifest section externally
* FBT, file_assets generator: add assets signature
* Storage: assets path alias
* Flipper application: assets unpacker
* Apps, Storage: use '/data' alias for apps data
* Storage: copy file to file
* Assets: log flag, fixes
* Update f18 api
* Assets: asserts
* Assets: fix signature_data check
* App assets: example
* Example assets: fix folder structure in readme
* Assets: fix error handling
* Assets builder: use ansii instead of utf-8, use .fapassets section instead of .fapfiles, add assets path to signature
* Elf file: comment strange places
* Storage: totaly optimized storage_file_copy_to_file
This commit is contained in:
Sergey Gavrilov
2023-03-09 18:01:53 +03:00
committed by GitHub
parent 50ef5deefc
commit 4fd043398a
22 changed files with 937 additions and 113 deletions

View File

@@ -1,6 +1,7 @@
#include "flipper_application.h"
#include "elf/elf_file.h"
#include <notification/notification_messages.h>
#include "application_assets.h"
#define TAG "fapp"
@@ -55,24 +56,83 @@ static FlipperApplicationPreloadStatus
return FlipperApplicationPreloadStatusSuccess;
}
/* Parse headers, load manifest */
FlipperApplicationPreloadStatus
flipper_application_preload_manifest(FlipperApplication* app, const char* path) {
if(!elf_file_open(app->elf, path) || !elf_file_load_manifest(app->elf, &app->manifest)) {
static bool flipper_application_process_manifest_section(
File* file,
size_t offset,
size_t size,
void* context) {
FlipperApplicationManifest* manifest = context;
if(size < sizeof(FlipperApplicationManifest)) {
return false;
}
if(manifest == NULL) {
return true;
}
return storage_file_seek(file, offset, true) &&
storage_file_read(file, manifest, size) == size;
}
// we can't use const char* as context because we will lose the const qualifier
typedef struct {
const char* path;
} FlipperApplicationPreloadAssetsContext;
static bool flipper_application_process_assets_section(
File* file,
size_t offset,
size_t size,
void* context) {
FlipperApplicationPreloadAssetsContext* preload_context = context;
return flipper_application_assets_load(file, preload_context->path, offset, size);
}
static FlipperApplicationPreloadStatus
flipper_application_load(FlipperApplication* app, const char* path, bool load_full) {
if(!elf_file_open(app->elf, path)) {
return FlipperApplicationPreloadStatusInvalidFile;
}
// if we are loading full file
if(load_full) {
// load section table
if(!elf_file_load_section_table(app->elf)) {
return FlipperApplicationPreloadStatusInvalidFile;
}
// load assets section
FlipperApplicationPreloadAssetsContext preload_context = {.path = path};
if(elf_process_section(
app->elf,
".fapassets",
flipper_application_process_assets_section,
&preload_context) == ElfProcessSectionResultCannotProcess) {
return FlipperApplicationPreloadStatusInvalidFile;
}
}
// load manifest section
if(elf_process_section(
app->elf, ".fapmeta", flipper_application_process_manifest_section, &app->manifest) !=
ElfProcessSectionResultSuccess) {
return FlipperApplicationPreloadStatusInvalidFile;
}
return flipper_application_validate_manifest(app);
}
/* Parse headers, load manifest */
FlipperApplicationPreloadStatus
flipper_application_preload_manifest(FlipperApplication* app, const char* path) {
return flipper_application_load(app, path, false);
}
/* Parse headers, load full file */
FlipperApplicationPreloadStatus
flipper_application_preload(FlipperApplication* app, const char* path) {
if(!elf_file_open(app->elf, path) || !elf_file_load_section_table(app->elf, &app->manifest)) {
return FlipperApplicationPreloadStatusInvalidFile;
}
return flipper_application_validate_manifest(app);
return flipper_application_load(app, path, true);
}
const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app) {