Subversion Repositories HelenOS-historic

Rev

Rev 512 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 512 Rev 517
Line 28... Line 28...
28
 
28
 
29
#include <main/kconsole.h>
29
#include <main/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 <typedefs.h>
34
#include <typedefs.h>
34
#include <arch/types.h>
35
#include <arch/types.h>
-
 
36
#include <list.h>
-
 
37
#include <arch.h>
-
 
38
#include <func.h>
-
 
39
#include <macros.h>
-
 
40
 
-
 
41
#define MAX_CMDLINE 256
-
 
42
 
-
 
43
/** Simple kernel console.
-
 
44
 *
-
 
45
 * The console is realized by kernel thread kconsole.
-
 
46
 * It doesn't understand any commands on its own, but
-
 
47
 * makes it possible for other kernel subsystems to
-
 
48
 * register their own commands.
-
 
49
 */
-
 
50
 
-
 
51
/** Locking.
-
 
52
 *
-
 
53
 * There is a list of cmd_info_t structures. This list
-
 
54
 * is protected by cmd_lock spinlock. Note that specially
-
 
55
 * the link elements of cmd_info_t are protected by
-
 
56
 * this lock.
-
 
57
 *
-
 
58
 * Each cmd_info_t also has its own lock, which protects
-
 
59
 * all elements thereof except the link element.
-
 
60
 *
-
 
61
 * cmd_lock must be acquired before any cmd_info lock.
-
 
62
 * When locking two cmd info structures, structure with
-
 
63
 * lower address must be locked first.
-
 
64
 */
-
 
65
 
-
 
66
spinlock_t cmd_lock;    /**< Lock protecting command list. */
-
 
67
link_t cmd_head;    /**< Command list. */
-
 
68
 
-
 
69
static cmd_info_t *parse_cmdline(char *cmdline, size_t len);
-
 
70
static int cmd_help(cmd_arg_t *cmd);
-
 
71
 
-
 
72
static cmd_info_t help_info;
-
 
73
 
-
 
74
/** Initialize kconsole data structures. */
-
 
75
void kconsole_init(void)
-
 
76
{
-
 
77
    spinlock_initialize(&cmd_lock);
-
 
78
    list_initialize(&cmd_head);
-
 
79
   
-
 
80
    help_info.name = "help";
-
 
81
    help_info.description = "List supported commands.";
-
 
82
    help_info.func = cmd_help;
-
 
83
    help_info.argc = 0;
-
 
84
    help_info.argv = NULL;
-
 
85
   
-
 
86
    spinlock_initialize(&help_info.lock);
-
 
87
    link_initialize(&help_info.link);
-
 
88
   
-
 
89
    if (!cmd_register(&help_info))
-
 
90
        panic("could not register command\n");
-
 
91
}
-
 
92
 
-
 
93
 
-
 
94
/** Register kconsole command.
-
 
95
 *
-
 
96
 * @param cmd Structure describing the command.
-
 
97
 *
-
 
98
 * @return 0 on failure, 1 on success.
-
 
99
 */
-
 
100
int cmd_register(cmd_info_t *cmd)
-
 
101
{
-
 
102
    ipl_t ipl;
-
 
103
    link_t *cur;
-
 
104
   
-
 
105
    ipl = interrupts_disable();
-
 
106
    spinlock_lock(&cmd_lock);
-
 
107
   
-
 
108
    /*
-
 
109
     * Make sure the command is not already listed.
-
 
110
     */
-
 
111
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
-
 
112
        cmd_info_t *hlp;
-
 
113
       
-
 
114
        hlp = list_get_instance(cur, cmd_info_t, link);
-
 
115
 
-
 
116
        if (hlp == cmd) {
-
 
117
            /* The command is already there. */
-
 
118
            spinlock_unlock(&cmd_lock);
-
 
119
            interrupts_restore(ipl);
-
 
120
            return 0;
-
 
121
        }
-
 
122
 
-
 
123
        /* Avoid deadlock. */
-
 
124
        if (hlp < cmd) {
-
 
125
            spinlock_lock(&hlp->lock);
-
 
126
            spinlock_lock(&cmd->lock);
-
 
127
        } else {
-
 
128
            spinlock_lock(&cmd->lock);
-
 
129
            spinlock_lock(&hlp->lock);
-
 
130
        }
-
 
131
       
-
 
132
        if ((strcmp(hlp->name, cmd->name, strlen(cmd->name)) == 0)) {
-
 
133
            /* The command is already there. */
-
 
134
            spinlock_unlock(&hlp->lock);
-
 
135
            spinlock_unlock(&cmd->lock);
-
 
136
            spinlock_unlock(&cmd_lock);
-
 
137
            interrupts_restore(ipl);
-
 
138
            return 0;
-
 
139
        }
-
 
140
       
-
 
141
        spinlock_unlock(&hlp->lock);
-
 
142
        spinlock_unlock(&cmd->lock);
-
 
143
    }
-
 
144
   
-
 
145
    /*
-
 
146
     * Now the command can be added.
-
 
147
     */
-
 
148
    list_append(&cmd->link, &cmd_head);
-
 
149
   
-
 
150
    spinlock_unlock(&cmd_lock);
-
 
151
    interrupts_restore(ipl);
-
 
152
    return 1;
-
 
153
}
35
 
154
 
36
/** Kernel console managing thread.
155
/** Kernel console managing thread.
37
 *
156
 *
38
 * @param arg Not used.
157
 * @param arg Not used.
39
 */
158
 */
40
void kconsole(void *arg)
159
void kconsole(void *arg)
41
{
160
{
42
    __u8 buf[CHARDEV_BUFLEN];
161
    char cmdline[MAX_CMDLINE+1];
-
 
162
    cmd_info_t *cmd_info;
-
 
163
    count_t len;
43
 
164
 
44
    if (!stdin) {
165
    if (!stdin) {
45
        printf("%s: no stdin\n", __FUNCTION__);
166
        printf("%s: no stdin\n", __FUNCTION__);
46
        return;
167
        return;
47
    }
168
    }
48
   
169
   
49
    while (true) {
170
    while (true) {
50
        printf("%s> ", __FUNCTION__);
171
        printf("%s> ", __FUNCTION__);
51
        gets(stdin, buf, sizeof(buf));
172
        len = gets(stdin, cmdline, sizeof(cmdline));
-
 
173
        cmdline[len] = '\0';
-
 
174
        cmd_info = parse_cmdline(cmdline, len);
-
 
175
        if (!cmd_info) {
52
        printf("?\n");
176
            printf("?\n");
-
 
177
            continue;
-
 
178
        }
-
 
179
        (void) cmd_info->func(cmd_info->argv);
53
    }
180
    }
54
}
181
}
-
 
182
 
-
 
183
/** Parse command line.
-
 
184
 *
-
 
185
 * @param cmdline Command line as read from input device.
-
 
186
 * @param len Command line length.
-
 
187
 *
-
 
188
 * @return Structure describing the command.
-
 
189
 */
-
 
190
cmd_info_t *parse_cmdline(char *cmdline, size_t len)
-
 
191
{
-
 
192
    index_t start = 0, end = 0;
-
 
193
    bool found_start = false;
-
 
194
    cmd_info_t *cmd = NULL;
-
 
195
    link_t *cur;
-
 
196
    ipl_t ipl;
-
 
197
    int i;
-
 
198
   
-
 
199
    for (i = 0; i < len; i++) {
-
 
200
        if (!found_start) {
-
 
201
            if (is_white(cmdline[i]))
-
 
202
                start++;
-
 
203
            else
-
 
204
                found_start = true;
-
 
205
        } else {
-
 
206
            if (is_white(cmdline[i]))
-
 
207
                break;
-
 
208
        }
-
 
209
    }
-
 
210
    end = i - 1;
-
 
211
   
-
 
212
    if (!found_start) {
-
 
213
        /* Command line did not contain alphanumeric word. */
-
 
214
        return NULL;
-
 
215
    }
-
 
216
 
-
 
217
    ipl = interrupts_disable();
-
 
218
    spinlock_lock(&cmd_lock);
-
 
219
   
-
 
220
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
-
 
221
        cmd_info_t *hlp;
-
 
222
       
-
 
223
        hlp = list_get_instance(cur, cmd_info_t, link);
-
 
224
        spinlock_lock(&hlp->lock);
-
 
225
       
-
 
226
        if (strcmp(hlp->name, &cmdline[start], (end - start) + 1) == 0) {
-
 
227
            cmd = hlp;
-
 
228
            break;
-
 
229
        }
-
 
230
       
-
 
231
        spinlock_unlock(&hlp->lock);
-
 
232
    }
-
 
233
   
-
 
234
    spinlock_unlock(&cmd_lock);
-
 
235
   
-
 
236
    if (!cmd) {
-
 
237
        /* Unknown command. */
-
 
238
        interrupts_restore(ipl);
-
 
239
        return NULL;
-
 
240
    }
-
 
241
 
-
 
242
    /* cmd == hlp is locked */
-
 
243
   
-
 
244
    /*
-
 
245
     * TODO:
-
 
246
     * The command line must be further analyzed and
-
 
247
     * the parameters therefrom must be matched and
-
 
248
     * converted to those specified in the cmd info
-
 
249
     * structure.
-
 
250
     */
-
 
251
   
-
 
252
    spinlock_unlock(&cmd->lock);
-
 
253
    interrupts_restore(ipl);
-
 
254
    return cmd;
-
 
255
}
-
 
256
 
-
 
257
/** List supported commands.
-
 
258
 *
-
 
259
 * @param cmd Argument vector.
-
 
260
 *
-
 
261
 * @return 0 on failure, 1 on success.
-
 
262
 */
-
 
263
int cmd_help(cmd_arg_t *cmd)
-
 
264
{
-
 
265
    link_t *cur;
-
 
266
    ipl_t ipl;
-
 
267
 
-
 
268
    ipl = interrupts_disable();
-
 
269
    spinlock_lock(&cmd_lock);
-
 
270
   
-
 
271
    for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
-
 
272
        cmd_info_t *hlp;
-
 
273
       
-
 
274
        hlp = list_get_instance(cur, cmd_info_t, link);
-
 
275
        spinlock_lock(&hlp->lock);
-
 
276
       
-
 
277
        printf("%s\t%s\n", hlp->name, hlp->description);
-
 
278
 
-
 
279
        spinlock_unlock(&hlp->lock);
-
 
280
    }
-
 
281
   
-
 
282
    spinlock_unlock(&cmd_lock);
-
 
283
    interrupts_restore(ipl);
-
 
284
 
-
 
285
    return 1;
-
 
286
}