MPU Hal (#1492)
* Furi HAL: memory protection unit * Core: prohibit NULL dereferencing, even for reads. * Applications: fix NULL dereference * Core: stack protection by MPU * MPU: stack region alignment * Apps: fix null pointer dereferences * Threads: fix non-null arg check * Desktop settings: fix null pointer dereference * Core: documented null-check hack * Fix null dereference issues * Apps: args check * Core: naming fixes * format code * Core: remove NONNULL specifier * FurHal: move MPU initialization to begining, fix enum naming Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									4a6477aaa8
								
							
						
					
					
						commit
						eed4296890
					
				| @ -37,7 +37,7 @@ void archive_scene_rename_on_enter(void* context) { | |||||||
|         false); |         false); | ||||||
| 
 | 
 | ||||||
|     ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( |     ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( | ||||||
|         string_get_cstr(archive->browser->path), archive->file_extension, NULL); |         string_get_cstr(archive->browser->path), archive->file_extension, ""); | ||||||
|     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); |     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); | ||||||
| 
 | 
 | ||||||
|     string_clear(filename); |     string_clear(filename); | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { | |||||||
| 
 | 
 | ||||||
|     string_init(app->file_path); |     string_init(app->file_path); | ||||||
| 
 | 
 | ||||||
|     if(arg != NULL) { |     if(arg && strlen(arg)) { | ||||||
|         string_set_str(app->file_path, arg); |         string_set_str(app->file_path, arg); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -79,7 +79,6 @@ void bad_usb_app_free(BadUsbApp* app) { | |||||||
|     furi_assert(app); |     furi_assert(app); | ||||||
| 
 | 
 | ||||||
|     // Views
 |     // Views
 | ||||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewFileSelect); |  | ||||||
|     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); |     view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork); | ||||||
|     bad_usb_free(app->bad_usb_view); |     bad_usb_free(app->bad_usb_view); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -38,6 +38,5 @@ struct BadUsbApp { | |||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     BadUsbAppViewError, |     BadUsbAppViewError, | ||||||
|     BadUsbAppViewFileSelect, |  | ||||||
|     BadUsbAppViewWork, |     BadUsbAppViewWork, | ||||||
| } BadUsbAppView; | } BadUsbAppView; | ||||||
|  | |||||||
| @ -347,7 +347,8 @@ static void bt_close_connection(Bt* bt) { | |||||||
|     furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); |     furi_event_flag_set(bt->api_event, BT_API_UNLOCK_EVENT); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t bt_srv() { | int32_t bt_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     Bt* bt = bt_alloc(); |     Bt* bt = bt_alloc(); | ||||||
| 
 | 
 | ||||||
|     if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { |     if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { | ||||||
|  | |||||||
| @ -143,7 +143,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) { | |||||||
|     furi_assert(view); |     furi_assert(view); | ||||||
|     bool activate = true; |     bool activate = true; | ||||||
|     BubbleAnimationViewModel* model = view_get_model(view->view); |     BubbleAnimationViewModel* model = view_get_model(view->view); | ||||||
|     if(!model->current) { |     if(model->current == NULL) { | ||||||
|         activate = false; |         activate = false; | ||||||
|     } else if(model->freeze_frame) { |     } else if(model->freeze_frame) { | ||||||
|         activate = false; |         activate = false; | ||||||
| @ -151,6 +151,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) { | |||||||
|         activate = false; |         activate = false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if(model->current != NULL) { | ||||||
|         if(!force) { |         if(!force) { | ||||||
|             if((model->active_ended_at + model->current->active_cooldown * 1000) > |             if((model->active_ended_at + model->current->active_cooldown * 1000) > | ||||||
|                xTaskGetTickCount()) { |                xTaskGetTickCount()) { | ||||||
| @ -161,6 +162,7 @@ static void bubble_animation_activate(BubbleAnimationView* view, bool force) { | |||||||
|                 activate = false; |                 activate = false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|     view_commit_model(view->view, false); |     view_commit_model(view->view, false); | ||||||
| 
 | 
 | ||||||
|     if(!activate && !force) { |     if(!activate && !force) { | ||||||
| @ -288,7 +290,10 @@ static void bubble_animation_enter(void* context) { | |||||||
|     bubble_animation_activate(view, false); |     bubble_animation_activate(view, false); | ||||||
| 
 | 
 | ||||||
|     BubbleAnimationViewModel* model = view_get_model(view->view); |     BubbleAnimationViewModel* model = view_get_model(view->view); | ||||||
|     uint8_t frame_rate = model->current->icon_animation.frame_rate; |     uint8_t frame_rate = 0; | ||||||
|  |     if(model->current != NULL) { | ||||||
|  |         frame_rate = model->current->icon_animation.frame_rate; | ||||||
|  |     } | ||||||
|     view_commit_model(view->view, false); |     view_commit_model(view->view, false); | ||||||
| 
 | 
 | ||||||
|     if(frame_rate) { |     if(frame_rate) { | ||||||
|  | |||||||
| @ -90,7 +90,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { | |||||||
| extern int32_t desktop_settings_app(void* p) { | extern int32_t desktop_settings_app(void* p) { | ||||||
|     DesktopSettingsApp* app = desktop_settings_app_alloc(); |     DesktopSettingsApp* app = desktop_settings_app_alloc(); | ||||||
|     LOAD_DESKTOP_SETTINGS(&app->settings); |     LOAD_DESKTOP_SETTINGS(&app->settings); | ||||||
|     if(!strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG)) { |     if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { | ||||||
|         scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); |         scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); | ||||||
|     } else { |     } else { | ||||||
|         scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart); |         scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneStart); | ||||||
|  | |||||||
| @ -185,6 +185,7 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { | |||||||
|             return false; |             return false; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |     if(item) { | ||||||
|         if(item->type == ButtonMenuItemTypeControl) { |         if(item->type == ButtonMenuItemTypeControl) { | ||||||
|             if(type == InputTypeShort) { |             if(type == InputTypeShort) { | ||||||
|                 if(item && item->callback) { |                 if(item && item->callback) { | ||||||
| @ -200,6 +201,7 @@ static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static bool button_menu_view_input_callback(InputEvent* event, void* context) { | static bool button_menu_view_input_callback(InputEvent* event, void* context) { | ||||||
|     furi_assert(event); |     furi_assert(event); | ||||||
|  | |||||||
| @ -147,7 +147,7 @@ static void text_input_backspace_cb(TextInputModel* model) { | |||||||
| 
 | 
 | ||||||
| static void text_input_view_draw_callback(Canvas* canvas, void* _model) { | static void text_input_view_draw_callback(Canvas* canvas, void* _model) { | ||||||
|     TextInputModel* model = _model; |     TextInputModel* model = _model; | ||||||
|     uint8_t text_length = strlen(model->text_buffer); |     uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; | ||||||
|     uint8_t needed_string_width = canvas_width(canvas) - 8; |     uint8_t needed_string_width = canvas_width(canvas) - 8; | ||||||
|     uint8_t start_pos = 4; |     uint8_t start_pos = 4; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| // #include <gui/view.h>
 |  | ||||||
| #include <m-string.h> | #include <m-string.h> | ||||||
|  | #include <core/common_defines.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
|  | |||||||
| @ -353,7 +353,7 @@ int32_t ibutton_app(void* p) { | |||||||
|     bool key_loaded = false; |     bool key_loaded = false; | ||||||
|     bool rpc_mode = false; |     bool rpc_mode = false; | ||||||
| 
 | 
 | ||||||
|     if(p) { |     if(p && strlen(p)) { | ||||||
|         uint32_t rpc_ctx = 0; |         uint32_t rpc_ctx = 0; | ||||||
|         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { |         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { | ||||||
|             FURI_LOG_D(TAG, "Running in RPC mode"); |             FURI_LOG_D(TAG, "Running in RPC mode"); | ||||||
|  | |||||||
| @ -405,7 +405,7 @@ int32_t infrared_app(void* p) { | |||||||
|     bool is_remote_loaded = false; |     bool is_remote_loaded = false; | ||||||
|     bool is_rpc_mode = false; |     bool is_rpc_mode = false; | ||||||
| 
 | 
 | ||||||
|     if(p) { |     if(p && strlen(p)) { | ||||||
|         uint32_t rpc_ctx = 0; |         uint32_t rpc_ctx = 0; | ||||||
|         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { |         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { | ||||||
|             infrared->rpc_ctx = (void*)rpc_ctx; |             infrared->rpc_ctx = (void*)rpc_ctx; | ||||||
|  | |||||||
| @ -64,7 +64,8 @@ const char* input_get_type_name(InputType type) { | |||||||
|     return "Unknown"; |     return "Unknown"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t input_srv() { | int32_t input_srv(void* p) { | ||||||
|  |     UNUSED(p); | ||||||
|     input = malloc(sizeof(Input)); |     input = malloc(sizeof(Input)); | ||||||
|     input->thread_id = furi_thread_get_current_id(); |     input->thread_id = furi_thread_get_current_id(); | ||||||
|     input->event_pubsub = furi_pubsub_alloc(); |     input->event_pubsub = furi_pubsub_alloc(); | ||||||
|  | |||||||
| @ -74,7 +74,7 @@ void LfRfidApp::run(void* _args) { | |||||||
| 
 | 
 | ||||||
|     make_app_folder(); |     make_app_folder(); | ||||||
| 
 | 
 | ||||||
|     if(strlen(args)) { |     if(args && strlen(args)) { | ||||||
|         uint32_t rpc_ctx_ptr = 0; |         uint32_t rpc_ctx_ptr = 0; | ||||||
|         if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { |         if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { | ||||||
|             rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; |             rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; | ||||||
|  | |||||||
| @ -300,7 +300,7 @@ int32_t music_player_app(void* p) { | |||||||
|     string_init(file_path); |     string_init(file_path); | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         if(p) { |         if(p && strlen(p)) { | ||||||
|             string_cat_str(file_path, p); |             string_cat_str(file_path, p); | ||||||
|         } else { |         } else { | ||||||
|             string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); |             string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); | ||||||
|  | |||||||
| @ -238,7 +238,7 @@ int32_t nfc_app(void* p) { | |||||||
|     char* args = p; |     char* args = p; | ||||||
| 
 | 
 | ||||||
|     // Check argument and run corresponding scene
 |     // Check argument and run corresponding scene
 | ||||||
|     if((*args != '\0')) { |     if(args && strlen(args)) { | ||||||
|         nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); |         nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); | ||||||
|         uint32_t rpc_ctx = 0; |         uint32_t rpc_ctx = 0; | ||||||
|         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { |         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { | ||||||
|  | |||||||
| @ -200,7 +200,7 @@ static void power_check_battery_level_change(Power* power) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t power_srv(void* p) { | int32_t power_srv(void* p) { | ||||||
|     (void)p; |     UNUSED(p); | ||||||
|     Power* power = power_alloc(); |     Power* power = power_alloc(); | ||||||
|     power_update_info(power); |     power_update_info(power); | ||||||
|     furi_record_create(RECORD_POWER, power); |     furi_record_create(RECORD_POWER, power); | ||||||
|  | |||||||
| @ -76,7 +76,7 @@ void power_settings_app_free(PowerSettingsApp* app) { | |||||||
| 
 | 
 | ||||||
| int32_t power_settings_app(void* p) { | int32_t power_settings_app(void* p) { | ||||||
|     uint32_t first_scene = PowerSettingsAppSceneStart; |     uint32_t first_scene = PowerSettingsAppSceneStart; | ||||||
|     if(p && !strcmp(p, "off")) { |     if(p && strlen(p) && !strcmp(p, "off")) { | ||||||
|         first_scene = PowerSettingsAppScenePowerOff; |         first_scene = PowerSettingsAppScenePowerOff; | ||||||
|     } |     } | ||||||
|     PowerSettingsApp* app = power_settings_app_alloc(first_scene); |     PowerSettingsApp* app = power_settings_app_alloc(first_scene); | ||||||
|  | |||||||
| @ -78,6 +78,8 @@ static void rpc_system_system_device_info_callback( | |||||||
|     furi_assert(value); |     furi_assert(value); | ||||||
|     RpcSystemContext* ctx = context; |     RpcSystemContext* ctx = context; | ||||||
| 
 | 
 | ||||||
|  |     furi_assert(key); | ||||||
|  |     furi_assert(value); | ||||||
|     char* str_key = strdup(key); |     char* str_key = strdup(key); | ||||||
|     char* str_value = strdup(value); |     char* str_value = strdup(value); | ||||||
| 
 | 
 | ||||||
| @ -232,6 +234,8 @@ static void rpc_system_system_power_info_callback( | |||||||
|     furi_assert(value); |     furi_assert(value); | ||||||
|     RpcSystemContext* ctx = context; |     RpcSystemContext* ctx = context; | ||||||
| 
 | 
 | ||||||
|  |     furi_assert(key); | ||||||
|  |     furi_assert(value); | ||||||
|     char* str_key = strdup(key); |     char* str_key = strdup(key); | ||||||
|     char* str_value = strdup(value); |     char* str_value = strdup(value); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -59,8 +59,8 @@ void subghz_scene_save_name_on_enter(void* context) { | |||||||
|         MAX_TEXT_INPUT_LEN, // buffer size
 |         MAX_TEXT_INPUT_LEN, // buffer size
 | ||||||
|         dev_name_empty); |         dev_name_empty); | ||||||
| 
 | 
 | ||||||
|     ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( |     ValidatorIsFile* validator_is_file = | ||||||
|         string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, NULL); |         validator_is_file_alloc_init(string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, ""); | ||||||
|     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); |     text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); | ||||||
| 
 | 
 | ||||||
|     string_clear(file_name); |     string_clear(file_name); | ||||||
|  | |||||||
| @ -320,7 +320,7 @@ int32_t subghz_app(void* p) { | |||||||
|     subghz_environment_load_keystore( |     subghz_environment_load_keystore( | ||||||
|         subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); |         subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); | ||||||
|     // Check argument and run corresponding scene
 |     // Check argument and run corresponding scene
 | ||||||
|     if(p) { |     if(p && strlen(p)) { | ||||||
|         uint32_t rpc_ctx = 0; |         uint32_t rpc_ctx = 0; | ||||||
|         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { |         if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { | ||||||
|             subghz->rpc_ctx = (void*)rpc_ctx; |             subghz->rpc_ctx = (void*)rpc_ctx; | ||||||
|  | |||||||
| @ -420,12 +420,14 @@ static void | |||||||
|     mu_check(result_msg_file->size == expected_msg_file->size); |     mu_check(result_msg_file->size == expected_msg_file->size); | ||||||
|     mu_check(result_msg_file->type == expected_msg_file->type); |     mu_check(result_msg_file->type == expected_msg_file->type); | ||||||
| 
 | 
 | ||||||
|     mu_check(!result_msg_file->data == !expected_msg_file->data); |     if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) { | ||||||
|  |         mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
 | ||||||
|         mu_check(result_msg_file->data->size == expected_msg_file->data->size); |         mu_check(result_msg_file->data->size == expected_msg_file->data->size); | ||||||
|         for(int i = 0; i < result_msg_file->data->size; ++i) { |         for(int i = 0; i < result_msg_file->data->size; ++i) { | ||||||
|             mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]); |             mu_check(result_msg_file->data->bytes[i] == expected_msg_file->data->bytes[i]); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) { | static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) { | ||||||
|     mu_check(result->command_id == expected->command_id); |     mu_check(result->command_id == expected->command_id); | ||||||
| @ -1346,8 +1348,7 @@ static void test_rpc_storage_rename_run( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(test_storage_rename) { | MU_TEST(test_storage_rename) { | ||||||
|     test_rpc_storage_rename_run( |     test_rpc_storage_rename_run("", "", ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME); | ||||||
|         NULL, NULL, ++command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME); |  | ||||||
| 
 | 
 | ||||||
|     furi_check(!test_is_exists(TEST_DIR "empty.txt")); |     furi_check(!test_is_exists(TEST_DIR "empty.txt")); | ||||||
|     test_create_file(TEST_DIR "empty.txt", 0); |     test_create_file(TEST_DIR "empty.txt", 0); | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ static void | |||||||
| 
 | 
 | ||||||
| Updater* updater_alloc(const char* arg) { | Updater* updater_alloc(const char* arg) { | ||||||
|     Updater* updater = malloc(sizeof(Updater)); |     Updater* updater = malloc(sizeof(Updater)); | ||||||
|     if(arg) { |     if(arg && strlen(arg)) { | ||||||
|         string_init_set_str(updater->startup_arg, arg); |         string_init_set_str(updater->startup_arg, arg); | ||||||
|         string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH("")); |         string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH("")); | ||||||
|     } else { |     } else { | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ extern uint32_t SystemCoreClock; | |||||||
| #define configUSE_16_BIT_TICKS 0 | #define configUSE_16_BIT_TICKS 0 | ||||||
| #define configUSE_MUTEXES 1 | #define configUSE_MUTEXES 1 | ||||||
| #define configQUEUE_REGISTRY_SIZE 0 | #define configQUEUE_REGISTRY_SIZE 0 | ||||||
| #define configCHECK_FOR_STACK_OVERFLOW 2 | #define configCHECK_FOR_STACK_OVERFLOW 0 | ||||||
| #define configUSE_RECURSIVE_MUTEXES 1 | #define configUSE_RECURSIVE_MUTEXES 1 | ||||||
| #define configUSE_COUNTING_SEMAPHORES 1 | #define configUSE_COUNTING_SEMAPHORES 1 | ||||||
| #define configENABLE_BACKWARD_COMPATIBILITY 0 | #define configENABLE_BACKWARD_COMPATIBILITY 0 | ||||||
| @ -145,3 +145,7 @@ standard names. */ | |||||||
| #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1 | #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1 | ||||||
| #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \ | #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \ | ||||||
|     1 /* required only for Keil but does not hurt otherwise */ |     1 /* required only for Keil but does not hurt otherwise */ | ||||||
|  | 
 | ||||||
|  | #define traceTASK_SWITCHED_IN()                                     \ | ||||||
|  |     extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \ | ||||||
|  |     furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack) | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
|  | #include <furi_hal_mpu.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_cortex.h> | #include <stm32wbxx_ll_cortex.h> | ||||||
| 
 | 
 | ||||||
| @ -35,6 +36,7 @@ void furi_hal_deinit_early() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_init() { | void furi_hal_init() { | ||||||
|  |     furi_hal_mpu_init(); | ||||||
|     furi_hal_clock_init(); |     furi_hal_clock_init(); | ||||||
|     furi_hal_console_init(); |     furi_hal_console_init(); | ||||||
|     furi_hal_rtc_init(); |     furi_hal_rtc_init(); | ||||||
| @ -80,17 +82,6 @@ void furi_hal_init() { | |||||||
|     // FatFS driver initialization
 |     // FatFS driver initialization
 | ||||||
|     MX_FATFS_Init(); |     MX_FATFS_Init(); | ||||||
|     FURI_LOG_I(TAG, "FATFS OK"); |     FURI_LOG_I(TAG, "FATFS OK"); | ||||||
| 
 |  | ||||||
|     // Partial null pointer dereference protection
 |  | ||||||
|     LL_MPU_Disable(); |  | ||||||
|     LL_MPU_ConfigRegion( |  | ||||||
|         LL_MPU_REGION_NUMBER0, |  | ||||||
|         0x00, |  | ||||||
|         0x0, |  | ||||||
|         LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | LL_MPU_ACCESS_BUFFERABLE | |  | ||||||
|             LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_TEX_LEVEL1 | |  | ||||||
|             LL_MPU_INSTRUCTION_ACCESS_ENABLE); |  | ||||||
|     LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_switch(void* address) { | void furi_hal_switch(void* address) { | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <stm32wbxx.h> | #include <stm32wbxx.h> | ||||||
| #include <stm32wbxx_ll_tim.h> | #include <stm32wbxx_ll_tim.h> | ||||||
| #include <stm32wbxx_ll_rcc.h> | #include <stm32wbxx_ll_rcc.h> | ||||||
|  | #include <stm32wbxx_ll_cortex.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "FuriHalInterrupt" | #define TAG "FuriHalInterrupt" | ||||||
| 
 | 
 | ||||||
| @ -95,6 +96,10 @@ void furi_hal_interrupt_init() { | |||||||
|     LL_SYSCFG_DisableIT_FPU_IDC(); |     LL_SYSCFG_DisableIT_FPU_IDC(); | ||||||
|     LL_SYSCFG_DisableIT_FPU_IXC(); |     LL_SYSCFG_DisableIT_FPU_IXC(); | ||||||
| 
 | 
 | ||||||
|  |     LL_HANDLER_EnableFault(LL_HANDLER_FAULT_USG); | ||||||
|  |     LL_HANDLER_EnableFault(LL_HANDLER_FAULT_BUS); | ||||||
|  |     LL_HANDLER_EnableFault(LL_HANDLER_FAULT_MEM); | ||||||
|  | 
 | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -241,6 +246,20 @@ void HardFault_Handler() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MemManage_Handler() { | void MemManage_Handler() { | ||||||
|  |     if(FURI_BIT(SCB->CFSR, SCB_CFSR_MMARVALID_Pos)) { | ||||||
|  |         uint32_t memfault_address = SCB->MMFAR; | ||||||
|  |         if(memfault_address < (1024 * 1024)) { | ||||||
|  |             // from 0x00 to 1MB, see FuriHalMpuRegionNULL
 | ||||||
|  |             furi_crash("NULL pointer dereference"); | ||||||
|  |         } else { | ||||||
|  |             // write or read of MPU region 1 (FuriHalMpuRegionStack)
 | ||||||
|  |             furi_crash("MPU fault, possibly stack overflow"); | ||||||
|  |         } | ||||||
|  |     } else if(FURI_BIT(SCB->CFSR, SCB_CFSR_MSTKERR_Pos)) { | ||||||
|  |         // push to stack on MPU region 1 (FuriHalMpuRegionStack)
 | ||||||
|  |         furi_crash("MemManage fault, possibly stack overflow"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     furi_crash("MemManage"); |     furi_crash("MemManage"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										66
									
								
								firmware/targets/f7/furi_hal/furi_hal_mpu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								firmware/targets/f7/furi_hal/furi_hal_mpu.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | |||||||
|  | #include <furi_hal_mpu.h> | ||||||
|  | #include <stm32wbxx_ll_cortex.h> | ||||||
|  | 
 | ||||||
|  | #define FURI_HAL_MPU_ATTRIBUTES                                                     \ | ||||||
|  |     (LL_MPU_ACCESS_BUFFERABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_SHAREABLE | \ | ||||||
|  |      LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_ENABLE) | ||||||
|  | 
 | ||||||
|  | #define FURI_HAL_MPU_STACK_PROTECT_REGION FuriHalMPURegionSize32B | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_init() { | ||||||
|  |     furi_hal_mpu_enable(); | ||||||
|  | 
 | ||||||
|  |     // NULL pointer dereference protection
 | ||||||
|  |     furi_hal_mpu_protect_no_access(FuriHalMpuRegionNULL, 0x00, FuriHalMPURegionSize1MB); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_enable() { | ||||||
|  |     LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_disable() { | ||||||
|  |     LL_MPU_Disable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_protect_no_access( | ||||||
|  |     FuriHalMpuRegion region, | ||||||
|  |     uint32_t address, | ||||||
|  |     FuriHalMPURegionSize size) { | ||||||
|  |     uint32_t size_ll = size; | ||||||
|  |     size_ll = size_ll << MPU_RASR_SIZE_Pos; | ||||||
|  | 
 | ||||||
|  |     furi_hal_mpu_disable(); | ||||||
|  |     LL_MPU_ConfigRegion( | ||||||
|  |         region, 0x00, address, FURI_HAL_MPU_ATTRIBUTES | LL_MPU_REGION_NO_ACCESS | size_ll); | ||||||
|  |     furi_hal_mpu_enable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_protect_read_only( | ||||||
|  |     FuriHalMpuRegion region, | ||||||
|  |     uint32_t address, | ||||||
|  |     FuriHalMPURegionSize size) { | ||||||
|  |     uint32_t size_ll = size; | ||||||
|  |     size_ll = size_ll << MPU_RASR_SIZE_Pos; | ||||||
|  | 
 | ||||||
|  |     furi_hal_mpu_disable(); | ||||||
|  |     LL_MPU_ConfigRegion( | ||||||
|  |         region, 0x00, address, FURI_HAL_MPU_ATTRIBUTES | LL_MPU_REGION_PRIV_RO_URO | size_ll); | ||||||
|  |     furi_hal_mpu_enable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_protect_disable(FuriHalMpuRegion region) { | ||||||
|  |     furi_hal_mpu_disable(); | ||||||
|  |     LL_MPU_DisableRegion(region); | ||||||
|  |     furi_hal_mpu_enable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_set_stack_protection(uint32_t* stack) { | ||||||
|  |     // Protection area address must be aligned to region size
 | ||||||
|  |     uint32_t stack_ptr = (uint32_t)stack; | ||||||
|  |     uint32_t mask = ((1 << (FURI_HAL_MPU_STACK_PROTECT_REGION + 2)) - 1); | ||||||
|  |     stack_ptr &= ~mask; | ||||||
|  |     if(stack_ptr < (uint32_t)stack) stack_ptr += (mask + 1); | ||||||
|  | 
 | ||||||
|  |     furi_hal_mpu_protect_read_only( | ||||||
|  |         FuriHalMpuRegionStack, stack_ptr, FURI_HAL_MPU_STACK_PROTECT_REGION); | ||||||
|  | } | ||||||
							
								
								
									
										86
									
								
								firmware/targets/furi_hal_include/furi_hal_mpu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								firmware/targets/furi_hal_include/furi_hal_mpu.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | /**
 | ||||||
|  |  * @file furi_hal_light.h | ||||||
|  |  * Light control HAL API | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     FuriHalMpuRegionNULL = 0x00, // region 0 used to protect null pointer dereference
 | ||||||
|  |     FuriHalMpuRegionStack = 0x01, // region 1 used to protect stack
 | ||||||
|  |     FuriHalMpuRegion2 = 0x02, | ||||||
|  |     FuriHalMpuRegion3 = 0x03, | ||||||
|  |     FuriHalMpuRegion4 = 0x04, | ||||||
|  |     FuriHalMpuRegion5 = 0x05, | ||||||
|  |     FuriHalMpuRegion6 = 0x06, | ||||||
|  |     FuriHalMpuRegion7 = 0x07, | ||||||
|  | } FuriHalMpuRegion; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     FuriHalMPURegionSize32B = 0x04U, | ||||||
|  |     FuriHalMPURegionSize64B = 0x05U, | ||||||
|  |     FuriHalMPURegionSize128B = 0x06U, | ||||||
|  |     FuriHalMPURegionSize256B = 0x07U, | ||||||
|  |     FuriHalMPURegionSize512B = 0x08U, | ||||||
|  |     FuriHalMPURegionSize1KB = 0x09U, | ||||||
|  |     FuriHalMPURegionSize2KB = 0x0AU, | ||||||
|  |     FuriHalMPURegionSize4KB = 0x0BU, | ||||||
|  |     FuriHalMPURegionSize8KB = 0x0CU, | ||||||
|  |     FuriHalMPURegionSize16KB = 0x0DU, | ||||||
|  |     FuriHalMPURegionSize32KB = 0x0EU, | ||||||
|  |     FuriHalMPURegionSize64KB = 0x0FU, | ||||||
|  |     FuriHalMPURegionSize128KB = 0x10U, | ||||||
|  |     FuriHalMPURegionSize256KB = 0x11U, | ||||||
|  |     FuriHalMPURegionSize512KB = 0x12U, | ||||||
|  |     FuriHalMPURegionSize1MB = 0x13U, | ||||||
|  |     FuriHalMPURegionSize2MB = 0x14U, | ||||||
|  |     FuriHalMPURegionSize4MB = 0x15U, | ||||||
|  |     FuriHalMPURegionSize8MB = 0x16U, | ||||||
|  |     FuriHalMPURegionSize16MB = 0x17U, | ||||||
|  |     FuriHalMPURegionSize32MB = 0x18U, | ||||||
|  |     FuriHalMPURegionSize64MB = 0x19U, | ||||||
|  |     FuriHalMPURegionSize128MB = 0x1AU, | ||||||
|  |     FuriHalMPURegionSize256MB = 0x1BU, | ||||||
|  |     FuriHalMPURegionSize512MB = 0x1CU, | ||||||
|  |     FuriHalMPURegionSize1GB = 0x1DU, | ||||||
|  |     FuriHalMPURegionSize2GB = 0x1EU, | ||||||
|  |     FuriHalMPURegionSize4GB = 0x1FU, | ||||||
|  | } FuriHalMPURegionSize; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Initialize memory protection unit | ||||||
|  |  */ | ||||||
|  | void furi_hal_mpu_init(); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  | * @brief Enable memory protection unit | ||||||
|  | */ | ||||||
|  | void furi_hal_mpu_enable(); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  | * @brief Disable memory protection unit | ||||||
|  | */ | ||||||
|  | void furi_hal_mpu_disable(); | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_protect_no_access( | ||||||
|  |     FuriHalMpuRegion region, | ||||||
|  |     uint32_t address, | ||||||
|  |     FuriHalMPURegionSize size); | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_protect_read_only( | ||||||
|  |     FuriHalMpuRegion region, | ||||||
|  |     uint32_t address, | ||||||
|  |     FuriHalMPURegionSize size); | ||||||
|  | 
 | ||||||
|  | void furi_hal_mpu_protect_disable(FuriHalMpuRegion region); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
| @ -36,10 +36,8 @@ void* calloc(size_t count, size_t size) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char* strdup(const char* s) { | char* strdup(const char* s) { | ||||||
|     const char* s_null = s; |     // arg s marked as non-null, so we need hack to check for NULL
 | ||||||
|     if(s_null == NULL) { |     furi_check(((uint32_t)s << 2) != 0); | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     size_t siz = strlen(s) + 1; |     size_t siz = strlen(s) + 1; | ||||||
|     char* y = pvPortMalloc(siz); |     char* y = pvPortMalloc(siz); | ||||||
|  | |||||||
| @ -88,7 +88,7 @@ void furi_thread_set_name(FuriThread* thread, const char* name) { | |||||||
|     furi_assert(thread); |     furi_assert(thread); | ||||||
|     furi_assert(thread->state == FuriThreadStateStopped); |     furi_assert(thread->state == FuriThreadStateStopped); | ||||||
|     if(thread->name) free((void*)thread->name); |     if(thread->name) free((void*)thread->name); | ||||||
|     thread->name = strdup(name); |     thread->name = name ? strdup(name) : NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) { | void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG