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 <env.h> 9#include <mapmem.h> 10#include <trace.h> 11#include <asm/io.h> 12 13static 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 = env_get_ulong("profsize", 16, 0); 20 *buff = map_sysmem(env_get_ulong("profbase", 16, 0), 21 *buff_size); 22 *buff_ptr = env_get_ulong("profoffset", 16, 0); 23 } else { 24 *buff_size = hextoul(argv[3], NULL); 25 *buff = map_sysmem(hextoul(argv[2], NULL), 26 *buff_size); 27 *buff_ptr = 0; 28 }; 29 return 0; 30} 31 32static int create_func_list(int argc, char *const argv[]) 33{ 34 size_t buff_size, avail, buff_ptr, needed, used; 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 (%#zx 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 55static int create_call_list(int argc, char *const argv[]) 56{ 57 size_t buff_size, avail, buff_ptr, needed, used; 58 char *buff; 59 int err; 60 61 if (get_args(argc, argv, &buff, &buff_ptr, &buff_size)) 62 return -1; 63 64 avail = buff_size - buff_ptr; 65 err = trace_list_calls(buff + buff_ptr, avail, &needed); 66 if (err) 67 printf("Error: truncated (%#zx bytes needed)\n", needed); 68 used = min(avail, (size_t)needed); 69 printf("Call list dumped to %08lx, size %#zx\n", 70 (ulong)map_to_sysmem(buff + buff_ptr), used); 71 72 env_set_hex("profbase", map_to_sysmem(buff)); 73 env_set_hex("profsize", buff_size); 74 env_set_hex("profoffset", buff_ptr + used); 75 76 return 0; 77} 78 79int do_trace(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 80{ 81 const char *cmd = argc < 2 ? NULL : argv[1]; 82 83 if (!cmd) 84 return cmd_usage(cmdtp); 85 switch (*cmd) { 86 case 'p': 87 trace_set_enabled(0); 88 break; 89 case 'c': 90 if (create_call_list(argc, argv)) 91 return cmd_usage(cmdtp); 92 break; 93 case 'r': 94 trace_set_enabled(1); 95 break; 96 case 'f': 97 if (create_func_list(argc, argv)) 98 return cmd_usage(cmdtp); 99 break; 100 case 's': 101 trace_print_stats(); 102 break; 103 default: 104 return CMD_RET_USAGE; 105 } 106 107 return 0; 108} 109 110U_BOOT_CMD( 111 trace, 4, 1, do_trace, 112 "trace utility commands", 113 "stats - display tracing statistics\n" 114 "trace pause - pause tracing\n" 115 "trace resume - resume tracing\n" 116 "trace funclist [<addr> <size>] - dump function list into buffer\n" 117 "trace calls [<addr> <size>] " 118 "- dump function call trace into buffer" 119); 120