[PATCH] ARM: Allow cross endian linux boot

This patch adds the capability to boot a little endian linux
kernel on a big endian u-boot. This is usefull on IXP425 platform
which is always big-endian in u-boot.

To enable crossboot, define the environment variable "crossboot". This was
done as I found no way to pass the crossboot flag into 
do_bootm_linux() through the command line.

Ramdisk images are not yet implemented/tested with this crossboot
feature. Command line is handled.


The patch is against "latest" u-boot git-repository

Please (still) be patient if style of submission or patches are
offending.

Signed-off-by: Stefan Althoefer <[EMAIL PROTECTED]>
----

diff -uprN u-boot-orig//lib_arm/bootm.c u-boot/lib_arm/bootm.c
--- u-boot-orig//lib_arm/bootm.c        2008-12-02 17:25:32.000000000 +0100
+++ u-boot/lib_arm/bootm.c      2008-12-03 11:37:05.000000000 +0100
@@ -56,6 +56,17 @@ static void setup_videolfb_tag (gd_t *gd
 static struct tag *params;
 #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG 
*/
 
+static int cross_boot;
+
+static inline unsigned int mswap32(unsigned int x)
+{
+       return (
+               ((x<<24) & 0xff000000) |
+               ((x<< 8) & 0x00ff0000) |
+               ((x>> 8) & 0x0000ff00) |
+               ((x>>24) & 0x000000ff) );
+}
+
 int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
 {
        bd_t    *bd = gd->bd;
@@ -72,6 +83,10 @@ int do_bootm_linux(int flag, int argc, c
 
        theKernel = (void (*)(int, int, uint))images->ep;
 
+       cross_boot = 0;
+       if( getenv("crossboot") )
+               cross_boot = 1;
+
        s = getenv ("machid");
        if (s) {
                machid = simple_strtoul (s, NULL, 16);
@@ -125,6 +140,31 @@ int do_bootm_linux(int flag, int argc, c
 
        cleanup_before_linux ();
 
+       /* swap the kernel code */
+       if (cross_boot) {
+               int            ksize, i;
+               volatile int   *pk;
+               volatile int   dummy;
+               unsigned long reg;
+
+               ksize = ntohl (images->os.image_len);
+               pk = (int *)theKernel;
+               for (i=0; i<ksize/(sizeof(int)); i++) {
+                       *pk = mswap32(*pk);
+                       pk++;
+               }
+
+               /* read more data to flush the cache */
+               for (i=0; i<64*1024; i++) {
+                       dummy = *pk++;
+               }
+
+               /* turn off Big-Endian mode */
+               asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (reg));
+               reg &= ~(1<<7);
+               asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (reg));
+       } while (0);
+
        theKernel (0, machid, bd->bi_boot_params);
        /* does not return */
 
@@ -194,6 +234,19 @@ static void setup_commandline_tag (bd_t
 
        strcpy (params->u.cmdline.cmdline, p);
 
+       /* swap the command line (for cross endian boot) */
+       if ( cross_boot ) {
+               u32            cmdsize, i;
+               volatile u32   *pcmd;
+
+               cmdsize = params->hdr.size; /* number of words! */
+               pcmd = (volatile u32 *)params->u.cmdline.cmdline;
+               for (i=0; i<cmdsize; i++) {
+                       *pcmd = mswap32(*pcmd);
+                       pcmd++;
+               }
+       }
+
        params = tag_next (params);
 }
 
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to