linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] generate COFF zImage in arch/powerpc/boot
@ 2005-11-18  6:06 Paul Mackerras
  2005-11-18  7:51 ` Olaf Hering
  0 siblings, 1 reply; 16+ messages in thread
From: Paul Mackerras @ 2005-11-18  6:06 UTC (permalink / raw)
  To: linuxppc-dev

This patch makes ARCH=powerpc on 32-bit machines generate an
arch/powerpc/boot/zImage.coff suitable for booting on old-world
powermacs.  I took the opportunity to reorganize prom.c and prom.h a
bit.  The *printf routines have been moved to their own file, stdio.c,
and prom.c now contains a version of claim() that knows what to do on
older machines.  The link address of the zImage has been moved up from
4MB to 5MB, since OF on oldworld machines occupies the 4M - 5M region.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---

diff -urN powerpc-merge/arch/powerpc/Makefile merge-hack/arch/powerpc/Makefile
--- powerpc-merge/arch/powerpc/Makefile	2005-11-18 16:11:26.000000000 +1100
+++ merge-hack/arch/powerpc/Makefile	2005-11-18 16:54:42.000000000 +1100
@@ -138,7 +138,7 @@
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
-defaultimage-$(CONFIG_PPC32)	:= zImage
+defaultimage-$(CONFIG_PPC32)	:= zImage zImage.coff
 defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
 defaultimage-$(CONFIG_PPC_PSERIES) := zImage
 KBUILD_IMAGE := $(defaultimage-y)
@@ -149,7 +149,8 @@
 # All the instructions talk about "make bzImage".
 bzImage: zImage
 
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm \
+	       zImage.vmode zImage.initrd.vmode zImage.coff zImage.initrd.coff
 
 .PHONY: $(BOOT_TARGETS)
 
diff -urN powerpc-merge/arch/powerpc/boot/Makefile merge-hack/arch/powerpc/boot/Makefile
--- powerpc-merge/arch/powerpc/boot/Makefile	2005-11-16 13:52:19.000000000 +1100
+++ merge-hack/arch/powerpc/boot/Makefile	2005-11-17 14:53:27.000000000 +1100
@@ -27,6 +27,7 @@
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 BOOTLFLAGS	:= -T $(srctree)/$(src)/zImage.lds
 OBJCOPYFLAGS    := contents,alloc,load,readonly,data
+OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
 
 zlib       := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
 zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
@@ -35,7 +36,7 @@
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
 
-src-boot := string.S prom.c main.c div64.S crt0.S
+src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
 src-boot += $(zlib)
 src-boot := $(addprefix $(obj)/, $(src-boot))
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@@ -87,12 +88,13 @@
 src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
 gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
 
-hostprogs-y		:= addnote addRamDisk
-targets 		+= zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
-			   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
-			   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
-			   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
-			   vmlinux.initrd
+hostprogs-y		:= addnote addRamDisk hack-coff
+
+targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
+	   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
+	   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
+	   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
+	   vmlinux.initrd
 extra-y			:= initrd.o
 
 quiet_cmd_ramdisk = RAMDISK $@
@@ -114,6 +116,10 @@
 quiet_cmd_addnote = ADDNOTE $@
       cmd_addnote = $(obj)/addnote $@
 
+quiet_cmd_gencoff = COFF    $@
+      cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $< $@ && \
+		    $(obj)/hack-coff $@
+
 $(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
 	$(call if_changed,gzip)
 
@@ -143,6 +149,12 @@
 	@cp -f $< $@
 	$(call if_changed,addnote)
 
+$(obj)/zImage.coff: $(obj)/zImage.vmode $(obj)/hack-coff
+	$(call cmd,gencoff)
+
+$(obj)/zImage.initrd.coff: $(obj)/zImage.initrd.vmode $(obj)/hack-coff
+	$(call cmd,gencoff)
+
 install: $(CONFIGURE) $(BOOTIMAGE)
 	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
 
diff -urN powerpc-merge/arch/powerpc/boot/crt0.S merge-hack/arch/powerpc/boot/crt0.S
--- powerpc-merge/arch/powerpc/boot/crt0.S	2005-11-18 13:18:16.000000000 +1100
+++ merge-hack/arch/powerpc/boot/crt0.S	2005-11-18 14:00:00.000000000 +1100
@@ -12,17 +12,22 @@
 #include "ppc_asm.h"
 
 	.text
+	/* a procedure descriptor used when booting this as a COFF file */
+	.long	_zimage_start, 0, 0, 0
+
 	.globl	_zimage_start
 _zimage_start:
+	/* Work out the offset between the address we were linked at
+	   and the address where we're running. */
 	bl	1f
-
-1:
-	mflr	r0
+1:	mflr	r0
 	lis	r9,1b@ha
 	addi	r9,r9,1b@l
 	subf.	r0,r9,r0
-	beq	3f
+	beq	3f		/* if running at same address as linked */
 
+	/* The .got2 section contains a list of addresses, so add
+	   the address offset onto each entry. */
 	lis	r9,__got2_start@ha
 	addi	r9,r9,__got2_start@l
 	lis	r8,__got2_end@ha
@@ -32,15 +37,14 @@
 	srwi.	r8,r8,2
 	mtctr	r8
 	add	r9,r0,r9
-2:
-	lwz	r8,0(r9)
+2:	lwz	r8,0(r9)
 	add	r8,r8,r0
 	stw	r8,0(r9)
 	addi	r9,r9,4
 	bdnz	2b
 
-3:
-	lis	r9,_start@h
+	/* Do a cache flush for our text, in case OF didn't */
+3:	lis	r9,_start@h
 	add	r9,r0,r9
 	lis	r8,_etext@ha
 	addi	r8,r8,_etext@l
diff -urN powerpc-merge/arch/powerpc/boot/hack-coff.c merge-hack/arch/powerpc/boot/hack-coff.c
--- /dev/null	2005-04-02 20:23:56.000000000 +1000
+++ merge-hack/arch/powerpc/boot/hack-coff.c	2005-11-17 14:57:08.000000000 +1100
@@ -0,0 +1,84 @@
+/*
+ * hack-coff.c - hack the header of an xcoff file to fill in
+ * a few fields needed by the Open Firmware xcoff loader on
+ * Power Macs but not initialized by objcopy.
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include "rs6000.h"
+
+#define AOUT_MAGIC	0x010b
+
+#define get_16be(x)	((((unsigned char *)(x))[0] << 8) \
+			 + ((unsigned char *)(x))[1])
+#define put_16be(x, v)	(((unsigned char *)(x))[0] = (v) >> 8, \
+			 ((unsigned char *)(x))[1] = (v) & 0xff)
+#define get_32be(x)	((((unsigned char *)(x))[0] << 24) \
+			 + (((unsigned char *)(x))[1] << 16) \
+			 + (((unsigned char *)(x))[2] << 8) \
+			 + ((unsigned char *)(x))[3])
+
+int
+main(int ac, char **av)
+{
+    int fd;
+    int i, nsect;
+    int aoutsz;
+    struct external_filehdr fhdr;
+    AOUTHDR aout;
+    struct external_scnhdr shdr;
+
+    if (ac != 2) {
+	fprintf(stderr, "Usage: hack-coff coff-file\n");
+	exit(1);
+    }
+    if ((fd = open(av[1], 2)) == -1) {
+	perror(av[2]);
+	exit(1);
+    }
+    if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
+	goto readerr;
+    i = get_16be(fhdr.f_magic);
+    if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
+	fprintf(stderr, "%s: not an xcoff file\n", av[1]);
+	exit(1);
+    }
+    aoutsz = get_16be(fhdr.f_opthdr);
+    if (read(fd, &aout, aoutsz) != aoutsz)
+	goto readerr;
+    nsect = get_16be(fhdr.f_nscns);
+    for (i = 0; i < nsect; ++i) {
+	if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+	    goto readerr;
+	if (strcmp(shdr.s_name, ".text") == 0) {
+	    put_16be(aout.o_snentry, i+1);
+	    put_16be(aout.o_sntext, i+1);
+	} else if (strcmp(shdr.s_name, ".data") == 0) {
+	    put_16be(aout.o_sndata, i+1);
+	} else if (strcmp(shdr.s_name, ".bss") == 0) {
+	    put_16be(aout.o_snbss, i+1);
+	}
+    }
+    put_16be(aout.magic, AOUT_MAGIC);
+    if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
+	|| write(fd, &aout, aoutsz) != aoutsz) {
+	fprintf(stderr, "%s: write error\n", av[1]);
+	exit(1);
+    }
+    close(fd);
+    exit(0);
+
+readerr:
+    fprintf(stderr, "%s: read error or file too short\n", av[1]);
+    exit(1);
+}
diff -urN powerpc-merge/arch/powerpc/boot/main.c merge-hack/arch/powerpc/boot/main.c
--- powerpc-merge/arch/powerpc/boot/main.c	2005-11-16 13:52:19.000000000 +1100
+++ merge-hack/arch/powerpc/boot/main.c	2005-11-17 14:41:13.000000000 +1100
@@ -21,8 +21,8 @@
 
 
 /* Value picked to match that used by yaboot */
-#define PROG_START	0x01400000
-#define RAM_END		(512<<20) // Fixme: use OF */
+#define PROG_START	0x01400000	/* only used on 64-bit systems */
+#define RAM_END		(512<<20)	/* Fixme: use OF */
 #define	ONE_MB		0x100000
 
 extern char _start[];
@@ -160,6 +160,17 @@
 	elfoffset = (unsigned long)elf64ph->p_offset;
 	vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
 	vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
+
+#if defined(PROG_START)
+	/*
+	 * Maintain a "magic" minimum address. This keeps some older
+	 * firmware platforms running.
+	 */
+
+	if (claim_base < PROG_START)
+		claim_base = PROG_START;
+#endif
+
 	return 1;
 }
 
@@ -206,12 +217,18 @@
 		exit();
 	if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
 		exit();
-	stderr = stdout;
-	if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
-		exit();
 
 	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
 
+	/*
+	 * The first available claim_base must be above the end of the
+	 * the loaded kernel wrapper file (_start to _end includes the
+	 * initrd image if it is present) and rounded up to a nice
+	 * 1 MB boundary for good measure.
+	 */
+
+	claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
+
 	vmlinuz.addr = (unsigned long)_vmlinux_start;
 	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
 
@@ -228,25 +245,6 @@
 		exit();
 	}
 
-	/*
-	 * The first available claim_base must be above the end of the
-	 * the loaded kernel wrapper file (_start to _end includes the
-	 * initrd image if it is present) and rounded up to a nice
-	 * 1 MB boundary for good measure.
-	 */
-
-	claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
-
-#if defined(PROG_START)
-	/*
-	 * Maintain a "magic" minimum address. This keeps some older
-	 * firmware platforms running.
-	 */
-
-	if (claim_base < PROG_START)
-		claim_base = PROG_START;
-#endif
-
 	/* 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
diff -urN powerpc-merge/arch/powerpc/boot/prom.c merge-hack/arch/powerpc/boot/prom.c
--- powerpc-merge/arch/powerpc/boot/prom.c	2005-11-16 13:52:19.000000000 +1100
+++ merge-hack/arch/powerpc/boot/prom.c	2005-11-17 14:37:12.000000000 +1100
@@ -13,487 +13,153 @@
 #include "prom.h"
 
 int (*prom)(void *);
+phandle chosen_handle;
+ihandle stdout;
 
-void *chosen_handle;
-
-void *stdin;
-void *stdout;
-void *stderr;
-
-
-int
-write(void *handle, void *ptr, int nb)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		void *ihandle;
-		void *addr;
-		int len;
-		int actual;
-	} args;
-
-	args.service = "write";
-	args.nargs = 3;
-	args.nret = 1;
-	args.ihandle = handle;
-	args.addr = ptr;
-	args.len = nb;
-	args.actual = -1;
-	(*prom)(&args);
-	return args.actual;
-}
-
-int
-read(void *handle, void *ptr, int nb)
+int call_prom(const char *service, int nargs, int nret, ...)
 {
+	int i;
 	struct prom_args {
-		char *service;
+		const char *service;
 		int nargs;
 		int nret;
-		void *ihandle;
-		void *addr;
-		int len;
-		int actual;
+		unsigned int args[12];
 	} args;
+	va_list list;
 
-	args.service = "read";
-	args.nargs = 3;
-	args.nret = 1;
-	args.ihandle = handle;
-	args.addr = ptr;
-	args.len = nb;
-	args.actual = -1;
-	(*prom)(&args);
-	return args.actual;
-}
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
 
-void
-exit()
-{
-	struct prom_args {
-		char *service;
-	} args;
+	va_start(list, nret);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
 
-	for (;;) {
-		args.service = "exit";
-		(*prom)(&args);
-	}
-}
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
 
-void
-pause(void)
-{
-	struct prom_args {
-		char *service;
-	} args;
-
-	args.service = "enter";
-	(*prom)(&args);
-}
-
-void *
-finddevice(const char *name)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		const char *devspec;
-		void *phandle;
-	} args;
-
-	args.service = "finddevice";
-	args.nargs = 1;
-	args.nret = 1;
-	args.devspec = name;
-	args.phandle = (void *) -1;
-	(*prom)(&args);
-	return args.phandle;
-}
-
-void *
-claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		unsigned int virt;
-		unsigned int size;
-		unsigned int align;
-		void *ret;
-	} args;
+	if (prom(&args) < 0)
+		return -1;
 
-	args.service = "claim";
-	args.nargs = 3;
-	args.nret = 1;
-	args.virt = virt;
-	args.size = size;
-	args.align = align;
-	(*prom)(&args);
-	return args.ret;
+	return (nret > 0)? args.args[nargs]: 0;
 }
 
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
+int call_prom_ret(const char *service, int nargs, int nret,
+		  unsigned int *rets, ...)
 {
+	int i;
 	struct prom_args {
-		char *service;
+		const char *service;
 		int nargs;
 		int nret;
-		void *phandle;
-		const char *name;
-		void *buf;
-		int buflen;
-		int size;
+		unsigned int args[12];
 	} args;
+	va_list list;
 
-	args.service = "getprop";
-	args.nargs = 4;
-	args.nret = 1;
-	args.phandle = phandle;
-	args.name = name;
-	args.buf = buf;
-	args.buflen = buflen;
-	args.size = -1;
-	(*prom)(&args);
-	return args.size;
-}
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
 
-int
-putc(int c, void *f)
-{
-	char ch = c;
+	va_start(list, rets);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
 
-	if (c == '\n')
-		putc('\r', f);
-	return write(f, &ch, 1) == 1? c: -1;
-}
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
 
-int
-putchar(int c)
-{
-	return putc(c, stdout);
-}
+	if (prom(&args) < 0)
+		return -1;
 
-int
-fputs(char *str, void *f)
-{
-	int n = strlen(str);
+	if (rets != (void *) 0)
+		for (i = 1; i < nret; ++i)
+			rets[i-1] = args.args[nargs+i];
 
-	return write(f, str, n) == n? 0: -1;
+	return (nret > 0)? args.args[nargs]: 0;
 }
 
-size_t strnlen(const char * s, size_t count)
+int write(void *handle, void *ptr, int nb)
 {
-	const char *sc;
-
-	for (sc = s; count-- && *sc != '\0'; ++sc)
-		/* nothing */;
-	return sc - s;
+	return call_prom("write", 3, 1, handle, ptr, nb);
 }
 
-extern unsigned int __div64_32(unsigned long long *dividend,
-			       unsigned int divisor);
-
-/* The unnecessary pointer compare is there
- * to check for type safety (n must be 64bit)
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
  */
-# define do_div(n,base) ({						\
-	unsigned int __base = (base);					\
-	unsigned int __rem;						\
-	(void)(((typeof((n)) *)0) == ((unsigned long long *)0));	\
-	if (((n) >> 32) == 0) {						\
-		__rem = (unsigned int)(n) % __base;			\
-		(n) = (unsigned int)(n) / __base;			\
-	} else								\
-		__rem = __div64_32(&(n), __base);			\
-	__rem;								\
- })
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
 
-static int skip_atoi(const char **s)
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
 {
-	int i, c;
-
-	for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
-		i = i*10 + c - '0';
-	return i;
+	for (; *s2; ++s2)
+		if (*s1++ != *s2)
+			return 0;
+	return 1;
 }
 
-#define ZEROPAD	1		/* pad with zero */
-#define SIGN	2		/* unsigned/signed long */
-#define PLUS	4		/* show plus */
-#define SPACE	8		/* space if plus */
-#define LEFT	16		/* left justified */
-#define SPECIAL	32		/* 0x */
-#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
+static int check_of_version(void)
 {
-	char c,sign,tmp[66];
-	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
-	int i;
+	phandle oprom, chosen;
+	char version[64];
 
-	if (type & LARGE)
-		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-	if (type & LEFT)
-		type &= ~ZEROPAD;
-	if (base < 2 || base > 36)
+	oprom = finddevice("/openprom");
+	if (oprom == (phandle) -1)
+		return 0;
+	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
 		return 0;
-	c = (type & ZEROPAD) ? '0' : ' ';
-	sign = 0;
-	if (type & SIGN) {
-		if ((signed long long)num < 0) {
-			sign = '-';
-			num = - (signed long long)num;
-			size--;
-		} else if (type & PLUS) {
-			sign = '+';
-			size--;
-		} else if (type & SPACE) {
-			sign = ' ';
-			size--;
+	version[sizeof(version)-1] = 0;
+	printf("OF version = '%s'\r\n", version);
+	if (!string_match(version, "Open Firmware, 1.")
+	    && !string_match(version, "FirmWorks,3."))
+		return 0;
+	chosen = finddevice("/chosen");
+	if (chosen == (phandle) -1) {
+		chosen = finddevice("/chosen@0");
+		if (chosen == (phandle) -1) {
+			printf("no chosen\n");
+			return 0;
 		}
 	}
-	if (type & SPECIAL) {
-		if (base == 16)
-			size -= 2;
-		else if (base == 8)
-			size--;
-	}
-	i = 0;
-	if (num == 0)
-		tmp[i++]='0';
-	else while (num != 0) {
-		tmp[i++] = digits[do_div(num, base)];
+	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+		printf("no mmu\n");
+		return 0;
 	}
-	if (i > precision)
-		precision = i;
-	size -= precision;
-	if (!(type&(ZEROPAD+LEFT)))
-		while(size-->0)
-			*str++ = ' ';
-	if (sign)
-		*str++ = sign;
-	if (type & SPECIAL) {
-		if (base==8)
-			*str++ = '0';
-		else if (base==16) {
-			*str++ = '0';
-			*str++ = digits[33];
+	memory = (ihandle) call_prom("open", 1, 1, "/memory");
+	if (memory == (ihandle) -1) {
+		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+		if (memory == (ihandle) -1) {
+			printf("no memory node\n");
+			return 0;
 		}
 	}
-	if (!(type & LEFT))
-		while (size-- > 0)
-			*str++ = c;
-	while (i < precision--)
-		*str++ = '0';
-	while (i-- > 0)
-		*str++ = tmp[i];
-	while (size-- > 0)
-		*str++ = ' ';
-	return str;
+	printf("old OF detected\r\n");
+	return 1;
 }
 
-int vsprintf(char *buf, const char *fmt, va_list args)
+void *claim(unsigned long virt, unsigned long size, unsigned long align)
 {
-	int len;
-	unsigned long long num;
-	int i, base;
-	char * str;
-	const char *s;
-
-	int flags;		/* flags to number() */
-
-	int field_width;	/* width of output field */
-	int precision;		/* min. # of digits for integers; max
-				   number of chars for from string */
-	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
-	                        /* 'z' support added 23/7/1999 S.H.    */
-				/* 'z' changed to 'Z' --davidm 1/25/99 */
+	int ret;
+	unsigned int result;
 
+	if (need_map < 0)
+		need_map = check_of_version();
+	if (align || !need_map)
+		return (void *) call_prom("claim", 3, 1, virt, size, align);
 	
-	for (str=buf ; *fmt ; ++fmt) {
-		if (*fmt != '%') {
-			*str++ = *fmt;
-			continue;
-		}
-			
-		/* process flags */
-		flags = 0;
-		repeat:
-			++fmt;		/* this also skips first '%' */
-			switch (*fmt) {
-				case '-': flags |= LEFT; goto repeat;
-				case '+': flags |= PLUS; goto repeat;
-				case ' ': flags |= SPACE; goto repeat;
-				case '#': flags |= SPECIAL; goto repeat;
-				case '0': flags |= ZEROPAD; goto repeat;
-				}
-		
-		/* get field width */
-		field_width = -1;
-		if ('0' <= *fmt && *fmt <= '9')
-			field_width = skip_atoi(&fmt);
-		else if (*fmt == '*') {
-			++fmt;
-			/* it's the next argument */
-			field_width = va_arg(args, int);
-			if (field_width < 0) {
-				field_width = -field_width;
-				flags |= LEFT;
-			}
-		}
-
-		/* get the precision */
-		precision = -1;
-		if (*fmt == '.') {
-			++fmt;	
-			if ('0' <= *fmt && *fmt <= '9')
-				precision = skip_atoi(&fmt);
-			else if (*fmt == '*') {
-				++fmt;
-				/* it's the next argument */
-				precision = va_arg(args, int);
-			}
-			if (precision < 0)
-				precision = 0;
-		}
-
-		/* get the conversion qualifier */
-		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
-			qualifier = *fmt;
-			++fmt;
-		}
-
-		/* default base */
-		base = 10;
-
-		switch (*fmt) {
-		case 'c':
-			if (!(flags & LEFT))
-				while (--field_width > 0)
-					*str++ = ' ';
-			*str++ = (unsigned char) va_arg(args, int);
-			while (--field_width > 0)
-				*str++ = ' ';
-			continue;
-
-		case 's':
-			s = va_arg(args, char *);
-			if (!s)
-				s = "<NULL>";
-
-			len = strnlen(s, precision);
-
-			if (!(flags & LEFT))
-				while (len < field_width--)
-					*str++ = ' ';
-			for (i = 0; i < len; ++i)
-				*str++ = *s++;
-			while (len < field_width--)
-				*str++ = ' ';
-			continue;
-
-		case 'p':
-			if (field_width == -1) {
-				field_width = 2*sizeof(void *);
-				flags |= ZEROPAD;
-			}
-			str = number(str,
-				(unsigned long) va_arg(args, void *), 16,
-				field_width, precision, flags);
-			continue;
-
-
-		case 'n':
-			if (qualifier == 'l') {
-				long * ip = va_arg(args, long *);
-				*ip = (str - buf);
-			} else if (qualifier == 'Z') {
-				size_t * ip = va_arg(args, size_t *);
-				*ip = (str - buf);
-			} else {
-				int * ip = va_arg(args, int *);
-				*ip = (str - buf);
-			}
-			continue;
-
-		case '%':
-			*str++ = '%';
-			continue;
-
-		/* integer number formats - set up the flags and "break" */
-		case 'o':
-			base = 8;
-			break;
-
-		case 'X':
-			flags |= LARGE;
-		case 'x':
-			base = 16;
-			break;
-
-		case 'd':
-		case 'i':
-			flags |= SIGN;
-		case 'u':
-			break;
-
-		default:
-			*str++ = '%';
-			if (*fmt)
-				*str++ = *fmt;
-			else
-				--fmt;
-			continue;
-		}
-		if (qualifier == 'l') {
-			num = va_arg(args, unsigned long);
-			if (flags & SIGN)
-				num = (signed long) num;
-		} else if (qualifier == 'Z') {
-			num = va_arg(args, size_t);
-		} else if (qualifier == 'h') {
-			num = (unsigned short) va_arg(args, int);
-			if (flags & SIGN)
-				num = (signed short) num;
-		} else {
-			num = va_arg(args, unsigned int);
-			if (flags & SIGN)
-				num = (signed int) num;
-		}
-		str = number(str, num, base, field_width, precision, flags);
-	}
-	*str = '\0';
-	return str-buf;
-}
-
-int sprintf(char * buf, const char *fmt, ...)
-{
-	va_list args;
-	int i;
-
-	va_start(args, fmt);
-	i=vsprintf(buf,fmt,args);
-	va_end(args);
-	return i;
-}
-
-static char sprint_buf[1024];
-
-int
-printf(const char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	write(stdout, sprint_buf, n);
-	return n;
+	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+			    align, size, virt);
+	if (ret != 0 || result == -1)
+		return (void *) -1;
+	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+			    align, size, virt);
+	/* 0x12 == coherent + read/write */
+	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+			0x12, size, virt, virt);
+	return (void *) virt;
 }
diff -urN powerpc-merge/arch/powerpc/boot/prom.h merge-hack/arch/powerpc/boot/prom.h
--- powerpc-merge/arch/powerpc/boot/prom.h	2005-11-16 13:52:19.000000000 +1100
+++ merge-hack/arch/powerpc/boot/prom.h	2005-11-17 11:11:47.000000000 +1100
@@ -1,18 +1,34 @@
 #ifndef _PPC_BOOT_PROM_H_
 #define _PPC_BOOT_PROM_H_
 
+typedef void *phandle;
+typedef void *ihandle;
+
 extern int (*prom) (void *);
-extern void *chosen_handle;
+extern phandle chosen_handle;
+extern ihandle stdout;
 
-extern void *stdin;
-extern void *stdout;
-extern void *stderr;
+int	call_prom(const char *service, int nargs, int nret, ...);
+int	call_prom_ret(const char *service, int nargs, int nret,
+		      unsigned int *rets, ...);
 
 extern int write(void *handle, void *ptr, int nb);
-extern int read(void *handle, void *ptr, int nb);
-extern void exit(void);
-extern void pause(void);
-extern void *finddevice(const char *);
-extern void *claim(unsigned long virt, unsigned long size, unsigned long align);
-extern int getprop(void *phandle, const char *name, void *buf, int buflen);
+extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
+
+static inline void exit(void)
+{
+	call_prom("exit", 0, 0);
+}
+
+static inline phandle finddevice(const char *name)
+{
+	return (phandle) call_prom("finddevice", 1, 1, name);
+}
+
+static inline int getprop(void *phandle, const char *name,
+			  void *buf, int buflen)
+{
+	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
 #endif				/* _PPC_BOOT_PROM_H_ */
diff -urN powerpc-merge/arch/powerpc/boot/rs6000.h merge-hack/arch/powerpc/boot/rs6000.h
--- /dev/null	2005-04-02 20:23:56.000000000 +1000
+++ merge-hack/arch/powerpc/boot/rs6000.h	2005-11-17 14:57:47.000000000 +1100
@@ -0,0 +1,243 @@
+/* IBM RS/6000 "XCOFF" file definitions for BFD.
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   FIXME: Can someone provide a transliteration of this name into ASCII?
+   Using the following chars caused a compiler warning on HIUX (so I replaced
+   them with octal escapes), and isn't useful without an understanding of what
+   character set it is.
+   Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+   and John Gilmore of Cygnus Support.  */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+	char f_magic[2];	/* magic number			*/
+	char f_nscns[2];	/* number of sections		*/
+	char f_timdat[4];	/* time & date stamp		*/
+	char f_symptr[4];	/* file pointer to symtab	*/
+	char f_nsyms[4];	/* number of symtab entries	*/
+	char f_opthdr[2];	/* sizeof(optional hdr)		*/
+	char f_flags[2];	/* flags			*/
+};
+
+        /* IBM RS/6000 */
+#define U802WRMAGIC     0730    /* writeable text segments **chh**      */
+#define U802ROMAGIC     0735    /* readonly sharable text segments      */
+#define U802TOCMAGIC    0737    /* readonly text segments and TOC       */
+
+#define BADMAG(x)	\
+	((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
+	 (x).f_magic != U802TOCMAGIC)
+
+#define	FILHDR	struct external_filehdr
+#define	FILHSZ	20
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+  unsigned char	magic[2];	/* type of file			*/
+  unsigned char	vstamp[2];	/* version stamp		*/
+  unsigned char	tsize[4];	/* text size in bytes, padded to FW bdry */
+  unsigned char	dsize[4];	/* initialized data "  "	*/
+  unsigned char	bsize[4];	/* uninitialized data "   "	*/
+  unsigned char	entry[4];	/* entry pt.			*/
+  unsigned char	text_start[4];	/* base of text used for this file */
+  unsigned char	data_start[4];	/* base of data used for this file */
+  unsigned char	o_toc[4];	/* address of TOC */
+  unsigned char	o_snentry[2];	/* section number of entry point */
+  unsigned char	o_sntext[2];	/* section number of .text section */
+  unsigned char	o_sndata[2];	/* section number of .data section */
+  unsigned char	o_sntoc[2];	/* section number of TOC */
+  unsigned char	o_snloader[2];	/* section number of .loader section */
+  unsigned char	o_snbss[2];	/* section number of .bss section */
+  unsigned char	o_algntext[2];	/* .text alignment */
+  unsigned char	o_algndata[2];	/* .data alignment */
+  unsigned char	o_modtype[2];	/* module type (??) */
+  unsigned char o_cputype[2];	/* cpu type */
+  unsigned char	o_maxstack[4];	/* max stack size (??) */
+  unsigned char o_maxdata[4];	/* max data size (??) */
+  unsigned char	o_resv2[12];	/* reserved */
+}
+AOUTHDR;
+
+#define AOUTSZ 72
+#define SMALL_AOUTSZ (28)
+#define AOUTHDRSZ 72
+
+#define	RS6K_AOUTHDR_OMAGIC	0x0107	/* old: text & data writeable */
+#define	RS6K_AOUTHDR_NMAGIC	0x0108	/* new: text r/o, data r/w */
+#define	RS6K_AOUTHDR_ZMAGIC	0x010B	/* paged: text r/o, both page-aligned */
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+	char		s_name[8];	/* section name			*/
+	char		s_paddr[4];	/* physical address, aliased s_nlib */
+	char		s_vaddr[4];	/* virtual address		*/
+	char		s_size[4];	/* section size			*/
+	char		s_scnptr[4];	/* file ptr to raw data for section */
+	char		s_relptr[4];	/* file ptr to relocation	*/
+	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
+	char		s_nreloc[2];	/* number of relocation entries	*/
+	char		s_nlnno[2];	/* number of line number entries*/
+	char		s_flags[4];	/* flags			*/
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT	".text"
+#define _DATA	".data"
+#define _BSS	".bss"
+#define _PAD	".pad"
+#define _LOADER	".loader"
+
+#define	SCNHDR	struct external_scnhdr
+#define	SCNHSZ	40
+
+/* XCOFF uses a special .loader section with type STYP_LOADER.  */
+#define STYP_LOADER 0x1000
+
+/* XCOFF uses a special .debug section with type STYP_DEBUG.  */
+#define STYP_DEBUG 0x2000
+
+/* XCOFF handles line number or relocation overflow by creating
+   another section header with STYP_OVRFLO set.  */
+#define STYP_OVRFLO 0x8000
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+	union {
+		char l_symndx[4];	/* function name symbol index, iff l_lnno == 0*/
+		char l_paddr[4];	/* (physical) address of line number	*/
+	} l_addr;
+	char l_lnno[2];	/* line number		*/
+};
+
+
+#define	LINENO	struct external_lineno
+#define	LINESZ	6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
+#define E_FILNMLEN	14	/* # characters in a file name		*/
+#define E_DIMNUM	4	/* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+  union {
+    char e_name[E_SYMNMLEN];
+    struct {
+      char e_zeroes[4];
+      char e_offset[4];
+    } e;
+  } e;
+  char e_value[4];
+  char e_scnum[2];
+  char e_type[2];
+  char e_sclass[1];
+  char e_numaux[1];
+};
+
+
+
+#define N_BTMASK	(017)
+#define N_TMASK		(060)
+#define N_BTSHFT	(4)
+#define N_TSHIFT	(2)
+
+
+union external_auxent {
+	struct {
+		char x_tagndx[4];	/* str, un, or enum tag indx */
+		union {
+			struct {
+			    char  x_lnno[2]; /* declaration line number */
+			    char  x_size[2]; /* str/union/array size */
+			} x_lnsz;
+			char x_fsize[4];	/* size of function */
+		} x_misc;
+		union {
+			struct {		/* if ISFCN, tag, or .bb */
+			    char x_lnnoptr[4];	/* ptr to fcn line # */
+			    char x_endndx[4];	/* entry ndx past block end */
+			} x_fcn;
+			struct {		/* if ISARY, up to 4 dimen. */
+			    char x_dimen[E_DIMNUM][2];
+			} x_ary;
+		} x_fcnary;
+		char x_tvndx[2];		/* tv index */
+	} x_sym;
+
+	union {
+		char x_fname[E_FILNMLEN];
+		struct {
+			char x_zeroes[4];
+			char x_offset[4];
+		} x_n;
+	} x_file;
+
+	struct {
+		char x_scnlen[4];			/* section length */
+		char x_nreloc[2];	/* # relocation entries */
+		char x_nlinno[2];	/* # line numbers */
+	} x_scn;
+
+        struct {
+		char x_tvfill[4];	/* tv fill value */
+		char x_tvlen[2];	/* length of .tv */
+		char x_tvran[2][2];	/* tv range */
+	} x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
+
+	struct {
+		unsigned char x_scnlen[4];
+		unsigned char x_parmhash[4];
+		unsigned char x_snhash[2];
+		unsigned char x_smtyp[1];
+		unsigned char x_smclas[1];
+		unsigned char x_stab[4];
+		unsigned char x_snstab[2];
+	} x_csect;
+
+};
+
+#define	SYMENT	struct external_syment
+#define	SYMESZ	18
+#define	AUXENT	union external_auxent
+#define	AUXESZ	18
+#define DBXMASK 0x80		/* for dbx storage mask */
+#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+  char r_vaddr[4];
+  char r_symndx[4];
+  char r_size[1];
+  char r_type[1];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
diff -urN powerpc-merge/arch/powerpc/boot/stdio.c merge-hack/arch/powerpc/boot/stdio.c
--- /dev/null	2005-04-02 20:23:56.000000000 +1000
+++ merge-hack/arch/powerpc/boot/stdio.c	2005-11-17 14:36:52.000000000 +1100
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
+
+size_t strnlen(const char * s, size_t count)
+{
+	const char *sc;
+
+	for (sc = s; count-- && *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+extern unsigned int __div64_32(unsigned long long *dividend,
+			       unsigned int divisor);
+
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({						\
+	unsigned int __base = (base);					\
+	unsigned int __rem;						\
+	(void)(((typeof((n)) *)0) == ((unsigned long long *)0));	\
+	if (((n) >> 32) == 0) {						\
+		__rem = (unsigned int)(n) % __base;			\
+		(n) = (unsigned int)(n) / __base;			\
+	} else								\
+		__rem = __div64_32(&(n), __base);			\
+	__rem;								\
+ })
+
+static int skip_atoi(const char **s)
+{
+	int i, c;
+
+	for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
+		i = i*10 + c - '0';
+	return i;
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SPECIAL	32		/* 0x */
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
+{
+	char c,sign,tmp[66];
+	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+	int i;
+
+	if (type & LARGE)
+		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	if (base < 2 || base > 36)
+		return 0;
+	c = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if ((signed long long)num < 0) {
+			sign = '-';
+			num = - (signed long long)num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else if (base == 8)
+			size--;
+	}
+	i = 0;
+	if (num == 0)
+		tmp[i++]='0';
+	else while (num != 0) {
+		tmp[i++] = digits[do_div(num, base)];
+	}
+	if (i > precision)
+		precision = i;
+	size -= precision;
+	if (!(type&(ZEROPAD+LEFT)))
+		while(size-->0)
+			*str++ = ' ';
+	if (sign)
+		*str++ = sign;
+	if (type & SPECIAL) {
+		if (base==8)
+			*str++ = '0';
+		else if (base==16) {
+			*str++ = '0';
+			*str++ = digits[33];
+		}
+	}
+	if (!(type & LEFT))
+		while (size-- > 0)
+			*str++ = c;
+	while (i < precision--)
+		*str++ = '0';
+	while (i-- > 0)
+		*str++ = tmp[i];
+	while (size-- > 0)
+		*str++ = ' ';
+	return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	int len;
+	unsigned long long num;
+	int i, base;
+	char * str;
+	const char *s;
+
+	int flags;		/* flags to number() */
+
+	int field_width;	/* width of output field */
+	int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+	                        /* 'z' support added 23/7/1999 S.H.    */
+				/* 'z' changed to 'Z' --davidm 1/25/99 */
+
+	
+	for (str=buf ; *fmt ; ++fmt) {
+		if (*fmt != '%') {
+			*str++ = *fmt;
+			continue;
+		}
+			
+		/* process flags */
+		flags = 0;
+		repeat:
+			++fmt;		/* this also skips first '%' */
+			switch (*fmt) {
+				case '-': flags |= LEFT; goto repeat;
+				case '+': flags |= PLUS; goto repeat;
+				case ' ': flags |= SPACE; goto repeat;
+				case '#': flags |= SPECIAL; goto repeat;
+				case '0': flags |= ZEROPAD; goto repeat;
+				}
+		
+		/* get field width */
+		field_width = -1;
+		if ('0' <= *fmt && *fmt <= '9')
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;	
+			if ('0' <= *fmt && *fmt <= '9')
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+			qualifier = *fmt;
+			++fmt;
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+		case 'c':
+			if (!(flags & LEFT))
+				while (--field_width > 0)
+					*str++ = ' ';
+			*str++ = (unsigned char) va_arg(args, int);
+			while (--field_width > 0)
+				*str++ = ' ';
+			continue;
+
+		case 's':
+			s = va_arg(args, char *);
+			if (!s)
+				s = "<NULL>";
+
+			len = strnlen(s, precision);
+
+			if (!(flags & LEFT))
+				while (len < field_width--)
+					*str++ = ' ';
+			for (i = 0; i < len; ++i)
+				*str++ = *s++;
+			while (len < field_width--)
+				*str++ = ' ';
+			continue;
+
+		case 'p':
+			if (field_width == -1) {
+				field_width = 2*sizeof(void *);
+				flags |= ZEROPAD;
+			}
+			str = number(str,
+				(unsigned long) va_arg(args, void *), 16,
+				field_width, precision, flags);
+			continue;
+
+
+		case 'n':
+			if (qualifier == 'l') {
+				long * ip = va_arg(args, long *);
+				*ip = (str - buf);
+			} else if (qualifier == 'Z') {
+				size_t * ip = va_arg(args, size_t *);
+				*ip = (str - buf);
+			} else {
+				int * ip = va_arg(args, int *);
+				*ip = (str - buf);
+			}
+			continue;
+
+		case '%':
+			*str++ = '%';
+			continue;
+
+		/* integer number formats - set up the flags and "break" */
+		case 'o':
+			base = 8;
+			break;
+
+		case 'X':
+			flags |= LARGE;
+		case 'x':
+			base = 16;
+			break;
+
+		case 'd':
+		case 'i':
+			flags |= SIGN;
+		case 'u':
+			break;
+
+		default:
+			*str++ = '%';
+			if (*fmt)
+				*str++ = *fmt;
+			else
+				--fmt;
+			continue;
+		}
+		if (qualifier == 'l') {
+			num = va_arg(args, unsigned long);
+			if (flags & SIGN)
+				num = (signed long) num;
+		} else if (qualifier == 'Z') {
+			num = va_arg(args, size_t);
+		} else if (qualifier == 'h') {
+			num = (unsigned short) va_arg(args, int);
+			if (flags & SIGN)
+				num = (signed short) num;
+		} else {
+			num = va_arg(args, unsigned int);
+			if (flags & SIGN)
+				num = (signed int) num;
+		}
+		str = number(str, num, base, field_width, precision, flags);
+	}
+	*str = '\0';
+	return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i=vsprintf(buf,fmt,args);
+	va_end(args);
+	return i;
+}
+
+static char sprint_buf[1024];
+
+int
+printf(const char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_buf, fmt, args);
+	va_end(args);
+	write(stdout, sprint_buf, n);
+	return n;
+}
diff -urN powerpc-merge/arch/powerpc/boot/stdio.h merge-hack/arch/powerpc/boot/stdio.h
--- powerpc-merge/arch/powerpc/boot/stdio.h	2005-11-16 13:52:19.000000000 +1100
+++ merge-hack/arch/powerpc/boot/stdio.h	2005-11-17 11:07:34.000000000 +1100
@@ -7,10 +7,4 @@
 
 extern int vsprintf(char *buf, const char *fmt, va_list args);
 
-extern int putc(int c, void *f);
-extern int putchar(int c);
-extern int getchar(void);
-
-extern int fputs(char *str, void *f);
-
 #endif				/* _PPC_BOOT_STDIO_H_ */
diff -urN powerpc-merge/arch/powerpc/boot/zImage.lds merge-hack/arch/powerpc/boot/zImage.lds
--- powerpc-merge/arch/powerpc/boot/zImage.lds	2005-11-16 13:52:19.000000000 +1100
+++ merge-hack/arch/powerpc/boot/zImage.lds	2005-11-16 23:16:48.000000000 +1100
@@ -2,7 +2,7 @@
 ENTRY(_zimage_start)
 SECTIONS
 {
-  . = (4*1024*1024);
+  . = (5*1024*1024);
   _start = .;
   .text      :
   {
@@ -19,22 +19,18 @@
     __got2_start = .;
     *(.got2)
     __got2_end = .;
-  }
 
-  . = ALIGN(4096);
-  _vmlinux_start =  .;
-  .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
-  _vmlinux_end =  .;
+    _vmlinux_start =  .;
+    *(.kernel:vmlinux.strip)
+    _vmlinux_end =  .;
 
-  . = ALIGN(4096);
-  _initrd_start =  .;
-  .kernel:initrd : { *(.kernel:initrd) }
-  _initrd_end =  .;
+    _initrd_start =  .;
+    *(.kernel:initrd)
+    _initrd_end =  .;
+  }
 
   . = ALIGN(4096);
   _edata  =  .;
-
-  . = ALIGN(4096);
   __bss_start = .;
   .bss       :
   {

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-18  6:06 [PATCH] generate COFF zImage in arch/powerpc/boot Paul Mackerras
@ 2005-11-18  7:51 ` Olaf Hering
  2005-11-18 22:13   ` Olaf Hering
  0 siblings, 1 reply; 16+ messages in thread
From: Olaf Hering @ 2005-11-18  7:51 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Fri, Nov 18, Paul Mackeras wrote:


> +++ merge-hack/arch/powerpc/boot/zImage.lds	2005-11-16 23:16:48.000000000 +1100

This change makes arch/powerpc/boot/README obsolete. 
Last time I looked, the COFF loader liked only .text, .data and .bss.
But maybe hack-coff needs some tweaking to modify also other sections.

I was about to do the same changes. There are some comments about the
COFF layout, and PReP, in arch/powerpc/kernel/head_32.S. Some of it can
go.

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-18  7:51 ` Olaf Hering
@ 2005-11-18 22:13   ` Olaf Hering
  2005-11-18 23:16     ` Olaf Hering
  2005-11-19  3:45     ` Paul Mackerras
  0 siblings, 2 replies; 16+ messages in thread
From: Olaf Hering @ 2005-11-18 22:13 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Fri, Nov 18, Olaf Hering wrote:

>  On Fri, Nov 18, Paul Mackeras wrote:
> 
> 
> > +++ merge-hack/arch/powerpc/boot/zImage.lds	2005-11-16 23:16:48.000000000 +1100
> 
> This change makes arch/powerpc/boot/README obsolete. 
> Last time I looked, the COFF loader liked only .text, .data and .bss.
> But maybe hack-coff needs some tweaking to modify also other sections.

I tried to keep the kernel in its own section. But the firmware does not
fully setup the memory range for that section. claim and map calls for
that area are not enough.
So we either need a ld script for coff with kernel and initrd in the
.data section. Or we write a tool to extract the vmlinux.gz and initrd
based on nm or readelf -a output.

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-18 22:13   ` Olaf Hering
@ 2005-11-18 23:16     ` Olaf Hering
  2005-11-19  3:45     ` Paul Mackerras
  1 sibling, 0 replies; 16+ messages in thread
From: Olaf Hering @ 2005-11-18 23:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Fri, Nov 18, Olaf Hering wrote:

>  On Fri, Nov 18, Olaf Hering wrote:
> 
> >  On Fri, Nov 18, Paul Mackeras wrote:
> > 
> > 
> > > +++ merge-hack/arch/powerpc/boot/zImage.lds	2005-11-16 23:16:48.000000000 +1100
> > 
> > This change makes arch/powerpc/boot/README obsolete. 
> > Last time I looked, the COFF loader liked only .text, .data and .bss.
> > But maybe hack-coff needs some tweaking to modify also other sections.
> 
> I tried to keep the kernel in its own section. But the firmware does not
> fully setup the memory range for that section. claim and map calls for
> that area are not enough.

After using your new version of claim, I found that the section is not
copied. It contains only sequences of ff0fffff fff0ff0f.

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-18 22:13   ` Olaf Hering
  2005-11-18 23:16     ` Olaf Hering
@ 2005-11-19  3:45     ` Paul Mackerras
  2005-11-19  8:46       ` Olaf Hering
  2005-11-19 10:29       ` Olaf Hering
  1 sibling, 2 replies; 16+ messages in thread
From: Paul Mackerras @ 2005-11-19  3:45 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev

Olaf Hering writes:

> So we either need a ld script for coff with kernel and initrd in the
> .data section. Or we write a tool to extract the vmlinux.gz and initrd
> based on nm or readelf -a output.

Here's a new version that does the first of those...

The zImage base address could go back to 4MB now.  In fact one could
argue that if OF is based at 12MB and load-base is near zero, linking
it at 6MB would be best.

There is still something I haven't got right: if you do make -j3, it
does this sort of thing:

  STRIP   vmlinux.strip
  STRIP   vmlinux.strip
  GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
  GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
  BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
  BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
mv: cannot stat `arch/powerpc/boot/.kernel-vmlinux.strip.o.tmp': No such file or directory
make[2]: *** [arch/powerpc/boot/kernel-vmlinux.strip.o] Error 1
make[1]: *** [zImage] Error 2

I have no idea why it tries to make those things twice in parallel.
It doesn't do that for vmlinux.

Paul.

diff -urN powerpc/arch/powerpc/Makefile merge-hack/arch/powerpc/Makefile
--- powerpc/arch/powerpc/Makefile	2005-11-18 17:19:11.000000000 +1100
+++ merge-hack/arch/powerpc/Makefile	2005-11-18 17:20:06.000000000 +1100
@@ -138,7 +138,7 @@
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
-defaultimage-$(CONFIG_PPC32)	:= zImage
+defaultimage-$(CONFIG_PPC32)	:= zImage zImage.coff
 defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
 defaultimage-$(CONFIG_PPC_PSERIES) := zImage
 KBUILD_IMAGE := $(defaultimage-y)
@@ -149,7 +149,8 @@
 # All the instructions talk about "make bzImage".
 bzImage: zImage
 
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm \
+	       zImage.vmode zImage.initrd.vmode zImage.coff zImage.initrd.coff
 
 .PHONY: $(BOOT_TARGETS)
 
diff -urN powerpc/arch/powerpc/boot/Makefile merge-hack/arch/powerpc/boot/Makefile
--- powerpc/arch/powerpc/boot/Makefile	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/Makefile	2005-11-19 14:18:04.000000000 +1100
@@ -25,8 +25,8 @@
 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
+OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
 
 zlib       := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
 zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
@@ -35,7 +35,7 @@
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
 
-src-boot := string.S prom.c main.c div64.S crt0.S
+src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
 src-boot += $(zlib)
 src-boot := $(addprefix $(obj)/, $(src-boot))
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@@ -70,7 +70,7 @@
       cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
 
 quiet_cmd_bootld = BOOTLD  $@
-      cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2)
+      cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2)
 
 $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
 	$(call if_changed_dep,bootcc)
@@ -87,12 +87,13 @@
 src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
 gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
 
-hostprogs-y		:= addnote addRamDisk
-targets 		+= zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
-			   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
-			   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
-			   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
-			   vmlinux.initrd
+hostprogs-y		:= addnote addRamDisk hack-coff
+
+targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
+	   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
+	   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
+	   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
+	   vmlinux.initrd
 extra-y			:= initrd.o
 
 quiet_cmd_ramdisk = RAMDISK $@
@@ -114,6 +115,10 @@
 quiet_cmd_addnote = ADDNOTE $@
       cmd_addnote = $(obj)/addnote $@
 
+quiet_cmd_gencoff = COFF    $@
+      cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \
+		    $(obj)/hack-coff $@
+
 $(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
 	$(call if_changed,gzip)
 
@@ -127,13 +132,13 @@
 	$(call if_changed_dep,bootcc)
 	$(call cmd,addsection)
 
-$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
+$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
 $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds
-	$(call cmd,bootld,$(obj-boot))
+	$(call cmd,bootld,$(obj-boot),zImage.lds)
 
-$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
+$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
 $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
-	$(call cmd,bootld,$(obj-boot))
+	$(call cmd,bootld,$(obj-boot),zImage.lds)
 
 $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
 	@cp -f $< $@
@@ -143,6 +148,15 @@
 	@cp -f $< $@
 	$(call if_changed,addnote)
 
+$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
+	$(call cmd,bootld,$(obj-boot),zImage.coff.lds)
+	$(call cmd,gencoff)
+
+$(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \
+			   $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
+	$(call cmd,bootld,$(obj-boot),zImage.coff.lds)
+	$(call cmd,gencoff)
+
 install: $(CONFIGURE) $(BOOTIMAGE)
 	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
 
diff -urN powerpc/arch/powerpc/boot/crt0.S merge-hack/arch/powerpc/boot/crt0.S
--- powerpc/arch/powerpc/boot/crt0.S	2005-11-18 15:57:30.000000000 +1100
+++ merge-hack/arch/powerpc/boot/crt0.S	2005-11-18 22:07:18.000000000 +1100
@@ -12,17 +12,23 @@
 #include "ppc_asm.h"
 
 	.text
+	/* a procedure descriptor used when booting this as a COFF file */
+_zimage_start_opd:
+	.long	_zimage_start, 0, 0, 0
+
 	.globl	_zimage_start
 _zimage_start:
+	/* Work out the offset between the address we were linked at
+	   and the address where we're running. */
 	bl	1f
-
-1:
-	mflr	r0
+1:	mflr	r0
 	lis	r9,1b@ha
 	addi	r9,r9,1b@l
 	subf.	r0,r9,r0
-	beq	3f
+	beq	3f		/* if running at same address as linked */
 
+	/* The .got2 section contains a list of addresses, so add
+	   the address offset onto each entry. */
 	lis	r9,__got2_start@ha
 	addi	r9,r9,__got2_start@l
 	lis	r8,__got2_end@ha
@@ -32,15 +38,14 @@
 	srwi.	r8,r8,2
 	mtctr	r8
 	add	r9,r0,r9
-2:
-	lwz	r8,0(r9)
+2:	lwz	r8,0(r9)
 	add	r8,r8,r0
 	stw	r8,0(r9)
 	addi	r9,r9,4
 	bdnz	2b
 
-3:
-	lis	r9,_start@h
+	/* Do a cache flush for our text, in case OF didn't */
+3:	lis	r9,_start@h
 	add	r9,r0,r9
 	lis	r8,_etext@ha
 	addi	r8,r8,_etext@l
diff -urN powerpc/arch/powerpc/boot/hack-coff.c merge-hack/arch/powerpc/boot/hack-coff.c
--- /dev/null	2005-11-19 12:36:29.626282000 +1100
+++ merge-hack/arch/powerpc/boot/hack-coff.c	2005-11-17 14:57:08.000000000 +1100
@@ -0,0 +1,84 @@
+/*
+ * hack-coff.c - hack the header of an xcoff file to fill in
+ * a few fields needed by the Open Firmware xcoff loader on
+ * Power Macs but not initialized by objcopy.
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include "rs6000.h"
+
+#define AOUT_MAGIC	0x010b
+
+#define get_16be(x)	((((unsigned char *)(x))[0] << 8) \
+			 + ((unsigned char *)(x))[1])
+#define put_16be(x, v)	(((unsigned char *)(x))[0] = (v) >> 8, \
+			 ((unsigned char *)(x))[1] = (v) & 0xff)
+#define get_32be(x)	((((unsigned char *)(x))[0] << 24) \
+			 + (((unsigned char *)(x))[1] << 16) \
+			 + (((unsigned char *)(x))[2] << 8) \
+			 + ((unsigned char *)(x))[3])
+
+int
+main(int ac, char **av)
+{
+    int fd;
+    int i, nsect;
+    int aoutsz;
+    struct external_filehdr fhdr;
+    AOUTHDR aout;
+    struct external_scnhdr shdr;
+
+    if (ac != 2) {
+	fprintf(stderr, "Usage: hack-coff coff-file\n");
+	exit(1);
+    }
+    if ((fd = open(av[1], 2)) == -1) {
+	perror(av[2]);
+	exit(1);
+    }
+    if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
+	goto readerr;
+    i = get_16be(fhdr.f_magic);
+    if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
+	fprintf(stderr, "%s: not an xcoff file\n", av[1]);
+	exit(1);
+    }
+    aoutsz = get_16be(fhdr.f_opthdr);
+    if (read(fd, &aout, aoutsz) != aoutsz)
+	goto readerr;
+    nsect = get_16be(fhdr.f_nscns);
+    for (i = 0; i < nsect; ++i) {
+	if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+	    goto readerr;
+	if (strcmp(shdr.s_name, ".text") == 0) {
+	    put_16be(aout.o_snentry, i+1);
+	    put_16be(aout.o_sntext, i+1);
+	} else if (strcmp(shdr.s_name, ".data") == 0) {
+	    put_16be(aout.o_sndata, i+1);
+	} else if (strcmp(shdr.s_name, ".bss") == 0) {
+	    put_16be(aout.o_snbss, i+1);
+	}
+    }
+    put_16be(aout.magic, AOUT_MAGIC);
+    if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
+	|| write(fd, &aout, aoutsz) != aoutsz) {
+	fprintf(stderr, "%s: write error\n", av[1]);
+	exit(1);
+    }
+    close(fd);
+    exit(0);
+
+readerr:
+    fprintf(stderr, "%s: read error or file too short\n", av[1]);
+    exit(1);
+}
diff -urN powerpc/arch/powerpc/boot/main.c merge-hack/arch/powerpc/boot/main.c
--- powerpc/arch/powerpc/boot/main.c	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/main.c	2005-11-17 14:41:13.000000000 +1100
@@ -21,8 +21,8 @@
 
 
 /* Value picked to match that used by yaboot */
-#define PROG_START	0x01400000
-#define RAM_END		(512<<20) // Fixme: use OF */
+#define PROG_START	0x01400000	/* only used on 64-bit systems */
+#define RAM_END		(512<<20)	/* Fixme: use OF */
 #define	ONE_MB		0x100000
 
 extern char _start[];
@@ -160,6 +160,17 @@
 	elfoffset = (unsigned long)elf64ph->p_offset;
 	vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
 	vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
+
+#if defined(PROG_START)
+	/*
+	 * Maintain a "magic" minimum address. This keeps some older
+	 * firmware platforms running.
+	 */
+
+	if (claim_base < PROG_START)
+		claim_base = PROG_START;
+#endif
+
 	return 1;
 }
 
@@ -206,12 +217,18 @@
 		exit();
 	if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
 		exit();
-	stderr = stdout;
-	if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
-		exit();
 
 	printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
 
+	/*
+	 * The first available claim_base must be above the end of the
+	 * the loaded kernel wrapper file (_start to _end includes the
+	 * initrd image if it is present) and rounded up to a nice
+	 * 1 MB boundary for good measure.
+	 */
+
+	claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
+
 	vmlinuz.addr = (unsigned long)_vmlinux_start;
 	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
 
@@ -228,25 +245,6 @@
 		exit();
 	}
 
-	/*
-	 * The first available claim_base must be above the end of the
-	 * the loaded kernel wrapper file (_start to _end includes the
-	 * initrd image if it is present) and rounded up to a nice
-	 * 1 MB boundary for good measure.
-	 */
-
-	claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
-
-#if defined(PROG_START)
-	/*
-	 * Maintain a "magic" minimum address. This keeps some older
-	 * firmware platforms running.
-	 */
-
-	if (claim_base < PROG_START)
-		claim_base = PROG_START;
-#endif
-
 	/* 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
diff -urN powerpc/arch/powerpc/boot/prom.c merge-hack/arch/powerpc/boot/prom.c
--- powerpc/arch/powerpc/boot/prom.c	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/prom.c	2005-11-17 14:37:12.000000000 +1100
@@ -13,487 +13,153 @@
 #include "prom.h"
 
 int (*prom)(void *);
+phandle chosen_handle;
+ihandle stdout;
 
-void *chosen_handle;
-
-void *stdin;
-void *stdout;
-void *stderr;
-
-
-int
-write(void *handle, void *ptr, int nb)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		void *ihandle;
-		void *addr;
-		int len;
-		int actual;
-	} args;
-
-	args.service = "write";
-	args.nargs = 3;
-	args.nret = 1;
-	args.ihandle = handle;
-	args.addr = ptr;
-	args.len = nb;
-	args.actual = -1;
-	(*prom)(&args);
-	return args.actual;
-}
-
-int
-read(void *handle, void *ptr, int nb)
+int call_prom(const char *service, int nargs, int nret, ...)
 {
+	int i;
 	struct prom_args {
-		char *service;
+		const char *service;
 		int nargs;
 		int nret;
-		void *ihandle;
-		void *addr;
-		int len;
-		int actual;
+		unsigned int args[12];
 	} args;
+	va_list list;
 
-	args.service = "read";
-	args.nargs = 3;
-	args.nret = 1;
-	args.ihandle = handle;
-	args.addr = ptr;
-	args.len = nb;
-	args.actual = -1;
-	(*prom)(&args);
-	return args.actual;
-}
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
 
-void
-exit()
-{
-	struct prom_args {
-		char *service;
-	} args;
+	va_start(list, nret);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
 
-	for (;;) {
-		args.service = "exit";
-		(*prom)(&args);
-	}
-}
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
 
-void
-pause(void)
-{
-	struct prom_args {
-		char *service;
-	} args;
-
-	args.service = "enter";
-	(*prom)(&args);
-}
-
-void *
-finddevice(const char *name)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		const char *devspec;
-		void *phandle;
-	} args;
-
-	args.service = "finddevice";
-	args.nargs = 1;
-	args.nret = 1;
-	args.devspec = name;
-	args.phandle = (void *) -1;
-	(*prom)(&args);
-	return args.phandle;
-}
-
-void *
-claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-	struct prom_args {
-		char *service;
-		int nargs;
-		int nret;
-		unsigned int virt;
-		unsigned int size;
-		unsigned int align;
-		void *ret;
-	} args;
+	if (prom(&args) < 0)
+		return -1;
 
-	args.service = "claim";
-	args.nargs = 3;
-	args.nret = 1;
-	args.virt = virt;
-	args.size = size;
-	args.align = align;
-	(*prom)(&args);
-	return args.ret;
+	return (nret > 0)? args.args[nargs]: 0;
 }
 
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
+int call_prom_ret(const char *service, int nargs, int nret,
+		  unsigned int *rets, ...)
 {
+	int i;
 	struct prom_args {
-		char *service;
+		const char *service;
 		int nargs;
 		int nret;
-		void *phandle;
-		const char *name;
-		void *buf;
-		int buflen;
-		int size;
+		unsigned int args[12];
 	} args;
+	va_list list;
 
-	args.service = "getprop";
-	args.nargs = 4;
-	args.nret = 1;
-	args.phandle = phandle;
-	args.name = name;
-	args.buf = buf;
-	args.buflen = buflen;
-	args.size = -1;
-	(*prom)(&args);
-	return args.size;
-}
+	args.service = service;
+	args.nargs = nargs;
+	args.nret = nret;
 
-int
-putc(int c, void *f)
-{
-	char ch = c;
+	va_start(list, rets);
+	for (i = 0; i < nargs; i++)
+		args.args[i] = va_arg(list, unsigned int);
+	va_end(list);
 
-	if (c == '\n')
-		putc('\r', f);
-	return write(f, &ch, 1) == 1? c: -1;
-}
+	for (i = 0; i < nret; i++)
+		args.args[nargs+i] = 0;
 
-int
-putchar(int c)
-{
-	return putc(c, stdout);
-}
+	if (prom(&args) < 0)
+		return -1;
 
-int
-fputs(char *str, void *f)
-{
-	int n = strlen(str);
+	if (rets != (void *) 0)
+		for (i = 1; i < nret; ++i)
+			rets[i-1] = args.args[nargs+i];
 
-	return write(f, str, n) == n? 0: -1;
+	return (nret > 0)? args.args[nargs]: 0;
 }
 
-size_t strnlen(const char * s, size_t count)
+int write(void *handle, void *ptr, int nb)
 {
-	const char *sc;
-
-	for (sc = s; count-- && *sc != '\0'; ++sc)
-		/* nothing */;
-	return sc - s;
+	return call_prom("write", 3, 1, handle, ptr, nb);
 }
 
-extern unsigned int __div64_32(unsigned long long *dividend,
-			       unsigned int divisor);
-
-/* The unnecessary pointer compare is there
- * to check for type safety (n must be 64bit)
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
  */
-# define do_div(n,base) ({						\
-	unsigned int __base = (base);					\
-	unsigned int __rem;						\
-	(void)(((typeof((n)) *)0) == ((unsigned long long *)0));	\
-	if (((n) >> 32) == 0) {						\
-		__rem = (unsigned int)(n) % __base;			\
-		(n) = (unsigned int)(n) / __base;			\
-	} else								\
-		__rem = __div64_32(&(n), __base);			\
-	__rem;								\
- })
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
 
-static int skip_atoi(const char **s)
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
 {
-	int i, c;
-
-	for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
-		i = i*10 + c - '0';
-	return i;
+	for (; *s2; ++s2)
+		if (*s1++ != *s2)
+			return 0;
+	return 1;
 }
 
-#define ZEROPAD	1		/* pad with zero */
-#define SIGN	2		/* unsigned/signed long */
-#define PLUS	4		/* show plus */
-#define SPACE	8		/* space if plus */
-#define LEFT	16		/* left justified */
-#define SPECIAL	32		/* 0x */
-#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
+static int check_of_version(void)
 {
-	char c,sign,tmp[66];
-	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
-	int i;
+	phandle oprom, chosen;
+	char version[64];
 
-	if (type & LARGE)
-		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-	if (type & LEFT)
-		type &= ~ZEROPAD;
-	if (base < 2 || base > 36)
+	oprom = finddevice("/openprom");
+	if (oprom == (phandle) -1)
+		return 0;
+	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
 		return 0;
-	c = (type & ZEROPAD) ? '0' : ' ';
-	sign = 0;
-	if (type & SIGN) {
-		if ((signed long long)num < 0) {
-			sign = '-';
-			num = - (signed long long)num;
-			size--;
-		} else if (type & PLUS) {
-			sign = '+';
-			size--;
-		} else if (type & SPACE) {
-			sign = ' ';
-			size--;
+	version[sizeof(version)-1] = 0;
+	printf("OF version = '%s'\r\n", version);
+	if (!string_match(version, "Open Firmware, 1.")
+	    && !string_match(version, "FirmWorks,3."))
+		return 0;
+	chosen = finddevice("/chosen");
+	if (chosen == (phandle) -1) {
+		chosen = finddevice("/chosen@0");
+		if (chosen == (phandle) -1) {
+			printf("no chosen\n");
+			return 0;
 		}
 	}
-	if (type & SPECIAL) {
-		if (base == 16)
-			size -= 2;
-		else if (base == 8)
-			size--;
-	}
-	i = 0;
-	if (num == 0)
-		tmp[i++]='0';
-	else while (num != 0) {
-		tmp[i++] = digits[do_div(num, base)];
+	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+		printf("no mmu\n");
+		return 0;
 	}
-	if (i > precision)
-		precision = i;
-	size -= precision;
-	if (!(type&(ZEROPAD+LEFT)))
-		while(size-->0)
-			*str++ = ' ';
-	if (sign)
-		*str++ = sign;
-	if (type & SPECIAL) {
-		if (base==8)
-			*str++ = '0';
-		else if (base==16) {
-			*str++ = '0';
-			*str++ = digits[33];
+	memory = (ihandle) call_prom("open", 1, 1, "/memory");
+	if (memory == (ihandle) -1) {
+		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+		if (memory == (ihandle) -1) {
+			printf("no memory node\n");
+			return 0;
 		}
 	}
-	if (!(type & LEFT))
-		while (size-- > 0)
-			*str++ = c;
-	while (i < precision--)
-		*str++ = '0';
-	while (i-- > 0)
-		*str++ = tmp[i];
-	while (size-- > 0)
-		*str++ = ' ';
-	return str;
+	printf("old OF detected\r\n");
+	return 1;
 }
 
-int vsprintf(char *buf, const char *fmt, va_list args)
+void *claim(unsigned long virt, unsigned long size, unsigned long align)
 {
-	int len;
-	unsigned long long num;
-	int i, base;
-	char * str;
-	const char *s;
-
-	int flags;		/* flags to number() */
-
-	int field_width;	/* width of output field */
-	int precision;		/* min. # of digits for integers; max
-				   number of chars for from string */
-	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
-	                        /* 'z' support added 23/7/1999 S.H.    */
-				/* 'z' changed to 'Z' --davidm 1/25/99 */
+	int ret;
+	unsigned int result;
 
+	if (need_map < 0)
+		need_map = check_of_version();
+	if (align || !need_map)
+		return (void *) call_prom("claim", 3, 1, virt, size, align);
 	
-	for (str=buf ; *fmt ; ++fmt) {
-		if (*fmt != '%') {
-			*str++ = *fmt;
-			continue;
-		}
-			
-		/* process flags */
-		flags = 0;
-		repeat:
-			++fmt;		/* this also skips first '%' */
-			switch (*fmt) {
-				case '-': flags |= LEFT; goto repeat;
-				case '+': flags |= PLUS; goto repeat;
-				case ' ': flags |= SPACE; goto repeat;
-				case '#': flags |= SPECIAL; goto repeat;
-				case '0': flags |= ZEROPAD; goto repeat;
-				}
-		
-		/* get field width */
-		field_width = -1;
-		if ('0' <= *fmt && *fmt <= '9')
-			field_width = skip_atoi(&fmt);
-		else if (*fmt == '*') {
-			++fmt;
-			/* it's the next argument */
-			field_width = va_arg(args, int);
-			if (field_width < 0) {
-				field_width = -field_width;
-				flags |= LEFT;
-			}
-		}
-
-		/* get the precision */
-		precision = -1;
-		if (*fmt == '.') {
-			++fmt;	
-			if ('0' <= *fmt && *fmt <= '9')
-				precision = skip_atoi(&fmt);
-			else if (*fmt == '*') {
-				++fmt;
-				/* it's the next argument */
-				precision = va_arg(args, int);
-			}
-			if (precision < 0)
-				precision = 0;
-		}
-
-		/* get the conversion qualifier */
-		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
-			qualifier = *fmt;
-			++fmt;
-		}
-
-		/* default base */
-		base = 10;
-
-		switch (*fmt) {
-		case 'c':
-			if (!(flags & LEFT))
-				while (--field_width > 0)
-					*str++ = ' ';
-			*str++ = (unsigned char) va_arg(args, int);
-			while (--field_width > 0)
-				*str++ = ' ';
-			continue;
-
-		case 's':
-			s = va_arg(args, char *);
-			if (!s)
-				s = "<NULL>";
-
-			len = strnlen(s, precision);
-
-			if (!(flags & LEFT))
-				while (len < field_width--)
-					*str++ = ' ';
-			for (i = 0; i < len; ++i)
-				*str++ = *s++;
-			while (len < field_width--)
-				*str++ = ' ';
-			continue;
-
-		case 'p':
-			if (field_width == -1) {
-				field_width = 2*sizeof(void *);
-				flags |= ZEROPAD;
-			}
-			str = number(str,
-				(unsigned long) va_arg(args, void *), 16,
-				field_width, precision, flags);
-			continue;
-
-
-		case 'n':
-			if (qualifier == 'l') {
-				long * ip = va_arg(args, long *);
-				*ip = (str - buf);
-			} else if (qualifier == 'Z') {
-				size_t * ip = va_arg(args, size_t *);
-				*ip = (str - buf);
-			} else {
-				int * ip = va_arg(args, int *);
-				*ip = (str - buf);
-			}
-			continue;
-
-		case '%':
-			*str++ = '%';
-			continue;
-
-		/* integer number formats - set up the flags and "break" */
-		case 'o':
-			base = 8;
-			break;
-
-		case 'X':
-			flags |= LARGE;
-		case 'x':
-			base = 16;
-			break;
-
-		case 'd':
-		case 'i':
-			flags |= SIGN;
-		case 'u':
-			break;
-
-		default:
-			*str++ = '%';
-			if (*fmt)
-				*str++ = *fmt;
-			else
-				--fmt;
-			continue;
-		}
-		if (qualifier == 'l') {
-			num = va_arg(args, unsigned long);
-			if (flags & SIGN)
-				num = (signed long) num;
-		} else if (qualifier == 'Z') {
-			num = va_arg(args, size_t);
-		} else if (qualifier == 'h') {
-			num = (unsigned short) va_arg(args, int);
-			if (flags & SIGN)
-				num = (signed short) num;
-		} else {
-			num = va_arg(args, unsigned int);
-			if (flags & SIGN)
-				num = (signed int) num;
-		}
-		str = number(str, num, base, field_width, precision, flags);
-	}
-	*str = '\0';
-	return str-buf;
-}
-
-int sprintf(char * buf, const char *fmt, ...)
-{
-	va_list args;
-	int i;
-
-	va_start(args, fmt);
-	i=vsprintf(buf,fmt,args);
-	va_end(args);
-	return i;
-}
-
-static char sprint_buf[1024];
-
-int
-printf(const char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	write(stdout, sprint_buf, n);
-	return n;
+	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+			    align, size, virt);
+	if (ret != 0 || result == -1)
+		return (void *) -1;
+	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+			    align, size, virt);
+	/* 0x12 == coherent + read/write */
+	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+			0x12, size, virt, virt);
+	return (void *) virt;
 }
diff -urN powerpc/arch/powerpc/boot/prom.h merge-hack/arch/powerpc/boot/prom.h
--- powerpc/arch/powerpc/boot/prom.h	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/prom.h	2005-11-17 11:11:47.000000000 +1100
@@ -1,18 +1,34 @@
 #ifndef _PPC_BOOT_PROM_H_
 #define _PPC_BOOT_PROM_H_
 
+typedef void *phandle;
+typedef void *ihandle;
+
 extern int (*prom) (void *);
-extern void *chosen_handle;
+extern phandle chosen_handle;
+extern ihandle stdout;
 
-extern void *stdin;
-extern void *stdout;
-extern void *stderr;
+int	call_prom(const char *service, int nargs, int nret, ...);
+int	call_prom_ret(const char *service, int nargs, int nret,
+		      unsigned int *rets, ...);
 
 extern int write(void *handle, void *ptr, int nb);
-extern int read(void *handle, void *ptr, int nb);
-extern void exit(void);
-extern void pause(void);
-extern void *finddevice(const char *);
-extern void *claim(unsigned long virt, unsigned long size, unsigned long align);
-extern int getprop(void *phandle, const char *name, void *buf, int buflen);
+extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
+
+static inline void exit(void)
+{
+	call_prom("exit", 0, 0);
+}
+
+static inline phandle finddevice(const char *name)
+{
+	return (phandle) call_prom("finddevice", 1, 1, name);
+}
+
+static inline int getprop(void *phandle, const char *name,
+			  void *buf, int buflen)
+{
+	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
 #endif				/* _PPC_BOOT_PROM_H_ */
diff -urN powerpc/arch/powerpc/boot/rs6000.h merge-hack/arch/powerpc/boot/rs6000.h
--- /dev/null	2005-11-19 12:36:29.626282000 +1100
+++ merge-hack/arch/powerpc/boot/rs6000.h	2005-11-17 14:57:47.000000000 +1100
@@ -0,0 +1,243 @@
+/* IBM RS/6000 "XCOFF" file definitions for BFD.
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   FIXME: Can someone provide a transliteration of this name into ASCII?
+   Using the following chars caused a compiler warning on HIUX (so I replaced
+   them with octal escapes), and isn't useful without an understanding of what
+   character set it is.
+   Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+   and John Gilmore of Cygnus Support.  */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+	char f_magic[2];	/* magic number			*/
+	char f_nscns[2];	/* number of sections		*/
+	char f_timdat[4];	/* time & date stamp		*/
+	char f_symptr[4];	/* file pointer to symtab	*/
+	char f_nsyms[4];	/* number of symtab entries	*/
+	char f_opthdr[2];	/* sizeof(optional hdr)		*/
+	char f_flags[2];	/* flags			*/
+};
+
+        /* IBM RS/6000 */
+#define U802WRMAGIC     0730    /* writeable text segments **chh**      */
+#define U802ROMAGIC     0735    /* readonly sharable text segments      */
+#define U802TOCMAGIC    0737    /* readonly text segments and TOC       */
+
+#define BADMAG(x)	\
+	((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
+	 (x).f_magic != U802TOCMAGIC)
+
+#define	FILHDR	struct external_filehdr
+#define	FILHSZ	20
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+  unsigned char	magic[2];	/* type of file			*/
+  unsigned char	vstamp[2];	/* version stamp		*/
+  unsigned char	tsize[4];	/* text size in bytes, padded to FW bdry */
+  unsigned char	dsize[4];	/* initialized data "  "	*/
+  unsigned char	bsize[4];	/* uninitialized data "   "	*/
+  unsigned char	entry[4];	/* entry pt.			*/
+  unsigned char	text_start[4];	/* base of text used for this file */
+  unsigned char	data_start[4];	/* base of data used for this file */
+  unsigned char	o_toc[4];	/* address of TOC */
+  unsigned char	o_snentry[2];	/* section number of entry point */
+  unsigned char	o_sntext[2];	/* section number of .text section */
+  unsigned char	o_sndata[2];	/* section number of .data section */
+  unsigned char	o_sntoc[2];	/* section number of TOC */
+  unsigned char	o_snloader[2];	/* section number of .loader section */
+  unsigned char	o_snbss[2];	/* section number of .bss section */
+  unsigned char	o_algntext[2];	/* .text alignment */
+  unsigned char	o_algndata[2];	/* .data alignment */
+  unsigned char	o_modtype[2];	/* module type (??) */
+  unsigned char o_cputype[2];	/* cpu type */
+  unsigned char	o_maxstack[4];	/* max stack size (??) */
+  unsigned char o_maxdata[4];	/* max data size (??) */
+  unsigned char	o_resv2[12];	/* reserved */
+}
+AOUTHDR;
+
+#define AOUTSZ 72
+#define SMALL_AOUTSZ (28)
+#define AOUTHDRSZ 72
+
+#define	RS6K_AOUTHDR_OMAGIC	0x0107	/* old: text & data writeable */
+#define	RS6K_AOUTHDR_NMAGIC	0x0108	/* new: text r/o, data r/w */
+#define	RS6K_AOUTHDR_ZMAGIC	0x010B	/* paged: text r/o, both page-aligned */
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+	char		s_name[8];	/* section name			*/
+	char		s_paddr[4];	/* physical address, aliased s_nlib */
+	char		s_vaddr[4];	/* virtual address		*/
+	char		s_size[4];	/* section size			*/
+	char		s_scnptr[4];	/* file ptr to raw data for section */
+	char		s_relptr[4];	/* file ptr to relocation	*/
+	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
+	char		s_nreloc[2];	/* number of relocation entries	*/
+	char		s_nlnno[2];	/* number of line number entries*/
+	char		s_flags[4];	/* flags			*/
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT	".text"
+#define _DATA	".data"
+#define _BSS	".bss"
+#define _PAD	".pad"
+#define _LOADER	".loader"
+
+#define	SCNHDR	struct external_scnhdr
+#define	SCNHSZ	40
+
+/* XCOFF uses a special .loader section with type STYP_LOADER.  */
+#define STYP_LOADER 0x1000
+
+/* XCOFF uses a special .debug section with type STYP_DEBUG.  */
+#define STYP_DEBUG 0x2000
+
+/* XCOFF handles line number or relocation overflow by creating
+   another section header with STYP_OVRFLO set.  */
+#define STYP_OVRFLO 0x8000
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+	union {
+		char l_symndx[4];	/* function name symbol index, iff l_lnno == 0*/
+		char l_paddr[4];	/* (physical) address of line number	*/
+	} l_addr;
+	char l_lnno[2];	/* line number		*/
+};
+
+
+#define	LINENO	struct external_lineno
+#define	LINESZ	6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
+#define E_FILNMLEN	14	/* # characters in a file name		*/
+#define E_DIMNUM	4	/* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+  union {
+    char e_name[E_SYMNMLEN];
+    struct {
+      char e_zeroes[4];
+      char e_offset[4];
+    } e;
+  } e;
+  char e_value[4];
+  char e_scnum[2];
+  char e_type[2];
+  char e_sclass[1];
+  char e_numaux[1];
+};
+
+
+
+#define N_BTMASK	(017)
+#define N_TMASK		(060)
+#define N_BTSHFT	(4)
+#define N_TSHIFT	(2)
+
+
+union external_auxent {
+	struct {
+		char x_tagndx[4];	/* str, un, or enum tag indx */
+		union {
+			struct {
+			    char  x_lnno[2]; /* declaration line number */
+			    char  x_size[2]; /* str/union/array size */
+			} x_lnsz;
+			char x_fsize[4];	/* size of function */
+		} x_misc;
+		union {
+			struct {		/* if ISFCN, tag, or .bb */
+			    char x_lnnoptr[4];	/* ptr to fcn line # */
+			    char x_endndx[4];	/* entry ndx past block end */
+			} x_fcn;
+			struct {		/* if ISARY, up to 4 dimen. */
+			    char x_dimen[E_DIMNUM][2];
+			} x_ary;
+		} x_fcnary;
+		char x_tvndx[2];		/* tv index */
+	} x_sym;
+
+	union {
+		char x_fname[E_FILNMLEN];
+		struct {
+			char x_zeroes[4];
+			char x_offset[4];
+		} x_n;
+	} x_file;
+
+	struct {
+		char x_scnlen[4];			/* section length */
+		char x_nreloc[2];	/* # relocation entries */
+		char x_nlinno[2];	/* # line numbers */
+	} x_scn;
+
+        struct {
+		char x_tvfill[4];	/* tv fill value */
+		char x_tvlen[2];	/* length of .tv */
+		char x_tvran[2][2];	/* tv range */
+	} x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
+
+	struct {
+		unsigned char x_scnlen[4];
+		unsigned char x_parmhash[4];
+		unsigned char x_snhash[2];
+		unsigned char x_smtyp[1];
+		unsigned char x_smclas[1];
+		unsigned char x_stab[4];
+		unsigned char x_snstab[2];
+	} x_csect;
+
+};
+
+#define	SYMENT	struct external_syment
+#define	SYMESZ	18
+#define	AUXENT	union external_auxent
+#define	AUXESZ	18
+#define DBXMASK 0x80		/* for dbx storage mask */
+#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+  char r_vaddr[4];
+  char r_symndx[4];
+  char r_size[1];
+  char r_type[1];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
diff -urN powerpc/arch/powerpc/boot/stdio.c merge-hack/arch/powerpc/boot/stdio.c
--- /dev/null	2005-11-19 12:36:29.626282000 +1100
+++ merge-hack/arch/powerpc/boot/stdio.c	2005-11-17 14:36:52.000000000 +1100
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
+
+size_t strnlen(const char * s, size_t count)
+{
+	const char *sc;
+
+	for (sc = s; count-- && *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+extern unsigned int __div64_32(unsigned long long *dividend,
+			       unsigned int divisor);
+
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({						\
+	unsigned int __base = (base);					\
+	unsigned int __rem;						\
+	(void)(((typeof((n)) *)0) == ((unsigned long long *)0));	\
+	if (((n) >> 32) == 0) {						\
+		__rem = (unsigned int)(n) % __base;			\
+		(n) = (unsigned int)(n) / __base;			\
+	} else								\
+		__rem = __div64_32(&(n), __base);			\
+	__rem;								\
+ })
+
+static int skip_atoi(const char **s)
+{
+	int i, c;
+
+	for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
+		i = i*10 + c - '0';
+	return i;
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SPECIAL	32		/* 0x */
+#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
+{
+	char c,sign,tmp[66];
+	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+	int i;
+
+	if (type & LARGE)
+		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	if (base < 2 || base > 36)
+		return 0;
+	c = (type & ZEROPAD) ? '0' : ' ';
+	sign = 0;
+	if (type & SIGN) {
+		if ((signed long long)num < 0) {
+			sign = '-';
+			num = - (signed long long)num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (type & SPECIAL) {
+		if (base == 16)
+			size -= 2;
+		else if (base == 8)
+			size--;
+	}
+	i = 0;
+	if (num == 0)
+		tmp[i++]='0';
+	else while (num != 0) {
+		tmp[i++] = digits[do_div(num, base)];
+	}
+	if (i > precision)
+		precision = i;
+	size -= precision;
+	if (!(type&(ZEROPAD+LEFT)))
+		while(size-->0)
+			*str++ = ' ';
+	if (sign)
+		*str++ = sign;
+	if (type & SPECIAL) {
+		if (base==8)
+			*str++ = '0';
+		else if (base==16) {
+			*str++ = '0';
+			*str++ = digits[33];
+		}
+	}
+	if (!(type & LEFT))
+		while (size-- > 0)
+			*str++ = c;
+	while (i < precision--)
+		*str++ = '0';
+	while (i-- > 0)
+		*str++ = tmp[i];
+	while (size-- > 0)
+		*str++ = ' ';
+	return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	int len;
+	unsigned long long num;
+	int i, base;
+	char * str;
+	const char *s;
+
+	int flags;		/* flags to number() */
+
+	int field_width;	/* width of output field */
+	int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+	                        /* 'z' support added 23/7/1999 S.H.    */
+				/* 'z' changed to 'Z' --davidm 1/25/99 */
+
+	
+	for (str=buf ; *fmt ; ++fmt) {
+		if (*fmt != '%') {
+			*str++ = *fmt;
+			continue;
+		}
+			
+		/* process flags */
+		flags = 0;
+		repeat:
+			++fmt;		/* this also skips first '%' */
+			switch (*fmt) {
+				case '-': flags |= LEFT; goto repeat;
+				case '+': flags |= PLUS; goto repeat;
+				case ' ': flags |= SPACE; goto repeat;
+				case '#': flags |= SPECIAL; goto repeat;
+				case '0': flags |= ZEROPAD; goto repeat;
+				}
+		
+		/* get field width */
+		field_width = -1;
+		if ('0' <= *fmt && *fmt <= '9')
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;	
+			if ('0' <= *fmt && *fmt <= '9')
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+			qualifier = *fmt;
+			++fmt;
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+		case 'c':
+			if (!(flags & LEFT))
+				while (--field_width > 0)
+					*str++ = ' ';
+			*str++ = (unsigned char) va_arg(args, int);
+			while (--field_width > 0)
+				*str++ = ' ';
+			continue;
+
+		case 's':
+			s = va_arg(args, char *);
+			if (!s)
+				s = "<NULL>";
+
+			len = strnlen(s, precision);
+
+			if (!(flags & LEFT))
+				while (len < field_width--)
+					*str++ = ' ';
+			for (i = 0; i < len; ++i)
+				*str++ = *s++;
+			while (len < field_width--)
+				*str++ = ' ';
+			continue;
+
+		case 'p':
+			if (field_width == -1) {
+				field_width = 2*sizeof(void *);
+				flags |= ZEROPAD;
+			}
+			str = number(str,
+				(unsigned long) va_arg(args, void *), 16,
+				field_width, precision, flags);
+			continue;
+
+
+		case 'n':
+			if (qualifier == 'l') {
+				long * ip = va_arg(args, long *);
+				*ip = (str - buf);
+			} else if (qualifier == 'Z') {
+				size_t * ip = va_arg(args, size_t *);
+				*ip = (str - buf);
+			} else {
+				int * ip = va_arg(args, int *);
+				*ip = (str - buf);
+			}
+			continue;
+
+		case '%':
+			*str++ = '%';
+			continue;
+
+		/* integer number formats - set up the flags and "break" */
+		case 'o':
+			base = 8;
+			break;
+
+		case 'X':
+			flags |= LARGE;
+		case 'x':
+			base = 16;
+			break;
+
+		case 'd':
+		case 'i':
+			flags |= SIGN;
+		case 'u':
+			break;
+
+		default:
+			*str++ = '%';
+			if (*fmt)
+				*str++ = *fmt;
+			else
+				--fmt;
+			continue;
+		}
+		if (qualifier == 'l') {
+			num = va_arg(args, unsigned long);
+			if (flags & SIGN)
+				num = (signed long) num;
+		} else if (qualifier == 'Z') {
+			num = va_arg(args, size_t);
+		} else if (qualifier == 'h') {
+			num = (unsigned short) va_arg(args, int);
+			if (flags & SIGN)
+				num = (signed short) num;
+		} else {
+			num = va_arg(args, unsigned int);
+			if (flags & SIGN)
+				num = (signed int) num;
+		}
+		str = number(str, num, base, field_width, precision, flags);
+	}
+	*str = '\0';
+	return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i=vsprintf(buf,fmt,args);
+	va_end(args);
+	return i;
+}
+
+static char sprint_buf[1024];
+
+int
+printf(const char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_buf, fmt, args);
+	va_end(args);
+	write(stdout, sprint_buf, n);
+	return n;
+}
diff -urN powerpc/arch/powerpc/boot/stdio.h merge-hack/arch/powerpc/boot/stdio.h
--- powerpc/arch/powerpc/boot/stdio.h	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/stdio.h	2005-11-17 11:07:34.000000000 +1100
@@ -7,10 +7,4 @@
 
 extern int vsprintf(char *buf, const char *fmt, va_list args);
 
-extern int putc(int c, void *f);
-extern int putchar(int c);
-extern int getchar(void);
-
-extern int fputs(char *str, void *f);
-
 #endif				/* _PPC_BOOT_STDIO_H_ */
diff -urN powerpc/arch/powerpc/boot/zImage.coff.lds merge-hack/arch/powerpc/boot/zImage.coff.lds
--- /dev/null	2005-11-19 12:36:29.626282000 +1100
+++ merge-hack/arch/powerpc/boot/zImage.coff.lds	2005-11-18 22:19:31.000000000 +1100
@@ -0,0 +1,46 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_start)
+SECTIONS
+{
+  . = (5*1024*1024);
+  _start = .;
+  .text      :
+  {
+    *(.text)
+    *(.fixup)
+  }
+  _etext = .;
+  . = ALIGN(4096);
+  .data    :
+  {
+    *(.rodata*)
+    *(.data*)
+    *(.sdata*)
+    __got2_start = .;
+    *(.got2)
+    __got2_end = .;
+
+    _vmlinux_start =  .;
+    *(.kernel:vmlinux.strip)
+    _vmlinux_end =  .;
+
+    _initrd_start =  .;
+    *(.kernel:initrd)
+    _initrd_end =  .;
+  }
+
+  . = ALIGN(4096);
+  _edata  =  .;
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss)
+   *(.bss)
+  }
+  _end = . ;
+
+  /DISCARD/ :
+  {
+    *(.comment)
+  }
+}
diff -urN powerpc/arch/powerpc/boot/zImage.lds merge-hack/arch/powerpc/boot/zImage.lds
--- powerpc/arch/powerpc/boot/zImage.lds	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/zImage.lds	2005-11-18 21:21:04.000000000 +1100
@@ -2,7 +2,7 @@
 ENTRY(_zimage_start)
 SECTIONS
 {
-  . = (4*1024*1024);
+  . = (5*1024*1024);
   _start = .;
   .text      :
   {
@@ -33,8 +33,6 @@
 
   . = ALIGN(4096);
   _edata  =  .;
-
-  . = ALIGN(4096);
   __bss_start = .;
   .bss       :
   {

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-19  3:45     ` Paul Mackerras
@ 2005-11-19  8:46       ` Olaf Hering
  2005-11-19  9:12         ` Olaf Hering
  2005-11-19 10:29       ` Olaf Hering
  1 sibling, 1 reply; 16+ messages in thread
From: Olaf Hering @ 2005-11-19  8:46 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Sat, Nov 19, Paul Mackeras wrote:

> There is still something I haven't got right: if you do make -j3, it
> does this sort of thing:
> 
>   STRIP   vmlinux.strip
>   STRIP   vmlinux.strip
>   GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
>   GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
>   BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
>   BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
> mv: cannot stat `arch/powerpc/boot/.kernel-vmlinux.strip.o.tmp': No such file or directory
> make[2]: *** [arch/powerpc/boot/kernel-vmlinux.strip.o] Error 1
> make[1]: *** [zImage] Error 2
> 
> I have no idea why it tries to make those things twice in parallel.
> It doesn't do that for vmlinux.

I think this comes from the targets evaluation. Maybe strip needs to be
some sort of serialization:

cmd_stripvm = $(STRIP) -s -R .comment $< -o $@.$$$$ && mv -v $@.$$$$ $@

gzip is also called twice, use the mygzip rule from
arch/ppc/boot/images/Makefile

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-19  8:46       ` Olaf Hering
@ 2005-11-19  9:12         ` Olaf Hering
  0 siblings, 0 replies; 16+ messages in thread
From: Olaf Hering @ 2005-11-19  9:12 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Sat, Nov 19, Olaf Hering wrote:

>  On Sat, Nov 19, Paul Mackeras wrote:
> 
> > There is still something I haven't got right: if you do make -j3, it
> > does this sort of thing:
> > 
> >   STRIP   vmlinux.strip
> >   STRIP   vmlinux.strip
> >   GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
> >   GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
> >   BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
> >   BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
> > mv: cannot stat `arch/powerpc/boot/.kernel-vmlinux.strip.o.tmp': No such file or directory
> > make[2]: *** [arch/powerpc/boot/kernel-vmlinux.strip.o] Error 1
> > make[1]: *** [zImage] Error 2
> > 
> > I have no idea why it tries to make those things twice in parallel.

I got this:
  Building modules, stage 2.
  BOOTAS  arch/powerpc/boot/crt0.o
  BOOTCC  arch/powerpc/boot/prom.o
  BOOTAS  arch/powerpc/boot/crt0.o
  BOOTCC  arch/powerpc/boot/prom.o
  BOOTCC  arch/powerpc/boot/stdio.o
  BOOTCC  arch/powerpc/boot/main.o
  BOOTCC  arch/powerpc/boot/stdio.o
  BOOTCC  arch/powerpc/boot/main.o
  HOSTCC  arch/powerpc/boot/hack-coff
mv: cannot stat `arch/powerpc/boot/.crt0.o.tmp': No such file or directory
make[2]: *** [arch/powerpc/boot/crt0.o] Error 1
make[2]: *** Waiting for unfinished jobs....
mv: cannot stat `arch/powerpc/boot/.prom.o.tmp': No such file or directory
make[2]: *** [arch/powerpc/boot/prom.o] Error 1
fixdep: arch/powerpc/boot/.main.o.d: No such file or directory
make[2]: *** [arch/powerpc/boot/main.o] Error 2
make[1]: *** [zImage] Error 2
make[1]: *** Waiting for unfinished jobs....
mv: cannot stat `arch/powerpc/boot/.stdio.o.tmp': No such file or directory
make[2]: *** [arch/powerpc/boot/stdio.o] Error 1
make[1]: *** [zImage.coff] Error 2

The dependencies need some work.

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-19  3:45     ` Paul Mackerras
  2005-11-19  8:46       ` Olaf Hering
@ 2005-11-19 10:29       ` Olaf Hering
  2005-11-19 17:29         ` Olaf Hering
  1 sibling, 1 reply; 16+ messages in thread
From: Olaf Hering @ 2005-11-19 10:29 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Sat, Nov 19, Paul Mackeras wrote:

> Olaf Hering writes:
> 
> > So we either need a ld script for coff with kernel and initrd in the
> > .data section. Or we write a tool to extract the vmlinux.gz and initrd
> > based on nm or readelf -a output.
> 
> Here's a new version that does the first of those...
> 
> The zImage base address could go back to 4MB now.  In fact one could
> argue that if OF is based at 12MB and load-base is near zero, linking
> it at 6MB would be best.
> 
> There is still something I haven't got right: if you do make -j3, it
> does this sort of thing:
> 
>   STRIP   vmlinux.strip
>   STRIP   vmlinux.strip
>   GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
>   GZIP    arch/powerpc/boot/kernel-vmlinux.strip.gz
>   BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
>   BOOTCC  arch/powerpc/boot/kernel-vmlinux.strip.o
> mv: cannot stat `arch/powerpc/boot/.kernel-vmlinux.strip.o.tmp': No such file or directory
> make[2]: *** [arch/powerpc/boot/kernel-vmlinux.strip.o] Error 1
> make[1]: *** [zImage] Error 2
> 
> I have no idea why it tries to make those things twice in parallel.
> It doesn't do that for vmlinux.

This patch on top of yours fixes it for me.

All members of $(BOOT_TARGETS) will be built in parallel.

make zImage.vmode doesnt work right now, without your patch.
And all it gains is one less host prog and one less zImage file.
Same for zImage.coff. Is it worth the trouble?

 arch/powerpc/Makefile      |    5 ++---
 arch/powerpc/boot/Makefile |   10 +++++-----
 2 files changed, 7 insertions(+), 8 deletions(-)

Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/Makefile
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/Makefile
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/Makefile
@@ -89,7 +89,7 @@ gz-sec  = $(foreach section, $(1), $(pat
 
 hostprogs-y		:= addnote addRamDisk hack-coff
 
-targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
+targets += zImage zImage.initrd \
 	   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
 	   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
 	   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
@@ -132,19 +132,19 @@ $(call obj-sec, $(required) $(initrd)): 
 	$(call if_changed_dep,bootcc)
 	$(call cmd,addsection)
 
-$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
+$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
 $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds
 	$(call cmd,bootld,$(obj-boot),zImage.lds)
 
-$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
+$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
 $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
 	$(call cmd,bootld,$(obj-boot),zImage.lds)
 
-$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
+$(obj)/zImage: $(obj)/zImage.vmode $(obj)/zImage.coff $(obj)/addnote
 	@cp -f $< $@
 	$(call if_changed,addnote)
 
-$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
+$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff $(obj)/addnote
 	@cp -f $< $@
 	$(call if_changed,addnote)
 
Index: linux-2.6.15-rc1-olh/arch/powerpc/Makefile
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/Makefile
+++ linux-2.6.15-rc1-olh/arch/powerpc/Makefile
@@ -138,7 +138,7 @@ drivers-$(CONFIG_CPM2)		+= arch/ppc/8260
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
-defaultimage-$(CONFIG_PPC32)	:= zImage zImage.coff
+defaultimage-$(CONFIG_PPC32)	:= zImage
 defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
 defaultimage-$(CONFIG_PPC_PSERIES) := zImage
 KBUILD_IMAGE := $(defaultimage-y)
@@ -149,8 +149,7 @@ CPPFLAGS_vmlinux.lds	:= -Upowerpc
 # All the instructions talk about "make bzImage".
 bzImage: zImage
 
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm \
-	       zImage.vmode zImage.initrd.vmode zImage.coff zImage.initrd.coff
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
 
 .PHONY: $(BOOT_TARGETS)
 

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-19 10:29       ` Olaf Hering
@ 2005-11-19 17:29         ` Olaf Hering
  2005-11-19 20:47           ` Olaf Hering
  0 siblings, 1 reply; 16+ messages in thread
From: Olaf Hering @ 2005-11-19 17:29 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Sat, Nov 19, Olaf Hering wrote:

> This patch on top of yours fixes it for me.

Another Makefile fix to actually include the kernel in the zImage.coff.

With this my 7200 almost works. There is one thing that I cant explain
right now. alloc_up calls prom_claim at some point, and it stores the
result in alloc_bottom. r30 holds the address where the code is running.
But this reg is 0 after returning from prom_claim. My debug patch below
adds checks for the value of r30, there is no way it can return with r30
being 0, according to the objdump output. But still it does. 
If I enable DEBUG_PROM, and add a 2 or 3 prom_debug calls, everything
works. Any idea what that means?

 arch/powerpc/boot/Makefile      |    2 ++
 arch/powerpc/boot/main.c        |    9 +++------
 arch/powerpc/kernel/prom_init.c |   21 +++++++++++++++++++++
 3 files changed, 26 insertions(+), 6 deletions(-)

Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/Makefile
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/Makefile
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/Makefile
@@ -140,10 +140,12 @@ $(obj)/zImage.initrd.vmode: obj-boot += 
 $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
 	$(call cmd,bootld,$(obj-boot),zImage.lds)
 
+$(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
 $(obj)/zImage: $(obj)/zImage.vmode $(obj)/zImage.coff $(obj)/addnote
 	@cp -f $< $@
 	$(call if_changed,addnote)
 
+$(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
 $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff $(obj)/addnote
 	@cp -f $< $@
 	$(call if_changed,addnote)
Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/main.c
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/main.c
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/main.c
@@ -299,15 +299,12 @@ void start(unsigned long a1, unsigned lo
 	flush_cache((void *)vmlinux.addr, vmlinux.size);
 
 	kernel_entry = (kernel_entry_t)vmlinux.addr;
-#ifdef DEBUG
+#if 1
 	printf( "kernel:\n\r"
 		"        entry addr = 0x%lx\n\r"
 		"        a1         = 0x%lx,\n\r"
-		"        a2         = 0x%lx,\n\r"
-		"        prom       = 0x%lx,\n\r"
-		"        bi_recs    = 0x%lx,\n\r",
-		(unsigned long)kernel_entry, a1, a2,
-		(unsigned long)prom, NULL);
+		"        a2         = 0x%lx,\n\r",
+		(unsigned long)kernel_entry, a1, a2);
 #endif
 
 	kernel_entry(a1, a2, prom, NULL);
Index: linux-2.6.15-rc1-olh/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/kernel/prom_init.c
+++ linux-2.6.15-rc1-olh/arch/powerpc/kernel/prom_init.c
@@ -144,6 +144,7 @@ struct mem_map_entry {
 typedef u32 cell_t;
 
 extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+static inline unsigned long __init olh_reg30(void) { unsigned long reg; __asm__ __volatile__("mr %0,30\n" : "=r" (reg)); return reg; }
 
 #ifdef CONFIG_PPC64
 extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -242,9 +243,13 @@ static int __init call_prom(const char *
 	for (i = 0; i < nret; i++)
 		args.args[nargs+i] = 0;
 
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 	if (enter_prom(&args, RELOC(prom_entry)) < 0)
 		return PROM_ERROR;
 
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 	return (nret > 0) ? args.args[nargs] : 0;
 }
 
@@ -255,6 +260,8 @@ static int __init call_prom_ret(const ch
 	struct prom_args args;
 	va_list list;
 
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 	args.service = ADDR(service);
 	args.nargs = nargs;
 	args.nret = nret;
@@ -274,6 +281,8 @@ static int __init call_prom_ret(const ch
 		for (i = 1; i < nret; ++i)
 			rets[i-1] = args.args[nargs+i];
 
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 	return (nret > 0) ? args.args[nargs] : 0;
 }
 
@@ -364,6 +373,8 @@ static unsigned int __init prom_claim(un
 {
 	struct prom_t *_prom = &RELOC(prom);
 
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 	if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
 		/*
 		 * Old OF requires we claim physical and virtual separately
@@ -375,21 +386,29 @@ static unsigned int __init prom_claim(un
 		ret = call_prom_ret("call-method", 5, 2, &result,
 				    ADDR("claim"), _prom->memory,
 				    align, size, virt);
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 		if (ret != 0 || result == -1)
 			return -1;
 		ret = call_prom_ret("call-method", 5, 2, &result,
 				    ADDR("claim"), _prom->mmumap,
 				    align, size, virt);
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 		if (ret != 0) {
 			call_prom("call-method", 4, 1, ADDR("release"),
 				  _prom->memory, size, virt);
+		asm(".long 0x0\n");
 			return -1;
 		}
 		/* the 0x12 is M (coherence) + PP == read/write */
 		call_prom("call-method", 6, 1,
 			  ADDR("map"), _prom->mmumap, 0x12, size, virt, virt);
+		if (!olh_reg30())
+			asm(".long 0x0\n");
 		return virt;
 	}
+		asm(".long 0x0\n");
 	return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
 			 (prom_arg_t)align);
 }
@@ -752,6 +771,8 @@ static unsigned long __init alloc_up(uns
 	    base = _ALIGN_UP(base + 0x100000, align)) {
 		prom_debug("    trying: 0x%x\n\r", base);
 		addr = (unsigned long)prom_claim(base, size, 0);
+	if (!olh_reg30())
+		asm(".long 0x0\n");
 		if (addr != PROM_ERROR && addr != 0)
 			break;
 		addr = 0;

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-19 17:29         ` Olaf Hering
@ 2005-11-19 20:47           ` Olaf Hering
  2005-11-23 20:21             ` Olaf Hering
  0 siblings, 1 reply; 16+ messages in thread
From: Olaf Hering @ 2005-11-19 20:47 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Sat, Nov 19, Olaf Hering wrote:

>  On Sat, Nov 19, Olaf Hering wrote:
> 
> > This patch on top of yours fixes it for me.
> 
> Another Makefile fix to actually include the kernel in the zImage.coff.

The kernel entry point should be printed unconditional. It helps
debugging the early init when it doesnt run at the link address.

My stack corruption was caused by a bug in call_prom_ret. It uses the
wrong pointer to clear the memory of the return values.

 arch/powerpc/boot/Makefile      |    2 ++
 arch/powerpc/boot/main.c        |   12 ++----------
 arch/powerpc/kernel/prom_init.c |    2 +-
 3 files changed, 5 insertions(+), 11 deletions(-)

Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/Makefile
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/Makefile
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/Makefile
@@ -140,10 +140,12 @@ $(obj)/zImage.initrd.vmode: obj-boot += 
 $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
 	$(call cmd,bootld,$(obj-boot),zImage.lds)
 
+$(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
 $(obj)/zImage: $(obj)/zImage.vmode $(obj)/zImage.coff $(obj)/addnote
 	@cp -f $< $@
 	$(call if_changed,addnote)
 
+$(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
 $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff $(obj)/addnote
 	@cp -f $< $@
 	$(call if_changed,addnote)
Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/main.c
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/main.c
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/main.c
@@ -299,16 +299,8 @@ void start(unsigned long a1, unsigned lo
 	flush_cache((void *)vmlinux.addr, vmlinux.size);
 
 	kernel_entry = (kernel_entry_t)vmlinux.addr;
-#ifdef DEBUG
-	printf( "kernel:\n\r"
-		"        entry addr = 0x%lx\n\r"
-		"        a1         = 0x%lx,\n\r"
-		"        a2         = 0x%lx,\n\r"
-		"        prom       = 0x%lx,\n\r"
-		"        bi_recs    = 0x%lx,\n\r",
-		(unsigned long)kernel_entry, a1, a2,
-		(unsigned long)prom, NULL);
-#endif
+	printf( "entering kernel at 0x%08x(%x/%x/%08x)\n\r",
+		(unsigned long)kernel_entry, a1, a2, prom);
 
 	kernel_entry(a1, a2, prom, NULL);
 
Index: linux-2.6.15-rc1-olh/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/kernel/prom_init.c
+++ linux-2.6.15-rc1-olh/arch/powerpc/kernel/prom_init.c
@@ -265,7 +265,7 @@ static int __init call_prom_ret(const ch
 	va_end(list);
 
 	for (i = 0; i < nret; i++)
-		rets[nargs+i] = 0;
+		args.args[nargs+i] = 0;
 
 	if (enter_prom(&args, RELOC(prom_entry)) < 0)
 		return PROM_ERROR;

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-19 20:47           ` Olaf Hering
@ 2005-11-23 20:21             ` Olaf Hering
  2005-11-23 22:35               ` Paul Mackerras
  0 siblings, 1 reply; 16+ messages in thread
From: Olaf Hering @ 2005-11-23 20:21 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Sat, Nov 19, Olaf Hering wrote:

>  On Sat, Nov 19, Olaf Hering wrote:
> 
> >  On Sat, Nov 19, Olaf Hering wrote:
> > 
> > > This patch on top of yours fixes it for me.
> > 
> > Another Makefile fix to actually include the kernel in the zImage.coff.

It just died while uncompressing vmlinux. Some unaligned load.
So we either need a very simple byte by byte memcpy, or my version below.

0 > boot file: 1.1.1.3,coffloading XCOFF
tsize=4D84 dsize=1542B8 bsize=BC80 entry=500000
SECTIONS:
.text    00500000 00500000 00004D84 000000FC
.data    00505000 00505000 001542B8 00004E80
.bss     0065A000 0065A000 0000BC80 00000000
.note.GN 00000000 00000000 00000000 00000000
loading .text, done..
loading .data, done..
clearing .bss, done..

zImage starting: loaded at 0x00500000 (sp: 0x003fff00)
Allocating 0x4b4660 bytes for kernel ...
OF version = 'Open Firmware, 1.0.5'
old OF detected
gunzipping (0x700000 <- 0x505c44:0x6592b8)...DEFAULT CATCH!, code=FFF00600
 ok
0 > .registers
Client's Fix Pt Regs:
 00 00000001 003FFDF0 00000000 00662183 00629FF6 000039FC 006621C0 9D6528E2
 08 7385808D 005023A0 00000002 005055C0 00000060 DEADBEEF DEADBEEF DEADBEEF
 10 DEADBEEF DEADBEEF DEADBEEF DEADBEEF DEADBEEF 00662183 000039FD 00000000
 18 003FFE80 0002F2FF 0065A45C 0062D9B6 00000000 00000000 0050DBC0 000039FD
Special Regs:
    %IV: 00000600   %SRR0: 005001C8   %SRR1: 00003070     %MQ: 00000000
    %CR: 50000055     %LR: 005023F4    %CTR: 00000737    %XER: E000BE6F
   %DAR: 00629FFE  %DSISR: 00004104   %SDR1: 004E0000
 ok
0 > reset-all


00000000005001a8 <memcpy>:
  5001a8:       54 a7 e8 ff     rlinm.  r7,r5,29,3,31
  5001ac:       38 c3 ff fc     cal     r6,-4(r3)
  5001b0:       38 84 ff fc     cal     r4,-4(r4)
  5001b4:       41 82 00 28     beq     5001dc <memcpy+0x34>
  5001b8:       70 c0 00 03     andil.  r0,r6,3
  5001bc:       7c e9 03 a6     mtctr   r7
  5001c0:       40 82 00 54     bne     500214 <memcpy+0x6c>
  5001c4:       80 e4 00 04     l       r7,4(r4)
  5001c8:       85 04 00 08     lu      r8,8(r4)
  5001cc:       90 e6 00 04     st      r7,4(r6)
  5001d0:       95 06 00 08     stu     r8,8(r6)
  5001d4:       42 00 ff f0     bdn     5001c4 <memcpy+0x1c>

 arch/powerpc/boot/string.S      |  121 +++++++++++++++++++++++++---------------

Index: linux-2.6.15-rc1-olh/arch/powerpc/boot/string.S
===================================================================
--- linux-2.6.15-rc1-olh.orig/arch/powerpc/boot/string.S
+++ linux-2.6.15-rc1-olh/arch/powerpc/boot/string.S
@@ -98,88 +98,124 @@ memset:
 
 	.globl	memmove
 memmove:
+	cmpwi	0,r5,0
+	beqlr
 	cmplw	0,r3,r4
 	bgt	backwards_memcpy
 	/* fall through */
 
 	.globl	memcpy
 memcpy:
+	cmpwi	0,r5,0
+	beqlr
+	andi.	r0,r4,3			/* get src word aligned */
+	beq	20f
+10:	subfic	r0,r0,4
+	cmpd	r0,r5
+	blt	11f
+	mr	r0,r5
+11:	mtctr	r0
+12:	lbz	r7,0(r4)
+	stb	r7,0(r3)
+	addi	r4,r4,1
+	addi	r3,r3,1
+	bdnz	12b
+	subf.	r5,r0,r5
+	beqlr
+20:	andi.	r0,r3,3			/* get dest word aligned */
+	beq	30f
+	subfic	r0,r0,4
+	cmpd	r0,r5
+	blt	21f
+	mr	r0,r5
+21:	mtctr	r0
+22:	lbz	r7,0(r4)
+	stb	r7,0(r3)
+	addi	r4,r4,1
+	addi	r3,r3,1
+	bdnz	22b
+	subf.	r5,r0,r5
+	beqlr
+	andi.	r0,r4,3			/* get src word aligned */
+	bne	10b
+30:
 	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
 	addi	r6,r3,-4
 	addi	r4,r4,-4
-	beq	2f			/* if less than 8 bytes to do */
-	andi.	r0,r6,3			/* get dest word aligned */
+	beq	32f			/* if less than 8 bytes to do */
 	mtctr	r7
-	bne	5f
-1:	lwz	r7,4(r4)
+31:	lwz	r7,4(r4)
 	lwzu	r8,8(r4)
 	stw	r7,4(r6)
 	stwu	r8,8(r6)
-	bdnz	1b
+	bdnz	31b
 	andi.	r5,r5,7
-2:	cmplwi	0,r5,4
-	blt	3f
+32:	cmplwi	0,r5,4
+	blt	33f
 	lwzu	r0,4(r4)
 	addi	r5,r5,-4
 	stwu	r0,4(r6)
-3:	cmpwi	0,r5,0
+33:	cmpwi	0,r5,0
 	beqlr
 	mtctr	r5
 	addi	r4,r4,3
 	addi	r6,r6,3
-4:	lbzu	r0,1(r4)
+34:	lbzu	r0,1(r4)
 	stbu	r0,1(r6)
-	bdnz	4b
+	bdnz	34b
 	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
 
 	.globl	backwards_memcpy
 backwards_memcpy:
-	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
 	add	r6,r3,r5
 	add	r4,r4,r5
-	beq	2f
-	andi.	r0,r6,3
+
+	andi.	r0,r4,3			/* get src word aligned */
+	beq	20f
+10:	cmpd	r0,r5
+	blt	11f
+	mr	r0,r5
+11:	mtctr	r0
+12:	lbzu	r7,-1(r4)
+	stbu	r7,-1(r6)
+	bdnz	12b
+	subf.	r5,r0,r5
+	beqlr
+20:	andi.	r0,r6,3			/* get dest word aligned */
+	beq	30f
+	cmpd	r0,r5
+	blt	21f
+	mr	r0,r5
+21:	mtctr	r0
+22:	lbzu	r7,-1(r4)
+	stbu	r7,-1(r6)
+	bdnz	22b
+	subf.	r5,r0,r5
+	beqlr
+	andi.	r0,r4,3			/* get src word aligned */
+	bne	10b
+30:
+	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
+	beq	32f
 	mtctr	r7
-	bne	5f
-1:	lwz	r7,-4(r4)
+31:	lwz	r7,-4(r4)
 	lwzu	r8,-8(r4)
 	stw	r7,-4(r6)
 	stwu	r8,-8(r6)
-	bdnz	1b
+	bdnz	31b
 	andi.	r5,r5,7
-2:	cmplwi	0,r5,4
-	blt	3f
+32:	cmplwi	0,r5,4
+	blt	33f
 	lwzu	r0,-4(r4)
 	subi	r5,r5,4
 	stwu	r0,-4(r6)
-3:	cmpwi	0,r5,0
+33:	cmpwi	0,r5,0
 	beqlr
 	mtctr	r5
-4:	lbzu	r0,-1(r4)
+34:	lbzu	r0,-1(r4)
 	stbu	r0,-1(r6)
-	bdnz	4b
+	bdnz	34b
 	blr
-5:	mtctr	r0
-6:	lbzu	r7,-1(r4)
-	stbu	r7,-1(r6)
-	bdnz	6b
-	subf	r5,r0,r5
-	rlwinm.	r7,r5,32-3,3,31
-	beq	2b
-	mtctr	r7
-	b	1b
 
 	.globl	memcmp
 memcmp:

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-23 20:21             ` Olaf Hering
@ 2005-11-23 22:35               ` Paul Mackerras
  2005-11-23 22:38                 ` Olaf Hering
  2005-12-10 18:31                 ` Olaf Hering
  0 siblings, 2 replies; 16+ messages in thread
From: Paul Mackerras @ 2005-11-23 22:35 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev

Olaf Hering writes:

> It just died while uncompressing vmlinux. Some unaligned load.
> So we either need a very simple byte by byte memcpy, or my version below.

This should achieve the same effect and is quite a bit simpler.  Your
version looks a bit strange - it copies 1-3 bytes to align the source
pointer, then copies 1-3 bytes to align the destination pointer, then
if the source pointer isn't aligned it goes back and tries again... :)

Regards,
Paul.

diff -urN powerpc/arch/powerpc/boot/string.S merge-hack/arch/powerpc/boot/string.S
--- powerpc/arch/powerpc/boot/string.S	2005-11-16 15:55:17.000000000 +1100
+++ merge-hack/arch/powerpc/boot/string.S	2005-11-24 09:18:47.000000000 +1100
@@ -107,7 +107,7 @@
 	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
 	addi	r6,r3,-4
 	addi	r4,r4,-4
-	beq	2f			/* if less than 8 bytes to do */
+	beq	3f			/* if less than 8 bytes to do */
 	andi.	r0,r6,3			/* get dest word aligned */
 	mtctr	r7
 	bne	5f
@@ -132,6 +132,11 @@
 	bdnz	4b
 	blr
 5:	subfic	r0,r0,4
+	cmpw	cr1,r0,r5
+	add	r7,r0,r4
+	andi.	r7,r7,3			/* will source be word-aligned too? */
+	ble	cr1,3b
+	bne	3b			/* do byte-by-byte if not */
 	mtctr	r0
 6:	lbz	r7,4(r4)
 	addi	r4,r4,1
@@ -149,7 +154,7 @@
 	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
 	add	r6,r3,r5
 	add	r4,r4,r5
-	beq	2f
+	beq	3f
 	andi.	r0,r6,3
 	mtctr	r7
 	bne	5f
@@ -171,7 +176,12 @@
 	stbu	r0,-1(r6)
 	bdnz	4b
 	blr
-5:	mtctr	r0
+5:	cmpw	cr1,r0,r5
+	subf	r7,r0,r4
+	andi.	r7,r7,3
+	ble	cr1,3b
+	bne	3b
+	mtctr	r0
 6:	lbzu	r7,-1(r4)
 	stbu	r7,-1(r6)
 	bdnz	6b

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-23 22:35               ` Paul Mackerras
@ 2005-11-23 22:38                 ` Olaf Hering
  2005-11-23 22:58                   ` Olaf Hering
  2005-11-23 23:06                   ` Paul Mackerras
  2005-12-10 18:31                 ` Olaf Hering
  1 sibling, 2 replies; 16+ messages in thread
From: Olaf Hering @ 2005-11-23 22:38 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Thu, Nov 24, Paul Mackeras wrote:

> Olaf Hering writes:
> 
> > It just died while uncompressing vmlinux. Some unaligned load.
> > So we either need a very simple byte by byte memcpy, or my version below.
> 
> This should achieve the same effect and is quite a bit simpler.  Your
> version looks a bit strange - it copies 1-3 bytes to align the source
> pointer, then copies 1-3 bytes to align the destination pointer, then
> if the source pointer isn't aligned it goes back and tries again... :)

Maybe I miss the point, but if the src is unaligned, and we align it,
dest will change as well and may be unaligned?

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-23 22:38                 ` Olaf Hering
@ 2005-11-23 22:58                   ` Olaf Hering
  2005-11-23 23:06                   ` Paul Mackerras
  1 sibling, 0 replies; 16+ messages in thread
From: Olaf Hering @ 2005-11-23 22:58 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Wed, Nov 23, Olaf Hering wrote:

>  On Thu, Nov 24, Paul Mackeras wrote:
> 
> > Olaf Hering writes:
> > 
> > > It just died while uncompressing vmlinux. Some unaligned load.
> > > So we either need a very simple byte by byte memcpy, or my version below.
> > 
> > This should achieve the same effect and is quite a bit simpler.  Your
> > version looks a bit strange - it copies 1-3 bytes to align the source
> > pointer, then copies 1-3 bytes to align the destination pointer, then
> > if the source pointer isn't aligned it goes back and tries again... :)
> 
> Maybe I miss the point, but if the src is unaligned, and we align it,
> dest will change as well and may be unaligned?

Oh yes, it starts with dest. So everything is alright.

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-23 22:38                 ` Olaf Hering
  2005-11-23 22:58                   ` Olaf Hering
@ 2005-11-23 23:06                   ` Paul Mackerras
  1 sibling, 0 replies; 16+ messages in thread
From: Paul Mackerras @ 2005-11-23 23:06 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev

Olaf Hering writes:

> Maybe I miss the point, but if the src is unaligned, and we align it,
> dest will change as well and may be unaligned?

Yes, but in aligning the dest you will unalign the source.  So with
your patch we will do something like copy 3 bytes, test, copy 1 byte,
test, go back, copy 3 bytes, test, copy 1 byte, etc., on and on until
the whole buffer is copied.  With my patch we get into one loop
copying the whole buffer byte-by-byte.

The other alternative is to work out the appropriate rotate amounts
and masks so that the main loop does load word, rotate, AND, AND, OR,
store word (a bit like the 64-bit kernel memcpy does, except it works
on doublewords not words).  That seems like a lot of trouble to go to
for the bootwrapper though.

Paul.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] generate COFF zImage in arch/powerpc/boot
  2005-11-23 22:35               ` Paul Mackerras
  2005-11-23 22:38                 ` Olaf Hering
@ 2005-12-10 18:31                 ` Olaf Hering
  1 sibling, 0 replies; 16+ messages in thread
From: Olaf Hering @ 2005-12-10 18:31 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

 On Thu, Nov 24, Paul Mackeras wrote:

> Olaf Hering writes:
> 
> > It just died while uncompressing vmlinux. Some unaligned load.
> > So we either need a very simple byte by byte memcpy, or my version below.
> 
> This should achieve the same effect and is quite a bit simpler.  Your
> version looks a bit strange - it copies 1-3 bytes to align the source
> pointer, then copies 1-3 bytes to align the destination pointer, then
> if the source pointer isn't aligned it goes back and tries again... :)

My version worked better:

0 > .registers
Client's Fix Pt Regs:
 00 00000000 003FFDE0 00000000 0115F890 0112FFF5 0000461D 0116007C FAAD15E5
 08 CD12EF34 0000461E 00538042 01167890 0115DBA8 DEADBEEF DEADBEEF DEADBEEF
 10 DEADBEEF DEADBEEF DEADBEEF DEADBEEF 00000006 00000000 0002BA4C 0115F890
 18 0000461D 01133E26 00000000 00000000 003FFE70 0115C16C 0100F991 0000461D
Special Regs:
    %IV: 00000600   %SRR0: 01000EAC   %SRR1: 00003070     %MQ: 00000000
    %CR: 39000035     %LR: 010034CC    %CTR: 000007C5    %XER: E000BE6F
   %DAR: 0112FFFD  %DSISR: 00004104   %SDR1: 004E0000

> diff -urN powerpc/arch/powerpc/boot/string.S merge-hack/arch/powerpc/boot/string.S
> --- powerpc/arch/powerpc/boot/string.S	2005-11-16 15:55:17.000000000 +1100
> +++ merge-hack/arch/powerpc/boot/string.S	2005-11-24 09:18:47.000000000 +1100
> @@ -107,7 +107,7 @@
>  	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
>  	addi	r6,r3,-4
>  	addi	r4,r4,-4
> -	beq	2f			/* if less than 8 bytes to do */
> +	beq	3f			/* if less than 8 bytes to do */
>  	andi.	r0,r6,3			/* get dest word aligned */

r4 is still unaligned at this point,

-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2005-12-10 18:31 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-18  6:06 [PATCH] generate COFF zImage in arch/powerpc/boot Paul Mackerras
2005-11-18  7:51 ` Olaf Hering
2005-11-18 22:13   ` Olaf Hering
2005-11-18 23:16     ` Olaf Hering
2005-11-19  3:45     ` Paul Mackerras
2005-11-19  8:46       ` Olaf Hering
2005-11-19  9:12         ` Olaf Hering
2005-11-19 10:29       ` Olaf Hering
2005-11-19 17:29         ` Olaf Hering
2005-11-19 20:47           ` Olaf Hering
2005-11-23 20:21             ` Olaf Hering
2005-11-23 22:35               ` Paul Mackerras
2005-11-23 22:38                 ` Olaf Hering
2005-11-23 22:58                   ` Olaf Hering
2005-11-23 23:06                   ` Paul Mackerras
2005-12-10 18:31                 ` Olaf Hering

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).