source: mainline/generic/src/console/cmd.c@ 7509ddc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7509ddc was c4e4507, checked in by Ondrej Palkovsky <ondrap@…>, 19 years ago

Renamed some things in IPC to be consistent.
Added ipc reporting to kconsole.

  • Property mode set to 100644
File size: 16.0 KB
RevLine 
[442d0ae]1/*
2 * Copyright (C) 2005 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - 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 copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
[cf26ba9]30 * @file cmd.c
31 * @brief Kernel console command wrappers.
32 *
[442d0ae]33 * This file is meant to contain all wrapper functions for
34 * all kconsole commands. The point is in separating
35 * kconsole specific wrappers from kconsole-unaware functions
36 * from other subsystems.
37 */
38
39#include <console/cmd.h>
[41d33ac]40#include <console/console.h>
[442d0ae]41#include <console/kconsole.h>
42#include <print.h>
43#include <panic.h>
44#include <typedefs.h>
45#include <arch/types.h>
[5c9a08b]46#include <adt/list.h>
[442d0ae]47#include <arch.h>
48#include <func.h>
49#include <macros.h>
50#include <debug.h>
51#include <symtab.h>
[0132630]52#include <cpu.h>
[442d0ae]53#include <mm/tlb.h>
54#include <arch/mm/tlb.h>
[80bff342]55#include <mm/frame.h>
[0132630]56#include <main/version.h>
[4e147a6]57#include <mm/slab.h>
[10e16a7]58#include <proc/scheduler.h>
[55ab0f1]59#include <proc/thread.h>
[37c57f2]60#include <proc/task.h>
[c4e4507]61#include <ipc/ipc.h>
[442d0ae]62
63/** Data and methods for 'help' command. */
64static int cmd_help(cmd_arg_t *argv);
65static cmd_info_t help_info = {
66 .name = "help",
67 .description = "List of supported commands.",
68 .func = cmd_help,
69 .argc = 0
70};
71
[e07fe0c]72static cmd_info_t exit_info = {
73 .name = "exit",
74 .description ="Exit kconsole",
75 .argc = 0
76};
77
[41d33ac]78static int cmd_continue(cmd_arg_t *argv);
79static cmd_info_t continue_info = {
80 .name = "continue",
81 .description ="Return console back to userspace",
82 .func = cmd_continue,
83 .argc = 0
84};
85
[442d0ae]86/** Data and methods for 'description' command. */
87static int cmd_desc(cmd_arg_t *argv);
88static void desc_help(void);
89static char desc_buf[MAX_CMDLINE+1];
90static cmd_arg_t desc_argv = {
91 .type = ARG_TYPE_STRING,
92 .buffer = desc_buf,
93 .len = sizeof(desc_buf)
94};
95static cmd_info_t desc_info = {
96 .name = "describe",
97 .description = "Describe specified command.",
98 .help = desc_help,
99 .func = cmd_desc,
100 .argc = 1,
101 .argv = &desc_argv
102};
103
104/** Data and methods for 'symaddr' command. */
105static int cmd_symaddr(cmd_arg_t *argv);
106static char symaddr_buf[MAX_CMDLINE+1];
107static cmd_arg_t symaddr_argv = {
108 .type = ARG_TYPE_STRING,
109 .buffer = symaddr_buf,
110 .len = sizeof(symaddr_buf)
111};
112static cmd_info_t symaddr_info = {
113 .name = "symaddr",
114 .description = "Return symbol address.",
115 .func = cmd_symaddr,
116 .argc = 1,
117 .argv = &symaddr_argv
118};
119
[ba276f7]120static char set_buf[MAX_CMDLINE+1];
121static int cmd_set4(cmd_arg_t *argv);
122static cmd_arg_t set4_argv[] = {
123 {
124 .type = ARG_TYPE_STRING,
125 .buffer = set_buf,
126 .len = sizeof(set_buf)
127 },
128 {
129 .type = ARG_TYPE_INT
130 }
131};
132static cmd_info_t set4_info = {
133 .name = "set4",
134 .description = "set <dest_addr> <value> - 4byte version",
135 .func = cmd_set4,
136 .argc = 2,
137 .argv = set4_argv
138};
139
[442d0ae]140/** Data and methods for 'call0' command. */
141static char call0_buf[MAX_CMDLINE+1];
142static char carg1_buf[MAX_CMDLINE+1];
143static char carg2_buf[MAX_CMDLINE+1];
144static char carg3_buf[MAX_CMDLINE+1];
145
146static int cmd_call0(cmd_arg_t *argv);
147static cmd_arg_t call0_argv = {
148 .type = ARG_TYPE_STRING,
149 .buffer = call0_buf,
150 .len = sizeof(call0_buf)
151};
152static cmd_info_t call0_info = {
153 .name = "call0",
154 .description = "call0 <function> -> call function().",
155 .func = cmd_call0,
156 .argc = 1,
157 .argv = &call0_argv
158};
159
160/** Data and methods for 'call1' command. */
161static int cmd_call1(cmd_arg_t *argv);
162static cmd_arg_t call1_argv[] = {
163 {
164 .type = ARG_TYPE_STRING,
165 .buffer = call0_buf,
166 .len = sizeof(call0_buf)
167 },
168 {
169 .type = ARG_TYPE_VAR,
170 .buffer = carg1_buf,
171 .len = sizeof(carg1_buf)
172 }
173};
174static cmd_info_t call1_info = {
175 .name = "call1",
176 .description = "call1 <function> <arg1> -> call function(arg1).",
177 .func = cmd_call1,
178 .argc = 2,
179 .argv = call1_argv
180};
181
182/** Data and methods for 'call2' command. */
183static int cmd_call2(cmd_arg_t *argv);
184static cmd_arg_t call2_argv[] = {
185 {
186 .type = ARG_TYPE_STRING,
187 .buffer = call0_buf,
188 .len = sizeof(call0_buf)
189 },
190 {
191 .type = ARG_TYPE_VAR,
192 .buffer = carg1_buf,
193 .len = sizeof(carg1_buf)
194 },
195 {
196 .type = ARG_TYPE_VAR,
197 .buffer = carg2_buf,
198 .len = sizeof(carg2_buf)
199 }
200};
201static cmd_info_t call2_info = {
202 .name = "call2",
203 .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
204 .func = cmd_call2,
205 .argc = 3,
206 .argv = call2_argv
207};
208
209/** Data and methods for 'call3' command. */
210static int cmd_call3(cmd_arg_t *argv);
211static cmd_arg_t call3_argv[] = {
212 {
213 .type = ARG_TYPE_STRING,
214 .buffer = call0_buf,
215 .len = sizeof(call0_buf)
216 },
217 {
218 .type = ARG_TYPE_VAR,
219 .buffer = carg1_buf,
220 .len = sizeof(carg1_buf)
221 },
222 {
223 .type = ARG_TYPE_VAR,
224 .buffer = carg2_buf,
225 .len = sizeof(carg2_buf)
226 },
227 {
228 .type = ARG_TYPE_VAR,
229 .buffer = carg3_buf,
230 .len = sizeof(carg3_buf)
231 }
232
233};
234static cmd_info_t call3_info = {
235 .name = "call3",
236 .description = "call3 <function> <arg1> <arg2> <arg3> -> call function(arg1,arg2,arg3).",
237 .func = cmd_call3,
238 .argc = 4,
239 .argv = call3_argv
240};
241
242/** Data and methods for 'halt' command. */
243static int cmd_halt(cmd_arg_t *argv);
244static cmd_info_t halt_info = {
245 .name = "halt",
246 .description = "Halt the kernel.",
247 .func = cmd_halt,
248 .argc = 0
249};
250
[0132630]251/** Data and methods for 'tlb' command. */
252static int cmd_tlb(cmd_arg_t *argv);
253cmd_info_t tlb_info = {
254 .name = "tlb",
[442d0ae]255 .description = "Print TLB of current processor.",
256 .help = NULL,
[0132630]257 .func = cmd_tlb,
[442d0ae]258 .argc = 0,
259 .argv = NULL
260};
261
[55ab0f1]262static int cmd_threads(cmd_arg_t *argv);
263static cmd_info_t threads_info = {
264 .name = "threads",
265 .description = "List all threads",
266 .func = cmd_threads,
267 .argc = 0
268};
269
[37c57f2]270static int cmd_tasks(cmd_arg_t *argv);
271static cmd_info_t tasks_info = {
272 .name = "tasks",
273 .description = "List all tasks",
274 .func = cmd_tasks,
275 .argc = 0
276};
277
[80bff342]278
[10e16a7]279static int cmd_sched(cmd_arg_t *argv);
280static cmd_info_t sched_info = {
281 .name = "scheduler",
282 .description = "List all scheduler information",
283 .func = cmd_sched,
284 .argc = 0
285};
286
[4e147a6]287static int cmd_slabs(cmd_arg_t *argv);
288static cmd_info_t slabs_info = {
289 .name = "slabs",
290 .description = "List SLAB caches.",
291 .func = cmd_slabs,
292 .argc = 0
293};
294
[80bff342]295/** Data and methods for 'zones' command */
296static int cmd_zones(cmd_arg_t *argv);
297static cmd_info_t zones_info = {
298 .name = "zones",
299 .description = "List of memory zones.",
300 .func = cmd_zones,
301 .argc = 0
302};
303
[c4e4507]304/** Data and methods for 'ipc_task' command */
305static int cmd_ipc_task(cmd_arg_t *argv);
306static cmd_arg_t ipc_task_argv = {
307 .type = ARG_TYPE_INT,
308};
309static cmd_info_t ipc_task_info = {
310 .name = "ipc_task",
311 .description = "Show memory zone structure.",
312 .func = cmd_ipc_task,
313 .argc = 1,
314 .argv = &ipc_task_argv
315};
316
[80bff342]317/** Data and methods for 'zone' command */
318static int cmd_zone(cmd_arg_t *argv);
319static cmd_arg_t zone_argv = {
320 .type = ARG_TYPE_INT,
321};
322
323static cmd_info_t zone_info = {
324 .name = "zone",
325 .description = "Show memory zone structure.",
326 .func = cmd_zone,
327 .argc = 1,
328 .argv = &zone_argv
329};
330
[0132630]331/** Data and methods for 'cpus' command. */
332static int cmd_cpus(cmd_arg_t *argv);
333cmd_info_t cpus_info = {
334 .name = "cpus",
335 .description = "List all processors.",
336 .help = NULL,
337 .func = cmd_cpus,
338 .argc = 0,
339 .argv = NULL
340};
341
342/** Data and methods for 'version' command. */
343static int cmd_version(cmd_arg_t *argv);
344cmd_info_t version_info = {
345 .name = "version",
346 .description = "Print version information.",
347 .help = NULL,
348 .func = cmd_version,
349 .argc = 0,
350 .argv = NULL
351};
352
[10e16a7]353static cmd_info_t *basic_commands[] = {
354 &call0_info,
355 &call1_info,
356 &call2_info,
357 &call3_info,
[41d33ac]358 &continue_info,
[10e16a7]359 &cpus_info,
360 &desc_info,
361 &exit_info,
362 &halt_info,
363 &help_info,
[c4e4507]364 &ipc_task_info,
[10e16a7]365 &set4_info,
366 &slabs_info,
367 &symaddr_info,
368 &sched_info,
[55ab0f1]369 &threads_info,
[37c57f2]370 &tasks_info,
[10e16a7]371 &tlb_info,
372 &version_info,
373 &zones_info,
374 &zone_info,
375 NULL
376};
[80bff342]377
378
[442d0ae]379/** Initialize command info structure.
380 *
381 * @param cmd Command info structure.
382 *
383 */
384void cmd_initialize(cmd_info_t *cmd)
385{
386 spinlock_initialize(&cmd->lock, "cmd");
387 link_initialize(&cmd->link);
388}
389
390/** Initialize and register commands. */
391void cmd_init(void)
392{
[10e16a7]393 int i;
[80bff342]394
[10e16a7]395 for (i=0;basic_commands[i]; i++) {
396 cmd_initialize(basic_commands[i]);
397 if (!cmd_register(basic_commands[i]))
398 panic("could not register command %s\n",
399 basic_commands[i]->name);
400 }
[442d0ae]401}
402
403
404/** List supported commands.
405 *
406 * @param argv Argument vector.
407 *
408 * @return 0 on failure, 1 on success.
409 */
410int cmd_help(cmd_arg_t *argv)
411{
412 link_t *cur;
413
414 spinlock_lock(&cmd_lock);
415
416 for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
417 cmd_info_t *hlp;
418
419 hlp = list_get_instance(cur, cmd_info_t, link);
420 spinlock_lock(&hlp->lock);
421
422 printf("%s - %s\n", hlp->name, hlp->description);
423
424 spinlock_unlock(&hlp->lock);
425 }
426
427 spinlock_unlock(&cmd_lock);
428
429 return 1;
430}
431
432/** Describe specified command.
433 *
434 * @param argv Argument vector.
435 *
436 * @return 0 on failure, 1 on success.
437 */
438int cmd_desc(cmd_arg_t *argv)
439{
440 link_t *cur;
441
442 spinlock_lock(&cmd_lock);
443
444 for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
445 cmd_info_t *hlp;
446
447 hlp = list_get_instance(cur, cmd_info_t, link);
448 spinlock_lock(&hlp->lock);
449
450 if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
451 printf("%s - %s\n", hlp->name, hlp->description);
452 if (hlp->help)
453 hlp->help();
454 spinlock_unlock(&hlp->lock);
455 break;
456 }
457
458 spinlock_unlock(&hlp->lock);
459 }
460
461 spinlock_unlock(&cmd_lock);
462
463 return 1;
464}
465
466/** Search symbol table */
467int cmd_symaddr(cmd_arg_t *argv)
468{
469 symtab_print_search(argv->buffer);
470
471 return 1;
472}
473
474/** Call function with zero parameters */
475int cmd_call0(cmd_arg_t *argv)
476{
477 __address symaddr;
478 char *symbol;
479 __native (*f)(void);
480
481 symaddr = get_symbol_addr(argv->buffer);
482 if (!symaddr)
483 printf("Symbol %s not found.\n", argv->buffer);
484 else if (symaddr == (__address) -1) {
485 symtab_print_search(argv->buffer);
486 printf("Duplicate symbol, be more specific.\n");
487 } else {
488 symbol = get_symtab_entry(symaddr);
[ad45bde9]489 printf("Calling f(): %.*p: %s\n", sizeof(__address) * 2, symaddr, symbol);
[442d0ae]490 f = (__native (*)(void)) symaddr;
[ad45bde9]491 printf("Result: %#zx\n", f());
[442d0ae]492 }
493
494 return 1;
495}
496
497/** Call function with one parameter */
498int cmd_call1(cmd_arg_t *argv)
499{
500 __address symaddr;
501 char *symbol;
[10e16a7]502 __native (*f)(__native,...);
[442d0ae]503 __native arg1 = argv[1].intval;
504
505 symaddr = get_symbol_addr(argv->buffer);
506 if (!symaddr)
507 printf("Symbol %s not found.\n", argv->buffer);
508 else if (symaddr == (__address) -1) {
509 symtab_print_search(argv->buffer);
510 printf("Duplicate symbol, be more specific.\n");
511 } else {
512 symbol = get_symtab_entry(symaddr);
[ad45bde9]513 printf("Calling f(0x%zX): %.*p: %s\n", arg1, sizeof(__address) * 2, symaddr, symbol);
[10e16a7]514 f = (__native (*)(__native,...)) symaddr;
[ad45bde9]515 printf("Result: %#zx\n", f(arg1));
[442d0ae]516 }
517
518 return 1;
519}
520
521/** Call function with two parameters */
522int cmd_call2(cmd_arg_t *argv)
523{
524 __address symaddr;
525 char *symbol;
[10e16a7]526 __native (*f)(__native,__native,...);
[442d0ae]527 __native arg1 = argv[1].intval;
528 __native arg2 = argv[2].intval;
529
530 symaddr = get_symbol_addr(argv->buffer);
531 if (!symaddr)
532 printf("Symbol %s not found.\n", argv->buffer);
533 else if (symaddr == (__address) -1) {
534 symtab_print_search(argv->buffer);
535 printf("Duplicate symbol, be more specific.\n");
536 } else {
537 symbol = get_symtab_entry(symaddr);
[ad45bde9]538 printf("Calling f(0x%zx,0x%zx): %.*p: %s\n",
539 arg1, arg2, sizeof(__address) * 2, symaddr, symbol);
[10e16a7]540 f = (__native (*)(__native,__native,...)) symaddr;
[ad45bde9]541 printf("Result: %#zx\n", f(arg1, arg2));
[442d0ae]542 }
543
544 return 1;
545}
546
547/** Call function with three parameters */
548int cmd_call3(cmd_arg_t *argv)
549{
550 __address symaddr;
551 char *symbol;
[10e16a7]552 __native (*f)(__native,__native,__native,...);
[442d0ae]553 __native arg1 = argv[1].intval;
554 __native arg2 = argv[2].intval;
555 __native arg3 = argv[3].intval;
556
557 symaddr = get_symbol_addr(argv->buffer);
558 if (!symaddr)
559 printf("Symbol %s not found.\n", argv->buffer);
560 else if (symaddr == (__address) -1) {
561 symtab_print_search(argv->buffer);
562 printf("Duplicate symbol, be more specific.\n");
563 } else {
564 symbol = get_symtab_entry(symaddr);
[ad45bde9]565 printf("Calling f(0x%zx,0x%zx, 0x%zx): %.*p: %s\n",
566 arg1, arg2, arg3, sizeof(__address) * 2, symaddr, symbol);
[10e16a7]567 f = (__native (*)(__native,__native,__native,...)) symaddr;
[ad45bde9]568 printf("Result: %#zx\n", f(arg1, arg2, arg3));
[442d0ae]569 }
570
571 return 1;
572}
573
574
575/** Print detailed description of 'describe' command. */
576void desc_help(void)
577{
578 printf("Syntax: describe command_name\n");
579}
580
581/** Halt the kernel.
582 *
583 * @param argv Argument vector (ignored).
584 *
585 * @return 0 on failure, 1 on success (never returns).
586 */
587int cmd_halt(cmd_arg_t *argv)
588{
589 halt();
590 return 1;
591}
592
593/** Command for printing TLB contents.
594 *
595 * @param argv Not used.
596 *
597 * @return Always returns 1.
598 */
[0132630]599int cmd_tlb(cmd_arg_t *argv)
[442d0ae]600{
601 tlb_print();
602 return 1;
603}
[ba276f7]604
605/** Write 4 byte value to address */
606int cmd_set4(cmd_arg_t *argv)
607{
608 __u32 *addr ;
609 __u32 arg1 = argv[1].intval;
610 bool pointer = false;
611
612 if (((char *)argv->buffer)[0] == '*') {
613 addr = (__u32 *) get_symbol_addr(argv->buffer+1);
614 pointer = true;
615 } else if (((char *)argv->buffer)[0] >= '0' &&
616 ((char *)argv->buffer)[0] <= '9')
617 addr = (__u32 *)atoi((char *)argv->buffer);
618 else
619 addr = (__u32 *)get_symbol_addr(argv->buffer);
620
621 if (!addr)
622 printf("Symbol %s not found.\n", argv->buffer);
623 else if (addr == (__u32 *) -1) {
624 symtab_print_search(argv->buffer);
625 printf("Duplicate symbol, be more specific.\n");
626 } else {
627 if (pointer)
[ebbdb8f]628 addr = (__u32 *)(*(__native *)addr);
[ad45bde9]629 printf("Writing 0x%x -> %.*p\n", arg1, sizeof(__address) * 2, addr);
[ba276f7]630 *addr = arg1;
631
632 }
633
634 return 1;
635}
[80bff342]636
[4e147a6]637/** Command for listings SLAB caches
638 *
639 * @param argv Ignores
640 *
641 * @return Always 1
642 */
643int cmd_slabs(cmd_arg_t * argv) {
644 slab_print_list();
645 return 1;
646}
647
[55ab0f1]648
649/** Command for listings Thread information
650 *
651 * @param argv Ignores
652 *
653 * @return Always 1
654 */
655int cmd_threads(cmd_arg_t * argv) {
656 thread_print_list();
657 return 1;
658}
659
[37c57f2]660/** Command for listings Task information
661 *
662 * @param argv Ignores
663 *
664 * @return Always 1
665 */
666int cmd_tasks(cmd_arg_t * argv) {
667 task_print_list();
668 return 1;
669}
670
[10e16a7]671/** Command for listings Thread information
672 *
673 * @param argv Ignores
674 *
675 * @return Always 1
676 */
677int cmd_sched(cmd_arg_t * argv) {
678 sched_print_list();
679 return 1;
680}
681
[96cacc1]682/** Command for listing memory zones
683 *
684 * @param argv Ignored
685 *
686 * return Always 1
687 */
[80bff342]688int cmd_zones(cmd_arg_t * argv) {
[dfd9186]689 zone_print_list();
[80bff342]690 return 1;
691}
[0132630]692
[96cacc1]693/** Command for memory zone details
694 *
695 * @param argv Integer argument from cmdline expected
696 *
697 * return Always 1
698 */
[80bff342]699int cmd_zone(cmd_arg_t * argv) {
[dfd9186]700 zone_print_one(argv[0].intval);
[80bff342]701 return 1;
702}
703
[c4e4507]704/** Command for printing task ipc details
705 *
706 * @param argv Integer argument from cmdline expected
707 *
708 * return Always 1
709 */
710int cmd_ipc_task(cmd_arg_t * argv) {
711 ipc_print_task(argv[0].intval);
712 return 1;
713}
714
715
[0132630]716/** Command for listing processors.
717 *
718 * @param argv Ignored.
719 *
720 * return Always 1.
721 */
722int cmd_cpus(cmd_arg_t *argv)
723{
724 cpu_list();
725 return 1;
726}
727
728/** Command for printing kernel version.
729 *
730 * @param argv Ignored.
731 *
732 * return Always 1.
733 */
734int cmd_version(cmd_arg_t *argv)
735{
736 version_print();
737 return 1;
738}
[41d33ac]739
740/** Command for returning console back to userspace.
741 *
742 * @param argv Ignored.
743 *
744 * return Always 1.
745 */
746int cmd_continue(cmd_arg_t *argv)
747{
748 arch_release_console();
749 return 1;
750}
Note: See TracBrowser for help on using the repository browser.