Subversion Repositories HelenOS

Rev

Rev 1224 | 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
}