1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2011 The Chromium OS Authors. 4 */ 5 6 #include <common.h> 7 #include <command.h> 8 #include <mapmem.h> 9 #include <trace.h> 10 #include <asm/io.h> 11 12 static int get_args(int argc, char * const argv[], char **buff, 13 size_t *buff_ptr, size_t *buff_size) 14 { 15 if (argc < 2) 16 return -1; 17 if (argc < 4) { 18 *buff_size = env_get_ulong("profsize", 16, 0); 19 *buff = map_sysmem(env_get_ulong("profbase", 16, 0), 20 *buff_size); 21 *buff_ptr = env_get_ulong("profoffset", 16, 0); 22 } else { 23 *buff_size = simple_strtoul(argv[3], NULL, 16); 24 *buff = map_sysmem(simple_strtoul(argv[2], NULL, 16), 25 *buff_size); 26 *buff_ptr = 0; 27 }; 28 return 0; 29 } 30 31 static int create_func_list(int argc, char * const argv[]) 32 { 33 size_t buff_size, avail, buff_ptr, used; 34 unsigned int needed; 35 char *buff; 36 int err; 37 38 if (get_args(argc, argv, &buff, &buff_ptr, &buff_size)) 39 return -1; 40 41 avail = buff_size - buff_ptr; 42 err = trace_list_functions(buff + buff_ptr, avail, &needed); 43 if (err) 44 printf("Error: truncated (%#x bytes needed)\n", needed); 45 used = min(avail, (size_t)needed); 46 printf("Function trace dumped to %08lx, size %#zx\n", 47 (ulong)map_to_sysmem(buff + buff_ptr), used); 48 env_set_hex("profbase", map_to_sysmem(buff)); 49 env_set_hex("profsize", buff_size); 50 env_set_hex("profoffset", buff_ptr + used); 51 52 return 0; 53 } 54 55 static int create_call_list(int argc, char * const argv[]) 56 { 57 size_t buff_size, avail, buff_ptr, used; 58 unsigned int needed; 59 char *buff; 60 int err; 61 62 if (get_args(argc, argv, &buff, &buff_ptr, &buff_size)) 63 return -1; 64 65 avail = buff_size - buff_ptr; 66 err = trace_list_calls(buff + buff_ptr, avail, &needed); 67 if (err) 68 printf("Error: truncated (%#x bytes needed)\n", needed); 69 used = min(avail, (size_t)needed); 70 printf("Call list dumped to %08lx, size %#zx\n", 71 (ulong)map_to_sysmem(buff + buff_ptr), used); 72 73 env_set_hex("profbase", map_to_sysmem(buff)); 74 env_set_hex("profsize", buff_size); 75 env_set_hex("profoffset", buff_ptr + used); 76 77 return 0; 78 } 79 80 int do_trace(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 81 { 82 const char *cmd = argc < 2 ? NULL : argv[1]; 83 84 if (!cmd) 85 return cmd_usage(cmdtp); 86 switch (*cmd) { 87 case 'p': 88 trace_set_enabled(0); 89 break; 90 case 'c': 91 if (create_call_list(argc, argv)) 92 return cmd_usage(cmdtp); 93 break; 94 case 'r': 95 trace_set_enabled(1); 96 break; 97 case 'f': 98 if (create_func_list(argc, argv)) 99 return cmd_usage(cmdtp); 100 break; 101 case 's': 102 trace_print_stats(); 103 break; 104 default: 105 return CMD_RET_USAGE; 106 } 107 108 return 0; 109 } 110 111 U_BOOT_CMD( 112 trace, 4, 1, do_trace, 113 "trace utility commands", 114 "stats - display tracing statistics\n" 115 "trace pause - pause tracing\n" 116 "trace resume - resume tracing\n" 117 "trace funclist [<addr> <size>] - dump function list into buffer\n" 118 "trace calls [<addr> <size>] " 119 "- dump function call trace into buffer" 120 ); 121