powerpc: Move ppc64 boot wrapper code over to arch/powerpc

This also extends the code to handle 32-bit ELF vmlinux files as well
as 64-bit ones.  This is sufficient for booting on new-world 32-bit
powermacs (i.e. all recent machines).

Signed-off-by: Paul Mackerras <paulus@samba.org>
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index d41ad2e..99dbea8 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -14,10 +14,6 @@
 
 HAS_BIARCH	:= $(call cc-option-yn, -m32)
 
-ifeq ($(CONFIG_PPC64),y)
-OLDARCH	:= ppc64
-SZ	:= 64
-
 # Set default 32 bits cross compilers for vdso and boot wrapper
 CROSS32_COMPILE ?=
 
@@ -37,6 +33,10 @@
 
 export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
 
+ifeq ($(CONFIG_PPC64),y)
+OLDARCH	:= ppc64
+SZ	:= 64
+
 new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
 
 ifeq ($(new_nm),y)
@@ -139,7 +139,7 @@
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
-defaultimage-$(CONFIG_PPC32)	:= uImage zImage
+defaultimage-$(CONFIG_PPC32)	:= zImage
 defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
 defaultimage-$(CONFIG_PPC_PSERIES) := zImage
 KBUILD_IMAGE := $(defaultimage-y)
@@ -154,23 +154,13 @@
 
 .PHONY: $(BOOT_TARGETS)
 
-boot := arch/$(OLDARCH)/boot
+boot := arch/$(ARCH)/boot
 
-# urk
-ifeq ($(CONFIG_PPC64),y)
 $(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
-else
-$(BOOT_TARGETS): vmlinux
-	$(Q)$(MAKE) ARCH=ppc $(build)=$(boot) $@
-endif
-
-uImage: vmlinux
-	$(Q)$(MAKE) ARCH=$(OLDARCH) $(build)=$(boot)/images $(boot)/images/$@
 
 define archhelp
-  @echo '* zImage          - Compressed kernel image (arch/$(ARCH)/boot/images/zImage.*)'
-  @echo '  uImage          - Create a bootable image for U-Boot / PPCBoot'
+  @echo '* zImage          - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)'
   @echo '  install         - Install kernel using'
   @echo '                    (your) ~/bin/installkernel or'
   @echo '                    (distribution) /sbin/installkernel or'
@@ -180,7 +170,6 @@
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
-	# Temporary hack until we have migrated to asm-powerpc
 	$(Q)rm -rf arch/$(ARCH)/include
 
 archprepare: checkbin
diff --git a/arch/ppc64/boot/Makefile b/arch/powerpc/boot/Makefile
similarity index 96%
rename from arch/ppc64/boot/Makefile
rename to arch/powerpc/boot/Makefile
index 301bc15..9770f58 100644
--- a/arch/ppc64/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -22,7 +22,8 @@
 
 
 HOSTCC		:= gcc
-BOOTCFLAGS	:= $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include) -fPIC
+BOOTCFLAGS	:= $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \
+		   $(shell $(CROSS32CC) -print-file-name=include) -fPIC
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 BOOTLFLAGS	:= -T $(srctree)/$(src)/zImage.lds
 OBJCOPYFLAGS    := contents,alloc,load,readonly,data
@@ -98,7 +99,7 @@
       cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
 
 quiet_cmd_stripvm = STRIP   $@
-      cmd_stripvm = $(STRIP) -s $< -o $@
+      cmd_stripvm = $(STRIP) -s -R .comment $< -o $@
 
 vmlinux.strip: vmlinux
 	$(call if_changed,stripvm)
diff --git a/arch/ppc64/boot/README b/arch/powerpc/boot/README
similarity index 100%
rename from arch/ppc64/boot/README
rename to arch/powerpc/boot/README
diff --git a/arch/ppc64/boot/addRamDisk.c b/arch/powerpc/boot/addRamDisk.c
similarity index 100%
rename from arch/ppc64/boot/addRamDisk.c
rename to arch/powerpc/boot/addRamDisk.c
diff --git a/arch/ppc64/boot/addnote.c b/arch/powerpc/boot/addnote.c
similarity index 100%
rename from arch/ppc64/boot/addnote.c
rename to arch/powerpc/boot/addnote.c
diff --git a/arch/ppc64/boot/crt0.S b/arch/powerpc/boot/crt0.S
similarity index 100%
rename from arch/ppc64/boot/crt0.S
rename to arch/powerpc/boot/crt0.S
diff --git a/arch/ppc64/boot/div64.S b/arch/powerpc/boot/div64.S
similarity index 100%
rename from arch/ppc64/boot/div64.S
rename to arch/powerpc/boot/div64.S
diff --git a/arch/ppc64/boot/elf.h b/arch/powerpc/boot/elf.h
similarity index 100%
rename from arch/ppc64/boot/elf.h
rename to arch/powerpc/boot/elf.h
diff --git a/arch/ppc64/boot/install.sh b/arch/powerpc/boot/install.sh
similarity index 100%
rename from arch/ppc64/boot/install.sh
rename to arch/powerpc/boot/install.sh
diff --git a/arch/ppc64/boot/main.c b/arch/powerpc/boot/main.c
similarity index 77%
rename from arch/ppc64/boot/main.c
rename to arch/powerpc/boot/main.c
index e0dde24..64ec931 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -42,6 +42,8 @@
 static struct addr_range vmlinuz;
 static struct addr_range initrd;
 
+static unsigned long elfoffset;
+
 static char scratch[46912];	/* scratch space for gunzip, from zlib_inflate_workspacesize() */
 static char elfheader[256];
 
@@ -131,13 +133,70 @@
 	return addr;
 }
 
+static int is_elf64(void *hdr)
+{
+	Elf64_Ehdr *elf64 = hdr;
+	Elf64_Phdr *elf64ph;
+	unsigned int i;
+
+	if (!(elf64->e_ident[EI_MAG0]  == ELFMAG0	&&
+	      elf64->e_ident[EI_MAG1]  == ELFMAG1	&&
+	      elf64->e_ident[EI_MAG2]  == ELFMAG2	&&
+	      elf64->e_ident[EI_MAG3]  == ELFMAG3	&&
+	      elf64->e_ident[EI_CLASS] == ELFCLASS64	&&
+	      elf64->e_ident[EI_DATA]  == ELFDATA2MSB	&&
+	      elf64->e_type            == ET_EXEC	&&
+	      elf64->e_machine         == EM_PPC64))
+		return 0;
+
+	elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
+				 (unsigned long)elf64->e_phoff);
+	for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++)
+		if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
+			break;
+	if (i >= (unsigned int)elf64->e_phnum)
+		return 0;
+
+	elfoffset = (unsigned long)elf64ph->p_offset;
+	vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
+	vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
+	return 1;
+}
+
+static int is_elf32(void *hdr)
+{
+	Elf32_Ehdr *elf32 = hdr;
+	Elf32_Phdr *elf32ph;
+	unsigned int i;
+
+	if (!(elf32->e_ident[EI_MAG0]  == ELFMAG0	&&
+	      elf32->e_ident[EI_MAG1]  == ELFMAG1	&&
+	      elf32->e_ident[EI_MAG2]  == ELFMAG2	&&
+	      elf32->e_ident[EI_MAG3]  == ELFMAG3	&&
+	      elf32->e_ident[EI_CLASS] == ELFCLASS32	&&
+	      elf32->e_ident[EI_DATA]  == ELFDATA2MSB	&&
+	      elf32->e_type            == ET_EXEC	&&
+	      elf32->e_machine         == EM_PPC))
+		return 0;
+
+	elf32 = (Elf32_Ehdr *)elfheader;
+	elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff);
+	for (i = 0; i < elf32->e_phnum; i++, elf32ph++)
+		if (elf32ph->p_type == PT_LOAD && elf32ph->p_offset != 0)
+			break;
+	if (i >= elf32->e_phnum)
+		return 0;
+
+	elfoffset = elf32ph->p_offset;
+	vmlinux.size = elf32ph->p_filesz + elf32ph->p_offset;
+	vmlinux.memsize = elf32ph->p_memsz + elf32ph->p_offset;
+	return 1;
+}
+
 void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 {
-	unsigned long i;
 	int len;
 	kernel_entry_t kernel_entry;
-	Elf64_Ehdr *elf64;
-	Elf64_Phdr *elf64ph;
 
 	memset(__bss_start, 0, _end - __bss_start);
 
@@ -153,6 +212,22 @@
 
 	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
 
+	vmlinuz.addr = (unsigned long)_vmlinux_start;
+	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
+
+	/* gunzip the ELF header of the kernel */
+	if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
+		len = vmlinuz.size;
+		gunzip(elfheader, sizeof(elfheader),
+				(unsigned char *)vmlinuz.addr, &len);
+	} else
+		memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
+
+	if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
+		printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
+		exit();
+	}
+
 	/*
 	 * The first available claim_base must be above the end of the
 	 * the loaded kernel wrapper file (_start to _end includes the
@@ -172,46 +247,11 @@
 		claim_base = PROG_START;
 #endif
 
-	vmlinuz.addr = (unsigned long)_vmlinux_start;
-	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
-
-	/* gunzip the ELF header of the kernel */
-	if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
-		len = vmlinuz.size;
-		gunzip(elfheader, sizeof(elfheader),
-				(unsigned char *)vmlinuz.addr, &len);
-	} else
-		memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
-
-	elf64 = (Elf64_Ehdr *)elfheader;
-	if ( elf64->e_ident[EI_MAG0]  != ELFMAG0	||
-	     elf64->e_ident[EI_MAG1]  != ELFMAG1	||
-	     elf64->e_ident[EI_MAG2]  != ELFMAG2	||
-	     elf64->e_ident[EI_MAG3]  != ELFMAG3	||
-	     elf64->e_ident[EI_CLASS] != ELFCLASS64	||
-	     elf64->e_ident[EI_DATA]  != ELFDATA2MSB	||
-	     elf64->e_type            != ET_EXEC	||
-	     elf64->e_machine         != EM_PPC64 )
-	{
-		printf("Error: not a valid PPC64 ELF file!\n\r");
-		exit();
-	}
-
-	elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
-				(unsigned long)elf64->e_phoff);
-	for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) {
-		if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
-			break;
-	}
-	vmlinux.size = (unsigned long)elf64ph->p_filesz +
-		(unsigned long)elf64ph->p_offset;
 	/* We need to claim the memsize plus the file offset since gzip
 	 * will expand the header (file offset), then the kernel, then
 	 * possible rubbish we don't care about. But the kernel bss must
 	 * be claimed (it will be zero'd by the kernel itself)
 	 */
-	vmlinux.memsize = (unsigned long)elf64ph->p_memsz +
-		(unsigned long)elf64ph->p_offset;
 	printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
 	vmlinux.addr = try_claim(vmlinux.memsize);
 	if (vmlinux.addr == 0) {
@@ -254,9 +294,9 @@
 	/* Skip over the ELF header */
 #ifdef DEBUG
 	printf("... skipping 0x%lx bytes of ELF header\n\r",
-			(unsigned long)elf64ph->p_offset);
+			elfoffset);
 #endif
-	vmlinux.addr += (unsigned long)elf64ph->p_offset;
+	vmlinux.addr += elfoffset;
 
 	flush_cache((void *)vmlinux.addr, vmlinux.size);
 
@@ -272,7 +312,7 @@
 		(unsigned long)prom, NULL);
 #endif
 
-	kernel_entry( a1, a2, prom, NULL );
+	kernel_entry(a1, a2, prom, NULL);
 
 	printf("Error: Linux kernel returned to zImage bootloader!\n\r");
 
diff --git a/arch/ppc64/boot/page.h b/arch/powerpc/boot/page.h
similarity index 100%
rename from arch/ppc64/boot/page.h
rename to arch/powerpc/boot/page.h
diff --git a/arch/ppc64/boot/ppc_asm.h b/arch/powerpc/boot/ppc_asm.h
similarity index 100%
rename from arch/ppc64/boot/ppc_asm.h
rename to arch/powerpc/boot/ppc_asm.h
diff --git a/arch/ppc64/boot/prom.c b/arch/powerpc/boot/prom.c
similarity index 100%
rename from arch/ppc64/boot/prom.c
rename to arch/powerpc/boot/prom.c
diff --git a/arch/ppc64/boot/prom.h b/arch/powerpc/boot/prom.h
similarity index 100%
rename from arch/ppc64/boot/prom.h
rename to arch/powerpc/boot/prom.h
diff --git a/arch/ppc64/boot/stdio.h b/arch/powerpc/boot/stdio.h
similarity index 100%
rename from arch/ppc64/boot/stdio.h
rename to arch/powerpc/boot/stdio.h
diff --git a/arch/ppc64/boot/string.S b/arch/powerpc/boot/string.S
similarity index 100%
rename from arch/ppc64/boot/string.S
rename to arch/powerpc/boot/string.S
diff --git a/arch/ppc64/boot/string.h b/arch/powerpc/boot/string.h
similarity index 100%
rename from arch/ppc64/boot/string.h
rename to arch/powerpc/boot/string.h
diff --git a/arch/ppc64/boot/zImage.lds b/arch/powerpc/boot/zImage.lds
similarity index 100%
rename from arch/ppc64/boot/zImage.lds
rename to arch/powerpc/boot/zImage.lds