diff options
Diffstat (limited to 'arch/arm/boot/compressed')
| -rw-r--r-- | arch/arm/boot/compressed/.gitignore | 14 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/Makefile | 90 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/atags_to_fdt.c | 191 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/debug.S | 40 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/decompress.c | 15 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head-sa1100.S | 1 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head-shark.S | 139 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head-shmobile.S | 60 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head-vt8500.S | 46 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head-xscale.S | 7 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head.S | 343 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/libfdt_env.h | 15 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/misc.c | 58 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/mmcif-sh7372.c | 2 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/ofw-shark.c | 260 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/piggy.lz4.S | 6 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/piggy.xzkern.S | 6 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/sdhi-sh7372.c | 2 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/string.c | 127 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.in | 4 |
20 files changed, 798 insertions, 628 deletions
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index c6028967d33..0714e0334e3 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -1,7 +1,21 @@ +ashldi3.S +bswapsdi2.S font.c lib1funcs.S +hyp-stub.S piggy.gzip piggy.lzo piggy.lzma +piggy.xzkern +piggy.lz4 vmlinux vmlinux.lds + +# borrowed libfdt files +fdt.c +fdt.h +fdt_ro.c +fdt_rw.c +fdt_wip.c +libfdt.h +libfdt_internal.h diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0c74a6fab95..68c918362b7 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -24,7 +24,18 @@ endif AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) HEAD = head.o OBJS += misc.o decompress.o -FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c +ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y) +OBJS += debug.o +endif +FONTC = $(srctree)/lib/fonts/font_acorn_8x8.c + +# string library code (-Os is enforced to keep it much smaller) +OBJS += string.o +CFLAGS_string.o := -Os + +ifeq ($(CONFIG_ARM_VIRT_EXT),y) +OBJS += hyp-stub.o +endif # # Architecture dependencies @@ -33,23 +44,10 @@ ifeq ($(CONFIG_ARCH_ACORN),y) OBJS += ll_char_wr.o font.o endif -ifeq ($(CONFIG_ARCH_SHARK),y) -OBJS += head-shark.o ofw-shark.o -endif - -ifeq ($(CONFIG_ARCH_P720T),y) -# Borrow this code from SA1100 -OBJS += head-sa1100.o -endif - ifeq ($(CONFIG_ARCH_SA1100),y) OBJS += head-sa1100.o endif -ifeq ($(CONFIG_ARCH_VT8500),y) -OBJS += head-vt8500.o -endif - ifeq ($(CONFIG_CPU_XSCALE),y) OBJS += head-xscale.o endif @@ -66,7 +64,7 @@ else endif endif -ifeq ($(CONFIG_ARCH_SHMOBILE),y) +ifeq ($(CONFIG_ARCH_SHMOBILE_LEGACY),y) OBJS += head-shmobile.o endif @@ -88,22 +86,48 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ suffix_$(CONFIG_KERNEL_GZIP) = gzip suffix_$(CONFIG_KERNEL_LZO) = lzo suffix_$(CONFIG_KERNEL_LZMA) = lzma +suffix_$(CONFIG_KERNEL_XZ) = xzkern +suffix_$(CONFIG_KERNEL_LZ4) = lz4 + +# Borrowed libfdt files for the ATAG compatibility mode + +libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c +libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h + +libfdt_objs := $(addsuffix .o, $(basename $(libfdt))) + +$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/% + $(call cmd,shipped) + +$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \ + $(addprefix $(obj)/,$(libfdt_hdrs)) + +ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y) +OBJS += $(libfdt_objs) atags_to_fdt.o +endif targets := vmlinux vmlinux.lds \ piggy.$(suffix_y) piggy.$(suffix_y).o \ - font.o font.c head.o misc.o $(OBJS) + lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S bswapsdi2.o \ + bswapsdi2.S font.o font.c head.o misc.o $(OBJS) # Make sure files are removed during clean -extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S +extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern piggy.lz4 \ + lib1funcs.S ashldi3.S bswapsdi2.S $(libfdt) $(libfdt_hdrs) \ + hyp-stub.S ifeq ($(CONFIG_FUNCTION_TRACER),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) endif -ccflags-y := -fpic -fno-builtin -asflags-y := -Wa,-march=all +ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj) +asflags-y := -DZIMAGE +# Supply kernel BSS size to the decompressor via a linker symbol. +KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \ + awk 'END{print $$3}') +LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) @@ -123,7 +147,19 @@ LDFLAGS_vmlinux += -T # For __aeabi_uidivmod lib1funcs = $(obj)/lib1funcs.o -$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE +$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S + $(call cmd,shipped) + +# For __aeabi_llsl +ashldi3 = $(obj)/ashldi3.o + +$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S + $(call cmd,shipped) + +# For __bswapsi2, __bswapdi2 +bswapsdi2 = $(obj)/bswapsdi2.o + +$(obj)/bswapsdi2.S: $(srctree)/arch/$(SRCARCH)/lib/bswapsdi2.S $(call cmd,shipped) # We need to prevent any GOTOFF relocs being used with references @@ -139,8 +175,17 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \ ( echo "following symbols must have non local/private scope:" >&2; \ echo "$$bad_syms" >&2; rm -f $@; false ) +check_for_multiple_zreladdr = \ +if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \ + echo 'multiple zreladdrs: $(ZRELADDR)'; \ + echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \ + false; \ +fi + $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ - $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE + $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \ + $(bswapsdi2) FORCE + @$(check_for_multiple_zreladdr) $(call if_changed,ld) @$(check_for_bad_syms) @@ -156,3 +201,6 @@ $(obj)/font.c: $(FONTC) $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG) @sed "$(SEDFLAGS)" < $< > $@ + +$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S + $(call cmd,shipped) 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 00000000000..9448aa0c668 --- /dev/null +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -0,0 +1,191 @@ +#include <asm/setup.h> +#include <libfdt.h> + +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) +#define do_extend_cmdline 1 +#else +#define do_extend_cmdline 0 +#endif + +#define NR_BANKS 16 + +static int node_offset(void *fdt, const char *node_path) +{ + int offset = fdt_path_offset(fdt, node_path); + if (offset == -FDT_ERR_NOTFOUND) + offset = fdt_add_subnode(fdt, 0, node_path); + return offset; +} + +static int setprop(void *fdt, const char *node_path, const char *property, + uint32_t *val_array, int size) +{ + int offset = node_offset(fdt, node_path); + if (offset < 0) + return offset; + return fdt_setprop(fdt, offset, property, val_array, size); +} + +static int setprop_string(void *fdt, const char *node_path, + const char *property, const char *string) +{ + int offset = node_offset(fdt, node_path); + if (offset < 0) + return offset; + return fdt_setprop_string(fdt, offset, property, string); +} + +static int setprop_cell(void *fdt, const char *node_path, + const char *property, uint32_t val) +{ + int offset = node_offset(fdt, node_path); + if (offset < 0) + return offset; + return fdt_setprop_cell(fdt, offset, property, val); +} + +static const void *getprop(const void *fdt, const char *node_path, + const char *property, int *len) +{ + int offset = fdt_path_offset(fdt, node_path); + + if (offset == -FDT_ERR_NOTFOUND) + return NULL; + + return fdt_getprop(fdt, offset, property, len); +} + +static uint32_t get_cell_size(const void *fdt) +{ + int len; + uint32_t cell_size = 1; + const uint32_t *size_len = getprop(fdt, "/", "#size-cells", &len); + + if (size_len) + cell_size = fdt32_to_cpu(*size_len); + return cell_size; +} + +static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) +{ + char cmdline[COMMAND_LINE_SIZE]; + const char *fdt_bootargs; + char *ptr = cmdline; + int len = 0; + + /* copy the fdt command line into the buffer */ + fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len); + if (fdt_bootargs) + if (len < COMMAND_LINE_SIZE) { + memcpy(ptr, fdt_bootargs, len); + /* len is the length of the string + * including the NULL terminator */ + ptr += len - 1; + } + + /* and append the ATAG_CMDLINE */ + if (fdt_cmdline) { + len = strlen(fdt_cmdline); + if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { + *ptr++ = ' '; + memcpy(ptr, fdt_cmdline, len); + ptr += len; + } + } + *ptr = '\0'; + + setprop_string(fdt, "/chosen", "bootargs", cmdline); +} + +/* + * Convert and fold provided ATAGs into the provided FDT. + * + * REturn values: + * = 0 -> pretend success + * = 1 -> bad ATAG (may retry with another possible ATAG pointer) + * < 0 -> error from libfdt + */ +int atags_to_fdt(void *atag_list, void *fdt, int total_space) +{ + struct tag *atag = atag_list; + /* In the case of 64 bits memory size, need to reserve 2 cells for + * address and size for each bank */ + uint32_t mem_reg_property[2 * 2 * NR_BANKS]; + int memcount = 0; + int ret, memsize; + + /* make sure we've got an aligned pointer */ + if ((u32)atag_list & 0x3) + return 1; + + /* if we get a DTB here we're done already */ + if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC)) + return 0; + + /* validate the ATAG */ + if (atag->hdr.tag != ATAG_CORE || + (atag->hdr.size != tag_size(tag_core) && + atag->hdr.size != 2)) + return 1; + + /* let's give it all the room it could need */ + ret = fdt_open_into(fdt, fdt, total_space); + if (ret < 0) + return ret; + + for_each_tag(atag, atag_list) { + if (atag->hdr.tag == ATAG_CMDLINE) { + /* Append the ATAGS command line to the device tree + * command line. + * NB: This means that if the same parameter is set in + * the device tree and in the tags, the one from the + * tags will be chosen. + */ + if (do_extend_cmdline) + merge_fdt_bootargs(fdt, + atag->u.cmdline.cmdline); + else + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); + } else if (atag->hdr.tag == ATAG_MEM) { + if (memcount >= sizeof(mem_reg_property)/4) + continue; + if (!atag->u.mem.size) + continue; + memsize = get_cell_size(fdt); + + if (memsize == 2) { + /* if memsize is 2, that means that + * each data needs 2 cells of 32 bits, + * so the data are 64 bits */ + uint64_t *mem_reg_prop64 = + (uint64_t *)mem_reg_property; + mem_reg_prop64[memcount++] = + cpu_to_fdt64(atag->u.mem.start); + mem_reg_prop64[memcount++] = + cpu_to_fdt64(atag->u.mem.size); + } else { + mem_reg_property[memcount++] = + cpu_to_fdt32(atag->u.mem.start); + mem_reg_property[memcount++] = + cpu_to_fdt32(atag->u.mem.size); + } + + } else if (atag->hdr.tag == ATAG_INITRD2) { + uint32_t initrd_start, initrd_size; + initrd_start = atag->u.initrd.start; + initrd_size = atag->u.initrd.size; + setprop_cell(fdt, "/chosen", "linux,initrd-start", + initrd_start); + setprop_cell(fdt, "/chosen", "linux,initrd-end", + initrd_start + initrd_size); + } + } + + if (memcount) { + setprop(fdt, "/memory", "reg", mem_reg_property, + 4 * memcount * memsize); + } + + return fdt_pack(fdt); +} diff --git a/arch/arm/boot/compressed/debug.S b/arch/arm/boot/compressed/debug.S new file mode 100644 index 00000000000..5392ee63338 --- /dev/null +++ b/arch/arm/boot/compressed/debug.S @@ -0,0 +1,40 @@ +#include <linux/linkage.h> +#include <asm/assembler.h> + +#ifndef CONFIG_DEBUG_SEMIHOSTING + +#include CONFIG_DEBUG_LL_INCLUDE + +ENTRY(putc) + addruart r1, r2, r3 + waituart r3, r1 + senduart r0, r1 + busyuart r3, r1 + mov pc, lr +ENDPROC(putc) + +#else + +ENTRY(putc) + adr r1, 1f + ldmia r1, {r2, r3} + add r2, r2, r1 + ldr r1, [r2, r3] + strb r0, [r1] + mov r0, #0x03 @ SYS_WRITEC + ARM( svc #0x123456 ) + THUMB( svc #0xab ) + mov pc, lr + .align 2 +1: .word _GLOBAL_OFFSET_TABLE_ - . + .word semi_writec_buf(GOT) +ENDPROC(putc) + + .bss + .global semi_writec_buf + .type semi_writec_buf, %object +semi_writec_buf: + .space 4 + .size semi_writec_buf, 4 + +#endif diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index 07be5a2f830..bd245d34952 100644 --- a/arch/arm/boot/compressed/decompress.c +++ b/arch/arm/boot/compressed/decompress.c @@ -13,8 +13,6 @@ extern void error(char *); #define STATIC static #define STATIC_RW_DATA /* non-static please */ -#define ARCH_HAS_DECOMP_WDOG - /* Diagnostic functions */ #ifdef DEBUG # define Assert(cond,msg) {if(!(cond)) error(msg);} @@ -32,6 +30,9 @@ extern void error(char *); # define Tracecv(c,x) #endif +/* Not needed, but used in some headers pulled in by decompressors */ +extern char * strstr(const char * s1, const char *s2); + #ifdef CONFIG_KERNEL_GZIP #include "../../../../lib/decompress_inflate.c" #endif @@ -44,6 +45,16 @@ extern void error(char *); #include "../../../../lib/decompress_unlzma.c" #endif +#ifdef CONFIG_KERNEL_XZ +#define memmove memmove +#define memcpy memcpy +#include "../../../../lib/decompress_unxz.c" +#endif + +#ifdef CONFIG_KERNEL_LZ4 +#include "../../../../lib/decompress_unlz4.c" +#endif + int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) { return decompress(input, len, NULL, NULL, output, NULL, error); diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S index 6179d94dd5c..3115e313d9f 100644 --- a/arch/arm/boot/compressed/head-sa1100.S +++ b/arch/arm/boot/compressed/head-sa1100.S @@ -11,6 +11,7 @@ #include <asm/mach-types.h> .section ".start", "ax" + .arch armv4 __SA1100_start: diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S deleted file mode 100644 index 089c560e07f..00000000000 --- a/arch/arm/boot/compressed/head-shark.S +++ /dev/null @@ -1,139 +0,0 @@ -/* The head-file for the Shark - * by Alexander Schulz - * - * Does the following: - * - get the memory layout from firmware. This can only be done as long as the mmu - * is still on. - * - switch the mmu off, so we have physical addresses - * - copy the kernel to 0x08508000. This is done to have a fixed address where the - * C-parts (misc.c) are executed. This address must be known at compile-time, - * but the load-address of the kernel depends on how much memory is installed. - * - Jump to this location. - * - Set r8 with 0, r7 with the architecture ID for head.S - */ - -#include <linux/linkage.h> - -#include <asm/assembler.h> - - .section ".start", "ax" - - b __beginning - -__ofw_data: .long 0 @ the number of memory blocks - .space 128 @ (startaddr,size) ... - .space 128 @ bootargs - .align - -__beginning: mov r4, r0 @ save the entry to the firmware - - mov r0, #0xC0 @ disable irq and fiq - mov r1, r0 - mrs r3, cpsr - bic r2, r3, r0 - eor r2, r2, r1 - msr cpsr_c, r2 - - mov r0, r4 @ get the Memory layout from firmware - adr r1, __ofw_data - add r2, r1, #4 - mov lr, pc - b ofw_init - mov r1, #0 - - adr r2, __mmu_off @ calculate physical address - sub r2, r2, #0xf0000000 @ openprom maps us at f000 virt, 0e50 phys - adr r0, __ofw_data - ldr r0, [r0, #4] - add r2, r2, r0 - add r2, r2, #0x00500000 - - mrc p15, 0, r3, c1, c0 - bic r3, r3, #0xC @ Write Buffer and DCache - bic r3, r3, #0x1000 @ ICache - mcr p15, 0, r3, c1, c0 @ disabled - - mov r0, #0 - mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 - mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 - - bic r3, r3, #0x1 @ MMU - mcr p15, 0, r3, c1, c0 @ disabled - - mov pc, r2 - -__copy_target: .long 0x08507FFC -__copy_end: .long 0x08607FFC - - .word _start - .word __bss_start - - .align -__temp_stack: .space 128 - -__mmu_off: - adr r0, __ofw_data @ read the 1. entry of the memory map - ldr r0, [r0, #4] - orr r0, r0, #0x00600000 - sub r0, r0, #4 - - ldr r1, __copy_end - ldr r3, __copy_target - -/* r0 = 0x0e600000 (current end of kernelcode) - * r3 = 0x08508000 (where it should begin) - * r1 = 0x08608000 (end of copying area, 1MB) - * The kernel is compressed, so 1 MB should be enough. - * copy the kernel to the beginning of physical memory - * We start from the highest address, so we can copy - * from 0x08500000 to 0x08508000 if we have only 8MB - */ - -/* As we get more 2.6-kernels it gets more and more - * uncomfortable to be bound to kernel images of 1MB only. - * So we add a loop here, to be able to copy some more. - * Alexander Schulz 2005-07-17 - */ - - mov r4, #3 @ How many megabytes to copy - - -__MoveCode: sub r4, r4, #1 - -__Copy: ldr r2, [r0], #-4 - str r2, [r1], #-4 - teq r1, r3 - bne __Copy - - /* The firmware maps us in blocks of 1 MB, the next block is - _below_ the last one. So our decrementing source pointer - ist right here, but the destination pointer must be increased - by 2 MB */ - add r1, r1, #0x00200000 - add r3, r3, #0x00100000 - - teq r4, #0 - bne __MoveCode - - - /* and jump to it */ - adr r2, __go_on @ where we want to jump - adr r0, __ofw_data @ read the 1. entry of the memory map - ldr r0, [r0, #4] - sub r2, r2, r0 @ we are mapped add 0e50 now, sub that (-0e00) - sub r2, r2, #0x00500000 @ -0050 - ldr r0, __copy_target @ and add 0850 8000 instead - add r0, r0, #4 - add r2, r2, r0 - mov pc, r2 @ and jump there - -__go_on: - adr sp, __temp_stack - add sp, sp, #128 - adr r0, __ofw_data - mov lr, pc - b create_params - - mov r8, #0 - mov r7, #15 diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S index fe3719b516f..e7f80928949 100644 --- a/arch/arm/boot/compressed/head-shmobile.S +++ b/arch/arm/boot/compressed/head-shmobile.S @@ -46,7 +46,7 @@ __image_start: __image_end: .long _got_end __load_base: - .long CONFIG_MEMORY_START + 0x02000000 @ Load at 32Mb into SDRAM + .long MEMORY_START + 0x02000000 @ Load at 32Mb into SDRAM __loaded: .long __continue .align @@ -55,29 +55,47 @@ __tmp_stack: __continue: #endif /* CONFIG_ZBOOT_ROM_MMC || CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI */ - b 1f -__atags:@ tag #1 - .long 12 @ tag->hdr.size = tag_size(tag_core); - .long 0x54410001 @ tag->hdr.tag = ATAG_CORE; - .long 0 @ tag->u.core.flags = 0; - .long 0 @ tag->u.core.pagesize = 0; - .long 0 @ tag->u.core.rootdev = 0; - @ tag #2 - .long 8 @ tag->hdr.size = tag_size(tag_mem32); - .long 0x54410002 @ tag->hdr.tag = ATAG_MEM; - .long CONFIG_MEMORY_SIZE @ tag->u.mem.size = CONFIG_MEMORY_SIZE; - .long CONFIG_MEMORY_START @ @ tag->u.mem.start = CONFIG_MEMORY_START; - @ tag #3 - .long 0 @ tag->hdr.size = 0 - .long 0 @ tag->hdr.tag = ATAG_NONE; -1: + adr r0, dtb_info + ldmia r0, {r1, r3, r4, r5, r7} - /* Set board ID necessary for boot */ - ldr r7, 1f @ Set machine type register - adr r8, __atags @ Set atag register + sub r0, r0, r1 @ calculate the delta offset + add r5, r5, r0 @ _edata + + ldr lr, [r5, #0] @ check if valid DTB is present + cmp lr, r3 + bne 0f + + add r9, r7, #31 @ rounded up to a multiple + bic r9, r9, #31 @ ... of 32 bytes + + add r6, r9, r5 @ copy from _edata + add r9, r9, r4 @ to MEMORY_START + +1: ldmdb r6!, {r0 - r3, r10 - r12, lr} + cmp r6, r5 + stmdb r9!, {r0 - r3, r10 - r12, lr} + bhi 1b + + /* Success: Zero board ID, pointer to start of memory for atag/dtb */ + mov r7, #0 + mov r8, r4 b 2f -1 : .long MACH_TYPE + .align 2 +dtb_info: + .word dtb_info +#ifndef __ARMEB__ + .word 0xedfe0dd0 @ sig is 0xd00dfeed big endian +#else + .word 0xd00dfeed +#endif + .word MEMORY_START + .word _edata + .word 0x4000 @ maximum DTB size +0: + /* Failure: Zero board ID, NULL atag/dtb */ + mov r7, #0 + mov r8, #0 @ pass null pointer as atag 2 : #endif /* CONFIG_ZBOOT_ROM */ diff --git a/arch/arm/boot/compressed/head-vt8500.S b/arch/arm/boot/compressed/head-vt8500.S deleted file mode 100644 index 1dc1e21a3be..00000000000 --- a/arch/arm/boot/compressed/head-vt8500.S +++ /dev/null @@ -1,46 +0,0 @@ -/* - * linux/arch/arm/boot/compressed/head-vt8500.S - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * VIA VT8500 specific tweaks. This is merged into head.S by the linker. - * - */ - -#include <linux/linkage.h> -#include <asm/mach-types.h> - - .section ".start", "ax" - -__VT8500_start: - @ Compare the SCC ID register against a list of known values - ldr r1, .SCCID - ldr r3, [r1] - - @ VT8500 override - ldr r4, .VT8500SCC - cmp r3, r4 - ldreq r7, .ID_BV07 - beq .Lendvt8500 - - @ WM8505 override - ldr r4, .WM8505SCC - cmp r3, r4 - ldreq r7, .ID_8505 - beq .Lendvt8500 - - @ Otherwise, leave the bootloader's machine id untouched - -.SCCID: - .word 0xd8120000 -.VT8500SCC: - .word 0x34000102 -.WM8505SCC: - .word 0x34260103 - -.ID_BV07: - .word MACH_TYPE_BV07 -.ID_8505: - .word MACH_TYPE_WM8505_7IN_NETBOOK - -.Lendvt8500: diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index aa5ee49c5c5..6ab0599c02d 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -32,10 +32,3 @@ __XScale_start: bic r0, r0, #0x1000 @ clear Icache mcr p15, 0, r0, c1, c0, 0 -#ifdef CONFIG_ARCH_IXP2000 - mov r1, #-1 - mov r0, #0xd6000000 - str r1, [r0, #0x14] - str r1, [r0, #0x18] -#endif - diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index e95a5989602..3a8b32df6b3 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -9,7 +9,9 @@ * published by the Free Software Foundation. */ #include <linux/linkage.h> +#include <asm/assembler.h> + .arch armv7-a /* * Debugging stuff * @@ -43,7 +45,7 @@ #else -#include <mach/debug-macro.S> +#include CONFIG_DEBUG_LL_INCLUDE .macro writeb, ch, rb senduart \ch, \rb @@ -58,11 +60,6 @@ add \rb, \rb, #0x00010000 @ Ser1 #endif .endm -#elif defined(CONFIG_ARCH_S3C2410) - .macro loadsp, rb, tmp - mov \rb, #0x50000000 - add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT - .endm #else .macro loadsp, rb, tmp addruart \rb, \tmp @@ -132,10 +129,15 @@ start: .word start @ absolute load/run zImage address .word _edata @ zImage end address THUMB( .thumb ) -1: mov r7, r1 @ save architecture ID +1: + ARM_BE8( setend be ) @ go BE8 if compiled for BE8 + mrs r9, cpsr +#ifdef CONFIG_ARM_VIRT_EXT + bl __hyp_stub_install @ get into SVC mode, reversibly +#endif + mov r7, r1 @ save architecture ID mov r8, r2 @ save atags pointer -#ifndef __ARM_ARCH_2__ /* * Booting from Angel - need to enter SVC mode and disable * FIQs/IRQs (numeric definitions from angel arm.h source). @@ -148,13 +150,9 @@ start: ARM( swi 0x123456 ) @ angel_SWI_ARM THUMB( svc 0xab ) @ angel_SWI_THUMB not_angel: - mrs r2, cpsr @ turn off interrupts to - orr r2, r2, #0xc0 @ prevent angel from running - msr cpsr_c, r2 -#else - teqp pc, #0x0c000003 @ turn off interrupts -#endif - + safe_svcmode_maskall r0 + msr spsr_cxsf, r9 @ Save the CPU boot mode in + @ SPSR /* * Note that some cache flushing and other stuff may * be needed here - is there an Angel SWI call for this? @@ -176,7 +174,19 @@ not_angel: ldr r4, =zreladdr #endif - bl cache_on + /* + * Set up a page table only if it won't overwrite ourself. + * That means r4 < pc && r4 - 16k page directory > &_end. + * Given that r4 > &_end is most unfrequent, we add a rough + * additional 1MB of room for a possible appended DTB. + */ + mov r0, pc + cmp r0, r4 + ldrcc r0, LC0+32 + addcc r0, r0, pc + cmpcc r4, r0 + orrcc r4, r4, #1 @ remember we skipped cache_on + blcs cache_on restart: adr r0, LC0 ldmia r0, {r1, r2, r3, r6, r10, r11, r12} @@ -216,22 +226,121 @@ restart: adr r0, LC0 mov r10, r6 #endif + mov r5, #0 @ init dtb size to 0 +#ifdef CONFIG_ARM_APPENDED_DTB +/* + * r0 = delta + * r2 = BSS start + * r3 = BSS end + * r4 = final kernel address (possibly with LSB set) + * r5 = appended dtb size (still unknown) + * r6 = _edata + * r7 = architecture ID + * r8 = atags/device tree pointer + * r9 = size of decompressed image + * r10 = end of this image, including bss/stack/malloc space if non XIP + * r11 = GOT start + * r12 = GOT end + * sp = stack pointer + * + * if there are device trees (dtb) appended to zImage, advance r10 so that the + * dtb data will get relocated along with the kernel if necessary. + */ + + ldr lr, [r6, #0] +#ifndef __ARMEB__ + ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian +#else + ldr r1, =0xd00dfeed +#endif + cmp lr, r1 + bne dtb_check_done @ not found + +#ifdef CONFIG_ARM_ATAG_DTB_COMPAT + /* + * OK... Let's do some funky business here. + * If we do have a DTB appended to zImage, and we do have + * an ATAG list around, we want the later to be translated + * and folded into the former here. To be on the safe side, + * let's temporarily move the stack away into the malloc + * area. No GOT fixup has occurred yet, but none of the + * code we're about to call uses any global variable. + */ + add sp, sp, #0x10000 + stmfd sp!, {r0-r3, ip, lr} + mov r0, r8 + mov r1, r6 + sub r2, sp, r6 + bl atags_to_fdt + + /* + * If returned value is 1, there is no ATAG at the location + * pointed by r8. Try the typical 0x100 offset from start + * of RAM and hope for the best. + */ + cmp r0, #1 + sub r0, r4, #TEXT_OFFSET + bic r0, r0, #1 + add r0, r0, #0x100 + mov r1, r6 + sub r2, sp, r6 + bleq atags_to_fdt + + ldmfd sp!, {r0-r3, ip, lr} + sub sp, sp, #0x10000 +#endif + + mov r8, r6 @ use the appended device tree + + /* + * Make sure that the DTB doesn't end up in the final + * kernel's .bss area. To do so, we adjust the decompressed + * kernel size to compensate if that .bss size is larger + * than the relocated code. + */ + ldr r5, =_kernel_bss_size + adr r1, wont_overwrite + sub r1, r6, r1 + subs r1, r5, r1 + addhi r9, r9, r1 + + /* Get the dtb's size */ + ldr r5, [r6, #4] +#ifndef __ARMEB__ + /* convert r5 (dtb size) to little endian */ + eor r1, r5, r5, ror #16 + bic r1, r1, #0x00ff0000 + mov r5, r5, ror #8 + eor r5, r5, r1, lsr #8 +#endif + + /* preserve 64-bit alignment */ + add r5, r5, #7 + bic r5, r5, #7 + + /* relocate some pointers past the appended dtb */ + add r6, r6, r5 + add r10, r10, r5 + add sp, sp, r5 +dtb_check_done: +#endif + /* * Check to see if we will overwrite ourselves. - * r4 = final kernel address + * r4 = final kernel address (possibly with LSB set) * r9 = size of decompressed image * r10 = end of this image, including bss/stack/malloc space if non XIP * We basically want: * r4 - 16k page directory >= r10 -> OK - * r4 + image length <= current position (pc) -> OK + * r4 + image length <= address of wont_overwrite -> OK + * Note: the possible LSB in r4 is harmless here. */ add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 - ARM( cmp r10, pc ) - THUMB( mov lr, pc ) - THUMB( cmp r10, lr ) + adr r9, wont_overwrite + cmp r10, r9 bls wont_overwrite /* @@ -253,6 +362,20 @@ restart: adr r0, LC0 adr r5, restart bic r5, r5, #31 +/* Relocate the hyp vector base if necessary */ +#ifdef CONFIG_ARM_VIRT_EXT + mrs r0, spsr + and r0, r0, #MODE_MASK + cmp r0, #HYP_MODE + bne 1f + + bl __hyp_get_vectors + sub r0, r0, r5 + add r0, r0, r10 + bl __hyp_set_vectors +1: +#endif + sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... of 32 bytes @@ -272,7 +395,8 @@ restart: adr r0, LC0 add sp, sp, r6 #endif - bl cache_clean_flush + tst r4, #1 + bleq cache_clean_flush adr r0, BSYM(restart) add r0, r0, r6 @@ -284,15 +408,17 @@ wont_overwrite: * r0 = delta * r2 = BSS start * r3 = BSS end - * r4 = kernel execution address + * r4 = kernel execution address (possibly with LSB set) + * r5 = appended dtb size (0 if not present) * r7 = architecture ID * r8 = atags pointer * r11 = GOT start * r12 = GOT end * sp = stack pointer */ - teq r0, #0 + orrs r1, r0, r5 beq not_relocated + add r11, r11, r0 add r12, r12, r0 @@ -307,12 +433,21 @@ wont_overwrite: /* * Relocate all entries in the GOT table. + * Bump bss entries to _edata + dtb size */ 1: ldr r1, [r11, #0] @ relocate entries in the GOT - add r1, r1, r0 @ table. This fixes up the - str r1, [r11], #4 @ C references. + add r1, r1, r0 @ This fixes up C references + cmp r1, r2 @ if entry >= bss_start && + cmphs r3, r1 @ bss_end > entry + addhi r1, r1, r5 @ entry += dtb size + str r1, [r11], #4 @ next entry cmp r11, r12 blo 1b + + /* bump our bss pointers too */ + add r2, r2, r5 + add r3, r3, r5 + #else /* @@ -336,6 +471,15 @@ not_relocated: mov r0, #0 cmp r2, r3 blo 1b + /* + * Did we skip the cache setup earlier? + * That is indicated by the LSB in r4. + * Do it now if so. + */ + tst r4, #1 + bic r4, r4, #1 + blne cache_on + /* * The C runtime environment should now be setup sufficiently. * Set up some pointers, and start decompressing. @@ -350,11 +494,29 @@ not_relocated: mov r0, #0 bl decompress_kernel bl cache_clean_flush bl cache_off - mov r0, #0 @ must be zero mov r1, r7 @ restore architecture number mov r2, r8 @ restore atags pointer - ARM( mov pc, r4 ) @ call kernel - THUMB( bx r4 ) @ entry point is always ARM + +#ifdef CONFIG_ARM_VIRT_EXT + mrs r0, spsr @ Get saved CPU boot mode + and r0, r0, #MODE_MASK + cmp r0, #HYP_MODE @ if not booted in HYP mode... + bne __enter_kernel @ boot kernel directly + + adr r12, .L__hyp_reentry_vectors_offset + ldr r0, [r12] + add r0, r0, r12 + + bl __hyp_set_vectors + __HVC(0) @ otherwise bounce to hyp mode + + b . @ should never be reached + + .align 2 +.L__hyp_reentry_vectors_offset: .long __hyp_reentry_vectors - . +#else + b __enter_kernel +#endif .align 2 .type LC0, #object @@ -366,6 +528,7 @@ LC0: .word LC0 @ r1 .word _got_start @ r11 .word _got_end @ ip .word .L_user_stack_end @ sp + .word _end - restart + 16384 + 1024*1024 .size LC0, . - LC0 #ifdef CONFIG_ARCH_RPC @@ -459,6 +622,12 @@ __armv3_mpu_cache_on: mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 mov pc, lr +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH +#define CB_BITS 0x08 +#else +#define CB_BITS 0x0c +#endif + __setup_mmu: sub r3, r4, #16384 @ Page directory size bic r3, r3, #0xff @ Align the pointer bic r3, r3, #0x3f00 @@ -470,17 +639,14 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size mov r9, r0, lsr #18 mov r9, r9, lsl #18 @ start of RAM add r10, r9, #0x10000000 @ a reasonable RAM size - mov r1, #0x12 - orr r1, r1, #3 << 10 + mov r1, #0x12 @ XN|U + section mapping + orr r1, r1, #3 << 10 @ AP=11 add r2, r3, #16384 1: cmp r1, r9 @ if virt > start of RAM -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - orrhs r1, r1, #0x08 @ set cacheable -#else - orrhs r1, r1, #0x0c @ set cacheable, bufferable -#endif - cmp r1, r10 @ if virt > end of RAM - bichs r1, r1, #0x0c @ clear cacheable, bufferable + cmphs r10, r1 @ && end of RAM > virt + bic r1, r1, #0x1c @ clear XN|U + C + B + orrlo r1, r1, #0x10 @ Set XN|U for non-RAM + orrhs r1, r1, r6 @ set RAM section settings str r1, [r0], #4 @ 1:1 mapping add r1, r1, #1048576 teq r0, r2 @@ -491,7 +657,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size * so there is no map overlap problem for up to 1 MB compressed kernel. * If the execution is in RAM then we would only be duplicating the above. */ - mov r1, #0x1e + orr r1, r6, #0x04 @ ensure B is set for this orr r1, r1, #3 << 10 mov r2, pc mov r2, r2, lsr #20 @@ -503,6 +669,15 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size mov pc, lr ENDPROC(__setup_mmu) +@ Enable unaligned access on v6, to allow better code generation +@ for the decompressor C code: +__armv6_mmu_cache_on: + mrc p15, 0, r0, c1, c0, 0 @ read SCTLR + bic r0, r0, #2 @ A (no unaligned access fault) + orr r0, r0, #1 << 22 @ U (v6 unaligned access model) + mcr p15, 0, r0, c1, c0, 0 @ write SCTLR + b __armv4_mmu_cache_on + __arm926ejs_mmu_cache_on: #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mov r0, #4 @ put dcache in WT mode @@ -512,6 +687,7 @@ __arm926ejs_mmu_cache_on: __armv4_mmu_cache_on: mov r12, lr #ifdef CONFIG_MMU + mov r6, #CB_BITS | 0x12 @ U bl __setup_mmu mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer @@ -519,9 +695,7 @@ __armv4_mmu_cache_on: mrc p15, 0, r0, c1, c0, 0 @ read control reg orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x0030 -#ifdef CONFIG_CPU_ENDIAN_BE8 - orr r0, r0, #1 << 25 @ big-endian page tables -#endif + ARM_BE8( orr r0, r0, #1 << 25 ) @ big-endian page tables bl __common_mmu_cache_on mov r0, #0 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs @@ -533,6 +707,7 @@ __armv7_mmu_cache_on: #ifdef CONFIG_MMU mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0 tst r11, #0xf @ VMSA + movne r6, #CB_BITS | 0x02 @ !XN blne __setup_mmu mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer @@ -540,17 +715,24 @@ __armv7_mmu_cache_on: mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs #endif mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #1 << 28 @ clear SCTLR.TRE orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer + bic r0, r0, #2 @ A (no unaligned access fault) + orr r0, r0, #1 << 22 @ U (v6 unaligned access model) + @ (needed for ARM1176) #ifdef CONFIG_MMU -#ifdef CONFIG_CPU_ENDIAN_BE8 - orr r0, r0, #1 << 25 @ big-endian page tables -#endif + ARM_BE8( orr r0, r0, #1 << 25 ) @ big-endian page tables + mrcne p15, 0, r6, c2, c0, 2 @ read ttb control reg orrne r0, r0, #1 @ MMU enabled - movne r1, #-1 + movne r1, #0xfffffffd @ domain 0 = client + bic r6, r6, #1 << 31 @ 32-bit translation system + bic r6, r6, #3 << 0 @ use only ttbr0 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer mcrne p15, 0, r1, c3, c0, 0 @ load domain access control + mcrne p15, 0, r6, c2, c0, 2 @ load ttb control #endif + mcr p15, 0, r0, c7, c5, 4 @ ISB mcr p15, 0, r0, c1, c0, 0 @ load control register mrc p15, 0, r0, c1, c0, 0 @ and read it back mov r0, #0 @@ -559,6 +741,7 @@ __armv7_mmu_cache_on: __fa526_cache_on: mov r12, lr + mov r6, #CB_BITS | 0x12 @ U bl __setup_mmu mov r0, #0 mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache @@ -571,18 +754,6 @@ __fa526_cache_on: mcr p15, 0, r0, c8, c7, 0 @ flush UTLB mov pc, r12 -__arm6_mmu_cache_on: - mov r12, lr - bl __setup_mmu - mov r0, #0 - mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 - mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 - mov r0, #0x30 - bl __common_mmu_cache_on - mov r0, #0 - mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 - mov pc, r12 - __common_mmu_cache_on: #ifndef CONFIG_THUMB2_KERNEL #ifndef DEBUG @@ -647,18 +818,8 @@ call_cache_fn: adr r12, proc_types .align 2 .type proc_types,#object proc_types: - .word 0x41560600 @ ARM6/610 - .word 0xffffffe0 - W(b) __arm6_mmu_cache_off @ works, but slow - W(b) __arm6_mmu_cache_off - mov pc, lr - THUMB( nop ) -@ b __arm6_mmu_cache_on @ untested -@ b __arm6_mmu_cache_off -@ b __armv3_mmu_cache_flush - - .word 0x00000000 @ old ARM ID - .word 0x0000f000 + .word 0x41000000 @ old ARM ID + .word 0xff00f000 mov pc, lr THUMB( nop ) mov pc, lr @@ -668,8 +829,10 @@ proc_types: .word 0x41007000 @ ARM7/710 .word 0xfff8fe00 - W(b) __arm7_mmu_cache_off - W(b) __arm7_mmu_cache_off + mov pc, lr + THUMB( nop ) + mov pc, lr + THUMB( nop ) mov pc, lr THUMB( nop ) @@ -776,7 +939,7 @@ proc_types: .word 0x0007b000 @ ARMv6 .word 0x000ff000 - W(b) __armv4_mmu_cache_on + W(b) __armv6_mmu_cache_on W(b) __armv4_mmu_cache_off W(b) __armv6_mmu_cache_flush @@ -868,21 +1031,6 @@ __armv7_mmu_cache_off: mcr p15, 0, r0, c7, c5, 4 @ ISB mov pc, r12 -__arm6_mmu_cache_off: - mov r0, #0x00000030 @ ARM6 control reg. - b __armv3_mmu_cache_off - -__arm7_mmu_cache_off: - mov r0, #0x00000070 @ ARM7 control reg. - b __armv3_mmu_cache_off - -__armv3_mmu_cache_off: - mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off - mov r0, #0 - mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 - mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 - mov pc, lr - /* * Clean and flush the cache to maintain consistency. * @@ -1111,6 +1259,25 @@ memdump: mov r12, r0 #endif .ltorg + +#ifdef CONFIG_ARM_VIRT_EXT +.align 5 +__hyp_reentry_vectors: + W(b) . @ reset + W(b) . @ undef + W(b) . @ svc + W(b) . @ pabort + W(b) . @ dabort + W(b) __enter_kernel @ hyp + W(b) . @ irq + W(b) . @ fiq +#endif /* CONFIG_ARM_VIRT_EXT */ + +__enter_kernel: + mov r0, #0 @ must be 0 + ARM( mov pc, r4 ) @ call kernel + THUMB( bx r4 ) @ entry point is always ARM + reloc_code_end: .align diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h new file mode 100644 index 00000000000..1f4e71876b0 --- /dev/null +++ b/arch/arm/boot/compressed/libfdt_env.h @@ -0,0 +1,15 @@ +#ifndef _ARM_LIBFDT_ENV_H +#define _ARM_LIBFDT_ENV_H + +#include <linux/types.h> +#include <linux/string.h> +#include <asm/byteorder.h> + +#define fdt16_to_cpu(x) be16_to_cpu(x) +#define cpu_to_fdt16(x) cpu_to_be16(x) +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) +#define fdt64_to_cpu(x) be64_to_cpu(x) +#define cpu_to_fdt64(x) cpu_to_be64(x) + +#endif diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 832d37236c5..d4f891f5699 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -18,19 +18,14 @@ unsigned int __machine_arch_type; -#define _LINUX_STRING_H_ - #include <linux/compiler.h> /* for inline */ -#include <linux/types.h> /* for size_t */ -#include <linux/stddef.h> /* for NULL */ +#include <linux/types.h> #include <linux/linkage.h> -#include <asm/string.h> - static void putstr(const char *ptr); extern void error(char *x); -#include <mach/uncompress.h> +#include CONFIG_UNCOMPRESS_INCLUDE #ifdef CONFIG_DEBUG_ICEDCC @@ -101,41 +96,6 @@ static void putstr(const char *ptr) flush(); } - -void *memcpy(void *__dest, __const void *__src, size_t __n) -{ - int i = 0; - unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; - - for (i = __n >> 3; i > 0; i--) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - - if (__n & 1 << 2) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - - if (__n & 1 << 1) { - *d++ = *s++; - *d++ = *s++; - } - - if (__n & 1) - *d++ = *s++; - - return __dest; -} - /* * gzip declarations */ @@ -167,6 +127,18 @@ asmlinkage void __div0(void) error("Attempting division by 0!"); } +unsigned long __stack_chk_guard; + +void __stack_chk_guard_setup(void) +{ + __stack_chk_guard = 0x000a0dff; +} + +void __stack_chk_fail(void) +{ + error("stack-protector: Kernel stack is corrupted\n"); +} + extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); @@ -177,6 +149,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, { int ret; + __stack_chk_guard_setup(); + output_data = (unsigned char *)output_start; free_mem_ptr = free_mem_ptr_p; free_mem_end_ptr = free_mem_ptr_end_p; diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c index b6f61d9a5a1..672ae95db5c 100644 --- a/arch/arm/boot/compressed/mmcif-sh7372.c +++ b/arch/arm/boot/compressed/mmcif-sh7372.c @@ -82,7 +82,7 @@ asmlinkage void mmc_loader(unsigned char *buf, unsigned long len) /* Disable clock to MMC hardware block */ - __raw_writel(__raw_readl(SMSTPCR3) & (1 << 12), SMSTPCR3); + __raw_writel(__raw_readl(SMSTPCR3) | (1 << 12), SMSTPCR3); mmc_update_progress(MMC_PROGRESS_DONE); } diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c deleted file mode 100644 index 465c54b6b12..00000000000 --- a/arch/arm/boot/compressed/ofw-shark.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * linux/arch/arm/boot/compressed/ofw-shark.c - * - * by Alexander Schulz - * - * This file is used to get some basic information - * about the memory layout of the shark we are running - * on. Memory is usually divided in blocks a 8 MB. - * And bootargs are copied from OpenFirmware. - */ - - -#include <linux/kernel.h> -#include <linux/types.h> -#include <asm/setup.h> -#include <asm/page.h> - - -asmlinkage void -create_params (unsigned long *buffer) -{ - /* Is there a better address? Also change in mach-shark/core.c */ - struct tag *tag = (struct tag *) 0x08003000; - int j,i,m,k,nr_banks,size; - unsigned char *c; - - k = 0; - - /* Head of the taglist */ - tag->hdr.tag = ATAG_CORE; - tag->hdr.size = tag_size(tag_core); - tag->u.core.flags = 1; - tag->u.core.pagesize = PAGE_SIZE; - tag->u.core.rootdev = 0; - - /* Build up one tagged block for each memory region */ - size=0; - nr_banks=(unsigned int) buffer[0]; - for (j=0;j<nr_banks;j++){ - /* search the lowest address and put it into the next entry */ - /* not a fast sort algorithm, but there are at most 8 entries */ - /* and this is used only once anyway */ - m=0xffffffff; - for (i=0;i<(unsigned int) buffer[0];i++){ - if (buffer[2*i+1]<m) { - m=buffer[2*i+1]; - k=i; - } - } - - tag = tag_next(tag); - tag->hdr.tag = ATAG_MEM; - tag->hdr.size = tag_size(tag_mem32); - tag->u.mem.size = buffer[2*k+2]; - tag->u.mem.start = buffer[2*k+1]; - - size += buffer[2*k+2]; - - buffer[2*k+1]=0xffffffff; /* mark as copied */ - } - - /* The command line */ - tag = tag_next(tag); - tag->hdr.tag = ATAG_CMDLINE; - - c=(unsigned char *)(&buffer[34]); - j=0; - while (*c) tag->u.cmdline.cmdline[j++]=*c++; - - tag->u.cmdline.cmdline[j]=0; - tag->hdr.size = (j + 7 + sizeof(struct tag_header)) >> 2; - - /* Hardware revision */ - tag = tag_next(tag); - tag->hdr.tag = ATAG_REVISION; - tag->hdr.size = tag_size(tag_revision); - tag->u.revision.rev = ((unsigned char) buffer[33])-'0'; - - /* End of the taglist */ - tag = tag_next(tag); - tag->hdr.tag = 0; - tag->hdr.size = 0; -} - - -typedef int (*ofw_handle_t)(void *); - -/* Everything below is called with a wrong MMU setting. - * This means: no string constants, no initialization of - * arrays, no global variables! This is ugly but I didn't - * want to write this in assembler :-) - */ - -int -of_decode_int(const unsigned char *p) -{ - unsigned int i = *p++ << 8; - i = (i + *p++) << 8; - i = (i + *p++) << 8; - return (i + *p); -} - -int -OF_finddevice(ofw_handle_t openfirmware, char *name) -{ - unsigned int args[8]; - char service[12]; - - service[0]='f'; - service[1]='i'; - service[2]='n'; - service[3]='d'; - service[4]='d'; - service[5]='e'; - service[6]='v'; - service[7]='i'; - service[8]='c'; - service[9]='e'; - service[10]='\0'; - - args[0]=(unsigned int)service; - args[1]=1; - args[2]=1; - args[3]=(unsigned int)name; - - if (openfirmware(args) == -1) - return -1; - return args[4]; -} - -int -OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop) -{ - unsigned int args[8]; - char service[12]; - - service[0]='g'; - service[1]='e'; - service[2]='t'; - service[3]='p'; - service[4]='r'; - service[5]='o'; - service[6]='p'; - service[7]='l'; - service[8]='e'; - service[9]='n'; - service[10]='\0'; - - args[0] = (unsigned int)service; - args[1] = 2; - args[2] = 1; - args[3] = (unsigned int)handle; - args[4] = (unsigned int)prop; - - if (openfirmware(args) == -1) - return -1; - return args[5]; -} - -int -OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen) -{ - unsigned int args[8]; - char service[8]; - - service[0]='g'; - service[1]='e'; - service[2]='t'; - service[3]='p'; - service[4]='r'; - service[5]='o'; - service[6]='p'; - service[7]='\0'; - - args[0] = (unsigned int)service; - args[1] = 4; - args[2] = 1; - args[3] = (unsigned int)handle; - args[4] = (unsigned int)prop; - args[5] = (unsigned int)buf; - args[6] = buflen; - - if (openfirmware(args) == -1) - return -1; - return args[7]; -} - -asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) -{ - int phandle,i,mem_len,buffer[32]; - char temp[15]; - - temp[0]='/'; - temp[1]='m'; - temp[2]='e'; - temp[3]='m'; - temp[4]='o'; - temp[5]='r'; - temp[6]='y'; - temp[7]='\0'; - - phandle=OF_finddevice(o,temp); - - temp[0]='r'; - temp[1]='e'; - temp[2]='g'; - temp[3]='\0'; - - mem_len = OF_getproplen(o,phandle, temp); - OF_getprop(o,phandle, temp, buffer, mem_len); - *nomr=mem_len >> 3; - - for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]); - - temp[0]='/'; - temp[1]='c'; - temp[2]='h'; - temp[3]='o'; - temp[4]='s'; - temp[5]='e'; - temp[6]='n'; - temp[7]='\0'; - - phandle=OF_finddevice(o,temp); - - temp[0]='b'; - temp[1]='o'; - temp[2]='o'; - temp[3]='t'; - temp[4]='a'; - temp[5]='r'; - temp[6]='g'; - temp[7]='s'; - temp[8]='\0'; - - mem_len = OF_getproplen(o,phandle, temp); - OF_getprop(o,phandle, temp, buffer, mem_len); - if (mem_len > 128) mem_len=128; - for (i=0; i<=mem_len/4; i++) pointer[i+33]=buffer[i]; - pointer[i+33]=0; - - temp[0]='/'; - temp[1]='\0'; - phandle=OF_finddevice(o,temp); - temp[0]='b'; - temp[1]='a'; - temp[2]='n'; - temp[3]='n'; - temp[4]='e'; - temp[5]='r'; - temp[6]='-'; - temp[7]='n'; - temp[8]='a'; - temp[9]='m'; - temp[10]='e'; - temp[11]='\0'; - mem_len = OF_getproplen(o,phandle, temp); - OF_getprop(o,phandle, temp, buffer, mem_len); - * ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2]; -} diff --git a/arch/arm/boot/compressed/piggy.lz4.S b/arch/arm/boot/compressed/piggy.lz4.S new file mode 100644 index 00000000000..3d9a575618a --- /dev/null +++ b/arch/arm/boot/compressed/piggy.lz4.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/boot/compressed/piggy.lz4" + .globl input_data_end +input_data_end: diff --git a/arch/arm/boot/compressed/piggy.xzkern.S b/arch/arm/boot/compressed/piggy.xzkern.S new file mode 100644 index 00000000000..5703f300d02 --- /dev/null +++ b/arch/arm/boot/compressed/piggy.xzkern.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/boot/compressed/piggy.xzkern" + .globl input_data_end +input_data_end: diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c index d403a8b24d7..d279294f238 100644 --- a/arch/arm/boot/compressed/sdhi-sh7372.c +++ b/arch/arm/boot/compressed/sdhi-sh7372.c @@ -85,7 +85,7 @@ asmlinkage void mmc_loader(unsigned short *buf, unsigned long len) goto err; /* Disable clock to SDHI1 hardware block */ - __raw_writel(__raw_readl(SMSTPCR3) & (1 << 13), SMSTPCR3); + __raw_writel(__raw_readl(SMSTPCR3) | (1 << 13), SMSTPCR3); mmc_update_progress(MMC_PROGRESS_DONE); diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c new file mode 100644 index 00000000000..36e53ef9200 --- /dev/null +++ b/arch/arm/boot/compressed/string.c @@ -0,0 +1,127 @@ +/* + * arch/arm/boot/compressed/string.c + * + * Small subset of simple string routines + */ + +#include <linux/string.h> + +void *memcpy(void *__dest, __const void *__src, size_t __n) +{ + int i = 0; + unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; + + for (i = __n >> 3; i > 0; i--) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 2) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 1) { + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1) + *d++ = *s++; + + return __dest; +} + +void *memmove(void *__dest, __const void *__src, size_t count) +{ + unsigned char *d = __dest; + const unsigned char *s = __src; + + if (__dest == __src) + return __dest; + + if (__dest < __src) + return memcpy(__dest, __src, count); + + while (count--) + d[count] = s[count]; + return __dest; +} + +size_t strlen(const char *s) +{ + const char *sc = s; + + while (*sc != '\0') + sc++; + return sc - s; +} + +int memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count; + int res = 0; + + while (su1 < end) { + res = *su1++ - *su2++; + if (res) + break; + } + return res; +} + +int strcmp(const char *cs, const char *ct) +{ + unsigned char c1, c2; + int res = 0; + + do { + c1 = *cs++; + c2 = *ct++; + res = c1 - c2; + if (res) + break; + } while (c1); + return res; +} + +void *memchr(const void *s, int c, size_t count) +{ + const unsigned char *p = s; + + while (count--) + if ((unsigned char)c == *p++) + return (void *)(p - 1); + return NULL; +} + +char *strchr(const char *s, int c) +{ + while (*s != (char)c) + if (*s++ == '\0') + return NULL; + return (char *)s; +} + +#undef memset + +void *memset(void *s, int c, size_t count) +{ + char *xs = s; + while (count--) + *xs++ = c; + return s; +} + +void __memzero(void *s, size_t count) +{ + memset(s, 0, count); +} diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 4e728834a1b..4919f2ac8b8 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -51,6 +51,10 @@ SECTIONS _got_start = .; .got : { *(.got) } _got_end = .; + + /* ensure the zImage file size is always a multiple of 64 bits */ + /* (without a dummy byte, ld just ignores the empty section) */ + .pad : { BYTE(0); . = ALIGN(8); } _edata = .; . = BSS_START; |
