Index: arch/ppc32/loader/asm.S
===================================================================
--- arch/ppc32/loader/asm.S	(revision 543c31f07e8cdf240bd7f9e3f4fea7a0c1ec3251)
+++ arch/ppc32/loader/asm.S	(revision f9413470bb085d792cd5a142694f4ed4868adecb)
@@ -38,8 +38,72 @@
 
 .global halt
+.global memcpy
 .global jump_to_kernel
 
 halt:
 	b halt
+
+memcpy:
+	srwi. r7, r5, 3
+	addi r6, r3, -4
+	addi r4, r4, -4
+	beq	2f
+	
+	andi. r0, r6, 3
+	mtctr r7
+	bne 5f
+	
+	1:
+	
+	lwz r7, 4(r4)
+	lwzu r8, 8(r4)
+	stw r7, 4(r6)
+	stwu r8, 8(r6)
+	bdnz 1b
+	
+	andi. r5, r5, 7
+	
+	2:
+	
+	cmplwi 0, r5, 4
+	blt 3f
+	
+	lwzu r0, 4(r4)
+	addi r5, r5, -4
+	stwu r0, 4(r6)
+	
+	3:
+	
+	cmpwi 0, r5, 0
+	beqlr
+	mtctr r5
+	addi r4, r4, 3
+	addi r6, r6, 3
+	
+	4:
+	
+	lbzu r0, 1(r4)
+	stbu r0, 1(r6)
+	bdnz 4b
+	blr
+	
+	5:
+	
+	subfic r0, r0, 4
+	mtctr r0
+	
+	6:
+	
+	lbz r7, 4(r4)
+	addi r4, r4, 1
+	stb r7, 4(r6)
+	addi r6, r6, 1
+	bdnz 6b
+	subf r5, r0, r5
+	rlwinm. r7, r5, 32-3, 3, 31
+	beq 2b
+	mtctr r7
+	b 1b
+
 
 jump_to_kernel:
Index: arch/ppc32/loader/asm.h
===================================================================
--- arch/ppc32/loader/asm.h	(revision 543c31f07e8cdf240bd7f9e3f4fea7a0c1ec3251)
+++ arch/ppc32/loader/asm.h	(revision f9413470bb085d792cd5a142694f4ed4868adecb)
@@ -40,4 +40,6 @@
 #ifndef __ASM__
 
+#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
+
 extern void *trans[TRANS_SIZE];
 
Index: arch/ppc32/loader/main.c
===================================================================
--- arch/ppc32/loader/main.c	(revision 543c31f07e8cdf240bd7f9e3f4fea7a0c1ec3251)
+++ arch/ppc32/loader/main.c	(revision f9413470bb085d792cd5a142694f4ed4868adecb)
@@ -35,4 +35,6 @@
 #define KERNEL_SIZE ((unsigned int) KERNEL_END - (unsigned int) KERNEL_START)
 
+#define HEAP_GAP 1024000
+
 memmap_t memmap;
 
@@ -47,9 +49,26 @@
 
 
-static void check_overlap(const void *addr, const char *desc)
+static void fix_overlap(void *va, void **pa, const char *desc, unsigned int *top)
 {
-	if ((unsigned int) addr < KERNEL_SIZE) {
-		printf("Error: %s overlaps kernel physical area\n", desc);
-		halt();
+	if ((unsigned int) *pa + PAGE_SIZE < *top) {
+		printf("Warning: %s overlaps kernel physical area\n", desc);
+		
+		void *new_va = (void *) (ALIGN_UP((unsigned int) KERNEL_END + HEAP_GAP, PAGE_SIZE) + *top);
+		void *new_pa = (void *) (HEAP_GAP + *top);
+		*top += PAGE_SIZE;
+		
+		if (ofw_map(new_pa, new_va, PAGE_SIZE, 0) != 0) {
+			printf("Error: Unable to map page aligned memory at %L (physical %L)\n", new_va, new_pa);
+			halt();
+		}
+		
+		if ((unsigned int) new_pa + PAGE_SIZE < KERNEL_SIZE) {
+			printf("Error: %s cannot be relocated\n", desc);
+			halt();	
+		}
+		
+		printf("Relocating %L -> %L (physical %L -> %L)\n", va, new_va, *pa, new_pa);
+		*pa = new_pa;
+		memcpy(new_va, va, PAGE_SIZE);
 	}
 }
@@ -73,8 +92,4 @@
 	void *memmap_pa = ofw_translate(&memmap);
 	
-	check_overlap(real_mode_pa, "Bootstrap trampoline");
-	check_overlap(trans_pa, "Translation table");
-	check_overlap(memmap_pa, "Memory map");
-	
 	printf("Memory statistics (total %d MB)\n", memmap.total >> 20);
 	printf(" kernel image         at %L (size %d bytes)\n", KERNEL_START, KERNEL_SIZE);
@@ -83,10 +98,15 @@
 	printf(" translation table    at %L (physical %L)\n", &trans, trans_pa);
 	
+	unsigned int top = ALIGN_UP(KERNEL_SIZE, PAGE_SIZE);
 	unsigned int addr;
 	for (addr = 0; addr < KERNEL_SIZE; addr += PAGE_SIZE) {
 		void *pa = ofw_translate(KERNEL_START + addr);
-		check_overlap(pa, "Kernel image");
+		fix_overlap(KERNEL_START + addr, &pa, "Kernel image", &top);
 		trans[addr >> PAGE_WIDTH] = pa;
 	}
+	
+	fix_overlap(&real_mode, &real_mode_pa, "Bootstrap trampoline", &top);
+	fix_overlap(&trans, &trans_pa, "Translation table", &top);
+	fix_overlap(&memmap, &memmap_pa, "Memory map", &top);
 	
 	printf("Booting the kernel...\n");
Index: arch/ppc32/loader/main.h
===================================================================
--- arch/ppc32/loader/main.h	(revision 543c31f07e8cdf240bd7f9e3f4fea7a0c1ec3251)
+++ arch/ppc32/loader/main.h	(revision f9413470bb085d792cd5a142694f4ed4868adecb)
@@ -32,4 +32,11 @@
 #include "ofw.h"
 
+/** Align to the nearest higher address.
+ *
+ * @param addr  Address or size to be aligned.
+ * @param align Size of alignment, must be power of 2.
+ */
+#define ALIGN_UP(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1))
+
 extern int _binary_____________kernel_kernel_bin_start;
 extern int _binary_____________kernel_kernel_bin_end;
Index: arch/ppc32/loader/ofw.c
===================================================================
--- arch/ppc32/loader/ofw.c	(revision 543c31f07e8cdf240bd7f9e3f4fea7a0c1ec3251)
+++ arch/ppc32/loader/ofw.c	(revision f9413470bb085d792cd5a142694f4ed4868adecb)
@@ -130,4 +130,10 @@
 
 
+int ofw_map(const void *phys, const void *virt, const int size, const int mode)
+{
+	return ofw_call("call-method", 6, 1, "map", ofw_mmu, mode, size, virt, phys);
+}
+
+
 int ofw_memmap(memmap_t *map)
 {
Index: arch/ppc32/loader/ofw.h
===================================================================
--- arch/ppc32/loader/ofw.h	(revision 543c31f07e8cdf240bd7f9e3f4fea7a0c1ec3251)
+++ arch/ppc32/loader/ofw.h	(revision f9413470bb085d792cd5a142694f4ed4868adecb)
@@ -57,4 +57,5 @@
 
 extern void *ofw_translate(const void *virt);
+extern int ofw_map(const void *phys, const void *virt, const int size, const int mode);
 extern int ofw_memmap(memmap_t *map);
 
