shell.c 4.67 KB
Newer Older
1 2 3 4
#include <stdio.h>
#include <string.h>
#include <errno.h>

5 6
#include "util.h"
#include "uart.h"
7
#include "syscon.h"
8
#include "shell.h"
9
#include "eeprom.h"
10

11
#define SH_MAX_LINE_LEN 80
12
#define SH_MAX_ARGS 8
13
#define SH_ENVIRON_SIZE 256
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

/* interactive shell state definitions */

#define SH_PROMPT 0
#define SH_INPUT 1
#define SH_EXEC 2

#define ESCAPE_FLAG 0x10000

#define KEY_LEFT (ESCAPE_FLAG | 68)
#define KEY_RIGHT (ESCAPE_FLAG | 67)
#define KEY_ENTER (13)
#define KEY_ESCAPE (27)
#define KEY_BACKSPACE (127)
#define KEY_DELETE (126)

struct shell_cmd {
	char *name;
32
	int (*exec) (const char *args[]);
33 34 35
};

static const struct shell_cmd cmds_list[] = {
36 37 38 39 40 41 42 43 44 45 46 47 48
	{"pll",		cmd_pll},
	{"gui",		cmd_gui},
	{"ver",		cmd_version},
	{"stat",	cmd_stat},
	{"ptp",		cmd_ptp},
	{"mode",	cmd_mode},
	{"calibration",	cmd_calib},
	{"set",		cmd_set},
	{"env",		cmd_env},
	{"saveenv",	cmd_saveenv},
	{"time",	cmd_time},
	{"sfp",		cmd_sfp},
	{"init",	cmd_init},
49
#if WITH_ETHERBONE
50
	{"ip",		cmd_ip},
51
#endif
52 53
	{"mac",		cmd_mac},
	{"sdb",		cmd_sdb},
54

55 56
	{NULL,	NULL}
};
57 58 59 60 61 62 63 64

static char cmd_buf[SH_MAX_LINE_LEN + 1];
static int cmd_pos = 0, cmd_len = 0;
static int state = SH_PROMPT;
static int current_key = 0;

static int insert(char c)
{
65
	if (cmd_len >= SH_MAX_LINE_LEN)
66 67
		return 0;

68 69 70
	if (cmd_pos != cmd_len)
		memmove(&cmd_buf[cmd_pos + 1], &cmd_buf[cmd_pos],
			cmd_len - cmd_pos);
71 72 73 74 75 76 77 78 79 80

	cmd_buf[cmd_pos] = c;
	cmd_pos++;
	cmd_len++;

	return 1;
}

static void delete(int where)
{
81
	memmove(&cmd_buf[where], &cmd_buf[where + 1], cmd_len - where);
82 83 84 85 86 87 88 89 90 91
	cmd_len--;
}

static void esc(char code)
{
	mprintf("\033[1%c", code);
}

static int _shell_exec()
{
92
	char *tokptr[SH_MAX_ARGS + 1];
93 94 95
	int n = 0, i = 0;

	memset(tokptr, 0, sizeof(tokptr));
96

97 98
	while (1) {
		if (n >= SH_MAX_ARGS)
99 100
			break;

101 102
		while (cmd_buf[i] == ' ' && cmd_buf[i])
			cmd_buf[i++] = 0;
103

104
		if (!cmd_buf[i])
105 106
			break;

107 108 109
		tokptr[n++] = &cmd_buf[i];
		while (cmd_buf[i] != ' ' && cmd_buf[i])
			i++;
110

111
		if (!cmd_buf[i])
112 113 114
			break;
	}

115
	if (!n)
116 117
		return 0;

118
	if (*tokptr[0] == '#')
119 120
		return 0;

121 122 123 124
	for (i = 0; cmds_list[i].name; i++)
		if (!strcasecmp(cmds_list[i].name, tokptr[0])) {
			int rv = cmds_list[i].exec((const char **)tokptr + 1);
			if (rv < 0)
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
				mprintf("Err %d\n", rv);
			return rv;
		}

	mprintf("Unrecognized command.\n");
	return -EINVAL;
}

int shell_exec(const char *cmd)
{
	strncpy(cmd_buf, cmd, SH_MAX_LINE_LEN);
	cmd_len = strlen(cmd_buf);
	return _shell_exec();
}

void shell_init()
{
142
	env_init();
143 144
	cmd_len = cmd_pos = 0;
	state = SH_PROMPT;
145
	mprintf("\033[2J\033[1;1H");
146 147 148 149 150
}

void shell_interactive()
{
	int c;
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
	switch (state) {
	case SH_PROMPT:
		mprintf("wrc# ");
		cmd_pos = 0;
		cmd_len = 0;
		state = SH_INPUT;
		break;

	case SH_INPUT:
		c = uart_read_byte();

		if (c < 0)
			return;

		if (c == 27 || ((current_key & ESCAPE_FLAG) && c == 91))
			current_key = ESCAPE_FLAG;
		else
			current_key |= c;

		if (current_key & 0xff) {

			switch (current_key) {
			case KEY_LEFT:
				if (cmd_pos > 0) {
					cmd_pos--;
					esc('D');
				}
				break;
			case KEY_RIGHT:
				if (cmd_pos < cmd_len) {
					cmd_pos++;
					esc('C');
				}
				break;

			case KEY_ENTER:
				mprintf("\n");
				state = SH_EXEC;
				break;
190

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
			case KEY_DELETE:
				if (cmd_pos != cmd_len) {
					delete(cmd_pos);
					esc('P');
				}
				break;

			case KEY_BACKSPACE:
				if (cmd_pos > 0) {
					esc('D');
					esc('P');
					delete(cmd_pos - 1);
					cmd_pos--;
				}
				break;
206

207 208 209 210 211 212 213 214
			case '\t':
				break;

			default:
				if (!(current_key & ESCAPE_FLAG)
				    && insert(current_key)) {
					esc('@');
					mprintf("%c", current_key);
215
				}
216 217
				break;

218
			}
219 220 221
			current_key = 0;
		}
		break;
222

223 224 225 226 227
	case SH_EXEC:
		cmd_buf[cmd_len] = 0;
		_shell_exec();
		state = SH_PROMPT;
		break;
228 229
	}
}
230

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
const char *fromhex(const char *hex, int *v)
{
	int o = 0;

	for (; *hex; ++hex) {
		if (*hex >= '0' && *hex <= '9') {
			o = (o << 4) + (*hex - '0');
		} else if (*hex >= 'A' && *hex <= 'F') {
			o = (o << 4) + (*hex - 'A') + 10;
		} else if (*hex >= 'a' && *hex <= 'f') {
			o = (o << 4) + (*hex - 'a') + 10;
		} else {
			break;
		}
	}

	*v = o;
	return hex;
249 250
}

251 252 253
const char *fromdec(const char *dec, int *v)
{
	int o = 0;
254

255 256 257 258 259 260 261
	for (; *dec; ++dec) {
		if (*dec >= '0' && *dec <= '9') {
			o = (o * 10) + (*dec - '0');
		} else {
			break;
		}
	}
262

263 264
	*v = o;
	return dec;
265
}
266 267 268

int shell_boot_script(void)
{
269
	uint8_t next = 0;
270

271
	//first check if EEPROM is really there
272
	eeprom_present(WRPC_FMC_I2C, FMC_EEPROM_ADR);
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
	if (!has_eeprom)
		return -1;

	while (1) {
		cmd_len = eeprom_init_readcmd(WRPC_FMC_I2C, FMC_EEPROM_ADR,
					      cmd_buf, SH_MAX_LINE_LEN, next);
		if (cmd_len <= 0) {
			if (next == 0)
				mprintf("Empty init script...\n");
			break;
		}
		cmd_buf[cmd_len - 1] = 0;

		mprintf("executing: %s\n", cmd_buf);
		_shell_exec();
		next = 1;
	}

	return 0;
292
}