* Implement new mechanism to export U-Boot's functions to standalone
  applications: instead of using (PPC-specific) system calls we now
  use a jump table; please see doc/README.standalone for details

* Patch by Dave Westwood, 24 Jul 2003:
  added support for Unity OS (a proprietary OS)
diff --git a/common/Makefile b/common/Makefile
index 3aa9b65..d144bef 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -42,7 +42,7 @@
 	  cmd_reginfo.o cmd_scsi.o cmd_spi.o cmd_usb.o cmd_vfd.o \
 	  command.o console.o devices.o dlmalloc.o docecc.o \
 	  environment.o env_common.o \
-	  env_flash.o env_eeprom.o env_nvram.o env_nowhere.o \
+	  env_flash.o env_eeprom.o env_nvram.o env_nowhere.o exports.o \
 	  flash.o fpga.o \
 	  hush.o kgdb.o lists.o miiphybb.o miiphyutil.o \
 	  s_record.o soft_i2c.o soft_spi.o spartan2.o \
diff --git a/common/cmd_boot.c b/common/cmd_boot.c
index fe8025d..b2f0331 100644
--- a/common/cmd_boot.c
+++ b/common/cmd_boot.c
@@ -27,13 +27,15 @@
 #include <common.h>
 #include <command.h>
 #include <net.h>
-#include <syscall.h>
 
 
 /* -------------------------------------------------------------------- */
 
 int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
+#if defined(CONFIG_I386)
+	DECLARE_GLOBAL_DATA_PTR;
+#endif
 	ulong	addr, rc;
 	int     rcode = 0;
 
@@ -50,6 +52,13 @@
 	 * pass address parameter as argv[0] (aka command name),
 	 * and all remaining args
 	 */
+#if defined(CONFIG_I386)
+	/*
+	 * x86 does not use a dedicated register to pass the pointer
+	 * to the global_data
+	 */
+	argv[0] = (char *)gd;
+#endif
 	rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);
 	if (rc != 0) rcode = 1;
 
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index d1d03e3..1343659 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -80,6 +80,13 @@
 #if (CONFIG_COMMANDS & CFG_CMD_IMI)
 static int image_info (unsigned long addr);
 #endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_IMLS)
+#include <flash.h>
+extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
+static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+#endif
+
 static void print_type (image_header_t *hdr);
 
 #ifdef __I386__
@@ -961,6 +968,56 @@
 
 #endif	/* CFG_CMD_IMI */
 
+#if (CONFIG_COMMANDS & CFG_CMD_IMLS)
+/*-----------------------------------------------------------------------
+ * List all images found in flash.
+ */
+int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	flash_info_t *info;
+	int i, j;
+	image_header_t *hdr;
+	ulong checksum;
+
+	for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
+		if (info->flash_id == FLASH_UNKNOWN)
+			goto next_bank;
+		for (j=0; j<CFG_MAX_FLASH_SECT; ++j) {
+
+			if (!(hdr=(image_header_t *)info->start[j]) ||
+			    (ntohl(hdr->ih_magic) != IH_MAGIC))
+				goto next_sector;
+
+			/* Copy header so we can blank CRC field for re-calculation */
+			memmove (&header, (char *)hdr, sizeof(image_header_t));
+
+			checksum = ntohl(header.ih_hcrc);
+			header.ih_hcrc = 0;
+
+			if (crc32 (0, (char *)&header, sizeof(image_header_t))
+			    != checksum)
+				goto next_sector;
+
+			printf ("Image at %08lX:\n", (ulong)hdr);
+			print_image_hdr( hdr );
+			putc ('\n');
+		next_sector:
+		}
+	next_bank:
+	}
+
+	return (0);
+}
+
+U_BOOT_CMD(
+	imls,	1,		1,	do_imls,
+	"imls    - list all images found in flash\n",
+	"\n"
+	"    - Prints information about all images found at sector\n"
+	"      boundaries in flash.\n"
+);
+#endif	/* CFG_CMD_IMLS */
+
 void
 print_image_hdr (image_header_t *hdr)
 {
diff --git a/common/cmd_load.c b/common/cmd_load.c
index 0ea8c4b..5622452 100644
--- a/common/cmd_load.c
+++ b/common/cmd_load.c
@@ -28,7 +28,7 @@
 #include <command.h>
 #include <s_record.h>
 #include <net.h>
-#include <syscall.h>
+#include <exports.h>
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)
@@ -213,6 +213,7 @@
 static int
 read_record (char *buf, ulong len)
 {
+	DECLARE_GLOBAL_DATA_PTR;
 	char *p;
 	char c;
 
@@ -236,13 +237,11 @@
 		}
 
 	    /* Check for the console hangup (if any different from serial) */
-#ifdef CONFIG_PPC	/* we don't have syscall_tbl anywhere else */
-	    if (syscall_tbl[SYSCALL_GETC] != serial_getc) {
+	    if (gd->jt[XF_getc] != serial_getc) {
 		if (ctrlc()) {
 		    return (-1);
 		}
 	    }
-#endif
 	}
 
 	/* line too long - truncate */
@@ -479,7 +478,7 @@
 	printf ("## Ready for binary (kermit) download "
 		"to 0x%08lX at %d bps...\n",
 		offset,
-		current_baudrate);
+		load_baudrate);
 	addr = load_serial_bin (offset);
 
 	if (addr == ~0) {
diff --git a/common/cmd_log.c b/common/cmd_log.c
index 8780da5..57ef484 100644
--- a/common/cmd_log.c
+++ b/common/cmd_log.c
@@ -86,8 +86,7 @@
 	post_word = post_word_load();
 #ifdef CONFIG_POST
 	/* The post routines have setup the word so we can simply test it */
- 	if (((post_word & 0xffff) == POST_POWERON) ||
-	    ((post_word & 0xffff) == POST_SLOWTEST)) {
+ 	if (post_word_load () & POST_COLDBOOT) {
  		logged_chars = log_size = log_start = 0;
 		*ext_tag = LOGBUFF_MAGIC;
  	}
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index 7e6c19e..3e22598 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -53,6 +53,8 @@
 			return 2;
 		case 'l':
 			return 4;
+		default:
+			return -1;
 		}
 	}
 	return default_size;
@@ -86,9 +88,10 @@
 #define DISP_LINE_LEN	16
 int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong	addr, size, length;
+	ulong	addr, length;
 	ulong	i, nbytes, linebytes;
 	u_char	*cp;
+	int	size;
 	int rc = 0;
 
 	/* We use the last specified parameters, unless new ones are
@@ -107,7 +110,8 @@
 		/* New command specified.  Check for a size specification.
 		 * Defaults to long if no or incorrect specification.
 		 */
-		size = cmd_get_data_size(argv[0], 4);
+		if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+			return 1;
 
 		/* Address is specified since argc > 1
 		*/
@@ -199,7 +203,8 @@
 
 int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong	addr, size, writeval, count;
+	ulong	addr, writeval, count;
+	int	size;
 
 	if ((argc < 3) || (argc > 4)) {
 		printf ("Usage:\n%s\n", cmdtp->usage);
@@ -208,7 +213,8 @@
 
 	/* Check for size specification.
 	*/
-	size = cmd_get_data_size(argv[0], 4);
+	if ((size = cmd_get_data_size(argv[0], 4)) < 1)
+		return 1;
 
 	/* Address is specified since argc > 1
 	*/
@@ -240,7 +246,8 @@
 
 int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong	size, addr1, addr2, count, ngood;
+	ulong	addr1, addr2, count, ngood;
+	int	size;
 	int     rcode = 0;
 
 	if (argc != 4) {
@@ -250,7 +257,8 @@
 
 	/* Check for size specification.
 	*/
-	size = cmd_get_data_size(argv[0], 4);
+	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+		return 1;
 
 	addr1 = simple_strtoul(argv[1], NULL, 16);
 	addr1 += base_address;
@@ -316,7 +324,8 @@
 
 int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong	addr, size, dest, count;
+	ulong	addr, dest, count;
+	int	size;
 
 	if (argc != 4) {
 		printf ("Usage:\n%s\n", cmdtp->usage);
@@ -325,7 +334,8 @@
 
 	/* Check for size specification.
 	*/
-	size = cmd_get_data_size(argv[0], 4);
+	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+		return 1;
 
 	addr = simple_strtoul(argv[1], NULL, 16);
 	addr += base_address;
@@ -458,7 +468,8 @@
 
 int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong	addr, size, length, i, junk;
+	ulong	addr, length, i, junk;
+	int	size;
 	volatile uint	*longp;
 	volatile ushort *shortp;
 	volatile u_char	*cp;
@@ -471,7 +482,8 @@
 	/* Check for a size spefication.
 	 * Defaults to long if no or incorrect specification.
 	 */
-	size = cmd_get_data_size(argv[0], 4);
+	if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+		return 1;
 
 	/* Address is always specified.
 	*/
@@ -839,8 +851,8 @@
 static int
 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
 {
-	ulong	addr, size, i;
-	int	nbytes;
+	ulong	addr, i;
+	int	nbytes, size;
 	extern char console_buffer[];
 
 	if (argc != 2) {
@@ -861,7 +873,8 @@
 		/* New command specified.  Check for a size specification.
 		 * Defaults to long if no or incorrect specification.
 		 */
-		size = cmd_get_data_size(argv[0], 4);
+		if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+			return 1;
 
 		/* Address is specified since argc > 1
 		*/
diff --git a/common/console.c b/common/console.c
index 8c94aa7..148c599 100644
--- a/common/console.c
+++ b/common/console.c
@@ -25,9 +25,7 @@
 #include <stdarg.h>
 #include <malloc.h>
 #include <console.h>
-#include <syscall.h>
-
-void **syscall_tbl;
+#include <exports.h>
 
 #ifdef CONFIG_AMIGAONEG3SE
 int console_changed = 0;
@@ -52,6 +50,7 @@
 
 static int console_setfile (int file, device_t * dev)
 {
+	DECLARE_GLOBAL_DATA_PTR;
 	int error = 0;
 
 	if (dev == NULL)
@@ -78,13 +77,13 @@
 		 */
 		switch (file) {
 		case stdin:
-			syscall_tbl[SYSCALL_GETC] = dev->getc;
-			syscall_tbl[SYSCALL_TSTC] = dev->tstc;
+			gd->jt[XF_getc] = dev->getc;
+			gd->jt[XF_tstc] = dev->tstc;
 			break;
 		case stdout:
-			syscall_tbl[SYSCALL_PUTC] = dev->putc;
-			syscall_tbl[SYSCALL_PUTS] = dev->puts;
-			syscall_tbl[SYSCALL_PRINTF] = printf;
+			gd->jt[XF_putc] = dev->putc;
+			gd->jt[XF_puts] = dev->puts;
+			gd->jt[XF_printf] = printf;
 			break;
 		}
 		break;
@@ -394,15 +393,16 @@
 /* Called after the relocation - use desired console functions */
 int console_init_r (void)
 {
+	DECLARE_GLOBAL_DATA_PTR;
 	char *stdinname, *stdoutname, *stderrname;
 	device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
 
 	/* set default handlers at first */
-	syscall_tbl[SYSCALL_GETC] = serial_getc;
-	syscall_tbl[SYSCALL_TSTC] = serial_tstc;
-	syscall_tbl[SYSCALL_PUTC] = serial_putc;
-	syscall_tbl[SYSCALL_PUTS] = serial_puts;
-	syscall_tbl[SYSCALL_PRINTF] = serial_printf;
+	gd->jt[XF_getc] = serial_getc;
+	gd->jt[XF_tstc] = serial_tstc;
+	gd->jt[XF_putc] = serial_putc;
+	gd->jt[XF_puts] = serial_puts;
+	gd->jt[XF_printf] = serial_printf;
 
 	/* stdin stdout and stderr are in environment */
 	/* scan for it */
diff --git a/common/exports.c b/common/exports.c
new file mode 100644
index 0000000..22002cc
--- /dev/null
+++ b/common/exports.c
@@ -0,0 +1,31 @@
+#include <common.h>
+#include <exports.h>
+
+static void dummy(void)
+{
+}
+
+unsigned long get_version(void)
+{
+	return XF_VERSION;
+}
+
+void jumptable_init (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	int i;
+
+	gd->jt = (void **) malloc (XF_MAX * sizeof (void *));
+	for (i = 0; i < XF_MAX; i++)
+		gd->jt[i] = (void *) dummy;
+
+	gd->jt[XF_get_version] = (void *) get_version;
+	gd->jt[XF_malloc] = (void *) malloc;
+	gd->jt[XF_free] = (void *) free;
+	gd->jt[XF_get_timer] = (void *)get_timer;
+	gd->jt[XF_udelay] = (void *)udelay;
+#if defined(CONFIG_I386) || defined(CONFIG_PPC)
+	gd->jt[XF_install_hdlr] = (void *) irq_install_handler;
+	gd->jt[XF_free_hdlr] = (void *) irq_free_handler;
+#endif
+}