Subversion Repositories HelenOS

Rev

Rev 1224 | Rev 1474 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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