* [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).