aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/boot/compressed
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/boot/compressed')
-rw-r--r--arch/arm/boot/compressed/.gitignore9
-rw-r--r--arch/arm/boot/compressed/Makefile21
-rw-r--r--arch/arm/boot/compressed/atags_to_fdt.c97
-rw-r--r--arch/arm/boot/compressed/head.S32
-rw-r--r--arch/arm/boot/compressed/libfdt_env.h15
5 files changed, 172 insertions, 2 deletions
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index c6028967d336..e0936a148516 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -5,3 +5,12 @@ piggy.lzo
5piggy.lzma 5piggy.lzma
6vmlinux 6vmlinux
7vmlinux.lds 7vmlinux.lds
8
9# borrowed libfdt files
10fdt.c
11fdt.h
12fdt_ro.c
13fdt_rw.c
14fdt_wip.c
15libfdt.h
16libfdt_internal.h
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index c20ddc69d950..55f86349d547 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -93,19 +93,36 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
93suffix_$(CONFIG_KERNEL_LZO) = lzo 93suffix_$(CONFIG_KERNEL_LZO) = lzo
94suffix_$(CONFIG_KERNEL_LZMA) = lzma 94suffix_$(CONFIG_KERNEL_LZMA) = lzma
95 95
96# Borrowed libfdt files for the ATAG compatibility mode
97
98libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
99libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h
100
101libfdt_objs := $(addsuffix .o, $(basename $(libfdt)))
102
103$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
104 $(call cmd,shipped)
105
106$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
107 $(addprefix $(obj)/,$(libfdt_hdrs))
108
109ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
110OBJS += $(libfdt_objs) atags_to_fdt.o
111endif
112
96targets := vmlinux vmlinux.lds \ 113targets := vmlinux vmlinux.lds \
97 piggy.$(suffix_y) piggy.$(suffix_y).o \ 114 piggy.$(suffix_y) piggy.$(suffix_y).o \
98 font.o font.c head.o misc.o $(OBJS) 115 font.o font.c head.o misc.o $(OBJS)
99 116
100# Make sure files are removed during clean 117# Make sure files are removed during clean
101extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S 118extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
102 119
103ifeq ($(CONFIG_FUNCTION_TRACER),y) 120ifeq ($(CONFIG_FUNCTION_TRACER),y)
104ORIG_CFLAGS := $(KBUILD_CFLAGS) 121ORIG_CFLAGS := $(KBUILD_CFLAGS)
105KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) 122KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
106endif 123endif
107 124
108ccflags-y := -fpic -fno-builtin 125ccflags-y := -fpic -fno-builtin -I$(obj)
109asflags-y := -Wa,-march=all 126asflags-y := -Wa,-march=all
110 127
111# Supply kernel BSS size to the decompressor via a linker symbol. 128# Supply kernel BSS size to the decompressor via a linker symbol.
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
new file mode 100644
index 000000000000..6ce11c481178
--- /dev/null
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -0,0 +1,97 @@
1#include <asm/setup.h>
2#include <libfdt.h>
3
4static int node_offset(void *fdt, const char *node_path)
5{
6 int offset = fdt_path_offset(fdt, node_path);
7 if (offset == -FDT_ERR_NOTFOUND)
8 offset = fdt_add_subnode(fdt, 0, node_path);
9 return offset;
10}
11
12static int setprop(void *fdt, const char *node_path, const char *property,
13 uint32_t *val_array, int size)
14{
15 int offset = node_offset(fdt, node_path);
16 if (offset < 0)
17 return offset;
18 return fdt_setprop(fdt, offset, property, val_array, size);
19}
20
21static int setprop_string(void *fdt, const char *node_path,
22 const char *property, const char *string)
23{
24 int offset = node_offset(fdt, node_path);
25 if (offset < 0)
26 return offset;
27 return fdt_setprop_string(fdt, offset, property, string);
28}
29
30static int setprop_cell(void *fdt, const char *node_path,
31 const char *property, uint32_t val)
32{
33 int offset = node_offset(fdt, node_path);
34 if (offset < 0)
35 return offset;
36 return fdt_setprop_cell(fdt, offset, property, val);
37}
38
39/*
40 * Convert and fold provided ATAGs into the provided FDT.
41 *
42 * REturn values:
43 * = 0 -> pretend success
44 * = 1 -> bad ATAG (may retry with another possible ATAG pointer)
45 * < 0 -> error from libfdt
46 */
47int atags_to_fdt(void *atag_list, void *fdt, int total_space)
48{
49 struct tag *atag = atag_list;
50 uint32_t mem_reg_property[2 * NR_BANKS];
51 int memcount = 0;
52 int ret;
53
54 /* make sure we've got an aligned pointer */
55 if ((u32)atag_list & 0x3)
56 return 1;
57
58 /* if we get a DTB here we're done already */
59 if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
60 return 0;
61
62 /* validate the ATAG */
63 if (atag->hdr.tag != ATAG_CORE ||
64 (atag->hdr.size != tag_size(tag_core) &&
65 atag->hdr.size != 2))
66 return 1;
67
68 /* let's give it all the room it could need */
69 ret = fdt_open_into(fdt, fdt, total_space);
70 if (ret < 0)
71 return ret;
72
73 for_each_tag(atag, atag_list) {
74 if (atag->hdr.tag == ATAG_CMDLINE) {
75 setprop_string(fdt, "/chosen", "bootargs",
76 atag->u.cmdline.cmdline);
77 } else if (atag->hdr.tag == ATAG_MEM) {
78 if (memcount >= sizeof(mem_reg_property)/4)
79 continue;
80 mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
81 mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
82 } else if (atag->hdr.tag == ATAG_INITRD2) {
83 uint32_t initrd_start, initrd_size;
84 initrd_start = atag->u.initrd.start;
85 initrd_size = atag->u.initrd.size;
86 setprop_cell(fdt, "/chosen", "linux,initrd-start",
87 initrd_start);
88 setprop_cell(fdt, "/chosen", "linux,initrd-end",
89 initrd_start + initrd_size);
90 }
91 }
92
93 if (memcount)
94 setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
95
96 return fdt_pack(fdt);
97}
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index ba5c552f8c69..9f5ac11ccd8e 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -246,6 +246,38 @@ restart: adr r0, LC0
246 cmp lr, r1 246 cmp lr, r1
247 bne dtb_check_done @ not found 247 bne dtb_check_done @ not found
248 248
249#ifdef CONFIG_ARM_ATAG_DTB_COMPAT
250 /*
251 * OK... Let's do some funky business here.
252 * If we do have a DTB appended to zImage, and we do have
253 * an ATAG list around, we want the later to be translated
254 * and folded into the former here. To be on the safe side,
255 * let's temporarily move the stack away into the malloc
256 * area. No GOT fixup has occurred yet, but none of the
257 * code we're about to call uses any global variable.
258 */
259 add sp, sp, #0x10000
260 stmfd sp!, {r0-r3, ip, lr}
261 mov r0, r8
262 mov r1, r6
263 sub r2, sp, r6
264 bl atags_to_fdt
265
266 /*
267 * If returned value is 1, there is no ATAG at the location
268 * pointed by r8. Try the typical 0x100 offset from start
269 * of RAM and hope for the best.
270 */
271 cmp r0, #1
272 sub r0, r4, #(TEXT_OFFSET - 0x100)
273 mov r1, r6
274 sub r2, sp, r6
275 blne atags_to_fdt
276
277 ldmfd sp!, {r0-r3, ip, lr}
278 sub sp, sp, #0x10000
279#endif
280
249 mov r8, r6 @ use the appended device tree 281 mov r8, r6 @ use the appended device tree
250 282
251 /* 283 /*
diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h
new file mode 100644
index 000000000000..1f4e71876b00
--- /dev/null
+++ b/arch/arm/boot/compressed/libfdt_env.h
@@ -0,0 +1,15 @@
1#ifndef _ARM_LIBFDT_ENV_H
2#define _ARM_LIBFDT_ENV_H
3
4#include <linux/types.h>
5#include <linux/string.h>
6#include <asm/byteorder.h>
7
8#define fdt16_to_cpu(x) be16_to_cpu(x)
9#define cpu_to_fdt16(x) cpu_to_be16(x)
10#define fdt32_to_cpu(x) be32_to_cpu(x)
11#define cpu_to_fdt32(x) cpu_to_be32(x)
12#define fdt64_to_cpu(x) be64_to_cpu(x)
13#define cpu_to_fdt64(x) cpu_to_be64(x)
14
15#endif