blob: 470ea79e6321ee71c16d37611afd969f36306e16 [file] [log] [blame]
dhendrix@google.com17bee8a2010-06-15 01:41:24 +00001/*
davidhendricks@gmail.comffdc0932012-02-27 23:46:44 +00002 * Copyright 2012, Google Inc.
3 * All rights reserved.
dhendrix@google.com17bee8a2010-06-15 01:41:24 +00004 *
davidhendricks@gmail.comffdc0932012-02-27 23:46:44 +00005 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
dhendrix@google.com17bee8a2010-06-15 01:41:24 +00008 *
davidhendricks@gmail.comffdc0932012-02-27 23:46:44 +00009 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
dhendrix@google.com17bee8a2010-06-15 01:41:24 +000018 *
davidhendricks@gmail.comffdc0932012-02-27 23:46:44 +000019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dhendrix@google.com17bee8a2010-06-15 01:41:24 +000030 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <inttypes.h>
35#include <unistd.h>
36#include <string.h>
37#include <errno.h>
38
39#include "mosys/alloc.h"
40#include "mosys/big_lock.h"
41#include "mosys/command_list.h"
42#include "mosys/globals.h"
43#include "mosys/kv_pair.h"
44#include "mosys/log.h"
45#include "mosys/output.h"
46#include "mosys/platform.h"
47
48static void usage(void)
49{
50 printf("usage: %s [options] [commands]\n"
51 "\n"
52 " Options:\n"
53 " -k print data in key=value format\n"
54 " -l print data in long format\n"
55 " -v verbose (can be used multiple times)\n"
56 " -f ignore mosys lock\n"
57 " -t display command tree\n"
58 " -s print supported platform IDs\n"
59 " -p [id] force platform id (bypass auto-detection)\n"
60 " -h print this help\n"
61 " -V print version\n"
62 "\n", PROGRAM);
63}
64
65static void sub_list(struct platform_cmd *sub)
66{
67 struct platform_cmd *_sub;
68
69 if (!sub)
70 return;
71
72 printf(" Commands:\n");
73 for (_sub = sub->arg.sub; _sub && _sub->name; _sub++) {
74 if (_sub->desc)
75 printf(" %-12s %s\n", _sub->name, _sub->desc);
76 }
77 printf("\n");
78}
79
80static int sub_main(struct platform_intf *intf,
81 struct platform_cmd *sub, int argc, char **argv)
82{
83 struct platform_cmd *cmd;
84
85 if (!intf || !sub)
86 return -1;
87
88 switch (sub->type) {
89 case ARG_TYPE_GETTER:
90 case ARG_TYPE_SETTER:
91 if (!sub->arg.func) {
92 lprintf(LOG_ERR, "Undefined Function\n");
93 return -1;
94 }
95
96 /* this is a function, it might have more args */
97 if (argc > 0 && strcmp(argv[0], "help") == 0) {
98 platform_cmd_usage(sub);
99 return 0;
100 }
101
102 /* run command handler */
103 return sub->arg.func(intf, sub, argc, argv);
104
105 case ARG_TYPE_SUB:
106 if (argc == 0) {
107 sub_list(sub);
108 return -1;
109 }
110
111 /* this is a sub-command, we must have some more args */
112 if (argc == 0 || strcmp(argv[0], "help") == 0) {
113 sub_list(sub);
114 return 0;
115 }
116
117 /* search for matching sub-command */
118 for (cmd = sub->arg.sub; cmd && cmd->name; cmd++) {
119 if (strlen(cmd->name) != strlen(argv[0]))
120 continue;
121 if (strcmp(cmd->name, argv[0]) == 0) {
122 lprintf(LOG_DEBUG, "Subcommand %s (%s)\n",
123 cmd->name, cmd->desc);
124 return sub_main(intf, cmd, argc - 1,
125 &(argv[1]));
126 }
127 }
128 break;
129
130 default:
131 lprintf(LOG_ERR, "Unknown subcommand type\n");
132 return -1;
133 }
134
135 lprintf(LOG_WARNING, "Command not found\n\n");
136 sub_list(sub);
137
138 return -1;
139}
140
141static int intf_main(struct platform_intf *intf, int argc, char **argv)
142{
143 struct platform_cmd **_sub, *sub;
144 int do_list = 0;
145 int ret = 0;
146
147 if (!intf || !intf->sub) {
148 lprintf(LOG_ERR, "No commands defined for this platform\n");
149 return -1;
150 }
151
152 if (argc == 0)
153 ret = -1;
154
155 if (argc == 0 || strcmp(argv[0], "help") == 0) {
156 do_list = 1;
157 usage();
158 printf(" Commands:\n");
159 }
160
161 /* go through subcommand list for this interface */
162 for (_sub = intf->sub; _sub && *_sub; _sub++) {
163
164 sub = *_sub;
165 if (do_list) {
166 /*FIXME: if the intf had a main sub, call sub_list */
167 printf(" %-12s %s\n", sub->name, sub->desc);
168 continue;
169 }
170
171 lprintf(LOG_DEBUG, "Command: %s (%s)\n", sub->name, argv[0]);
172
173 /* is this sub-command is the one they asked for? */
174 if (strlen(sub->name) != strlen(argv[0]))
175 continue;
176 if (strcmp(sub->name, argv[0]) == 0) {
177 lprintf(LOG_DEBUG, "Found command %s (%s)\n",
178 sub->name, sub->desc);
179 return sub_main(intf, sub, argc - 1, &(argv[1]));
180 }
181 }
182
183 if (do_list) {
184 printf("\n");
185 return ret;
186 }
187
188 lprintf(LOG_WARNING, "Command not found\n\n");
189 return intf_main(intf, 0, NULL); /* trigger a help listing */
190}
191
192#define LOCK_TIMEOUT_SECS 10
193
194int mosys_main(int argc, char **argv)
195{
196 int rc;
197 int argflag;
198 int verbose = 0;
199 int force_lock = 0;
200 int s_opt = 0;
201 int showtree = 0;
202 char *p_opt = NULL;
203 struct platform_intf *intf;
204 enum kv_pair_style style = KV_STYLE_VALUE;
205
206 while ((argflag = getopt(argc, argv, "klvftsp:Vh")) > 0) {
207 switch (argflag) {
208 case 'k':
209 style = KV_STYLE_PAIR;
210 break;
211 case 'l':
212 style = KV_STYLE_LONG;
213 break;
214 case 'v':
215 verbose++;
216 break;
217 case 'f':
218 force_lock = 1;
219 break;
220 case 't':
221 showtree = 1;
222 break;
223 case 's':
224 s_opt = 1;
225 break;
226 case 'p':
dhendrix@google.com74d43892011-01-05 21:52:48 +0000227 p_opt = optarg;
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000228 break;
229 case 'V':
230 printf("mosys version %s\n", VERSION);
231 exit(EXIT_SUCCESS);
232 case 'h':
233 usage();
234 exit(EXIT_SUCCESS);
235 default:
236 usage();
237 exit(EXIT_FAILURE);
238 }
239 }
240
241 mosys_set_kv_pair_style(style);
242 if (s_opt) {
243 print_platforms();
244 exit(EXIT_SUCCESS);
245 }
246
247 /*
248 * Init the logging system and the default log output file (stderr).
dhendrix@google.com6e8af7f2010-09-13 23:10:10 +0000249 * Anything logged with a level above CONFIG_LOGLEVEL will not be logged
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000250 * at all. We use the number of "-v" arguments on the commandline as
251 * a bias against the default threshold. The more times you use
dhendrix@google.com6e8af7f2010-09-13 23:10:10 +0000252 * "-v", the greater your logging level becomes, and the more
253 * information will be printed.
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000254 */
255 mosys_log_init(PROGRAM, CONFIG_LOGLEVEL+verbose, NULL);
256
david.hendricks@gmail.comb87d94c2011-04-04 03:22:49 +0000257#if defined(CONFIG_USE_IPC_LOCK)
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000258 /* try to get lock */
259 if (!force_lock && (mosys_acquire_big_lock(LOCK_TIMEOUT_SECS) < 0)) {
260 rc = -1;
261 goto do_exit_1;
262 }
david.hendricks@gmail.comb87d94c2011-04-04 03:22:49 +0000263#endif
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000264
265 /* set the global verbosity level */
dhendrix@google.comd46a2322010-09-13 23:11:06 +0000266 mosys_set_verbosity(CONFIG_LOGLEVEL+verbose);
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000267
268 /* try to identify the platform */
269 intf = mosys_platform_setup(p_opt);
270 if (!intf) {
271 lprintf(LOG_ERR, "Platform not supported\n");
272 rc = -1;
273 goto do_exit_2;
274 }
275 lprintf(LOG_DEBUG, "Platform: %s\n", intf->name);
276
277 if (showtree) {
278 print_tree(intf);
279 rc = 0;
280 goto do_exit_3;
281 }
282
283 /* FIXME: debug print */
284 /* run command */
285 rc = intf_main(intf, argc - optind, &(argv[optind]));
286 if (rc == -ENOSYS)
287 lprintf(LOG_ERR, "Command not supported on this platform\n");
288
289 /* clean up */
290do_exit_3:
291 mosys_platform_destroy(intf);
292do_exit_2:
david.hendricks@gmail.comb87d94c2011-04-04 03:22:49 +0000293#if defined(CONFIG_USE_IPC_LOCK)
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000294 mosys_release_big_lock();
david.hendricks@gmail.comb87d94c2011-04-04 03:22:49 +0000295#endif
dhendrix@google.com17bee8a2010-06-15 01:41:24 +0000296do_exit_1:
297 mosys_log_halt();
298
299 if (rc < 0)
300 exit(EXIT_FAILURE);
301 else
302 exit(EXIT_SUCCESS);
303}
304
305int main(int argc, char **argv)
306{
307 mosys_globals_init();
308 return mosys_main(argc, argv);
309}