Changeset ff3b3197 in mainline for generic/src/main/kconsole.c


Ignore:
Timestamp:
2005-11-25T22:58:38Z (20 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f4338d2
Parents:
78c32b4
Message:

Implement basic kernel console command recognition.
Commands without arguments are now recognized.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • generic/src/main/kconsole.c

    r78c32b4 rff3b3197  
    3131#include <console/chardev.h>
    3232#include <print.h>
     33#include <panic.h>
    3334#include <typedefs.h>
    3435#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 
     66spinlock_t cmd_lock;    /**< Lock protecting command list. */
     67link_t cmd_head;        /**< Command list. */
     68
     69static cmd_info_t *parse_cmdline(char *cmdline, size_t len);
     70static int cmd_help(cmd_arg_t *cmd);
     71
     72static cmd_info_t help_info;
     73
     74/** Initialize kconsole data structures. */
     75void 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 */
     100int 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}
    35154
    36155/** Kernel console managing thread.
     
    40159void kconsole(void *arg)
    41160{
    42         __u8 buf[CHARDEV_BUFLEN];
     161        char cmdline[MAX_CMDLINE+1];
     162        cmd_info_t *cmd_info;
     163        count_t len;
    43164
    44165        if (!stdin) {
     
    49170        while (true) {
    50171                printf("%s> ", __FUNCTION__);
    51                 gets(stdin, buf, sizeof(buf));
    52                 printf("?\n");
    53         }
    54 }
     172                len = gets(stdin, cmdline, sizeof(cmdline));
     173                cmdline[len] = '\0';
     174                cmd_info = parse_cmdline(cmdline, len);
     175                if (!cmd_info) {
     176                        printf("?\n");
     177                        continue;
     178                }
     179                (void) cmd_info->func(cmd_info->argv);
     180        }
     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 */
     190cmd_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 */
     263int 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}
Note: See TracChangeset for help on using the changeset viewer.