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: Paul Mackerras <paulus@samba.org>

+905 -509
+34 -15
arch/powerpc/boot/Makefile
··· 25 25 BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ 26 26 $(shell $(CROSS32CC) -print-file-name=include) -fPIC 27 27 BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc 28 - BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds 29 28 OBJCOPYFLAGS := contents,alloc,load,readonly,data 29 + OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 30 30 31 31 zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c 32 32 zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h ··· 35 35 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) 36 36 #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) 37 37 38 - src-boot := string.S prom.c main.c div64.S crt0.S 38 + src-boot := crt0.S string.S prom.c stdio.c main.c div64.S 39 39 src-boot += $(zlib) 40 40 src-boot := $(addprefix $(obj)/, $(src-boot)) 41 41 obj-boot := $(addsuffix .o, $(basename $(src-boot))) ··· 70 70 cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< 71 71 72 72 quiet_cmd_bootld = BOOTLD $@ 73 - cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2) 73 + cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2) 74 74 75 75 $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c 76 76 $(call if_changed_dep,bootcc) ··· 87 87 src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) 88 88 gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) 89 89 90 - hostprogs-y := addnote addRamDisk 91 - targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ 92 - $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ 93 - $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ 94 - $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ 95 - vmlinux.initrd 90 + hostprogs-y := addnote addRamDisk hack-coff 91 + 92 + targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ 93 + zImage.coff zImage.initrd.coff \ 94 + $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ 95 + $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ 96 + $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ 97 + vmlinux.initrd 96 98 extra-y := initrd.o 97 99 98 100 quiet_cmd_ramdisk = RAMDISK $@ ··· 116 114 quiet_cmd_addnote = ADDNOTE $@ 117 115 cmd_addnote = $(obj)/addnote $@ 118 116 117 + quiet_cmd_gencoff = COFF $@ 118 + cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ 119 + $(obj)/hack-coff $@ 120 + 119 121 $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % 120 122 $(call if_changed,gzip) 121 123 ··· 133 127 $(call if_changed_dep,bootcc) 134 128 $(call cmd,addsection) 135 129 136 - $(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) 130 + $(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required)) 137 131 $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds 138 - $(call cmd,bootld,$(obj-boot)) 132 + $(call cmd,bootld,$(obj-boot),zImage.lds) 139 133 140 - $(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) 134 + $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd)) 141 135 $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds 142 - $(call cmd,bootld,$(obj-boot)) 136 + $(call cmd,bootld,$(obj-boot),zImage.lds) 143 137 144 - $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote 138 + # For 32-bit powermacs, build the COFF images as well as the ELF images. 139 + coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff 140 + coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff 141 + 142 + $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) 145 143 @cp -f $< $@ 146 144 $(call if_changed,addnote) 147 145 148 - $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote 146 + $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) 149 147 @cp -f $< $@ 150 148 $(call if_changed,addnote) 149 + 150 + $(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff 151 + $(call cmd,bootld,$(obj-boot),zImage.coff.lds) 152 + $(call cmd,gencoff) 153 + 154 + $(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ 155 + $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff 156 + $(call cmd,bootld,$(obj-boot),zImage.coff.lds) 157 + $(call cmd,gencoff) 151 158 152 159 #----------------------------------------------------------- 153 160 # build u-boot images
+13 -8
arch/powerpc/boot/crt0.S
··· 12 12 #include "ppc_asm.h" 13 13 14 14 .text 15 + /* a procedure descriptor used when booting this as a COFF file */ 16 + _zimage_start_opd: 17 + .long _zimage_start, 0, 0, 0 18 + 15 19 .globl _zimage_start 16 20 _zimage_start: 21 + /* Work out the offset between the address we were linked at 22 + and the address where we're running. */ 17 23 bl 1f 18 - 19 - 1: 20 - mflr r0 24 + 1: mflr r0 21 25 lis r9,1b@ha 22 26 addi r9,r9,1b@l 23 27 subf. r0,r9,r0 24 - beq 3f 28 + beq 3f /* if running at same address as linked */ 25 29 30 + /* The .got2 section contains a list of addresses, so add 31 + the address offset onto each entry. */ 26 32 lis r9,__got2_start@ha 27 33 addi r9,r9,__got2_start@l 28 34 lis r8,__got2_end@ha ··· 38 32 srwi. r8,r8,2 39 33 mtctr r8 40 34 add r9,r0,r9 41 - 2: 42 - lwz r8,0(r9) 35 + 2: lwz r8,0(r9) 43 36 add r8,r8,r0 44 37 stw r8,0(r9) 45 38 addi r9,r9,4 46 39 bdnz 2b 47 40 48 - 3: 49 - lis r9,_start@h 41 + /* Do a cache flush for our text, in case OF didn't */ 42 + 3: lis r9,_start@h 50 43 add r9,r0,r9 51 44 lis r8,_etext@ha 52 45 addi r8,r8,_etext@l
+84
arch/powerpc/boot/hack-coff.c
··· 1 + /* 2 + * hack-coff.c - hack the header of an xcoff file to fill in 3 + * a few fields needed by the Open Firmware xcoff loader on 4 + * Power Macs but not initialized by objcopy. 5 + * 6 + * Copyright (C) Paul Mackerras 1997. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * as published by the Free Software Foundation; either version 11 + * 2 of the License, or (at your option) any later version. 12 + */ 13 + #include <stdio.h> 14 + #include <stdlib.h> 15 + #include <unistd.h> 16 + #include <fcntl.h> 17 + #include <string.h> 18 + #include "rs6000.h" 19 + 20 + #define AOUT_MAGIC 0x010b 21 + 22 + #define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ 23 + + ((unsigned char *)(x))[1]) 24 + #define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ 25 + ((unsigned char *)(x))[1] = (v) & 0xff) 26 + #define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ 27 + + (((unsigned char *)(x))[1] << 16) \ 28 + + (((unsigned char *)(x))[2] << 8) \ 29 + + ((unsigned char *)(x))[3]) 30 + 31 + int 32 + main(int ac, char **av) 33 + { 34 + int fd; 35 + int i, nsect; 36 + int aoutsz; 37 + struct external_filehdr fhdr; 38 + AOUTHDR aout; 39 + struct external_scnhdr shdr; 40 + 41 + if (ac != 2) { 42 + fprintf(stderr, "Usage: hack-coff coff-file\n"); 43 + exit(1); 44 + } 45 + if ((fd = open(av[1], 2)) == -1) { 46 + perror(av[2]); 47 + exit(1); 48 + } 49 + if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) 50 + goto readerr; 51 + i = get_16be(fhdr.f_magic); 52 + if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { 53 + fprintf(stderr, "%s: not an xcoff file\n", av[1]); 54 + exit(1); 55 + } 56 + aoutsz = get_16be(fhdr.f_opthdr); 57 + if (read(fd, &aout, aoutsz) != aoutsz) 58 + goto readerr; 59 + nsect = get_16be(fhdr.f_nscns); 60 + for (i = 0; i < nsect; ++i) { 61 + if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) 62 + goto readerr; 63 + if (strcmp(shdr.s_name, ".text") == 0) { 64 + put_16be(aout.o_snentry, i+1); 65 + put_16be(aout.o_sntext, i+1); 66 + } else if (strcmp(shdr.s_name, ".data") == 0) { 67 + put_16be(aout.o_sndata, i+1); 68 + } else if (strcmp(shdr.s_name, ".bss") == 0) { 69 + put_16be(aout.o_snbss, i+1); 70 + } 71 + } 72 + put_16be(aout.magic, AOUT_MAGIC); 73 + if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 74 + || write(fd, &aout, aoutsz) != aoutsz) { 75 + fprintf(stderr, "%s: write error\n", av[1]); 76 + exit(1); 77 + } 78 + close(fd); 79 + exit(0); 80 + 81 + readerr: 82 + fprintf(stderr, "%s: read error or file too short\n", av[1]); 83 + exit(1); 84 + }
+22 -24
arch/powerpc/boot/main.c
··· 21 21 22 22 23 23 /* Value picked to match that used by yaboot */ 24 - #define PROG_START 0x01400000 25 - #define RAM_END (512<<20) // Fixme: use OF */ 24 + #define PROG_START 0x01400000 /* only used on 64-bit systems */ 25 + #define RAM_END (512<<20) /* Fixme: use OF */ 26 26 #define ONE_MB 0x100000 27 27 28 28 extern char _start[]; ··· 160 160 elfoffset = (unsigned long)elf64ph->p_offset; 161 161 vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; 162 162 vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; 163 + 164 + #if defined(PROG_START) 165 + /* 166 + * Maintain a "magic" minimum address. This keeps some older 167 + * firmware platforms running. 168 + */ 169 + 170 + if (claim_base < PROG_START) 171 + claim_base = PROG_START; 172 + #endif 173 + 163 174 return 1; 164 175 } 165 176 ··· 217 206 exit(); 218 207 if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) 219 208 exit(); 220 - stderr = stdout; 221 - if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) 222 - exit(); 223 209 224 210 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); 211 + 212 + /* 213 + * The first available claim_base must be above the end of the 214 + * the loaded kernel wrapper file (_start to _end includes the 215 + * initrd image if it is present) and rounded up to a nice 216 + * 1 MB boundary for good measure. 217 + */ 218 + 219 + claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); 225 220 226 221 vmlinuz.addr = (unsigned long)_vmlinux_start; 227 222 vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); ··· 244 227 printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); 245 228 exit(); 246 229 } 247 - 248 - /* 249 - * The first available claim_base must be above the end of the 250 - * the loaded kernel wrapper file (_start to _end includes the 251 - * initrd image if it is present) and rounded up to a nice 252 - * 1 MB boundary for good measure. 253 - */ 254 - 255 - claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); 256 - 257 - #if defined(PROG_START) 258 - /* 259 - * Maintain a "magic" minimum address. This keeps some older 260 - * firmware platforms running. 261 - */ 262 - 263 - if (claim_base < PROG_START) 264 - claim_base = PROG_START; 265 - #endif 266 230 267 231 /* We need to claim the memsize plus the file offset since gzip 268 232 * will expand the header (file offset), then the kernel, then
+111 -445
arch/powerpc/boot/prom.c
··· 13 13 #include "prom.h" 14 14 15 15 int (*prom)(void *); 16 + phandle chosen_handle; 17 + ihandle stdout; 16 18 17 - void *chosen_handle; 18 - 19 - void *stdin; 20 - void *stdout; 21 - void *stderr; 22 - 23 - 24 - int 25 - write(void *handle, void *ptr, int nb) 19 + int call_prom(const char *service, int nargs, int nret, ...) 26 20 { 21 + int i; 27 22 struct prom_args { 28 - char *service; 23 + const char *service; 29 24 int nargs; 30 25 int nret; 31 - void *ihandle; 32 - void *addr; 33 - int len; 34 - int actual; 26 + unsigned int args[12]; 35 27 } args; 28 + va_list list; 36 29 37 - args.service = "write"; 38 - args.nargs = 3; 39 - args.nret = 1; 40 - args.ihandle = handle; 41 - args.addr = ptr; 42 - args.len = nb; 43 - args.actual = -1; 44 - (*prom)(&args); 45 - return args.actual; 30 + args.service = service; 31 + args.nargs = nargs; 32 + args.nret = nret; 33 + 34 + va_start(list, nret); 35 + for (i = 0; i < nargs; i++) 36 + args.args[i] = va_arg(list, unsigned int); 37 + va_end(list); 38 + 39 + for (i = 0; i < nret; i++) 40 + args.args[nargs+i] = 0; 41 + 42 + if (prom(&args) < 0) 43 + return -1; 44 + 45 + return (nret > 0)? args.args[nargs]: 0; 46 46 } 47 47 48 - int 49 - read(void *handle, void *ptr, int nb) 48 + int call_prom_ret(const char *service, int nargs, int nret, 49 + unsigned int *rets, ...) 50 50 { 51 + int i; 51 52 struct prom_args { 52 - char *service; 53 + const char *service; 53 54 int nargs; 54 55 int nret; 55 - void *ihandle; 56 - void *addr; 57 - int len; 58 - int actual; 56 + unsigned int args[12]; 59 57 } args; 58 + va_list list; 60 59 61 - args.service = "read"; 62 - args.nargs = 3; 63 - args.nret = 1; 64 - args.ihandle = handle; 65 - args.addr = ptr; 66 - args.len = nb; 67 - args.actual = -1; 68 - (*prom)(&args); 69 - return args.actual; 60 + args.service = service; 61 + args.nargs = nargs; 62 + args.nret = nret; 63 + 64 + va_start(list, rets); 65 + for (i = 0; i < nargs; i++) 66 + args.args[i] = va_arg(list, unsigned int); 67 + va_end(list); 68 + 69 + for (i = 0; i < nret; i++) 70 + args.args[nargs+i] = 0; 71 + 72 + if (prom(&args) < 0) 73 + return -1; 74 + 75 + if (rets != (void *) 0) 76 + for (i = 1; i < nret; ++i) 77 + rets[i-1] = args.args[nargs+i]; 78 + 79 + return (nret > 0)? args.args[nargs]: 0; 70 80 } 71 81 72 - void 73 - exit() 82 + int write(void *handle, void *ptr, int nb) 74 83 { 75 - struct prom_args { 76 - char *service; 77 - } args; 78 - 79 - for (;;) { 80 - args.service = "exit"; 81 - (*prom)(&args); 82 - } 84 + return call_prom("write", 3, 1, handle, ptr, nb); 83 85 } 84 86 85 - void 86 - pause(void) 87 - { 88 - struct prom_args { 89 - char *service; 90 - } args; 91 - 92 - args.service = "enter"; 93 - (*prom)(&args); 94 - } 95 - 96 - void * 97 - finddevice(const char *name) 98 - { 99 - struct prom_args { 100 - char *service; 101 - int nargs; 102 - int nret; 103 - const char *devspec; 104 - void *phandle; 105 - } args; 106 - 107 - args.service = "finddevice"; 108 - args.nargs = 1; 109 - args.nret = 1; 110 - args.devspec = name; 111 - args.phandle = (void *) -1; 112 - (*prom)(&args); 113 - return args.phandle; 114 - } 115 - 116 - void * 117 - claim(unsigned long virt, unsigned long size, unsigned long align) 118 - { 119 - struct prom_args { 120 - char *service; 121 - int nargs; 122 - int nret; 123 - unsigned int virt; 124 - unsigned int size; 125 - unsigned int align; 126 - void *ret; 127 - } args; 128 - 129 - args.service = "claim"; 130 - args.nargs = 3; 131 - args.nret = 1; 132 - args.virt = virt; 133 - args.size = size; 134 - args.align = align; 135 - (*prom)(&args); 136 - return args.ret; 137 - } 138 - 139 - int 140 - getprop(void *phandle, const char *name, void *buf, int buflen) 141 - { 142 - struct prom_args { 143 - char *service; 144 - int nargs; 145 - int nret; 146 - void *phandle; 147 - const char *name; 148 - void *buf; 149 - int buflen; 150 - int size; 151 - } args; 152 - 153 - args.service = "getprop"; 154 - args.nargs = 4; 155 - args.nret = 1; 156 - args.phandle = phandle; 157 - args.name = name; 158 - args.buf = buf; 159 - args.buflen = buflen; 160 - args.size = -1; 161 - (*prom)(&args); 162 - return args.size; 163 - } 164 - 165 - int 166 - putc(int c, void *f) 167 - { 168 - char ch = c; 169 - 170 - if (c == '\n') 171 - putc('\r', f); 172 - return write(f, &ch, 1) == 1? c: -1; 173 - } 174 - 175 - int 176 - putchar(int c) 177 - { 178 - return putc(c, stdout); 179 - } 180 - 181 - int 182 - fputs(char *str, void *f) 183 - { 184 - int n = strlen(str); 185 - 186 - return write(f, str, n) == n? 0: -1; 187 - } 188 - 189 - size_t strnlen(const char * s, size_t count) 190 - { 191 - const char *sc; 192 - 193 - for (sc = s; count-- && *sc != '\0'; ++sc) 194 - /* nothing */; 195 - return sc - s; 196 - } 197 - 198 - extern unsigned int __div64_32(unsigned long long *dividend, 199 - unsigned int divisor); 200 - 201 - /* The unnecessary pointer compare is there 202 - * to check for type safety (n must be 64bit) 87 + /* 88 + * Older OF's require that when claiming a specific range of addresses, 89 + * we claim the physical space in the /memory node and the virtual 90 + * space in the chosen mmu node, and then do a map operation to 91 + * map virtual to physical. 203 92 */ 204 - # define do_div(n,base) ({ \ 205 - unsigned int __base = (base); \ 206 - unsigned int __rem; \ 207 - (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ 208 - if (((n) >> 32) == 0) { \ 209 - __rem = (unsigned int)(n) % __base; \ 210 - (n) = (unsigned int)(n) / __base; \ 211 - } else \ 212 - __rem = __div64_32(&(n), __base); \ 213 - __rem; \ 214 - }) 93 + static int need_map = -1; 94 + static ihandle chosen_mmu; 95 + static phandle memory; 215 96 216 - static int skip_atoi(const char **s) 97 + /* returns true if s2 is a prefix of s1 */ 98 + static int string_match(const char *s1, const char *s2) 217 99 { 218 - int i, c; 219 - 220 - for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) 221 - i = i*10 + c - '0'; 222 - return i; 100 + for (; *s2; ++s2) 101 + if (*s1++ != *s2) 102 + return 0; 103 + return 1; 223 104 } 224 105 225 - #define ZEROPAD 1 /* pad with zero */ 226 - #define SIGN 2 /* unsigned/signed long */ 227 - #define PLUS 4 /* show plus */ 228 - #define SPACE 8 /* space if plus */ 229 - #define LEFT 16 /* left justified */ 230 - #define SPECIAL 32 /* 0x */ 231 - #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 232 - 233 - static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) 106 + static int check_of_version(void) 234 107 { 235 - char c,sign,tmp[66]; 236 - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; 237 - int i; 108 + phandle oprom, chosen; 109 + char version[64]; 238 110 239 - if (type & LARGE) 240 - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 241 - if (type & LEFT) 242 - type &= ~ZEROPAD; 243 - if (base < 2 || base > 36) 111 + oprom = finddevice("/openprom"); 112 + if (oprom == (phandle) -1) 244 113 return 0; 245 - c = (type & ZEROPAD) ? '0' : ' '; 246 - sign = 0; 247 - if (type & SIGN) { 248 - if ((signed long long)num < 0) { 249 - sign = '-'; 250 - num = - (signed long long)num; 251 - size--; 252 - } else if (type & PLUS) { 253 - sign = '+'; 254 - size--; 255 - } else if (type & SPACE) { 256 - sign = ' '; 257 - size--; 114 + if (getprop(oprom, "model", version, sizeof(version)) <= 0) 115 + return 0; 116 + version[sizeof(version)-1] = 0; 117 + printf("OF version = '%s'\r\n", version); 118 + if (!string_match(version, "Open Firmware, 1.") 119 + && !string_match(version, "FirmWorks,3.")) 120 + return 0; 121 + chosen = finddevice("/chosen"); 122 + if (chosen == (phandle) -1) { 123 + chosen = finddevice("/chosen@0"); 124 + if (chosen == (phandle) -1) { 125 + printf("no chosen\n"); 126 + return 0; 258 127 } 259 128 } 260 - if (type & SPECIAL) { 261 - if (base == 16) 262 - size -= 2; 263 - else if (base == 8) 264 - size--; 129 + if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { 130 + printf("no mmu\n"); 131 + return 0; 265 132 } 266 - i = 0; 267 - if (num == 0) 268 - tmp[i++]='0'; 269 - else while (num != 0) { 270 - tmp[i++] = digits[do_div(num, base)]; 271 - } 272 - if (i > precision) 273 - precision = i; 274 - size -= precision; 275 - if (!(type&(ZEROPAD+LEFT))) 276 - while(size-->0) 277 - *str++ = ' '; 278 - if (sign) 279 - *str++ = sign; 280 - if (type & SPECIAL) { 281 - if (base==8) 282 - *str++ = '0'; 283 - else if (base==16) { 284 - *str++ = '0'; 285 - *str++ = digits[33]; 133 + memory = (ihandle) call_prom("open", 1, 1, "/memory"); 134 + if (memory == (ihandle) -1) { 135 + memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); 136 + if (memory == (ihandle) -1) { 137 + printf("no memory node\n"); 138 + return 0; 286 139 } 287 140 } 288 - if (!(type & LEFT)) 289 - while (size-- > 0) 290 - *str++ = c; 291 - while (i < precision--) 292 - *str++ = '0'; 293 - while (i-- > 0) 294 - *str++ = tmp[i]; 295 - while (size-- > 0) 296 - *str++ = ' '; 297 - return str; 141 + printf("old OF detected\r\n"); 142 + return 1; 298 143 } 299 144 300 - int vsprintf(char *buf, const char *fmt, va_list args) 145 + void *claim(unsigned long virt, unsigned long size, unsigned long align) 301 146 { 302 - int len; 303 - unsigned long long num; 304 - int i, base; 305 - char * str; 306 - const char *s; 147 + int ret; 148 + unsigned int result; 307 149 308 - int flags; /* flags to number() */ 309 - 310 - int field_width; /* width of output field */ 311 - int precision; /* min. # of digits for integers; max 312 - number of chars for from string */ 313 - int qualifier; /* 'h', 'l', or 'L' for integer fields */ 314 - /* 'z' support added 23/7/1999 S.H. */ 315 - /* 'z' changed to 'Z' --davidm 1/25/99 */ 316 - 150 + if (need_map < 0) 151 + need_map = check_of_version(); 152 + if (align || !need_map) 153 + return (void *) call_prom("claim", 3, 1, virt, size, align); 317 154 318 - for (str=buf ; *fmt ; ++fmt) { 319 - if (*fmt != '%') { 320 - *str++ = *fmt; 321 - continue; 322 - } 323 - 324 - /* process flags */ 325 - flags = 0; 326 - repeat: 327 - ++fmt; /* this also skips first '%' */ 328 - switch (*fmt) { 329 - case '-': flags |= LEFT; goto repeat; 330 - case '+': flags |= PLUS; goto repeat; 331 - case ' ': flags |= SPACE; goto repeat; 332 - case '#': flags |= SPECIAL; goto repeat; 333 - case '0': flags |= ZEROPAD; goto repeat; 334 - } 335 - 336 - /* get field width */ 337 - field_width = -1; 338 - if ('0' <= *fmt && *fmt <= '9') 339 - field_width = skip_atoi(&fmt); 340 - else if (*fmt == '*') { 341 - ++fmt; 342 - /* it's the next argument */ 343 - field_width = va_arg(args, int); 344 - if (field_width < 0) { 345 - field_width = -field_width; 346 - flags |= LEFT; 347 - } 348 - } 349 - 350 - /* get the precision */ 351 - precision = -1; 352 - if (*fmt == '.') { 353 - ++fmt; 354 - if ('0' <= *fmt && *fmt <= '9') 355 - precision = skip_atoi(&fmt); 356 - else if (*fmt == '*') { 357 - ++fmt; 358 - /* it's the next argument */ 359 - precision = va_arg(args, int); 360 - } 361 - if (precision < 0) 362 - precision = 0; 363 - } 364 - 365 - /* get the conversion qualifier */ 366 - qualifier = -1; 367 - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { 368 - qualifier = *fmt; 369 - ++fmt; 370 - } 371 - 372 - /* default base */ 373 - base = 10; 374 - 375 - switch (*fmt) { 376 - case 'c': 377 - if (!(flags & LEFT)) 378 - while (--field_width > 0) 379 - *str++ = ' '; 380 - *str++ = (unsigned char) va_arg(args, int); 381 - while (--field_width > 0) 382 - *str++ = ' '; 383 - continue; 384 - 385 - case 's': 386 - s = va_arg(args, char *); 387 - if (!s) 388 - s = "<NULL>"; 389 - 390 - len = strnlen(s, precision); 391 - 392 - if (!(flags & LEFT)) 393 - while (len < field_width--) 394 - *str++ = ' '; 395 - for (i = 0; i < len; ++i) 396 - *str++ = *s++; 397 - while (len < field_width--) 398 - *str++ = ' '; 399 - continue; 400 - 401 - case 'p': 402 - if (field_width == -1) { 403 - field_width = 2*sizeof(void *); 404 - flags |= ZEROPAD; 405 - } 406 - str = number(str, 407 - (unsigned long) va_arg(args, void *), 16, 408 - field_width, precision, flags); 409 - continue; 410 - 411 - 412 - case 'n': 413 - if (qualifier == 'l') { 414 - long * ip = va_arg(args, long *); 415 - *ip = (str - buf); 416 - } else if (qualifier == 'Z') { 417 - size_t * ip = va_arg(args, size_t *); 418 - *ip = (str - buf); 419 - } else { 420 - int * ip = va_arg(args, int *); 421 - *ip = (str - buf); 422 - } 423 - continue; 424 - 425 - case '%': 426 - *str++ = '%'; 427 - continue; 428 - 429 - /* integer number formats - set up the flags and "break" */ 430 - case 'o': 431 - base = 8; 432 - break; 433 - 434 - case 'X': 435 - flags |= LARGE; 436 - case 'x': 437 - base = 16; 438 - break; 439 - 440 - case 'd': 441 - case 'i': 442 - flags |= SIGN; 443 - case 'u': 444 - break; 445 - 446 - default: 447 - *str++ = '%'; 448 - if (*fmt) 449 - *str++ = *fmt; 450 - else 451 - --fmt; 452 - continue; 453 - } 454 - if (qualifier == 'l') { 455 - num = va_arg(args, unsigned long); 456 - if (flags & SIGN) 457 - num = (signed long) num; 458 - } else if (qualifier == 'Z') { 459 - num = va_arg(args, size_t); 460 - } else if (qualifier == 'h') { 461 - num = (unsigned short) va_arg(args, int); 462 - if (flags & SIGN) 463 - num = (signed short) num; 464 - } else { 465 - num = va_arg(args, unsigned int); 466 - if (flags & SIGN) 467 - num = (signed int) num; 468 - } 469 - str = number(str, num, base, field_width, precision, flags); 470 - } 471 - *str = '\0'; 472 - return str-buf; 473 - } 474 - 475 - int sprintf(char * buf, const char *fmt, ...) 476 - { 477 - va_list args; 478 - int i; 479 - 480 - va_start(args, fmt); 481 - i=vsprintf(buf,fmt,args); 482 - va_end(args); 483 - return i; 484 - } 485 - 486 - static char sprint_buf[1024]; 487 - 488 - int 489 - printf(const char *fmt, ...) 490 - { 491 - va_list args; 492 - int n; 493 - 494 - va_start(args, fmt); 495 - n = vsprintf(sprint_buf, fmt, args); 496 - va_end(args); 497 - write(stdout, sprint_buf, n); 498 - return n; 155 + ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, 156 + align, size, virt); 157 + if (ret != 0 || result == -1) 158 + return (void *) -1; 159 + ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, 160 + align, size, virt); 161 + /* 0x12 == coherent + read/write */ 162 + ret = call_prom("call-method", 6, 1, "map", chosen_mmu, 163 + 0x12, size, virt, virt); 164 + return (void *) virt; 499 165 }
+27 -11
arch/powerpc/boot/prom.h
··· 1 1 #ifndef _PPC_BOOT_PROM_H_ 2 2 #define _PPC_BOOT_PROM_H_ 3 3 4 - extern int (*prom) (void *); 5 - extern void *chosen_handle; 4 + typedef void *phandle; 5 + typedef void *ihandle; 6 6 7 - extern void *stdin; 8 - extern void *stdout; 9 - extern void *stderr; 7 + extern int (*prom) (void *); 8 + extern phandle chosen_handle; 9 + extern ihandle stdout; 10 + 11 + int call_prom(const char *service, int nargs, int nret, ...); 12 + int call_prom_ret(const char *service, int nargs, int nret, 13 + unsigned int *rets, ...); 10 14 11 15 extern int write(void *handle, void *ptr, int nb); 12 - extern int read(void *handle, void *ptr, int nb); 13 - extern void exit(void); 14 - extern void pause(void); 15 - extern void *finddevice(const char *); 16 - extern void *claim(unsigned long virt, unsigned long size, unsigned long align); 17 - extern int getprop(void *phandle, const char *name, void *buf, int buflen); 16 + extern void *claim(unsigned long virt, unsigned long size, unsigned long aln); 17 + 18 + static inline void exit(void) 19 + { 20 + call_prom("exit", 0, 0); 21 + } 22 + 23 + static inline phandle finddevice(const char *name) 24 + { 25 + return (phandle) call_prom("finddevice", 1, 1, name); 26 + } 27 + 28 + static inline int getprop(void *phandle, const char *name, 29 + void *buf, int buflen) 30 + { 31 + return call_prom("getprop", 4, 1, phandle, name, buf, buflen); 32 + } 33 + 18 34 #endif /* _PPC_BOOT_PROM_H_ */
+243
arch/powerpc/boot/rs6000.h
··· 1 + /* IBM RS/6000 "XCOFF" file definitions for BFD. 2 + Copyright (C) 1990, 1991 Free Software Foundation, Inc. 3 + FIXME: Can someone provide a transliteration of this name into ASCII? 4 + Using the following chars caused a compiler warning on HIUX (so I replaced 5 + them with octal escapes), and isn't useful without an understanding of what 6 + character set it is. 7 + Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM 8 + and John Gilmore of Cygnus Support. */ 9 + 10 + /********************** FILE HEADER **********************/ 11 + 12 + struct external_filehdr { 13 + char f_magic[2]; /* magic number */ 14 + char f_nscns[2]; /* number of sections */ 15 + char f_timdat[4]; /* time & date stamp */ 16 + char f_symptr[4]; /* file pointer to symtab */ 17 + char f_nsyms[4]; /* number of symtab entries */ 18 + char f_opthdr[2]; /* sizeof(optional hdr) */ 19 + char f_flags[2]; /* flags */ 20 + }; 21 + 22 + /* IBM RS/6000 */ 23 + #define U802WRMAGIC 0730 /* writeable text segments **chh** */ 24 + #define U802ROMAGIC 0735 /* readonly sharable text segments */ 25 + #define U802TOCMAGIC 0737 /* readonly text segments and TOC */ 26 + 27 + #define BADMAG(x) \ 28 + ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ 29 + (x).f_magic != U802TOCMAGIC) 30 + 31 + #define FILHDR struct external_filehdr 32 + #define FILHSZ 20 33 + 34 + 35 + /********************** AOUT "OPTIONAL HEADER" **********************/ 36 + 37 + 38 + typedef struct 39 + { 40 + unsigned char magic[2]; /* type of file */ 41 + unsigned char vstamp[2]; /* version stamp */ 42 + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ 43 + unsigned char dsize[4]; /* initialized data " " */ 44 + unsigned char bsize[4]; /* uninitialized data " " */ 45 + unsigned char entry[4]; /* entry pt. */ 46 + unsigned char text_start[4]; /* base of text used for this file */ 47 + unsigned char data_start[4]; /* base of data used for this file */ 48 + unsigned char o_toc[4]; /* address of TOC */ 49 + unsigned char o_snentry[2]; /* section number of entry point */ 50 + unsigned char o_sntext[2]; /* section number of .text section */ 51 + unsigned char o_sndata[2]; /* section number of .data section */ 52 + unsigned char o_sntoc[2]; /* section number of TOC */ 53 + unsigned char o_snloader[2]; /* section number of .loader section */ 54 + unsigned char o_snbss[2]; /* section number of .bss section */ 55 + unsigned char o_algntext[2]; /* .text alignment */ 56 + unsigned char o_algndata[2]; /* .data alignment */ 57 + unsigned char o_modtype[2]; /* module type (??) */ 58 + unsigned char o_cputype[2]; /* cpu type */ 59 + unsigned char o_maxstack[4]; /* max stack size (??) */ 60 + unsigned char o_maxdata[4]; /* max data size (??) */ 61 + unsigned char o_resv2[12]; /* reserved */ 62 + } 63 + AOUTHDR; 64 + 65 + #define AOUTSZ 72 66 + #define SMALL_AOUTSZ (28) 67 + #define AOUTHDRSZ 72 68 + 69 + #define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ 70 + #define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ 71 + #define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ 72 + 73 + 74 + /********************** SECTION HEADER **********************/ 75 + 76 + 77 + struct external_scnhdr { 78 + char s_name[8]; /* section name */ 79 + char s_paddr[4]; /* physical address, aliased s_nlib */ 80 + char s_vaddr[4]; /* virtual address */ 81 + char s_size[4]; /* section size */ 82 + char s_scnptr[4]; /* file ptr to raw data for section */ 83 + char s_relptr[4]; /* file ptr to relocation */ 84 + char s_lnnoptr[4]; /* file ptr to line numbers */ 85 + char s_nreloc[2]; /* number of relocation entries */ 86 + char s_nlnno[2]; /* number of line number entries*/ 87 + char s_flags[4]; /* flags */ 88 + }; 89 + 90 + /* 91 + * names of "special" sections 92 + */ 93 + #define _TEXT ".text" 94 + #define _DATA ".data" 95 + #define _BSS ".bss" 96 + #define _PAD ".pad" 97 + #define _LOADER ".loader" 98 + 99 + #define SCNHDR struct external_scnhdr 100 + #define SCNHSZ 40 101 + 102 + /* XCOFF uses a special .loader section with type STYP_LOADER. */ 103 + #define STYP_LOADER 0x1000 104 + 105 + /* XCOFF uses a special .debug section with type STYP_DEBUG. */ 106 + #define STYP_DEBUG 0x2000 107 + 108 + /* XCOFF handles line number or relocation overflow by creating 109 + another section header with STYP_OVRFLO set. */ 110 + #define STYP_OVRFLO 0x8000 111 + 112 + /********************** LINE NUMBERS **********************/ 113 + 114 + /* 1 line number entry for every "breakpointable" source line in a section. 115 + * Line numbers are grouped on a per function basis; first entry in a function 116 + * grouping will have l_lnno = 0 and in place of physical address will be the 117 + * symbol table index of the function name. 118 + */ 119 + struct external_lineno { 120 + union { 121 + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ 122 + char l_paddr[4]; /* (physical) address of line number */ 123 + } l_addr; 124 + char l_lnno[2]; /* line number */ 125 + }; 126 + 127 + 128 + #define LINENO struct external_lineno 129 + #define LINESZ 6 130 + 131 + 132 + /********************** SYMBOLS **********************/ 133 + 134 + #define E_SYMNMLEN 8 /* # characters in a symbol name */ 135 + #define E_FILNMLEN 14 /* # characters in a file name */ 136 + #define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ 137 + 138 + struct external_syment 139 + { 140 + union { 141 + char e_name[E_SYMNMLEN]; 142 + struct { 143 + char e_zeroes[4]; 144 + char e_offset[4]; 145 + } e; 146 + } e; 147 + char e_value[4]; 148 + char e_scnum[2]; 149 + char e_type[2]; 150 + char e_sclass[1]; 151 + char e_numaux[1]; 152 + }; 153 + 154 + 155 + 156 + #define N_BTMASK (017) 157 + #define N_TMASK (060) 158 + #define N_BTSHFT (4) 159 + #define N_TSHIFT (2) 160 + 161 + 162 + union external_auxent { 163 + struct { 164 + char x_tagndx[4]; /* str, un, or enum tag indx */ 165 + union { 166 + struct { 167 + char x_lnno[2]; /* declaration line number */ 168 + char x_size[2]; /* str/union/array size */ 169 + } x_lnsz; 170 + char x_fsize[4]; /* size of function */ 171 + } x_misc; 172 + union { 173 + struct { /* if ISFCN, tag, or .bb */ 174 + char x_lnnoptr[4]; /* ptr to fcn line # */ 175 + char x_endndx[4]; /* entry ndx past block end */ 176 + } x_fcn; 177 + struct { /* if ISARY, up to 4 dimen. */ 178 + char x_dimen[E_DIMNUM][2]; 179 + } x_ary; 180 + } x_fcnary; 181 + char x_tvndx[2]; /* tv index */ 182 + } x_sym; 183 + 184 + union { 185 + char x_fname[E_FILNMLEN]; 186 + struct { 187 + char x_zeroes[4]; 188 + char x_offset[4]; 189 + } x_n; 190 + } x_file; 191 + 192 + struct { 193 + char x_scnlen[4]; /* section length */ 194 + char x_nreloc[2]; /* # relocation entries */ 195 + char x_nlinno[2]; /* # line numbers */ 196 + } x_scn; 197 + 198 + struct { 199 + char x_tvfill[4]; /* tv fill value */ 200 + char x_tvlen[2]; /* length of .tv */ 201 + char x_tvran[2][2]; /* tv range */ 202 + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ 203 + 204 + struct { 205 + unsigned char x_scnlen[4]; 206 + unsigned char x_parmhash[4]; 207 + unsigned char x_snhash[2]; 208 + unsigned char x_smtyp[1]; 209 + unsigned char x_smclas[1]; 210 + unsigned char x_stab[4]; 211 + unsigned char x_snstab[2]; 212 + } x_csect; 213 + 214 + }; 215 + 216 + #define SYMENT struct external_syment 217 + #define SYMESZ 18 218 + #define AUXENT union external_auxent 219 + #define AUXESZ 18 220 + #define DBXMASK 0x80 /* for dbx storage mask */ 221 + #define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) 222 + 223 + 224 + 225 + /********************** RELOCATION DIRECTIVES **********************/ 226 + 227 + 228 + struct external_reloc { 229 + char r_vaddr[4]; 230 + char r_symndx[4]; 231 + char r_size[1]; 232 + char r_type[1]; 233 + }; 234 + 235 + 236 + #define RELOC struct external_reloc 237 + #define RELSZ 10 238 + 239 + #define DEFAULT_DATA_SECTION_ALIGNMENT 4 240 + #define DEFAULT_BSS_SECTION_ALIGNMENT 4 241 + #define DEFAULT_TEXT_SECTION_ALIGNMENT 4 242 + /* For new sections we havn't heard of before */ 243 + #define DEFAULT_SECTION_ALIGNMENT 4
+325
arch/powerpc/boot/stdio.c
··· 1 + /* 2 + * Copyright (C) Paul Mackerras 1997. 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation; either version 7 + * 2 of the License, or (at your option) any later version. 8 + */ 9 + #include <stdarg.h> 10 + #include <stddef.h> 11 + #include "string.h" 12 + #include "stdio.h" 13 + #include "prom.h" 14 + 15 + size_t strnlen(const char * s, size_t count) 16 + { 17 + const char *sc; 18 + 19 + for (sc = s; count-- && *sc != '\0'; ++sc) 20 + /* nothing */; 21 + return sc - s; 22 + } 23 + 24 + extern unsigned int __div64_32(unsigned long long *dividend, 25 + unsigned int divisor); 26 + 27 + /* The unnecessary pointer compare is there 28 + * to check for type safety (n must be 64bit) 29 + */ 30 + # define do_div(n,base) ({ \ 31 + unsigned int __base = (base); \ 32 + unsigned int __rem; \ 33 + (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ 34 + if (((n) >> 32) == 0) { \ 35 + __rem = (unsigned int)(n) % __base; \ 36 + (n) = (unsigned int)(n) / __base; \ 37 + } else \ 38 + __rem = __div64_32(&(n), __base); \ 39 + __rem; \ 40 + }) 41 + 42 + static int skip_atoi(const char **s) 43 + { 44 + int i, c; 45 + 46 + for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) 47 + i = i*10 + c - '0'; 48 + return i; 49 + } 50 + 51 + #define ZEROPAD 1 /* pad with zero */ 52 + #define SIGN 2 /* unsigned/signed long */ 53 + #define PLUS 4 /* show plus */ 54 + #define SPACE 8 /* space if plus */ 55 + #define LEFT 16 /* left justified */ 56 + #define SPECIAL 32 /* 0x */ 57 + #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 58 + 59 + static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) 60 + { 61 + char c,sign,tmp[66]; 62 + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; 63 + int i; 64 + 65 + if (type & LARGE) 66 + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 67 + if (type & LEFT) 68 + type &= ~ZEROPAD; 69 + if (base < 2 || base > 36) 70 + return 0; 71 + c = (type & ZEROPAD) ? '0' : ' '; 72 + sign = 0; 73 + if (type & SIGN) { 74 + if ((signed long long)num < 0) { 75 + sign = '-'; 76 + num = - (signed long long)num; 77 + size--; 78 + } else if (type & PLUS) { 79 + sign = '+'; 80 + size--; 81 + } else if (type & SPACE) { 82 + sign = ' '; 83 + size--; 84 + } 85 + } 86 + if (type & SPECIAL) { 87 + if (base == 16) 88 + size -= 2; 89 + else if (base == 8) 90 + size--; 91 + } 92 + i = 0; 93 + if (num == 0) 94 + tmp[i++]='0'; 95 + else while (num != 0) { 96 + tmp[i++] = digits[do_div(num, base)]; 97 + } 98 + if (i > precision) 99 + precision = i; 100 + size -= precision; 101 + if (!(type&(ZEROPAD+LEFT))) 102 + while(size-->0) 103 + *str++ = ' '; 104 + if (sign) 105 + *str++ = sign; 106 + if (type & SPECIAL) { 107 + if (base==8) 108 + *str++ = '0'; 109 + else if (base==16) { 110 + *str++ = '0'; 111 + *str++ = digits[33]; 112 + } 113 + } 114 + if (!(type & LEFT)) 115 + while (size-- > 0) 116 + *str++ = c; 117 + while (i < precision--) 118 + *str++ = '0'; 119 + while (i-- > 0) 120 + *str++ = tmp[i]; 121 + while (size-- > 0) 122 + *str++ = ' '; 123 + return str; 124 + } 125 + 126 + int vsprintf(char *buf, const char *fmt, va_list args) 127 + { 128 + int len; 129 + unsigned long long num; 130 + int i, base; 131 + char * str; 132 + const char *s; 133 + 134 + int flags; /* flags to number() */ 135 + 136 + int field_width; /* width of output field */ 137 + int precision; /* min. # of digits for integers; max 138 + number of chars for from string */ 139 + int qualifier; /* 'h', 'l', or 'L' for integer fields */ 140 + /* 'z' support added 23/7/1999 S.H. */ 141 + /* 'z' changed to 'Z' --davidm 1/25/99 */ 142 + 143 + 144 + for (str=buf ; *fmt ; ++fmt) { 145 + if (*fmt != '%') { 146 + *str++ = *fmt; 147 + continue; 148 + } 149 + 150 + /* process flags */ 151 + flags = 0; 152 + repeat: 153 + ++fmt; /* this also skips first '%' */ 154 + switch (*fmt) { 155 + case '-': flags |= LEFT; goto repeat; 156 + case '+': flags |= PLUS; goto repeat; 157 + case ' ': flags |= SPACE; goto repeat; 158 + case '#': flags |= SPECIAL; goto repeat; 159 + case '0': flags |= ZEROPAD; goto repeat; 160 + } 161 + 162 + /* get field width */ 163 + field_width = -1; 164 + if ('0' <= *fmt && *fmt <= '9') 165 + field_width = skip_atoi(&fmt); 166 + else if (*fmt == '*') { 167 + ++fmt; 168 + /* it's the next argument */ 169 + field_width = va_arg(args, int); 170 + if (field_width < 0) { 171 + field_width = -field_width; 172 + flags |= LEFT; 173 + } 174 + } 175 + 176 + /* get the precision */ 177 + precision = -1; 178 + if (*fmt == '.') { 179 + ++fmt; 180 + if ('0' <= *fmt && *fmt <= '9') 181 + precision = skip_atoi(&fmt); 182 + else if (*fmt == '*') { 183 + ++fmt; 184 + /* it's the next argument */ 185 + precision = va_arg(args, int); 186 + } 187 + if (precision < 0) 188 + precision = 0; 189 + } 190 + 191 + /* get the conversion qualifier */ 192 + qualifier = -1; 193 + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { 194 + qualifier = *fmt; 195 + ++fmt; 196 + } 197 + 198 + /* default base */ 199 + base = 10; 200 + 201 + switch (*fmt) { 202 + case 'c': 203 + if (!(flags & LEFT)) 204 + while (--field_width > 0) 205 + *str++ = ' '; 206 + *str++ = (unsigned char) va_arg(args, int); 207 + while (--field_width > 0) 208 + *str++ = ' '; 209 + continue; 210 + 211 + case 's': 212 + s = va_arg(args, char *); 213 + if (!s) 214 + s = "<NULL>"; 215 + 216 + len = strnlen(s, precision); 217 + 218 + if (!(flags & LEFT)) 219 + while (len < field_width--) 220 + *str++ = ' '; 221 + for (i = 0; i < len; ++i) 222 + *str++ = *s++; 223 + while (len < field_width--) 224 + *str++ = ' '; 225 + continue; 226 + 227 + case 'p': 228 + if (field_width == -1) { 229 + field_width = 2*sizeof(void *); 230 + flags |= ZEROPAD; 231 + } 232 + str = number(str, 233 + (unsigned long) va_arg(args, void *), 16, 234 + field_width, precision, flags); 235 + continue; 236 + 237 + 238 + case 'n': 239 + if (qualifier == 'l') { 240 + long * ip = va_arg(args, long *); 241 + *ip = (str - buf); 242 + } else if (qualifier == 'Z') { 243 + size_t * ip = va_arg(args, size_t *); 244 + *ip = (str - buf); 245 + } else { 246 + int * ip = va_arg(args, int *); 247 + *ip = (str - buf); 248 + } 249 + continue; 250 + 251 + case '%': 252 + *str++ = '%'; 253 + continue; 254 + 255 + /* integer number formats - set up the flags and "break" */ 256 + case 'o': 257 + base = 8; 258 + break; 259 + 260 + case 'X': 261 + flags |= LARGE; 262 + case 'x': 263 + base = 16; 264 + break; 265 + 266 + case 'd': 267 + case 'i': 268 + flags |= SIGN; 269 + case 'u': 270 + break; 271 + 272 + default: 273 + *str++ = '%'; 274 + if (*fmt) 275 + *str++ = *fmt; 276 + else 277 + --fmt; 278 + continue; 279 + } 280 + if (qualifier == 'l') { 281 + num = va_arg(args, unsigned long); 282 + if (flags & SIGN) 283 + num = (signed long) num; 284 + } else if (qualifier == 'Z') { 285 + num = va_arg(args, size_t); 286 + } else if (qualifier == 'h') { 287 + num = (unsigned short) va_arg(args, int); 288 + if (flags & SIGN) 289 + num = (signed short) num; 290 + } else { 291 + num = va_arg(args, unsigned int); 292 + if (flags & SIGN) 293 + num = (signed int) num; 294 + } 295 + str = number(str, num, base, field_width, precision, flags); 296 + } 297 + *str = '\0'; 298 + return str-buf; 299 + } 300 + 301 + int sprintf(char * buf, const char *fmt, ...) 302 + { 303 + va_list args; 304 + int i; 305 + 306 + va_start(args, fmt); 307 + i=vsprintf(buf,fmt,args); 308 + va_end(args); 309 + return i; 310 + } 311 + 312 + static char sprint_buf[1024]; 313 + 314 + int 315 + printf(const char *fmt, ...) 316 + { 317 + va_list args; 318 + int n; 319 + 320 + va_start(args, fmt); 321 + n = vsprintf(sprint_buf, fmt, args); 322 + va_end(args); 323 + write(stdout, sprint_buf, n); 324 + return n; 325 + }
-6
arch/powerpc/boot/stdio.h
··· 7 7 8 8 extern int vsprintf(char *buf, const char *fmt, va_list args); 9 9 10 - extern int putc(int c, void *f); 11 - extern int putchar(int c); 12 - extern int getchar(void); 13 - 14 - extern int fputs(char *str, void *f); 15 - 16 10 #endif /* _PPC_BOOT_STDIO_H_ */
+46
arch/powerpc/boot/zImage.coff.lds
··· 1 + OUTPUT_ARCH(powerpc:common) 2 + ENTRY(_start) 3 + SECTIONS 4 + { 5 + . = (5*1024*1024); 6 + _start = .; 7 + .text : 8 + { 9 + *(.text) 10 + *(.fixup) 11 + } 12 + _etext = .; 13 + . = ALIGN(4096); 14 + .data : 15 + { 16 + *(.rodata*) 17 + *(.data*) 18 + *(.sdata*) 19 + __got2_start = .; 20 + *(.got2) 21 + __got2_end = .; 22 + 23 + _vmlinux_start = .; 24 + *(.kernel:vmlinux.strip) 25 + _vmlinux_end = .; 26 + 27 + _initrd_start = .; 28 + *(.kernel:initrd) 29 + _initrd_end = .; 30 + } 31 + 32 + . = ALIGN(4096); 33 + _edata = .; 34 + __bss_start = .; 35 + .bss : 36 + { 37 + *(.sbss) 38 + *(.bss) 39 + } 40 + _end = . ; 41 + 42 + /DISCARD/ : 43 + { 44 + *(.comment) 45 + } 46 + }