]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/cmd_bootm.c
Add zero-copy ramdisk support (requires corresponding kernel support!)
[karo-tx-uboot.git] / common / cmd_bootm.c
index c3d62cb8c197c02426ce5c584af881cbf49f9b18..af62becf4a9eaa6f6868c08a4aa0c122eaebeb30 100644 (file)
@@ -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 @@ 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;
 
@@ -338,6 +342,12 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *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);
@@ -364,6 +374,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
        ulong   cmd_start, cmd_end;
        ulong   initrd_high;
        ulong   data;
+       int     initrd_copy_to_ram = 1;
        char    *cmdline;
        char    *s;
        bd_t    *kbd;
@@ -375,6 +386,8 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
                 * turning the "load high" feature off. This is intentional.
                 */
                initrd_high = simple_strtoul(s, NULL, 16);
+               if (initrd_high == ~0)
+                       initrd_copy_to_ram = 0;
        } else {        /* not set, no restrictions to load high */
                initrd_high = ~0;
        }
@@ -557,6 +570,10 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
        }
 
        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 */
 
@@ -611,6 +628,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
                memmove ((void *)initrd_start, (void *)data, len);
 #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
                printf ("OK\n");
+           }
        } else {
                initrd_start = 0;
                initrd_end = 0;
@@ -717,6 +735,99 @@ 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[])
 {
@@ -839,6 +950,9 @@ print_type (image_header_t *hdr)
        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;
        }