]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib_arm/armlinux.c
* Patch by Jon Loeliger, 15 Jul 2004:
[karo-tx-uboot.git] / lib_arm / armlinux.c
index 03058033f8a9d79b14a1fb92279fe871bb787b43..6855d5f9494cf393310d59fd7e3f63efb6ea23fe 100644 (file)
  *
  * 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
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
  *
  */
 
 #include <common.h>
 #include <command.h>
-#include <cmd_boot.h>
 #include <image.h>
 #include <zlib.h>
 #include <asm/byteorder.h>
 #include <dataflash.h>
 #endif
 
-#include <asm/setup.h>
-#define tag_size(type)  ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
-#define tag_next(t)     ((struct tag *)((u32 *)(t) + (t)->hdr.size))
+/*cmd_boot.c*/
+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 
 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
     defined (CONFIG_CMDLINE_TAG) || \
     defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
     defined (CONFIG_VFD)
-static void setup_start_tag(bd_t *bd);
+static void setup_start_tag (bd_t *bd);
+
 # ifdef CONFIG_SETUP_MEMORY_TAGS
-static void setup_memory_tags(bd_t *bd);
+static void setup_memory_tags (bd_t *bd);
 # endif
-static void setup_commandline_tag(bd_t *bd, char *commandline);
+static void setup_commandline_tag (bd_t *bd, char *commandline);
+
 #if 0
-static void setup_ramdisk_tag(bd_t *bd);
+static void setup_ramdisk_tag (bd_t *bd);
 #endif
 # ifdef CONFIG_INITRD_TAG
-static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end);
+static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
+                             ulong initrd_end);
 # endif
-static void setup_end_tag(bd_t *bd);
+static void setup_end_tag (bd_t *bd);
+
 # if defined (CONFIG_VFD)
-static void setup_videolfb_tag(gd_t *gd);
+static void setup_videolfb_tag (gd_t *gd);
 # endif
 
 
@@ -66,306 +70,312 @@ static struct tag *params;
 # define SHOW_BOOT_PROGRESS(arg)
 #endif
 
-extern image_header_t header;           /* from cmd_bootm.c */
+extern image_header_t header;  /* from cmd_bootm.c */
 
 
-void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
-               ulong addr, ulong *len_ptr, int   verify)
+void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+                    ulong addr, ulong *len_ptr, int verify)
 {
        DECLARE_GLOBAL_DATA_PTR;
 
-    ulong len = 0, checksum;
-    ulong initrd_start, initrd_end;
-    ulong data;
-    void (*theKernel)(int zero, int arch);
-    image_header_t *hdr = &header;
-    bd_t *bd = gd->bd;
+       ulong len = 0, checksum;
+       ulong initrd_start, initrd_end;
+       ulong data;
+       void (*theKernel)(int zero, int arch, uint params);
+       image_header_t *hdr = &header;
+       bd_t *bd = gd->bd;
+
 #ifdef CONFIG_CMDLINE_TAG
-    char *commandline = getenv("bootargs");
+       char *commandline = getenv ("bootargs");
 #endif
 
-    theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);
+       theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
 
-    /*
-     * Check if there is an initrd image
-     */
-    if (argc >= 3) {
-       SHOW_BOOT_PROGRESS (9);
+       /*
+        * Check if there is an initrd image
+        */
+       if (argc >= 3) {
+               SHOW_BOOT_PROGRESS (9);
 
-       addr = simple_strtoul(argv[2], NULL, 16);
+               addr = simple_strtoul (argv[2], NULL, 16);
 
-       printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
+               printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
 
-       /* Copy header so we can blank CRC field for re-calculation */
+               /* Copy header so we can blank CRC field for re-calculation */
 #ifdef CONFIG_HAS_DATAFLASH
-       if (addr_dataflash(addr)){
-               read_dataflash(addr, sizeof(image_header_t), (char *)&header);
-       } else
-#endif 
-       memcpy (&header, (char *)addr, sizeof(image_header_t));
-
-       if (ntohl(hdr->ih_magic) != IH_MAGIC) {
-           printf ("Bad Magic Number\n");
-           SHOW_BOOT_PROGRESS (-10);
-           do_reset (cmdtp, flag, argc, argv);
-       }
+               if (addr_dataflash (addr)) {
+                       read_dataflash (addr, sizeof (image_header_t),
+                                       (char *) &header);
+               } else
+#endif
+                       memcpy (&header, (char *) addr,
+                               sizeof (image_header_t));
 
-       data = (ulong)&header;
-       len  = sizeof(image_header_t);
+               if (ntohl (hdr->ih_magic) != IH_MAGIC) {
+                       printf ("Bad Magic Number\n");
+                       SHOW_BOOT_PROGRESS (-10);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
 
-       checksum = ntohl(hdr->ih_hcrc);
-       hdr->ih_hcrc = 0;
+               data = (ulong) & header;
+               len = sizeof (image_header_t);
 
-       if (crc32 (0, (char *)data, len) != checksum) {
-           printf ("Bad Header Checksum\n");
-           SHOW_BOOT_PROGRESS (-11);
-           do_reset (cmdtp, flag, argc, argv);
-       }
+               checksum = ntohl (hdr->ih_hcrc);
+               hdr->ih_hcrc = 0;
+
+               if (crc32 (0, (char *) data, len) != checksum) {
+                       printf ("Bad Header Checksum\n");
+                       SHOW_BOOT_PROGRESS (-11);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
 
-       SHOW_BOOT_PROGRESS (10);
+               SHOW_BOOT_PROGRESS (10);
 
-       print_image_hdr (hdr);
+               print_image_hdr (hdr);
 
-       data = addr + sizeof(image_header_t);
-       len  = ntohl(hdr->ih_size);
+               data = addr + sizeof (image_header_t);
+               len = ntohl (hdr->ih_size);
 
 #ifdef CONFIG_HAS_DATAFLASH
-       if (addr_dataflash(addr)){
-               read_dataflash(data, len, (char *)CFG_LOAD_ADDR);
-               data = CFG_LOAD_ADDR;
-       }
+               if (addr_dataflash (addr)) {
+                       read_dataflash (data, len, (char *) CFG_LOAD_ADDR);
+                       data = CFG_LOAD_ADDR;
+               }
 #endif
 
-       if (verify) {
-           ulong csum = 0;
-
-           printf ("   Verifying Checksum ... ");
-           csum = crc32 (0, (char *)data, len);
-           if (csum != ntohl(hdr->ih_dcrc)) {
-               printf ("Bad Data CRC\n");
-               SHOW_BOOT_PROGRESS (-12);
-               do_reset (cmdtp, flag, argc, argv);
-           }
-           printf ("OK\n");
+               if (verify) {
+                       ulong csum = 0;
+
+                       printf ("   Verifying Checksum ... ");
+                       csum = crc32 (0, (char *) data, len);
+                       if (csum != ntohl (hdr->ih_dcrc)) {
+                               printf ("Bad Data CRC\n");
+                               SHOW_BOOT_PROGRESS (-12);
+                               do_reset (cmdtp, flag, argc, argv);
+                       }
+                       printf ("OK\n");
+               }
+
+               SHOW_BOOT_PROGRESS (11);
+
+               if ((hdr->ih_os != IH_OS_LINUX) ||
+                   (hdr->ih_arch != IH_CPU_ARM) ||
+                   (hdr->ih_type != IH_TYPE_RAMDISK)) {
+                       printf ("No Linux ARM Ramdisk Image\n");
+                       SHOW_BOOT_PROGRESS (-13);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
+
+#if defined(CONFIG_B2) || defined(CONFIG_EVB4510)
+               /*
+                *we need to copy the ramdisk to SRAM to let Linux boot
+                */
+               memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
+               data = ntohl(hdr->ih_load);
+#endif /* CONFIG_B2 || CONFIG_EVB4510 */
+
+               /*
+                * Now check if we have a multifile image
+                */
+       } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) {
+               ulong tail = ntohl (len_ptr[0]) % 4;
+               int i;
+
+               SHOW_BOOT_PROGRESS (13);
+
+               /* skip kernel length and terminator */
+               data = (ulong) (&len_ptr[2]);
+               /* skip any additional image length fields */
+               for (i = 1; len_ptr[i]; ++i)
+                       data += 4;
+               /* add kernel length, and align */
+               data += ntohl (len_ptr[0]);
+               if (tail) {
+                       data += 4 - tail;
+               }
+
+               len = ntohl (len_ptr[1]);
+
+       } else {
+               /*
+                * no initrd image
+                */
+               SHOW_BOOT_PROGRESS (14);
+
+               len = data = 0;
        }
 
-       SHOW_BOOT_PROGRESS (11);
-
-       if ((hdr->ih_os   != IH_OS_LINUX)       ||
-           (hdr->ih_arch != IH_CPU_ARM)        ||
-           (hdr->ih_type != IH_TYPE_RAMDISK)   ) {
-           printf ("No Linux ARM Ramdisk Image\n");
-           SHOW_BOOT_PROGRESS (-13);
-           do_reset (cmdtp, flag, argc, argv);
-       }
-
-       /*
-        * Now check if we have a multifile image
-        */
-    } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
-       ulong tail    = ntohl(len_ptr[0]) % 4;
-       int i;
-
-       SHOW_BOOT_PROGRESS (13);
-
-       /* skip kernel length and terminator */
-       data = (ulong)(&len_ptr[2]);
-       /* skip any additional image length fields */
-       for (i=1; len_ptr[i]; ++i)
-         data += 4;
-       /* add kernel length, and align */
-       data += ntohl(len_ptr[0]);
-       if (tail) {
-           data += 4 - tail;
-       }
-
-       len   = ntohl(len_ptr[1]);
-
-    } else {
-       /*
-        * no initrd image
-        */
-        SHOW_BOOT_PROGRESS (14);
-
-       data = 0;
-    }
-
 #ifdef DEBUG
-    if (!data) {
-       printf ("No initrd\n");
-    }
+       if (!data) {
+               printf ("No initrd\n");
+       }
 #endif
 
-    if (data) {
-       initrd_start = data;
-       initrd_end   = initrd_start + len;
-    } else {
-       initrd_start = 0;
-       initrd_end = 0;
-    }
+       if (data) {
+               initrd_start = data;
+               initrd_end = initrd_start + len;
+       } else {
+               initrd_start = 0;
+               initrd_end = 0;
+       }
 
-    SHOW_BOOT_PROGRESS (15);
+       SHOW_BOOT_PROGRESS (15);
 
-#ifdef DEBUG
-    printf ("## Transferring control to Linux (at address %08lx) ...\n",
-           (ulong)theKernel);
-#endif
+       debug ("## Transferring control to Linux (at address %08lx) ...\n",
+              (ulong) theKernel);
 
 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
     defined (CONFIG_CMDLINE_TAG) || \
     defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
     defined (CONFIG_VFD)
-    setup_start_tag(bd);
+       setup_start_tag (bd);
+#ifdef CONFIG_SERIAL_TAG
+       setup_serial_tag (&params);
+#endif
+#ifdef CONFIG_REVISION_TAG
+       setup_revision_tag (&params);
+#endif
 #ifdef CONFIG_SETUP_MEMORY_TAGS
-    setup_memory_tags(bd);
+       setup_memory_tags (bd);
 #endif
 #ifdef CONFIG_CMDLINE_TAG
-    setup_commandline_tag(bd, commandline);
+       setup_commandline_tag (bd, commandline);
 #endif
 #ifdef CONFIG_INITRD_TAG
-    setup_initrd_tag(bd, initrd_start, initrd_end);
-#endif
-#if 0
-    setup_ramdisk_tag(bd);
+       if (initrd_start && initrd_end)
+               setup_initrd_tag (bd, initrd_start, initrd_end);
 #endif
 #if defined (CONFIG_VFD)
-    setup_videolfb_tag(gd);
+       setup_videolfb_tag ((gd_t *) gd);
 #endif
-    setup_end_tag(bd);
+       setup_end_tag (bd);
 #endif
 
-    /* we assume that the kernel is in place */
-    printf("\nStarting kernel ...\n\n");
+       /* we assume that the kernel is in place */
+       printf ("\nStarting kernel ...\n\n");
+
+#ifdef CONFIG_USB_DEVICE
+       {
+               extern void udc_disconnect (void);
+               udc_disconnect ();
+       }
+#endif
 
-    cleanup_before_linux();
+       cleanup_before_linux ();
 
-    theKernel(0, bd->bi_arch_number);
+       theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
 }
 
 
 #if defined (CONFIG_SETUP_MEMORY_TAGS) || \
     defined (CONFIG_CMDLINE_TAG) || \
     defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
     defined (CONFIG_VFD)
-static void setup_start_tag(bd_t *bd)
+static void setup_start_tag (bd_t *bd)
 {
-    params = (struct tag *)bd->bi_boot_params;
+       params = (struct tag *) bd->bi_boot_params;
 
-    params->hdr.tag = ATAG_CORE;
-    params->hdr.size = tag_size(tag_core);
+       params->hdr.tag = ATAG_CORE;
+       params->hdr.size = tag_size (tag_core);
 
-    params->u.core.flags = 0;
-    params->u.core.pagesize = 0;
-    params->u.core.rootdev = 0;
+       params->u.core.flags = 0;
+       params->u.core.pagesize = 0;
+       params->u.core.rootdev = 0;
 
-    params = tag_next(params);
+       params = tag_next (params);
 }
 
 
 #ifdef CONFIG_SETUP_MEMORY_TAGS
-static void setup_memory_tags(bd_t *bd)
+static void setup_memory_tags (bd_t *bd)
 {
-    int i;
+       int i;
 
-    for(i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-       params->hdr.tag = ATAG_MEM;
-       params->hdr.size = tag_size(tag_mem32);
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               params->hdr.tag = ATAG_MEM;
+               params->hdr.size = tag_size (tag_mem32);
 
-       params->u.mem.start = bd->bi_dram[i].start;
-       params->u.mem.size = bd->bi_dram[i].size;
+               params->u.mem.start = bd->bi_dram[i].start;
+               params->u.mem.size = bd->bi_dram[i].size;
 
-       params = tag_next(params);
-    }
+               params = tag_next (params);
+       }
 }
-#endif /* CONFIG_SETUP_MEMORY_TAGS */
+#endif /* CONFIG_SETUP_MEMORY_TAGS */
 
 
-static void setup_commandline_tag(bd_t *bd, char *commandline)
+static void setup_commandline_tag (bd_t *bd, char *commandline)
 {
-    char *p;
+       char *p;
 
-    /* eat leading white space */
-    for(p = commandline; *p == ' '; p++)
-      ;
+       if (!commandline)
+               return;
 
-    /* skip non-existent command lines so the kernel will still
-     * use its default command line.
-     */
-    if(*p == '\0')
-      return;
+       /* eat leading white space */
+       for (p = commandline; *p == ' '; p++);
 
-    params->hdr.tag = ATAG_CMDLINE;
-    params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
+       /* skip non-existent command lines so the kernel will still
+        * use its default command line.
+        */
+       if (*p == '\0')
+               return;
 
-    strcpy(params->u.cmdline.cmdline, p);
+       params->hdr.tag = ATAG_CMDLINE;
+       params->hdr.size =
+               (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
 
-    params = tag_next(params);
-}
+       strcpy (params->u.cmdline.cmdline, p);
 
+       params = tag_next (params);
+}
 
-#ifndef ATAG_INITRD2
-#define ATAG_INITRD2    0x54420005
-#endif
 
 #ifdef CONFIG_INITRD_TAG
-static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end)
+static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
 {
-    /* an ATAG_INITRD node tells the kernel where the compressed
-     * ramdisk can be found. ATAG_RDIMG is a better name, actually.
-     */
-    params->hdr.tag = ATAG_INITRD2;
-    params->hdr.size = tag_size(tag_initrd);
+       /* an ATAG_INITRD node tells the kernel where the compressed
+        * ramdisk can be found. ATAG_RDIMG is a better name, actually.
+        */
+       params->hdr.tag = ATAG_INITRD2;
+       params->hdr.size = tag_size (tag_initrd);
 
-    params->u.initrd.start = initrd_start;
-    params->u.initrd.size = initrd_end - initrd_start;
+       params->u.initrd.start = initrd_start;
+       params->u.initrd.size = initrd_end - initrd_start;
 
-    params = tag_next(params);
+       params = tag_next (params);
 }
-#endif /* CONFIG_INITRD_TAG */
+#endif /* CONFIG_INITRD_TAG */
 
 
-#if 0
-static void setup_ramdisk_tag(bd_t *bd)
+#if defined (CONFIG_VFD)
+static void setup_videolfb_tag (gd_t *gd)
 {
-    /* an ATAG_RAMDISK node tells the kernel how large the
-     * decompressed ramdisk will become.
-     */
-    params->hdr.tag = ATAG_RAMDISK;
-    params->hdr.size = tag_size(tag_ramdisk);
-
-    params->u.ramdisk.start = 0;
-    /*params->u.ramdisk.size = RAMDISK_SIZE; */
-    params->u.ramdisk.flags = 1;       /* automatically load ramdisk */
+       /* An ATAG_VIDEOLFB node tells the kernel where and how large
+        * the framebuffer for video was allocated (among other things).
+        * Note that a _physical_ address is passed !
+        *
+        * We only use it to pass the address and size, the other entries
+        * in the tag_videolfb are not of interest.
+        */
+       params->hdr.tag = ATAG_VIDEOLFB;
+       params->hdr.size = tag_size (tag_videolfb);
 
-    params = tag_next(params);
-}
-#endif /* 0 */
+       params->u.videolfb.lfb_base = (u32) gd->fb_base;
+       /* 7168 = 256*4*56/8 - actually 2 pages (8192 bytes) are allocated */
+       params->u.videolfb.lfb_size = 7168;
 
-#if defined (CONFIG_VFD)
-static void setup_videolfb_tag(gd_t *gd)
-{
-    /* An ATAG_VIDEOLFB node tells the kernel where and how large
-     * the framebuffer for video was allocated (among other things).
-     * Note that a _physical_ address is passed !
-     *
-     * We only use it to pass the address and size, the other entries
-     * in the tag_videolfb are not of interest.
-     */
-    params->hdr.tag = ATAG_VIDEOLFB;
-    params->hdr.size = tag_size(tag_videolfb);
-
-    params->u.videolfb.lfb_base = (u32)gd->fb_base;
-    /* 7168 = 256*4*56/8 - actually 2 pages (8192 bytes) are allocated */
-    params->u.videolfb.lfb_size = 7168;
-
-    params = tag_next(params);
+       params = tag_next (params);
 }
 #endif
 
-static void setup_end_tag(bd_t *bd)
+static void setup_end_tag (bd_t *bd)
 {
-    params->hdr.tag = ATAG_NONE;
-    params->hdr.size = 0;
+       params->hdr.tag = ATAG_NONE;
+       params->hdr.size = 0;
 }
 
 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */