]>
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> | |
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 = getenv_ulong("profsize", 16, 0); | |
19 | *buff = map_sysmem(getenv_ulong("profbase", 16, 0), | |
20 | *buff_size); | |
21 | *buff_ptr = getenv_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, needed); | |
46 | printf("Function trace dumped to %08lx, size %#zx\n", | |
47 | (ulong)map_to_sysmem(buff + buff_ptr), used); | |
48 | setenv_hex("profbase", map_to_sysmem(buff)); | |
49 | setenv_hex("profsize", buff_size); | |
50 | setenv_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, needed); | |
70 | printf("Call list dumped to %08lx, size %#zx\n", | |
71 | (ulong)map_to_sysmem(buff + buff_ptr), used); | |
72 | ||
73 | setenv_hex("profbase", map_to_sysmem(buff)); | |
74 | setenv_hex("profsize", buff_size); | |
75 | setenv_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 | ); |