Subversion Repositories HelenOS

Rev

Rev 579 | Rev 585 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 579 Rev 582
1
/*
1
/*
2
 * Copyright (C) 2005 Jakub Jermar
2
 * Copyright (C) 2005 Jakub Jermar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
#include <console/kconsole.h>
29
#include <console/kconsole.h>
30
#include <console/console.h>
30
#include <console/console.h>
31
#include <console/chardev.h>
31
#include <console/chardev.h>
32
#include <print.h>
32
#include <print.h>
33
#include <panic.h>
33
#include <panic.h>
34
#include <typedefs.h>
34
#include <typedefs.h>
35
#include <arch/types.h>
35
#include <arch/types.h>
36
#include <list.h>
36
#include <list.h>
37
#include <arch.h>
37
#include <arch.h>
38
#include <func.h>
38
#include <func.h>
39
#include <macros.h>
39
#include <macros.h>
40
#include <debug.h>
40
#include <debug.h>
-
 
41
#include <symtab.h>
41
 
42
 
42
#define MAX_CMDLINE 256
43
#define MAX_CMDLINE 256
43
 
44
 
44
/** Simple kernel console.
45
/** Simple kernel console.
45
 *
46
 *
46
 * The console is realized by kernel thread kconsole.
47
 * The console is realized by kernel thread kconsole.
47
 * It doesn't understand any useful command on its own,
48
 * It doesn't understand any useful command on its own,
48
 * but makes it possible for other kernel subsystems to
49
 * but makes it possible for other kernel subsystems to
49
 * register their own commands.
50
 * register their own commands.
50
 */
51
 */
51
 
52
 
52
/** Locking.
53
/** Locking.
53
 *
54
 *
54
 * There is a list of cmd_info_t structures. This list
55
 * There is a list of cmd_info_t structures. This list
55
 * is protected by cmd_lock spinlock. Note that specially
56
 * is protected by cmd_lock spinlock. Note that specially
56
 * the link elements of cmd_info_t are protected by
57
 * the link elements of cmd_info_t are protected by
57
 * this lock.
58
 * this lock.
58
 *
59
 *
59
 * Each cmd_info_t also has its own lock, which protects
60
 * Each cmd_info_t also has its own lock, which protects
60
 * all elements thereof except the link element.
61
 * all elements thereof except the link element.
61
 *
62
 *
62
 * cmd_lock must be acquired before any cmd_info lock.
63
 * cmd_lock must be acquired before any cmd_info lock.
63
 * When locking two cmd info structures, structure with
64
 * When locking two cmd info structures, structure with
64
 * lower address must be locked first.
65
 * lower address must be locked first.
65
 */
66
 */
66
 
67
 
67
spinlock_t cmd_lock;    /**< Lock protecting command list. */
68
spinlock_t cmd_lock;    /**< Lock protecting command list. */
68
link_t cmd_head;    /**< Command list. */
69
link_t cmd_head;    /**< Command list. */
69
 
70
 
70
static cmd_info_t *parse_cmdline(char *cmdline, size_t len);
71
static cmd_info_t *parse_cmdline(char *cmdline, size_t len);
71
static bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end);
72
static bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end);
72
 
73
 
73
/** Data and methods for 'help' command. */
74
/** Data and methods for 'help' command. */
74
static int cmd_help(cmd_arg_t *argv);
75
static int cmd_help(cmd_arg_t *argv);
75
static cmd_info_t help_info;
76
static cmd_info_t help_info = {
-
 
77
    .name = "help",
-
 
78
    .description = "List of supported commands.",
-
 
79
    .func = cmd_help,
-
 
80
    .argc = 0
-
 
81
};
76
 
82
 
77
/** Data and methods for 'description' command. */
83
/** Data and methods for 'description' command. */
78
static int cmd_desc(cmd_arg_t *argv);
84
static int cmd_desc(cmd_arg_t *argv);
79
static void desc_help(void);
85
static void desc_help(void);
80
static cmd_info_t desc_info;
-
 
81
static char desc_buf[MAX_CMDLINE+1];
86
static char desc_buf[MAX_CMDLINE+1];
82
static cmd_arg_t desc_argv = {
87
static cmd_arg_t desc_argv = {
83
    .type = ARG_TYPE_STRING,
88
    .type = ARG_TYPE_STRING,
84
    .buffer = desc_buf,
89
    .buffer = desc_buf,
85
    .len = sizeof(desc_buf)
90
    .len = sizeof(desc_buf)
86
};
91
};
-
 
92
static cmd_info_t desc_info = {
-
 
93
    .name = "describe",
-
 
94
    .description = "Describe specified command.",
-
 
95
    .help = desc_help,
-
 
96
    .func = cmd_desc,
-
 
97
    .argc = 1,
-
 
98
    .argv = &desc_argv
-
 
99
};
-
 
100
 
-
 
101
/** Data and methods for 'symaddr' command. */
-
 
102
static int cmd_symaddr(cmd_arg_t *argv);
-
 
103
static char symaddr_buf[MAX_CMDLINE+1];
-
 
104
static cmd_arg_t symaddr_argv = {
-
 
105
    .type = ARG_TYPE_STRING,
-
 
106
    .buffer = symaddr_buf,
-
 
107
    .len = sizeof(symaddr_buf)
-
 
108
};
-
 
109
static cmd_info_t symaddr_info = {
-
 
110
    .name = "symaddr",
-
 
111
    .description = "Return symbol address.",
-
 
112
    .func = cmd_symaddr,
-
 
113
    .argc = 1,
-
 
114
    .argv = &symaddr_argv
-
 
115
};
-
 
116
 
-
 
117
/** Call0 - call function with no parameters */
-
 
118
static char call0_buf[MAX_CMDLINE+1];
-
 
119
 
-
 
120
static int cmd_call0(cmd_arg_t *argv);
-
 
121
static cmd_arg_t call0_argv = {
-
 
122
    .type = ARG_TYPE_STRING,
-
 
123
    .buffer = call0_buf,
-
 
124
    .len = sizeof(call0_buf)
-
 
125
};
-
 
126
static cmd_info_t call0_info = {
-
 
127
    .name = "call0",
-
 
128
    .description = "call0 <function> -> call function().",
-
 
129
    .func = cmd_call0,
-
 
130
    .argc = 1,
-
 
131
    .argv = &call0_argv
-
 
132
};
-
 
133
 
-
 
134
static int cmd_call1(cmd_arg_t *argv);
-
 
135
static cmd_arg_t call1_argv[] = {
-
 
136
    {
-
 
137
        .type = ARG_TYPE_STRING,
-
 
138
        .buffer = call0_buf,
-
 
139
        .len = sizeof(call0_buf)
-
 
140
    },
-
 
141
    { .type = ARG_TYPE_INT }
-
 
142
};
-
 
143
static cmd_info_t call1_info = {
-
 
144
    .name = "call1",
-
 
145
    .description = "call1 <function> <arg1> -> call function(arg1).",
-
 
146
    .func = cmd_call1,
-
 
147
    .argc = 2,
-
 
148
    .argv = call1_argv
-
 
149
};
-
 
150
 
-
 
151
static int cmd_call2(cmd_arg_t *argv);
-
 
152
static cmd_arg_t call2_argv[] = {
-
 
153
    {
-
 
154
        .type = ARG_TYPE_STRING,
-
 
155
        .buffer = call0_buf,
-
 
156
        .len = sizeof(call0_buf)
-
 
157
    },
-
 
158
    { .type = ARG_TYPE_INT },
-
 
159
    { .type = ARG_TYPE_INT }
-
 
160
};
-
 
161
static cmd_info_t call2_info = {
-
 
162
    .name = "call2",
-
 
163
    .description = "call2 <function> <arg1> <arg2> -> call function(arg1,arg2).",
-
 
164
    .func = cmd_call2,
-
 
165
    .argc = 3,
-
 
166
    .argv = call2_argv
-
 
167
};
-
 
168
 
87
 
169
 
88
/** Data and methods for 'halt' command. */
170
/** Data and methods for 'halt' command. */
89
static int cmd_halt(cmd_arg_t *argv);
171
static int cmd_halt(cmd_arg_t *argv);
90
static cmd_info_t halt_info;
172
static cmd_info_t halt_info = {
-
 
173
    .name = "halt",
-
 
174
    .description = "Halt the kernel.",
-
 
175
    .func = cmd_halt,
-
 
176
    .argc = 0
-
 
177
};
91
 
178
 
92
/** Initialize kconsole data structures. */
179
/** Initialize kconsole data structures. */
93
void kconsole_init(void)
180
void kconsole_init(void)
94
{
181
{
95
    spinlock_initialize(&cmd_lock, "kconsole_cmd");
182
    spinlock_initialize(&cmd_lock, "kconsole_cmd");
96
    list_initialize(&cmd_head);
183
    list_initialize(&cmd_head);
97
   
184
   
98
    help_info.name = "help";
-
 
99
    help_info.description = "List supported commands.";
-
 
100
    help_info.func = cmd_help;
-
 
101
    help_info.help = NULL;
-
 
102
    help_info.argc = 0;
-
 
103
    help_info.argv = NULL;
-
 
104
 
-
 
105
    spinlock_initialize(&help_info.lock, "kconsole_help");
185
    spinlock_initialize(&help_info.lock, "kconsole_help");
106
    link_initialize(&help_info.link);
186
    link_initialize(&help_info.link);
107
 
-
 
108
    if (!cmd_register(&help_info))
187
    if (!cmd_register(&help_info))
109
        panic("could not register command %s\n", help_info.name);
188
        panic("could not register command %s\n", help_info.name);
110
 
189
 
111
 
190
 
112
    desc_info.name = "describe";
-
 
113
    desc_info.description = "Describe specified command.";
-
 
114
    desc_info.help = desc_help;
-
 
115
    desc_info.func = cmd_desc;
-
 
116
    desc_info.argc = 1;
-
 
117
    desc_info.argv = &desc_argv;
-
 
118
   
-
 
119
    spinlock_initialize(&desc_info.lock, "kconsole_desc");
191
    spinlock_initialize(&desc_info.lock, "kconsole_desc");
120
    link_initialize(&desc_info.link);
192
    link_initialize(&desc_info.link);
121
   
-
 
122
    if (!cmd_register(&desc_info))
193
    if (!cmd_register(&desc_info))
123
        panic("could not register command %s\n", desc_info.name);
194
        panic("could not register command %s\n", desc_info.name);
124
   
195
   
-
 
196
    spinlock_initialize(&symaddr_info.lock, "kconsole_symaddr");
-
 
197
    link_initialize(&symaddr_info.link);
-
 
198
    if (!cmd_register(&symaddr_info))
-
 
199
        panic("could not register command %s\n", symaddr_info.name);
-
 
200
 
-
 
201
    spinlock_initialize(&call0_info.lock, "kconsole_call0");
-
 
202
    link_initialize(&call0_info.link);
-
 
203
    if (!cmd_register(&call0_info))
-
 
204
        panic("could not register command %s\n", call0_info.name);
-
 
205
 
-
 
206
    spinlock_initialize(&call1_info.lock, "kconsole_call1");
-
 
207
    link_initialize(&call1_info.link);
-
 
208
    if (!cmd_register(&call1_info))
-
 
209
        panic("could not register command %s\n", call1_info.name);
-
 
210
 
-
 
211
 
-
 
212
    spinlock_initialize(&call2_info.lock, "kconsole_call2");
-
 
213
    link_initialize(&call2_info.link);
-
 
214
    if (!cmd_register(&call2_info))
-
 
215
        panic("could not register command %s\n", call2_info.name);
125
   
216
   
126
    halt_info.name = "halt";
-
 
127
    halt_info.description = "Halt the kernel.";
-
 
128
    halt_info.func = cmd_halt;
-
 
129
    halt_info.help = NULL;
-
 
130
    halt_info.argc = 0;
-
 
131
    halt_info.argv = NULL;
-
 
132
 
-
 
133
    spinlock_initialize(&halt_info.lock, "kconsole_halt");
217
    spinlock_initialize(&halt_info.lock, "kconsole_halt");
134
    link_initialize(&halt_info.link);
218
    link_initialize(&halt_info.link);
135
 
-
 
136
    if (!cmd_register(&halt_info))
219
    if (!cmd_register(&halt_info))
137
        panic("could not register command %s\n", halt_info.name);
220
        panic("could not register command %s\n", halt_info.name);
138
}
221
}
139
 
222
 
140
 
223
 
141
/** Register kconsole command.
224
/** Register kconsole command.
142
 *
225
 *
143
 * @param cmd Structure describing the command.
226
 * @param cmd Structure describing the command.
144
 *
227
 *
145
 * @return 0 on failure, 1 on success.
228
 * @return 0 on failure, 1 on success.
146
 */
229
 */
147
int cmd_register(cmd_info_t *cmd)
230
int cmd_register(cmd_info_t *cmd)
148
{
231
{
149
    ipl_t ipl;
232
    ipl_t ipl;
150
    link_t *cur;
233
    link_t *cur;
151
   
234
   
152
    spinlock_lock(&cmd_lock);
235
    spinlock_lock(&cmd_lock);
153
   
236
   
154
    /*
237
    /*
155
     * Make sure the command is not already listed.
238
     * Make sure the command is not already listed.
156
     */
239
     */
157
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
240
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
158
        cmd_info_t *hlp;
241
        cmd_info_t *hlp;
159
       
242
       
160
        hlp = list_get_instance(cur, cmd_info_t, link);
243
        hlp = list_get_instance(cur, cmd_info_t, link);
161
 
244
 
162
        if (hlp == cmd) {
245
        if (hlp == cmd) {
163
            /* The command is already there. */
246
            /* The command is already there. */
164
            spinlock_unlock(&cmd_lock);
247
            spinlock_unlock(&cmd_lock);
165
            return 0;
248
            return 0;
166
        }
249
        }
167
 
250
 
168
        /* Avoid deadlock. */
251
        /* Avoid deadlock. */
169
        if (hlp < cmd) {
252
        if (hlp < cmd) {
170
            spinlock_lock(&hlp->lock);
253
            spinlock_lock(&hlp->lock);
171
            spinlock_lock(&cmd->lock);
254
            spinlock_lock(&cmd->lock);
172
        } else {
255
        } else {
173
            spinlock_lock(&cmd->lock);
256
            spinlock_lock(&cmd->lock);
174
            spinlock_lock(&hlp->lock);
257
            spinlock_lock(&hlp->lock);
175
        }
258
        }
176
       
259
       
177
        if ((strncmp(hlp->name, cmd->name, strlen(cmd->name)) == 0)) {
260
        if ((strncmp(hlp->name, cmd->name, strlen(cmd->name)) == 0)) {
178
            /* The command is already there. */
261
            /* The command is already there. */
179
            spinlock_unlock(&hlp->lock);
262
            spinlock_unlock(&hlp->lock);
180
            spinlock_unlock(&cmd->lock);
263
            spinlock_unlock(&cmd->lock);
181
            spinlock_unlock(&cmd_lock);
264
            spinlock_unlock(&cmd_lock);
182
            return 0;
265
            return 0;
183
        }
266
        }
184
       
267
       
185
        spinlock_unlock(&hlp->lock);
268
        spinlock_unlock(&hlp->lock);
186
        spinlock_unlock(&cmd->lock);
269
        spinlock_unlock(&cmd->lock);
187
    }
270
    }
188
   
271
   
189
    /*
272
    /*
190
     * Now the command can be added.
273
     * Now the command can be added.
191
     */
274
     */
192
    list_append(&cmd->link, &cmd_head);
275
    list_append(&cmd->link, &cmd_head);
193
   
276
   
194
    spinlock_unlock(&cmd_lock);
277
    spinlock_unlock(&cmd_lock);
195
    return 1;
278
    return 1;
196
}
279
}
197
 
280
 
198
/** Kernel console managing thread.
281
/** Kernel console managing thread.
199
 *
282
 *
200
 * @param arg Not used.
283
 * @param arg Not used.
201
 */
284
 */
202
void kconsole(void *arg)
285
void kconsole(void *arg)
203
{
286
{
204
    char cmdline[MAX_CMDLINE+1];
287
    char cmdline[MAX_CMDLINE+1];
205
    cmd_info_t *cmd_info;
288
    cmd_info_t *cmd_info;
206
    count_t len;
289
    count_t len;
207
 
290
 
208
    if (!stdin) {
291
    if (!stdin) {
209
        printf("%s: no stdin\n", __FUNCTION__);
292
        printf("%s: no stdin\n", __FUNCTION__);
210
        return;
293
        return;
211
    }
294
    }
212
   
295
   
213
    while (true) {
296
    while (true) {
214
        printf("%s> ", __FUNCTION__);
297
        printf("%s> ", __FUNCTION__);
215
        if (!(len = gets(stdin, cmdline, sizeof(cmdline))))
298
        if (!(len = gets(stdin, cmdline, sizeof(cmdline))))
216
            continue;
299
            continue;
217
        cmdline[len] = '\0';
300
        cmdline[len] = '\0';
218
        cmd_info = parse_cmdline(cmdline, len);
301
        cmd_info = parse_cmdline(cmdline, len);
219
        if (!cmd_info)
302
        if (!cmd_info)
220
            continue;
303
            continue;
221
        (void) cmd_info->func(cmd_info->argv);
304
        (void) cmd_info->func(cmd_info->argv);
222
    }
305
    }
223
}
306
}
224
 
307
 
225
/** Parse command line.
308
/** Parse command line.
226
 *
309
 *
227
 * @param cmdline Command line as read from input device.
310
 * @param cmdline Command line as read from input device.
228
 * @param len Command line length.
311
 * @param len Command line length.
229
 *
312
 *
230
 * @return Structure describing the command.
313
 * @return Structure describing the command.
231
 */
314
 */
232
cmd_info_t *parse_cmdline(char *cmdline, size_t len)
315
cmd_info_t *parse_cmdline(char *cmdline, size_t len)
233
{
316
{
234
    index_t start = 0, end = 0;
317
    index_t start = 0, end = 0;
235
    cmd_info_t *cmd = NULL;
318
    cmd_info_t *cmd = NULL;
236
    link_t *cur;
319
    link_t *cur;
237
    ipl_t ipl;
320
    ipl_t ipl;
238
    int i;
321
    int i;
239
   
322
   
240
    if (!parse_argument(cmdline, len, &start, &end)) {
323
    if (!parse_argument(cmdline, len, &start, &end)) {
241
        /* Command line did not contain alphanumeric word. */
324
        /* Command line did not contain alphanumeric word. */
242
        return NULL;
325
        return NULL;
243
    }
326
    }
244
 
327
 
245
    spinlock_lock(&cmd_lock);
328
    spinlock_lock(&cmd_lock);
246
   
329
   
247
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
330
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
248
        cmd_info_t *hlp;
331
        cmd_info_t *hlp;
249
       
332
       
250
        hlp = list_get_instance(cur, cmd_info_t, link);
333
        hlp = list_get_instance(cur, cmd_info_t, link);
251
        spinlock_lock(&hlp->lock);
334
        spinlock_lock(&hlp->lock);
252
       
335
       
253
        if (strncmp(hlp->name, &cmdline[start], (end - start) + 1) == 0) {
336
        if (strncmp(hlp->name, &cmdline[start], (end - start) + 1) == 0) {
254
            cmd = hlp;
337
            cmd = hlp;
255
            break;
338
            break;
256
        }
339
        }
257
       
340
       
258
        spinlock_unlock(&hlp->lock);
341
        spinlock_unlock(&hlp->lock);
259
    }
342
    }
260
   
343
   
261
    spinlock_unlock(&cmd_lock);
344
    spinlock_unlock(&cmd_lock);
262
   
345
   
263
    if (!cmd) {
346
    if (!cmd) {
264
        /* Unknown command. */
347
        /* Unknown command. */
265
        printf("Unknown command.\n");
348
        printf("Unknown command.\n");
266
        return NULL;
349
        return NULL;
267
    }
350
    }
268
 
351
 
269
    /* cmd == hlp is locked */
352
    /* cmd == hlp is locked */
270
   
353
   
271
    /*
354
    /*
272
     * The command line must be further analyzed and
355
     * The command line must be further analyzed and
273
     * the parameters therefrom must be matched and
356
     * the parameters therefrom must be matched and
274
     * converted to those specified in the cmd info
357
     * converted to those specified in the cmd info
275
     * structure.
358
     * structure.
276
     */
359
     */
277
 
360
 
278
    for (i = 0; i < cmd->argc; i++) {
361
    for (i = 0; i < cmd->argc; i++) {
279
        char *buf;
362
        char *buf;
280
        start = end + 1;
363
        start = end + 1;
281
        if (!parse_argument(cmdline, len, &start, &end)) {
364
        if (!parse_argument(cmdline, len, &start, &end)) {
282
            printf("Too few arguments.\n");
365
            printf("Too few arguments.\n");
283
            spinlock_unlock(&cmd->lock);
366
            spinlock_unlock(&cmd->lock);
284
            return NULL;
367
            return NULL;
285
        }
368
        }
286
       
369
       
287
        switch (cmd->argv[i].type) {
370
        switch (cmd->argv[i].type) {
288
            case ARG_TYPE_STRING:
371
        case ARG_TYPE_STRING:
289
                buf = cmd->argv[i].buffer;
372
                buf = cmd->argv[i].buffer;
290
                strncpy(buf, (const char *) &cmdline[start], min((end - start) + 1, cmd->argv[i].len - 1));
373
                strncpy(buf, (const char *) &cmdline[start], min((end - start) + 1, cmd->argv[i].len - 1));
291
            buf[min((end - start) + 1, cmd->argv[i].len - 1)] = '\0';
374
            buf[min((end - start) + 1, cmd->argv[i].len - 1)] = '\0';
292
            break;
375
            break;
293
            case ARG_TYPE_INT:
376
        case ARG_TYPE_INT: {
-
 
377
            char symname[MAX_SYMBOL_NAME];
-
 
378
            __address symaddr;
-
 
379
 
-
 
380
            /* If we get a name, try to find it in symbol table */
-
 
381
            if (cmdline[start] < '0' | cmdline[start] > '9') {
-
 
382
                strncpy(symname, cmdline+start, min((end-start) + 1, MAX_SYMBOL_NAME -1 ));
-
 
383
                symaddr = get_symbol_addr(symname);
-
 
384
                if (!symaddr) {
-
 
385
                    printf("Symbol %s not found.\n",symname);
-
 
386
                    return NULL;
-
 
387
                }
-
 
388
                if (symaddr == (__address) -1) {
-
 
389
                    printf("Duplicate symbol %s.\n",symname);
-
 
390
                    symtab_print_search(symname);
-
 
391
                    return NULL;
-
 
392
                }
-
 
393
                cmd->argv[i].intval = *((__native *)symaddr);
-
 
394
            } else /* It's a number - convert it */
-
 
395
                cmd->argv[i].intval = atoi(cmdline+start);
-
 
396
            break;
-
 
397
            }
294
            case ARG_TYPE_INVALID:
398
        case ARG_TYPE_INVALID:
295
            default:
399
        default:
296
            panic("invalid argument type\n");
400
            printf("invalid argument type\n");
-
 
401
            return NULL;
297
            break;
402
            break;
298
        }
403
        }
299
    }
404
    }
300
   
405
   
301
    start = end + 1;
406
    start = end + 1;
302
    if (parse_argument(cmdline, len, &start, &end)) {
407
    if (parse_argument(cmdline, len, &start, &end)) {
303
        printf("Too many arguments.\n");
408
        printf("Too many arguments.\n");
304
        spinlock_unlock(&cmd->lock);
409
        spinlock_unlock(&cmd->lock);
305
        return NULL;
410
        return NULL;
306
    }
411
    }
307
   
412
   
308
    spinlock_unlock(&cmd->lock);
413
    spinlock_unlock(&cmd->lock);
309
    return cmd;
414
    return cmd;
310
}
415
}
311
 
416
 
312
/** Parse argument.
417
/** Parse argument.
313
 *
418
 *
314
 * Find start and end positions of command line argument.
419
 * Find start and end positions of command line argument.
315
 *
420
 *
316
 * @param cmdline Command line as read from the input device.
421
 * @param cmdline Command line as read from the input device.
317
 * @param len Number of characters in cmdline.
422
 * @param len Number of characters in cmdline.
318
 * @param start On entry, 'start' contains pointer to the index
423
 * @param start On entry, 'start' contains pointer to the index
319
 *        of first unprocessed character of cmdline.
424
 *        of first unprocessed character of cmdline.
320
 *        On successful exit, it marks beginning of the next argument.
425
 *        On successful exit, it marks beginning of the next argument.
321
 * @param end Undefined on entry. On exit, 'end' points to the last character
426
 * @param end Undefined on entry. On exit, 'end' points to the last character
322
 *        of the next argument.
427
 *        of the next argument.
323
 *
428
 *
324
 * @return false on failure, true on success.
429
 * @return false on failure, true on success.
325
 */
430
 */
326
bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end)
431
bool parse_argument(char *cmdline, size_t len, index_t *start, index_t *end)
327
{
432
{
328
    int i;
433
    int i;
329
    bool found_start = false;
434
    bool found_start = false;
330
   
435
   
331
    ASSERT(start != NULL);
436
    ASSERT(start != NULL);
332
    ASSERT(end != NULL);
437
    ASSERT(end != NULL);
333
   
438
   
334
    for (i = *start; i < len; i++) {
439
    for (i = *start; i < len; i++) {
335
        if (!found_start) {
440
        if (!found_start) {
336
            if (is_white(cmdline[i]))
441
            if (is_white(cmdline[i]))
337
                (*start)++;
442
                (*start)++;
338
            else
443
            else
339
                found_start = true;
444
                found_start = true;
340
        } else {
445
        } else {
341
            if (is_white(cmdline[i]))
446
            if (is_white(cmdline[i]))
342
                break;
447
                break;
343
        }
448
        }
344
    }
449
    }
345
    *end = i - 1;
450
    *end = i - 1;
346
 
451
 
347
    return found_start;
452
    return found_start;
348
}
453
}
349
 
454
 
350
 
455
 
351
/** List supported commands.
456
/** List supported commands.
352
 *
457
 *
353
 * @param argv Argument vector.
458
 * @param argv Argument vector.
354
 *
459
 *
355
 * @return 0 on failure, 1 on success.
460
 * @return 0 on failure, 1 on success.
356
 */
461
 */
357
int cmd_help(cmd_arg_t *argv)
462
int cmd_help(cmd_arg_t *argv)
358
{
463
{
359
    link_t *cur;
464
    link_t *cur;
360
    ipl_t ipl;
465
    ipl_t ipl;
361
 
466
 
362
    spinlock_lock(&cmd_lock);
467
    spinlock_lock(&cmd_lock);
363
   
468
   
364
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
469
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
365
        cmd_info_t *hlp;
470
        cmd_info_t *hlp;
366
       
471
       
367
        hlp = list_get_instance(cur, cmd_info_t, link);
472
        hlp = list_get_instance(cur, cmd_info_t, link);
368
        spinlock_lock(&hlp->lock);
473
        spinlock_lock(&hlp->lock);
369
       
474
       
370
        printf("%s - %s\n", hlp->name, hlp->description);
475
        printf("%s - %s\n", hlp->name, hlp->description);
371
 
476
 
372
        spinlock_unlock(&hlp->lock);
477
        spinlock_unlock(&hlp->lock);
373
    }
478
    }
374
   
479
   
375
    spinlock_unlock(&cmd_lock);
480
    spinlock_unlock(&cmd_lock);
376
 
481
 
377
    return 1;
482
    return 1;
378
}
483
}
379
 
484
 
380
/** Describe specified command.
485
/** Describe specified command.
381
 *
486
 *
382
 * @param argv Argument vector.
487
 * @param argv Argument vector.
383
 *
488
 *
384
 * @return 0 on failure, 1 on success.
489
 * @return 0 on failure, 1 on success.
385
 */
490
 */
386
int cmd_desc(cmd_arg_t *argv)
491
int cmd_desc(cmd_arg_t *argv)
387
{
492
{
388
    link_t *cur;
493
    link_t *cur;
389
    ipl_t ipl;
494
    ipl_t ipl;
390
 
495
 
391
    spinlock_lock(&cmd_lock);
496
    spinlock_lock(&cmd_lock);
392
   
497
   
393
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
498
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
394
        cmd_info_t *hlp;
499
        cmd_info_t *hlp;
395
       
500
       
396
        hlp = list_get_instance(cur, cmd_info_t, link);
501
        hlp = list_get_instance(cur, cmd_info_t, link);
397
        spinlock_lock(&hlp->lock);
502
        spinlock_lock(&hlp->lock);
398
 
503
 
399
        if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
504
        if (strncmp(hlp->name, (const char *) argv->buffer, strlen(hlp->name)) == 0) {
400
            printf("%s - %s\n", hlp->name, hlp->description);
505
            printf("%s - %s\n", hlp->name, hlp->description);
401
            if (hlp->help)
506
            if (hlp->help)
402
                hlp->help();
507
                hlp->help();
403
            spinlock_unlock(&hlp->lock);
508
            spinlock_unlock(&hlp->lock);
404
            break;
509
            break;
405
        }
510
        }
406
 
511
 
407
        spinlock_unlock(&hlp->lock);
512
        spinlock_unlock(&hlp->lock);
408
    }
513
    }
409
   
514
   
410
    spinlock_unlock(&cmd_lock);
515
    spinlock_unlock(&cmd_lock);
411
 
516
 
412
    return 1;
517
    return 1;
413
}
518
}
414
 
519
 
-
 
520
/** Search symbol table */
-
 
521
int cmd_symaddr(cmd_arg_t *argv)
-
 
522
{
-
 
523
    __address symaddr;
-
 
524
    char *symbol;
-
 
525
 
-
 
526
    symtab_print_search(argv->buffer);
-
 
527
   
-
 
528
    return 1;
-
 
529
}
-
 
530
 
-
 
531
/** Call function with zero parameters */
-
 
532
int cmd_call0(cmd_arg_t *argv)
-
 
533
{
-
 
534
    __address symaddr;
-
 
535
    char *symbol;
-
 
536
    __native (*f)(void);
-
 
537
 
-
 
538
    symaddr = get_symbol_addr(argv->buffer);
-
 
539
    if (!symaddr)
-
 
540
        printf("Symbol not found.\n");
-
 
541
    else if (symaddr == (__address) -1) {
-
 
542
        symtab_print_search(argv->buffer);
-
 
543
        printf("Duplicate symbol, be more specific.\n");
-
 
544
    } else {
-
 
545
        symbol = get_symtab_entry(symaddr);
-
 
546
        printf("Calling f(): 0x%p: %s\n", symaddr, symbol);
-
 
547
        f =  (__native (*)(void)) symaddr;
-
 
548
        printf("Result: 0x%X\n", f());
-
 
549
    }
-
 
550
   
-
 
551
    return 1;
-
 
552
}
-
 
553
 
-
 
554
/** Call function with one parameter */
-
 
555
int cmd_call1(cmd_arg_t *argv)
-
 
556
{
-
 
557
    __address symaddr;
-
 
558
    char *symbol;
-
 
559
    __native (*f)(__native);
-
 
560
    __native arg1 = argv[1].intval;
-
 
561
 
-
 
562
    symaddr = get_symbol_addr(argv->buffer);
-
 
563
    if (!symaddr)
-
 
564
        printf("Symbol not found.\n");
-
 
565
    else if (symaddr == (__address) -1) {
-
 
566
        symtab_print_search(argv->buffer);
-
 
567
        printf("Duplicate symbol, be more specific.\n");
-
 
568
    } else {
-
 
569
        symbol = get_symtab_entry(symaddr);
-
 
570
        printf("Calling f(0x%x): 0x%p: %s\n", arg1, symaddr, symbol);
-
 
571
        f =  (__native (*)(__native)) symaddr;
-
 
572
        printf("Result: 0x%x\n", f(arg1));
-
 
573
    }
-
 
574
   
-
 
575
    return 1;
-
 
576
}
-
 
577
 
-
 
578
/** Call function with two parameters */
-
 
579
int cmd_call2(cmd_arg_t *argv)
-
 
580
{
-
 
581
    __address symaddr;
-
 
582
    char *symbol;
-
 
583
    __native (*f)(__native);
-
 
584
    __native arg1 = argv[1].intval;
-
 
585
    __native arg2 = argv[2].intval;
-
 
586
 
-
 
587
    symaddr = get_symbol_addr(argv->buffer);
-
 
588
    if (!symaddr)
-
 
589
        printf("Symbol not found.\n");
-
 
590
    else if (symaddr == (__address) -1) {
-
 
591
        symtab_print_search(argv->buffer);
-
 
592
        printf("Duplicate symbol, be more specific.\n");
-
 
593
    } else {
-
 
594
        symbol = get_symtab_entry(symaddr);
-
 
595
        printf("Calling f(0x%x,0x%x): 0x%p: %s\n",
-
 
596
               arg1, arg2, symaddr, symbol);
-
 
597
        f =  (__native (*)(__native)) symaddr;
-
 
598
        printf("Result: 0x%x\n", f(arg1));
-
 
599
    }
-
 
600
   
-
 
601
    return 1;
-
 
602
}
-
 
603
 
-
 
604
 
415
/** Print detailed description of 'describe' command. */
605
/** Print detailed description of 'describe' command. */
416
void desc_help(void)
606
void desc_help(void)
417
{
607
{
418
    printf("Syntax: describe command_name\n");
608
    printf("Syntax: describe command_name\n");
419
}
609
}
420
 
610
 
421
/** Halt the kernel.
611
/** Halt the kernel.
422
 *
612
 *
423
 * @param argv Argument vector (ignored).
613
 * @param argv Argument vector (ignored).
424
 *
614
 *
425
 * @return 0 on failure, 1 on success (never returns).
615
 * @return 0 on failure, 1 on success (never returns).
426
 */
616
 */
427
int cmd_halt(cmd_arg_t *argv)
617
int cmd_halt(cmd_arg_t *argv)
428
{
618
{
429
    halt();
619
    halt();
430
    return 1;
620
    return 1;
431
}
621
}
432
 
622