Add basic support for mini2440 board to barebox.
[barebox-mini2440.git] / commands / menu.c
blobf734db38746840a8a65364cf60d22c580adfdf87
1 /*
2 * (C) Copyright 2009-2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
4 * See file CREDITS for list of people who contributed to this
5 * project.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
23 #include <common.h>
24 #include <command.h>
25 #include <readkey.h>
26 #include <menu.h>
27 #include <getopt.h>
28 #include <errno.h>
29 #include <linux/err.h>
31 typedef enum {
32 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
33 action_add,
34 action_remove,
35 action_select,
36 #endif
37 action_list,
38 action_show,
39 } menu_action;
41 struct cmd_menu {
42 char *menu;
43 menu_action action;
44 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
45 int entry;
46 int re_entrant;
47 char *description;
48 char *command;
49 char *submenu;
50 int num;
51 #endif
54 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
55 #define OPTS "m:earlc:d:RsSn:u:"
56 #define is_entry(x) ((x)->entry)
57 #else
58 #define OPTS "m:ls"
59 #define is_entry(x) (0)
60 #endif
62 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
64 * menu -e -a -m <menu> -c <command> [-R] -d <description>
65 * menu -e -a -m <menu> -u submenu -d <description>
67 static int do_menu_entry_add(struct cmd_menu *cm)
69 struct menu_entry *me;
70 struct menu *m;
72 if (!cm->menu || (!cm->command && !cm->submenu) || !cm->description)
73 return -EINVAL;
75 m = menu_get_by_name(cm->menu);
77 if (!m) {
78 eprintf("Menu '%s' not found\n", cm->menu);
79 return -EINVAL;
82 if (cm->submenu)
83 me = menu_add_submenu(m, cm->submenu, cm->description);
84 else
85 me = menu_add_command_entry(m, cm->description, cm->command);
86 if (!me)
87 return PTR_ERR(me);
89 me->non_re_ent = !cm->re_entrant;
91 return 0;
95 * menu -e -r -m <name> -n <num>
97 static int do_menu_entry_remove(struct cmd_menu *cm)
99 struct menu *m;
100 struct menu_entry *me;
102 if (!cm->menu || cm->num < 0)
103 return -EINVAL;
105 m = menu_get_by_name(cm->menu);
107 if (!m) {
108 eprintf("Menu '%s' not found\n", cm->menu);
109 return -EINVAL;
112 me = menu_entry_get_by_num(m, cm->num);
114 if (!me) {
115 eprintf("Entry '%s' not found\n", cm->num);
116 return -EINVAL;
119 menu_remove_entry(m, me);
121 menu_entry_free(me);
123 return 0;
127 * menu -a -m <name> -d <description>
129 static int do_menu_add(struct cmd_menu *cm)
131 struct menu *m;
132 int ret = -ENOMEM;
134 if (!cm->menu || !cm->description)
135 return -EINVAL;
137 m = menu_alloc();
139 if (!m)
140 goto free;
142 m->name = strdup(cm->menu);
143 if (!m->name)
144 goto free;
146 m->display = strdup(cm->description);
147 if (!m->display)
148 goto free;
150 ret = menu_add(m);
152 if (ret)
153 goto free;
155 return 0;
157 free:
158 eprintf("Menu '%s' add fail", cm->menu);
159 if (ret == -EEXIST)
160 eputs(" already exist");
161 eputs("\n");
163 menu_free(m);
165 return ret;
168 * menu -r -m <name>
170 static int do_menu_remove(struct cmd_menu *cm)
172 struct menu *m;
174 m = menu_get_by_name(cm->menu);
176 if (!m) {
177 eprintf("Menu '%s' not found\n", cm->menu);
178 return -EINVAL;
181 menu_remove(m);
183 menu_free(m);
185 return 0;
189 * menu -m <menu> -S -n <entry num starting at 1>
191 static int do_menu_select(struct cmd_menu *cm)
193 struct menu *m;
195 if (cm->num < 0)
196 return -EINVAL;
198 m = menu_get_by_name(cm->menu);
200 if (!m) {
201 eprintf("Menu '%s' not found\n", cm->menu);
202 return -EINVAL;
205 if (!menu_set_selected(m, cm->num)) {
206 eprintf("Entry '%d' not found\n", cm->num);
207 return -EINVAL;
210 return 0;
212 #endif
215 * menu -s -m <menu>
217 static int do_menu_show(struct cmd_menu *cm)
219 struct menu *m;
221 if (cm->menu)
222 m = menu_get_by_name(cm->menu);
223 else
224 m = menu_get_by_name("boot");
226 return menu_show(m);
229 static void print_entries(struct menu *m)
231 struct menu_entry *me;
233 list_for_each_entry(me, &m->entries, list)
234 printf("%d: %s\n", me->num, me->display);
238 * menu -l
239 * menu -e -l [menu]
241 static int do_menu_list(struct cmd_menu *cm)
243 struct menu* m = NULL;
244 struct menu* menus = menu_get_menus();
246 if (!menus)
247 return 0;
249 if (is_entry(cm)) {
250 if (cm->menu)
251 m = menu_get_by_name(cm->menu);
253 if (m) {
254 print_entries(m);
255 return 0;
259 list_for_each_entry(m, &menus->list, list) {
260 printf("%s: %s\n", m->name, m->display? m->display : m->name);
261 if (is_entry(cm))
262 print_entries(m);
265 return 0;
268 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
269 static int do_menu_entry(struct cmd_menu *cm)
271 switch(cm->action) {
272 case action_list:
273 return do_menu_list(cm);
274 case action_remove:
275 return do_menu_entry_remove(cm);
276 case action_add:
277 return do_menu_entry_add(cm);
278 case action_select:
279 case action_show:
280 break;
282 return -EINVAL;
284 #else
285 static int do_menu_entry(struct cmd_menu *cm)
287 return -EINVAL;
289 #endif
291 static int do_menu(struct command *cmdtp, int argc, char *argv[])
293 struct cmd_menu cm;
294 int opt;
295 int ret = -EINVAL;
297 if (!argc)
298 return COMMAND_ERROR_USAGE;
300 memset(&cm, 0, sizeof(struct cmd_menu));
301 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
302 cm.num = -EINVAL;
303 #endif
305 cm.action = action_show;
307 while((opt = getopt(argc, argv, OPTS)) > 0) {
308 switch(opt) {
309 case 'm':
310 cm.menu = optarg;
311 break;
312 case 'l':
313 cm.action = action_list;
314 break;
315 case 's':
316 cm.action = action_show;
317 break;
318 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
319 case 'e':
320 cm.entry = 1;
321 break;
322 case 'a':
323 cm.action = action_add;
324 break;
325 case 'r':
326 cm.action = action_remove;
327 break;
328 case 'c':
329 cm.command = optarg;
330 break;
331 case 'u':
332 cm.submenu = optarg;
333 break;
334 case 'd':
335 cm.description = optarg;
336 break;
337 case 'R':
338 cm.re_entrant = 1;
339 break;
340 case 'S':
341 cm.action = action_select;
342 break;
343 case 'n':
344 cm.num = simple_strtoul(optarg, NULL, 10);
345 break;
346 #endif
347 default:
348 return 1;
352 if (is_entry(&cm)) {
353 ret = do_menu_entry(&cm);
354 goto end;
357 switch(cm.action) {
358 case action_list:
359 ret = do_menu_list(&cm);
360 break;
361 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
362 case action_remove:
363 ret = do_menu_remove(&cm);
364 break;
365 case action_add:
366 ret = do_menu_add(&cm);
367 break;
368 case action_select:
369 ret = do_menu_select(&cm);
370 break;
371 #endif
372 case action_show:
373 ret = do_menu_show(&cm);
374 break;
377 end:
378 if (ret)
379 return 0;
381 return 1;
384 static const __maybe_unused char cmd_menu_help[] =
385 "Usage: menu [OPTION]... \n"
386 "Manage Menu\n"
387 " -m menu\n"
388 " -l list\n"
389 " -s show\n"
390 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
391 "Advanced\n"
392 " -e menu entry\n"
393 " -a add\n"
394 " -r remove\n"
395 " -S select\n"
396 #endif
397 "\n"
398 "How to\n"
399 "\n"
400 "Show menu\n"
401 " menu -s -m <menu>\n"
402 "\n"
403 "List menu\n"
404 " menu -l\n"
405 "\n"
406 #if defined(CONFIG_CMD_MENU_MANAGEMENT)
407 "Add a menu\n"
408 " menu -a -m <name> -d <description>\n"
409 "\n"
410 "Remove a menu\n"
411 " menu -r -m <name>\n"
412 "\n"
413 "Add an entry\n"
414 " (-R for do no exit the menu after executing the command)\n"
415 " menu -e -a -m <menu> -c <command> [-R] -d <description>\n"
417 "Add a submenu entry\n"
418 " (-R is not needed)\n"
419 " menu -e -a -m <menu> -u <menu> -d <description>\n"
420 "\n"
421 "Remove an entry\n"
422 " menu -e -r -m <name> -n <num>\n"
423 "\n"
424 "Select an entry\n"
425 " menu -m <menu> -S -n <entry num starting at 1>\n"
426 "\n"
427 "List menu\n"
428 " menu -e -l [menu]\n"
429 "\n"
430 "Menu example\n"
431 "menu -a -m boot -d \"Boot Menu\"\n"
432 "menu -e -a -m boot -c boot -d \"Boot\"\n"
433 "menu -e -a -m boot -c reset -d \"Reset\"\n"
434 "menu -s -m boot\n"
435 #else
436 "Menu example\n"
437 "menu -s -m boot\n"
438 #endif
441 BAREBOX_CMD_START(menu)
442 .cmd = do_menu,
443 .usage = "Menu Management",
444 BAREBOX_CMD_HELP(cmd_menu_help)
445 BAREBOX_CMD_END