aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/boot')
-rw-r--r--arch/powerpc/boot/.gitignore3
-rw-r--r--arch/powerpc/boot/Makefile122
-rw-r--r--arch/powerpc/boot/crt0.S37
-rw-r--r--arch/powerpc/boot/cuboot-83xx.c68
-rw-r--r--arch/powerpc/boot/cuboot-85xx.c69
-rw-r--r--arch/powerpc/boot/devtree.c307
-rw-r--r--arch/powerpc/boot/dts/kuroboxHD.dts7
-rw-r--r--arch/powerpc/boot/dts/kuroboxHG.dts7
-rw-r--r--arch/powerpc/boot/dts/lite5200.dts1
-rw-r--r--arch/powerpc/boot/dts/lite5200b.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc7448hpc2.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8272ads.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8313erdb.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc832x_mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc832x_rdb.dts291
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitx.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitxgp.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc834x_mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc836x_mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8540ads.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8541cds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8544ds.dts136
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8555cds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8560ads.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8568mds.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8641_hpcn.dts25
-rw-r--r--arch/powerpc/boot/dts/mpc866ads.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc885ads.dts1
-rw-r--r--arch/powerpc/boot/elf.h8
-rw-r--r--arch/powerpc/boot/elf_util.c76
-rw-r--r--arch/powerpc/boot/flatdevtree.c199
-rw-r--r--arch/powerpc/boot/flatdevtree.h7
-rw-r--r--arch/powerpc/boot/flatdevtree_misc.c42
-rw-r--r--arch/powerpc/boot/gunzip_util.c206
-rw-r--r--arch/powerpc/boot/gunzip_util.h45
-rw-r--r--arch/powerpc/boot/main.c369
-rw-r--r--arch/powerpc/boot/ns16550.c9
-rw-r--r--arch/powerpc/boot/of.c21
-rw-r--r--arch/powerpc/boot/ops.h103
-rw-r--r--arch/powerpc/boot/ppcboot.h108
-rw-r--r--arch/powerpc/boot/reg.h22
-rw-r--r--arch/powerpc/boot/simple_alloc.c31
-rw-r--r--arch/powerpc/boot/stdio.h5
-rwxr-xr-xarch/powerpc/boot/wrapper53
-rw-r--r--arch/powerpc/boot/zImage.coff.lds.S3
-rw-r--r--arch/powerpc/boot/zImage.lds.S1
47 files changed, 1965 insertions, 433 deletions
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
index 0734b2fc1d95..eec7af7e5993 100644
--- a/arch/powerpc/boot/.gitignore
+++ b/arch/powerpc/boot/.gitignore
@@ -18,6 +18,9 @@ kernel-vmlinux.strip.c
18kernel-vmlinux.strip.gz 18kernel-vmlinux.strip.gz
19mktree 19mktree
20uImage 20uImage
21cuImage
22cuImage.bin.gz
23cuImage.elf
21zImage 24zImage
22zImage.chrp 25zImage.chrp
23zImage.coff 26zImage.coff
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index dc779407de14..3716594ea33e 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,10 +40,11 @@ zliblinuxheader := zlib.h zconf.h zutil.h
40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ 40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
41 $(addprefix $(obj)/,$(zlibheader)) 41 $(addprefix $(obj)/,$(zlibheader))
42 42
43src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ 43src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
44 ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib) 44 ns16550.c serial.c simple_alloc.c div64.S util.S \
45src-plat := of.c 45 gunzip_util.c elf_util.c $(zlib) devtree.c
46src-boot := crt0.S $(src-wlib) $(src-plat) empty.c 46src-plat := of.c cuboot-83xx.c cuboot-85xx.c
47src-boot := $(src-wlib) $(src-plat) empty.c
47 48
48src-boot := $(addprefix $(obj)/, $(src-boot)) 49src-boot := $(addprefix $(obj)/, $(src-boot))
49obj-boot := $(addsuffix .o, $(basename $(src-boot))) 50obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@@ -75,7 +76,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S
75 @cp $< $@ 76 @cp $< $@
76 77
77clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ 78clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
78 empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint 79 empty.c zImage.coff.lds zImage.lds
79 80
80quiet_cmd_bootcc = BOOTCC $@ 81quiet_cmd_bootcc = BOOTCC $@
81 cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< 82 cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@ -84,23 +85,25 @@ quiet_cmd_bootas = BOOTAS $@
84 cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< 85 cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
85 86
86quiet_cmd_bootar = BOOTAR $@ 87quiet_cmd_bootar = BOOTAR $@
87 cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $^; mv $@.$$$$ $@ 88 cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
88 89
89$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c 90$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE
90 $(call if_changed_dep,bootcc) 91 $(call if_changed_dep,bootcc)
91$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S 92$(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE
92 $(call if_changed_dep,bootas) 93 $(call if_changed_dep,bootas)
93 94
94$(obj)/wrapper.a: $(obj-wlib) 95$(obj)/wrapper.a: $(obj-wlib) FORCE
95 $(call cmd,bootar) 96 $(call if_changed,bootar)
96 97
97hostprogs-y := addnote addRamDisk hack-coff mktree 98hostprogs-y := addnote addRamDisk hack-coff mktree
98 99
99extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ 100targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
101extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
100 $(obj)/zImage.lds $(obj)/zImage.coff.lds 102 $(obj)/zImage.lds $(obj)/zImage.coff.lds
101 103
102wrapper :=$(srctree)/$(src)/wrapper 104wrapper :=$(srctree)/$(src)/wrapper
103wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) 105wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
106 $(wrapper) FORCE
104 107
105############# 108#############
106# Bits for building various flavours of zImage 109# Bits for building various flavours of zImage
@@ -113,50 +116,10 @@ CROSSWRAP := -C "$(CROSS_COMPILE)"
113endif 116endif
114endif 117endif
115 118
119# args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd
116quiet_cmd_wrap = WRAP $@ 120quiet_cmd_wrap = WRAP $@
117 cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux 121 cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
118quiet_cmd_wrap_initrd = WRAP $@ 122 $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
119 cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
120 -i $(obj)/ramdisk.image.gz vmlinux
121
122$(obj)/zImage.chrp: vmlinux $(wrapperbits)
123 $(call cmd,wrap,chrp)
124
125$(obj)/zImage.initrd.chrp: vmlinux $(wrapperbits)
126 $(call cmd,wrap_initrd,chrp)
127
128$(obj)/zImage.pseries: vmlinux $(wrapperbits)
129 $(call cmd,wrap,pseries)
130
131$(obj)/zImage.initrd.pseries: vmlinux $(wrapperbits)
132 $(call cmd,wrap_initrd,pseries)
133
134$(obj)/zImage.pmac: vmlinux $(wrapperbits)
135 $(call cmd,wrap,pmac)
136
137$(obj)/zImage.initrd.pmac: vmlinux $(wrapperbits)
138 $(call cmd,wrap_initrd,pmac)
139
140$(obj)/zImage.coff: vmlinux $(wrapperbits)
141 $(call cmd,wrap,pmaccoff)
142
143$(obj)/zImage.initrd.coff: vmlinux $(wrapperbits)
144 $(call cmd,wrap_initrd,pmaccoff)
145
146$(obj)/zImage.miboot: vmlinux $(wrapperbits)
147 $(call cmd,wrap,miboot)
148
149$(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits)
150 $(call cmd,wrap_initrd,miboot)
151
152$(obj)/zImage.ps3: vmlinux
153 $(STRIP) -s -R .comment $< -o $@
154
155$(obj)/zImage.initrd.ps3: vmlinux
156 @echo " WARNING zImage.initrd.ps3 not supported (yet)"
157
158$(obj)/uImage: vmlinux $(wrapperbits)
159 $(call cmd,wrap,uboot)
160 123
161image-$(CONFIG_PPC_PSERIES) += zImage.pseries 124image-$(CONFIG_PPC_PSERIES) += zImage.pseries
162image-$(CONFIG_PPC_MAPLE) += zImage.pseries 125image-$(CONFIG_PPC_MAPLE) += zImage.pseries
@@ -166,7 +129,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries
166image-$(CONFIG_PPC_CHRP) += zImage.chrp 129image-$(CONFIG_PPC_CHRP) += zImage.chrp
167image-$(CONFIG_PPC_EFIKA) += zImage.chrp 130image-$(CONFIG_PPC_EFIKA) += zImage.chrp
168image-$(CONFIG_PPC_PMAC) += zImage.pmac 131image-$(CONFIG_PPC_PMAC) += zImage.pmac
169image-$(CONFIG_DEFAULT_UIMAGE) += uImage 132image-$(CONFIG_DEFAULT_UIMAGE) += uImage cuImage
170 133
171# For 32-bit powermacs, build the COFF and miboot images 134# For 32-bit powermacs, build the COFF and miboot images
172# as well as the ELF images. 135# as well as the ELF images.
@@ -174,16 +137,55 @@ ifeq ($(CONFIG_PPC32),y)
174image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot 137image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot
175endif 138endif
176 139
140initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
177initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y)) 141initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y))
142initrd-y := $(filter-out $(image-y), $(initrd-y))
143targets += $(image-y) $(initrd-y)
144
145$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
146
147# Don't put the ramdisk on the pattern rule; when its missing make will try
148# the pattern rule with less dependencies that also matches (even with the
149# hard dependency listed).
150$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
151 $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
152
153$(obj)/zImage.%: vmlinux $(wrapperbits)
154 $(call if_changed,wrap,$*)
155
156$(obj)/zImage.ps3: vmlinux
157 $(STRIP) -s -R .comment $< -o $@
158
159$(obj)/zImage.initrd.ps3: vmlinux
160 @echo " WARNING zImage.initrd.ps3 not supported (yet)"
161
162$(obj)/uImage: vmlinux $(wrapperbits)
163 $(call if_changed,wrap,uboot)
164
165cuboot-plat-$(CONFIG_83xx) += 83xx
166cuboot-plat-$(CONFIG_85xx) += 85xx
167cuboot-plat-y += unknown-platform
168
169dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
170 ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE)
171
172$(obj)/cuImage: vmlinux $(wrapperbits)
173 $(call if_changed,wrap,cuboot-$(word 1,$(cuboot-plat-y)),$(dts))
178 174
179$(obj)/zImage: $(addprefix $(obj)/, $(image-y)) 175$(obj)/zImage: $(addprefix $(obj)/, $(image-y))
180 @rm -f $@; ln $< $@ 176 @rm -f $@; ln $< $@
181$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) 177$(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
182 @rm -f $@; ln $< $@ 178 @rm -f $@; ln $< $@
183 179
184install: $(CONFIGURE) $(image-y) 180install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
185 sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< 181 sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
186 182
187clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) 183# anything not in $(targets)
188clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) 184clean-files += $(image-) $(initrd-) zImage zImage.initrd \
189clean-files += $(image-) 185 cuImage.elf cuImage.bin.gz
186
187# clean up files cached by wrapper
188clean-kernel := vmlinux.strip vmlinux.bin
189clean-kernel += $(addsuffix .gz,$(clean-kernel))
190# If not absolute clean-files are relative to $(obj).
191clean-files += $(addprefix $(objtree)/, $(clean-kernel))
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 70e65b13e033..5a4215c4b014 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -16,8 +16,11 @@
16_zimage_start_opd: 16_zimage_start_opd:
17 .long _zimage_start, 0, 0, 0 17 .long _zimage_start, 0, 0, 0
18 18
19 .weak _zimage_start
19 .globl _zimage_start 20 .globl _zimage_start
20_zimage_start: 21_zimage_start:
22 .globl _zimage_start_lib
23_zimage_start_lib:
21 /* Work out the offset between the address we were linked at 24 /* Work out the offset between the address we were linked at
22 and the address where we're running. */ 25 and the address where we're running. */
23 bl 1f 26 bl 1f
@@ -44,7 +47,7 @@ _zimage_start:
44 addi r9,r9,4 47 addi r9,r9,4
45 bdnz 2b 48 bdnz 2b
46 49
47 /* Do a cache flush for our text, in case OF didn't */ 50 /* Do a cache flush for our text, in case the loader didn't */
483: lis r9,_start@ha 513: lis r9,_start@ha
49 addi r9,r9,_start@l 52 addi r9,r9,_start@l
50 add r9,r0,r9 53 add r9,r0,r9
@@ -59,6 +62,34 @@ _zimage_start:
59 sync 62 sync
60 isync 63 isync
61 64
62 mr r6,r1 65 /* Clear the BSS */
63 b start 66 lis r9,__bss_start@ha
67 addi r9,r9,__bss_start@l
68 add r9,r0,r9
69 lis r8,_end@ha
70 addi r8,r8,_end@l
71 add r8,r0,r8
72 li r10,0
735: stw r10,0(r9)
74 addi r9,r9,4
75 cmplw cr0,r9,r8
76 blt 5b
64 77
78 /* Possibly set up a custom stack */
79.weak _platform_stack_top
80 lis r8,_platform_stack_top@ha
81 addi r8,r8,_platform_stack_top@l
82 cmpwi r8,0
83 beq 6f
84 add r8,r0,r8
85 lwz r1,0(r8)
86 add r1,r0,r1
87 li r0,0
88 stwu r0,-16(r1) /* establish a stack frame */
896:
90
91 /* Call platform_init() */
92 bl platform_init
93
94 /* Call start */
95 b start
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c
new file mode 100644
index 000000000000..6cbc20afb4d8
--- /dev/null
+++ b/arch/powerpc/boot/cuboot-83xx.c
@@ -0,0 +1,68 @@
1/*
2 * Old U-boot compatibility for 83xx
3 *
4 * Author: Scott Wood <scottwood@freescale.com>
5 *
6 * Copyright (c) 2007 Freescale Semiconductor, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 */
12
13#include "ops.h"
14#include "stdio.h"
15
16#define TARGET_83xx
17#include "ppcboot.h"
18
19static bd_t bd;
20extern char _end[];
21extern char _dtb_start[], _dtb_end[];
22
23static void platform_fixups(void)
24{
25 void *soc;
26
27 dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
28 dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
29 dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq);
30
31 /* Unfortunately, the specific model number is encoded in the
32 * soc node name in existing dts files -- once that is fixed,
33 * this can do a simple path lookup.
34 */
35 soc = find_node_by_devtype(NULL, "soc");
36 if (soc) {
37 void *serial = NULL;
38
39 setprop(soc, "bus-frequency", &bd.bi_busfreq,
40 sizeof(bd.bi_busfreq));
41
42 while ((serial = find_node_by_devtype(serial, "serial"))) {
43 if (get_parent(serial) != soc)
44 continue;
45
46 setprop(serial, "clock-frequency", &bd.bi_busfreq,
47 sizeof(bd.bi_busfreq));
48 }
49 }
50}
51
52void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
53 unsigned long r6, unsigned long r7)
54{
55 unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
56 unsigned long avail_ram = end_of_ram - (unsigned long)_end;
57
58 memcpy(&bd, (bd_t *)r3, sizeof(bd));
59 loader_info.initrd_addr = r4;
60 loader_info.initrd_size = r4 ? r5 : 0;
61 loader_info.cmdline = (char *)r6;
62 loader_info.cmdline_len = r7 - r6;
63
64 simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
65 ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
66 serial_console_init();
67 platform_ops.fixups = platform_fixups;
68}
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c
new file mode 100644
index 000000000000..f88ba00ac122
--- /dev/null
+++ b/arch/powerpc/boot/cuboot-85xx.c
@@ -0,0 +1,69 @@
1/*
2 * Old U-boot compatibility for 85xx
3 *
4 * Author: Scott Wood <scottwood@freescale.com>
5 *
6 * Copyright (c) 2007 Freescale Semiconductor, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 */
12
13#include "ops.h"
14#include "stdio.h"
15
16#define TARGET_85xx
17#include "ppcboot.h"
18
19static bd_t bd;
20extern char _end[];
21extern char _dtb_start[], _dtb_end[];
22
23static void platform_fixups(void)
24{
25 void *soc;
26
27 dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
28 dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr,
29 bd.bi_enet2addr);
30 dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 8, bd.bi_busfreq);
31
32 /* Unfortunately, the specific model number is encoded in the
33 * soc node name in existing dts files -- once that is fixed,
34 * this can do a simple path lookup.
35 */
36 soc = find_node_by_devtype(NULL, "soc");
37 if (soc) {
38 void *serial = NULL;
39
40 setprop(soc, "bus-frequency", &bd.bi_busfreq,
41 sizeof(bd.bi_busfreq));
42
43 while ((serial = find_node_by_devtype(serial, "serial"))) {
44 if (get_parent(serial) != soc)
45 continue;
46
47 setprop(serial, "clock-frequency", &bd.bi_busfreq,
48 sizeof(bd.bi_busfreq));
49 }
50 }
51}
52
53void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
54 unsigned long r6, unsigned long r7)
55{
56 unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize;
57 unsigned long avail_ram = end_of_ram - (unsigned long)_end;
58
59 memcpy(&bd, (bd_t *)r3, sizeof(bd));
60 loader_info.initrd_addr = r4;
61 loader_info.initrd_size = r4 ? r5 : 0;
62 loader_info.cmdline = (char *)r6;
63 loader_info.cmdline_len = r7 - r6;
64
65 simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64);
66 ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
67 serial_console_init();
68 platform_ops.fixups = platform_fixups;
69}
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
new file mode 100644
index 000000000000..c9951550ed2c
--- /dev/null
+++ b/arch/powerpc/boot/devtree.c
@@ -0,0 +1,307 @@
1/*
2 * devtree.c - convenience functions for device tree manipulation
3 * Copyright 2007 David Gibson, IBM Corporation.
4 * Copyright (c) 2007 Freescale Semiconductor, Inc.
5 *
6 * Authors: David Gibson <david@gibson.dropbear.id.au>
7 * Scott Wood <scottwood@freescale.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14#include <stdarg.h>
15#include <stddef.h>
16#include "types.h"
17#include "string.h"
18#include "stdio.h"
19#include "ops.h"
20
21void dt_fixup_memory(u64 start, u64 size)
22{
23 void *root, *memory;
24 int naddr, nsize, i;
25 u32 memreg[4];
26
27 root = finddevice("/");
28 if (getprop(root, "#address-cells", &naddr, sizeof(naddr)) < 0)
29 naddr = 2;
30 if (naddr < 1 || naddr > 2)
31 fatal("Can't cope with #address-cells == %d in /\n\r", naddr);
32
33 if (getprop(root, "#size-cells", &nsize, sizeof(nsize)) < 0)
34 nsize = 1;
35 if (nsize < 1 || nsize > 2)
36 fatal("Can't cope with #size-cells == %d in /\n\r", nsize);
37
38 i = 0;
39 if (naddr == 2)
40 memreg[i++] = start >> 32;
41 memreg[i++] = start & 0xffffffff;
42 if (nsize == 2)
43 memreg[i++] = size >> 32;
44 memreg[i++] = size & 0xffffffff;
45
46 memory = finddevice("/memory");
47 if (! memory) {
48 memory = create_node(NULL, "memory");
49 setprop_str(memory, "device_type", "memory");
50 }
51
52 printf("Memory <- <0x%x", memreg[0]);
53 for (i = 1; i < (naddr + nsize); i++)
54 printf(" 0x%x", memreg[i]);
55 printf("> (%ldMB)\n\r", (unsigned long)(size >> 20));
56
57 setprop(memory, "reg", memreg, (naddr + nsize)*sizeof(u32));
58}
59
60#define MHZ(x) ((x + 500000) / 1000000)
61
62void dt_fixup_cpu_clocks(u32 cpu, u32 tb, u32 bus)
63{
64 void *devp = NULL;
65
66 printf("CPU clock-frequency <- 0x%x (%dMHz)\n\r", cpu, MHZ(cpu));
67 printf("CPU timebase-frequency <- 0x%x (%dMHz)\n\r", tb, MHZ(tb));
68 if (bus > 0)
69 printf("CPU bus-frequency <- 0x%x (%dMHz)\n\r", bus, MHZ(bus));
70
71 while ((devp = find_node_by_devtype(devp, "cpu"))) {
72 setprop_val(devp, "clock-frequency", cpu);
73 setprop_val(devp, "timebase-frequency", tb);
74 if (bus > 0)
75 setprop_val(devp, "bus-frequency", bus);
76 }
77}
78
79void dt_fixup_clock(const char *path, u32 freq)
80{
81 void *devp = finddevice(path);
82
83 if (devp) {
84 printf("%s: clock-frequency <- %x (%dMHz)\n\r", path, freq, MHZ(freq));
85 setprop_val(devp, "clock-frequency", freq);
86 }
87}
88
89void __dt_fixup_mac_addresses(u32 startindex, ...)
90{
91 va_list ap;
92 u32 index = startindex;
93 void *devp;
94 const u8 *addr;
95
96 va_start(ap, startindex);
97 while ((addr = va_arg(ap, const u8 *))) {
98 devp = find_node_by_prop_value(NULL, "linux,network-index",
99 (void*)&index, sizeof(index));
100
101 printf("ENET%d: local-mac-address <-"
102 " %02x:%02x:%02x:%02x:%02x:%02x\n\r", index,
103 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
104
105 if (devp)
106 setprop(devp, "local-mac-address", addr, 6);
107
108 index++;
109 }
110 va_end(ap);
111}
112
113#define MAX_ADDR_CELLS 4
114#define MAX_RANGES 8
115
116static void get_reg_format(void *node, u32 *naddr, u32 *nsize)
117{
118 if (getprop(node, "#address-cells", naddr, 4) != 4)
119 *naddr = 2;
120 if (getprop(node, "#size-cells", nsize, 4) != 4)
121 *nsize = 1;
122}
123
124static void copy_val(u32 *dest, u32 *src, int naddr)
125{
126 int pad = MAX_ADDR_CELLS - naddr;
127
128 memset(dest, 0, pad * 4);
129 memcpy(dest + pad, src, naddr * 4);
130}
131
132static int sub_reg(u32 *reg, u32 *sub)
133{
134 int i, borrow = 0;
135
136 for (i = MAX_ADDR_CELLS - 1; i >= 0; i--) {
137 int prev_borrow = borrow;
138 borrow = reg[i] < sub[i] + prev_borrow;
139 reg[i] -= sub[i] + prev_borrow;
140 }
141
142 return !borrow;
143}
144
145static int add_reg(u32 *reg, u32 *add, int naddr)
146{
147 int i, carry = 0;
148
149 for (i = MAX_ADDR_CELLS - 1; i >= MAX_ADDR_CELLS - naddr; i--) {
150 u64 tmp = (u64)reg[i] + add[i] + carry;
151 carry = tmp >> 32;
152 reg[i] = (u32)tmp;
153 }
154
155 return !carry;
156}
157
158/* It is assumed that if the first byte of reg fits in a
159 * range, then the whole reg block fits.
160 */
161static int compare_reg(u32 *reg, u32 *range, u32 *rangesize)
162{
163 int i;
164 u32 end;
165
166 for (i = 0; i < MAX_ADDR_CELLS; i++) {
167 if (reg[i] < range[i])
168 return 0;
169 if (reg[i] > range[i])
170 break;
171 }
172
173 for (i = 0; i < MAX_ADDR_CELLS; i++) {
174 end = range[i] + rangesize[i];
175
176 if (reg[i] < end)
177 break;
178 if (reg[i] > end)
179 return 0;
180 }
181
182 return reg[i] != end;
183}
184
185/* reg must be MAX_ADDR_CELLS */
186static int find_range(u32 *reg, u32 *ranges, int nregaddr,
187 int naddr, int nsize, int buflen)
188{
189 int nrange = nregaddr + naddr + nsize;
190 int i;
191
192 for (i = 0; i + nrange <= buflen; i += nrange) {
193 u32 range_addr[MAX_ADDR_CELLS];
194 u32 range_size[MAX_ADDR_CELLS];
195
196 copy_val(range_addr, ranges + i, naddr);
197 copy_val(range_size, ranges + i + nregaddr + naddr, nsize);
198
199 if (compare_reg(reg, range_addr, range_size))
200 return i;
201 }
202
203 return -1;
204}
205
206/* Currently only generic buses without special encodings are supported.
207 * In particular, PCI is not supported. Also, only the beginning of the
208 * reg block is tracked; size is ignored except in ranges.
209 */
210static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3];
211
212static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
213 unsigned long *size)
214{
215 u32 last_addr[MAX_ADDR_CELLS];
216 u32 this_addr[MAX_ADDR_CELLS];
217 void *parent;
218 u64 ret_addr, ret_size;
219 u32 naddr, nsize, prev_naddr;
220 int buflen, offset;
221
222 parent = get_parent(node);
223 if (!parent)
224 return 0;
225
226 get_reg_format(parent, &naddr, &nsize);
227
228 if (nsize > 2)
229 return 0;
230
231 offset = (naddr + nsize) * res;
232
233 if (reglen < offset + naddr + nsize ||
234 sizeof(dt_xlate_buf) < offset + naddr + nsize)
235 return 0;
236
237 copy_val(last_addr, dt_xlate_buf + offset, naddr);
238
239 ret_size = dt_xlate_buf[offset + naddr];
240 if (nsize == 2) {
241 ret_size <<= 32;
242 ret_size |= dt_xlate_buf[offset + naddr + 1];
243 }
244
245 while ((node = get_parent(node))) {
246 prev_naddr = naddr;
247
248 get_reg_format(node, &naddr, &nsize);
249
250 buflen = getprop(node, "ranges", dt_xlate_buf,
251 sizeof(dt_xlate_buf));
252 if (buflen < 0)
253 continue;
254 if (buflen > sizeof(dt_xlate_buf))
255 return 0;
256
257 offset = find_range(last_addr, dt_xlate_buf, prev_naddr,
258 naddr, nsize, buflen / 4);
259
260 if (offset < 0)
261 return 0;
262
263 copy_val(this_addr, dt_xlate_buf + offset, prev_naddr);
264
265 if (!sub_reg(last_addr, this_addr))
266 return 0;
267
268 copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr);
269
270 if (!add_reg(last_addr, this_addr, naddr))
271 return 0;
272 }
273
274 if (naddr > 2)
275 return 0;
276
277 ret_addr = ((u64)last_addr[2] << 32) | last_addr[3];
278
279 if (sizeof(void *) == 4 &&
280 (ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL ||
281 ret_addr + ret_size > 0x100000000ULL))
282 return 0;
283
284 *addr = ret_addr;
285 if (size)
286 *size = ret_size;
287
288 return 1;
289}
290
291int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size)
292{
293 int reglen;
294
295 reglen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4;
296 return dt_xlate(node, res, reglen, addr, size);
297}
298
299int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr)
300{
301
302 if (buflen > sizeof(dt_xlate_buf))
303 return 0;
304
305 memcpy(dt_xlate_buf, buf, buflen);
306 return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL);
307}
diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
index b89791802e86..157dc98d3988 100644
--- a/arch/powerpc/boot/dts/kuroboxHD.dts
+++ b/arch/powerpc/boot/dts/kuroboxHD.dts
@@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
29 29
30 cpus { 30 cpus {
31 linux,phandle = <2000>; 31 linux,phandle = <2000>;
32 #cpus = <1>;
33 #address-cells = <1>; 32 #address-cells = <1>;
34 #size-cells = <0>; 33 #size-cells = <0>;
35 34
@@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
126 interrupt-parent = <4400>; 125 interrupt-parent = <4400>;
127 interrupt-map-mask = <f800 0 0 7>; 126 interrupt-map-mask = <f800 0 0 7>;
128 interrupt-map = < 127 interrupt-map = <
129 /* IDSEL 0x11 - IRQ0 ETH */ 128 /* IDSEL 11 - IRQ0 ETH */
130 5800 0 0 1 4400 0 1 129 5800 0 0 1 4400 0 1
131 5800 0 0 2 4400 1 1 130 5800 0 0 2 4400 1 1
132 5800 0 0 3 4400 2 1 131 5800 0 0 3 4400 2 1
133 5800 0 0 4 4400 3 1 132 5800 0 0 4 4400 3 1
134 /* IDSEL 0x12 - IRQ1 IDE0 */ 133 /* IDSEL 12 - IRQ1 IDE0 */
135 6000 0 0 1 4400 1 1 134 6000 0 0 1 4400 1 1
136 6000 0 0 2 4400 2 1 135 6000 0 0 2 4400 2 1
137 6000 0 0 3 4400 3 1 136 6000 0 0 3 4400 3 1
138 6000 0 0 4 4400 0 1 137 6000 0 0 4 4400 0 1
139 /* IDSEL 0x14 - IRQ3 USB2.0 */ 138 /* IDSEL 14 - IRQ3 USB2.0 */
140 7000 0 0 1 4400 3 1 139 7000 0 0 1 4400 3 1
141 7000 0 0 2 4400 3 1 140 7000 0 0 2 4400 3 1
142 7000 0 0 3 4400 3 1 141 7000 0 0 3 4400 3 1
diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
index 753102752d8b..919eb29097db 100644
--- a/arch/powerpc/boot/dts/kuroboxHG.dts
+++ b/arch/powerpc/boot/dts/kuroboxHG.dts
@@ -29,7 +29,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
29 29
30 cpus { 30 cpus {
31 linux,phandle = <2000>; 31 linux,phandle = <2000>;
32 #cpus = <1>;
33 #address-cells = <1>; 32 #address-cells = <1>;
34 #size-cells = <0>; 33 #size-cells = <0>;
35 34
@@ -126,17 +125,17 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
126 interrupt-parent = <4400>; 125 interrupt-parent = <4400>;
127 interrupt-map-mask = <f800 0 0 7>; 126 interrupt-map-mask = <f800 0 0 7>;
128 interrupt-map = < 127 interrupt-map = <
129 /* IDSEL 0x11 - IRQ0 ETH */ 128 /* IDSEL 11 - IRQ0 ETH */
130 5800 0 0 1 4400 0 1 129 5800 0 0 1 4400 0 1
131 5800 0 0 2 4400 1 1 130 5800 0 0 2 4400 1 1
132 5800 0 0 3 4400 2 1 131 5800 0 0 3 4400 2 1
133 5800 0 0 4 4400 3 1 132 5800 0 0 4 4400 3 1
134 /* IDSEL 0x12 - IRQ1 IDE0 */ 133 /* IDSEL 12 - IRQ1 IDE0 */
135 6000 0 0 1 4400 1 1 134 6000 0 0 1 4400 1 1
136 6000 0 0 2 4400 2 1 135 6000 0 0 2 4400 2 1
137 6000 0 0 3 4400 3 1 136 6000 0 0 3 4400 3 1
138 6000 0 0 4 4400 0 1 137 6000 0 0 4 4400 0 1
139 /* IDSEL 0x14 - IRQ3 USB2.0 */ 138 /* IDSEL 14 - IRQ3 USB2.0 */
140 7000 0 0 1 4400 3 1 139 7000 0 0 1 4400 3 1
141 7000 0 0 2 4400 3 1 140 7000 0 0 2 4400 3 1
142 7000 0 0 3 4400 3 1 141 7000 0 0 3 4400 3 1
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index c03103c63285..ba54c6b40a09 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -24,7 +24,6 @@
24 #size-cells = <1>; 24 #size-cells = <1>;
25 25
26 cpus { 26 cpus {
27 #cpus = <1>;
28 #address-cells = <1>; 27 #address-cells = <1>;
29 #size-cells = <0>; 28 #size-cells = <0>;
30 29
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 3875ca9a9a62..2e003081b0d3 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -24,7 +24,6 @@
24 #size-cells = <1>; 24 #size-cells = <1>;
25 25
26 cpus { 26 cpus {
27 #cpus = <1>;
28 #address-cells = <1>; 27 #address-cells = <1>;
29 #size-cells = <0>; 28 #size-cells = <0>;
30 29
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 41d0720c5900..6fa3754f293a 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -19,7 +19,6 @@
19 linux,phandle = <100>; 19 linux,phandle = <100>;
20 20
21 cpus { 21 cpus {
22 #cpus = <1>;
23 #address-cells = <1>; 22 #address-cells = <1>;
24 #size-cells =<0>; 23 #size-cells =<0>;
25 linux,phandle = <200>; 24 linux,phandle = <200>;
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
index 260b2e447779..423eedcf634f 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -17,7 +17,6 @@
17 linux,phandle = <100>; 17 linux,phandle = <100>;
18 18
19 cpus { 19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 linux,phandle = <200>; 22 linux,phandle = <200>;
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 6d721900d00e..a1533cc07d09 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -16,7 +16,6 @@
16 #size-cells = <1>; 16 #size-cells = <1>;
17 17
18 cpus { 18 cpus {
19 #cpus = <1>;
20 #address-cells = <1>; 19 #address-cells = <1>;
21 #size-cells = <0>; 20 #size-cells = <0>;
22 21
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 06b310698a02..c798491f4cd0 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -16,7 +16,6 @@
16 #size-cells = <1>; 16 #size-cells = <1>;
17 17
18 cpus { 18 cpus {
19 #cpus = <1>;
20 #address-cells = <1>; 19 #address-cells = <1>;
21 #size-cells = <0>; 20 #size-cells = <0>;
22 21
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
new file mode 100644
index 000000000000..b55bced1593d
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -0,0 +1,291 @@
1/*
2 * MPC832x RDB Device Tree Source
3 *
4 * Copyright 2007 Freescale Semiconductor Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12/ {
13 model = "MPC8323ERDB";
14 compatible = "MPC8323ERDB", "MPC832xRDB", "MPC83xxRDB";
15 #address-cells = <1>;
16 #size-cells = <1>;
17
18 cpus {
19 #address-cells = <1>;
20 #size-cells = <0>;
21
22 PowerPC,8323@0 {
23 device_type = "cpu";
24 reg = <0>;
25 d-cache-line-size = <20>; // 32 bytes
26 i-cache-line-size = <20>; // 32 bytes
27 d-cache-size = <4000>; // L1, 16K
28 i-cache-size = <4000>; // L1, 16K
29 timebase-frequency = <0>;
30 bus-frequency = <0>;
31 clock-frequency = <0>;
32 32-bit;
33 };
34 };
35
36 memory {
37 device_type = "memory";
38 reg = <00000000 04000000>;
39 };
40
41 soc8323@e0000000 {
42 #address-cells = <1>;
43 #size-cells = <1>;
44 #interrupt-cells = <2>;
45 device_type = "soc";
46 ranges = <0 e0000000 00100000>;
47 reg = <e0000000 00000200>;
48 bus-frequency = <0>;
49
50 wdt@200 {
51 device_type = "watchdog";
52 compatible = "mpc83xx_wdt";
53 reg = <200 100>;
54 };
55
56 i2c@3000 {
57 device_type = "i2c";
58 compatible = "fsl-i2c";
59 reg = <3000 100>;
60 interrupts = <e 8>;
61 interrupt-parent = <&pic>;
62 dfsrr;
63 };
64
65 serial@4500 {
66 device_type = "serial";
67 compatible = "ns16550";
68 reg = <4500 100>;
69 clock-frequency = <0>;
70 interrupts = <9 8>;
71 interrupt-parent = <&pic>;
72 };
73
74 serial@4600 {
75 device_type = "serial";
76 compatible = "ns16550";
77 reg = <4600 100>;
78 clock-frequency = <0>;
79 interrupts = <a 8>;
80 interrupt-parent = <&pic>;
81 };
82
83 crypto@30000 {
84 device_type = "crypto";
85 model = "SEC2";
86 compatible = "talitos";
87 reg = <30000 7000>;
88 interrupts = <b 8>;
89 interrupt-parent = <&pic>;
90 /* Rev. 2.2 */
91 num-channels = <1>;
92 channel-fifo-len = <18>;
93 exec-units-mask = <0000004c>;
94 descriptor-types-mask = <0122003f>;
95 };
96
97 pci@8500 {
98 interrupt-map-mask = <f800 0 0 7>;
99 interrupt-map = <
100 /* IDSEL 0x10 AD16 (USB) */
101 8000 0 0 1 &pic 11 8
102
103 /* IDSEL 0x11 AD17 (Mini1)*/
104 8800 0 0 1 &pic 12 8
105 8800 0 0 2 &pic 13 8
106 8800 0 0 3 &pic 14 8
107 8800 0 0 4 &pic 30 8
108
109 /* IDSEL 0x12 AD18 (PCI/Mini2) */
110 9000 0 0 1 &pic 13 8
111 9000 0 0 2 &pic 14 8
112 9000 0 0 3 &pic 30 8
113 9000 0 0 4 &pic 11 8>;
114
115 interrupt-parent = <&pic>;
116 interrupts = <42 8>;
117 bus-range = <0 0>;
118 ranges = <42000000 0 80000000 80000000 0 10000000
119 02000000 0 90000000 90000000 0 10000000
120 01000000 0 d0000000 d0000000 0 04000000>;
121 clock-frequency = <0>;
122 #interrupt-cells = <1>;
123 #size-cells = <2>;
124 #address-cells = <3>;
125 reg = <8500 100>;
126 compatible = "83xx";
127 device_type = "pci";
128 };
129
130 pic:pic@700 {
131 interrupt-controller;
132 #address-cells = <0>;
133 #interrupt-cells = <2>;
134 reg = <700 100>;
135 built-in;
136 device_type = "ipic";
137 };
138
139 par_io@1400 {
140 reg = <1400 100>;
141 device_type = "par_io";
142 num-ports = <7>;
143
144 ucc2pio:ucc_pin@02 {
145 pio-map = <
146 /* port pin dir open_drain assignment has_irq */
147 3 4 3 0 2 0 /* MDIO */
148 3 5 1 0 2 0 /* MDC */
149 3 15 2 0 1 0 /* RX_CLK (CLK16) */
150 3 17 2 0 1 0 /* TX_CLK (CLK3) */
151 0 12 1 0 1 0 /* TxD0 */
152 0 13 1 0 1 0 /* TxD1 */
153 0 14 1 0 1 0 /* TxD2 */
154 0 15 1 0 1 0 /* TxD3 */
155 0 16 2 0 1 0 /* RxD0 */
156 0 17 2 0 1 0 /* RxD1 */
157 0 18 2 0 1 0 /* RxD2 */
158 0 19 2 0 1 0 /* RxD3 */
159 0 1a 2 0 1 0 /* RX_ER */
160 0 1b 1 0 1 0 /* TX_ER */
161 0 1c 2 0 1 0 /* RX_DV */
162 0 1d 2 0 1 0 /* COL */
163 0 1e 1 0 1 0 /* TX_EN */
164 0 1f 2 0 1 0>; /* CRS */
165 };
166 ucc3pio:ucc_pin@03 {
167 pio-map = <
168 /* port pin dir open_drain assignment has_irq */
169 0 d 2 0 1 0 /* RX_CLK (CLK9) */
170 3 18 2 0 1 0 /* TX_CLK (CLK10) */
171 1 0 1 0 1 0 /* TxD0 */
172 1 1 1 0 1 0 /* TxD1 */
173 1 2 1 0 1 0 /* TxD2 */
174 1 3 1 0 1 0 /* TxD3 */
175 1 4 2 0 1 0 /* RxD0 */
176 1 5 2 0 1 0 /* RxD1 */
177 1 6 2 0 1 0 /* RxD2 */
178 1 7 2 0 1 0 /* RxD3 */
179 1 8 2 0 1 0 /* RX_ER */
180 1 9 1 0 1 0 /* TX_ER */
181 1 a 2 0 1 0 /* RX_DV */
182 1 b 2 0 1 0 /* COL */
183 1 c 1 0 1 0 /* TX_EN */
184 1 d 2 0 1 0>; /* CRS */
185 };
186 };
187 };
188
189 qe@e0100000 {
190 #address-cells = <1>;
191 #size-cells = <1>;
192 device_type = "qe";
193 model = "QE";
194 ranges = <0 e0100000 00100000>;
195 reg = <e0100000 480>;
196 brg-frequency = <0>;
197 bus-frequency = <BCD3D80>;
198
199 muram@10000 {
200 device_type = "muram";
201 ranges = <0 00010000 00004000>;
202
203 data-only@0 {
204 reg = <0 4000>;
205 };
206 };
207
208 spi@4c0 {
209 device_type = "spi";
210 compatible = "fsl_spi";
211 reg = <4c0 40>;
212 interrupts = <2>;
213 interrupt-parent = <&qeic>;
214 mode = "cpu";
215 };
216
217 spi@500 {
218 device_type = "spi";
219 compatible = "fsl_spi";
220 reg = <500 40>;
221 interrupts = <1>;
222 interrupt-parent = <&qeic>;
223 mode = "cpu";
224 };
225
226 ucc@3000 {
227 device_type = "network";
228 compatible = "ucc_geth";
229 model = "UCC";
230 device-id = <2>;
231 reg = <3000 200>;
232 interrupts = <21>;
233 interrupt-parent = <&qeic>;
234 mac-address = [ 00 04 9f ef 03 02 ];
235 rx-clock = <20>;
236 tx-clock = <13>;
237 phy-handle = <&phy00>;
238 pio-handle = <&ucc2pio>;
239 };
240
241 ucc@2200 {
242 device_type = "network";
243 compatible = "ucc_geth";
244 model = "UCC";
245 device-id = <3>;
246 reg = <2200 200>;
247 interrupts = <22>;
248 interrupt-parent = <&qeic>;
249 mac-address = [ 00 04 9f ef 03 01 ];
250 rx-clock = <19>;
251 tx-clock = <1a>;
252 phy-handle = <&phy04>;
253 pio-handle = <&ucc3pio>;
254 };
255
256 mdio@3120 {
257 #address-cells = <1>;
258 #size-cells = <0>;
259 reg = <3120 18>;
260 device_type = "mdio";
261 compatible = "ucc_geth_phy";
262
263 phy00:ethernet-phy@00 {
264 interrupt-parent = <&pic>;
265 interrupts = <0>;
266 reg = <0>;
267 device_type = "ethernet-phy";
268 interface = <3>; //ENET_100_MII
269 };
270 phy04:ethernet-phy@04 {
271 interrupt-parent = <&pic>;
272 interrupts = <0>;
273 reg = <4>;
274 device_type = "ethernet-phy";
275 interface = <3>;
276 };
277 };
278
279 qeic:qeic@80 {
280 interrupt-controller;
281 device_type = "qeic";
282 #address-cells = <0>;
283 #interrupt-cells = <1>;
284 reg = <80 80>;
285 built-in;
286 big-endian;
287 interrupts = <20 8 21 8>; //high:32 low:33
288 interrupt-parent = <&pic>;
289 };
290 };
291};
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 61b550bf1645..db0d00303275 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -15,7 +15,6 @@
15 #size-cells = <1>; 15 #size-cells = <1>;
16 16
17 cpus { 17 cpus {
18 #cpus = <1>;
19 #address-cells = <1>; 18 #address-cells = <1>;
20 #size-cells = <0>; 19 #size-cells = <0>;
21 20
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
index b2e1a5ec3779..f636528a3c72 100644
--- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
@@ -15,7 +15,6 @@
15 #size-cells = <1>; 15 #size-cells = <1>;
16 16
17 cpus { 17 cpus {
18 #cpus = <1>;
19 #address-cells = <1>; 18 #address-cells = <1>;
20 #size-cells = <0>; 19 #size-cells = <0>;
21 20
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index e4b43c24bc0b..07bcc5194d2b 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -16,7 +16,6 @@
16 #size-cells = <1>; 16 #size-cells = <1>;
17 17
18 cpus { 18 cpus {
19 #cpus = <1>;
20 #address-cells = <1>; 19 #address-cells = <1>;
21 #size-cells = <0>; 20 #size-cells = <0>;
22 21
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 4fe45c021848..7f578eb57082 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -21,7 +21,6 @@
21 #size-cells = <1>; 21 #size-cells = <1>;
22 22
23 cpus { 23 cpus {
24 #cpus = <1>;
25 #address-cells = <1>; 24 #address-cells = <1>;
26 #size-cells = <0>; 25 #size-cells = <0>;
27 26
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index 3c0917fa791c..f261d647ac85 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -17,7 +17,6 @@
17 #size-cells = <1>; 17 #size-cells = <1>;
18 18
19 cpus { 19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 22
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 2a1ae760ab3a..5fdcb69554f2 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -17,7 +17,6 @@
17 #size-cells = <1>; 17 #size-cells = <1>;
18 18
19 cpus { 19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 22
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
new file mode 100644
index 000000000000..6b084605bb4b
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -0,0 +1,136 @@
1/*
2 * MPC8544 DS Device Tree Source
3 *
4 * Copyright 2007 Freescale Semiconductor Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12/ {
13 model = "MPC8544DS";
14 compatible = "MPC8544DS", "MPC85xxDS";
15 #address-cells = <1>;
16 #size-cells = <1>;
17
18 cpus {
19 #cpus = <1>;
20 #address-cells = <1>;
21 #size-cells = <0>;
22
23 PowerPC,8544@0 {
24 device_type = "cpu";
25 reg = <0>;
26 d-cache-line-size = <20>; // 32 bytes
27 i-cache-line-size = <20>; // 32 bytes
28 d-cache-size = <8000>; // L1, 32K
29 i-cache-size = <8000>; // L1, 32K
30 timebase-frequency = <0>;
31 bus-frequency = <0>;
32 clock-frequency = <0>;
33 32-bit;
34 };
35 };
36
37 memory {
38 device_type = "memory";
39 reg = <00000000 00000000>; // Filled by U-Boot
40 };
41
42 soc8544@e0000000 {
43 #address-cells = <1>;
44 #size-cells = <1>;
45 #interrupt-cells = <2>;
46 device_type = "soc";
47 ranges = <0 e0000000 00100000>;
48 reg = <e0000000 00100000>; // CCSRBAR 1M
49 bus-frequency = <0>; // Filled out by uboot.
50
51 i2c@3000 {
52 device_type = "i2c";
53 compatible = "fsl-i2c";
54 reg = <3000 100>;
55 interrupts = <1b 2>;
56 interrupt-parent = <&mpic>;
57 dfsrr;
58 };
59
60 mdio@24520 {
61 #address-cells = <1>;
62 #size-cells = <0>;
63 device_type = "mdio";
64 compatible = "gianfar";
65 reg = <24520 20>;
66 phy0: ethernet-phy@0 {
67 interrupt-parent = <&mpic>;
68 interrupts = <3a 1>;
69 reg = <0>;
70 device_type = "ethernet-phy";
71 };
72 phy1: ethernet-phy@1 {
73 interrupt-parent = <&mpic>;
74 interrupts = <3a 1>;
75 reg = <1>;
76 device_type = "ethernet-phy";
77 };
78 };
79
80 ethernet@24000 {
81 #address-cells = <1>;
82 #size-cells = <0>;
83 device_type = "network";
84 model = "TSEC";
85 compatible = "gianfar";
86 reg = <24000 1000>;
87 local-mac-address = [ 00 00 00 00 00 00 ];
88 interrupts = <d 2 e 2 12 2>;
89 interrupt-parent = <&mpic>;
90 phy-handle = <&phy0>;
91 };
92
93 ethernet@26000 {
94 #address-cells = <1>;
95 #size-cells = <0>;
96 device_type = "network";
97 model = "TSEC";
98 compatible = "gianfar";
99 reg = <26000 1000>;
100 local-mac-address = [ 00 00 00 00 00 00 ];
101 interrupts = <f 2 10 2 11 2>;
102 interrupt-parent = <&mpic>;
103 phy-handle = <&phy1>;
104 };
105
106 serial@4500 {
107 device_type = "serial";
108 compatible = "ns16550";
109 reg = <4500 100>;
110 clock-frequency = <0>;
111 interrupts = <1a 2>;
112 interrupt-parent = <&mpic>;
113 };
114
115 serial@4600 {
116 device_type = "serial";
117 compatible = "ns16550";
118 reg = <4600 100>;
119 clock-frequency = <0>;
120 interrupts = <1a 2>;
121 interrupt-parent = <&mpic>;
122 };
123
124 mpic: pic@40000 {
125 clock-frequency = <0>;
126 interrupt-controller;
127 #address-cells = <0>;
128 #interrupt-cells = <2>;
129 reg = <40000 40000>;
130 built-in;
131 compatible = "chrp,open-pic";
132 device_type = "open-pic";
133 big-endian;
134 };
135 };
136};
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index 7eb5d81d5eec..b2b2200d0425 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -17,7 +17,6 @@
17 #size-cells = <1>; 17 #size-cells = <1>;
18 18
19 cpus { 19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 22
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 5f9c102a0ab4..68a4795720dc 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -17,7 +17,6 @@
17 #size-cells = <1>; 17 #size-cells = <1>;
18 18
19 cpus { 19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 22
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 10502638b0e9..1f2afe9291d2 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -17,7 +17,6 @@
17 #size-cells = <1>; 17 #size-cells = <1>;
18 18
19 cpus { 19 cpus {
20 #cpus = <1>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 22
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index bf49d8c997b9..7361b36749cb 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -21,7 +21,6 @@
21 #size-cells = <1>; 21 #size-cells = <1>;
22 22
23 cpus { 23 cpus {
24 #cpus = <1>;
25 #address-cells = <1>; 24 #address-cells = <1>;
26 #size-cells = <0>; 25 #size-cells = <0>;
27 26
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 8a4995a85ba0..260b264c869e 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -17,7 +17,6 @@
17 #size-cells = <1>; 17 #size-cells = <1>;
18 18
19 cpus { 19 cpus {
20 #cpus = <2>;
21 #address-cells = <1>; 20 #address-cells = <1>;
22 #size-cells = <0>; 21 #size-cells = <0>;
23 22
@@ -300,6 +299,30 @@
300 }; 299 };
301 300
302 }; 301 };
302
303 pci@9000 {
304 compatible = "86xx";
305 device_type = "pci";
306 #interrupt-cells = <1>;
307 #size-cells = <2>;
308 #address-cells = <3>;
309 reg = <9000 1000>;
310 bus-range = <0 ff>;
311 ranges = <02000000 0 a0000000 a0000000 0 20000000
312 01000000 0 00000000 e3000000 0 00100000>;
313 clock-frequency = <1fca055>;
314 interrupt-parent = <&mpic>;
315 interrupts = <19 2>;
316 interrupt-map-mask = <f800 0 0 7>;
317 interrupt-map = <
318 /* IDSEL 0x0 */
319 0000 0 0 1 &mpic 44 1
320 0000 0 0 2 &mpic 45 1
321 0000 0 0 3 &mpic 46 1
322 0000 0 0 4 &mpic 47 1
323 >;
324 };
325
303 mpic: pic@40000 { 326 mpic: pic@40000 {
304 clock-frequency = <0>; 327 clock-frequency = <0>;
305 interrupt-controller; 328 interrupt-controller;
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index 2b56b5df451a..c0d06fd12927 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -18,7 +18,6 @@
18 linux,phandle = <100>; 18 linux,phandle = <100>;
19 19
20 cpus { 20 cpus {
21 #cpus = <1>;
22 #address-cells = <1>; 21 #address-cells = <1>;
23 #size-cells = <0>; 22 #size-cells = <0>;
24 linux,phandle = <200>; 23 linux,phandle = <200>;
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index faecd08c54da..110bf6170603 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -18,7 +18,6 @@
18 linux,phandle = <100>; 18 linux,phandle = <100>;
19 19
20 cpus { 20 cpus {
21 #cpus = <1>;
22 #address-cells = <1>; 21 #address-cells = <1>;
23 #size-cells = <0>; 22 #size-cells = <0>;
24 linux,phandle = <200>; 23 linux,phandle = <200>;
diff --git a/arch/powerpc/boot/elf.h b/arch/powerpc/boot/elf.h
index d4828fcf1cb9..1941bc50d4c5 100644
--- a/arch/powerpc/boot/elf.h
+++ b/arch/powerpc/boot/elf.h
@@ -146,4 +146,12 @@ typedef struct elf64_phdr {
146#define ELFOSABI_NONE 0 146#define ELFOSABI_NONE 0
147#define ELFOSABI_LINUX 3 147#define ELFOSABI_LINUX 3
148 148
149struct elf_info {
150 unsigned long loadsize;
151 unsigned long memsize;
152 unsigned long elfoffset;
153};
154int parse_elf64(void *hdr, struct elf_info *info);
155int parse_elf32(void *hdr, struct elf_info *info);
156
149#endif /* _PPC_BOOT_ELF_H_ */ 157#endif /* _PPC_BOOT_ELF_H_ */
diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c
new file mode 100644
index 000000000000..7454aa4cc20c
--- /dev/null
+++ b/arch/powerpc/boot/elf_util.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright (C) Paul Mackerras 1997.
3 *
4 * Updates for PPC64 by Todd Inglett, Dave Engebretsen & Peter Bergner.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <stdarg.h>
12#include <stddef.h>
13#include "elf.h"
14#include "page.h"
15#include "string.h"
16#include "stdio.h"
17
18int parse_elf64(void *hdr, struct elf_info *info)
19{
20 Elf64_Ehdr *elf64 = hdr;
21 Elf64_Phdr *elf64ph;
22 unsigned int i;
23
24 if (!(elf64->e_ident[EI_MAG0] == ELFMAG0 &&
25 elf64->e_ident[EI_MAG1] == ELFMAG1 &&
26 elf64->e_ident[EI_MAG2] == ELFMAG2 &&
27 elf64->e_ident[EI_MAG3] == ELFMAG3 &&
28 elf64->e_ident[EI_CLASS] == ELFCLASS64 &&
29 elf64->e_ident[EI_DATA] == ELFDATA2MSB &&
30 elf64->e_type == ET_EXEC &&
31 elf64->e_machine == EM_PPC64))
32 return 0;
33
34 elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
35 (unsigned long)elf64->e_phoff);
36 for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++)
37 if (elf64ph->p_type == PT_LOAD)
38 break;
39 if (i >= (unsigned int)elf64->e_phnum)
40 return 0;
41
42 info->loadsize = (unsigned long)elf64ph->p_filesz;
43 info->memsize = (unsigned long)elf64ph->p_memsz;
44 info->elfoffset = (unsigned long)elf64ph->p_offset;
45
46 return 1;
47}
48
49int parse_elf32(void *hdr, struct elf_info *info)
50{
51 Elf32_Ehdr *elf32 = hdr;
52 Elf32_Phdr *elf32ph;
53 unsigned int i;
54
55 if (!(elf32->e_ident[EI_MAG0] == ELFMAG0 &&
56 elf32->e_ident[EI_MAG1] == ELFMAG1 &&
57 elf32->e_ident[EI_MAG2] == ELFMAG2 &&
58 elf32->e_ident[EI_MAG3] == ELFMAG3 &&
59 elf32->e_ident[EI_CLASS] == ELFCLASS32 &&
60 elf32->e_ident[EI_DATA] == ELFDATA2MSB &&
61 elf32->e_type == ET_EXEC &&
62 elf32->e_machine == EM_PPC))
63 return 0;
64
65 elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff);
66 for (i = 0; i < elf32->e_phnum; i++, elf32ph++)
67 if (elf32ph->p_type == PT_LOAD)
68 break;
69 if (i >= elf32->e_phnum)
70 return 0;
71
72 info->loadsize = elf32ph->p_filesz;
73 info->memsize = elf32ph->p_memsz;
74 info->elfoffset = elf32ph->p_offset;
75 return 1;
76}
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
index c76c194715b2..d00fbd92a458 100644
--- a/arch/powerpc/boot/flatdevtree.c
+++ b/arch/powerpc/boot/flatdevtree.c
@@ -29,12 +29,20 @@
29 29
30#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1)) 30#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1))
31 31
32static char *ft_root_node(struct ft_cxt *cxt)
33{
34 return cxt->rgn[FT_STRUCT].start;
35}
36
32/* Routines for keeping node ptrs returned by ft_find_device current */ 37/* Routines for keeping node ptrs returned by ft_find_device current */
33/* First entry not used b/c it would return 0 and be taken as NULL/error */ 38/* First entry not used b/c it would return 0 and be taken as NULL/error */
34static void *ft_node_add(struct ft_cxt *cxt, char *node) 39static void *ft_get_phandle(struct ft_cxt *cxt, char *node)
35{ 40{
36 unsigned int i; 41 unsigned int i;
37 42
43 if (!node)
44 return NULL;
45
38 for (i = 1; i < cxt->nodes_used; i++) /* already there? */ 46 for (i = 1; i < cxt->nodes_used; i++) /* already there? */
39 if (cxt->node_tbl[i] == node) 47 if (cxt->node_tbl[i] == node)
40 return (void *)i; 48 return (void *)i;
@@ -238,7 +246,7 @@ static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
238 if (rgn == FT_STRUCT) 246 if (rgn == FT_STRUCT)
239 ft_node_update_before(cxt, p, -nextra); 247 ft_node_update_before(cxt, p, -nextra);
240 } 248 }
241 *p -= nextra; 249 *pp -= nextra;
242 cxt->rgn[rgn].start -= nextra; 250 cxt->rgn[rgn].start -= nextra;
243 cxt->rgn[rgn].size += nextra; 251 cxt->rgn[rgn].size += nextra;
244 return 1; 252 return 1;
@@ -253,8 +261,14 @@ static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
253 char *str, *next; 261 char *str, *next;
254 enum ft_rgn_id r; 262 enum ft_rgn_id r;
255 263
256 if (!cxt->isordered && !ft_reorder(cxt, nextra)) 264 if (!cxt->isordered) {
257 return 0; 265 unsigned long rgn_off = *pp - cxt->rgn[rgn].start;
266
267 if (!ft_reorder(cxt, nextra))
268 return 0;
269
270 *pp = cxt->rgn[rgn].start + rgn_off;
271 }
258 if (ft_shuffle(cxt, pp, rgn, nextra)) 272 if (ft_shuffle(cxt, pp, rgn, nextra))
259 return 1; 273 return 1;
260 274
@@ -415,7 +429,7 @@ int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
415{ 429{
416 int off, len; 430 int off, len;
417 431
418 off = lookup_string(cxt, name); 432 off = map_string(cxt, name);
419 if (off == NO_STRING) 433 if (off == NO_STRING)
420 return -1; 434 return -1;
421 435
@@ -590,7 +604,7 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
590 604
591void ft_begin_tree(struct ft_cxt *cxt) 605void ft_begin_tree(struct ft_cxt *cxt)
592{ 606{
593 cxt->p = cxt->rgn[FT_STRUCT].start; 607 cxt->p = ft_root_node(cxt);
594} 608}
595 609
596void ft_end_tree(struct ft_cxt *cxt) 610void ft_end_tree(struct ft_cxt *cxt)
@@ -636,8 +650,21 @@ void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
636 /* require absolute path */ 650 /* require absolute path */
637 if (srch_path[0] != '/') 651 if (srch_path[0] != '/')
638 return NULL; 652 return NULL;
639 node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path); 653 node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path);
640 return ft_node_add(cxt, node); 654 return ft_get_phandle(cxt, node);
655}
656
657void *ft_find_device_rel(struct ft_cxt *cxt, const void *top,
658 const char *srch_path)
659{
660 char *node;
661
662 node = ft_node_ph2node(cxt, top);
663 if (node == NULL)
664 return NULL;
665
666 node = ft_find_descendent(cxt, node, srch_path);
667 return ft_get_phandle(cxt, node);
641} 668}
642 669
643void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) 670void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
@@ -701,23 +728,18 @@ void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
701 return NULL; 728 return NULL;
702} 729}
703 730
704void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) 731void *__ft_get_parent(struct ft_cxt *cxt, void *node)
705{ 732{
706 void *node;
707 int d; 733 int d;
708 struct ft_atom atom; 734 struct ft_atom atom;
709 char *p; 735 char *p;
710 736
711 node = ft_node_ph2node(cxt, phandle);
712 if (node == NULL)
713 return NULL;
714
715 for (d = 0; cxt->genealogy[d] != NULL; ++d) 737 for (d = 0; cxt->genealogy[d] != NULL; ++d)
716 if (cxt->genealogy[d] == node) 738 if (cxt->genealogy[d] == node)
717 return cxt->genealogy[d > 0 ? d - 1 : 0]; 739 return d > 0 ? cxt->genealogy[d - 1] : NULL;
718 740
719 /* have to do it the hard way... */ 741 /* have to do it the hard way... */
720 p = cxt->rgn[FT_STRUCT].start; 742 p = ft_root_node(cxt);
721 d = 0; 743 d = 0;
722 while ((p = ft_next(cxt, p, &atom)) != NULL) { 744 while ((p = ft_next(cxt, p, &atom)) != NULL) {
723 switch (atom.tag) { 745 switch (atom.tag) {
@@ -726,7 +748,7 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
726 if (node == atom.data) { 748 if (node == atom.data) {
727 /* found it */ 749 /* found it */
728 cxt->genealogy[d + 1] = NULL; 750 cxt->genealogy[d + 1] = NULL;
729 return d > 0 ? cxt->genealogy[d - 1] : node; 751 return d > 0 ? cxt->genealogy[d - 1] : NULL;
730 } 752 }
731 ++d; 753 ++d;
732 break; 754 break;
@@ -738,41 +760,131 @@ void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
738 return NULL; 760 return NULL;
739} 761}
740 762
741int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, 763void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
742 void *buf, const unsigned int buflen)
743{ 764{
744 struct ft_atom atom; 765 void *node = ft_node_ph2node(cxt, phandle);
745 void *node;
746 char *p;
747 int depth;
748 unsigned int size;
749
750 node = ft_node_ph2node(cxt, phandle);
751 if (node == NULL) 766 if (node == NULL)
752 return -1; 767 return NULL;
753 768
754 depth = 0; 769 node = __ft_get_parent(cxt, node);
755 p = (char *)node; 770 return ft_get_phandle(cxt, node);
771}
756 772
757 while ((p = ft_next(cxt, p, &atom)) != NULL) { 773static const void *__ft_get_prop(struct ft_cxt *cxt, void *node,
774 const char *propname, unsigned int *len)
775{
776 struct ft_atom atom;
777 int depth = 0;
778
779 while ((node = ft_next(cxt, node, &atom)) != NULL) {
758 switch (atom.tag) { 780 switch (atom.tag) {
759 case OF_DT_BEGIN_NODE: 781 case OF_DT_BEGIN_NODE:
760 ++depth; 782 ++depth;
761 break; 783 break;
784
762 case OF_DT_PROP: 785 case OF_DT_PROP:
763 if ((depth != 1) || strcmp(atom.name, propname)) 786 if (depth != 1 || strcmp(atom.name, propname))
764 break; 787 break;
765 size = min(atom.size, buflen); 788
766 memcpy(buf, atom.data, size); 789 if (len)
767 return atom.size; 790 *len = atom.size;
791
792 return atom.data;
793
768 case OF_DT_END_NODE: 794 case OF_DT_END_NODE:
769 if (--depth <= 0) 795 if (--depth <= 0)
770 return -1; 796 return NULL;
771 } 797 }
772 } 798 }
799
800 return NULL;
801}
802
803int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
804 void *buf, const unsigned int buflen)
805{
806 const void *data;
807 unsigned int size;
808
809 void *node = ft_node_ph2node(cxt, phandle);
810 if (!node)
811 return -1;
812
813 data = __ft_get_prop(cxt, node, propname, &size);
814 if (data) {
815 unsigned int clipped_size = min(size, buflen);
816 memcpy(buf, data, clipped_size);
817 return size;
818 }
819
773 return -1; 820 return -1;
774} 821}
775 822
823void *__ft_find_node_by_prop_value(struct ft_cxt *cxt, void *prev,
824 const char *propname, const char *propval,
825 unsigned int proplen)
826{
827 struct ft_atom atom;
828 char *p = ft_root_node(cxt);
829 char *next;
830 int past_prev = prev ? 0 : 1;
831 int depth = -1;
832
833 while ((next = ft_next(cxt, p, &atom)) != NULL) {
834 const void *data;
835 unsigned int size;
836
837 switch (atom.tag) {
838 case OF_DT_BEGIN_NODE:
839 depth++;
840
841 if (prev == p) {
842 past_prev = 1;
843 break;
844 }
845
846 if (!past_prev || depth < 1)
847 break;
848
849 data = __ft_get_prop(cxt, p, propname, &size);
850 if (!data || size != proplen)
851 break;
852 if (memcmp(data, propval, size))
853 break;
854
855 return p;
856
857 case OF_DT_END_NODE:
858 if (depth-- == 0)
859 return NULL;
860
861 break;
862 }
863
864 p = next;
865 }
866
867 return NULL;
868}
869
870void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev,
871 const char *propname, const char *propval,
872 int proplen)
873{
874 void *node = NULL;
875
876 if (prev) {
877 node = ft_node_ph2node(cxt, prev);
878
879 if (!node)
880 return NULL;
881 }
882
883 node = __ft_find_node_by_prop_value(cxt, node, propname,
884 propval, proplen);
885 return ft_get_phandle(cxt, node);
886}
887
776int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, 888int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
777 const void *buf, const unsigned int buflen) 889 const void *buf, const unsigned int buflen)
778{ 890{
@@ -849,19 +961,26 @@ int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
849 return -1; 961 return -1;
850} 962}
851 963
852void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) 964void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name)
853{ 965{
854 struct ft_atom atom; 966 struct ft_atom atom;
855 char *p, *next; 967 char *p, *next;
856 int depth = 0; 968 int depth = 0;
857 969
858 p = cxt->rgn[FT_STRUCT].start; 970 if (parent) {
971 p = ft_node_ph2node(cxt, parent);
972 if (!p)
973 return NULL;
974 } else {
975 p = ft_root_node(cxt);
976 }
977
859 while ((next = ft_next(cxt, p, &atom)) != NULL) { 978 while ((next = ft_next(cxt, p, &atom)) != NULL) {
860 switch (atom.tag) { 979 switch (atom.tag) {
861 case OF_DT_BEGIN_NODE: 980 case OF_DT_BEGIN_NODE:
862 ++depth; 981 ++depth;
863 if (depth == 1 && strcmp(atom.name, path) == 0) 982 if (depth == 1 && strcmp(atom.name, name) == 0)
864 /* duplicate node path, return error */ 983 /* duplicate node name, return error */
865 return NULL; 984 return NULL;
866 break; 985 break;
867 case OF_DT_END_NODE: 986 case OF_DT_END_NODE:
@@ -870,7 +989,7 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
870 break; 989 break;
871 /* end of node, insert here */ 990 /* end of node, insert here */
872 cxt->p = p; 991 cxt->p = p;
873 ft_begin_node(cxt, path); 992 ft_begin_node(cxt, name);
874 ft_end_node(cxt); 993 ft_end_node(cxt);
875 return p; 994 return p;
876 } 995 }
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
index b9cd9f61f351..cb26325d72db 100644
--- a/arch/powerpc/boot/flatdevtree.h
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -97,10 +97,17 @@ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
97void ft_dump_blob(const void *bphp); 97void ft_dump_blob(const void *bphp);
98void ft_merge_blob(struct ft_cxt *cxt, void *blob); 98void ft_merge_blob(struct ft_cxt *cxt, void *blob);
99void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); 99void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
100void *ft_find_device_rel(struct ft_cxt *cxt, const void *top,
101 const char *srch_path);
100void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); 102void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
101int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, 103int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
102 void *buf, const unsigned int buflen); 104 void *buf, const unsigned int buflen);
103int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, 105int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
104 const void *buf, const unsigned int buflen); 106 const void *buf, const unsigned int buflen);
107void *ft_get_parent(struct ft_cxt *cxt, const void *phandle);
108void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev,
109 const char *propname, const char *propval,
110 int proplen);
111void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name);
105 112
106#endif /* FLATDEVTREE_H */ 113#endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c
index 04da38fa477f..4341e6558c1a 100644
--- a/arch/powerpc/boot/flatdevtree_misc.c
+++ b/arch/powerpc/boot/flatdevtree_misc.c
@@ -16,24 +16,43 @@
16 16
17static struct ft_cxt cxt; 17static struct ft_cxt cxt;
18 18
19static void *ft_finddevice(const char *name) 19static void *fdtm_finddevice(const char *name)
20{ 20{
21 return ft_find_device(&cxt, name); 21 return ft_find_device(&cxt, name);
22} 22}
23 23
24static int ft_getprop(const void *phandle, const char *propname, void *buf, 24static int fdtm_getprop(const void *phandle, const char *propname,
25 const int buflen) 25 void *buf, const int buflen)
26{ 26{
27 return ft_get_prop(&cxt, phandle, propname, buf, buflen); 27 return ft_get_prop(&cxt, phandle, propname, buf, buflen);
28} 28}
29 29
30static int ft_setprop(const void *phandle, const char *propname, 30static int fdtm_setprop(const void *phandle, const char *propname,
31 const void *buf, const int buflen) 31 const void *buf, const int buflen)
32{ 32{
33 return ft_set_prop(&cxt, phandle, propname, buf, buflen); 33 return ft_set_prop(&cxt, phandle, propname, buf, buflen);
34} 34}
35 35
36static unsigned long ft_finalize(void) 36static void *fdtm_get_parent(const void *phandle)
37{
38 return ft_get_parent(&cxt, phandle);
39}
40
41static void *fdtm_create_node(const void *phandle, const char *name)
42{
43 return ft_create_node(&cxt, phandle, name);
44}
45
46static void *fdtm_find_node_by_prop_value(const void *prev,
47 const char *propname,
48 const char *propval,
49 int proplen)
50{
51 return ft_find_node_by_prop_value(&cxt, prev, propname,
52 propval, proplen);
53}
54
55static unsigned long fdtm_finalize(void)
37{ 56{
38 ft_end_tree(&cxt); 57 ft_end_tree(&cxt);
39 return (unsigned long)cxt.bph; 58 return (unsigned long)cxt.bph;
@@ -41,10 +60,13 @@ static unsigned long ft_finalize(void)
41 60
42int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) 61int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
43{ 62{
44 dt_ops.finddevice = ft_finddevice; 63 dt_ops.finddevice = fdtm_finddevice;
45 dt_ops.getprop = ft_getprop; 64 dt_ops.getprop = fdtm_getprop;
46 dt_ops.setprop = ft_setprop; 65 dt_ops.setprop = fdtm_setprop;
47 dt_ops.finalize = ft_finalize; 66 dt_ops.get_parent = fdtm_get_parent;
67 dt_ops.create_node = fdtm_create_node;
68 dt_ops.find_node_by_prop_value = fdtm_find_node_by_prop_value;
69 dt_ops.finalize = fdtm_finalize;
48 70
49 return ft_open(&cxt, dt_blob, max_size, max_find_device, 71 return ft_open(&cxt, dt_blob, max_size, max_find_device,
50 platform_ops.realloc); 72 platform_ops.realloc);
diff --git a/arch/powerpc/boot/gunzip_util.c b/arch/powerpc/boot/gunzip_util.c
new file mode 100644
index 000000000000..df8ab07e9ff4
--- /dev/null
+++ b/arch/powerpc/boot/gunzip_util.c
@@ -0,0 +1,206 @@
1/*
2 * Copyright 2007 David Gibson, IBM Corporation.
3 * Based on earlier work, Copyright (C) Paul Mackerras 1997.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#include <stddef.h>
12#include "string.h"
13#include "stdio.h"
14#include "ops.h"
15#include "gunzip_util.h"
16
17#define HEAD_CRC 2
18#define EXTRA_FIELD 4
19#define ORIG_NAME 8
20#define COMMENT 0x10
21#define RESERVED 0xe0
22
23/**
24 * gunzip_start - prepare to decompress gzip data
25 * @state: decompressor state structure to be initialized
26 * @src: buffer containing gzip compressed or uncompressed data
27 * @srclen: size in bytes of the buffer at src
28 *
29 * If the buffer at @src contains a gzip header, this function
30 * initializes zlib to decompress the data, storing the decompression
31 * state in @state. The other functions in this file can then be used
32 * to decompress data from the gzipped stream.
33 *
34 * If the buffer at @src does not contain a gzip header, it is assumed
35 * to contain uncompressed data. The buffer information is recorded
36 * in @state and the other functions in this file will simply copy
37 * data from the uncompressed data stream at @src.
38 *
39 * Any errors, such as bad compressed data, cause an error to be
40 * printed an the platform's exit() function to be called.
41 */
42void gunzip_start(struct gunzip_state *state, void *src, int srclen)
43{
44 char *hdr = src;
45 int hdrlen = 0;
46
47 memset(state, 0, sizeof(*state));
48
49 /* Check for gzip magic number */
50 if ((hdr[0] == 0x1f) && (hdr[1] == 0x8b)) {
51 /* gzip data, initialize zlib parameters */
52 int r, flags;
53
54 state->s.workspace = state->scratch;
55 if (zlib_inflate_workspacesize() > sizeof(state->scratch))
56 fatal("insufficient scratch space for gunzip\n\r");
57
58 /* skip header */
59 hdrlen = 10;
60 flags = hdr[3];
61 if (hdr[2] != Z_DEFLATED || (flags & RESERVED) != 0)
62 fatal("bad gzipped data\n\r");
63 if ((flags & EXTRA_FIELD) != 0)
64 hdrlen = 12 + hdr[10] + (hdr[11] << 8);
65 if ((flags & ORIG_NAME) != 0)
66 while (hdr[hdrlen++] != 0)
67 ;
68 if ((flags & COMMENT) != 0)
69 while (hdr[hdrlen++] != 0)
70 ;
71 if ((flags & HEAD_CRC) != 0)
72 hdrlen += 2;
73 if (hdrlen >= srclen)
74 fatal("gunzip_start: ran out of data in header\n\r");
75
76 r = zlib_inflateInit2(&state->s, -MAX_WBITS);
77 if (r != Z_OK)
78 fatal("inflateInit2 returned %d\n\r", r);
79 }
80
81 state->s.next_in = src + hdrlen;
82 state->s.avail_in = srclen - hdrlen;
83}
84
85/**
86 * gunzip_partial - extract bytes from a gzip data stream
87 * @state: gzip state structure previously initialized by gunzip_start()
88 * @dst: buffer to store extracted data
89 * @dstlen: maximum number of bytes to extract
90 *
91 * This function extracts at most @dstlen bytes from the data stream
92 * previously associated with @state by gunzip_start(), decompressing
93 * if necessary. Exactly @dstlen bytes are extracted unless the data
94 * stream doesn't contain enough bytes, in which case the entire
95 * remainder of the stream is decompressed.
96 *
97 * Returns the actual number of bytes extracted. If any errors occur,
98 * such as a corrupted compressed stream, an error is printed an the
99 * platform's exit() function is called.
100 */
101int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen)
102{
103 int len;
104
105 if (state->s.workspace) {
106 /* gunzipping */
107 int r;
108
109 state->s.next_out = dst;
110 state->s.avail_out = dstlen;
111 r = zlib_inflate(&state->s, Z_FULL_FLUSH);
112 if (r != Z_OK && r != Z_STREAM_END)
113 fatal("inflate returned %d msg: %s\n\r", r, state->s.msg);
114 len = state->s.next_out - (unsigned char *)dst;
115 } else {
116 /* uncompressed image */
117 len = min(state->s.avail_in, (unsigned)dstlen);
118 memcpy(dst, state->s.next_in, len);
119 state->s.next_in += len;
120 state->s.avail_in -= len;
121 }
122 return len;
123}
124
125/**
126 * gunzip_exactly - extract a fixed number of bytes from a gzip data stream
127 * @state: gzip state structure previously initialized by gunzip_start()
128 * @dst: buffer to store extracted data
129 * @dstlen: number of bytes to extract
130 *
131 * This function extracts exactly @dstlen bytes from the data stream
132 * previously associated with @state by gunzip_start(), decompressing
133 * if necessary.
134 *
135 * If there are less @dstlen bytes available in the data stream, or if
136 * any other errors occur, such as a corrupted compressed stream, an
137 * error is printed an the platform's exit() function is called.
138 */
139void gunzip_exactly(struct gunzip_state *state, void *dst, int dstlen)
140{
141 int len;
142
143 len = gunzip_partial(state, dst, dstlen);
144 if (len < dstlen)
145 fatal("\n\rgunzip_exactly: ran out of data!"
146 " Wanted %d, got %d.\n\r", dstlen, len);
147}
148
149/**
150 * gunzip_discard - discard bytes from a gzip data stream
151 * @state: gzip state structure previously initialized by gunzip_start()
152 * @len: number of bytes to discard
153 *
154 * This function extracts, then discards exactly @len bytes from the
155 * data stream previously associated with @state by gunzip_start().
156 * Subsequent gunzip_partial(), gunzip_exactly() or gunzip_finish()
157 * calls will extract the data following the discarded bytes in the
158 * data stream.
159 *
160 * If there are less @len bytes available in the data stream, or if
161 * any other errors occur, such as a corrupted compressed stream, an
162 * error is printed an the platform's exit() function is called.
163 */
164void gunzip_discard(struct gunzip_state *state, int len)
165{
166 static char discard_buf[128];
167
168 while (len > sizeof(discard_buf)) {
169 gunzip_exactly(state, discard_buf, sizeof(discard_buf));
170 len -= sizeof(discard_buf);
171 }
172
173 if (len > 0)
174 gunzip_exactly(state, discard_buf, len);
175}
176
177/**
178 * gunzip_finish - extract all remaining bytes from a gzip data stream
179 * @state: gzip state structure previously initialized by gunzip_start()
180 * @dst: buffer to store extracted data
181 * @dstlen: maximum number of bytes to extract
182 *
183 * This function extracts all remaining data, or at most @dstlen
184 * bytes, from the stream previously associated with @state by
185 * gunzip_start(). zlib is then shut down, so it is an error to use
186 * any of the functions in this file on @state until it is
187 * re-initialized with another call to gunzip_start().
188 *
189 * If any errors occur, such as a corrupted compressed stream, an
190 * error is printed an the platform's exit() function is called.
191 */
192int gunzip_finish(struct gunzip_state *state, void *dst, int dstlen)
193{
194 int len;
195
196 if (state->s.workspace) {
197 len = gunzip_partial(state, dst, dstlen);
198 zlib_inflateEnd(&state->s);
199 } else {
200 /* uncompressed image */
201 len = min(state->s.avail_in, (unsigned)dstlen);
202 memcpy(dst, state->s.next_in, len);
203 }
204
205 return len;
206}
diff --git a/arch/powerpc/boot/gunzip_util.h b/arch/powerpc/boot/gunzip_util.h
new file mode 100644
index 000000000000..b3dfa6e87b3a
--- /dev/null
+++ b/arch/powerpc/boot/gunzip_util.h
@@ -0,0 +1,45 @@
1/*
2 * Decompression convenience functions
3 *
4 * Copyright 2007 David Gibson, IBM Corporation.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10#ifndef _PPC_BOOT_GUNZIP_UTIL_H_
11#define _PPC_BOOT_GUNZIP_UTIL_H_
12
13#include "zlib.h"
14
15/*
16 * These functions are designed to make life easy for decompressing
17 * kernel images, initrd images or any other gzip compressed image,
18 * particularly if its useful to decompress part of the image (e.g. to
19 * examine headers) before decompressing the remainder.
20 *
21 * To use:
22 * - declare a gunzip_state structure
23 * - use gunzip_start() to initialize the state, associating it
24 * with a stream of compressed data
25 * - use gunzip_partial(), gunzip_exactly() and gunzip_discard()
26 * in any combination to extract pieces of data from the stream
27 * - Finally use gunzip_finish() to extract the tail of the
28 * compressed stream and wind up zlib
29 */
30
31/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
32#define GUNZIP_SCRATCH_SIZE 46912
33
34struct gunzip_state {
35 z_stream s;
36 char scratch[46912];
37};
38
39void gunzip_start(struct gunzip_state *state, void *src, int srclen);
40int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen);
41void gunzip_exactly(struct gunzip_state *state, void *dst, int len);
42void gunzip_discard(struct gunzip_state *state, int len);
43int gunzip_finish(struct gunzip_state *state, void *dst, int len);
44
45#endif /* _PPC_BOOT_GUNZIP_UTIL_H_ */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 6f6b50d238b6..56b56a8d4b23 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -14,11 +14,10 @@
14#include "page.h" 14#include "page.h"
15#include "string.h" 15#include "string.h"
16#include "stdio.h" 16#include "stdio.h"
17#include "zlib.h"
18#include "ops.h" 17#include "ops.h"
18#include "gunzip_util.h"
19#include "flatdevtree.h" 19#include "flatdevtree.h"
20 20#include "reg.h"
21extern void flush_cache(void *, unsigned long);
22 21
23extern char _start[]; 22extern char _start[];
24extern char __bss_start[]; 23extern char __bss_start[];
@@ -30,304 +29,173 @@ extern char _initrd_end[];
30extern char _dtb_start[]; 29extern char _dtb_start[];
31extern char _dtb_end[]; 30extern char _dtb_end[];
32 31
32static struct gunzip_state gzstate;
33
33struct addr_range { 34struct addr_range {
34 unsigned long addr; 35 void *addr;
35 unsigned long size; 36 unsigned long size;
36 unsigned long memsize;
37}; 37};
38static struct addr_range vmlinux;
39static struct addr_range vmlinuz;
40static struct addr_range initrd;
41
42static unsigned long elfoffset;
43static int is_64bit;
44
45/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
46static char scratch[46912];
47static char elfheader[256];
48 38
49typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); 39typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
50 40
51#undef DEBUG 41#undef DEBUG
52 42
53#define HEAD_CRC 2 43static struct addr_range prep_kernel(void)
54#define EXTRA_FIELD 4
55#define ORIG_NAME 8
56#define COMMENT 0x10
57#define RESERVED 0xe0
58
59static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
60{ 44{
61 z_stream s; 45 char elfheader[256];
62 int r, i, flags; 46 void *vmlinuz_addr = _vmlinux_start;
63 47 unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
64 /* skip header */ 48 void *addr = 0;
65 i = 10; 49 struct elf_info ei;
66 flags = src[3]; 50 int len;
67 if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
68 printf("bad gzipped data\n\r");
69 exit();
70 }
71 if ((flags & EXTRA_FIELD) != 0)
72 i = 12 + src[10] + (src[11] << 8);
73 if ((flags & ORIG_NAME) != 0)
74 while (src[i++] != 0)
75 ;
76 if ((flags & COMMENT) != 0)
77 while (src[i++] != 0)
78 ;
79 if ((flags & HEAD_CRC) != 0)
80 i += 2;
81 if (i >= *lenp) {
82 printf("gunzip: ran out of data in header\n\r");
83 exit();
84 }
85 51
86 if (zlib_inflate_workspacesize() > sizeof(scratch)) { 52 /* gunzip the ELF header of the kernel */
87 printf("gunzip needs more mem\n"); 53 gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
88 exit(); 54 gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
89 } 55
90 memset(&s, 0, sizeof(s)); 56 if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
91 s.workspace = scratch; 57 fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
92 r = zlib_inflateInit2(&s, -MAX_WBITS); 58
93 if (r != Z_OK) { 59 if (platform_ops.image_hdr)
94 printf("inflateInit2 returned %d\n\r", r); 60 platform_ops.image_hdr(elfheader);
95 exit(); 61
96 } 62 /* We need to alloc the memsize: gzip will expand the kernel
97 s.next_in = src + i; 63 * text/data, then possible rubbish we don't care about. But
98 s.avail_in = *lenp - i; 64 * the kernel bss must be claimed (it will be zero'd by the
99 s.next_out = dst; 65 * kernel itself)
100 s.avail_out = dstlen; 66 */
101 r = zlib_inflate(&s, Z_FULL_FLUSH); 67 printf("Allocating 0x%lx bytes for kernel ...\n\r", ei.memsize);
102 if (r != Z_OK && r != Z_STREAM_END) { 68
103 printf("inflate returned %d msg: %s\n\r", r, s.msg); 69 if (platform_ops.vmlinux_alloc) {
104 exit(); 70 addr = platform_ops.vmlinux_alloc(ei.memsize);
71 } else {
72 if ((unsigned long)_start < ei.memsize)
73 fatal("Insufficient memory for kernel at address 0!"
74 " (_start=%p)\n\r", _start);
105 } 75 }
106 *lenp = s.next_out - (unsigned char *) dst;
107 zlib_inflateEnd(&s);
108}
109 76
110static int is_elf64(void *hdr) 77 /* Finally, gunzip the kernel */
111{ 78 printf("gunzipping (0x%p <- 0x%p:0x%p)...", addr,
112 Elf64_Ehdr *elf64 = hdr; 79 vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
113 Elf64_Phdr *elf64ph; 80 /* discard up to the actual load data */
114 unsigned int i; 81 gunzip_discard(&gzstate, ei.elfoffset - sizeof(elfheader));
115 82 len = gunzip_finish(&gzstate, addr, ei.loadsize);
116 if (!(elf64->e_ident[EI_MAG0] == ELFMAG0 && 83 if (len != ei.loadsize)
117 elf64->e_ident[EI_MAG1] == ELFMAG1 && 84 fatal("ran out of data! only got 0x%x of 0x%lx bytes.\n\r",
118 elf64->e_ident[EI_MAG2] == ELFMAG2 && 85 len, ei.loadsize);
119 elf64->e_ident[EI_MAG3] == ELFMAG3 && 86 printf("done 0x%x bytes\n\r", len);
120 elf64->e_ident[EI_CLASS] == ELFCLASS64 &&
121 elf64->e_ident[EI_DATA] == ELFDATA2MSB &&
122 elf64->e_type == ET_EXEC &&
123 elf64->e_machine == EM_PPC64))
124 return 0;
125
126 elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
127 (unsigned long)elf64->e_phoff);
128 for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++)
129 if (elf64ph->p_type == PT_LOAD)
130 break;
131 if (i >= (unsigned int)elf64->e_phnum)
132 return 0;
133
134 elfoffset = (unsigned long)elf64ph->p_offset;
135 vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
136 vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
137
138 is_64bit = 1;
139 return 1;
140}
141 87
142static int is_elf32(void *hdr) 88 flush_cache(addr, ei.loadsize);
143{ 89
144 Elf32_Ehdr *elf32 = hdr; 90 return (struct addr_range){addr, ei.memsize};
145 Elf32_Phdr *elf32ph;
146 unsigned int i;
147
148 if (!(elf32->e_ident[EI_MAG0] == ELFMAG0 &&
149 elf32->e_ident[EI_MAG1] == ELFMAG1 &&
150 elf32->e_ident[EI_MAG2] == ELFMAG2 &&
151 elf32->e_ident[EI_MAG3] == ELFMAG3 &&
152 elf32->e_ident[EI_CLASS] == ELFCLASS32 &&
153 elf32->e_ident[EI_DATA] == ELFDATA2MSB &&
154 elf32->e_type == ET_EXEC &&
155 elf32->e_machine == EM_PPC))
156 return 0;
157
158 elf32 = (Elf32_Ehdr *)elfheader;
159 elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff);
160 for (i = 0; i < elf32->e_phnum; i++, elf32ph++)
161 if (elf32ph->p_type == PT_LOAD)
162 break;
163 if (i >= elf32->e_phnum)
164 return 0;
165
166 elfoffset = elf32ph->p_offset;
167 vmlinux.size = elf32ph->p_filesz + elf32ph->p_offset;
168 vmlinux.memsize = elf32ph->p_memsz + elf32ph->p_offset;
169 return 1;
170} 91}
171 92
172static void prep_kernel(unsigned long a1, unsigned long a2) 93static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
94 unsigned long initrd_addr,
95 unsigned long initrd_size)
173{ 96{
174 int len; 97 /* If we have an image attached to us, it overrides anything
175 98 * supplied by the loader. */
176 vmlinuz.addr = (unsigned long)_vmlinux_start; 99 if (_initrd_end > _initrd_start) {
177 vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); 100 printf("Attached initrd image at 0x%p-0x%p\n\r",
178 101 _initrd_start, _initrd_end);
179 /* gunzip the ELF header of the kernel */ 102 initrd_addr = (unsigned long)_initrd_start;
180 if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { 103 initrd_size = _initrd_end - _initrd_start;
181 len = vmlinuz.size; 104 } else if (initrd_size > 0) {
182 gunzip(elfheader, sizeof(elfheader), 105 printf("Using loader supplied ramdisk at 0x%lx-0x%lx\n\r",
183 (unsigned char *)vmlinuz.addr, &len); 106 initrd_addr, initrd_addr + initrd_size);
184 } else
185 memcpy(elfheader, (const void *)vmlinuz.addr,
186 sizeof(elfheader));
187
188 if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
189 printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
190 exit();
191 } 107 }
192 if (platform_ops.image_hdr)
193 platform_ops.image_hdr(elfheader);
194 108
195 /* We need to alloc the memsize plus the file offset since gzip 109 /* If there's no initrd at all, we're done */
196 * will expand the header (file offset), then the kernel, then 110 if (! initrd_size)
197 * possible rubbish we don't care about. But the kernel bss must 111 return (struct addr_range){0, 0};
198 * be claimed (it will be zero'd by the kernel itself)
199 */
200 printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
201 vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
202 if (vmlinux.addr == 0) {
203 printf("Can't allocate memory for kernel image !\n\r");
204 exit();
205 }
206 112
207 /* 113 /*
208 * Now find the initrd 114 * If the initrd is too low it will be clobbered when the
209 * 115 * kernel relocates to its final location. In this case,
210 * First see if we have an image attached to us. If so 116 * allocate a safer place and move it.
211 * allocate memory for it and copy it there.
212 */ 117 */
213 initrd.size = (unsigned long)(_initrd_end - _initrd_start); 118 if (initrd_addr < vmlinux.size) {
214 initrd.memsize = initrd.size; 119 void *old_addr = (void *)initrd_addr;
215 if (initrd.size > 0) { 120
216 printf("Allocating 0x%lx bytes for initrd ...\n\r", 121 printf("Allocating 0x%lx bytes for initrd ...\n\r",
217 initrd.size); 122 initrd_size);
218 initrd.addr = (unsigned long)malloc((u32)initrd.size); 123 initrd_addr = (unsigned long)malloc(initrd_size);
219 if (initrd.addr == 0) { 124 if (! initrd_addr)
220 printf("Can't allocate memory for initial " 125 fatal("Can't allocate memory for initial "
221 "ramdisk !\n\r"); 126 "ramdisk !\n\r");
222 exit(); 127 printf("Relocating initrd 0x%lx <- 0x%p (0x%lx bytes)\n\r",
223 } 128 initrd_addr, old_addr, initrd_size);
224 printf("initial ramdisk moving 0x%lx <- 0x%lx " 129 memmove((void *)initrd_addr, old_addr, initrd_size);
225 "(0x%lx bytes)\n\r", initrd.addr,
226 (unsigned long)_initrd_start, initrd.size);
227 memmove((void *)initrd.addr, (void *)_initrd_start,
228 initrd.size);
229 printf("initrd head: 0x%lx\n\r",
230 *((unsigned long *)initrd.addr));
231 } else if (a2 != 0) {
232 /* Otherwise, see if yaboot or another loader gave us an initrd */
233 initrd.addr = a1;
234 initrd.memsize = initrd.size = a2;
235 printf("Using loader supplied initrd at 0x%lx (0x%lx bytes)\n\r",
236 initrd.addr, initrd.size);
237 } 130 }
238 131
239 /* Eventually gunzip the kernel */ 132 printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd_addr));
240 if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
241 printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
242 vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
243 len = vmlinuz.size;
244 gunzip((void *)vmlinux.addr, vmlinux.memsize,
245 (unsigned char *)vmlinuz.addr, &len);
246 printf("done 0x%lx bytes\n\r", len);
247 } else {
248 memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,
249 vmlinuz.size);
250 }
251 133
252 /* Skip over the ELF header */ 134 /* Tell the kernel initrd address via device tree */
253#ifdef DEBUG 135 setprop_val(chosen, "linux,initrd-start", (u32)(initrd_addr));
254 printf("... skipping 0x%lx bytes of ELF header\n\r", 136 setprop_val(chosen, "linux,initrd-end", (u32)(initrd_addr+initrd_size));
255 elfoffset);
256#endif
257 vmlinux.addr += elfoffset;
258 137
259 flush_cache((void *)vmlinux.addr, vmlinux.size); 138 return (struct addr_range){(void *)initrd_addr, initrd_size};
260} 139}
261 140
262/* A buffer that may be edited by tools operating on a zImage binary so as to 141/* A buffer that may be edited by tools operating on a zImage binary so as to
263 * edit the command line passed to vmlinux (by setting /chosen/bootargs). 142 * edit the command line passed to vmlinux (by setting /chosen/bootargs).
264 * The buffer is put in it's own section so that tools may locate it easier. 143 * The buffer is put in it's own section so that tools may locate it easier.
265 */ 144 */
266static char builtin_cmdline[COMMAND_LINE_SIZE] 145static char cmdline[COMMAND_LINE_SIZE]
267 __attribute__((__section__("__builtin_cmdline"))); 146 __attribute__((__section__("__builtin_cmdline")));
268 147
269static void get_cmdline(char *buf, int size) 148static void prep_cmdline(void *chosen)
270{ 149{
271 void *devp; 150 if (cmdline[0] == '\0')
272 int len = strlen(builtin_cmdline); 151 getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
273
274 buf[0] = '\0';
275
276 if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
277 len = min(len, size-1);
278 strncpy(buf, builtin_cmdline, len);
279 buf[len] = '\0';
280 }
281 else if ((devp = finddevice("/chosen")))
282 getprop(devp, "bootargs", buf, size);
283}
284 152
285static void set_cmdline(char *buf) 153 printf("\n\rLinux/PowerPC load: %s", cmdline);
286{ 154 /* If possible, edit the command line */
287 void *devp; 155 if (console_ops.edit_cmdline)
156 console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
157 printf("\n\r");
288 158
289 if ((devp = finddevice("/chosen"))) 159 /* Put the command line back into the devtree for the kernel */
290 setprop(devp, "bootargs", buf, strlen(buf) + 1); 160 setprop_str(chosen, "bootargs", cmdline);
291} 161}
292 162
293struct platform_ops platform_ops; 163struct platform_ops platform_ops;
294struct dt_ops dt_ops; 164struct dt_ops dt_ops;
295struct console_ops console_ops; 165struct console_ops console_ops;
166struct loader_info loader_info;
296 167
297void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) 168void start(void)
298{ 169{
170 struct addr_range vmlinux, initrd;
299 kernel_entry_t kentry; 171 kernel_entry_t kentry;
300 char cmdline[COMMAND_LINE_SIZE];
301 unsigned long ft_addr = 0; 172 unsigned long ft_addr = 0;
173 void *chosen;
302 174
303 memset(__bss_start, 0, _end - __bss_start); 175 /* Do this first, because malloc() could clobber the loader's
304 memset(&platform_ops, 0, sizeof(platform_ops)); 176 * command line. Only use the loader command line if a
305 memset(&dt_ops, 0, sizeof(dt_ops)); 177 * built-in command line wasn't set by an external tool */
306 memset(&console_ops, 0, sizeof(console_ops)); 178 if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
179 memmove(cmdline, loader_info.cmdline,
180 min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1));
307 181
308 if (platform_init(promptr, _dtb_start, _dtb_end))
309 exit();
310 if (console_ops.open && (console_ops.open() < 0)) 182 if (console_ops.open && (console_ops.open() < 0))
311 exit(); 183 exit();
312 if (platform_ops.fixups) 184 if (platform_ops.fixups)
313 platform_ops.fixups(); 185 platform_ops.fixups();
314 186
315 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", 187 printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
316 _start, sp); 188 _start, get_sp());
317 189
318 prep_kernel(a1, a2); 190 /* Ensure that the device tree has a /chosen node */
191 chosen = finddevice("/chosen");
192 if (!chosen)
193 chosen = create_node(NULL, "chosen");
319 194
320 /* If cmdline came from zimage wrapper or if we can edit the one 195 vmlinux = prep_kernel();
321 * in the dt, print it out and edit it, if possible. 196 initrd = prep_initrd(vmlinux, chosen,
322 */ 197 loader_info.initrd_addr, loader_info.initrd_size);
323 if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) { 198 prep_cmdline(chosen);
324 get_cmdline(cmdline, COMMAND_LINE_SIZE);
325 printf("\n\rLinux/PowerPC load: %s", cmdline);
326 if (console_ops.edit_cmdline)
327 console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
328 printf("\n\r");
329 set_cmdline(cmdline);
330 }
331 199
332 printf("Finalizing device tree..."); 200 printf("Finalizing device tree...");
333 if (dt_ops.finalize) 201 if (dt_ops.finalize)
@@ -335,7 +203,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
335 if (ft_addr) 203 if (ft_addr)
336 printf(" flat tree at 0x%lx\n\r", ft_addr); 204 printf(" flat tree at 0x%lx\n\r", ft_addr);
337 else 205 else
338 printf(" using OF tree (promptr=%p)\n\r", promptr); 206 printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr);
339 207
340 if (console_ops.close) 208 if (console_ops.close)
341 console_ops.close(); 209 console_ops.close();
@@ -344,10 +212,9 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
344 if (ft_addr) 212 if (ft_addr)
345 kentry(ft_addr, 0, NULL); 213 kentry(ft_addr, 0, NULL);
346 else 214 else
347 /* XXX initrd addr/size should be passed in properties */ 215 kentry((unsigned long)initrd.addr, initrd.size,
348 kentry(initrd.addr, initrd.size, promptr); 216 loader_info.promptr);
349 217
350 /* console closed so printf below may not work */ 218 /* console closed so printf in fatal below may not work */
351 printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); 219 fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r");
352 exit();
353} 220}
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
index 1ffe72e35cdc..f8f1b2f31412 100644
--- a/arch/powerpc/boot/ns16550.c
+++ b/arch/powerpc/boot/ns16550.c
@@ -55,10 +55,15 @@ static u8 ns16550_tstc(void)
55int ns16550_console_init(void *devp, struct serial_console_data *scdp) 55int ns16550_console_init(void *devp, struct serial_console_data *scdp)
56{ 56{
57 int n; 57 int n;
58 unsigned long reg_phys;
58 59
59 n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base)); 60 n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
60 if (n != sizeof(reg_base)) 61 if (n != sizeof(reg_base)) {
61 return -1; 62 if (!dt_xlate_reg(devp, 0, &reg_phys, NULL))
63 return -1;
64
65 reg_base = (void *)reg_phys;
66 }
62 67
63 n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift)); 68 n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
64 if (n != sizeof(reg_shift)) 69 if (n != sizeof(reg_shift))
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index 0182f384f3e6..d16ee3e3f868 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -173,7 +173,7 @@ static void *claim(unsigned long virt, unsigned long size, unsigned long align)
173 return (void *) virt; 173 return (void *) virt;
174} 174}
175 175
176static void *of_try_claim(u32 size) 176static void *of_try_claim(unsigned long size)
177{ 177{
178 unsigned long addr = 0; 178 unsigned long addr = 0;
179 179
@@ -208,6 +208,16 @@ static void of_image_hdr(const void *hdr)
208 } 208 }
209} 209}
210 210
211static void *of_vmlinux_alloc(unsigned long size)
212{
213 void *p = malloc(size);
214
215 if (!p)
216 fatal("Can't allocate memory for kernel image!\n\r");
217
218 return p;
219}
220
211static void of_exit(void) 221static void of_exit(void)
212{ 222{
213 call_prom("exit", 0, 0); 223 call_prom("exit", 0, 0);
@@ -256,11 +266,12 @@ static void of_console_write(char *buf, int len)
256 call_prom("write", 3, 1, of_stdout_handle, buf, len); 266 call_prom("write", 3, 1, of_stdout_handle, buf, len);
257} 267}
258 268
259int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) 269void platform_init(unsigned long a1, unsigned long a2, void *promptr)
260{ 270{
261 platform_ops.image_hdr = of_image_hdr; 271 platform_ops.image_hdr = of_image_hdr;
262 platform_ops.malloc = of_try_claim; 272 platform_ops.malloc = of_try_claim;
263 platform_ops.exit = of_exit; 273 platform_ops.exit = of_exit;
274 platform_ops.vmlinux_alloc = of_vmlinux_alloc;
264 275
265 dt_ops.finddevice = of_finddevice; 276 dt_ops.finddevice = of_finddevice;
266 dt_ops.getprop = of_getprop; 277 dt_ops.getprop = of_getprop;
@@ -270,5 +281,9 @@ int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
270 console_ops.write = of_console_write; 281 console_ops.write = of_console_write;
271 282
272 prom = (int (*)(void *))promptr; 283 prom = (int (*)(void *))promptr;
273 return 0; 284 loader_info.promptr = promptr;
285 if (a1 && a2 && a2 != 0xdeadbeef) {
286 loader_info.initrd_addr = a1;
287 loader_info.initrd_size = a2;
288 }
274} 289}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 8abb6516bb7c..73bd47a3a079 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -11,7 +11,9 @@
11#ifndef _PPC_BOOT_OPS_H_ 11#ifndef _PPC_BOOT_OPS_H_
12#define _PPC_BOOT_OPS_H_ 12#define _PPC_BOOT_OPS_H_
13 13
14#include <stddef.h>
14#include "types.h" 15#include "types.h"
16#include "string.h"
15 17
16#define COMMAND_LINE_SIZE 512 18#define COMMAND_LINE_SIZE 512
17#define MAX_PATH_LEN 256 19#define MAX_PATH_LEN 256
@@ -21,10 +23,11 @@
21struct platform_ops { 23struct platform_ops {
22 void (*fixups)(void); 24 void (*fixups)(void);
23 void (*image_hdr)(const void *); 25 void (*image_hdr)(const void *);
24 void * (*malloc)(u32 size); 26 void * (*malloc)(unsigned long size);
25 void (*free)(void *ptr); 27 void (*free)(void *ptr);
26 void * (*realloc)(void *ptr, unsigned long size); 28 void * (*realloc)(void *ptr, unsigned long size);
27 void (*exit)(void); 29 void (*exit)(void);
30 void * (*vmlinux_alloc)(unsigned long size);
28}; 31};
29extern struct platform_ops platform_ops; 32extern struct platform_ops platform_ops;
30 33
@@ -35,6 +38,12 @@ struct dt_ops {
35 const int buflen); 38 const int buflen);
36 int (*setprop)(const void *phandle, const char *name, 39 int (*setprop)(const void *phandle, const char *name,
37 const void *buf, const int buflen); 40 const void *buf, const int buflen);
41 void *(*get_parent)(const void *phandle);
42 /* The node must not already exist. */
43 void *(*create_node)(const void *parent, const char *name);
44 void *(*find_node_by_prop_value)(const void *prev,
45 const char *propname,
46 const char *propval, int proplen);
38 unsigned long (*finalize)(void); 47 unsigned long (*finalize)(void);
39}; 48};
40extern struct dt_ops dt_ops; 49extern struct dt_ops dt_ops;
@@ -58,13 +67,23 @@ struct serial_console_data {
58 void (*close)(void); 67 void (*close)(void);
59}; 68};
60 69
61int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); 70struct loader_info {
71 void *promptr;
72 unsigned long initrd_addr, initrd_size;
73 char *cmdline;
74 int cmdline_len;
75};
76extern struct loader_info loader_info;
77
78void start(void);
62int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); 79int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
63int serial_console_init(void); 80int serial_console_init(void);
64int ns16550_console_init(void *devp, struct serial_console_data *scdp); 81int ns16550_console_init(void *devp, struct serial_console_data *scdp);
65void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, 82void *simple_alloc_init(char *base, unsigned long heap_size,
66 u32 max_allocs); 83 unsigned long granularity, unsigned long max_allocs);
67 84extern void flush_cache(void *, unsigned long);
85int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
86int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
68 87
69static inline void *finddevice(const char *name) 88static inline void *finddevice(const char *name)
70{ 89{
@@ -76,12 +95,76 @@ static inline int getprop(void *devp, const char *name, void *buf, int buflen)
76 return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1; 95 return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1;
77} 96}
78 97
79static inline int setprop(void *devp, const char *name, void *buf, int buflen) 98static inline int setprop(void *devp, const char *name,
99 const void *buf, int buflen)
80{ 100{
81 return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1; 101 return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1;
82} 102}
103#define setprop_val(devp, name, val) \
104 do { \
105 typeof(val) x = (val); \
106 setprop((devp), (name), &x, sizeof(x)); \
107 } while (0)
108
109static inline int setprop_str(void *devp, const char *name, const char *buf)
110{
111 if (dt_ops.setprop)
112 return dt_ops.setprop(devp, name, buf, strlen(buf) + 1);
113
114 return -1;
115}
116
117static inline void *get_parent(const char *devp)
118{
119 return dt_ops.get_parent ? dt_ops.get_parent(devp) : NULL;
120}
121
122static inline void *create_node(const void *parent, const char *name)
123{
124 return dt_ops.create_node ? dt_ops.create_node(parent, name) : NULL;
125}
126
83 127
84static inline void *malloc(u32 size) 128static inline void *find_node_by_prop_value(const void *prev,
129 const char *propname,
130 const char *propval, int proplen)
131{
132 if (dt_ops.find_node_by_prop_value)
133 return dt_ops.find_node_by_prop_value(prev, propname,
134 propval, proplen);
135
136 return NULL;
137}
138
139static inline void *find_node_by_prop_value_str(const void *prev,
140 const char *propname,
141 const char *propval)
142{
143 return find_node_by_prop_value(prev, propname, propval,
144 strlen(propval) + 1);
145}
146
147static inline void *find_node_by_devtype(const void *prev,
148 const char *type)
149{
150 return find_node_by_prop_value_str(prev, "device_type", type);
151}
152
153void dt_fixup_memory(u64 start, u64 size);
154void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq);
155void dt_fixup_clock(const char *path, u32 freq);
156void __dt_fixup_mac_addresses(u32 startindex, ...);
157#define dt_fixup_mac_addresses(...) \
158 __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
159
160
161static inline void *find_node_by_linuxphandle(const u32 linuxphandle)
162{
163 return find_node_by_prop_value(NULL, "linux,phandle",
164 (char *)&linuxphandle, sizeof(u32));
165}
166
167static inline void *malloc(unsigned long size)
85{ 168{
86 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; 169 return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
87} 170}
@@ -98,5 +181,11 @@ static inline void exit(void)
98 platform_ops.exit(); 181 platform_ops.exit();
99 for(;;); 182 for(;;);
100} 183}
184#define fatal(args...) { printf(args); exit(); }
185
186
187#define BSS_STACK(size) \
188 static char _bss_stack[size]; \
189 void *_platform_stack_top = _bss_stack + sizeof(_bss_stack);
101 190
102#endif /* _PPC_BOOT_OPS_H_ */ 191#endif /* _PPC_BOOT_OPS_H_ */
diff --git a/arch/powerpc/boot/ppcboot.h b/arch/powerpc/boot/ppcboot.h
new file mode 100644
index 000000000000..5290ff2c2b2b
--- /dev/null
+++ b/arch/powerpc/boot/ppcboot.h
@@ -0,0 +1,108 @@
1/*
2 * This interface is used for compatibility with old U-boots *ONLY*.
3 * Please do not imitate or extend this.
4 */
5
6/*
7 * (C) Copyright 2000, 2001
8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#ifndef __PPCBOOT_H__
27#define __PPCBOOT_H__
28
29/*
30 * Board information passed to kernel from PPCBoot
31 *
32 * include/asm-ppc/ppcboot.h
33 */
34
35#include "types.h"
36
37typedef struct bd_info {
38 unsigned long bi_memstart; /* start of DRAM memory */
39 unsigned long bi_memsize; /* size of DRAM memory in bytes */
40 unsigned long bi_flashstart; /* start of FLASH memory */
41 unsigned long bi_flashsize; /* size of FLASH memory */
42 unsigned long bi_flashoffset; /* reserved area for startup monitor */
43 unsigned long bi_sramstart; /* start of SRAM memory */
44 unsigned long bi_sramsize; /* size of SRAM memory */
45#if defined(TARGET_8xx) || defined(TARGET_CPM2) || defined(TARGET_85xx) ||\
46 defined(TARGET_83xx)
47 unsigned long bi_immr_base; /* base of IMMR register */
48#endif
49#if defined(TARGET_PPC_MPC52xx)
50 unsigned long bi_mbar_base; /* base of internal registers */
51#endif
52 unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */
53 unsigned long bi_ip_addr; /* IP Address */
54 unsigned char bi_enetaddr[6]; /* Ethernet address */
55 unsigned short bi_ethspeed; /* Ethernet speed in Mbps */
56 unsigned long bi_intfreq; /* Internal Freq, in MHz */
57 unsigned long bi_busfreq; /* Bus Freq, in MHz */
58#if defined(TARGET_CPM2)
59 unsigned long bi_cpmfreq; /* CPM_CLK Freq, in MHz */
60 unsigned long bi_brgfreq; /* BRG_CLK Freq, in MHz */
61 unsigned long bi_sccfreq; /* SCC_CLK Freq, in MHz */
62 unsigned long bi_vco; /* VCO Out from PLL, in MHz */
63#endif
64#if defined(TARGET_PPC_MPC52xx)
65 unsigned long bi_ipbfreq; /* IPB Bus Freq, in MHz */
66 unsigned long bi_pcifreq; /* PCI Bus Freq, in MHz */
67#endif
68 unsigned long bi_baudrate; /* Console Baudrate */
69#if defined(TARGET_4xx)
70 unsigned char bi_s_version[4]; /* Version of this structure */
71 unsigned char bi_r_version[32]; /* Version of the ROM (IBM) */
72 unsigned int bi_procfreq; /* CPU (Internal) Freq, in Hz */
73 unsigned int bi_plb_busfreq; /* PLB Bus speed, in Hz */
74 unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
75 unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
76#endif
77#if defined(TARGET_HYMOD)
78 hymod_conf_t bi_hymod_conf; /* hymod configuration information */
79#endif
80#if defined(TARGET_EVB64260) || defined(TARGET_405EP) || defined(TARGET_44x) || \
81 defined(TARGET_85xx) || defined(TARGET_83xx)
82 /* second onboard ethernet port */
83 unsigned char bi_enet1addr[6];
84#define HAVE_ENET1ADDR
85#endif
86#if defined(TARGET_EVB64260) || defined(TARGET_440GX) || defined(TARGET_85xx)
87 /* third onboard ethernet ports */
88 unsigned char bi_enet2addr[6];
89#define HAVE_ENET2ADDR
90#endif
91#if defined(TARGET_440GX)
92 /* fourth onboard ethernet ports */
93 unsigned char bi_enet3addr[6];
94#define HAVE_ENET3ADDR
95#endif
96#if defined(TARGET_4xx)
97 unsigned int bi_opbfreq; /* OB clock in Hz */
98 int bi_iic_fast[2]; /* Use fast i2c mode */
99#endif
100#if defined(TARGET_440GX)
101 int bi_phynum[4]; /* phy mapping */
102 int bi_phymode[4]; /* phy mode */
103#endif
104} bd_t;
105
106#define bi_tbfreq bi_intfreq
107
108#endif /* __PPCBOOT_H__ */
diff --git a/arch/powerpc/boot/reg.h b/arch/powerpc/boot/reg.h
new file mode 100644
index 000000000000..d3cd9ee98afb
--- /dev/null
+++ b/arch/powerpc/boot/reg.h
@@ -0,0 +1,22 @@
1#ifndef _PPC_BOOT_REG_H
2#define _PPC_BOOT_REG_H
3/*
4 * Copyright 2007 Davud Gibson, IBM Corporation.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12static inline u32 mfpvr(void)
13{
14 u32 pvr;
15 asm volatile ("mfpvr %0" : "=r"(pvr));
16 return pvr;
17}
18
19register void *__stack_pointer asm("r1");
20#define get_sp() (__stack_pointer)
21
22#endif /* _PPC_BOOT_REG_H */
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
index cfe3a7505ba0..65ec135d0157 100644
--- a/arch/powerpc/boot/simple_alloc.c
+++ b/arch/powerpc/boot/simple_alloc.c
@@ -19,24 +19,24 @@
19#define ENTRY_IN_USE 0x02 19#define ENTRY_IN_USE 0x02
20 20
21static struct alloc_info { 21static struct alloc_info {
22 u32 flags; 22 unsigned long flags;
23 u32 base; 23 unsigned long base;
24 u32 size; 24 unsigned long size;
25} *alloc_tbl; 25} *alloc_tbl;
26 26
27static u32 tbl_entries; 27static unsigned long tbl_entries;
28static u32 alloc_min; 28static unsigned long alloc_min;
29static u32 next_base; 29static unsigned long next_base;
30static u32 space_left; 30static unsigned long space_left;
31 31
32/* 32/*
33 * First time an entry is used, its base and size are set. 33 * First time an entry is used, its base and size are set.
34 * An entry can be freed and re-malloc'd but its base & size don't change. 34 * An entry can be freed and re-malloc'd but its base & size don't change.
35 * Should be smart enough for needs of bootwrapper. 35 * Should be smart enough for needs of bootwrapper.
36 */ 36 */
37static void *simple_malloc(u32 size) 37static void *simple_malloc(unsigned long size)
38{ 38{
39 u32 i; 39 unsigned long i;
40 struct alloc_info *p = alloc_tbl; 40 struct alloc_info *p = alloc_tbl;
41 41
42 if (size == 0) 42 if (size == 0)
@@ -67,13 +67,14 @@ err_out:
67 67
68static struct alloc_info *simple_find_entry(void *ptr) 68static struct alloc_info *simple_find_entry(void *ptr)
69{ 69{
70 u32 i; 70 unsigned long i;
71 struct alloc_info *p = alloc_tbl; 71 struct alloc_info *p = alloc_tbl;
72 72
73 for (i=0; i<tbl_entries; i++,p++) { 73 for (i=0; i<tbl_entries; i++,p++) {
74 if (!(p->flags & ENTRY_BEEN_USED)) 74 if (!(p->flags & ENTRY_BEEN_USED))
75 break; 75 break;
76 if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr)) 76 if ((p->flags & ENTRY_IN_USE) &&
77 (p->base == (unsigned long)ptr))
77 return p; 78 return p;
78 } 79 }
79 return NULL; 80 return NULL;
@@ -122,10 +123,10 @@ static void *simple_realloc(void *ptr, unsigned long size)
122 * Returns addr of first byte after heap so caller can see if it took 123 * Returns addr of first byte after heap so caller can see if it took
123 * too much space. If so, change args & try again. 124 * too much space. If so, change args & try again.
124 */ 125 */
125void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, 126void *simple_alloc_init(char *base, unsigned long heap_size,
126 u32 max_allocs) 127 unsigned long granularity, unsigned long max_allocs)
127{ 128{
128 u32 heap_base, tbl_size; 129 unsigned long heap_base, tbl_size;
129 130
130 heap_size = _ALIGN_UP(heap_size, granularity); 131 heap_size = _ALIGN_UP(heap_size, granularity);
131 alloc_min = granularity; 132 alloc_min = granularity;
@@ -136,7 +137,7 @@ void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
136 alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8); 137 alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
137 memset(alloc_tbl, 0, tbl_size); 138 memset(alloc_tbl, 0, tbl_size);
138 139
139 heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min); 140 heap_base = _ALIGN_UP((unsigned long)alloc_tbl + tbl_size, alloc_min);
140 141
141 next_base = heap_base; 142 next_base = heap_base;
142 space_left = heap_size; 143 space_left = heap_size;
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h
index 73b8a91bfb34..adffc58412d4 100644
--- a/arch/powerpc/boot/stdio.h
+++ b/arch/powerpc/boot/stdio.h
@@ -7,11 +7,12 @@
7#define EINVAL 22 /* Invalid argument */ 7#define EINVAL 22 /* Invalid argument */
8#define ENOSPC 28 /* No space left on device */ 8#define ENOSPC 28 /* No space left on device */
9 9
10extern int printf(const char *fmt, ...); 10extern int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
11 11
12#define fprintf(fmt, args...) printf(args) 12#define fprintf(fmt, args...) printf(args)
13 13
14extern int sprintf(char *buf, const char *fmt, ...); 14extern int sprintf(char *buf, const char *fmt, ...)
15 __attribute__((format(printf, 2, 3)));
15 16
16extern int vsprintf(char *buf, const char *fmt, va_list args); 17extern int vsprintf(char *buf, const char *fmt, va_list args);
17 18
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 024e4d425c59..5cedd901201f 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -29,6 +29,7 @@ initrd=
29dtb= 29dtb=
30dts= 30dts=
31cacheit= 31cacheit=
32gzip=.gz
32 33
33# cross-compilation prefix 34# cross-compilation prefix
34CROSS= 35CROSS=
@@ -42,7 +43,7 @@ tmpdir=.
42usage() { 43usage() {
43 echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2 44 echo 'Usage: wrapper [-o output] [-p platform] [-i initrd]' >&2
44 echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&2 45 echo ' [-d devtree] [-s tree.dts] [-c] [-C cross-prefix]' >&2
45 echo ' [-D datadir] [-W workingdir] [vmlinux]' >&2 46 echo ' [-D datadir] [-W workingdir] [--no-gzip] [vmlinux]' >&2
46 exit 1 47 exit 1
47} 48}
48 49
@@ -91,6 +92,9 @@ while [ "$#" -gt 0 ]; do
91 [ "$#" -gt 0 ] || usage 92 [ "$#" -gt 0 ] || usage
92 tmpdir="$1" 93 tmpdir="$1"
93 ;; 94 ;;
95 --no-gzip)
96 gzip=
97 ;;
94 -?) 98 -?)
95 usage 99 usage
96 ;; 100 ;;
@@ -137,31 +141,44 @@ miboot|uboot)
137 ksection=image 141 ksection=image
138 isection=initrd 142 isection=initrd
139 ;; 143 ;;
144cuboot*)
145 gzip=
146 ;;
140esac 147esac
141 148
142vmz="$tmpdir/`basename \"$kernel\"`.$ext" 149vmz="$tmpdir/`basename \"$kernel\"`.$ext"
143if [ -z "$cacheit" -o ! -f "$vmz.gz" -o "$vmz.gz" -ot "$kernel" ]; then 150if [ -z "$cacheit" -o ! -f "$vmz$gzip" -o "$vmz$gzip" -ot "$kernel" ]; then
144 ${CROSS}objcopy $objflags "$kernel" "$vmz.$$" 151 ${CROSS}objcopy $objflags "$kernel" "$vmz.$$"
145 gzip -f -9 "$vmz.$$" 152
153 if [ -n "$gzip" ]; then
154 gzip -f -9 "$vmz.$$"
155 fi
156
146 if [ -n "$cacheit" ]; then 157 if [ -n "$cacheit" ]; then
147 mv -f "$vmz.$$.gz" "$vmz.gz" 158 mv -f "$vmz.$$$gzip" "$vmz$gzip"
148 else 159 else
149 vmz="$vmz.$$" 160 vmz="$vmz.$$"
150 fi 161 fi
151fi 162fi
152 163
164vmz="$vmz$gzip"
165
153case "$platform" in 166case "$platform" in
154uboot) 167uboot|cuboot*)
155 rm -f "$ofile"
156 version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \ 168 version=`${CROSS}strings "$kernel" | grep '^Linux version [-0-9.]' | \
157 cut -d' ' -f3` 169 cut -d' ' -f3`
158 if [ -n "$version" ]; then 170 if [ -n "$version" ]; then
159 version="-n Linux-$version" 171 version="-n Linux-$version"
160 fi 172 fi
173esac
174
175case "$platform" in
176uboot)
177 rm -f "$ofile"
161 mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \ 178 mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
162 $version -d "$vmz.gz" "$ofile" 179 $version -d "$vmz" "$ofile"
163 if [ -z "$cacheit" ]; then 180 if [ -z "$cacheit" ]; then
164 rm -f $vmz.gz 181 rm -f "$vmz"
165 fi 182 fi
166 exit 0 183 exit 0
167 ;; 184 ;;
@@ -173,9 +190,9 @@ addsec() {
173 --set-section-flags=$3=contents,alloc,load,readonly,data 190 --set-section-flags=$3=contents,alloc,load,readonly,data
174} 191}
175 192
176addsec $tmp "$vmz.gz" $ksection $object/empty.o 193addsec $tmp "$vmz" $ksection $object/empty.o
177if [ -z "$cacheit" ]; then 194if [ -z "$cacheit" ]; then
178 rm -f "$vmz.gz" 195 rm -f "$vmz"
179fi 196fi
180 197
181if [ -n "$initrd" ]; then 198if [ -n "$initrd" ]; then
@@ -191,7 +208,7 @@ fi
191 208
192if [ "$platform" != "miboot" ]; then 209if [ "$platform" != "miboot" ]; then
193 ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \ 210 ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \
194 $object/crt0.o $platformo $tmp $object/wrapper.a 211 $platformo $tmp $object/wrapper.a
195 rm $tmp 212 rm $tmp
196fi 213fi
197 214
@@ -201,7 +218,19 @@ pseries|chrp)
201 $object/addnote "$ofile" 218 $object/addnote "$ofile"
202 ;; 219 ;;
203pmaccoff) 220pmaccoff)
204 ${CROSS}objcopy -O aixcoff-rs6000 --set-start 0x500000 "$ofile" 221 entry=`objdump -f "$ofile" | grep '^start address ' | \
222 cut -d' ' -f3`
223 ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
205 $object/hack-coff "$ofile" 224 $object/hack-coff "$ofile"
206 ;; 225 ;;
226cuboot*)
227 base=`${CROSS}nm "$ofile" | grep ' _start$' | cut -d' ' -f1`
228 entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | \
229 cut -d' ' -f3`
230 mv "$ofile" "$ofile".elf
231 ${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin
232 gzip -f -9 "$ofile".bin
233 mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \
234 $version -d "$ofile".bin.gz "$ofile"
235 ;;
207esac 236esac
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S
index a360905e5428..fe87a90ce7f1 100644
--- a/arch/powerpc/boot/zImage.coff.lds.S
+++ b/arch/powerpc/boot/zImage.coff.lds.S
@@ -1,5 +1,6 @@
1OUTPUT_ARCH(powerpc:common) 1OUTPUT_ARCH(powerpc:common)
2ENTRY(_start) 2ENTRY(_zimage_start_opd)
3EXTERN(_zimage_start_opd)
3SECTIONS 4SECTIONS
4{ 5{
5 . = (5*1024*1024); 6 . = (5*1024*1024);
diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S
index 4be3c6414b04..f6e380fdb388 100644
--- a/arch/powerpc/boot/zImage.lds.S
+++ b/arch/powerpc/boot/zImage.lds.S
@@ -1,5 +1,6 @@
1OUTPUT_ARCH(powerpc:common) 1OUTPUT_ARCH(powerpc:common)
2ENTRY(_zimage_start) 2ENTRY(_zimage_start)
3EXTERN(_zimage_start)
3SECTIONS 4SECTIONS
4{ 5{
5 . = (4*1024*1024); 6 . = (4*1024*1024);