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