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

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

Fix pointers output format.
Fix format of slab and zones tables.

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