summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:02:13 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:02:13 +0200
commit4b07af6730d2811363f158f5175138116038f7b9 (patch)
tree206044270884f80204a2da69e02ca3b6f5803185 /lib
parentd08c60e9d77dc0f83946cd702d383451865e66dd (diff)
downloadbarebox-4b07af6730d2811363f158f5175138116038f7b9.tar.gz
barebox-4b07af6730d2811363f158f5175138116038f7b9.tar.xz
svn_rev_643
structure cleanup
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig19
-rw-r--r--lib/Makefile12
-rw-r--r--lib/crc16.c107
-rw-r--r--lib/getopt.c143
-rw-r--r--lib/readkey.c58
-rw-r--r--lib/readline.c302
-rw-r--r--lib/readline_simple.c142
-rw-r--r--lib/xfuncs.c30
8 files changed, 809 insertions, 4 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
new file mode 100644
index 0000000000..ac86758786
--- /dev/null
+++ b/lib/Kconfig
@@ -0,0 +1,19 @@
+config ZLIB
+ bool
+
+config BZLIB
+ bool
+
+config CRC32
+ bool
+
+config DYNAMIC_CRC_TABLE
+ bool
+ prompt "Generate the crc32 table dynamically"
+ default y
+ help
+ Saying yes to this option saves around 800 bytes of binary size.
+ If unsure say yes.
+
+config CRC16
+ bool
diff --git a/lib/Makefile b/lib/Makefile
index f42fcdb1de..3e11016668 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,6 +1,3 @@
-obj-$(CONFIG_BZLIB) += bzlib.o bzlib_crctable.o bzlib_decompress.o bzlib_huffman.o bzlib_randtable.o
-obj-$(CONFIG_ZLIB) += zlib.o
-obj-y += crc32.o
obj-y += ctype.o
obj-y += display_options.o
obj-y += ldiv.o
@@ -11,4 +8,11 @@ obj-y += misc.o
obj-y += driver.o
obj-y += parameter.o
obj-y += global.o
-
+obj-y += xfuncs.o
+obj-y += getopt.o
+obj-y += readkey.o
+obj-$(CONFIG_BZLIB) += bzlib.o bzlib_crctable.o bzlib_decompress.o bzlib_huffman.o bzlib_randtable.o
+obj-$(CONFIG_ZLIB) += zlib.o
+obj-$(CONFIG_CRC32) += crc32.o
+obj-$(CONFIG_CMDLINE_EDITING) += readline.o
+obj-$(CONFIG_SIMPLE_READLINE) += readline_simple.o
diff --git a/lib/crc16.c b/lib/crc16.c
new file mode 100644
index 0000000000..6904365e59
--- /dev/null
+++ b/lib/crc16.c
@@ -0,0 +1,107 @@
+/*
+ *==========================================================================
+ *
+ * crc16.c
+ *
+ * 16 bit CRC with polynomial x^16+x^12+x^5+1
+ *
+ *==========================================================================
+ *####ECOSGPLCOPYRIGHTBEGIN####
+ * -------------------------------------------
+ * This file is part of eCos, the Embedded Configurable Operating System.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+ * Copyright (C) 2002 Gary Thomas
+ *
+ * eCos is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 or (at your option) any later version.
+ *
+ * eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with eCos; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+ *
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ *
+ * Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+ * at http: *sources.redhat.com/ecos/ecos-license/
+ * -------------------------------------------
+ *####ECOSGPLCOPYRIGHTEND####
+ *==========================================================================
+ *#####DESCRIPTIONBEGIN####
+ *
+ * Author(s): gthomas
+ * Contributors: gthomas,asl
+ * Date: 2001-01-31
+ * Purpose:
+ * Description:
+ *
+ * This code is part of eCos (tm).
+ *
+ *####DESCRIPTIONEND####
+ *
+ *==========================================================================
+ */
+
+#include "crc.h"
+
+/* Table of CRC constants - implements x^16+x^12+x^5+1 */
+static const uint16_t crc16_tab[] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
+};
+
+uint16_t
+cyg_crc16(unsigned char *buf, int len)
+{
+ int i;
+ uint16_t cksum;
+
+ cksum = 0;
+ for (i = 0; i < len; i++) {
+ cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xFF] ^ (cksum << 8);
+ }
+ return cksum;
+}
diff --git a/lib/getopt.c b/lib/getopt.c
new file mode 100644
index 0000000000..c054e1365f
--- /dev/null
+++ b/lib/getopt.c
@@ -0,0 +1,143 @@
+/*
+ * getopt.c - a simple getopt(3) implementation. See getopt.h for explanation.
+ *
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <getopt.h>
+
+int opterr = 1;
+int optind = 1;
+int optopt;
+char *optarg;
+
+static int optindex = 1; /* option index in the current argv[] element */
+static int nonopts = 0; /* number of nonopts found */
+
+void getopt_reset(void)
+{
+ optind = opterr = optindex = 1;
+ nonopts = 0;
+}
+
+int getopt(int argc, char *argv[], char *optstring)
+{
+ char curopt; /* current option character */
+ char *curoptp; /* pointer to the current option in optstring */
+
+ while(1) {
+// printf("optindex: %d nonopts: %d optind: %d\n", optindex, nonopts, optind);
+
+ /* first put nonopts to the end */
+ while (optind + nonopts < argc && *argv[optind] != '-') {
+ int i;
+ char *tmp;
+
+ nonopts++;
+ tmp = argv[optind];
+ for (i = optind; i + 1 < argc; i++)
+ argv[i] = argv[i + 1];
+ argv[argc - 1] = tmp;
+ }
+
+ if (optind + nonopts >= argc)
+ return -1;
+
+ /* We have found an option */
+ curopt = argv[optind][optindex];
+ if (curopt)
+ break;
+ /* no more options in current argv[] element. Start
+ * over with looking for nonopts
+ */
+ optind++;
+ optindex = 1;
+ }
+
+ /* look up current option in optstring */
+ curoptp = strchr(optstring, curopt);
+
+ if (!curoptp) {
+ if (opterr)
+ printf("%s: invalid option -- %c\n", argv[0], curopt);
+ optopt = curopt;
+ optindex++;
+ return '?';
+ }
+
+ if (*(curoptp + 1) != ':') {
+ /* option with no argument. Just return it */
+ optarg = NULL;
+ optindex++;
+ return curopt;
+ }
+
+ if (*(curoptp + 1) && *(curoptp + 2) == ':') {
+ /* optional argument */
+ if (argv[optind][optindex + 1]) {
+ /* optional argument with directly following optarg */
+ optarg = argv[optind] + optindex + 1;
+ optindex = 1;
+ optind++;
+ return curopt;
+ }
+ if (optind + nonopts + 1 == argc) {
+ /* We are at the last argv[] element */
+ optarg = NULL;
+ optind++;
+ return curopt;
+ }
+ if (*argv[optind + 1] != '-') {
+ /* optional argument with optarg in next argv[] element
+ */
+ optind++;
+ optarg = argv[optind];
+ optind++;
+ optindex = 1;
+ return curopt;
+ }
+
+ /* no optional argument found */
+ optarg = NULL;
+ optindex = 1;
+ optind++;
+ return curopt;
+ }
+
+ if (argv[optind][optindex + 1]) {
+ /* required argument with directly following optarg */
+ optarg = argv[optind] + optindex + 1;
+ optind++;
+ optindex = 1;
+ return curopt;
+ }
+
+ optind++;
+ optindex = 1;
+
+ if (optind + nonopts >= argc || argv[optind][0] == '-') {
+ if (opterr)
+ printf("option requires an argument -- %c\n",
+ curopt);
+ optopt = curopt;
+ return ':';
+ }
+
+ optarg = argv[optind];
+ optind++;
+ return curopt;
+}
diff --git a/lib/readkey.c b/lib/readkey.c
new file mode 100644
index 0000000000..d4e86ed3eb
--- /dev/null
+++ b/lib/readkey.c
@@ -0,0 +1,58 @@
+
+#include <common.h>
+#include <linux/ctype.h>
+#include <readkey.h>
+
+struct esc_cmds {
+ const char *seq;
+ char val;
+};
+
+static const struct esc_cmds esccmds[] = {
+ {"OA", KEY_UP}, // cursor key Up
+ {"OB", KEY_DOWN}, // cursor key Down
+ {"OC", KEY_RIGHT}, // Cursor Key Right
+ {"OD", KEY_LEFT}, // cursor key Left
+ {"OH", KEY_HOME}, // Cursor Key Home
+ {"OF", KEY_END}, // Cursor Key End
+ {"[A", KEY_UP}, // cursor key Up
+ {"[B", KEY_DOWN}, // cursor key Down
+ {"[C", KEY_RIGHT}, // Cursor Key Right
+ {"[D", KEY_LEFT}, // cursor key Left
+ {"[H", KEY_HOME}, // Cursor Key Home
+ {"[F", KEY_END}, // Cursor Key End
+ {"[1~", KEY_HOME}, // Cursor Key Home
+ {"[2~", KEY_INSERT}, // Cursor Key Insert
+ {"[3~", KEY_DEL}, // Cursor Key Delete
+ {"[4~", KEY_END}, // Cursor Key End
+ {"[5~", KEY_PAGEUP}, // Cursor Key Page Up
+ {"[6~", KEY_PAGEDOWN},// Cursor Key Page Down
+};
+
+char read_key(void)
+{
+ char c;
+ char esc[5];
+ c = getc();
+
+ if (c == 27) {
+ int i = 0;
+ esc[i++] = getc();
+ esc[i++] = getc();
+ if (isdigit(esc[1])) {
+ while(1) {
+ esc[i] = getc();
+ if (esc[i++] == '~')
+ break;
+ }
+ }
+ esc[i] = 0;
+ for (i = 0; i < 18; i++){
+ if (!strcmp(esc, esccmds[i].seq))
+ return esccmds[i].val;
+ }
+ return -1;
+ }
+ return c;
+}
+
diff --git a/lib/readline.c b/lib/readline.c
new file mode 100644
index 0000000000..ab0a46a8c3
--- /dev/null
+++ b/lib/readline.c
@@ -0,0 +1,302 @@
+#include <common.h>
+#include <readkey.h>
+#include <init.h>
+#include <xfuncs.h>
+
+extern char console_buffer[CONFIG_CBSIZE]; /* console I/O buffer */
+
+/*
+ * cmdline-editing related codes from vivi.
+ * Author: Janghoon Lyu <nandy@mizi.com>
+ */
+
+#define putnstr(str,n) do { \
+ printf ("%.*s", n, str); \
+ } while (0)
+
+#define MAX_CMDBUF_SIZE 256
+
+#define CTL_BACKSPACE ('\b')
+#define DEL ((char)255)
+#define DEL7 ((char)127)
+#define CREAD_HIST_CHAR ('!')
+
+#define getcmd_putch(ch) putc(ch)
+#define getcmd_getch() getc()
+#define getcmd_cbeep() getcmd_putch('\a')
+
+#define HIST_MAX 20
+#define HIST_SIZE MAX_CMDBUF_SIZE
+
+static int hist_max = 0;
+static int hist_add_idx = 0;
+static int hist_cur = -1;
+unsigned hist_num = 0;
+
+char* hist_list[HIST_MAX];
+char hist_lines[HIST_MAX][HIST_SIZE];
+
+#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
+
+static int hist_init(void)
+{
+ int i;
+
+ hist_max = 0;
+ hist_add_idx = 0;
+ hist_cur = -1;
+ hist_num = 0;
+
+ for (i = 0; i < HIST_MAX; i++) {
+ hist_list[i] = hist_lines[i];
+ hist_list[i][0] = '\0';
+ }
+ return 0;
+}
+
+postcore_initcall(hist_init);
+
+static void cread_add_to_hist(char *line)
+{
+ strcpy(hist_list[hist_add_idx], line);
+
+ if (++hist_add_idx >= HIST_MAX)
+ hist_add_idx = 0;
+
+ if (hist_add_idx > hist_max)
+ hist_max = hist_add_idx;
+
+ hist_num++;
+}
+
+static char* hist_prev(void)
+{
+ char *ret;
+ int old_cur;
+
+ if (hist_cur < 0)
+ return NULL;
+
+ old_cur = hist_cur;
+ if (--hist_cur < 0)
+ hist_cur = hist_max;
+
+ if (hist_cur == hist_add_idx) {
+ hist_cur = old_cur;
+ ret = NULL;
+ } else
+ ret = hist_list[hist_cur];
+
+ return (ret);
+}
+
+static char* hist_next(void)
+{
+ char *ret;
+
+ if (hist_cur < 0)
+ return NULL;
+
+ if (hist_cur == hist_add_idx)
+ return NULL;
+
+ if (++hist_cur > hist_max)
+ hist_cur = 0;
+
+ if (hist_cur == hist_add_idx) {
+ ret = "";
+ } else
+ ret = hist_list[hist_cur];
+
+ return (ret);
+}
+
+#define BEGINNING_OF_LINE() { \
+ while (num) { \
+ getcmd_putch(CTL_BACKSPACE); \
+ num--; \
+ } \
+}
+
+#define ERASE_TO_EOL() { \
+ if (num < eol_num) { \
+ int tmp; \
+ for (tmp = num; tmp < eol_num; tmp++) \
+ getcmd_putch(' '); \
+ while (tmp-- > num) \
+ getcmd_putch(CTL_BACKSPACE); \
+ eol_num = num; \
+ } \
+}
+
+#define REFRESH_TO_EOL() { \
+ if (num < eol_num) { \
+ wlen = eol_num - num; \
+ putnstr(buf + num, wlen); \
+ num = eol_num; \
+ } \
+}
+
+static void cread_add_char(char ichar, int insert, unsigned long *num,
+ unsigned long *eol_num, char *buf, unsigned long len)
+{
+ unsigned long wlen;
+
+ /* room ??? */
+ if (insert || *num == *eol_num) {
+ if (*eol_num > len - 1) {
+ getcmd_cbeep();
+ return;
+ }
+ (*eol_num)++;
+ }
+
+ if (insert) {
+ wlen = *eol_num - *num;
+ if (wlen > 1) {
+ memmove(&buf[*num+1], &buf[*num], wlen-1);
+ }
+
+ buf[*num] = ichar;
+ putnstr(buf + *num, wlen);
+ (*num)++;
+ while (--wlen) {
+ getcmd_putch(CTL_BACKSPACE);
+ }
+ } else {
+ /* echo the character */
+ wlen = 1;
+ buf[*num] = ichar;
+ putnstr(buf + *num, wlen);
+ (*num)++;
+ }
+}
+
+int readline(const char *prompt, char *buf, int len)
+{
+ unsigned long num = 0;
+ unsigned long eol_num = 0;
+ unsigned long rlen;
+ unsigned long wlen;
+ char ichar;
+ int insert = 1;
+ int rc = 0;
+
+ puts (prompt);
+
+ while (1) {
+ rlen = 1;
+ ichar = read_key();
+
+ if ((ichar == '\n') || (ichar == '\r')) {
+ putc('\n');
+ break;
+ }
+
+ switch (ichar) {
+ case KEY_HOME:
+ BEGINNING_OF_LINE();
+ break;
+ case CTL_CH('c'): /* ^C - break */
+ *buf = 0; /* discard input */
+ return -1;
+ case KEY_RIGHT:
+ if (num < eol_num) {
+ getcmd_putch(buf[num]);
+ num++;
+ }
+ break;
+ case KEY_LEFT:
+ if (num) {
+ getcmd_putch(CTL_BACKSPACE);
+ num--;
+ }
+ break;
+ case CTL_CH('d'):
+ if (num < eol_num) {
+ wlen = eol_num - num - 1;
+ if (wlen) {
+ memmove(&buf[num], &buf[num+1], wlen);
+ putnstr(buf + num, wlen);
+ }
+
+ getcmd_putch(' ');
+ do {
+ getcmd_putch(CTL_BACKSPACE);
+ } while (wlen--);
+ eol_num--;
+ }
+ break;
+ case KEY_ERASE_TO_EOL:
+ ERASE_TO_EOL();
+ break;
+ case KEY_REFRESH_TO_EOL:
+ case KEY_END:
+ REFRESH_TO_EOL();
+ break;
+ case KEY_INSERT:
+ insert = !insert;
+ break;
+ case KEY_ERASE_LINE:
+ BEGINNING_OF_LINE();
+ ERASE_TO_EOL();
+ break;
+ case DEL:
+ case KEY_DEL7:
+ case 8:
+ if (num) {
+ wlen = eol_num - num;
+ num--;
+ memmove(&buf[num], &buf[num+1], wlen);
+ getcmd_putch(CTL_BACKSPACE);
+ putnstr(buf + num, wlen);
+ getcmd_putch(' ');
+ do {
+ getcmd_putch(CTL_BACKSPACE);
+ } while (wlen--);
+ eol_num--;
+ }
+ break;
+ case KEY_UP:
+ case KEY_DOWN:
+ {
+ char * hline;
+
+ if (ichar == KEY_UP)
+ hline = hist_prev();
+ else
+ hline = hist_next();
+
+ if (!hline) {
+ getcmd_cbeep();
+ continue;
+ }
+
+ /* nuke the current line */
+ /* first, go home */
+ BEGINNING_OF_LINE();
+
+ /* erase to end of line */
+ ERASE_TO_EOL();
+
+ /* copy new line into place and display */
+ strcpy(buf, hline);
+ eol_num = strlen(buf);
+ REFRESH_TO_EOL();
+ continue;
+ }
+ default:
+ cread_add_char(ichar, insert, &num, &eol_num, buf, len);
+ break;
+ }
+ }
+ len = eol_num;
+ buf[eol_num] = '\0'; /* lose the newline */
+
+ if (buf[0] && buf[0] != CREAD_HIST_CHAR)
+ cread_add_to_hist(buf);
+ hist_cur = hist_add_idx;
+
+ return rc < 0 ? rc : len;
+}
+
diff --git a/lib/readline_simple.c b/lib/readline_simple.c
new file mode 100644
index 0000000000..7675103ea1
--- /dev/null
+++ b/lib/readline_simple.c
@@ -0,0 +1,142 @@
+#include <common.h>
+#include <watchdog.h>
+
+static char erase_seq[] = "\b \b"; /* erase sequence */
+static char tab_seq[] = " "; /* used to expand TABs */
+
+static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
+{
+ char *s;
+
+ if (*np == 0) {
+ return (p);
+ }
+
+ if (*(--p) == '\t') { /* will retype the whole line */
+ while (*colp > plen) {
+ puts (erase_seq);
+ (*colp)--;
+ }
+ for (s=buffer; s<p; ++s) {
+ if (*s == '\t') {
+ puts (tab_seq+((*colp) & 07));
+ *colp += 8 - ((*colp) & 07);
+ } else {
+ ++(*colp);
+ putc (*s);
+ }
+ }
+ } else {
+ puts (erase_seq);
+ (*colp)--;
+ }
+ (*np)--;
+ return (p);
+}
+
+/*
+ * Prompt for input and read a line.
+ * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
+ * time out when time goes past endtime (timebase time in ticks).
+ * Return: number of read characters
+ * -1 if break
+ * -2 if timed out
+ */
+int readline (const char *prompt, char *line, int len)
+{
+ char *p = line;
+ int n = 0; /* buffer index */
+ int plen = 0; /* prompt length */
+ int col; /* output column cnt */
+ char c;
+
+ /* print prompt */
+ if (prompt) {
+ plen = strlen (prompt);
+ puts (prompt);
+ }
+ col = plen;
+
+ for (;;) {
+#ifdef CONFIG_BOOT_RETRY_TIME
+ while (!tstc()) { /* while no incoming data */
+ if (retry_time >= 0 && get_ticks() > endtime)
+ return (-2); /* timed out */
+ }
+#endif
+ WATCHDOG_RESET(); /* Trigger watchdog, if needed */
+
+#ifdef CONFIG_SHOW_ACTIVITY
+ while (!tstc()) {
+ extern void show_activity(int arg);
+ show_activity(0);
+ }
+#endif
+ c = getc();
+
+ /*
+ * Special character handling
+ */
+ switch (c) {
+ case '\r': /* Enter */
+ case '\n':
+ *p = '\0';
+ puts ("\r\n");
+ return (p - line);
+
+ case '\0': /* nul */
+ continue;
+
+ case 0x03: /* ^C - break */
+ line[0] = '\0'; /* discard input */
+ return (-1);
+
+ case 0x15: /* ^U - erase line */
+ while (col > plen) {
+ puts (erase_seq);
+ --col;
+ }
+ p = line;
+ n = 0;
+ continue;
+
+ case 0x17: /* ^W - erase word */
+ p=delete_char(line, p, &col, &n, plen);
+ while ((n > 0) && (*p != ' ')) {
+ p=delete_char(line, p, &col, &n, plen);
+ }
+ continue;
+
+ case 0x08: /* ^H - backspace */
+ case 0x7F: /* DEL - backspace */
+ p=delete_char(line, p, &col, &n, plen);
+ continue;
+
+ default:
+ /*
+ * Must be a normal character then
+ */
+ if (n < CONFIG_CBSIZE-2) {
+ if (c == '\t') { /* expand TABs */
+#ifdef CONFIG_AUTO_COMPLETE
+ /* if auto completion triggered just continue */
+ *p = '\0';
+ if (cmd_auto_complete(prompt, line, &n, &col)) {
+ p = line + n; /* reset */
+ continue;
+ }
+#endif
+ puts (tab_seq+(col&07));
+ col += 8 - (col&07);
+ } else {
+ ++col; /* echo input */
+ putc (c);
+ }
+ *p++ = c;
+ ++n;
+ } else { /* Buffer full */
+ putc ('\a');
+ }
+ }
+ }
+}
diff --git a/lib/xfuncs.c b/lib/xfuncs.c
new file mode 100644
index 0000000000..12b12e28f4
--- /dev/null
+++ b/lib/xfuncs.c
@@ -0,0 +1,30 @@
+
+#include <common.h>
+#include <malloc.h>
+
+void *xmalloc(size_t size)
+{
+ void *p = NULL;
+
+ if (!(p = malloc(size)))
+ panic("ERROR: out of memory\n");
+
+ return p;
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+ void *p = NULL;
+
+ if (!(p = realloc(ptr, size)))
+ panic("ERROR: out of memory\n");
+
+ return p;
+}
+
+void *xzalloc(size_t size)
+{
+ void *ptr = xmalloc(size);
+ memset(ptr, 0, size);
+ return ptr;
+}