root/sys/arch/landisk/stand/boot/monitor.c
/*      $NetBSD: monitor.c,v 1.4 2016/06/11 06:31:49 dholland Exp $     */

/*-
 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Kazuki Sakamoto.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#if defined(DBMONITOR)

#include <lib/libsa/stand.h>
#include <lib/libkern/libkern.h>

#include "boot.h"

#ifndef NULL
#define NULL    (void *)0
#endif

static void db_cmd_dump(int, char **);
static void db_cmd_get(int, char **);
static void db_cmd_put(int, char **);
static void db_cmd_help(int, char **);

static int db_atob(char *);

static const struct db_cmd {
        char *name;
        void (*fcn)(int, char **);
} db_cmd[] = {
        { "dump",       db_cmd_dump },
        { "get",        db_cmd_get },
        { "put",        db_cmd_put },
        { "help",       db_cmd_help },
        { NULL,         NULL },
};

int
db_monitor(void)
{
        char line[1024];
        char *p, *argv[16];
        int argc, flag;
        int tmp;

        for (;;) {
                printf("db> ");
                kgets(line, sizeof(line));

                flag = 0;
                argc = 0;
                for (p = line; *p != '\0'; p++) {
                        if (*p != ' ' && *p != '\t') {
                                if (!flag) {
                                        flag++;
                                        argv[argc++] = p;
                                }
                        } else {
                                if (flag) {
                                        *p = '\0';
                                        flag = 0;
                                }
                        }
                }
                if (argc == 0)
                        continue;

                tmp = 0;
                while (db_cmd[tmp].name != NULL) {
                        if (strcmp("continue", argv[0]) == 0)
                                return 0;
                        if (strcmp(db_cmd[tmp].name, argv[0]) == 0) {
                                (db_cmd[tmp].fcn)(argc, argv);
                                break;
                        }
                        tmp++;
                }
                if (db_cmd[tmp].name == NULL)
                        db_cmd_help(argc, argv);
        }

        return 0;
}

static int
db_atob(char *p)
{
        int b = 0, width, tmp, exp, x = 0;
        
        if (p[1] == 'x') {
                p += 2;
                x = 1;
        }

        width = strlen(p);
        while (width--) {
                exp = 1;
                for (tmp = 1; tmp <= width; tmp++)
                        exp *= (x ? 16 : 10);
                if (*p >= '0' && *p <= '9') {
                        tmp = *p - '0';
                } else {
                        tmp = *p - 'a' + 10;
                }
                b += tmp * exp;
                p++;
        }
        return b;
}

static void
db_cmd_dump(int argc, char **argv)
{
        char *p, *r, *pp;
        int mode, add, size, i;

        switch (argc) {
        case 4:
                r = argv[1];
                switch (r[1]) {
                case 'b':
                        mode = 1;
                        break;
                case 'h':
                        mode = 2;
                        break;
                case 'w':
                        mode = 4;
                        break;
                default:
                        goto out;
                }
                p = argv[2];
                pp = argv[3];
                break;
        case 3:
                mode = 4;
                p = argv[1];
                pp = argv[2];
                break;
        default:
                goto out;
        }

        add = db_atob(p);
        size = db_atob(pp);
        i = 0;
        for (; size > 0;) {
                if (i == 0) {
                        printf("\n0x%x:", add);
                }
                switch (mode) {
                case 1:
                        printf(" ");
                        puthex(*(unsigned char *)add, 1);
                        add += 1;
                        size -= 1;
                        if (++i == 16)
                                i = 0;
                        break;
                case 2:
                        printf(" ");
                        puthex(*(unsigned short *)add, 2);
                        add += 2;
                        size -= 2;
                        if (++i == 8)
                                i = 0;
                        break;
                case 4:
                        printf(" ");
                        puthex(*(unsigned int *)add, 4);
                        add += 4;
                        size -= 4;
                        if (++i == 4)
                                i = 0;
                        break;
                }
        }
        printf("\n");
        return;

out:    
        printf("dump [-b][-h][-w] address size\n");
        return;
}

static void
db_cmd_get(int argc, char **argv)
{
        char *p, *r;
        int mode, add;
        int val;

        switch (argc) {
        case 3:
                r = argv[1];
                switch (r[1]) {
                case 'b':
                        mode = 1;
                        break;
                case 'h':
                        mode = 2;
                        break;
                case 'w':
                        mode = 4;
                        break;
                default:
                        goto out;
                }
                p = argv[2];
                break;
        case 2:
                mode = 4;
                p = argv[1];
                break;
        default:
                goto out;
        }

        add = db_atob(p);
        printf("0x%x: 0x", add);
        switch (mode) {
        case 1:
                val = *(char *)add;
                break;
        case 2:
                val = *(short *)add;
                break;
        case 4:
                val = *(int *)add;
                break;
        default:
                val = 0;
                break;
        }
        puthex(val, mode);
        printf("\n");
        return;

out:    
        printf("get [-b][-h][-w] address\n");
        return;
}

static void
db_cmd_put(int argc, char **argv)
{
        char *p, *r, *pp;
        int mode, add, data;

        switch (argc) {
        case 4:
                r = argv[1];
                switch (r[1]) {
                case 'b':
                        mode = 1;
                        break;
                case 'h':
                        mode = 2;
                        break;
                case 'w':
                        mode = 4;
                        break;
                default:
                        goto out;
                }
                p = argv[2];
                pp = argv[3];
                break;
        case 3:
                mode = 4;
                p = argv[1];
                pp = argv[2];
                break;
        default:
                goto out;
        }

        add = db_atob(p);
        data = db_atob(pp);
        printf("0x%x: 0x", add);
        puthex(data, mode);
        switch (mode) {
        case 1:
                *(char *)add = data;
                break;
        case 2:
                *(short *)add = data;
                break;
        case 4:
                *(int *)add = data;
                break;
        }
        printf("\n");
        return;

out:    
        printf("put [-b][-h][-w] address data\n");
        return;
}

static void
db_cmd_help(int argc, char **argv)
{
        int i = 0;

        while (db_cmd[i].name != NULL)
                printf("%s, ", db_cmd[i++].name);
        printf("continue\n");
}

#endif  /* DBMONITOR */