flipper_application.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include "flipper_application.h"
  2. #include "flipper_application_i.h"
  3. #define TAG "fapp"
  4. /* For debugger access to app state */
  5. FlipperApplication* last_loaded_app = NULL;
  6. FlipperApplication*
  7. flipper_application_alloc(Storage* storage, const ElfApiInterface* api_interface) {
  8. FlipperApplication* app = malloc(sizeof(FlipperApplication));
  9. app->api_interface = api_interface;
  10. app->fd = storage_file_alloc(storage);
  11. app->thread = NULL;
  12. return app;
  13. }
  14. void flipper_application_free(FlipperApplication* app) {
  15. furi_assert(app);
  16. if(app->thread) {
  17. furi_thread_join(app->thread);
  18. furi_thread_free(app->thread);
  19. }
  20. last_loaded_app = NULL;
  21. if(app->state.debug_link_size) {
  22. free(app->state.debug_link);
  23. }
  24. if(app->state.mmap_entries) {
  25. free(app->state.mmap_entries);
  26. }
  27. ELFSection_t* sections[] = {&app->text, &app->rodata, &app->data, &app->bss};
  28. for(size_t i = 0; i < COUNT_OF(sections); i++) {
  29. flipper_application_free_section(sections[i]);
  30. }
  31. storage_file_free(app->fd);
  32. free(app);
  33. }
  34. /* Parse headers, load manifest */
  35. FlipperApplicationPreloadStatus
  36. flipper_application_preload(FlipperApplication* app, const char* path) {
  37. if(!flipper_application_load_elf_headers(app, path) ||
  38. !flipper_application_load_section_table(app)) {
  39. return FlipperApplicationPreloadStatusInvalidFile;
  40. }
  41. if((app->manifest.base.manifest_magic != FAP_MANIFEST_MAGIC) &&
  42. (app->manifest.base.manifest_version == FAP_MANIFEST_SUPPORTED_VERSION)) {
  43. return FlipperApplicationPreloadStatusInvalidManifest;
  44. }
  45. if(app->manifest.base.api_version.major != app->api_interface->api_version_major /* ||
  46. app->manifest.base.api_version.minor > app->api_interface->api_version_minor */) {
  47. return FlipperApplicationPreloadStatusApiMismatch;
  48. }
  49. return FlipperApplicationPreloadStatusSuccess;
  50. }
  51. const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app) {
  52. return &app->manifest;
  53. }
  54. FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplication* app) {
  55. last_loaded_app = app;
  56. return flipper_application_load_sections(app);
  57. }
  58. const FlipperApplicationState* flipper_application_get_state(FlipperApplication* app) {
  59. return &app->state;
  60. }
  61. FuriThread* flipper_application_spawn(FlipperApplication* app, void* args) {
  62. furi_check(app->thread == NULL);
  63. const FlipperApplicationManifest* manifest = flipper_application_get_manifest(app);
  64. furi_check(manifest->stack_size > 0);
  65. app->thread = furi_thread_alloc();
  66. furi_thread_set_stack_size(app->thread, manifest->stack_size);
  67. furi_thread_set_name(app->thread, manifest->name);
  68. furi_thread_set_callback(app->thread, (entry_t*)app->entry);
  69. furi_thread_set_context(app->thread, args);
  70. return app->thread;
  71. }
  72. FuriThread* flipper_application_get_thread(FlipperApplication* app) {
  73. return app->thread;
  74. }
  75. void const* flipper_application_get_entry_address(FlipperApplication* app) {
  76. return (void*)app->entry;
  77. }
  78. static const char* preload_status_strings[] = {
  79. [FlipperApplicationPreloadStatusSuccess] = "Success",
  80. [FlipperApplicationPreloadStatusUnspecifiedError] = "Unknown error",
  81. [FlipperApplicationPreloadStatusInvalidFile] = "Invalid file",
  82. [FlipperApplicationPreloadStatusInvalidManifest] = "Invalid file manifest",
  83. [FlipperApplicationPreloadStatusApiMismatch] = "API version mismatch",
  84. [FlipperApplicationPreloadStatusTargetMismatch] = "Hardware target mismatch",
  85. };
  86. static const char* load_status_strings[] = {
  87. [FlipperApplicationLoadStatusSuccess] = "Success",
  88. [FlipperApplicationLoadStatusUnspecifiedError] = "Unknown error",
  89. [FlipperApplicationLoadStatusNoFreeMemory] = "Out of memory",
  90. [FlipperApplicationLoadStatusMissingImports] = "Found unsatisfied imports",
  91. };
  92. const char* flipper_application_preload_status_to_string(FlipperApplicationPreloadStatus status) {
  93. if(status >= COUNT_OF(preload_status_strings) || preload_status_strings[status] == NULL) {
  94. return "Unknown error";
  95. }
  96. return preload_status_strings[status];
  97. }
  98. const char* flipper_application_load_status_to_string(FlipperApplicationLoadStatus status) {
  99. if(status >= COUNT_OF(load_status_strings) || load_status_strings[status] == NULL) {
  100. return "Unknown error";
  101. }
  102. return load_status_strings[status];
  103. }