|
@@ -26,6 +26,7 @@
|
|
|
#include <linux/sizes.h>
|
|
|
#include <linux/device.h>
|
|
|
#include <linux/dma-contiguous.h>
|
|
|
+#include <linux/decompress/generic.h>
|
|
|
|
|
|
#include <asm/addrspace.h>
|
|
|
#include <asm/bootinfo.h>
|
|
@@ -243,6 +244,35 @@ disable:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/* In some conditions (e.g. big endian bootloader with a little endian
|
|
|
+ kernel), the initrd might appear byte swapped. Try to detect this and
|
|
|
+ byte swap it if needed. */
|
|
|
+static void __init maybe_bswap_initrd(void)
|
|
|
+{
|
|
|
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
|
|
|
+ u64 buf;
|
|
|
+
|
|
|
+ /* Check for CPIO signature */
|
|
|
+ if (!memcmp((void *)initrd_start, "070701", 6))
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* Check for compressed initrd */
|
|
|
+ if (decompress_method((unsigned char *)initrd_start, 8, NULL))
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* Try again with a byte swapped header */
|
|
|
+ buf = swab64p((u64 *)initrd_start);
|
|
|
+ if (!memcmp(&buf, "070701", 6) ||
|
|
|
+ decompress_method((unsigned char *)(&buf), 8, NULL)) {
|
|
|
+ unsigned long i;
|
|
|
+
|
|
|
+ pr_info("Byteswapped initrd detected\n");
|
|
|
+ for (i = initrd_start; i < ALIGN(initrd_end, 8); i += 8)
|
|
|
+ swab64s((u64 *)i);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
static void __init finalize_initrd(void)
|
|
|
{
|
|
|
unsigned long size = initrd_end - initrd_start;
|
|
@@ -256,6 +286,8 @@ static void __init finalize_initrd(void)
|
|
|
goto disable;
|
|
|
}
|
|
|
|
|
|
+ maybe_bswap_initrd();
|
|
|
+
|
|
|
reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT);
|
|
|
initrd_below_start_ok = 1;
|
|
|
|