mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Krzysztof Halasa <khc@pm.waw.pl>
To: barebox@lists.infradead.org
Subject: [PATCH 2/3] ARM: support big/little endian switching in "bootX".
Date: Thu, 06 Jan 2011 16:25:20 +0100	[thread overview]
Message-ID: <m3zkrekqan.fsf@intrepid.localdomain> (raw)
In-Reply-To: <m38vyym6k9.fsf@intrepid.localdomain> (Krzysztof Halasa's message of "Thu, 06 Jan 2011 15:48:38 +0100")

Currently implemented only in "bootz".

Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>

diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig
index 3572a1f..8ee7d6c 100644
--- a/arch/arm/cpu/Kconfig
+++ b/arch/arm/cpu/Kconfig
@@ -73,6 +73,15 @@ config CPU_BIG_ENDIAN
 	  port must properly enable any big-endian related features
 	  of your chipset/board/processor.
 
+config BOOT_ENDIANNESS_SWITCH
+	bool "Support switching of Linux kernel endianness"
+	help
+	  Say Y here if you need to switch CPU endianness before running
+	  Linux kernel, e.g. if you want big-endian Barebox to run
+	  little-endian Linux.
+
+	  Currently implemented only by "bootz" command.
+
 config ARCH_HAS_L2X0
 	bool
 
diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c
index f826da6..9927b76 100644
--- a/arch/arm/lib/armlinux.c
+++ b/arch/arm/lib/armlinux.c
@@ -41,6 +41,7 @@
 #include <asm/setup.h>
 #include <asm/barebox-arm.h>
 #include <asm/armlinux.h>
+#include <asm/system.h>
 
 static struct tag *params;
 static int armlinux_architecture = 0;
@@ -85,9 +86,10 @@ static void setup_memory_tags(void)
 	}
 }
 
-static void setup_commandline_tag(const char *commandline)
+static void setup_commandline_tag(const char *commandline, int swap)
 {
 	const char *p;
+	size_t words;
 
 	if (!commandline)
 		return;
@@ -102,12 +104,20 @@ static void setup_commandline_tag(const char *commandline)
 	if (*p == '\0')
 		return;
 
+	words = (strlen(p) + 1 /* NUL */ + 3 /* round up */) >> 2;
 	params->hdr.tag = ATAG_CMDLINE;
-	params->hdr.size =
-	    (sizeof (struct tag_header) + strlen(p) + 1 + 4) >> 2;
+	params->hdr.size = (sizeof(struct tag_header) >> 2) + words;
 
 	strcpy(params->u.cmdline.cmdline, p);
 
+#ifdef CONFIG_BOOT_ENDIANNESS_SWITCH
+	if (swap) {
+		u32 *cmd = (u32 *)params->u.cmdline.cmdline;
+		while (words--)
+			cmd[words] = swab32(cmd[words]);
+	}
+#endif
+
 	params = tag_next(params);
 }
 
@@ -156,13 +166,13 @@ static void setup_end_tag (void)
 	params->hdr.size = 0;
 }
 
-static void setup_tags(struct image_data *data)
+static void setup_tags(struct image_data *data, int swap)
 {
 	const char *commandline = getenv("bootargs");
 
 	setup_start_tag();
 	setup_memory_tags();
-	setup_commandline_tag(commandline);
+	setup_commandline_tag(commandline, swap);
 
 	if (data && data->initrd)
 		setup_initrd_tag (&data->initrd->header);
@@ -231,7 +241,7 @@ static int do_bootm_linux(struct image_data *data)
 	debug("## Transferring control to Linux (at address 0x%p) ...\n",
 	       theKernel);
 
-	setup_tags(data);
+	setup_tags(data, 0);
 
 	if (relocate_image(data->os, (void *)image_get_load(os_header)))
 		return -1;
@@ -290,18 +300,21 @@ late_initcall(armlinux_register_image_handler);
 
 #ifdef CONFIG_CMD_BOOTZ
 struct zimage_header {
-	u32	unsused[9];
+	u32	unused[9];
 	u32	magic;
 	u32	start;
 	u32	end;
 };
 
+#define ZIMAGE_MAGIC 0x016F2818
+
 static int do_bootz(struct command *cmdtp, int argc, char *argv[])
 {
 	void (*theKernel)(int zero, int arch, void *params);
-	int fd, ret;
+	int fd, ret, swap = 0;
 	struct zimage_header header;
 	void *zimage;
+	u32 end;
 
 	if (argc != 2) {
 		barebox_cmd_usage(cmdtp);
@@ -320,27 +333,53 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[])
 		goto err_out;
 	}
 
-	if (header.magic != 0x016f2818) {
+	switch (header.magic) {
+#ifdef CONFIG_BOOT_ENDIANNESS_SWITCH
+	case swab32(ZIMAGE_MAGIC):
+		swap = 1;
+		/* fall through */
+#endif
+	case ZIMAGE_MAGIC:
+		break;
+	default:
 		printf("invalid magic 0x%08x\n", header.magic);
 		goto err_out;
 	}
 
-	zimage = xmalloc(header.end);
+	end = header.end;
+
+	if (swap)
+		end = swab32(end);
+
+	zimage = xmalloc(end);
 	memcpy(zimage, &header, sizeof(header));
 
-	ret = read(fd, zimage + sizeof(header), header.end - sizeof(header));
-	if (ret < header.end - sizeof(header)) {
+	ret = read(fd, zimage + sizeof(header), end - sizeof(header));
+	if (ret < end - sizeof(header)) {
 		printf("could not read %s\n", argv[1]);
 		goto err_out1;
 	}
 
+	if (swap) {
+		void *ptr;
+		for (ptr = zimage; ptr < zimage + end; ptr += 4)
+			*(u32 *)ptr = swab32(*(u32 *)ptr);
+	}
+
 	theKernel = zimage;
 
-	printf("loaded zImage from %s with size %d\n", argv[1], header.end);
+	printf("loaded zImage from %s with size %d\n", argv[1], end);
 
-	setup_tags(NULL);
+	setup_tags(NULL, swap);
 
 	shutdown_barebox();
+	if (swap) {
+		u32 reg;
+		__asm__ __volatile__("mrc p15, 0, %0, c1, c0" : "=r" (reg));
+		reg ^= CR_B; /* swap big-endian flag */
+		__asm__ __volatile__("mcr p15, 0, %0, c1, c0" :: "r" (reg));
+	}
+
 	theKernel(0, armlinux_architecture, armlinux_bootparams);
 
 	return 0;
@@ -382,7 +421,7 @@ static int do_bootu(struct command *cmdtp, int argc, char *argv[])
 	if (!theKernel)
 		theKernel = (void *)simple_strtoul(argv[1], NULL, 0);
 
-	setup_tags(NULL);
+	setup_tags(NULL, 0);
 
 	shutdown_barebox();
 	theKernel(0, armlinux_architecture, armlinux_bootparams);

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2011-01-06 15:25 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-06 14:48 New round of my IXP42x patches Krzysztof Halasa
2011-01-06 15:23 ` [PATCH 1/3] Fix error handling with malloc, memalign etc. Introduce xmemalign() Krzysztof Halasa
2011-01-06 15:25 ` Krzysztof Halasa [this message]
2011-01-06 15:26 ` [PATCH 3/3] ARM: Add support for IXP4xx CPU and for Goramo Multilink router platform Krzysztof Halasa
2011-01-06 23:36   ` Jean-Christophe PLAGNIOL-VILLARD
2011-01-08 12:16     ` Krzysztof Halasa
2011-01-08 13:55       ` Sascha Hauer
2011-01-08 17:35         ` Krzysztof Halasa
2011-01-08 18:10           ` Jean-Christophe PLAGNIOL-VILLARD
2011-01-09 12:03             ` Krzysztof Halasa
2011-01-08 13:33     ` Krzysztof Halasa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m3zkrekqan.fsf@intrepid.localdomain \
    --to=khc@pm.waw.pl \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox