[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