File: [local] / sys / arch / zaurus / stand / zboot / cmd.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:08:50 2008 UTC (16 years, 6 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: cmd.c,v 1.3 2007/03/21 03:29:05 tedu Exp $ */
/*
* Copyright (c) 1997-1999 Michael Shalayeff
* All rights reserved.
*
* 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 AUTHOR ``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 REGENTS 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.
*/
#include <sys/param.h>
#include <sys/reboot.h>
#ifdef REGRESS
#include <sys/stat.h>
#include <errno.h>
#else
#include <libsa.h>
#include <lib/libkern/funcs.h>
#endif
#include <stand/boot/cmd.h>
#define CTRL(c) ((c)&0x1f)
static int Xboot(void);
static int Xclear(void);
static int Xecho(void);
static int Xhelp(void);
static int Xls(void);
static int Xnop(void);
static int Xreboot(void);
static int Xstty(void);
static int Xtime(void);
#ifdef MACHINE_CMD
static int Xmachine(void);
extern const struct cmd_table MACHINE_CMD[];
#endif
extern int Xset(void);
extern int Xenv(void);
extern const struct cmd_table cmd_set[];
const struct cmd_table cmd_table[] = {
{"#", CMDT_CMD, Xnop}, /* XXX must be first */
{"boot", CMDT_CMD, Xboot},
{"clear", CMDT_CMD, Xclear},
{"echo", CMDT_CMD, Xecho},
{"env", CMDT_CMD, Xenv},
{"help", CMDT_CMD, Xhelp},
{"ls", CMDT_CMD, Xls},
#ifdef MACHINE_CMD
{"machine",CMDT_MDC, Xmachine},
#endif
{"reboot", CMDT_CMD, Xreboot},
{"set", CMDT_SET, Xset},
{"stty", CMDT_CMD, Xstty},
{"time", CMDT_CMD, Xtime},
{NULL, 0},
};
static void ls(char *, struct stat *);
static int readline(char *, size_t, int);
char *nextword(char *);
static char *whatcmd(const struct cmd_table **ct, char *);
static char *qualify(char *);
char cmd_buf[CMD_BUFF_SIZE];
int
getcmd(void)
{
cmd.cmd = NULL;
if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout))
cmd.cmd = cmd_table;
return docmd();
}
int
read_conf(void)
{
#ifndef INSECURE
struct stat sb;
#endif
int fd, rc = 0;
if ((fd = open(qualify(cmd.conf), 0)) < 0) {
if (errno != ENOENT && errno != ENXIO) {
printf("open(%s): %s\n", cmd.path, strerror(errno));
return 0;
}
return -1;
}
#ifndef INSECURE
(void) fstat(fd, &sb);
if (sb.st_uid || (sb.st_mode & 2)) {
printf("non-secure %s, will not proceed\n", cmd.path);
close(fd);
return -1;
}
#endif
do {
char *p = cmd_buf;
cmd.cmd = NULL;
do {
rc = read(fd, p, 1);
} while (rc > 0 && *p++ != '\n' &&
(p-cmd_buf) < sizeof(cmd_buf));
if (rc < 0) { /* Error from read() */
printf("%s: %s\n", cmd.path, strerror(errno));
break;
}
if (rc == 0) { /* eof from read() */
if (p != cmd_buf) { /* Line w/o trailing \n */
*p = '\0';
rc = docmd();
break;
}
} else { /* rc > 0, read a char */
p--; /* Get back to last character */
if (*p != '\n') { /* Line was too long */
printf("%s: line too long\n", cmd.path);
/* Don't want to run the truncated command */
rc = -1;
}
*p = '\0';
}
} while (rc > 0 && !(rc = docmd()));
close(fd);
return rc;
}
int
docmd(void)
{
char *p = NULL;
const struct cmd_table *ct = cmd_table, *cs;
cmd.argc = 1;
if (cmd.cmd == NULL) {
/* command */
for (p = cmd_buf; *p == ' ' || *p == '\t'; p++)
;
if (*p == '#' || *p == '\0') { /* comment or empty string */
#ifdef DEBUG
printf("rem\n");
#endif
return 0;
}
ct = cmd_table;
cs = NULL;
cmd.argv[cmd.argc] = p; /* in case it's shortcut boot */
p = whatcmd(&ct, p);
if (ct == NULL) {
cmd.argc++;
ct = cmd_table;
} else if (ct->cmd_type == CMDT_SET && p != NULL) {
cs = cmd_set;
#ifdef MACHINE_CMD
} else if (ct->cmd_type == CMDT_MDC && p != NULL) {
cs = MACHINE_CMD;
#endif
}
if (cs != NULL) {
p = whatcmd(&cs, p);
if (cs == NULL) {
printf("%s: syntax error\n", ct->cmd_name);
return 0;
}
ct = cs;
}
cmd.cmd = ct;
}
cmd.argv[0] = ct->cmd_name;
while (p && cmd.argc+1 < sizeof(cmd.argv) / sizeof(cmd.argv[0])) {
cmd.argv[cmd.argc++] = p;
p = nextword(p);
}
cmd.argv[cmd.argc] = NULL;
#ifdef REGRESS
printf("%s %s\n", cmd.argv[0],
(cmd.argv[1] == NULL) ? "(null)" : cmd.argv[1]);
#else
return (*cmd.cmd->cmd_exec)();
#endif
}
static char *
whatcmd(const struct cmd_table **ct, char *p)
{
char *q;
int l;
q = nextword(p);
for (l = 0; p[l]; l++)
;
while ((*ct)->cmd_name != NULL && strncmp(p, (*ct)->cmd_name, l))
(*ct)++;
if ((*ct)->cmd_name == NULL)
*ct = NULL;
return q;
}
static int
readline(char *buf, size_t n, int to)
{
#ifdef DEBUG
extern int debug;
#endif
char *p = buf, ch;
/* Only do timeout if greater than 0 */
if (to > 0) {
u_long i = 0;
time_t tt = getsecs() + to;
#ifdef DEBUG
if (debug > 2)
printf ("readline: timeout(%d) at %u\n", to, tt);
#endif
/* check for timeout expiration less often
(for some very constrained archs) */
while (!cnischar())
if (!(i++ % 1000) && (getsecs() >= tt))
break;
if (!cnischar()) {
strlcpy(buf, "boot", 5);
putchar('\n');
return strlen(buf);
}
} else
while (!cnischar())
;
/* User has typed something. Turn off timeouts. */
cmd.timeout = 0;
while (1) {
switch ((ch = getchar())) {
case CTRL('u'):
while (p > buf) {
putchar('\177');
p--;
}
continue;
case '\n':
case '\r':
p[1] = *p = '\0';
break;
case '\b':
case '\177':
if (p > buf) {
putchar('\177');
p--;
}
continue;
default:
if (p - buf < n-1)
*p++ = ch;
else {
putchar('\007');
putchar('\177');
}
continue;
}
break;
}
return p - buf;
}
/*
* Search for spaces/tabs after the current word. If found, \0 the
* first one. Then pass a pointer to the first character of the
* next word, or NULL if there is no next word.
*/
char *
nextword(char *p)
{
/* skip blanks */
while (*p && *p != '\t' && *p != ' ')
p++;
if (*p) {
*p++ = '\0';
while (*p == '\t' || *p == ' ')
p++;
}
if (*p == '\0')
p = NULL;
return p;
}
static void
print_help(const struct cmd_table *ct)
{
for (; ct->cmd_name != NULL; ct++)
printf(" %s", ct->cmd_name);
putchar('\n');
}
static int
Xhelp(void)
{
printf("commands:");
print_help(cmd_table);
#ifdef MACHINE_CMD
return Xmachine();
#else
return 0;
#endif
}
#ifdef MACHINE_CMD
static int
Xmachine(void)
{
printf("machine:");
print_help(MACHINE_CMD);
return 0;
}
#endif
static int
Xclear(void)
{
int i;
printf("\033[H\033[J");
return 0;
}
static int
Xecho(void)
{
int i;
for (i = 1; i < cmd.argc; i++)
printf("%s ", cmd.argv[i]);
putchar('\n');
return 0;
}
static int
Xstty(void)
{
int sp;
char *cp;
dev_t dev;
if (cmd.argc == 1) {
printf("%s speed is %d\n", ttyname(0), cnspeed(0, -1));
return 0;
}
dev = ttydev(cmd.argv[1]);
if (dev == NODEV) {
printf("%s not a console device\n", cmd.argv[1]);
return 0;
}
if (cmd.argc == 2)
printf("%s speed is %d\n", cmd.argv[1],
cnspeed(dev, -1));
else {
sp = 0;
for (cp = cmd.argv[2]; isdigit(*cp); cp++)
sp = sp * 10 + (*cp - '0');
cnspeed(dev, sp);
}
return 0;
}
static int
Xtime(void)
{
time_t tt = getsecs();
if (cmd.argc == 1)
printf(ctime(&tt));
return 0;
}
static int
Xls(void)
{
struct stat sb;
char *p;
int fd;
if (stat(qualify((cmd.argv[1]? cmd.argv[1]: "/.")), &sb) < 0) {
printf("stat(%s): %s\n", cmd.path, strerror(errno));
return 0;
}
if ((sb.st_mode & S_IFMT) != S_IFDIR)
ls(cmd.path, &sb);
else {
if ((fd = opendir(cmd.path)) < 0) {
printf("opendir(%s): %s\n", cmd.path,
strerror(errno));
return 0;
}
/* no strlen in lib !!! */
for (p = cmd.path; *p; p++)
;
*p++ = '/';
*p = '\0';
while (readdir(fd, p) >= 0) {
if (stat(cmd.path, &sb) < 0)
printf("stat(%s): %s\n", cmd.path,
strerror(errno));
else
ls(p, &sb);
}
closedir (fd);
}
return 0;
}
#define lsrwx(mode,s) \
putchar ((mode) & S_IROTH? 'r' : '-'); \
putchar ((mode) & S_IWOTH? 'w' : '-'); \
putchar ((mode) & S_IXOTH? *(s): (s)[1]);
static void
ls(char *name, struct stat *sb)
{
putchar("-fc-d-b---l-s-w-"[(sb->st_mode & S_IFMT) >> 12]);
lsrwx(sb->st_mode >> 6, (sb->st_mode & S_ISUID? "sS" : "x-"));
lsrwx(sb->st_mode >> 3, (sb->st_mode & S_ISGID? "sS" : "x-"));
lsrwx(sb->st_mode , (sb->st_mode & S_ISTXT? "tT" : "x-"));
printf (" %u,%u\t%lu\t%s\n", sb->st_uid, sb->st_gid,
(u_long)sb->st_size, name);
}
#undef lsrwx
int doboot = 1;
static int
Xnop(void)
{
if (doboot) {
doboot = 0;
return (Xboot());
}
return 0;
}
static int
Xboot(void)
{
if (cmd.argc > 1 && cmd.argv[1][0] != '-') {
qualify((cmd.argv[1]? cmd.argv[1]: cmd.image));
if (bootparse(2))
return 0;
} else {
if (bootparse(1))
return 0;
snprintf(cmd.path, sizeof cmd.path, "%s:%s",
cmd.bootdev, cmd.image);
}
return 1;
}
/*
* Qualifies the path adding necessary dev
*/
static char *
qualify(char *name)
{
char *p;
for (p = name; *p; p++)
if (*p == ':')
break;
if (*p == ':')
strlcpy(cmd.path, name, sizeof(cmd.path));
else
snprintf(cmd.path, sizeof cmd.path, "%s:%s",
cmd.bootdev, name);
return cmd.path;
}
static int
Xreboot(void)
{
printf("Rebooting...\n");
exit();
return 0; /* just in case */
}