source: mainline/generic/src/console/cmd.c@ b6529ae

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b6529ae was b45c443, checked in by Josef Cejka <malyzelenyhnus@…>, 19 years ago

Kernel doxygen comments updated.

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