flipper_application.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "flipper_application.h"
  2. #include "elf/elf_file.h"
  3. #define TAG "fapp"
  4. struct FlipperApplication {
  5. ELFDebugInfo state;
  6. FlipperApplicationManifest manifest;
  7. ELFFile* elf;
  8. FuriThread* thread;
  9. };
  10. /* For debugger access to app state */
  11. FlipperApplication* last_loaded_app = NULL;
  12. FlipperApplication*
  13. flipper_application_alloc(Storage* storage, const ElfApiInterface* api_interface) {
  14. FlipperApplication* app = malloc(sizeof(FlipperApplication));
  15. app->elf = elf_file_alloc(storage, api_interface);
  16. app->thread = NULL;
  17. return app;
  18. }
  19. void flipper_application_free(FlipperApplication* app) {
  20. furi_assert(app);
  21. if(app->thread) {
  22. furi_thread_join(app->thread);
  23. furi_thread_free(app->thread);
  24. }
  25. last_loaded_app = NULL;
  26. elf_file_clear_debug_info(&app->state);
  27. elf_file_free(app->elf);
  28. free(app);
  29. }
  30. static FlipperApplicationPreloadStatus
  31. flipper_application_validate_manifest(FlipperApplication* app) {
  32. if(!flipper_application_manifest_is_valid(&app->manifest)) {
  33. return FlipperApplicationPreloadStatusInvalidManifest;
  34. }
  35. if(!flipper_application_manifest_is_compatible(
  36. &app->manifest, elf_file_get_api_interface(app->elf))) {
  37. return FlipperApplicationPreloadStatusApiMismatch;
  38. }
  39. return FlipperApplicationPreloadStatusSuccess;
  40. }
  41. /* Parse headers, load manifest */
  42. FlipperApplicationPreloadStatus
  43. flipper_application_preload_manifest(FlipperApplication* app, const char* path) {
  44. if(!elf_file_open(app->elf, path) || !elf_file_load_manifest(app->elf, &app->manifest)) {
  45. return FlipperApplicationPreloadStatusInvalidFile;
  46. }
  47. return flipper_application_validate_manifest(app);
  48. }
  49. /* Parse headers, load full file */
  50. FlipperApplicationPreloadStatus
  51. flipper_application_preload(FlipperApplication* app, const char* path) {
  52. if(!elf_file_open(app->elf, path) || !elf_file_load_section_table(app->elf, &app->manifest)) {
  53. return FlipperApplicationPreloadStatusInvalidFile;
  54. }
  55. return flipper_application_validate_manifest(app);
  56. }
  57. const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app) {
  58. return &app->manifest;
  59. }
  60. FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplication* app) {
  61. last_loaded_app = app;
  62. ELFFileLoadStatus status = elf_file_load_sections(app->elf);
  63. switch(status) {
  64. case ELFFileLoadStatusSuccess:
  65. elf_file_init_debug_info(app->elf, &app->state);
  66. return FlipperApplicationLoadStatusSuccess;
  67. case ELFFileLoadStatusNoFreeMemory:
  68. return FlipperApplicationLoadStatusNoFreeMemory;
  69. case ELFFileLoadStatusMissingImports:
  70. return FlipperApplicationLoadStatusMissingImports;
  71. default:
  72. return FlipperApplicationLoadStatusUnspecifiedError;
  73. }
  74. }
  75. static int32_t flipper_application_thread(void* context) {
  76. elf_file_pre_run(last_loaded_app->elf);
  77. int32_t result = elf_file_run(last_loaded_app->elf, context);
  78. elf_file_post_run(last_loaded_app->elf);
  79. return result;
  80. }
  81. FuriThread* flipper_application_spawn(FlipperApplication* app, void* args) {
  82. furi_check(app->thread == NULL);
  83. const FlipperApplicationManifest* manifest = flipper_application_get_manifest(app);
  84. furi_check(manifest->stack_size > 0);
  85. app->thread = furi_thread_alloc_ex(
  86. manifest->name, manifest->stack_size, flipper_application_thread, args);
  87. return app->thread;
  88. }
  89. static const char* preload_status_strings[] = {
  90. [FlipperApplicationPreloadStatusSuccess] = "Success",
  91. [FlipperApplicationPreloadStatusUnspecifiedError] = "Unknown error",
  92. [FlipperApplicationPreloadStatusInvalidFile] = "Invalid file",
  93. [FlipperApplicationPreloadStatusInvalidManifest] = "Invalid file manifest",
  94. [FlipperApplicationPreloadStatusApiMismatch] = "API version mismatch",
  95. [FlipperApplicationPreloadStatusTargetMismatch] = "Hardware target mismatch",
  96. };
  97. static const char* load_status_strings[] = {
  98. [FlipperApplicationLoadStatusSuccess] = "Success",
  99. [FlipperApplicationLoadStatusUnspecifiedError] = "Unknown error",
  100. [FlipperApplicationLoadStatusNoFreeMemory] = "Out of memory",
  101. [FlipperApplicationLoadStatusMissingImports] = "Found unsatisfied imports",
  102. };
  103. const char* flipper_application_preload_status_to_string(FlipperApplicationPreloadStatus status) {
  104. if(status >= COUNT_OF(preload_status_strings) || preload_status_strings[status] == NULL) {
  105. return "Unknown error";
  106. }
  107. return preload_status_strings[status];
  108. }
  109. const char* flipper_application_load_status_to_string(FlipperApplicationLoadStatus status) {
  110. if(status >= COUNT_OF(load_status_strings) || load_status_strings[status] == NULL) {
  111. return "Unknown error";
  112. }
  113. return load_status_strings[status];
  114. }