[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