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