aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/boot
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2011-10-24 15:02:37 -0400
committerRob Herring <rob.herring@calxeda.com>2011-10-24 15:02:37 -0400
commit3a8254364277fabe01bc0e12b9691722939f5ef3 (patch)
tree0befa43780509144cc840f767859006409e0506d /arch/arm/boot
parent976d167615b64e14bc1491ca51d424e2ba9a5e84 (diff)
parent34471a9168c8bfd7f0d00989a7b0797ad27d585e (diff)
Merge remote-tracking branch 'rmk/devel-stable' into HEAD
Diffstat (limited to 'arch/arm/boot')
-rw-r--r--arch/arm/boot/compressed/.gitignore9
-rw-r--r--arch/arm/boot/compressed/Makefile32
-rw-r--r--arch/arm/boot/compressed/atags_to_fdt.c97
-rw-r--r--arch/arm/boot/compressed/head.S121
-rw-r--r--arch/arm/boot/compressed/libfdt_env.h15
-rw-r--r--arch/arm/boot/compressed/misc.c42
-rw-r--r--arch/arm/boot/compressed/string.c127
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.in4
8 files changed, 395 insertions, 52 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 0c74a6fab952..e4f32a8e002a 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -26,6 +26,10 @@ HEAD = head.o
26OBJS += misc.o decompress.o 26OBJS += misc.o decompress.o
27FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c 27FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
28 28
29# string library code (-Os is enforced to keep it much smaller)
30OBJS += string.o
31CFLAGS_string.o := -Os
32
29# 33#
30# Architecture dependencies 34# Architecture dependencies
31# 35#
@@ -89,21 +93,41 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
89suffix_$(CONFIG_KERNEL_LZO) = lzo 93suffix_$(CONFIG_KERNEL_LZO) = lzo
90suffix_$(CONFIG_KERNEL_LZMA) = lzma 94suffix_$(CONFIG_KERNEL_LZMA) = lzma
91 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
92targets := vmlinux vmlinux.lds \ 113targets := vmlinux vmlinux.lds \
93 piggy.$(suffix_y) piggy.$(suffix_y).o \ 114 piggy.$(suffix_y) piggy.$(suffix_y).o \
94 font.o font.c head.o misc.o $(OBJS) 115 lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
95 116
96# Make sure files are removed during clean 117# Make sure files are removed during clean
97extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S 118extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
98 119
99ifeq ($(CONFIG_FUNCTION_TRACER),y) 120ifeq ($(CONFIG_FUNCTION_TRACER),y)
100ORIG_CFLAGS := $(KBUILD_CFLAGS) 121ORIG_CFLAGS := $(KBUILD_CFLAGS)
101KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) 122KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
102endif 123endif
103 124
104ccflags-y := -fpic -fno-builtin 125ccflags-y := -fpic -fno-builtin -I$(obj)
105asflags-y := -Wa,-march=all 126asflags-y := -Wa,-march=all
106 127
128# Supply kernel BSS size to the decompressor via a linker symbol.
129KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')
130LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
107# Supply ZRELADDR to the decompressor via a linker symbol. 131# Supply ZRELADDR to the decompressor via a linker symbol.
108ifneq ($(CONFIG_AUTO_ZRELADDR),y) 132ifneq ($(CONFIG_AUTO_ZRELADDR),y)
109LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) 133LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
@@ -123,7 +147,7 @@ LDFLAGS_vmlinux += -T
123# For __aeabi_uidivmod 147# For __aeabi_uidivmod
124lib1funcs = $(obj)/lib1funcs.o 148lib1funcs = $(obj)/lib1funcs.o
125 149
126$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE 150$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
127 $(call cmd,shipped) 151 $(call cmd,shipped)
128 152
129# We need to prevent any GOTOFF relocs being used with references 153# We need to prevent any GOTOFF relocs being used with references
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 e95a5989602a..9f5ac11ccd8e 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -216,6 +216,103 @@ restart: adr r0, LC0
216 mov r10, r6 216 mov r10, r6
217#endif 217#endif
218 218
219 mov r5, #0 @ init dtb size to 0
220#ifdef CONFIG_ARM_APPENDED_DTB
221/*
222 * r0 = delta
223 * r2 = BSS start
224 * r3 = BSS end
225 * r4 = final kernel address
226 * r5 = appended dtb size (still unknown)
227 * r6 = _edata
228 * r7 = architecture ID
229 * r8 = atags/device tree pointer
230 * r9 = size of decompressed image
231 * r10 = end of this image, including bss/stack/malloc space if non XIP
232 * r11 = GOT start
233 * r12 = GOT end
234 * sp = stack pointer
235 *
236 * if there are device trees (dtb) appended to zImage, advance r10 so that the
237 * dtb data will get relocated along with the kernel if necessary.
238 */
239
240 ldr lr, [r6, #0]
241#ifndef __ARMEB__
242 ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian
243#else
244 ldr r1, =0xd00dfeed
245#endif
246 cmp lr, r1
247 bne dtb_check_done @ not found
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
281 mov r8, r6 @ use the appended device tree
282
283 /*
284 * Make sure that the DTB doesn't end up in the final
285 * kernel's .bss area. To do so, we adjust the decompressed
286 * kernel size to compensate if that .bss size is larger
287 * than the relocated code.
288 */
289 ldr r5, =_kernel_bss_size
290 adr r1, wont_overwrite
291 sub r1, r6, r1
292 subs r1, r5, r1
293 addhi r9, r9, r1
294
295 /* Get the dtb's size */
296 ldr r5, [r6, #4]
297#ifndef __ARMEB__
298 /* convert r5 (dtb size) to little endian */
299 eor r1, r5, r5, ror #16
300 bic r1, r1, #0x00ff0000
301 mov r5, r5, ror #8
302 eor r5, r5, r1, lsr #8
303#endif
304
305 /* preserve 64-bit alignment */
306 add r5, r5, #7
307 bic r5, r5, #7
308
309 /* relocate some pointers past the appended dtb */
310 add r6, r6, r5
311 add r10, r10, r5
312 add sp, sp, r5
313dtb_check_done:
314#endif
315
219/* 316/*
220 * Check to see if we will overwrite ourselves. 317 * Check to see if we will overwrite ourselves.
221 * r4 = final kernel address 318 * r4 = final kernel address
@@ -223,15 +320,14 @@ restart: adr r0, LC0
223 * r10 = end of this image, including bss/stack/malloc space if non XIP 320 * r10 = end of this image, including bss/stack/malloc space if non XIP
224 * We basically want: 321 * We basically want:
225 * r4 - 16k page directory >= r10 -> OK 322 * r4 - 16k page directory >= r10 -> OK
226 * r4 + image length <= current position (pc) -> OK 323 * r4 + image length <= address of wont_overwrite -> OK
227 */ 324 */
228 add r10, r10, #16384 325 add r10, r10, #16384
229 cmp r4, r10 326 cmp r4, r10
230 bhs wont_overwrite 327 bhs wont_overwrite
231 add r10, r4, r9 328 add r10, r4, r9
232 ARM( cmp r10, pc ) 329 adr r9, wont_overwrite
233 THUMB( mov lr, pc ) 330 cmp r10, r9
234 THUMB( cmp r10, lr )
235 bls wont_overwrite 331 bls wont_overwrite
236 332
237/* 333/*
@@ -285,14 +381,16 @@ wont_overwrite:
285 * r2 = BSS start 381 * r2 = BSS start
286 * r3 = BSS end 382 * r3 = BSS end
287 * r4 = kernel execution address 383 * r4 = kernel execution address
384 * r5 = appended dtb size (0 if not present)
288 * r7 = architecture ID 385 * r7 = architecture ID
289 * r8 = atags pointer 386 * r8 = atags pointer
290 * r11 = GOT start 387 * r11 = GOT start
291 * r12 = GOT end 388 * r12 = GOT end
292 * sp = stack pointer 389 * sp = stack pointer
293 */ 390 */
294 teq r0, #0 391 orrs r1, r0, r5
295 beq not_relocated 392 beq not_relocated
393
296 add r11, r11, r0 394 add r11, r11, r0
297 add r12, r12, r0 395 add r12, r12, r0
298 396
@@ -307,12 +405,21 @@ wont_overwrite:
307 405
308 /* 406 /*
309 * Relocate all entries in the GOT table. 407 * Relocate all entries in the GOT table.
408 * Bump bss entries to _edata + dtb size
310 */ 409 */
3111: ldr r1, [r11, #0] @ relocate entries in the GOT 4101: ldr r1, [r11, #0] @ relocate entries in the GOT
312 add r1, r1, r0 @ table. This fixes up the 411 add r1, r1, r0 @ This fixes up C references
313 str r1, [r11], #4 @ C references. 412 cmp r1, r2 @ if entry >= bss_start &&
413 cmphs r3, r1 @ bss_end > entry
414 addhi r1, r1, r5 @ entry += dtb size
415 str r1, [r11], #4 @ next entry
314 cmp r11, r12 416 cmp r11, r12
315 blo 1b 417 blo 1b
418
419 /* bump our bss pointers too */
420 add r2, r2, r5
421 add r3, r3, r5
422
316#else 423#else
317 424
318 /* 425 /*
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
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 832d37236c59..8e2a8fca5ed2 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -18,14 +18,9 @@
18 18
19unsigned int __machine_arch_type; 19unsigned int __machine_arch_type;
20 20
21#define _LINUX_STRING_H_
22
23#include <linux/compiler.h> /* for inline */ 21#include <linux/compiler.h> /* for inline */
24#include <linux/types.h> /* for size_t */ 22#include <linux/types.h>
25#include <linux/stddef.h> /* for NULL */
26#include <linux/linkage.h> 23#include <linux/linkage.h>
27#include <asm/string.h>
28
29 24
30static void putstr(const char *ptr); 25static void putstr(const char *ptr);
31extern void error(char *x); 26extern void error(char *x);
@@ -101,41 +96,6 @@ static void putstr(const char *ptr)
101 flush(); 96 flush();
102} 97}
103 98
104
105void *memcpy(void *__dest, __const void *__src, size_t __n)
106{
107 int i = 0;
108 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
109
110 for (i = __n >> 3; i > 0; i--) {
111 *d++ = *s++;
112 *d++ = *s++;
113 *d++ = *s++;
114 *d++ = *s++;
115 *d++ = *s++;
116 *d++ = *s++;
117 *d++ = *s++;
118 *d++ = *s++;
119 }
120
121 if (__n & 1 << 2) {
122 *d++ = *s++;
123 *d++ = *s++;
124 *d++ = *s++;
125 *d++ = *s++;
126 }
127
128 if (__n & 1 << 1) {
129 *d++ = *s++;
130 *d++ = *s++;
131 }
132
133 if (__n & 1)
134 *d++ = *s++;
135
136 return __dest;
137}
138
139/* 99/*
140 * gzip declarations 100 * gzip declarations
141 */ 101 */
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c
new file mode 100644
index 000000000000..36e53ef9200f
--- /dev/null
+++ b/arch/arm/boot/compressed/string.c
@@ -0,0 +1,127 @@
1/*
2 * arch/arm/boot/compressed/string.c
3 *
4 * Small subset of simple string routines
5 */
6
7#include <linux/string.h>
8
9void *memcpy(void *__dest, __const void *__src, size_t __n)
10{
11 int i = 0;
12 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
13
14 for (i = __n >> 3; i > 0; i--) {
15 *d++ = *s++;
16 *d++ = *s++;
17 *d++ = *s++;
18 *d++ = *s++;
19 *d++ = *s++;
20 *d++ = *s++;
21 *d++ = *s++;
22 *d++ = *s++;
23 }
24
25 if (__n & 1 << 2) {
26 *d++ = *s++;
27 *d++ = *s++;
28 *d++ = *s++;
29 *d++ = *s++;
30 }
31
32 if (__n & 1 << 1) {
33 *d++ = *s++;
34 *d++ = *s++;
35 }
36
37 if (__n & 1)
38 *d++ = *s++;
39
40 return __dest;
41}
42
43void *memmove(void *__dest, __const void *__src, size_t count)
44{
45 unsigned char *d = __dest;
46 const unsigned char *s = __src;
47
48 if (__dest == __src)
49 return __dest;
50
51 if (__dest < __src)
52 return memcpy(__dest, __src, count);
53
54 while (count--)
55 d[count] = s[count];
56 return __dest;
57}
58
59size_t strlen(const char *s)
60{
61 const char *sc = s;
62
63 while (*sc != '\0')
64 sc++;
65 return sc - s;
66}
67
68int memcmp(const void *cs, const void *ct, size_t count)
69{
70 const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
71 int res = 0;
72
73 while (su1 < end) {
74 res = *su1++ - *su2++;
75 if (res)
76 break;
77 }
78 return res;
79}
80
81int strcmp(const char *cs, const char *ct)
82{
83 unsigned char c1, c2;
84 int res = 0;
85
86 do {
87 c1 = *cs++;
88 c2 = *ct++;
89 res = c1 - c2;
90 if (res)
91 break;
92 } while (c1);
93 return res;
94}
95
96void *memchr(const void *s, int c, size_t count)
97{
98 const unsigned char *p = s;
99
100 while (count--)
101 if ((unsigned char)c == *p++)
102 return (void *)(p - 1);
103 return NULL;
104}
105
106char *strchr(const char *s, int c)
107{
108 while (*s != (char)c)
109 if (*s++ == '\0')
110 return NULL;
111 return (char *)s;
112}
113
114#undef memset
115
116void *memset(void *s, int c, size_t count)
117{
118 char *xs = s;
119 while (count--)
120 *xs++ = c;
121 return s;
122}
123
124void __memzero(void *s, size_t count)
125{
126 memset(s, 0, count);
127}
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index 4e728834a1b9..4919f2ac8b89 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -51,6 +51,10 @@ SECTIONS
51 _got_start = .; 51 _got_start = .;
52 .got : { *(.got) } 52 .got : { *(.got) }
53 _got_end = .; 53 _got_end = .;
54
55 /* ensure the zImage file size is always a multiple of 64 bits */
56 /* (without a dummy byte, ld just ignores the empty section) */
57 .pad : { BYTE(0); . = ALIGN(8); }
54 _edata = .; 58 _edata = .;
55 59
56 . = BSS_START; 60 . = BSS_START;