// Copyright 2020-2021 Beken // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "cli.h" #include #include #include "bk_sys_ctrl.h" #include "bk_drv_model.h" #include "release.h" #include #include #include #include "sys_driver.h" #include #include #include "gpio_driver.h" #include #include "bk_ps.h" #include "bk_pm_internal_api.h" #include "reset_reason.h" #include #include "sdkconfig.h" #include #if CONFIG_CACHE_ENABLE #include "cache.h" #endif #include #include "dwt.h" static void cli_trap_test_help(void) { CLI_LOGI("trap_test [data][read|write][invalid|align|zero|nonsecure|mpuprotect|null]\r\n"); CLI_LOGI("trap_test [instruction][zero|invalid_addr|invalid_instruction|nonsecure]\r\n"); CLI_LOGI("trap_test [memory][func_stack_overwrite|task_stack_overwrite|hw_stack_overwrite|global_overwrite|heap_overwrite|heap_free_malloc_overwrite]\r\n"); } static uint32_t s_trap_test_data_read = 0; static uint32_t s_trap_test_data_read_addr = 0; static uint32_t s_trap_test_data_write = 0; static uint32_t s_trap_test_data_write_addr = 0; typedef void (*trap_test_instruction_ptr)(void); static trap_test_instruction_ptr s_trap_test_instruction_ptr = cli_trap_test_help; void (*test_instruction_fun)(void); #define TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE (16 * 1) //please set it as: 16 * x void func_stack_test(char *array_1, char *array_2, uint32_t len) { typedef struct { char array[TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE]; char *ptr; uint32_t len; }array_test; array_test array; CLI_LOGI("array_addr=0x%x array_1=0x%x array_2=0x%x len=%d\r\n", &array, array_1, array_2, len); for(uint32_t i = 0; i < TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE; i+=16) { CLI_LOGI("array_1:0x%x 0x%x 0x%x 0x%x\r\n", *(uint32_t *)&array_1[i], *(uint32_t *)&array_1[i+4], *(uint32_t *)&array_1[i+8], *(uint32_t *)&array_1[i+12]); CLI_LOGI("array_2:0x%x 0x%x 0x%x 0x%x\r\n", *(uint32_t *)&array_2[i], *(uint32_t *)&array_2[i+4], *(uint32_t *)&array_2[i+8], *(uint32_t *)&array_2[i+12]); } array.ptr = &array.array[0]; memset(array.ptr, 0x32, len); CLI_LOGI("array.array=%s\r\n", array.array); #if 0 for(uint32_t i = 0; i < TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE; i+=16) { CLI_LOGI("array_1:0x%x 0x%x 0x%x 0x%x\r\n", *(uint32_t *)&array_1[i], *(uint32_t *)&array_1[i+4], *(uint32_t *)&array_1[i+8], *(uint32_t *)&array_1[i+12]); CLI_LOGI("array_2:0x%x 0x%x 0x%x 0x%x\r\n", *(uint32_t *)&array_2[i], *(uint32_t *)&array_2[i+4], *(uint32_t *)&array_2[i+8], *(uint32_t *)&array_2[i+12]); } #endif } void trap_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) { if (argc < 2) { goto bk_err_help; } if (os_strcmp(argv[1], "data") == 0) { if(argc < 3) goto bk_err_help; if(os_strcmp(argv[2], "read") == 0) { if(argc < 4) goto bk_err_help; if(os_strcmp(argv[3], "invalid") == 0) { s_trap_test_data_read_addr = 0xC0000000; CLI_LOGI("data read invalid addr=0x%x\r\n", s_trap_test_data_read_addr); s_trap_test_data_read = *(uint32_t *)s_trap_test_data_read_addr; } else if(os_strcmp(argv[3], "align") == 0) { s_trap_test_data_read_addr = 0x2809FFFE; CLI_LOGI("data read align addr=0x%x\r\n", s_trap_test_data_read_addr); s_trap_test_data_read = *(uint32_t *)s_trap_test_data_read_addr; } else if(os_strcmp(argv[3], "zero") == 0) { s_trap_test_data_read_addr = 0; CLI_LOGI("data read zero addr=0x%x\r\n", s_trap_test_data_read_addr); s_trap_test_data_read = *(uint32_t *)s_trap_test_data_read_addr; } else if(os_strcmp(argv[3], "nonsecure") == 0) { s_trap_test_data_read_addr = 0; CLI_LOGI("data read nonsecure addr=0x%x\r\n", s_trap_test_data_read_addr); s_trap_test_data_read = *(uint32_t *)s_trap_test_data_read_addr; } else if(os_strcmp(argv[3], "mpuprotect") == 0) { s_trap_test_data_read_addr = 0; CLI_LOGI("data read mpuprotect addr=0x%x\r\n", s_trap_test_data_read_addr); s_trap_test_data_read = *(uint32_t *)s_trap_test_data_read_addr; } CLI_LOGI("data read addr=0x%x,value=0x%x\r\n", s_trap_test_data_read_addr, s_trap_test_data_read); } else if(os_strcmp(argv[2], "write") == 0) { if(argc < 4) goto bk_err_help; if(os_strcmp(argv[3], "invalid") == 0) { s_trap_test_data_write_addr = 0xC0000000; CLI_LOGI("data write invalid addr=0x%x\r\n", s_trap_test_data_write_addr); *(uint32_t *)s_trap_test_data_write_addr = 0xC0000000; } else if(os_strcmp(argv[3], "align") == 0) { s_trap_test_data_write_addr = 0x2809FFFE; CLI_LOGI("data write align addr=0x%x\r\n", s_trap_test_data_write_addr); *(uint32_t *)s_trap_test_data_write_addr = 0x2809FFFE; } else if(os_strcmp(argv[3], "zero") == 0) { s_trap_test_data_write_addr = 0; CLI_LOGI("data write zero addr=0x%x\r\n", s_trap_test_data_write_addr); *(uint32_t *)s_trap_test_data_write_addr = 0; } else if(os_strcmp(argv[3], "nonsecure") == 0) { s_trap_test_data_write_addr = 0; CLI_LOGI("data write nonsecure addr=0x%x\r\n", s_trap_test_data_write_addr); *(uint32_t *)s_trap_test_data_write_addr = 0; } else if(os_strcmp(argv[3], "mpuprotect") == 0) { s_trap_test_data_write_addr = 0; CLI_LOGI("data write mpuprotect addr=0x%x\r\n", s_trap_test_data_write_addr); *(uint32_t *)s_trap_test_data_write_addr = 0; } CLI_LOGI("data write addr=0x%x,value=0x%x\r\n", s_trap_test_data_write_addr, s_trap_test_data_write); } } else if (os_strcmp(argv[1], "instruction") == 0) { if(argc < 3) goto bk_err_help; if(os_strcmp(argv[3], "zero") == 0) { test_instruction_fun = (void (*)())0x00000000; CLI_LOGI("instruction zero \r\n"); test_instruction_fun(); } else if (os_strcmp(argv[3], "invalid_addr") == 0) { test_instruction_fun = (void (*)())0xffffff00; CLI_LOGI("instruction invalid_addr \r\n"); test_instruction_fun(); } else if (os_strcmp(argv[3], "invalid_instruction") == 0) { CLI_LOGI("instruction invalid_instruction \r\n"); __asm__ volatile( "UDF #0 \n" ); } else if (os_strcmp(argv[3], "nonsecure") == 0) { test_instruction_fun = (void (*)())0x2035000 ; CLI_LOGI("instruction nonsecure \r\n"); test_instruction_fun(); } } else if (os_strcmp(argv[1], "memory") == 0) { if(argc < 3) goto bk_err_help; //[func_stack|task_stack|hw_stack|global_overwrite|heap_overwrite|heap_free_malloc_overwrite] if(os_strcmp(argv[2], "func_stack_overwrite") == 0) { char array_1[TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE]; char array_2[TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE]; memset(array_1, 0, sizeof(array_1)); memset(array_2, 0, sizeof(array_2)); extern int bk_rand(void); func_stack_test(array_1, array_2, (uint32_t)(bk_rand()*99)%(TRAP_TEST_FUNC_STACK_OVERFLOW_SIZE*8)); //the stack variable value is over-writed by func_stack_test if((array_1[0] != 0) || (array_2[0] != 0)) BK_ASSERT(0); } else if(os_strcmp(argv[2], "task_stack_overwrite") == 0) { extern uint32_t vTaskStackSize(); extern uint32_t * vTaskStackAddr(); //uint32_t stack_size = vTaskStackSize() * sizeof( StackType_t ); uint32_t *p_task_stack = vTaskStackAddr(); //stack start addr #if 1 //( portSTACK_GROWTH < 0 ) //TODO:portSTACK_GROWTH isn't valid in this file. strcpy((char *)(p_task_stack), "task_stack_overwrite"); #else strcpy((char *)(p_task_stack+vTaskStackSize()-1), "task_stack_overwrite"); #endif } else if(os_strcmp(argv[2], "hw_stack_overwrite") == 0) { rtos_delay_milliseconds(1000); //wait log out { CLI_LOGI("psplimit val =0x%x\r\n", __get_PSPLIM()); CLI_LOGI("SP val =0x%x\r\n", __get_SP()); CLI_LOGI("PSP val =0x%x\r\n", __get_PSP()); uint32_t sp = __get_PSPLIM(); /* set the stack pointer value less than the psplimit value */ sp = sp - 0x4; __set_PSP(sp); __asm__ volatile("bx lr"); } CLI_LOGI("hw_stack test pass\r\n"); } else if(os_strcmp(argv[2], "global_overwrite") == 0) { s_trap_test_data_read = 0x5A5A5A5A; s_trap_test_data_read_addr = (uint32_t)&s_trap_test_data_read; *(uint32_t *)s_trap_test_data_read_addr = 0xCDCDCDCD; //valid init value dwt_set_data_address_write((uint32_t)&s_trap_test_data_read); //valid set value dwt_disable_debug_monitor_mode(); *(uint32_t *)s_trap_test_data_read_addr = 0xAAAABBBB; //valid set value //invlaid set value dwt_set_data_address_write((uint32_t)&s_trap_test_data_read); *(uint32_t *)s_trap_test_data_read_addr = 0x88888888; //invalid set value, monitor will crash } else if(os_strcmp(argv[2], "heap_overwrite") == 0) { s_trap_test_data_write_addr = (uint32_t)os_malloc(4); //*(uint32_t *)(s_trap_test_data_write_addr + 4) = 0x88888888; os_memset((uint32_t *)s_trap_test_data_write_addr, 0x88, 16); os_free((void *)s_trap_test_data_write_addr); } else if(os_strcmp(argv[2], "heap_free_malloc_overwrite") == 0) { s_trap_test_data_write_addr = (uint32_t)os_malloc(128); os_free((void *)s_trap_test_data_write_addr); char *tmp_p = os_malloc(128); os_memset(tmp_p, 0, 128); strcpy(tmp_p, "heap_free_malloc_overwrite"); os_memset((uint32_t *)s_trap_test_data_write_addr, 0x31, 128); if(strcmp(tmp_p, "heap_free_malloc_overwrite") != 0) BK_ASSERT(0); } }else { s_trap_test_instruction_ptr(); return; } bk_err_help: cli_trap_test_help(); } #define TRAP_TEST_CMD_CNT (sizeof(s_trap_test_commands) / sizeof(struct cli_command)) static const struct cli_command s_trap_test_commands[] = { {"trap_test", NULL, trap_test}, }; int cli_trap_test_init(void) { return cli_register_commands(s_trap_test_commands, TRAP_TEST_CMD_CNT); }