source: mainline/generic/src/console/cmd.c@ 41d33ac

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

Added syscall that lets kernel regain access to keyboard.

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