diff options
author | Rob Herring <rob.herring@calxeda.com> | 2011-10-24 15:02:37 -0400 |
---|---|---|
committer | Rob Herring <rob.herring@calxeda.com> | 2011-10-24 15:02:37 -0400 |
commit | 3a8254364277fabe01bc0e12b9691722939f5ef3 (patch) | |
tree | 0befa43780509144cc840f767859006409e0506d /arch/arm/boot | |
parent | 976d167615b64e14bc1491ca51d424e2ba9a5e84 (diff) | |
parent | 34471a9168c8bfd7f0d00989a7b0797ad27d585e (diff) |
Merge remote-tracking branch 'rmk/devel-stable' into HEAD
Diffstat (limited to 'arch/arm/boot')
-rw-r--r-- | arch/arm/boot/compressed/.gitignore | 9 | ||||
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 32 | ||||
-rw-r--r-- | arch/arm/boot/compressed/atags_to_fdt.c | 97 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 121 | ||||
-rw-r--r-- | arch/arm/boot/compressed/libfdt_env.h | 15 | ||||
-rw-r--r-- | arch/arm/boot/compressed/misc.c | 42 | ||||
-rw-r--r-- | arch/arm/boot/compressed/string.c | 127 | ||||
-rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.in | 4 |
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 | |||
5 | piggy.lzma | 5 | piggy.lzma |
6 | vmlinux | 6 | vmlinux |
7 | vmlinux.lds | 7 | vmlinux.lds |
8 | |||
9 | # borrowed libfdt files | ||
10 | fdt.c | ||
11 | fdt.h | ||
12 | fdt_ro.c | ||
13 | fdt_rw.c | ||
14 | fdt_wip.c | ||
15 | libfdt.h | ||
16 | libfdt_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 | |||
26 | OBJS += misc.o decompress.o | 26 | OBJS += misc.o decompress.o |
27 | FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c | 27 | FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c |
28 | 28 | ||
29 | # string library code (-Os is enforced to keep it much smaller) | ||
30 | OBJS += string.o | ||
31 | CFLAGS_string.o := -Os | ||
32 | |||
29 | # | 33 | # |
30 | # Architecture dependencies | 34 | # Architecture dependencies |
31 | # | 35 | # |
@@ -89,21 +93,41 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip | |||
89 | suffix_$(CONFIG_KERNEL_LZO) = lzo | 93 | suffix_$(CONFIG_KERNEL_LZO) = lzo |
90 | suffix_$(CONFIG_KERNEL_LZMA) = lzma | 94 | suffix_$(CONFIG_KERNEL_LZMA) = lzma |
91 | 95 | ||
96 | # Borrowed libfdt files for the ATAG compatibility mode | ||
97 | |||
98 | libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c | ||
99 | libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h | ||
100 | |||
101 | libfdt_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 | |||
109 | ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y) | ||
110 | OBJS += $(libfdt_objs) atags_to_fdt.o | ||
111 | endif | ||
112 | |||
92 | targets := vmlinux vmlinux.lds \ | 113 | targets := 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 |
97 | extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S | 118 | extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs) |
98 | 119 | ||
99 | ifeq ($(CONFIG_FUNCTION_TRACER),y) | 120 | ifeq ($(CONFIG_FUNCTION_TRACER),y) |
100 | ORIG_CFLAGS := $(KBUILD_CFLAGS) | 121 | ORIG_CFLAGS := $(KBUILD_CFLAGS) |
101 | KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) | 122 | KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) |
102 | endif | 123 | endif |
103 | 124 | ||
104 | ccflags-y := -fpic -fno-builtin | 125 | ccflags-y := -fpic -fno-builtin -I$(obj) |
105 | asflags-y := -Wa,-march=all | 126 | asflags-y := -Wa,-march=all |
106 | 127 | ||
128 | # Supply kernel BSS size to the decompressor via a linker symbol. | ||
129 | KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}') | ||
130 | LDFLAGS_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. |
108 | ifneq ($(CONFIG_AUTO_ZRELADDR),y) | 132 | ifneq ($(CONFIG_AUTO_ZRELADDR),y) |
109 | LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) | 133 | LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) |
@@ -123,7 +147,7 @@ LDFLAGS_vmlinux += -T | |||
123 | # For __aeabi_uidivmod | 147 | # For __aeabi_uidivmod |
124 | lib1funcs = $(obj)/lib1funcs.o | 148 | lib1funcs = $(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 | |||
4 | static 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 | |||
12 | static 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 | |||
21 | static 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 | |||
30 | static 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 | */ | ||
47 | int 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 | ||
313 | dtb_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 | */ |
311 | 1: ldr r1, [r11, #0] @ relocate entries in the GOT | 410 | 1: 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 | ||
19 | unsigned int __machine_arch_type; | 19 | unsigned 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 | ||
30 | static void putstr(const char *ptr); | 25 | static void putstr(const char *ptr); |
31 | extern void error(char *x); | 26 | extern void error(char *x); |
@@ -101,41 +96,6 @@ static void putstr(const char *ptr) | |||
101 | flush(); | 96 | flush(); |
102 | } | 97 | } |
103 | 98 | ||
104 | |||
105 | void *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 | |||
9 | void *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 | |||
43 | void *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 | |||
59 | size_t strlen(const char *s) | ||
60 | { | ||
61 | const char *sc = s; | ||
62 | |||
63 | while (*sc != '\0') | ||
64 | sc++; | ||
65 | return sc - s; | ||
66 | } | ||
67 | |||
68 | int 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 | |||
81 | int 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 | |||
96 | void *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 | |||
106 | char *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 | |||
116 | void *memset(void *s, int c, size_t count) | ||
117 | { | ||
118 | char *xs = s; | ||
119 | while (count--) | ||
120 | *xs++ = c; | ||
121 | return s; | ||
122 | } | ||
123 | |||
124 | void __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; |