* Patch by David Updegraff, 22 Apr 2003:
  update for CrayL1 board

* Patch by Pantelis Antoniou, 21 Apr 2003:
  add boot support for ARTOS (a proprietary OS)

* Patch by Steven Scholz, 11 Apr 2003:
  Add support for RTC DS1338

* Patch by Rod Boyce, 24 Jan 2003:
  Fix counting of extended partitions in diskboot command
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index c3d62cb..fa32d46 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -31,6 +31,7 @@
 #include <image.h>
 #include <malloc.h>
 #include <zlib.h>
+#include <environment.h>
 #include <asm/byteorder.h>
 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
 #include <rtc.h>
@@ -105,6 +106,9 @@
 int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
 int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] );
 #endif /* CFG_CMD_ELF */
+#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
+static boot_os_Fcn do_bootm_artos;
+#endif
 
 image_header_t header;
 
@@ -338,6 +342,12 @@
 			      addr, len_ptr, verify);
 	    break;
 #endif /* CFG_CMD_ELF */
+#ifdef CONFIG_ARTOS
+	case IH_OS_ARTOS:
+	    do_bootm_artos  (cmdtp, flag, argc, argv,
+			     addr, len_ptr, verify);
+	    break;
+#endif
 	}
 
 	SHOW_BOOT_PROGRESS (-9);
@@ -717,6 +727,99 @@
 	(*loader) (gd->bd, img_addr, consdev, cmdline);
 }
 
+#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
+
+/* Function that returns a character from the environment */
+extern uchar (*env_get_char)(int);
+
+static void
+do_bootm_artos (cmd_tbl_t *cmdtp, int flag,
+		int	argc, char *argv[],
+		ulong	addr,
+		ulong	*len_ptr,
+		int	verify)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	ulong top;
+	char *s, *cmdline;
+	char **fwenv, **ss;
+	int i, j, nxt, len, envno, envsz;
+	bd_t *kbd;
+	void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top);
+	image_header_t *hdr = &header;
+
+	/*
+	 * Booting an ARTOS kernel image + application
+	 */
+
+	/* this used to be the top of memory, but was wrong... */
+#ifdef CONFIG_PPC
+	/* get stack pointer */
+	asm volatile ("mr %0,1" : "=r"(top) );
+#endif
+	debug ("## Current stack ends at 0x%08lX ", top);
+
+	top -= 2048;		/* just to be sure */
+	if (top > CFG_BOOTMAPSZ)
+		top = CFG_BOOTMAPSZ;
+	top &= ~0xF;
+
+	debug ("=> set upper limit to 0x%08lX\n", top);
+
+	/* first check the artos specific boot args, then the linux args*/
+	if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL)
+		s = "";
+
+	/* get length of cmdline, and place it */
+	len = strlen(s);
+	top = (top - (len + 1)) & ~0xF;
+	cmdline = (char *)top;
+	debug ("## cmdline at 0x%08lX ", top);
+	strcpy(cmdline, s);
+
+	/* copy bdinfo */
+	top = (top - sizeof(bd_t)) & ~0xF;
+	debug ("## bd at 0x%08lX ", top);
+	kbd = (bd_t *)top;
+	memcpy(kbd, gd->bd, sizeof(bd_t));
+
+	/* first find number of env entries, and their size */
+	envno = 0;
+	envsz = 0;
+	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
+		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
+			;
+		envno++;
+		envsz += (nxt - i) + 1;	/* plus trailing zero */
+	}
+	envno++;	/* plus the terminating zero */
+	debug ("## %u envvars total size %u ", envno, envsz);
+
+	top = (top - sizeof(char **)*envno) & ~0xF;
+	fwenv = (char **)top;
+	debug ("## fwenv at 0x%08lX ", top);
+
+	top = (top - envsz) & ~0xF;
+	s = (char *)top;
+	ss = fwenv;
+
+	/* now copy them */
+	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
+		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
+			;
+		*ss++ = s;
+		for (j = i; j < nxt; ++j)
+			*s++ = env_get_char(j);
+		*s++ = '\0';
+	}
+	*ss++ = NULL;	/* terminate */
+
+	entry = (void (*)(bd_t *, char *, char **, ulong))ntohl(hdr->ih_ep);
+	(*entry)(kbd, cmdline, fwenv, top);
+}
+#endif
+
+
 #if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
 int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
@@ -839,6 +942,9 @@
 	case IH_OS_QNX:		os = "QNX";			break;
 	case IH_OS_U_BOOT:	os = "U-Boot";			break;
 	case IH_OS_RTEMS:	os = "RTEMS";			break;
+#ifdef CONFIG_ARTOS
+	case IH_OS_ARTOS:	os = "ARTOS";			break;
+#endif
 	default:		os = "Unknown OS";		break;
 	}