diff options
Diffstat (limited to 'arch/powerpc/boot')
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 | |||
18 | kernel-vmlinux.strip.gz | 18 | kernel-vmlinux.strip.gz |
19 | mktree | 19 | mktree |
20 | uImage | 20 | uImage |
21 | cuImage | ||
22 | cuImage.bin.gz | ||
23 | cuImage.elf | ||
21 | zImage | 24 | zImage |
22 | zImage.chrp | 25 | zImage.chrp |
23 | zImage.coff | 26 | zImage.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 | ||
43 | src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ | 43 | src-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 \ |
45 | src-plat := of.c | 45 | gunzip_util.c elf_util.c $(zlib) devtree.c |
46 | src-boot := crt0.S $(src-wlib) $(src-plat) empty.c | 46 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c |
47 | src-boot := $(src-wlib) $(src-plat) empty.c | ||
47 | 48 | ||
48 | src-boot := $(addprefix $(obj)/, $(src-boot)) | 49 | src-boot := $(addprefix $(obj)/, $(src-boot)) |
49 | obj-boot := $(addsuffix .o, $(basename $(src-boot))) | 50 | obj-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 | ||
77 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ | 78 | clean-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 | ||
80 | quiet_cmd_bootcc = BOOTCC $@ | 81 | quiet_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 | ||
86 | quiet_cmd_bootar = BOOTAR $@ | 87 | quiet_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 | ||
97 | hostprogs-y := addnote addRamDisk hack-coff mktree | 98 | hostprogs-y := addnote addRamDisk hack-coff mktree |
98 | 99 | ||
99 | extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | 100 | targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) |
101 | extra-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 | ||
102 | wrapper :=$(srctree)/$(src)/wrapper | 104 | wrapper :=$(srctree)/$(src)/wrapper |
103 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) | 105 | wrapperbits := $(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)" | |||
113 | endif | 116 | endif |
114 | endif | 117 | endif |
115 | 118 | ||
119 | # args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd | ||
116 | quiet_cmd_wrap = WRAP $@ | 120 | quiet_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) \ |
118 | quiet_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 | ||
161 | image-$(CONFIG_PPC_PSERIES) += zImage.pseries | 124 | image-$(CONFIG_PPC_PSERIES) += zImage.pseries |
162 | image-$(CONFIG_PPC_MAPLE) += zImage.pseries | 125 | image-$(CONFIG_PPC_MAPLE) += zImage.pseries |
@@ -166,7 +129,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries | |||
166 | image-$(CONFIG_PPC_CHRP) += zImage.chrp | 129 | image-$(CONFIG_PPC_CHRP) += zImage.chrp |
167 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp | 130 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp |
168 | image-$(CONFIG_PPC_PMAC) += zImage.pmac | 131 | image-$(CONFIG_PPC_PMAC) += zImage.pmac |
169 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage | 132 | image-$(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) | |||
174 | image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot | 137 | image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot |
175 | endif | 138 | endif |
176 | 139 | ||
140 | initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-)) | ||
177 | initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y)) | 141 | initrd-y := $(patsubst zImage%, zImage.initrd%, $(image-y)) |
142 | initrd-y := $(filter-out $(image-y), $(initrd-y)) | ||
143 | targets += $(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 | |||
165 | cuboot-plat-$(CONFIG_83xx) += 83xx | ||
166 | cuboot-plat-$(CONFIG_85xx) += 85xx | ||
167 | cuboot-plat-y += unknown-platform | ||
168 | |||
169 | dts = $(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 | ||
184 | install: $(CONFIGURE) $(image-y) | 180 | install: $(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 | ||
187 | clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) | 183 | # anything not in $(targets) |
188 | clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) | 184 | clean-files += $(image-) $(initrd-) zImage zImage.initrd \ |
189 | clean-files += $(image-) | 185 | cuImage.elf cuImage.bin.gz |
186 | |||
187 | # clean up files cached by wrapper | ||
188 | clean-kernel := vmlinux.strip vmlinux.bin | ||
189 | clean-kernel += $(addsuffix .gz,$(clean-kernel)) | ||
190 | # If not absolute clean-files are relative to $(obj). | ||
191 | clean-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 */ |
48 | 3: lis r9,_start@ha | 51 | 3: 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 | ||
73 | 5: 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 */ | ||
89 | 6: | ||
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 | |||
19 | static bd_t bd; | ||
20 | extern char _end[]; | ||
21 | extern char _dtb_start[], _dtb_end[]; | ||
22 | |||
23 | static 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 | |||
52 | void 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 | |||
19 | static bd_t bd; | ||
20 | extern char _end[]; | ||
21 | extern char _dtb_start[], _dtb_end[]; | ||
22 | |||
23 | static 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 | |||
53 | void 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 | |||
21 | void 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 | |||
62 | void 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 | |||
79 | void 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 | |||
89 | void __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 | |||
116 | static 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 | |||
124 | static 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 | |||
132 | static 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 | |||
145 | static 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 | */ | ||
161 | static 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 */ | ||
186 | static 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 | */ | ||
210 | static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; | ||
211 | |||
212 | static 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 | |||
291 | int 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 | |||
299 | int 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 | ||
149 | struct elf_info { | ||
150 | unsigned long loadsize; | ||
151 | unsigned long memsize; | ||
152 | unsigned long elfoffset; | ||
153 | }; | ||
154 | int parse_elf64(void *hdr, struct elf_info *info); | ||
155 | int 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 | |||
18 | int 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 | |||
49 | int 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 | ||
32 | static 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 */ |
34 | static void *ft_node_add(struct ft_cxt *cxt, char *node) | 39 | static 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 | ||
591 | void ft_begin_tree(struct ft_cxt *cxt) | 605 | void 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 | ||
596 | void ft_end_tree(struct ft_cxt *cxt) | 610 | void 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 | |||
657 | void *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 | ||
643 | void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) | 670 | void *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 | ||
704 | void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) | 731 | void *__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 | ||
741 | int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | 763 | void *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) { | 773 | static 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 | |||
803 | int 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 | ||
823 | void *__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 | |||
870 | void *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 | |||
776 | int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | 888 | int 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 | ||
852 | void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) | 964 | void *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); | |||
97 | void ft_dump_blob(const void *bphp); | 97 | void ft_dump_blob(const void *bphp); |
98 | void ft_merge_blob(struct ft_cxt *cxt, void *blob); | 98 | void ft_merge_blob(struct ft_cxt *cxt, void *blob); |
99 | void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); | 99 | void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); |
100 | void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, | ||
101 | const char *srch_path); | ||
100 | void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); | 102 | void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); |
101 | int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | 103 | int 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); |
103 | int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | 105 | int 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); |
107 | void *ft_get_parent(struct ft_cxt *cxt, const void *phandle); | ||
108 | void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev, | ||
109 | const char *propname, const char *propval, | ||
110 | int proplen); | ||
111 | void *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 | ||
17 | static struct ft_cxt cxt; | 17 | static struct ft_cxt cxt; |
18 | 18 | ||
19 | static void *ft_finddevice(const char *name) | 19 | static 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 | ||
24 | static int ft_getprop(const void *phandle, const char *propname, void *buf, | 24 | static 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 | ||
30 | static int ft_setprop(const void *phandle, const char *propname, | 30 | static 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 | ||
36 | static unsigned long ft_finalize(void) | 36 | static void *fdtm_get_parent(const void *phandle) |
37 | { | ||
38 | return ft_get_parent(&cxt, phandle); | ||
39 | } | ||
40 | |||
41 | static void *fdtm_create_node(const void *phandle, const char *name) | ||
42 | { | ||
43 | return ft_create_node(&cxt, phandle, name); | ||
44 | } | ||
45 | |||
46 | static 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 | |||
55 | static 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 | ||
42 | int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) | 61 | int 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 | */ | ||
42 | void 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 | */ | ||
101 | int 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 | */ | ||
139 | void 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 | */ | ||
164 | void 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 | */ | ||
192 | int 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 | |||
34 | struct gunzip_state { | ||
35 | z_stream s; | ||
36 | char scratch[46912]; | ||
37 | }; | ||
38 | |||
39 | void gunzip_start(struct gunzip_state *state, void *src, int srclen); | ||
40 | int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen); | ||
41 | void gunzip_exactly(struct gunzip_state *state, void *dst, int len); | ||
42 | void gunzip_discard(struct gunzip_state *state, int len); | ||
43 | int 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" | |
21 | extern void flush_cache(void *, unsigned long); | ||
22 | 21 | ||
23 | extern char _start[]; | 22 | extern char _start[]; |
24 | extern char __bss_start[]; | 23 | extern char __bss_start[]; |
@@ -30,304 +29,173 @@ extern char _initrd_end[]; | |||
30 | extern char _dtb_start[]; | 29 | extern char _dtb_start[]; |
31 | extern char _dtb_end[]; | 30 | extern char _dtb_end[]; |
32 | 31 | ||
32 | static struct gunzip_state gzstate; | ||
33 | |||
33 | struct addr_range { | 34 | struct addr_range { |
34 | unsigned long addr; | 35 | void *addr; |
35 | unsigned long size; | 36 | unsigned long size; |
36 | unsigned long memsize; | ||
37 | }; | 37 | }; |
38 | static struct addr_range vmlinux; | ||
39 | static struct addr_range vmlinuz; | ||
40 | static struct addr_range initrd; | ||
41 | |||
42 | static unsigned long elfoffset; | ||
43 | static int is_64bit; | ||
44 | |||
45 | /* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */ | ||
46 | static char scratch[46912]; | ||
47 | static char elfheader[256]; | ||
48 | 38 | ||
49 | typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); | 39 | typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); |
50 | 40 | ||
51 | #undef DEBUG | 41 | #undef DEBUG |
52 | 42 | ||
53 | #define HEAD_CRC 2 | 43 | static 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 | |||
59 | static 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 | ||
110 | static 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 | ||
142 | static 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 | ||
172 | static void prep_kernel(unsigned long a1, unsigned long a2) | 93 | static 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 | */ |
266 | static char builtin_cmdline[COMMAND_LINE_SIZE] | 145 | static char cmdline[COMMAND_LINE_SIZE] |
267 | __attribute__((__section__("__builtin_cmdline"))); | 146 | __attribute__((__section__("__builtin_cmdline"))); |
268 | 147 | ||
269 | static void get_cmdline(char *buf, int size) | 148 | static 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 | ||
285 | static 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 | ||
293 | struct platform_ops platform_ops; | 163 | struct platform_ops platform_ops; |
294 | struct dt_ops dt_ops; | 164 | struct dt_ops dt_ops; |
295 | struct console_ops console_ops; | 165 | struct console_ops console_ops; |
166 | struct loader_info loader_info; | ||
296 | 167 | ||
297 | void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | 168 | void 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) | |||
55 | int ns16550_console_init(void *devp, struct serial_console_data *scdp) | 55 | int 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", ®_base, sizeof(reg_base)); | 60 | n = getprop(devp, "virtual-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, ®_phys, NULL)) |
63 | return -1; | ||
64 | |||
65 | reg_base = (void *)reg_phys; | ||
66 | } | ||
62 | 67 | ||
63 | n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); | 68 | n = getprop(devp, "reg-shift", ®_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 | ||
176 | static void *of_try_claim(u32 size) | 176 | static 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 | ||
211 | static 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 | |||
211 | static void of_exit(void) | 221 | static 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 | ||
259 | int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) | 269 | void 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 @@ | |||
21 | struct platform_ops { | 23 | struct 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 | }; |
29 | extern struct platform_ops platform_ops; | 32 | extern 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 | }; |
40 | extern struct dt_ops dt_ops; | 49 | extern 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 | ||
61 | int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); | 70 | struct loader_info { |
71 | void *promptr; | ||
72 | unsigned long initrd_addr, initrd_size; | ||
73 | char *cmdline; | ||
74 | int cmdline_len; | ||
75 | }; | ||
76 | extern struct loader_info loader_info; | ||
77 | |||
78 | void start(void); | ||
62 | int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); | 79 | int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); |
63 | int serial_console_init(void); | 80 | int serial_console_init(void); |
64 | int ns16550_console_init(void *devp, struct serial_console_data *scdp); | 81 | int ns16550_console_init(void *devp, struct serial_console_data *scdp); |
65 | void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, | 82 | void *simple_alloc_init(char *base, unsigned long heap_size, |
66 | u32 max_allocs); | 83 | unsigned long granularity, unsigned long max_allocs); |
67 | 84 | extern void flush_cache(void *, unsigned long); | |
85 | int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); | ||
86 | int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); | ||
68 | 87 | ||
69 | static inline void *finddevice(const char *name) | 88 | static 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 | ||
79 | static inline int setprop(void *devp, const char *name, void *buf, int buflen) | 98 | static 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 | |||
109 | static 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 | |||
117 | static inline void *get_parent(const char *devp) | ||
118 | { | ||
119 | return dt_ops.get_parent ? dt_ops.get_parent(devp) : NULL; | ||
120 | } | ||
121 | |||
122 | static 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 | ||
84 | static inline void *malloc(u32 size) | 128 | static 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 | |||
139 | static 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 | |||
147 | static 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 | |||
153 | void dt_fixup_memory(u64 start, u64 size); | ||
154 | void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq); | ||
155 | void dt_fixup_clock(const char *path, u32 freq); | ||
156 | void __dt_fixup_mac_addresses(u32 startindex, ...); | ||
157 | #define dt_fixup_mac_addresses(...) \ | ||
158 | __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) | ||
159 | |||
160 | |||
161 | static 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 | |||
167 | static 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 | |||
37 | typedef 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 | |||
12 | static inline u32 mfpvr(void) | ||
13 | { | ||
14 | u32 pvr; | ||
15 | asm volatile ("mfpvr %0" : "=r"(pvr)); | ||
16 | return pvr; | ||
17 | } | ||
18 | |||
19 | register 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 | ||
21 | static struct alloc_info { | 21 | static 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 | ||
27 | static u32 tbl_entries; | 27 | static unsigned long tbl_entries; |
28 | static u32 alloc_min; | 28 | static unsigned long alloc_min; |
29 | static u32 next_base; | 29 | static unsigned long next_base; |
30 | static u32 space_left; | 30 | static 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 | */ |
37 | static void *simple_malloc(u32 size) | 37 | static 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 | ||
68 | static struct alloc_info *simple_find_entry(void *ptr) | 68 | static 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 | */ |
125 | void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, | 126 | void *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 | ||
10 | extern int printf(const char *fmt, ...); | 10 | extern 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 | ||
14 | extern int sprintf(char *buf, const char *fmt, ...); | 14 | extern int sprintf(char *buf, const char *fmt, ...) |
15 | __attribute__((format(printf, 2, 3))); | ||
15 | 16 | ||
16 | extern int vsprintf(char *buf, const char *fmt, va_list args); | 17 | extern 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= | |||
29 | dtb= | 29 | dtb= |
30 | dts= | 30 | dts= |
31 | cacheit= | 31 | cacheit= |
32 | gzip=.gz | ||
32 | 33 | ||
33 | # cross-compilation prefix | 34 | # cross-compilation prefix |
34 | CROSS= | 35 | CROSS= |
@@ -42,7 +43,7 @@ tmpdir=. | |||
42 | usage() { | 43 | usage() { |
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 | ;; |
144 | cuboot*) | ||
145 | gzip= | ||
146 | ;; | ||
140 | esac | 147 | esac |
141 | 148 | ||
142 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" | 149 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" |
143 | if [ -z "$cacheit" -o ! -f "$vmz.gz" -o "$vmz.gz" -ot "$kernel" ]; then | 150 | if [ -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 |
151 | fi | 162 | fi |
152 | 163 | ||
164 | vmz="$vmz$gzip" | ||
165 | |||
153 | case "$platform" in | 166 | case "$platform" in |
154 | uboot) | 167 | uboot|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 |
173 | esac | ||
174 | |||
175 | case "$platform" in | ||
176 | uboot) | ||
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 | ||
176 | addsec $tmp "$vmz.gz" $ksection $object/empty.o | 193 | addsec $tmp "$vmz" $ksection $object/empty.o |
177 | if [ -z "$cacheit" ]; then | 194 | if [ -z "$cacheit" ]; then |
178 | rm -f "$vmz.gz" | 195 | rm -f "$vmz" |
179 | fi | 196 | fi |
180 | 197 | ||
181 | if [ -n "$initrd" ]; then | 198 | if [ -n "$initrd" ]; then |
@@ -191,7 +208,7 @@ fi | |||
191 | 208 | ||
192 | if [ "$platform" != "miboot" ]; then | 209 | if [ "$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 |
196 | fi | 213 | fi |
197 | 214 | ||
@@ -201,7 +218,19 @@ pseries|chrp) | |||
201 | $object/addnote "$ofile" | 218 | $object/addnote "$ofile" |
202 | ;; | 219 | ;; |
203 | pmaccoff) | 220 | pmaccoff) |
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 | ;; |
226 | cuboot*) | ||
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 | ;; | ||
207 | esac | 236 | esac |
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 @@ | |||
1 | OUTPUT_ARCH(powerpc:common) | 1 | OUTPUT_ARCH(powerpc:common) |
2 | ENTRY(_start) | 2 | ENTRY(_zimage_start_opd) |
3 | EXTERN(_zimage_start_opd) | ||
3 | SECTIONS | 4 | SECTIONS |
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 @@ | |||
1 | OUTPUT_ARCH(powerpc:common) | 1 | OUTPUT_ARCH(powerpc:common) |
2 | ENTRY(_zimage_start) | 2 | ENTRY(_zimage_start) |
3 | EXTERN(_zimage_start) | ||
3 | SECTIONS | 4 | SECTIONS |
4 | { | 5 | { |
5 | . = (4*1024*1024); | 6 | . = (4*1024*1024); |