[U-Boot] [PATCH] ARM: Allow cross endian linux boot Part 1/1

Stefan Althoefer stefan.althoefer at web.de
Thu Dec 4 22:08:47 CET 2008


[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 <stefan.althoefer at web.de>
----

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);
 }
 


More information about the U-Boot mailing list