]>
Commit | Line | Data |
---|---|---|
cabcbb56 SG |
1 | /* |
2 | * Copyright (c) 2011 The Chromium OS Authors. | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
cabcbb56 SG |
5 | */ |
6 | ||
7 | #include <common.h> | |
8 | #include <command.h> | |
0eb25b61 | 9 | #include <mapmem.h> |
cabcbb56 SG |
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); | |
5eca9779 | 46 | used = min(avail, (size_t)needed); |
cabcbb56 SG |
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); | |
5eca9779 | 70 | used = min(avail, (size_t)needed); |
cabcbb56 SG |
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 | ); |