#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>
#include <asm/cache.h>
#endif
+#ifdef CONFIG_LOGBUFFER
+#include <logbuff.h>
+#endif
+
/*
* Some systems (for example LWMON) have very short watchdog periods;
* we must make sure to split long operations like memmove() or
#endif
static void print_type (image_header_t *hdr);
+#ifdef __I386__
+image_header_t *fake_header(image_header_t *hdr, void *ptr, int size);
+#endif
+
/*
* Continue booting an OS image; caller already has:
* - copied image header to global variable `header'
ulong *len_ptr, /* multi-file image length table */
int verify); /* getenv("verify")[0] != 'n' */
-#ifndef CONFIG_ARM
+#ifdef CONFIG_PPC
static boot_os_Fcn do_bootm_linux;
#else
extern boot_os_Fcn do_bootm_linux;
#endif
static boot_os_Fcn do_bootm_netbsd;
+static boot_os_Fcn do_bootm_rtems;
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
static boot_os_Fcn do_bootm_vxworks;
static boot_os_Fcn do_bootm_qnxelf;
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;
memmove (&header, (char *)addr, sizeof(image_header_t));
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+#ifdef __I386__ /* correct image format not implemented yet - fake it */
+ if (fake_header(hdr, (void*)addr, -1) != NULL) {
+ /* to compensate for the addition below */
+ addr -= sizeof(image_header_t);
+ /* turnof verify,
+ * fake_header() does not fake the data crc
+ */
+ verify = 0;
+ } else
+#endif /* __I386__ */
+ {
printf ("Bad Magic Number\n");
SHOW_BOOT_PROGRESS (-1);
return 1;
+ }
}
SHOW_BOOT_PROGRESS (2);
SHOW_BOOT_PROGRESS (3);
/* for multi-file images we need the data part, too */
- print_image_hdr ((image_header_t *)addr);
+ print_image_hdr (hdr);
data = addr + sizeof(image_header_t);
len = ntohl(hdr->ih_size);
len_ptr = (ulong *)data;
- if (hdr->ih_arch != IH_CPU_PPC && hdr->ih_arch != IH_CPU_ARM) {
- printf ("Unsupported Architecture\n");
+#if defined(__PPC__)
+ if (hdr->ih_arch != IH_CPU_PPC)
+#elif defined(__ARM__)
+ if (hdr->ih_arch != IH_CPU_ARM)
+#elif defined(__I386__)
+ if (hdr->ih_arch != IH_CPU_I386)
+#elif defined(__mips__)
+ if (hdr->ih_arch != IH_CPU_MIPS)
+#else
+# error Unknown CPU type
+#endif
+ {
+ printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);
SHOW_BOOT_PROGRESS (-4);
return 1;
}
iflag = disable_interrupts();
+#ifdef CONFIG_AMIGAONEG3SE
+ /*
+ * We've possible left the caches enabled during
+ * bios emulation, so turn them off again
+ */
+ icache_disable();
+ invalidate_l1_instruction_cache();
+ flush_data_cache();
+ dcache_disable();
+#endif
+
switch (hdr->ih_comp) {
case IH_COMP_NONE:
- if(hdr->ih_load == addr) {
+ if(ntohl(hdr->ih_load) == addr) {
printf (" XIP %s ... ", name);
} else {
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
switch (hdr->ih_type) {
case IH_TYPE_STANDALONE:
- appl = (int (*)(cmd_tbl_t *, int, int, char *[]))ntohl(hdr->ih_ep);
if (iflag)
enable_interrupts();
+ /* load (and uncompress), but don't start if "autostart"
+ * is set to "no"
+ */
+ if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0))
+ return 0;
+ appl = (int (*)(cmd_tbl_t *, int, int, char *[]))ntohl(hdr->ih_ep);
(*appl)(cmdtp, flag, argc-1, &argv[1]);
- break;
+ return 0;
case IH_TYPE_KERNEL:
case IH_TYPE_MULTI:
/* handled below */
do_bootm_netbsd (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
+
+ case IH_OS_RTEMS:
+ do_bootm_rtems (cmdtp, flag, argc, argv,
+ addr, len_ptr, verify);
+ break;
+
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
case IH_OS_VXWORKS:
do_bootm_vxworks (cmdtp, flag, argc, argv,
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);
return 1;
}
-#ifndef CONFIG_ARM
+#ifdef CONFIG_PPC
static void
do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
int argc, char *argv[],
ulong cmd_start, cmd_end;
ulong initrd_high;
ulong data;
+ int initrd_copy_to_ram = 1;
char *cmdline;
char *s;
bd_t *kbd;
* turning the "load high" feature off. This is intentional.
*/
initrd_high = simple_strtoul(s, NULL, 16);
- } else { /* not set, no restrictions to load high */
+ if (initrd_high == ~0)
+ initrd_copy_to_ram = 0;
+ } else { /* not set, no restrictions to load high */
initrd_high = ~0;
}
#ifdef CONFIG_LOGBUFFER
kbd=gd->bd;
- if ((s = getenv ("logstart")) != NULL) {
- kbd->bi_sramstart = simple_strtoul(s, NULL, 16);
- /* Prevent initrd from overwriting logbuffer */
- if (initrd_high < kbd->bi_sramstart)
- initrd_high = kbd->bi_sramstart-1024;
- }
- debug ("## Logbuffer at 0x%08lX ", kbd->bi_sramstart);
+ /* Prevent initrd from overwriting logbuffer */
+ if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD))
+ initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD;
+ debug ("## Logbuffer at 0x%08lX ", kbd->bi_memsize-LOGBUFF_LEN);
#endif
/*
}
if (data) {
+ if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */
+ initrd_start = data;
+ initrd_end = initrd_start + len;
+ } else {
initrd_start = (ulong)kbd - len;
initrd_start &= ~(4096 - 1); /* align on page */
memmove ((void *)initrd_start, (void *)data, len);
#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
printf ("OK\n");
+ }
} else {
initrd_start = 0;
initrd_end = 0;
*/
(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
}
-#endif /* CONFIG_ARM */
+#endif /* CONFIG_PPC */
static void
do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
(*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[])
{
case IH_OS_VXWORKS: os = "VxWorks"; break;
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;
}
return (0);
}
+static void
+do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+ ulong addr, ulong *len_ptr, int verify)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ image_header_t *hdr = &header;
+ void (*entry_point)(bd_t *);
+
+ entry_point = (void (*)(bd_t *)) hdr->ih_ep;
+
+ printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
+ (ulong)entry_point);
+
+ SHOW_BOOT_PROGRESS (15);
+
+ /*
+ * RTEMS Parameters:
+ * r3: ptr to board info data
+ */
+
+ (*entry_point ) ( gd->bd );
+}
+
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
static void
do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],