Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66a45dd3 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

powerpc: Make COFF zImages for old 32-bit powermacs



This adds code to build zImage.coff and/or zImage.initrd.coff when
CONFIG_PPC32 and CONFIG_PPC_PMAC are defined.  It also restructures
the OF client code and adds some workarounds for OF quirks on the
older machines.

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 36874579
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ HOSTCC := gcc
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 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(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 @@ quiet_cmd_bootas = BOOTAS $@
      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,8 +87,10 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))

hostprogs-y		:= addnote addRamDisk
hostprogs-y		:= addnote addRamDisk hack-coff

targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
	   zImage.coff zImage.initrd.coff \
	   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
	   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
	   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
@@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@
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,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c
	$(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)

# For 32-bit powermacs, build the COFF images as well as the ELF images.
coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff
coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff

$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y)
	@cp -f $< $@
	$(call if_changed,addnote)

$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y)
	@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)

#-----------------------------------------------------------
# build u-boot images
#-----------------------------------------------------------
+13 −8
Original line number Diff line number Diff line
@@ -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 @@ _zimage_start:
	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
+84 −0
Original line number Diff line number Diff line
/*
 * 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);
}
+22 −24
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long);


/* 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 @@ static int is_elf64(void *hdr)
	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 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
		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 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
		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
+102 −436
Original line number Diff line number Diff line
@@ -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)
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 = "write";
	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;

int
read(void *handle, void *ptr, int nb)
{
	struct prom_args {
		char *service;
		int nargs;
		int nret;
		void *ihandle;
		void *addr;
		int len;
		int actual;
	} args;
	va_start(list, nret);
	for (i = 0; i < nargs; i++)
		args.args[i] = va_arg(list, unsigned int);
	va_end(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;
}
	for (i = 0; i < nret; i++)
		args.args[nargs+i] = 0;

void
exit()
{
	struct prom_args {
		char *service;
	} args;

	for (;;) {
		args.service = "exit";
		(*prom)(&args);
	}
}

void
pause(void)
{
	struct prom_args {
		char *service;
	} args;
	if (prom(&args) < 0)
		return -1;

	args.service = "enter";
	(*prom)(&args);
	return (nret > 0)? args.args[nargs]: 0;
}

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;

	args.service = "claim";
	args.nargs = 3;
	args.nret = 1;
	args.virt = virt;
	args.size = size;
	args.align = align;
	(*prom)(&args);
	return args.ret;
}

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 skip_atoi(const char **s)
{
	int i, c;
static int need_map = -1;
static ihandle chosen_mmu;
static phandle memory;

	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)
/* returns true if s2 is a prefix of s1 */
static int string_match(const char *s1, const char *s2)
{
	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)
	for (; *s2; ++s2)
		if (*s1++ != *s2)
			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;
	return 1;
}

int vsprintf(char *buf, const char *fmt, va_list args)
static int check_of_version(void)
{
	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 */
	phandle oprom, chosen;
	char version[64];

	
	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;
	oprom = finddevice("/openprom");
	if (oprom == (phandle) -1)
		return 0;
	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
		return 0;
	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;
		}
			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 (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
		printf("no mmu\n");
		return 0;
	}
		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;
	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;
		}
		str = number(str, num, base, field_width, precision, flags);
	}
	*str = '\0';
	return str-buf;
	printf("old OF detected\r\n");
	return 1;
}

int sprintf(char * buf, const char *fmt, ...)
void *claim(unsigned long virt, unsigned long size, unsigned long align)
{
	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 ret;
	unsigned int result;

int
printf(const char *fmt, ...)
{
	va_list args;
	int n;
	if (need_map < 0)
		need_map = check_of_version();
	if (align || !need_map)
		return (void *) call_prom("claim", 3, 1, virt, size, align);
	
	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;
}
Loading