diff options
author | Paul Mackerras <paulus@samba.org> | 2006-01-13 23:04:06 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-13 23:04:06 -0500 |
commit | 66a45dd3620ee5f913ba1af3d2dca8b9bdfa2b96 (patch) | |
tree | f98b25a1004d6e6bc84244186db61e76d5b2fe1c /arch/powerpc/boot | |
parent | 36874579dbf4cafa31486d4207c6807efbbf1378 (diff) |
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>
Diffstat (limited to 'arch/powerpc/boot')
-rw-r--r-- | arch/powerpc/boot/Makefile | 49 | ||||
-rw-r--r-- | arch/powerpc/boot/crt0.S | 21 | ||||
-rw-r--r-- | arch/powerpc/boot/hack-coff.c | 84 | ||||
-rw-r--r-- | arch/powerpc/boot/main.c | 46 | ||||
-rw-r--r-- | arch/powerpc/boot/prom.c | 538 | ||||
-rw-r--r-- | arch/powerpc/boot/prom.h | 36 | ||||
-rw-r--r-- | arch/powerpc/boot/rs6000.h | 243 | ||||
-rw-r--r-- | arch/powerpc/boot/stdio.c | 325 | ||||
-rw-r--r-- | arch/powerpc/boot/stdio.h | 6 | ||||
-rw-r--r-- | arch/powerpc/boot/zImage.coff.lds | 46 |
10 files changed, 895 insertions, 499 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index b53d677f6742..788dec4c7ef3 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -25,8 +25,8 @@ HOSTCC := gcc | |||
25 | BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ | 25 | BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ |
26 | $(shell $(CROSS32CC) -print-file-name=include) -fPIC | 26 | $(shell $(CROSS32CC) -print-file-name=include) -fPIC |
27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc | 27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc |
28 | BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds | ||
29 | OBJCOPYFLAGS := contents,alloc,load,readonly,data | 28 | OBJCOPYFLAGS := contents,alloc,load,readonly,data |
29 | OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 | ||
30 | 30 | ||
31 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 31 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c |
32 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h | 32 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h |
@@ -35,7 +35,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h | |||
35 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) | 35 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) |
36 | #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) | 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 | src-boot += $(zlib) | 39 | src-boot += $(zlib) |
40 | src-boot := $(addprefix $(obj)/, $(src-boot)) | 40 | src-boot := $(addprefix $(obj)/, $(src-boot)) |
41 | obj-boot := $(addsuffix .o, $(basename $(src-boot))) | 41 | obj-boot := $(addsuffix .o, $(basename $(src-boot))) |
@@ -70,7 +70,7 @@ quiet_cmd_bootas = BOOTAS $@ | |||
70 | cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< | 70 | cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< |
71 | 71 | ||
72 | quiet_cmd_bootld = BOOTLD $@ | 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 | $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c | 75 | $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c |
76 | $(call if_changed_dep,bootcc) | 76 | $(call if_changed_dep,bootcc) |
@@ -87,12 +87,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section))) | |||
87 | src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) | 87 | src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) |
88 | gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) | 88 | gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) |
89 | 89 | ||
90 | hostprogs-y := addnote addRamDisk | 90 | hostprogs-y := addnote addRamDisk hack-coff |
91 | targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ | 91 | |
92 | $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ | 92 | targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ |
93 | $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ | 93 | zImage.coff zImage.initrd.coff \ |
94 | $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ | 94 | $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ |
95 | vmlinux.initrd | 95 | $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ |
96 | $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ | ||
97 | vmlinux.initrd | ||
96 | extra-y := initrd.o | 98 | extra-y := initrd.o |
97 | 99 | ||
98 | quiet_cmd_ramdisk = RAMDISK $@ | 100 | quiet_cmd_ramdisk = RAMDISK $@ |
@@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@ | |||
114 | quiet_cmd_addnote = ADDNOTE $@ | 116 | quiet_cmd_addnote = ADDNOTE $@ |
115 | cmd_addnote = $(obj)/addnote $@ | 117 | cmd_addnote = $(obj)/addnote $@ |
116 | 118 | ||
119 | quiet_cmd_gencoff = COFF $@ | ||
120 | cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ | ||
121 | $(obj)/hack-coff $@ | ||
122 | |||
117 | $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % | 123 | $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % |
118 | $(call if_changed,gzip) | 124 | $(call if_changed,gzip) |
119 | 125 | ||
@@ -127,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c | |||
127 | $(call if_changed_dep,bootcc) | 133 | $(call if_changed_dep,bootcc) |
128 | $(call cmd,addsection) | 134 | $(call cmd,addsection) |
129 | 135 | ||
130 | $(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) | 136 | $(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required)) |
131 | $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds | 137 | $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds |
132 | $(call cmd,bootld,$(obj-boot)) | 138 | $(call cmd,bootld,$(obj-boot),zImage.lds) |
133 | 139 | ||
134 | $(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) | 140 | $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd)) |
135 | $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds | 141 | $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds |
136 | $(call cmd,bootld,$(obj-boot)) | 142 | $(call cmd,bootld,$(obj-boot),zImage.lds) |
143 | |||
144 | # For 32-bit powermacs, build the COFF images as well as the ELF images. | ||
145 | coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff | ||
146 | coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff | ||
137 | 147 | ||
138 | $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote | 148 | $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) |
139 | @cp -f $< $@ | 149 | @cp -f $< $@ |
140 | $(call if_changed,addnote) | 150 | $(call if_changed,addnote) |
141 | 151 | ||
142 | $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote | 152 | $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) |
143 | @cp -f $< $@ | 153 | @cp -f $< $@ |
144 | $(call if_changed,addnote) | 154 | $(call if_changed,addnote) |
145 | 155 | ||
156 | $(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff | ||
157 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | ||
158 | $(call cmd,gencoff) | ||
159 | |||
160 | $(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ | ||
161 | $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff | ||
162 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | ||
163 | $(call cmd,gencoff) | ||
164 | |||
146 | #----------------------------------------------------------- | 165 | #----------------------------------------------------------- |
147 | # build u-boot images | 166 | # build u-boot images |
148 | #----------------------------------------------------------- | 167 | #----------------------------------------------------------- |
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index d2f2ace56cd3..e0192c26037b 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S | |||
@@ -12,17 +12,23 @@ | |||
12 | #include "ppc_asm.h" | 12 | #include "ppc_asm.h" |
13 | 13 | ||
14 | .text | 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 | .globl _zimage_start | 19 | .globl _zimage_start |
16 | _zimage_start: | 20 | _zimage_start: |
21 | /* Work out the offset between the address we were linked at | ||
22 | and the address where we're running. */ | ||
17 | bl 1f | 23 | bl 1f |
18 | 24 | 1: mflr r0 | |
19 | 1: | ||
20 | mflr r0 | ||
21 | lis r9,1b@ha | 25 | lis r9,1b@ha |
22 | addi r9,r9,1b@l | 26 | addi r9,r9,1b@l |
23 | subf. r0,r9,r0 | 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 | lis r9,__got2_start@ha | 32 | lis r9,__got2_start@ha |
27 | addi r9,r9,__got2_start@l | 33 | addi r9,r9,__got2_start@l |
28 | lis r8,__got2_end@ha | 34 | lis r8,__got2_end@ha |
@@ -32,15 +38,14 @@ _zimage_start: | |||
32 | srwi. r8,r8,2 | 38 | srwi. r8,r8,2 |
33 | mtctr r8 | 39 | mtctr r8 |
34 | add r9,r0,r9 | 40 | add r9,r0,r9 |
35 | 2: | 41 | 2: lwz r8,0(r9) |
36 | lwz r8,0(r9) | ||
37 | add r8,r8,r0 | 42 | add r8,r8,r0 |
38 | stw r8,0(r9) | 43 | stw r8,0(r9) |
39 | addi r9,r9,4 | 44 | addi r9,r9,4 |
40 | bdnz 2b | 45 | bdnz 2b |
41 | 46 | ||
42 | 3: | 47 | /* Do a cache flush for our text, in case OF didn't */ |
43 | lis r9,_start@h | 48 | 3: lis r9,_start@h |
44 | add r9,r0,r9 | 49 | add r9,r0,r9 |
45 | lis r8,_etext@ha | 50 | lis r8,_etext@ha |
46 | addi r8,r8,_etext@l | 51 | addi r8,r8,_etext@l |
diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c new file mode 100644 index 000000000000..5e5a6573a1ef --- /dev/null +++ b/arch/powerpc/boot/hack-coff.c | |||
@@ -0,0 +1,84 @@ | |||
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 | } | ||
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 64ec93116fa6..55ec59867250 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
@@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long); | |||
21 | 21 | ||
22 | 22 | ||
23 | /* Value picked to match that used by yaboot */ | 23 | /* Value picked to match that used by yaboot */ |
24 | #define PROG_START 0x01400000 | 24 | #define PROG_START 0x01400000 /* only used on 64-bit systems */ |
25 | #define RAM_END (512<<20) // Fixme: use OF */ | 25 | #define RAM_END (512<<20) /* Fixme: use OF */ |
26 | #define ONE_MB 0x100000 | 26 | #define ONE_MB 0x100000 |
27 | 27 | ||
28 | extern char _start[]; | 28 | extern char _start[]; |
@@ -160,6 +160,17 @@ static int is_elf64(void *hdr) | |||
160 | elfoffset = (unsigned long)elf64ph->p_offset; | 160 | elfoffset = (unsigned long)elf64ph->p_offset; |
161 | vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; | 161 | vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; |
162 | vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; | 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 | return 1; | 174 | return 1; |
164 | } | 175 | } |
165 | 176 | ||
@@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | |||
206 | exit(); | 217 | exit(); |
207 | if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) | 218 | if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) |
208 | exit(); | 219 | exit(); |
209 | stderr = stdout; | ||
210 | if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) | ||
211 | exit(); | ||
212 | 220 | ||
213 | printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); | 221 | printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); |
214 | 222 | ||
223 | /* | ||
224 | * The first available claim_base must be above the end of the | ||
225 | * the loaded kernel wrapper file (_start to _end includes the | ||
226 | * initrd image if it is present) and rounded up to a nice | ||
227 | * 1 MB boundary for good measure. | ||
228 | */ | ||
229 | |||
230 | claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); | ||
231 | |||
215 | vmlinuz.addr = (unsigned long)_vmlinux_start; | 232 | vmlinuz.addr = (unsigned long)_vmlinux_start; |
216 | vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); | 233 | vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); |
217 | 234 | ||
@@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | |||
228 | exit(); | 245 | exit(); |
229 | } | 246 | } |
230 | 247 | ||
231 | /* | ||
232 | * The first available claim_base must be above the end of the | ||
233 | * the loaded kernel wrapper file (_start to _end includes the | ||
234 | * initrd image if it is present) and rounded up to a nice | ||
235 | * 1 MB boundary for good measure. | ||
236 | */ | ||
237 | |||
238 | claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); | ||
239 | |||
240 | #if defined(PROG_START) | ||
241 | /* | ||
242 | * Maintain a "magic" minimum address. This keeps some older | ||
243 | * firmware platforms running. | ||
244 | */ | ||
245 | |||
246 | if (claim_base < PROG_START) | ||
247 | claim_base = PROG_START; | ||
248 | #endif | ||
249 | |||
250 | /* We need to claim the memsize plus the file offset since gzip | 248 | /* We need to claim the memsize plus the file offset since gzip |
251 | * will expand the header (file offset), then the kernel, then | 249 | * will expand the header (file offset), then the kernel, then |
252 | * possible rubbish we don't care about. But the kernel bss must | 250 | * possible rubbish we don't care about. But the kernel bss must |
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c index 4bea2f4dcb06..fa0057736f6b 100644 --- a/arch/powerpc/boot/prom.c +++ b/arch/powerpc/boot/prom.c | |||
@@ -13,487 +13,153 @@ | |||
13 | #include "prom.h" | 13 | #include "prom.h" |
14 | 14 | ||
15 | int (*prom)(void *); | 15 | int (*prom)(void *); |
16 | phandle chosen_handle; | ||
17 | ihandle stdout; | ||
16 | 18 | ||
17 | void *chosen_handle; | 19 | int call_prom(const char *service, int nargs, int nret, ...) |
18 | |||
19 | void *stdin; | ||
20 | void *stdout; | ||
21 | void *stderr; | ||
22 | |||
23 | |||
24 | int | ||
25 | write(void *handle, void *ptr, int nb) | ||
26 | { | ||
27 | struct prom_args { | ||
28 | char *service; | ||
29 | int nargs; | ||
30 | int nret; | ||
31 | void *ihandle; | ||
32 | void *addr; | ||
33 | int len; | ||
34 | int actual; | ||
35 | } args; | ||
36 | |||
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; | ||
46 | } | ||
47 | |||
48 | int | ||
49 | read(void *handle, void *ptr, int nb) | ||
50 | { | 20 | { |
21 | int i; | ||
51 | struct prom_args { | 22 | struct prom_args { |
52 | char *service; | 23 | const char *service; |
53 | int nargs; | 24 | int nargs; |
54 | int nret; | 25 | int nret; |
55 | void *ihandle; | 26 | unsigned int args[12]; |
56 | void *addr; | ||
57 | int len; | ||
58 | int actual; | ||
59 | } args; | ||
60 | |||
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; | ||
70 | } | ||
71 | |||
72 | void | ||
73 | exit() | ||
74 | { | ||
75 | struct prom_args { | ||
76 | char *service; | ||
77 | } args; | ||
78 | |||
79 | for (;;) { | ||
80 | args.service = "exit"; | ||
81 | (*prom)(&args); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void | ||
86 | pause(void) | ||
87 | { | ||
88 | struct prom_args { | ||
89 | char *service; | ||
90 | } args; | 27 | } args; |
28 | va_list list; | ||
91 | 29 | ||
92 | args.service = "enter"; | 30 | args.service = service; |
93 | (*prom)(&args); | 31 | args.nargs = nargs; |
94 | } | 32 | args.nret = nret; |
95 | 33 | ||
96 | void * | 34 | va_start(list, nret); |
97 | finddevice(const char *name) | 35 | for (i = 0; i < nargs; i++) |
98 | { | 36 | args.args[i] = va_arg(list, unsigned int); |
99 | struct prom_args { | 37 | va_end(list); |
100 | char *service; | ||
101 | int nargs; | ||
102 | int nret; | ||
103 | const char *devspec; | ||
104 | void *phandle; | ||
105 | } args; | ||
106 | 38 | ||
107 | args.service = "finddevice"; | 39 | for (i = 0; i < nret; i++) |
108 | args.nargs = 1; | 40 | args.args[nargs+i] = 0; |
109 | args.nret = 1; | ||
110 | args.devspec = name; | ||
111 | args.phandle = (void *) -1; | ||
112 | (*prom)(&args); | ||
113 | return args.phandle; | ||
114 | } | ||
115 | 41 | ||
116 | void * | 42 | if (prom(&args) < 0) |
117 | claim(unsigned long virt, unsigned long size, unsigned long align) | 43 | return -1; |
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 | 44 | ||
129 | args.service = "claim"; | 45 | return (nret > 0)? args.args[nargs]: 0; |
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 | } | 46 | } |
138 | 47 | ||
139 | int | 48 | int call_prom_ret(const char *service, int nargs, int nret, |
140 | getprop(void *phandle, const char *name, void *buf, int buflen) | 49 | unsigned int *rets, ...) |
141 | { | 50 | { |
51 | int i; | ||
142 | struct prom_args { | 52 | struct prom_args { |
143 | char *service; | 53 | const char *service; |
144 | int nargs; | 54 | int nargs; |
145 | int nret; | 55 | int nret; |
146 | void *phandle; | 56 | unsigned int args[12]; |
147 | const char *name; | ||
148 | void *buf; | ||
149 | int buflen; | ||
150 | int size; | ||
151 | } args; | 57 | } args; |
58 | va_list list; | ||
152 | 59 | ||
153 | args.service = "getprop"; | 60 | args.service = service; |
154 | args.nargs = 4; | 61 | args.nargs = nargs; |
155 | args.nret = 1; | 62 | args.nret = nret; |
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 | 63 | ||
165 | int | 64 | va_start(list, rets); |
166 | putc(int c, void *f) | 65 | for (i = 0; i < nargs; i++) |
167 | { | 66 | args.args[i] = va_arg(list, unsigned int); |
168 | char ch = c; | 67 | va_end(list); |
169 | 68 | ||
170 | if (c == '\n') | 69 | for (i = 0; i < nret; i++) |
171 | putc('\r', f); | 70 | args.args[nargs+i] = 0; |
172 | return write(f, &ch, 1) == 1? c: -1; | ||
173 | } | ||
174 | 71 | ||
175 | int | 72 | if (prom(&args) < 0) |
176 | putchar(int c) | 73 | return -1; |
177 | { | ||
178 | return putc(c, stdout); | ||
179 | } | ||
180 | 74 | ||
181 | int | 75 | if (rets != (void *) 0) |
182 | fputs(char *str, void *f) | 76 | for (i = 1; i < nret; ++i) |
183 | { | 77 | rets[i-1] = args.args[nargs+i]; |
184 | int n = strlen(str); | ||
185 | 78 | ||
186 | return write(f, str, n) == n? 0: -1; | 79 | return (nret > 0)? args.args[nargs]: 0; |
187 | } | 80 | } |
188 | 81 | ||
189 | size_t strnlen(const char * s, size_t count) | 82 | int write(void *handle, void *ptr, int nb) |
190 | { | 83 | { |
191 | const char *sc; | 84 | return call_prom("write", 3, 1, handle, ptr, nb); |
192 | |||
193 | for (sc = s; count-- && *sc != '\0'; ++sc) | ||
194 | /* nothing */; | ||
195 | return sc - s; | ||
196 | } | 85 | } |
197 | 86 | ||
198 | extern unsigned int __div64_32(unsigned long long *dividend, | 87 | /* |
199 | unsigned int divisor); | 88 | * Older OF's require that when claiming a specific range of addresses, |
200 | 89 | * we claim the physical space in the /memory node and the virtual | |
201 | /* The unnecessary pointer compare is there | 90 | * space in the chosen mmu node, and then do a map operation to |
202 | * to check for type safety (n must be 64bit) | 91 | * map virtual to physical. |
203 | */ | 92 | */ |
204 | # define do_div(n,base) ({ \ | 93 | static int need_map = -1; |
205 | unsigned int __base = (base); \ | 94 | static ihandle chosen_mmu; |
206 | unsigned int __rem; \ | 95 | static phandle memory; |
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 | }) | ||
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; | 100 | for (; *s2; ++s2) |
219 | 101 | if (*s1++ != *s2) | |
220 | for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) | 102 | return 0; |
221 | i = i*10 + c - '0'; | 103 | return 1; |
222 | return i; | ||
223 | } | 104 | } |
224 | 105 | ||
225 | #define ZEROPAD 1 /* pad with zero */ | 106 | static int check_of_version(void) |
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) | ||
234 | { | 107 | { |
235 | char c,sign,tmp[66]; | 108 | phandle oprom, chosen; |
236 | const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; | 109 | char version[64]; |
237 | int i; | ||
238 | 110 | ||
239 | if (type & LARGE) | 111 | oprom = finddevice("/openprom"); |
240 | digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | 112 | if (oprom == (phandle) -1) |
241 | if (type & LEFT) | ||
242 | type &= ~ZEROPAD; | ||
243 | if (base < 2 || base > 36) | ||
244 | return 0; | 113 | return 0; |
245 | c = (type & ZEROPAD) ? '0' : ' '; | 114 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) |
246 | sign = 0; | 115 | return 0; |
247 | if (type & SIGN) { | 116 | version[sizeof(version)-1] = 0; |
248 | if ((signed long long)num < 0) { | 117 | printf("OF version = '%s'\r\n", version); |
249 | sign = '-'; | 118 | if (!string_match(version, "Open Firmware, 1.") |
250 | num = - (signed long long)num; | 119 | && !string_match(version, "FirmWorks,3.")) |
251 | size--; | 120 | return 0; |
252 | } else if (type & PLUS) { | 121 | chosen = finddevice("/chosen"); |
253 | sign = '+'; | 122 | if (chosen == (phandle) -1) { |
254 | size--; | 123 | chosen = finddevice("/chosen@0"); |
255 | } else if (type & SPACE) { | 124 | if (chosen == (phandle) -1) { |
256 | sign = ' '; | 125 | printf("no chosen\n"); |
257 | size--; | 126 | return 0; |
258 | } | 127 | } |
259 | } | 128 | } |
260 | if (type & SPECIAL) { | 129 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { |
261 | if (base == 16) | 130 | printf("no mmu\n"); |
262 | size -= 2; | 131 | return 0; |
263 | else if (base == 8) | ||
264 | size--; | ||
265 | } | ||
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 | } | 132 | } |
272 | if (i > precision) | 133 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); |
273 | precision = i; | 134 | if (memory == (ihandle) -1) { |
274 | size -= precision; | 135 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); |
275 | if (!(type&(ZEROPAD+LEFT))) | 136 | if (memory == (ihandle) -1) { |
276 | while(size-->0) | 137 | printf("no memory node\n"); |
277 | *str++ = ' '; | 138 | return 0; |
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]; | ||
286 | } | 139 | } |
287 | } | 140 | } |
288 | if (!(type & LEFT)) | 141 | printf("old OF detected\r\n"); |
289 | while (size-- > 0) | 142 | return 1; |
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; | ||
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; | 147 | int ret; |
303 | unsigned long long num; | 148 | unsigned int result; |
304 | int i, base; | ||
305 | char * str; | ||
306 | const char *s; | ||
307 | |||
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 | 149 | ||
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) { | 155 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, |
319 | if (*fmt != '%') { | 156 | align, size, virt); |
320 | *str++ = *fmt; | 157 | if (ret != 0 || result == -1) |
321 | continue; | 158 | return (void *) -1; |
322 | } | 159 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, |
323 | 160 | align, size, virt); | |
324 | /* process flags */ | 161 | /* 0x12 == coherent + read/write */ |
325 | flags = 0; | 162 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, |
326 | repeat: | 163 | 0x12, size, virt, virt); |
327 | ++fmt; /* this also skips first '%' */ | 164 | return (void *) virt; |
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; | ||
499 | } | 165 | } |
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h index 96ab5aec740c..3e2ddd4a5a81 100644 --- a/arch/powerpc/boot/prom.h +++ b/arch/powerpc/boot/prom.h | |||
@@ -1,18 +1,34 @@ | |||
1 | #ifndef _PPC_BOOT_PROM_H_ | 1 | #ifndef _PPC_BOOT_PROM_H_ |
2 | #define _PPC_BOOT_PROM_H_ | 2 | #define _PPC_BOOT_PROM_H_ |
3 | 3 | ||
4 | typedef void *phandle; | ||
5 | typedef void *ihandle; | ||
6 | |||
4 | extern int (*prom) (void *); | 7 | extern int (*prom) (void *); |
5 | extern void *chosen_handle; | 8 | extern phandle chosen_handle; |
9 | extern ihandle stdout; | ||
6 | 10 | ||
7 | extern void *stdin; | 11 | int call_prom(const char *service, int nargs, int nret, ...); |
8 | extern void *stdout; | 12 | int call_prom_ret(const char *service, int nargs, int nret, |
9 | extern void *stderr; | 13 | unsigned int *rets, ...); |
10 | 14 | ||
11 | extern int write(void *handle, void *ptr, int nb); | 15 | extern int write(void *handle, void *ptr, int nb); |
12 | extern int read(void *handle, void *ptr, int nb); | 16 | extern void *claim(unsigned long virt, unsigned long size, unsigned long aln); |
13 | extern void exit(void); | 17 | |
14 | extern void pause(void); | 18 | static inline void exit(void) |
15 | extern void *finddevice(const char *); | 19 | { |
16 | extern void *claim(unsigned long virt, unsigned long size, unsigned long align); | 20 | call_prom("exit", 0, 0); |
17 | extern int getprop(void *phandle, const char *name, void *buf, int buflen); | 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 | #endif /* _PPC_BOOT_PROM_H_ */ | 34 | #endif /* _PPC_BOOT_PROM_H_ */ |
diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h new file mode 100644 index 000000000000..433f45084e41 --- /dev/null +++ b/arch/powerpc/boot/rs6000.h | |||
@@ -0,0 +1,243 @@ | |||
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 | ||
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c new file mode 100644 index 000000000000..b5aa522f8b77 --- /dev/null +++ b/arch/powerpc/boot/stdio.c | |||
@@ -0,0 +1,325 @@ | |||
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 | } | ||
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h index 24bd3a8dee94..eb9e16c87aef 100644 --- a/arch/powerpc/boot/stdio.h +++ b/arch/powerpc/boot/stdio.h | |||
@@ -7,10 +7,4 @@ extern int sprintf(char *buf, const char *fmt, ...); | |||
7 | 7 | ||
8 | extern int vsprintf(char *buf, const char *fmt, va_list args); | 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 | #endif /* _PPC_BOOT_STDIO_H_ */ | 10 | #endif /* _PPC_BOOT_STDIO_H_ */ |
diff --git a/arch/powerpc/boot/zImage.coff.lds b/arch/powerpc/boot/zImage.coff.lds new file mode 100644 index 000000000000..6016251a1a2c --- /dev/null +++ b/arch/powerpc/boot/zImage.coff.lds | |||
@@ -0,0 +1,46 @@ | |||
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 | } | ||