diff options
Diffstat (limited to 'arch/arm/boot')
24 files changed, 2458 insertions, 0 deletions
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile new file mode 100644 index 000000000000..937a353bc37c --- /dev/null +++ b/arch/arm/boot/Makefile | |||
@@ -0,0 +1,91 @@ | |||
1 | # | ||
2 | # arch/arm/boot/Makefile | ||
3 | # | ||
4 | # This file is subject to the terms and conditions of the GNU General Public | ||
5 | # License. See the file "COPYING" in the main directory of this archive | ||
6 | # for more details. | ||
7 | # | ||
8 | # Copyright (C) 1995-2002 Russell King | ||
9 | # | ||
10 | |||
11 | MKIMAGE := $(srctree)/scripts/mkuboot.sh | ||
12 | |||
13 | ifneq ($(MACHINE),) | ||
14 | include $(srctree)/$(MACHINE)/Makefile.boot | ||
15 | endif | ||
16 | |||
17 | # Note: the following conditions must always be true: | ||
18 | # ZRELADDR == virt_to_phys(TEXTADDR) | ||
19 | # PARAMS_PHYS must be within 4MB of ZRELADDR | ||
20 | # INITRD_PHYS must be in RAM | ||
21 | ZRELADDR := $(zreladdr-y) | ||
22 | PARAMS_PHYS := $(params_phys-y) | ||
23 | INITRD_PHYS := $(initrd_phys-y) | ||
24 | |||
25 | export ZRELADDR INITRD_PHYS PARAMS_PHYS | ||
26 | |||
27 | targets := Image zImage xipImage bootpImage uImage | ||
28 | |||
29 | ifeq ($(CONFIG_XIP_KERNEL),y) | ||
30 | |||
31 | $(obj)/xipImage: vmlinux FORCE | ||
32 | $(call if_changed,objcopy) | ||
33 | @echo ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))' | ||
34 | |||
35 | $(obj)/Image $(obj)/zImage: FORCE | ||
36 | @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)' | ||
37 | @echo 'Only the xipImage target is available in this case' | ||
38 | @false | ||
39 | |||
40 | else | ||
41 | |||
42 | $(obj)/xipImage: FORCE | ||
43 | @echo 'Kernel not configured for XIP (CONFIG_XIP_KERNEL!=y)' | ||
44 | @false | ||
45 | |||
46 | $(obj)/Image: vmlinux FORCE | ||
47 | $(call if_changed,objcopy) | ||
48 | @echo ' Kernel: $@ is ready' | ||
49 | |||
50 | $(obj)/compressed/vmlinux: $(obj)/Image FORCE | ||
51 | $(Q)$(MAKE) $(build)=$(obj)/compressed $@ | ||
52 | |||
53 | $(obj)/zImage: $(obj)/compressed/vmlinux FORCE | ||
54 | $(call if_changed,objcopy) | ||
55 | @echo ' Kernel: $@ is ready' | ||
56 | |||
57 | endif | ||
58 | |||
59 | quiet_cmd_uimage = UIMAGE $@ | ||
60 | cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ | ||
61 | -C none -a $(ZRELADDR) -e $(ZRELADDR) \ | ||
62 | -n 'Linux-$(KERNELRELEASE)' -d $< $@ | ||
63 | |||
64 | $(obj)/uImage: $(obj)/zImage FORCE | ||
65 | $(call if_changed,uimage) | ||
66 | @echo ' Image $@ is ready' | ||
67 | |||
68 | $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE | ||
69 | $(Q)$(MAKE) $(build)=$(obj)/bootp $@ | ||
70 | @: | ||
71 | |||
72 | $(obj)/bootpImage: $(obj)/bootp/bootp FORCE | ||
73 | $(call if_changed,objcopy) | ||
74 | @echo ' Kernel: $@ is ready' | ||
75 | |||
76 | .PHONY: initrd FORCE | ||
77 | initrd: | ||
78 | @test "$(INITRD_PHYS)" != "" || \ | ||
79 | (echo This machine does not support INITRD; exit -1) | ||
80 | @test "$(INITRD)" != "" || \ | ||
81 | (echo You must specify INITRD; exit -1) | ||
82 | |||
83 | install: $(obj)/Image | ||
84 | $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ | ||
85 | $(obj)/Image System.map "$(INSTALL_PATH)" | ||
86 | |||
87 | zinstall: $(obj)/zImage | ||
88 | $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ | ||
89 | $(obj)/zImage System.map "$(INSTALL_PATH)" | ||
90 | |||
91 | subdir- := bootp compressed | ||
diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile new file mode 100644 index 000000000000..8e8879b6b3d7 --- /dev/null +++ b/arch/arm/boot/bootp/Makefile | |||
@@ -0,0 +1,24 @@ | |||
1 | # | ||
2 | # linux/arch/arm/boot/bootp/Makefile | ||
3 | # | ||
4 | |||
5 | LDFLAGS_bootp :=-p --no-undefined -X \ | ||
6 | --defsym initrd_phys=$(INITRD_PHYS) \ | ||
7 | --defsym params_phys=$(PARAMS_PHYS) -T | ||
8 | AFLAGS_initrd.o :=-DINITRD=\"$(INITRD)\" | ||
9 | |||
10 | targets := bootp init.o kernel.o initrd.o | ||
11 | |||
12 | # Note that bootp.lds picks up kernel.o and initrd.o | ||
13 | $(obj)/bootp: $(src)/bootp.lds $(addprefix $(obj)/,init.o kernel.o initrd.o) FORCE | ||
14 | $(call if_changed,ld) | ||
15 | @: | ||
16 | |||
17 | # kernel.o and initrd.o includes a binary image using | ||
18 | # .incbin, a dependency which is not tracked automatically | ||
19 | |||
20 | $(obj)/kernel.o: arch/arm/boot/zImage FORCE | ||
21 | |||
22 | $(obj)/initrd.o: $(INITRD) FORCE | ||
23 | |||
24 | .PHONY: $(INITRD) FORCE | ||
diff --git a/arch/arm/boot/bootp/bootp.lds b/arch/arm/boot/bootp/bootp.lds new file mode 100644 index 000000000000..8e3d81ce695e --- /dev/null +++ b/arch/arm/boot/bootp/bootp.lds | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/bootp/bootp.lds | ||
3 | * | ||
4 | * Copyright (C) 2000-2002 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | OUTPUT_ARCH(arm) | ||
11 | ENTRY(_start) | ||
12 | SECTIONS | ||
13 | { | ||
14 | . = 0; | ||
15 | .text : { | ||
16 | _stext = .; | ||
17 | *(.start) | ||
18 | *(.text) | ||
19 | initrd_size = initrd_end - initrd_start; | ||
20 | _etext = .; | ||
21 | } | ||
22 | |||
23 | .stab 0 : { *(.stab) } | ||
24 | .stabstr 0 : { *(.stabstr) } | ||
25 | .stab.excl 0 : { *(.stab.excl) } | ||
26 | .stab.exclstr 0 : { *(.stab.exclstr) } | ||
27 | .stab.index 0 : { *(.stab.index) } | ||
28 | .stab.indexstr 0 : { *(.stab.indexstr) } | ||
29 | .comment 0 : { *(.comment) } | ||
30 | } | ||
diff --git a/arch/arm/boot/bootp/init.S b/arch/arm/boot/bootp/init.S new file mode 100644 index 000000000000..df7bc7068d0f --- /dev/null +++ b/arch/arm/boot/bootp/init.S | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/bootp/init.S | ||
3 | * | ||
4 | * Copyright (C) 2000-2003 Russell King. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * "Header" file for splitting kernel + initrd. Note that we pass | ||
11 | * r0 through to r3 straight through. | ||
12 | * | ||
13 | * This demonstrates how to append code to the start of the kernel | ||
14 | * zImage, and boot the kernel without copying it around. This | ||
15 | * example would be simpler; if we didn't have an object of unknown | ||
16 | * size immediately following the kernel, we could build this into | ||
17 | * a binary blob, and concatenate the zImage using the cat command. | ||
18 | */ | ||
19 | .section .start,#alloc,#execinstr | ||
20 | .type _start, #function | ||
21 | .globl _start | ||
22 | |||
23 | _start: add lr, pc, #-0x8 @ lr = current load addr | ||
24 | adr r13, data | ||
25 | ldmia r13!, {r4-r6} @ r5 = dest, r6 = length | ||
26 | add r4, r4, lr @ r4 = initrd_start + load addr | ||
27 | bl move @ move the initrd | ||
28 | |||
29 | /* | ||
30 | * Setup the initrd parameters to pass to the kernel. This can only be | ||
31 | * passed in via the tagged list. | ||
32 | */ | ||
33 | ldmia r13, {r5-r9} @ get size and addr of initrd | ||
34 | @ r5 = ATAG_CORE | ||
35 | @ r6 = ATAG_INITRD2 | ||
36 | @ r7 = initrd start | ||
37 | @ r8 = initrd end | ||
38 | @ r9 = param_struct address | ||
39 | |||
40 | ldr r10, [r9, #4] @ get first tag | ||
41 | teq r10, r5 @ is it ATAG_CORE? | ||
42 | /* | ||
43 | * If we didn't find a valid tag list, create a dummy ATAG_CORE entry. | ||
44 | */ | ||
45 | movne r10, #0 @ terminator | ||
46 | movne r4, #2 @ Size of this entry (2 words) | ||
47 | stmneia r9, {r4, r5, r10} @ Size, ATAG_CORE, terminator | ||
48 | |||
49 | /* | ||
50 | * find the end of the tag list, and then add an INITRD tag on the end. | ||
51 | * If there is already an INITRD tag, then we ignore it; the last INITRD | ||
52 | * tag takes precidence. | ||
53 | */ | ||
54 | taglist: ldr r10, [r9, #0] @ tag length | ||
55 | teq r10, #0 @ last tag (zero length)? | ||
56 | addne r9, r9, r10, lsl #2 | ||
57 | bne taglist | ||
58 | |||
59 | mov r5, #4 @ Size of initrd tag (4 words) | ||
60 | stmia r9, {r5, r6, r7, r8, r10} | ||
61 | b kernel_start @ call kernel | ||
62 | |||
63 | /* | ||
64 | * Move the block of memory length r6 from address r4 to address r5 | ||
65 | */ | ||
66 | move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time | ||
67 | stmia r5!, {r7 - r10} | ||
68 | ldmia r4!, {r7 - r10} | ||
69 | stmia r5!, {r7 - r10} | ||
70 | subs r6, r6, #8 * 4 | ||
71 | bcs move | ||
72 | mov pc, lr | ||
73 | |||
74 | .size _start, . - _start | ||
75 | |||
76 | .type data,#object | ||
77 | data: .word initrd_start @ source initrd address | ||
78 | .word initrd_phys @ destination initrd address | ||
79 | .word initrd_size @ initrd size | ||
80 | |||
81 | .word 0x54410001 @ r5 = ATAG_CORE | ||
82 | .word 0x54420005 @ r6 = ATAG_INITRD2 | ||
83 | .word initrd_phys @ r7 | ||
84 | .word initrd_size @ r8 | ||
85 | .word params_phys @ r9 | ||
86 | .size data, . - data | ||
diff --git a/arch/arm/boot/bootp/initrd.S b/arch/arm/boot/bootp/initrd.S new file mode 100644 index 000000000000..d81ea183785c --- /dev/null +++ b/arch/arm/boot/bootp/initrd.S | |||
@@ -0,0 +1,6 @@ | |||
1 | .type initrd_start,#object | ||
2 | .globl initrd_start | ||
3 | initrd_start: | ||
4 | .incbin INITRD | ||
5 | .globl initrd_end | ||
6 | initrd_end: | ||
diff --git a/arch/arm/boot/bootp/kernel.S b/arch/arm/boot/bootp/kernel.S new file mode 100644 index 000000000000..b87a25c7ef88 --- /dev/null +++ b/arch/arm/boot/bootp/kernel.S | |||
@@ -0,0 +1,6 @@ | |||
1 | .globl kernel_start | ||
2 | kernel_start: | ||
3 | .incbin "arch/arm/boot/zImage" | ||
4 | .globl kernel_end | ||
5 | kernel_end: | ||
6 | .align 2 | ||
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile new file mode 100644 index 000000000000..6b505ce41a75 --- /dev/null +++ b/arch/arm/boot/compressed/Makefile | |||
@@ -0,0 +1,114 @@ | |||
1 | # | ||
2 | # linux/arch/arm/boot/compressed/Makefile | ||
3 | # | ||
4 | # create a compressed vmlinuz image from the original vmlinux | ||
5 | # | ||
6 | |||
7 | HEAD = head.o | ||
8 | OBJS = misc.o | ||
9 | FONTC = drivers/video/console/font_acorn_8x8.c | ||
10 | |||
11 | FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o) | ||
12 | |||
13 | # | ||
14 | # Architecture dependencies | ||
15 | # | ||
16 | ifeq ($(CONFIG_ARCH_ACORN),y) | ||
17 | OBJS += ll_char_wr.o $(FONT) | ||
18 | endif | ||
19 | |||
20 | ifeq ($(CONFIG_ARCH_SHARK),y) | ||
21 | OBJS += head-shark.o ofw-shark.o | ||
22 | endif | ||
23 | |||
24 | ifeq ($(CONFIG_ARCH_CAMELOT),y) | ||
25 | OBJS += head-epxa10db.o | ||
26 | endif | ||
27 | |||
28 | ifeq ($(CONFIG_ARCH_L7200),y) | ||
29 | OBJS += head-l7200.o | ||
30 | endif | ||
31 | |||
32 | ifeq ($(CONFIG_ARCH_CLPS7500),y) | ||
33 | HEAD = head-clps7500.o | ||
34 | endif | ||
35 | |||
36 | ifeq ($(CONFIG_ARCH_P720T),y) | ||
37 | # Borrow this code from SA1100 | ||
38 | OBJS += head-sa1100.o | ||
39 | endif | ||
40 | |||
41 | ifeq ($(CONFIG_ARCH_SA1100),y) | ||
42 | OBJS += head-sa1100.o | ||
43 | endif | ||
44 | |||
45 | ifeq ($(CONFIG_CPU_XSCALE),y) | ||
46 | OBJS += head-xscale.o | ||
47 | endif | ||
48 | |||
49 | ifeq ($(CONFIG_PXA_SHARPSL),y) | ||
50 | OBJS += head-sharpsl.o | ||
51 | endif | ||
52 | |||
53 | ifeq ($(CONFIG_DEBUG_ICEDCC),y) | ||
54 | OBJS += ice-dcc.o | ||
55 | endif | ||
56 | |||
57 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) | ||
58 | OBJS += big-endian.o | ||
59 | endif | ||
60 | |||
61 | # | ||
62 | # We now have a PIC decompressor implementation. Decompressors running | ||
63 | # from RAM should not define ZTEXTADDR. Decompressors running directly | ||
64 | # from ROM or Flash must define ZTEXTADDR (preferably via the config) | ||
65 | # FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK | ||
66 | ifeq ($(CONFIG_ZBOOT_ROM),y) | ||
67 | ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) | ||
68 | ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) | ||
69 | else | ||
70 | ZTEXTADDR := 0 | ||
71 | ZBSSADDR := ALIGN(4) | ||
72 | endif | ||
73 | |||
74 | SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ | ||
75 | |||
76 | targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \ | ||
77 | head.o misc.o $(OBJS) | ||
78 | EXTRA_CFLAGS := -fpic | ||
79 | EXTRA_AFLAGS := | ||
80 | |||
81 | # Supply ZRELADDR, INITRD_PHYS and PARAMS_PHYS to the decompressor via | ||
82 | # linker symbols. We only define initrd_phys and params_phys if the | ||
83 | # machine class defined the corresponding makefile variable. | ||
84 | LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) | ||
85 | ifneq ($(INITRD_PHYS),) | ||
86 | LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS) | ||
87 | endif | ||
88 | ifneq ($(PARAMS_PHYS),) | ||
89 | LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) | ||
90 | endif | ||
91 | LDFLAGS_vmlinux += -p --no-undefined -X \ | ||
92 | $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T | ||
93 | |||
94 | # Don't allow any static data in misc.o, which | ||
95 | # would otherwise mess up our GOT table | ||
96 | CFLAGS_misc.o := -Dstatic= | ||
97 | |||
98 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \ | ||
99 | $(addprefix $(obj)/, $(OBJS)) FORCE | ||
100 | $(call if_changed,ld) | ||
101 | @: | ||
102 | |||
103 | $(obj)/piggy.gz: $(obj)/../Image FORCE | ||
104 | $(call if_changed,gzip) | ||
105 | |||
106 | $(obj)/piggy.o: $(obj)/piggy.gz FORCE | ||
107 | |||
108 | CFLAGS_font_acorn_8x8.o := -Dstatic= | ||
109 | |||
110 | $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config | ||
111 | @sed "$(SEDFLAGS)" < $< > $@ | ||
112 | |||
113 | $(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c | ||
114 | |||
diff --git a/arch/arm/boot/compressed/Makefile.debug b/arch/arm/boot/compressed/Makefile.debug new file mode 100644 index 000000000000..491a037b2973 --- /dev/null +++ b/arch/arm/boot/compressed/Makefile.debug | |||
@@ -0,0 +1,23 @@ | |||
1 | # | ||
2 | # linux/arch/arm/boot/compressed/Makefile | ||
3 | # | ||
4 | # create a compressed vmlinux image from the original vmlinux | ||
5 | # | ||
6 | |||
7 | COMPRESSED_EXTRA=../../lib/ll_char_wr.o | ||
8 | OBJECTS=misc-debug.o ll_char_wr.aout.o | ||
9 | |||
10 | CFLAGS=-D__KERNEL__ -O2 -DSTDC_HEADERS -DSTANDALONE_DEBUG -Wall -I../../../../include -c | ||
11 | |||
12 | test-gzip: piggy.aout.o $(OBJECTS) | ||
13 | $(CC) -o $@ $(OBJECTS) piggy.aout.o | ||
14 | |||
15 | misc-debug.o: misc.c | ||
16 | $(CC) $(CFLAGS) -o $@ misc.c | ||
17 | |||
18 | piggy.aout.o: piggy.o | ||
19 | arm-linuxelf-objcopy --change-leading-char -I elf32-arm -O arm-aout32-linux piggy.o piggy.aout.o | ||
20 | |||
21 | ll_char_wr.aout.o: $(COMPRESSED_EXTRA) | ||
22 | arm-linuxelf-objcopy --change-leading-char -I elf32-arm -O arm-aout32-linux $(COMPRESSED_EXTRA) ll_char_wr.aout.o | ||
23 | |||
diff --git a/arch/arm/boot/compressed/big-endian.S b/arch/arm/boot/compressed/big-endian.S new file mode 100644 index 000000000000..25ab26f1c6f0 --- /dev/null +++ b/arch/arm/boot/compressed/big-endian.S | |||
@@ -0,0 +1,13 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/big-endian.S | ||
3 | * | ||
4 | * Switch CPU into big endian mode. | ||
5 | * Author: Nicolas Pitre | ||
6 | */ | ||
7 | |||
8 | .section ".start", #alloc, #execinstr | ||
9 | |||
10 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
11 | orr r0, r0, #(1 << 7) @ enable big endian mode | ||
12 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | ||
13 | |||
diff --git a/arch/arm/boot/compressed/head-clps7500.S b/arch/arm/boot/compressed/head-clps7500.S new file mode 100644 index 000000000000..4a8a689d15e6 --- /dev/null +++ b/arch/arm/boot/compressed/head-clps7500.S | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head.S | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000, 2001 Nexus Electronics Ltd | ||
5 | */ | ||
6 | |||
7 | #include <linux/config.h> | ||
8 | |||
9 | /* There are three different ways the kernel can be | ||
10 | booted on a 7500 system: from Angel (loaded in RAM), from | ||
11 | 16-bit ROM or from 32-bit Flash. Luckily, a single kernel | ||
12 | image does for them all. */ | ||
13 | /* This branch is taken if the CPU memory width matches the | ||
14 | actual device in use. The default at power on is 16 bits | ||
15 | so we must be prepared for a mismatch. */ | ||
16 | .section ".start", "ax" | ||
17 | 2: | ||
18 | b 1f | ||
19 | .word 0xffff | ||
20 | .word 0xb632 @ mov r11, #0x03200000 | ||
21 | .word 0xe3a0 | ||
22 | .word 0x0000 @ mov r0, #0 | ||
23 | .word 0xe3a0 | ||
24 | .word 0x0080 @ strb r0, [r11, #0x80] | ||
25 | .word 0xe5cb | ||
26 | .word 0xf000 @ mov pc, #0 | ||
27 | .word 0xe3a0 | ||
28 | 1: | ||
29 | adr r1, 2b | ||
30 | teq r1, #0 | ||
31 | bne .Langel | ||
32 | /* This is a direct-from-ROM boot. Copy the kernel into | ||
33 | RAM and run it there. */ | ||
34 | mov r0, #0x30 | ||
35 | mcr p15, 0, r0, c1, c0, 0 | ||
36 | mov r0, #0x13 | ||
37 | msr cpsr_cxsf, r0 | ||
38 | mov r12, #0x03000000 @ point to LEDs | ||
39 | orr r12, r12, #0x00020000 | ||
40 | orr r12, r12, #0xba00 | ||
41 | mov r0, #0x5500 | ||
42 | str r0, [r12] | ||
43 | mov r0, #0x10000000 | ||
44 | orr r0, r0, #0x8000 | ||
45 | mov r4, r0 | ||
46 | ldr r2, =_end | ||
47 | 2: | ||
48 | ldr r3, [r1], #4 | ||
49 | str r3, [r0], #4 | ||
50 | teq r0, r2 | ||
51 | bne 2b | ||
52 | mov r0, #0xff00 | ||
53 | str r0, [r12] | ||
54 | 1: | ||
55 | mov r12, #0x03000000 @ point to LEDs | ||
56 | orr r12, r12, #0x00020000 | ||
57 | orr r12, r12, #0xba00 | ||
58 | mov r0, #0xfe00 | ||
59 | str r0, [r12] | ||
60 | |||
61 | adr lr, 1f | ||
62 | mov r0, #0 | ||
63 | mov r1, #14 /* MACH_TYPE_CLPS7500 */ | ||
64 | mov pc, lr | ||
65 | .Langel: | ||
66 | #ifdef CONFIG_ANGELBOOT | ||
67 | /* Call Angel to switch into SVC mode. */ | ||
68 | mov r0, #0x17 | ||
69 | swi 0x123456 | ||
70 | #endif | ||
71 | /* Ensure all interrupts are off and MMU disabled */ | ||
72 | mrs r0, cpsr | ||
73 | orr r0, r0, #0xc0 | ||
74 | msr cpsr_cxsf, r0 | ||
75 | |||
76 | adr lr, 1b | ||
77 | orr lr, lr, #0x10000000 | ||
78 | mov r0, #0x30 @ MMU off | ||
79 | mcr p15, 0, r0, c1, c0, 0 | ||
80 | mov r0, r0 | ||
81 | mov pc, lr | ||
82 | |||
83 | .ltorg | ||
84 | |||
85 | 1: | ||
86 | /* And the rest */ | ||
87 | #include "head.S" | ||
diff --git a/arch/arm/boot/compressed/head-epxa10db.S b/arch/arm/boot/compressed/head-epxa10db.S new file mode 100644 index 000000000000..757681f12a39 --- /dev/null +++ b/arch/arm/boot/compressed/head-epxa10db.S | |||
@@ -0,0 +1,5 @@ | |||
1 | #include <asm/mach-types.h> | ||
2 | #include <asm/arch/excalibur.h> | ||
3 | |||
4 | .section ".start", "ax" | ||
5 | mov r7, #MACH_TYPE_CAMELOT | ||
diff --git a/arch/arm/boot/compressed/head-l7200.S b/arch/arm/boot/compressed/head-l7200.S new file mode 100644 index 000000000000..b08bd23f8d16 --- /dev/null +++ b/arch/arm/boot/compressed/head-l7200.S | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head-l7200.S | ||
3 | * | ||
4 | * Copyright (C) 2000 Steve Hill <sjhill@cotw.com> | ||
5 | * | ||
6 | * Some code borrowed from Nicolas Pitre's 'head-sa1100.S' file. This | ||
7 | * is merged with head.S by the linker. | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <asm/mach-types.h> | ||
12 | |||
13 | #ifndef CONFIG_ARCH_L7200 | ||
14 | #error What am I doing here... | ||
15 | #endif | ||
16 | |||
17 | .section ".start", "ax" | ||
18 | |||
19 | __L7200_start: | ||
20 | mov r0, #0x00100000 @ FLASH address of initrd | ||
21 | mov r2, #0xf1000000 @ RAM address of initrd | ||
22 | add r3, r2, #0x00700000 @ Size of initrd | ||
23 | 1: | ||
24 | ldmia r0!, {r4, r5, r6, r7} | ||
25 | stmia r2!, {r4, r5, r6, r7} | ||
26 | cmp r2, r3 | ||
27 | ble 1b | ||
28 | |||
29 | mov r8, #0 @ Zero it out | ||
30 | mov r7, #MACH_TYPE_L7200 @ Set architecture ID | ||
diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S new file mode 100644 index 000000000000..5aefffd46048 --- /dev/null +++ b/arch/arm/boot/compressed/head-sa1100.S | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head-sa1100.S | ||
3 | * | ||
4 | * Copyright (C) 1999 Nicolas Pitre <nico@cam.org> | ||
5 | * | ||
6 | * SA1100 specific tweaks. This is merged into head.S by the linker. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/linkage.h> | ||
12 | #include <asm/mach-types.h> | ||
13 | |||
14 | .section ".start", "ax" | ||
15 | |||
16 | __SA1100_start: | ||
17 | |||
18 | @ Preserve r8/r7 i.e. kernel entry values | ||
19 | #ifdef CONFIG_SA1100_COLLIE | ||
20 | mov r7, #MACH_TYPE_COLLIE | ||
21 | #endif | ||
22 | #ifdef CONFIG_SA1100_SIMPAD | ||
23 | @ UNTIL we've something like an open bootldr | ||
24 | mov r7, #MACH_TYPE_SIMPAD @should be 87 | ||
25 | #endif | ||
26 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
27 | ands r0, r0, #0x0d | ||
28 | beq 99f | ||
29 | |||
30 | @ Data cache might be active. | ||
31 | @ Be sure to flush kernel binary out of the cache, | ||
32 | @ whatever state it is, before it is turned off. | ||
33 | @ This is done by fetching through currently executed | ||
34 | @ memory to be sure we hit the same cache. | ||
35 | bic r2, pc, #0x1f | ||
36 | add r3, r2, #0x4000 @ 16 kb is quite enough... | ||
37 | 1: ldr r0, [r2], #32 | ||
38 | teq r2, r3 | ||
39 | bne 1b | ||
40 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | ||
41 | mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches | ||
42 | |||
43 | @ disabling MMU and caches | ||
44 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
45 | bic r0, r0, #0x0d @ clear WB, DC, MMU | ||
46 | bic r0, r0, #0x1000 @ clear Icache | ||
47 | mcr p15, 0, r0, c1, c0, 0 | ||
48 | 99: | ||
diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S new file mode 100644 index 000000000000..848f60e5429b --- /dev/null +++ b/arch/arm/boot/compressed/head-shark.S | |||
@@ -0,0 +1,115 @@ | |||
1 | /* The head-file for the Shark | ||
2 | * by Alexander Schulz | ||
3 | * | ||
4 | * Does the following: | ||
5 | * - get the memory layout from firmware. This can only be done as long as the mmu | ||
6 | * is still on. | ||
7 | * - switch the mmu off, so we have physical addresses | ||
8 | * - copy the kernel to 0x08508000. This is done to have a fixed address where the | ||
9 | * C-parts (misc.c) are executed. This address must be known at compile-time, | ||
10 | * but the load-address of the kernel depends on how much memory is installed. | ||
11 | * - Jump to this location. | ||
12 | * - Set r8 with 0, r7 with the architecture ID for head.S | ||
13 | */ | ||
14 | |||
15 | #include <linux/linkage.h> | ||
16 | |||
17 | #include <asm/assembler.h> | ||
18 | |||
19 | .section ".start", "ax" | ||
20 | |||
21 | b __beginning | ||
22 | |||
23 | __ofw_data: .long 0 @ the number of memory blocks | ||
24 | .space 128 @ (startaddr,size) ... | ||
25 | .space 128 @ bootargs | ||
26 | .align | ||
27 | |||
28 | __beginning: mov r4, r0 @ save the entry to the firmware | ||
29 | |||
30 | mov r0, #0xC0 @ disable irq and fiq | ||
31 | mov r1, r0 | ||
32 | mrs r3, cpsr | ||
33 | bic r2, r3, r0 | ||
34 | eor r2, r2, r1 | ||
35 | msr cpsr_c, r2 | ||
36 | |||
37 | mov r0, r4 @ get the Memory layout from firmware | ||
38 | adr r1, __ofw_data | ||
39 | add r2, r1, #4 | ||
40 | mov lr, pc | ||
41 | b ofw_init | ||
42 | mov r1, #0 | ||
43 | |||
44 | adr r2, __mmu_off @ calculate physical address | ||
45 | sub r2, r2, #0xf0000000 @ openprom maps us at f000 virt, 0e50 phys | ||
46 | adr r0, __ofw_data | ||
47 | ldr r0, [r0, #4] | ||
48 | add r2, r2, r0 | ||
49 | add r2, r2, #0x00500000 | ||
50 | |||
51 | mrc p15, 0, r3, c1, c0 | ||
52 | bic r3, r3, #0xC @ Write Buffer and DCache | ||
53 | bic r3, r3, #0x1000 @ ICache | ||
54 | mcr p15, 0, r3, c1, c0 @ disabled | ||
55 | |||
56 | mov r0, #0 | ||
57 | mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 | ||
58 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 | ||
59 | mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 | ||
60 | |||
61 | bic r3, r3, #0x1 @ MMU | ||
62 | mcr p15, 0, r3, c1, c0 @ disabled | ||
63 | |||
64 | mov pc, r2 | ||
65 | |||
66 | __copy_target: .long 0x08508000 | ||
67 | __copy_end: .long 0x08608000 | ||
68 | |||
69 | .word _start | ||
70 | .word __bss_start | ||
71 | |||
72 | .align | ||
73 | __temp_stack: .space 128 | ||
74 | |||
75 | __mmu_off: | ||
76 | adr r0, __ofw_data | ||
77 | ldr r0, [r0, #4] | ||
78 | orr r0, r0, #0x00600000 | ||
79 | |||
80 | ldr r1, __copy_end | ||
81 | ldr r3, __copy_target | ||
82 | |||
83 | /* r0 = 0x0e600000 (current end of kernelcode) | ||
84 | * r3 = 0x08508000 (where it should begin) | ||
85 | * r1 = 0x08608000 (end of copying area, 1MB) | ||
86 | * The kernel is compressed, so 1 MB should be enough. | ||
87 | * copy the kernel to the beginning of physical memory | ||
88 | * We start from the highest address, so we can copy | ||
89 | * from 0x08500000 to 0x08508000 if we have only 8MB | ||
90 | */ | ||
91 | |||
92 | |||
93 | __Copy: ldr r2, [r0], #-4 | ||
94 | str r2, [r1], #-4 | ||
95 | teq r1, r3 | ||
96 | bne __Copy | ||
97 | /* and jump to it */ | ||
98 | adr r2, __go_on | ||
99 | adr r0, __ofw_data | ||
100 | ldr r0, [r0, #4] | ||
101 | sub r2, r2, r0 | ||
102 | sub r2, r2, #0x00500000 | ||
103 | ldr r0, __copy_target | ||
104 | add r2, r2, r0 | ||
105 | mov pc, r2 | ||
106 | |||
107 | __go_on: | ||
108 | adr sp, __temp_stack | ||
109 | add sp, sp, #128 | ||
110 | adr r0, __ofw_data | ||
111 | mov lr, pc | ||
112 | b create_params | ||
113 | |||
114 | mov r8, #0 | ||
115 | mov r7, #15 | ||
diff --git a/arch/arm/boot/compressed/head-sharpsl.S b/arch/arm/boot/compressed/head-sharpsl.S new file mode 100644 index 000000000000..d6bf8a2b090d --- /dev/null +++ b/arch/arm/boot/compressed/head-sharpsl.S | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head-sharpsl.S | ||
3 | * | ||
4 | * Copyright (C) 2004-2005 Richard Purdie <rpurdie@rpsys.net> | ||
5 | * | ||
6 | * Sharp's bootloader doesn't pass any kind of machine ID | ||
7 | * so we have to figure out the machine for ourselves... | ||
8 | * | ||
9 | * Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750) | ||
10 | * and Husky (SL-C760). | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/linkage.h> | ||
16 | #include <asm/mach-types.h> | ||
17 | |||
18 | #ifndef CONFIG_PXA_SHARPSL | ||
19 | #error What am I doing here... | ||
20 | #endif | ||
21 | |||
22 | .section ".start", "ax" | ||
23 | |||
24 | __SharpSL_start: | ||
25 | |||
26 | ldr r1, .W100ADDR @ Base address of w100 chip + regs offset | ||
27 | |||
28 | mov r6, #0x31 @ Load Magic Init value | ||
29 | str r6, [r1, #0x280] @ to SCRATCH_UMSK | ||
30 | mov r5, #0x3000 | ||
31 | .W100LOOP: | ||
32 | subs r5, r5, #1 | ||
33 | bne .W100LOOP | ||
34 | mov r6, #0x30 @ Load 2nd Magic Init value | ||
35 | str r6, [r1, #0x280] @ to SCRATCH_UMSK | ||
36 | |||
37 | ldr r6, [r1, #0] @ Load Chip ID | ||
38 | ldr r3, .W100ID | ||
39 | ldr r7, .POODLEID | ||
40 | cmp r6, r3 | ||
41 | bne .SHARPEND @ We have no w100 - Poodle | ||
42 | |||
43 | mrc p15, 0, r6, c0, c0 @ Get Processor ID | ||
44 | and r6, r6, #0xffffff00 | ||
45 | ldr r7, .CORGIID | ||
46 | ldr r3, .PXA255ID | ||
47 | cmp r6, r3 | ||
48 | blo .SHARPEND @ We have a PXA250 - Corgi | ||
49 | |||
50 | mov r1, #0x0c000000 @ Base address of NAND chip | ||
51 | ldrb r3, [r1, #24] @ Load FLASHCTL | ||
52 | bic r3, r3, #0x11 @ SET NCE | ||
53 | orr r3, r3, #0x0a @ SET CLR + FLWP | ||
54 | strb r3, [r1, #24] @ Save to FLASHCTL | ||
55 | mov r2, #0x90 @ Command "readid" | ||
56 | strb r2, [r1, #20] @ Save to FLASHIO | ||
57 | bic r3, r3, #2 @ CLR CLE | ||
58 | orr r3, r3, #4 @ SET ALE | ||
59 | strb r3, [r1, #24] @ Save to FLASHCTL | ||
60 | mov r2, #0 @ Address 0x00 | ||
61 | strb r2, [r1, #20] @ Save to FLASHIO | ||
62 | bic r3, r3, #4 @ CLR ALE | ||
63 | strb r3, [r1, #24] @ Save to FLASHCTL | ||
64 | .SHARP1: | ||
65 | ldrb r3, [r1, #24] @ Load FLASHCTL | ||
66 | tst r3, #32 @ Is chip ready? | ||
67 | beq .SHARP1 | ||
68 | ldrb r2, [r1, #20] @ NAND Manufacturer ID | ||
69 | ldrb r3, [r1, #20] @ NAND Chip ID | ||
70 | ldr r7, .SHEPHERDID | ||
71 | cmp r3, #0x76 @ 64MiB flash | ||
72 | beq .SHARPEND @ We have Shepherd | ||
73 | ldr r7, .HUSKYID @ Must be Husky | ||
74 | b .SHARPEND | ||
75 | |||
76 | .PXA255ID: | ||
77 | .word 0x69052d00 @ PXA255 Processor ID | ||
78 | .W100ID: | ||
79 | .word 0x57411002 @ w100 Chip ID | ||
80 | .W100ADDR: | ||
81 | .word 0x08010000 @ w100 Chip ID Reg Address | ||
82 | .POODLEID: | ||
83 | .word MACH_TYPE_POODLE | ||
84 | .CORGIID: | ||
85 | .word MACH_TYPE_CORGI | ||
86 | .SHEPHERDID: | ||
87 | .word MACH_TYPE_SHEPHERD | ||
88 | .HUSKYID: | ||
89 | .word MACH_TYPE_HUSKY | ||
90 | .SHARPEND: | ||
91 | |||
92 | |||
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S new file mode 100644 index 000000000000..665bd2c20743 --- /dev/null +++ b/arch/arm/boot/compressed/head-xscale.S | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head-xscale.S | ||
3 | * | ||
4 | * XScale specific tweaks. This is merged into head.S by the linker. | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/config.h> | ||
9 | #include <linux/linkage.h> | ||
10 | #include <asm/mach-types.h> | ||
11 | |||
12 | .section ".start", "ax" | ||
13 | |||
14 | __XScale_start: | ||
15 | |||
16 | @ Preserve r8/r7 i.e. kernel entry values | ||
17 | |||
18 | @ Data cache might be active. | ||
19 | @ Be sure to flush kernel binary out of the cache, | ||
20 | @ whatever state it is, before it is turned off. | ||
21 | @ This is done by fetching through currently executed | ||
22 | @ memory to be sure we hit the same cache. | ||
23 | bic r2, pc, #0x1f | ||
24 | add r3, r2, #0x10000 @ 64 kb is quite enough... | ||
25 | 1: ldr r0, [r2], #32 | ||
26 | teq r2, r3 | ||
27 | bne 1b | ||
28 | mcr p15, 0, r0, c7, c10, 4 @ drain WB | ||
29 | mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches | ||
30 | |||
31 | @ disabling MMU and caches | ||
32 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
33 | bic r0, r0, #0x05 @ clear DC, MMU | ||
34 | bic r0, r0, #0x1000 @ clear Icache | ||
35 | mcr p15, 0, r0, c1, c0, 0 | ||
36 | |||
37 | #ifdef CONFIG_ARCH_LUBBOCK | ||
38 | mov r7, #MACH_TYPE_LUBBOCK | ||
39 | #endif | ||
40 | |||
41 | #ifdef CONFIG_ARCH_COTULLA_IDP | ||
42 | mov r7, #MACH_TYPE_COTULLA_IDP | ||
43 | #endif | ||
44 | |||
45 | #ifdef CONFIG_MACH_GTWX5715 | ||
46 | mov r7, #(MACH_TYPE_GTWX5715 & 0xff) | ||
47 | orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00) | ||
48 | #endif | ||
49 | |||
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S new file mode 100644 index 000000000000..c0e7aff3dec2 --- /dev/null +++ b/arch/arm/boot/compressed/head.S | |||
@@ -0,0 +1,786 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/head.S | ||
3 | * | ||
4 | * Copyright (C) 1996-2002 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/config.h> | ||
11 | #include <linux/linkage.h> | ||
12 | |||
13 | /* | ||
14 | * Debugging stuff | ||
15 | * | ||
16 | * Note that these macros must not contain any code which is not | ||
17 | * 100% relocatable. Any attempt to do so will result in a crash. | ||
18 | * Please select one of the following when turning on debugging. | ||
19 | */ | ||
20 | #ifdef DEBUG | ||
21 | #if defined(CONFIG_DEBUG_DC21285_PORT) | ||
22 | .macro loadsp, rb | ||
23 | mov \rb, #0x42000000 | ||
24 | .endm | ||
25 | .macro writeb, rb | ||
26 | str \rb, [r3, #0x160] | ||
27 | .endm | ||
28 | #elif defined(CONFIG_DEBUG_ICEDCC) | ||
29 | .macro loadsp, rb | ||
30 | .endm | ||
31 | .macro writeb, rb | ||
32 | mcr p14, 0, \rb, c0, c1, 0 | ||
33 | .endm | ||
34 | #elif defined(CONFIG_FOOTBRIDGE) | ||
35 | .macro loadsp, rb | ||
36 | mov \rb, #0x7c000000 | ||
37 | .endm | ||
38 | .macro writeb, rb | ||
39 | strb \rb, [r3, #0x3f8] | ||
40 | .endm | ||
41 | #elif defined(CONFIG_ARCH_RPC) | ||
42 | .macro loadsp, rb | ||
43 | mov \rb, #0x03000000 | ||
44 | orr \rb, \rb, #0x00010000 | ||
45 | .endm | ||
46 | .macro writeb, rb | ||
47 | strb \rb, [r3, #0x3f8 << 2] | ||
48 | .endm | ||
49 | #elif defined(CONFIG_ARCH_INTEGRATOR) | ||
50 | .macro loadsp, rb | ||
51 | mov \rb, #0x16000000 | ||
52 | .endm | ||
53 | .macro writeb, rb | ||
54 | strb \rb, [r3, #0] | ||
55 | .endm | ||
56 | #elif defined(CONFIG_ARCH_PXA) /* Xscale-type */ | ||
57 | .macro loadsp, rb | ||
58 | mov \rb, #0x40000000 | ||
59 | orr \rb, \rb, #0x00100000 | ||
60 | .endm | ||
61 | .macro writeb, rb | ||
62 | strb \rb, [r3, #0] | ||
63 | .endm | ||
64 | #elif defined(CONFIG_ARCH_SA1100) | ||
65 | .macro loadsp, rb | ||
66 | mov \rb, #0x80000000 @ physical base address | ||
67 | # if defined(CONFIG_DEBUG_LL_SER3) | ||
68 | add \rb, \rb, #0x00050000 @ Ser3 | ||
69 | # else | ||
70 | add \rb, \rb, #0x00010000 @ Ser1 | ||
71 | # endif | ||
72 | .endm | ||
73 | .macro writeb, rb | ||
74 | str \rb, [r3, #0x14] @ UTDR | ||
75 | .endm | ||
76 | #elif defined(CONFIG_ARCH_IXP4XX) | ||
77 | .macro loadsp, rb | ||
78 | mov \rb, #0xc8000000 | ||
79 | .endm | ||
80 | .macro writeb, rb | ||
81 | str \rb, [r3, #0] | ||
82 | #elif defined(CONFIG_ARCH_IXP2000) | ||
83 | .macro loadsp, rb | ||
84 | mov \rb, #0xc0000000 | ||
85 | orr \rb, \rb, #0x00030000 | ||
86 | .endm | ||
87 | .macro writeb, rb | ||
88 | str \rb, [r3, #0] | ||
89 | .endm | ||
90 | #elif defined(CONFIG_ARCH_LH7A40X) | ||
91 | .macro loadsp, rb | ||
92 | ldr \rb, =0x80000700 @ UART2 UARTBASE | ||
93 | .endm | ||
94 | .macro writeb, rb | ||
95 | strb \rb, [r3, #0] | ||
96 | .endm | ||
97 | #elif defined(CONFIG_ARCH_OMAP) | ||
98 | .macro loadsp, rb | ||
99 | mov \rb, #0xff000000 @ physical base address | ||
100 | add \rb, \rb, #0x00fb0000 | ||
101 | #if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3) | ||
102 | add \rb, \rb, #0x00000800 | ||
103 | #endif | ||
104 | #ifdef CONFIG_OMAP_LL_DEBUG_UART3 | ||
105 | add \rb, \rb, #0x00009000 | ||
106 | #endif | ||
107 | .endm | ||
108 | .macro writeb, rb | ||
109 | strb \rb, [r3] | ||
110 | .endm | ||
111 | #elif defined(CONFIG_ARCH_IOP331) | ||
112 | .macro loadsp, rb | ||
113 | mov \rb, #0xff000000 | ||
114 | orr \rb, \rb, #0x00ff0000 | ||
115 | orr \rb, \rb, #0x0000f700 @ location of the UART | ||
116 | .endm | ||
117 | .macro writeb, rb | ||
118 | str \rb, [r3, #0] | ||
119 | .endm | ||
120 | #elif defined(CONFIG_ARCH_S3C2410) | ||
121 | .macro loadsp, rb | ||
122 | mov \rb, #0x50000000 | ||
123 | add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT | ||
124 | .endm | ||
125 | .macro writeb, rb | ||
126 | strb \rb, [r3, #0x20] | ||
127 | .endm | ||
128 | #else | ||
129 | #error no serial architecture defined | ||
130 | #endif | ||
131 | #endif | ||
132 | |||
133 | .macro kputc,val | ||
134 | mov r0, \val | ||
135 | bl putc | ||
136 | .endm | ||
137 | |||
138 | .macro kphex,val,len | ||
139 | mov r0, \val | ||
140 | mov r1, #\len | ||
141 | bl phex | ||
142 | .endm | ||
143 | |||
144 | .macro debug_reloc_start | ||
145 | #ifdef DEBUG | ||
146 | kputc #'\n' | ||
147 | kphex r6, 8 /* processor id */ | ||
148 | kputc #':' | ||
149 | kphex r7, 8 /* architecture id */ | ||
150 | kputc #':' | ||
151 | mrc p15, 0, r0, c1, c0 | ||
152 | kphex r0, 8 /* control reg */ | ||
153 | kputc #'\n' | ||
154 | kphex r5, 8 /* decompressed kernel start */ | ||
155 | kputc #'-' | ||
156 | kphex r8, 8 /* decompressed kernel end */ | ||
157 | kputc #'>' | ||
158 | kphex r4, 8 /* kernel execution address */ | ||
159 | kputc #'\n' | ||
160 | #endif | ||
161 | .endm | ||
162 | |||
163 | .macro debug_reloc_end | ||
164 | #ifdef DEBUG | ||
165 | kphex r5, 8 /* end of kernel */ | ||
166 | kputc #'\n' | ||
167 | mov r0, r4 | ||
168 | bl memdump /* dump 256 bytes at start of kernel */ | ||
169 | #endif | ||
170 | .endm | ||
171 | |||
172 | .section ".start", #alloc, #execinstr | ||
173 | /* | ||
174 | * sort out different calling conventions | ||
175 | */ | ||
176 | .align | ||
177 | start: | ||
178 | .type start,#function | ||
179 | .rept 8 | ||
180 | mov r0, r0 | ||
181 | .endr | ||
182 | |||
183 | b 1f | ||
184 | .word 0x016f2818 @ Magic numbers to help the loader | ||
185 | .word start @ absolute load/run zImage address | ||
186 | .word _edata @ zImage end address | ||
187 | 1: mov r7, r1 @ save architecture ID | ||
188 | mov r8, #0 @ save r0 | ||
189 | |||
190 | #ifndef __ARM_ARCH_2__ | ||
191 | /* | ||
192 | * Booting from Angel - need to enter SVC mode and disable | ||
193 | * FIQs/IRQs (numeric definitions from angel arm.h source). | ||
194 | * We only do this if we were in user mode on entry. | ||
195 | */ | ||
196 | mrs r2, cpsr @ get current mode | ||
197 | tst r2, #3 @ not user? | ||
198 | bne not_angel | ||
199 | mov r0, #0x17 @ angel_SWIreason_EnterSVC | ||
200 | swi 0x123456 @ angel_SWI_ARM | ||
201 | not_angel: | ||
202 | mrs r2, cpsr @ turn off interrupts to | ||
203 | orr r2, r2, #0xc0 @ prevent angel from running | ||
204 | msr cpsr_c, r2 | ||
205 | #else | ||
206 | teqp pc, #0x0c000003 @ turn off interrupts | ||
207 | #endif | ||
208 | |||
209 | /* | ||
210 | * Note that some cache flushing and other stuff may | ||
211 | * be needed here - is there an Angel SWI call for this? | ||
212 | */ | ||
213 | |||
214 | /* | ||
215 | * some architecture specific code can be inserted | ||
216 | * by the linker here, but it should preserve r7 and r8. | ||
217 | */ | ||
218 | |||
219 | .text | ||
220 | adr r0, LC0 | ||
221 | ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} | ||
222 | subs r0, r0, r1 @ calculate the delta offset | ||
223 | |||
224 | @ if delta is zero, we are | ||
225 | beq not_relocated @ running at the address we | ||
226 | @ were linked at. | ||
227 | |||
228 | /* | ||
229 | * We're running at a different address. We need to fix | ||
230 | * up various pointers: | ||
231 | * r5 - zImage base address | ||
232 | * r6 - GOT start | ||
233 | * ip - GOT end | ||
234 | */ | ||
235 | add r5, r5, r0 | ||
236 | add r6, r6, r0 | ||
237 | add ip, ip, r0 | ||
238 | |||
239 | #ifndef CONFIG_ZBOOT_ROM | ||
240 | /* | ||
241 | * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, | ||
242 | * we need to fix up pointers into the BSS region. | ||
243 | * r2 - BSS start | ||
244 | * r3 - BSS end | ||
245 | * sp - stack pointer | ||
246 | */ | ||
247 | add r2, r2, r0 | ||
248 | add r3, r3, r0 | ||
249 | add sp, sp, r0 | ||
250 | |||
251 | /* | ||
252 | * Relocate all entries in the GOT table. | ||
253 | */ | ||
254 | 1: ldr r1, [r6, #0] @ relocate entries in the GOT | ||
255 | add r1, r1, r0 @ table. This fixes up the | ||
256 | str r1, [r6], #4 @ C references. | ||
257 | cmp r6, ip | ||
258 | blo 1b | ||
259 | #else | ||
260 | |||
261 | /* | ||
262 | * Relocate entries in the GOT table. We only relocate | ||
263 | * the entries that are outside the (relocated) BSS region. | ||
264 | */ | ||
265 | 1: ldr r1, [r6, #0] @ relocate entries in the GOT | ||
266 | cmp r1, r2 @ entry < bss_start || | ||
267 | cmphs r3, r1 @ _end < entry | ||
268 | addlo r1, r1, r0 @ table. This fixes up the | ||
269 | str r1, [r6], #4 @ C references. | ||
270 | cmp r6, ip | ||
271 | blo 1b | ||
272 | #endif | ||
273 | |||
274 | not_relocated: mov r0, #0 | ||
275 | 1: str r0, [r2], #4 @ clear bss | ||
276 | str r0, [r2], #4 | ||
277 | str r0, [r2], #4 | ||
278 | str r0, [r2], #4 | ||
279 | cmp r2, r3 | ||
280 | blo 1b | ||
281 | |||
282 | /* | ||
283 | * The C runtime environment should now be setup | ||
284 | * sufficiently. Turn the cache on, set up some | ||
285 | * pointers, and start decompressing. | ||
286 | */ | ||
287 | bl cache_on | ||
288 | |||
289 | mov r1, sp @ malloc space above stack | ||
290 | add r2, sp, #0x10000 @ 64k max | ||
291 | |||
292 | /* | ||
293 | * Check to see if we will overwrite ourselves. | ||
294 | * r4 = final kernel address | ||
295 | * r5 = start of this image | ||
296 | * r2 = end of malloc space (and therefore this image) | ||
297 | * We basically want: | ||
298 | * r4 >= r2 -> OK | ||
299 | * r4 + image length <= r5 -> OK | ||
300 | */ | ||
301 | cmp r4, r2 | ||
302 | bhs wont_overwrite | ||
303 | add r0, r4, #4096*1024 @ 4MB largest kernel size | ||
304 | cmp r0, r5 | ||
305 | bls wont_overwrite | ||
306 | |||
307 | mov r5, r2 @ decompress after malloc space | ||
308 | mov r0, r5 | ||
309 | mov r3, r7 | ||
310 | bl decompress_kernel | ||
311 | |||
312 | add r0, r0, #127 | ||
313 | bic r0, r0, #127 @ align the kernel length | ||
314 | /* | ||
315 | * r0 = decompressed kernel length | ||
316 | * r1-r3 = unused | ||
317 | * r4 = kernel execution address | ||
318 | * r5 = decompressed kernel start | ||
319 | * r6 = processor ID | ||
320 | * r7 = architecture ID | ||
321 | * r8-r14 = unused | ||
322 | */ | ||
323 | add r1, r5, r0 @ end of decompressed kernel | ||
324 | adr r2, reloc_start | ||
325 | ldr r3, LC1 | ||
326 | add r3, r2, r3 | ||
327 | 1: ldmia r2!, {r8 - r13} @ copy relocation code | ||
328 | stmia r1!, {r8 - r13} | ||
329 | ldmia r2!, {r8 - r13} | ||
330 | stmia r1!, {r8 - r13} | ||
331 | cmp r2, r3 | ||
332 | blo 1b | ||
333 | |||
334 | bl cache_clean_flush | ||
335 | add pc, r5, r0 @ call relocation code | ||
336 | |||
337 | /* | ||
338 | * We're not in danger of overwriting ourselves. Do this the simple way. | ||
339 | * | ||
340 | * r4 = kernel execution address | ||
341 | * r7 = architecture ID | ||
342 | */ | ||
343 | wont_overwrite: mov r0, r4 | ||
344 | mov r3, r7 | ||
345 | bl decompress_kernel | ||
346 | b call_kernel | ||
347 | |||
348 | .type LC0, #object | ||
349 | LC0: .word LC0 @ r1 | ||
350 | .word __bss_start @ r2 | ||
351 | .word _end @ r3 | ||
352 | .word zreladdr @ r4 | ||
353 | .word _start @ r5 | ||
354 | .word _got_start @ r6 | ||
355 | .word _got_end @ ip | ||
356 | .word user_stack+4096 @ sp | ||
357 | LC1: .word reloc_end - reloc_start | ||
358 | .size LC0, . - LC0 | ||
359 | |||
360 | #ifdef CONFIG_ARCH_RPC | ||
361 | .globl params | ||
362 | params: ldr r0, =params_phys | ||
363 | mov pc, lr | ||
364 | .ltorg | ||
365 | .align | ||
366 | #endif | ||
367 | |||
368 | /* | ||
369 | * Turn on the cache. We need to setup some page tables so that we | ||
370 | * can have both the I and D caches on. | ||
371 | * | ||
372 | * We place the page tables 16k down from the kernel execution address, | ||
373 | * and we hope that nothing else is using it. If we're using it, we | ||
374 | * will go pop! | ||
375 | * | ||
376 | * On entry, | ||
377 | * r4 = kernel execution address | ||
378 | * r6 = processor ID | ||
379 | * r7 = architecture number | ||
380 | * r8 = run-time address of "start" | ||
381 | * On exit, | ||
382 | * r1, r2, r3, r8, r9, r12 corrupted | ||
383 | * This routine must preserve: | ||
384 | * r4, r5, r6, r7 | ||
385 | */ | ||
386 | .align 5 | ||
387 | cache_on: mov r3, #8 @ cache_on function | ||
388 | b call_cache_fn | ||
389 | |||
390 | __setup_mmu: sub r3, r4, #16384 @ Page directory size | ||
391 | bic r3, r3, #0xff @ Align the pointer | ||
392 | bic r3, r3, #0x3f00 | ||
393 | /* | ||
394 | * Initialise the page tables, turning on the cacheable and bufferable | ||
395 | * bits for the RAM area only. | ||
396 | */ | ||
397 | mov r0, r3 | ||
398 | mov r8, r0, lsr #18 | ||
399 | mov r8, r8, lsl #18 @ start of RAM | ||
400 | add r9, r8, #0x10000000 @ a reasonable RAM size | ||
401 | mov r1, #0x12 | ||
402 | orr r1, r1, #3 << 10 | ||
403 | add r2, r3, #16384 | ||
404 | 1: cmp r1, r8 @ if virt > start of RAM | ||
405 | orrhs r1, r1, #0x0c @ set cacheable, bufferable | ||
406 | cmp r1, r9 @ if virt > end of RAM | ||
407 | bichs r1, r1, #0x0c @ clear cacheable, bufferable | ||
408 | str r1, [r0], #4 @ 1:1 mapping | ||
409 | add r1, r1, #1048576 | ||
410 | teq r0, r2 | ||
411 | bne 1b | ||
412 | /* | ||
413 | * If ever we are running from Flash, then we surely want the cache | ||
414 | * to be enabled also for our execution instance... We map 2MB of it | ||
415 | * so there is no map overlap problem for up to 1 MB compressed kernel. | ||
416 | * If the execution is in RAM then we would only be duplicating the above. | ||
417 | */ | ||
418 | mov r1, #0x1e | ||
419 | orr r1, r1, #3 << 10 | ||
420 | mov r2, pc, lsr #20 | ||
421 | orr r1, r1, r2, lsl #20 | ||
422 | add r0, r3, r2, lsl #2 | ||
423 | str r1, [r0], #4 | ||
424 | add r1, r1, #1048576 | ||
425 | str r1, [r0] | ||
426 | mov pc, lr | ||
427 | |||
428 | __armv4_cache_on: | ||
429 | mov r12, lr | ||
430 | bl __setup_mmu | ||
431 | mov r0, #0 | ||
432 | mcr p15, 0, r0, c7, c10, 4 @ drain write buffer | ||
433 | mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs | ||
434 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | ||
435 | orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement | ||
436 | orr r0, r0, #0x0030 | ||
437 | bl __common_cache_on | ||
438 | mov r0, #0 | ||
439 | mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs | ||
440 | mov pc, r12 | ||
441 | |||
442 | __arm6_cache_on: | ||
443 | mov r12, lr | ||
444 | bl __setup_mmu | ||
445 | mov r0, #0 | ||
446 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
447 | mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 | ||
448 | mov r0, #0x30 | ||
449 | bl __common_cache_on | ||
450 | mov r0, #0 | ||
451 | mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 | ||
452 | mov pc, r12 | ||
453 | |||
454 | __common_cache_on: | ||
455 | #ifndef DEBUG | ||
456 | orr r0, r0, #0x000d @ Write buffer, mmu | ||
457 | #endif | ||
458 | mov r1, #-1 | ||
459 | mcr p15, 0, r3, c2, c0, 0 @ load page table pointer | ||
460 | mcr p15, 0, r1, c3, c0, 0 @ load domain access control | ||
461 | mcr p15, 0, r0, c1, c0, 0 @ load control register | ||
462 | mov pc, lr | ||
463 | |||
464 | /* | ||
465 | * All code following this line is relocatable. It is relocated by | ||
466 | * the above code to the end of the decompressed kernel image and | ||
467 | * executed there. During this time, we have no stacks. | ||
468 | * | ||
469 | * r0 = decompressed kernel length | ||
470 | * r1-r3 = unused | ||
471 | * r4 = kernel execution address | ||
472 | * r5 = decompressed kernel start | ||
473 | * r6 = processor ID | ||
474 | * r7 = architecture ID | ||
475 | * r8-r14 = unused | ||
476 | */ | ||
477 | .align 5 | ||
478 | reloc_start: add r8, r5, r0 | ||
479 | debug_reloc_start | ||
480 | mov r1, r4 | ||
481 | 1: | ||
482 | .rept 4 | ||
483 | ldmia r5!, {r0, r2, r3, r9 - r13} @ relocate kernel | ||
484 | stmia r1!, {r0, r2, r3, r9 - r13} | ||
485 | .endr | ||
486 | |||
487 | cmp r5, r8 | ||
488 | blo 1b | ||
489 | debug_reloc_end | ||
490 | |||
491 | call_kernel: bl cache_clean_flush | ||
492 | bl cache_off | ||
493 | mov r0, #0 | ||
494 | mov r1, r7 @ restore architecture number | ||
495 | mov pc, r4 @ call kernel | ||
496 | |||
497 | /* | ||
498 | * Here follow the relocatable cache support functions for the | ||
499 | * various processors. This is a generic hook for locating an | ||
500 | * entry and jumping to an instruction at the specified offset | ||
501 | * from the start of the block. Please note this is all position | ||
502 | * independent code. | ||
503 | * | ||
504 | * r1 = corrupted | ||
505 | * r2 = corrupted | ||
506 | * r3 = block offset | ||
507 | * r6 = corrupted | ||
508 | * r12 = corrupted | ||
509 | */ | ||
510 | |||
511 | call_cache_fn: adr r12, proc_types | ||
512 | mrc p15, 0, r6, c0, c0 @ get processor ID | ||
513 | 1: ldr r1, [r12, #0] @ get value | ||
514 | ldr r2, [r12, #4] @ get mask | ||
515 | eor r1, r1, r6 @ (real ^ match) | ||
516 | tst r1, r2 @ & mask | ||
517 | addeq pc, r12, r3 @ call cache function | ||
518 | add r12, r12, #4*5 | ||
519 | b 1b | ||
520 | |||
521 | /* | ||
522 | * Table for cache operations. This is basically: | ||
523 | * - CPU ID match | ||
524 | * - CPU ID mask | ||
525 | * - 'cache on' method instruction | ||
526 | * - 'cache off' method instruction | ||
527 | * - 'cache flush' method instruction | ||
528 | * | ||
529 | * We match an entry using: ((real_id ^ match) & mask) == 0 | ||
530 | * | ||
531 | * Writethrough caches generally only need 'on' and 'off' | ||
532 | * methods. Writeback caches _must_ have the flush method | ||
533 | * defined. | ||
534 | */ | ||
535 | .type proc_types,#object | ||
536 | proc_types: | ||
537 | .word 0x41560600 @ ARM6/610 | ||
538 | .word 0xffffffe0 | ||
539 | b __arm6_cache_off @ works, but slow | ||
540 | b __arm6_cache_off | ||
541 | mov pc, lr | ||
542 | @ b __arm6_cache_on @ untested | ||
543 | @ b __arm6_cache_off | ||
544 | @ b __armv3_cache_flush | ||
545 | |||
546 | .word 0x00000000 @ old ARM ID | ||
547 | .word 0x0000f000 | ||
548 | mov pc, lr | ||
549 | mov pc, lr | ||
550 | mov pc, lr | ||
551 | |||
552 | .word 0x41007000 @ ARM7/710 | ||
553 | .word 0xfff8fe00 | ||
554 | b __arm7_cache_off | ||
555 | b __arm7_cache_off | ||
556 | mov pc, lr | ||
557 | |||
558 | .word 0x41807200 @ ARM720T (writethrough) | ||
559 | .word 0xffffff00 | ||
560 | b __armv4_cache_on | ||
561 | b __armv4_cache_off | ||
562 | mov pc, lr | ||
563 | |||
564 | .word 0x00007000 @ ARM7 IDs | ||
565 | .word 0x0000f000 | ||
566 | mov pc, lr | ||
567 | mov pc, lr | ||
568 | mov pc, lr | ||
569 | |||
570 | @ Everything from here on will be the new ID system. | ||
571 | |||
572 | .word 0x4401a100 @ sa110 / sa1100 | ||
573 | .word 0xffffffe0 | ||
574 | b __armv4_cache_on | ||
575 | b __armv4_cache_off | ||
576 | b __armv4_cache_flush | ||
577 | |||
578 | .word 0x6901b110 @ sa1110 | ||
579 | .word 0xfffffff0 | ||
580 | b __armv4_cache_on | ||
581 | b __armv4_cache_off | ||
582 | b __armv4_cache_flush | ||
583 | |||
584 | @ These match on the architecture ID | ||
585 | |||
586 | .word 0x00020000 @ ARMv4T | ||
587 | .word 0x000f0000 | ||
588 | b __armv4_cache_on | ||
589 | b __armv4_cache_off | ||
590 | b __armv4_cache_flush | ||
591 | |||
592 | .word 0x00050000 @ ARMv5TE | ||
593 | .word 0x000f0000 | ||
594 | b __armv4_cache_on | ||
595 | b __armv4_cache_off | ||
596 | b __armv4_cache_flush | ||
597 | |||
598 | .word 0x00060000 @ ARMv5TEJ | ||
599 | .word 0x000f0000 | ||
600 | b __armv4_cache_on | ||
601 | b __armv4_cache_off | ||
602 | b __armv4_cache_flush | ||
603 | |||
604 | .word 0x00070000 @ ARMv6 | ||
605 | .word 0x000f0000 | ||
606 | b __armv4_cache_on | ||
607 | b __armv4_cache_off | ||
608 | b __armv6_cache_flush | ||
609 | |||
610 | .word 0 @ unrecognised type | ||
611 | .word 0 | ||
612 | mov pc, lr | ||
613 | mov pc, lr | ||
614 | mov pc, lr | ||
615 | |||
616 | .size proc_types, . - proc_types | ||
617 | |||
618 | /* | ||
619 | * Turn off the Cache and MMU. ARMv3 does not support | ||
620 | * reading the control register, but ARMv4 does. | ||
621 | * | ||
622 | * On entry, r6 = processor ID | ||
623 | * On exit, r0, r1, r2, r3, r12 corrupted | ||
624 | * This routine must preserve: r4, r6, r7 | ||
625 | */ | ||
626 | .align 5 | ||
627 | cache_off: mov r3, #12 @ cache_off function | ||
628 | b call_cache_fn | ||
629 | |||
630 | __armv4_cache_off: | ||
631 | mrc p15, 0, r0, c1, c0 | ||
632 | bic r0, r0, #0x000d | ||
633 | mcr p15, 0, r0, c1, c0 @ turn MMU and cache off | ||
634 | mov r0, #0 | ||
635 | mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 | ||
636 | mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 | ||
637 | mov pc, lr | ||
638 | |||
639 | __arm6_cache_off: | ||
640 | mov r0, #0x00000030 @ ARM6 control reg. | ||
641 | b __armv3_cache_off | ||
642 | |||
643 | __arm7_cache_off: | ||
644 | mov r0, #0x00000070 @ ARM7 control reg. | ||
645 | b __armv3_cache_off | ||
646 | |||
647 | __armv3_cache_off: | ||
648 | mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off | ||
649 | mov r0, #0 | ||
650 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
651 | mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 | ||
652 | mov pc, lr | ||
653 | |||
654 | /* | ||
655 | * Clean and flush the cache to maintain consistency. | ||
656 | * | ||
657 | * On entry, | ||
658 | * r6 = processor ID | ||
659 | * On exit, | ||
660 | * r1, r2, r3, r11, r12 corrupted | ||
661 | * This routine must preserve: | ||
662 | * r0, r4, r5, r6, r7 | ||
663 | */ | ||
664 | .align 5 | ||
665 | cache_clean_flush: | ||
666 | mov r3, #16 | ||
667 | b call_cache_fn | ||
668 | |||
669 | __armv6_cache_flush: | ||
670 | mov r1, #0 | ||
671 | mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D | ||
672 | mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB | ||
673 | mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified | ||
674 | mcr p15, 0, r1, c7, c10, 4 @ drain WB | ||
675 | mov pc, lr | ||
676 | |||
677 | __armv4_cache_flush: | ||
678 | mov r2, #64*1024 @ default: 32K dcache size (*2) | ||
679 | mov r11, #32 @ default: 32 byte line size | ||
680 | mrc p15, 0, r3, c0, c0, 1 @ read cache type | ||
681 | teq r3, r6 @ cache ID register present? | ||
682 | beq no_cache_id | ||
683 | mov r1, r3, lsr #18 | ||
684 | and r1, r1, #7 | ||
685 | mov r2, #1024 | ||
686 | mov r2, r2, lsl r1 @ base dcache size *2 | ||
687 | tst r3, #1 << 14 @ test M bit | ||
688 | addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 | ||
689 | mov r3, r3, lsr #12 | ||
690 | and r3, r3, #3 | ||
691 | mov r11, #8 | ||
692 | mov r11, r11, lsl r3 @ cache line size in bytes | ||
693 | no_cache_id: | ||
694 | bic r1, pc, #63 @ align to longest cache line | ||
695 | add r2, r1, r2 | ||
696 | 1: ldr r3, [r1], r11 @ s/w flush D cache | ||
697 | teq r1, r2 | ||
698 | bne 1b | ||
699 | |||
700 | mcr p15, 0, r1, c7, c5, 0 @ flush I cache | ||
701 | mcr p15, 0, r1, c7, c6, 0 @ flush D cache | ||
702 | mcr p15, 0, r1, c7, c10, 4 @ drain WB | ||
703 | mov pc, lr | ||
704 | |||
705 | __armv3_cache_flush: | ||
706 | mov r1, #0 | ||
707 | mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 | ||
708 | mov pc, lr | ||
709 | |||
710 | /* | ||
711 | * Various debugging routines for printing hex characters and | ||
712 | * memory, which again must be relocatable. | ||
713 | */ | ||
714 | #ifdef DEBUG | ||
715 | .type phexbuf,#object | ||
716 | phexbuf: .space 12 | ||
717 | .size phexbuf, . - phexbuf | ||
718 | |||
719 | phex: adr r3, phexbuf | ||
720 | mov r2, #0 | ||
721 | strb r2, [r3, r1] | ||
722 | 1: subs r1, r1, #1 | ||
723 | movmi r0, r3 | ||
724 | bmi puts | ||
725 | and r2, r0, #15 | ||
726 | mov r0, r0, lsr #4 | ||
727 | cmp r2, #10 | ||
728 | addge r2, r2, #7 | ||
729 | add r2, r2, #'0' | ||
730 | strb r2, [r3, r1] | ||
731 | b 1b | ||
732 | |||
733 | puts: loadsp r3 | ||
734 | 1: ldrb r2, [r0], #1 | ||
735 | teq r2, #0 | ||
736 | moveq pc, lr | ||
737 | 2: writeb r2 | ||
738 | mov r1, #0x00020000 | ||
739 | 3: subs r1, r1, #1 | ||
740 | bne 3b | ||
741 | teq r2, #'\n' | ||
742 | moveq r2, #'\r' | ||
743 | beq 2b | ||
744 | teq r0, #0 | ||
745 | bne 1b | ||
746 | mov pc, lr | ||
747 | putc: | ||
748 | mov r2, r0 | ||
749 | mov r0, #0 | ||
750 | loadsp r3 | ||
751 | b 2b | ||
752 | |||
753 | memdump: mov r12, r0 | ||
754 | mov r10, lr | ||
755 | mov r11, #0 | ||
756 | 2: mov r0, r11, lsl #2 | ||
757 | add r0, r0, r12 | ||
758 | mov r1, #8 | ||
759 | bl phex | ||
760 | mov r0, #':' | ||
761 | bl putc | ||
762 | 1: mov r0, #' ' | ||
763 | bl putc | ||
764 | ldr r0, [r12, r11, lsl #2] | ||
765 | mov r1, #8 | ||
766 | bl phex | ||
767 | and r0, r11, #7 | ||
768 | teq r0, #3 | ||
769 | moveq r0, #' ' | ||
770 | bleq putc | ||
771 | and r0, r11, #7 | ||
772 | add r11, r11, #1 | ||
773 | teq r0, #7 | ||
774 | bne 1b | ||
775 | mov r0, #'\n' | ||
776 | bl putc | ||
777 | cmp r11, #64 | ||
778 | blt 2b | ||
779 | mov pc, r10 | ||
780 | #endif | ||
781 | |||
782 | reloc_end: | ||
783 | |||
784 | .align | ||
785 | .section ".stack", "w" | ||
786 | user_stack: .space 4096 | ||
diff --git a/arch/arm/boot/compressed/ice-dcc.S b/arch/arm/boot/compressed/ice-dcc.S new file mode 100644 index 000000000000..104377a199bb --- /dev/null +++ b/arch/arm/boot/compressed/ice-dcc.S | |||
@@ -0,0 +1,17 @@ | |||
1 | |||
2 | |||
3 | .text | ||
4 | |||
5 | .global icedcc_putc | ||
6 | |||
7 | icedcc_putc: | ||
8 | mov r2, #0x4000000 | ||
9 | 1: | ||
10 | subs r2, r2, #1 | ||
11 | movlt pc, r14 | ||
12 | mrc p14, 0, r1, c0, c0, 0 | ||
13 | tst r1, #2 | ||
14 | bne 1b | ||
15 | |||
16 | mcr p14, 0, r0, c1, c0, 0 | ||
17 | mov pc, r14 | ||
diff --git a/arch/arm/boot/compressed/ll_char_wr.S b/arch/arm/boot/compressed/ll_char_wr.S new file mode 100644 index 000000000000..d7bbd9da2fca --- /dev/null +++ b/arch/arm/boot/compressed/ll_char_wr.S | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/lib/ll_char_wr.S | ||
3 | * | ||
4 | * Copyright (C) 1995, 1996 Russell King. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Speedups & 1bpp code (C) 1996 Philip Blundell & Russell King. | ||
11 | * | ||
12 | * 10-04-96 RMK Various cleanups & reduced register usage. | ||
13 | * 08-04-98 RMK Shifts re-ordered | ||
14 | */ | ||
15 | |||
16 | @ Regs: [] = corruptible | ||
17 | @ {} = used | ||
18 | @ () = do not use | ||
19 | |||
20 | #include <linux/linkage.h> | ||
21 | #include <asm/assembler.h> | ||
22 | .text | ||
23 | |||
24 | LC0: .word LC0 | ||
25 | .word bytes_per_char_h | ||
26 | .word video_size_row | ||
27 | .word acorndata_8x8 | ||
28 | .word con_charconvtable | ||
29 | |||
30 | /* | ||
31 | * r0 = ptr | ||
32 | * r1 = char | ||
33 | * r2 = white | ||
34 | */ | ||
35 | ENTRY(ll_write_char) | ||
36 | stmfd sp!, {r4 - r7, lr} | ||
37 | @ | ||
38 | @ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc) | ||
39 | @ | ||
40 | /* | ||
41 | * calculate offset into character table | ||
42 | */ | ||
43 | mov r1, r1, lsl #3 | ||
44 | /* | ||
45 | * calculate offset required for each row. | ||
46 | */ | ||
47 | adr ip, LC0 | ||
48 | ldmia ip, {r3, r4, r5, r6, lr} | ||
49 | sub ip, ip, r3 | ||
50 | add r6, r6, ip | ||
51 | add lr, lr, ip | ||
52 | ldr r4, [r4, ip] | ||
53 | ldr r5, [r5, ip] | ||
54 | /* | ||
55 | * Go to resolution-dependent routine... | ||
56 | */ | ||
57 | cmp r4, #4 | ||
58 | blt Lrow1bpp | ||
59 | add r0, r0, r5, lsl #3 @ Move to bottom of character | ||
60 | orr r1, r1, #7 | ||
61 | ldrb r7, [r6, r1] | ||
62 | teq r4, #8 | ||
63 | beq Lrow8bpplp | ||
64 | @ | ||
65 | @ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) | ||
66 | @ | ||
67 | Lrow4bpplp: | ||
68 | ldr r7, [lr, r7, lsl #2] | ||
69 | mul r7, r2, r7 | ||
70 | sub r1, r1, #1 @ avoid using r7 directly after | ||
71 | str r7, [r0, -r5]! | ||
72 | ldrb r7, [r6, r1] | ||
73 | ldr r7, [lr, r7, lsl #2] | ||
74 | mul r7, r2, r7 | ||
75 | tst r1, #7 @ avoid using r7 directly after | ||
76 | str r7, [r0, -r5]! | ||
77 | subne r1, r1, #1 | ||
78 | ldrneb r7, [r6, r1] | ||
79 | bne Lrow4bpplp | ||
80 | LOADREGS(fd, sp!, {r4 - r7, pc}) | ||
81 | |||
82 | @ | ||
83 | @ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) | ||
84 | @ | ||
85 | Lrow8bpplp: | ||
86 | mov ip, r7, lsr #4 | ||
87 | ldr ip, [lr, ip, lsl #2] | ||
88 | mul r4, r2, ip | ||
89 | and ip, r7, #15 @ avoid r4 | ||
90 | ldr ip, [lr, ip, lsl #2] @ avoid r4 | ||
91 | mul ip, r2, ip @ avoid r4 | ||
92 | sub r1, r1, #1 @ avoid ip | ||
93 | sub r0, r0, r5 @ avoid ip | ||
94 | stmia r0, {r4, ip} | ||
95 | ldrb r7, [r6, r1] | ||
96 | mov ip, r7, lsr #4 | ||
97 | ldr ip, [lr, ip, lsl #2] | ||
98 | mul r4, r2, ip | ||
99 | and ip, r7, #15 @ avoid r4 | ||
100 | ldr ip, [lr, ip, lsl #2] @ avoid r4 | ||
101 | mul ip, r2, ip @ avoid r4 | ||
102 | tst r1, #7 @ avoid ip | ||
103 | sub r0, r0, r5 @ avoid ip | ||
104 | stmia r0, {r4, ip} | ||
105 | subne r1, r1, #1 | ||
106 | ldrneb r7, [r6, r1] | ||
107 | bne Lrow8bpplp | ||
108 | LOADREGS(fd, sp!, {r4 - r7, pc}) | ||
109 | |||
110 | @ | ||
111 | @ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc) | ||
112 | @ | ||
113 | Lrow1bpp: | ||
114 | add r6, r6, r1 | ||
115 | ldmia r6, {r4, r7} | ||
116 | strb r4, [r0], r5 | ||
117 | mov r4, r4, lsr #8 | ||
118 | strb r4, [r0], r5 | ||
119 | mov r4, r4, lsr #8 | ||
120 | strb r4, [r0], r5 | ||
121 | mov r4, r4, lsr #8 | ||
122 | strb r4, [r0], r5 | ||
123 | strb r7, [r0], r5 | ||
124 | mov r7, r7, lsr #8 | ||
125 | strb r7, [r0], r5 | ||
126 | mov r7, r7, lsr #8 | ||
127 | strb r7, [r0], r5 | ||
128 | mov r7, r7, lsr #8 | ||
129 | strb r7, [r0], r5 | ||
130 | LOADREGS(fd, sp!, {r4 - r7, pc}) | ||
131 | |||
132 | .bss | ||
133 | ENTRY(con_charconvtable) | ||
134 | .space 1024 | ||
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c new file mode 100644 index 000000000000..23434b56786a --- /dev/null +++ b/arch/arm/boot/compressed/misc.c | |||
@@ -0,0 +1,329 @@ | |||
1 | /* | ||
2 | * misc.c | ||
3 | * | ||
4 | * This is a collection of several routines from gzip-1.0.3 | ||
5 | * adapted for Linux. | ||
6 | * | ||
7 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | ||
8 | * | ||
9 | * Modified for ARM Linux by Russell King | ||
10 | * | ||
11 | * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : | ||
12 | * For this code to run directly from Flash, all constant variables must | ||
13 | * be marked with 'const' and all other variables initialized at run-time | ||
14 | * only. This way all non constant variables will end up in the bss segment, | ||
15 | * which should point to addresses in RAM and cleared to 0 on start. | ||
16 | * This allows for a much quicker boot time. | ||
17 | */ | ||
18 | |||
19 | unsigned int __machine_arch_type; | ||
20 | |||
21 | #include <linux/string.h> | ||
22 | |||
23 | #include <asm/arch/uncompress.h> | ||
24 | |||
25 | #ifdef STANDALONE_DEBUG | ||
26 | #define putstr printf | ||
27 | #endif | ||
28 | |||
29 | #ifdef CONFIG_DEBUG_ICEDCC | ||
30 | #define putstr icedcc_putstr | ||
31 | #define putc icedcc_putc | ||
32 | |||
33 | extern void idedcc_putc(int ch); | ||
34 | |||
35 | static void | ||
36 | icedcc_putstr(const char *ptr) | ||
37 | { | ||
38 | for (; *ptr != '\0'; ptr++) { | ||
39 | icedcc_putc(*ptr); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | #endif | ||
44 | |||
45 | #define __ptr_t void * | ||
46 | |||
47 | /* | ||
48 | * Optimised C version of memzero for the ARM. | ||
49 | */ | ||
50 | void __memzero (__ptr_t s, size_t n) | ||
51 | { | ||
52 | union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; | ||
53 | int i; | ||
54 | |||
55 | u.vp = s; | ||
56 | |||
57 | for (i = n >> 5; i > 0; i--) { | ||
58 | *u.ulp++ = 0; | ||
59 | *u.ulp++ = 0; | ||
60 | *u.ulp++ = 0; | ||
61 | *u.ulp++ = 0; | ||
62 | *u.ulp++ = 0; | ||
63 | *u.ulp++ = 0; | ||
64 | *u.ulp++ = 0; | ||
65 | *u.ulp++ = 0; | ||
66 | } | ||
67 | |||
68 | if (n & 1 << 4) { | ||
69 | *u.ulp++ = 0; | ||
70 | *u.ulp++ = 0; | ||
71 | *u.ulp++ = 0; | ||
72 | *u.ulp++ = 0; | ||
73 | } | ||
74 | |||
75 | if (n & 1 << 3) { | ||
76 | *u.ulp++ = 0; | ||
77 | *u.ulp++ = 0; | ||
78 | } | ||
79 | |||
80 | if (n & 1 << 2) | ||
81 | *u.ulp++ = 0; | ||
82 | |||
83 | if (n & 1 << 1) { | ||
84 | *u.ucp++ = 0; | ||
85 | *u.ucp++ = 0; | ||
86 | } | ||
87 | |||
88 | if (n & 1) | ||
89 | *u.ucp++ = 0; | ||
90 | } | ||
91 | |||
92 | static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, | ||
93 | size_t __n) | ||
94 | { | ||
95 | int i = 0; | ||
96 | unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; | ||
97 | |||
98 | for (i = __n >> 3; i > 0; i--) { | ||
99 | *d++ = *s++; | ||
100 | *d++ = *s++; | ||
101 | *d++ = *s++; | ||
102 | *d++ = *s++; | ||
103 | *d++ = *s++; | ||
104 | *d++ = *s++; | ||
105 | *d++ = *s++; | ||
106 | *d++ = *s++; | ||
107 | } | ||
108 | |||
109 | if (__n & 1 << 2) { | ||
110 | *d++ = *s++; | ||
111 | *d++ = *s++; | ||
112 | *d++ = *s++; | ||
113 | *d++ = *s++; | ||
114 | } | ||
115 | |||
116 | if (__n & 1 << 1) { | ||
117 | *d++ = *s++; | ||
118 | *d++ = *s++; | ||
119 | } | ||
120 | |||
121 | if (__n & 1) | ||
122 | *d++ = *s++; | ||
123 | |||
124 | return __dest; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * gzip delarations | ||
129 | */ | ||
130 | #define OF(args) args | ||
131 | #define STATIC static | ||
132 | |||
133 | typedef unsigned char uch; | ||
134 | typedef unsigned short ush; | ||
135 | typedef unsigned long ulg; | ||
136 | |||
137 | #define WSIZE 0x8000 /* Window size must be at least 32k, */ | ||
138 | /* and a power of two */ | ||
139 | |||
140 | static uch *inbuf; /* input buffer */ | ||
141 | static uch window[WSIZE]; /* Sliding window buffer */ | ||
142 | |||
143 | static unsigned insize; /* valid bytes in inbuf */ | ||
144 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
145 | static unsigned outcnt; /* bytes in output buffer */ | ||
146 | |||
147 | /* gzip flag byte */ | ||
148 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ | ||
149 | #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ | ||
150 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ | ||
151 | #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ | ||
152 | #define COMMENT 0x10 /* bit 4 set: file comment present */ | ||
153 | #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ | ||
154 | #define RESERVED 0xC0 /* bit 6,7: reserved */ | ||
155 | |||
156 | #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | ||
157 | |||
158 | /* Diagnostic functions */ | ||
159 | #ifdef DEBUG | ||
160 | # define Assert(cond,msg) {if(!(cond)) error(msg);} | ||
161 | # define Trace(x) fprintf x | ||
162 | # define Tracev(x) {if (verbose) fprintf x ;} | ||
163 | # define Tracevv(x) {if (verbose>1) fprintf x ;} | ||
164 | # define Tracec(c,x) {if (verbose && (c)) fprintf x ;} | ||
165 | # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} | ||
166 | #else | ||
167 | # define Assert(cond,msg) | ||
168 | # define Trace(x) | ||
169 | # define Tracev(x) | ||
170 | # define Tracevv(x) | ||
171 | # define Tracec(c,x) | ||
172 | # define Tracecv(c,x) | ||
173 | #endif | ||
174 | |||
175 | static int fill_inbuf(void); | ||
176 | static void flush_window(void); | ||
177 | static void error(char *m); | ||
178 | static void gzip_mark(void **); | ||
179 | static void gzip_release(void **); | ||
180 | |||
181 | extern char input_data[]; | ||
182 | extern char input_data_end[]; | ||
183 | |||
184 | static uch *output_data; | ||
185 | static ulg output_ptr; | ||
186 | static ulg bytes_out; | ||
187 | |||
188 | static void *malloc(int size); | ||
189 | static void free(void *where); | ||
190 | static void error(char *m); | ||
191 | static void gzip_mark(void **); | ||
192 | static void gzip_release(void **); | ||
193 | |||
194 | static void putstr(const char *); | ||
195 | |||
196 | extern int end; | ||
197 | static ulg free_mem_ptr; | ||
198 | static ulg free_mem_ptr_end; | ||
199 | |||
200 | #define HEAP_SIZE 0x2000 | ||
201 | |||
202 | #include "../../../../lib/inflate.c" | ||
203 | |||
204 | #ifndef STANDALONE_DEBUG | ||
205 | static void *malloc(int size) | ||
206 | { | ||
207 | void *p; | ||
208 | |||
209 | if (size <0) error("Malloc error"); | ||
210 | if (free_mem_ptr <= 0) error("Memory error"); | ||
211 | |||
212 | free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ | ||
213 | |||
214 | p = (void *)free_mem_ptr; | ||
215 | free_mem_ptr += size; | ||
216 | |||
217 | if (free_mem_ptr >= free_mem_ptr_end) | ||
218 | error("Out of memory"); | ||
219 | return p; | ||
220 | } | ||
221 | |||
222 | static void free(void *where) | ||
223 | { /* gzip_mark & gzip_release do the free */ | ||
224 | } | ||
225 | |||
226 | static void gzip_mark(void **ptr) | ||
227 | { | ||
228 | arch_decomp_wdog(); | ||
229 | *ptr = (void *) free_mem_ptr; | ||
230 | } | ||
231 | |||
232 | static void gzip_release(void **ptr) | ||
233 | { | ||
234 | arch_decomp_wdog(); | ||
235 | free_mem_ptr = (long) *ptr; | ||
236 | } | ||
237 | #else | ||
238 | static void gzip_mark(void **ptr) | ||
239 | { | ||
240 | } | ||
241 | |||
242 | static void gzip_release(void **ptr) | ||
243 | { | ||
244 | } | ||
245 | #endif | ||
246 | |||
247 | /* =========================================================================== | ||
248 | * Fill the input buffer. This is called only when the buffer is empty | ||
249 | * and at least one byte is really needed. | ||
250 | */ | ||
251 | int fill_inbuf(void) | ||
252 | { | ||
253 | if (insize != 0) | ||
254 | error("ran out of input data"); | ||
255 | |||
256 | inbuf = input_data; | ||
257 | insize = &input_data_end[0] - &input_data[0]; | ||
258 | |||
259 | inptr = 1; | ||
260 | return inbuf[0]; | ||
261 | } | ||
262 | |||
263 | /* =========================================================================== | ||
264 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
265 | * (Used for the decompressed data only.) | ||
266 | */ | ||
267 | void flush_window(void) | ||
268 | { | ||
269 | ulg c = crc; | ||
270 | unsigned n; | ||
271 | uch *in, *out, ch; | ||
272 | |||
273 | in = window; | ||
274 | out = &output_data[output_ptr]; | ||
275 | for (n = 0; n < outcnt; n++) { | ||
276 | ch = *out++ = *in++; | ||
277 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
278 | } | ||
279 | crc = c; | ||
280 | bytes_out += (ulg)outcnt; | ||
281 | output_ptr += (ulg)outcnt; | ||
282 | outcnt = 0; | ||
283 | putstr("."); | ||
284 | } | ||
285 | |||
286 | static void error(char *x) | ||
287 | { | ||
288 | putstr("\n\n"); | ||
289 | putstr(x); | ||
290 | putstr("\n\n -- System halted"); | ||
291 | |||
292 | while(1); /* Halt */ | ||
293 | } | ||
294 | |||
295 | #ifndef STANDALONE_DEBUG | ||
296 | |||
297 | ulg | ||
298 | decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, | ||
299 | int arch_id) | ||
300 | { | ||
301 | output_data = (uch *)output_start; /* Points to kernel start */ | ||
302 | free_mem_ptr = free_mem_ptr_p; | ||
303 | free_mem_ptr_end = free_mem_ptr_end_p; | ||
304 | __machine_arch_type = arch_id; | ||
305 | |||
306 | arch_decomp_setup(); | ||
307 | |||
308 | makecrc(); | ||
309 | putstr("Uncompressing Linux..."); | ||
310 | gunzip(); | ||
311 | putstr(" done, booting the kernel.\n"); | ||
312 | return output_ptr; | ||
313 | } | ||
314 | #else | ||
315 | |||
316 | char output_buffer[1500*1024]; | ||
317 | |||
318 | int main() | ||
319 | { | ||
320 | output_data = output_buffer; | ||
321 | |||
322 | makecrc(); | ||
323 | putstr("Uncompressing Linux..."); | ||
324 | gunzip(); | ||
325 | putstr("done.\n"); | ||
326 | return 0; | ||
327 | } | ||
328 | #endif | ||
329 | |||
diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c new file mode 100644 index 000000000000..7f6f5db0d060 --- /dev/null +++ b/arch/arm/boot/compressed/ofw-shark.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/ofw-shark.c | ||
3 | * | ||
4 | * by Alexander Schulz | ||
5 | * | ||
6 | * This file is used to get some basic information | ||
7 | * about the memory layout of the shark we are running | ||
8 | * on. Memory is usually divided in blocks a 8 MB. | ||
9 | * And bootargs are copied from OpenFirmware. | ||
10 | */ | ||
11 | |||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <asm/setup.h> | ||
16 | #include <asm/page.h> | ||
17 | |||
18 | |||
19 | asmlinkage void | ||
20 | create_params (unsigned long *buffer) | ||
21 | { | ||
22 | /* Is there a better address? Also change in mach-shark/core.c */ | ||
23 | struct tag *tag = (struct tag *) 0x08003000; | ||
24 | int j,i,m,k,nr_banks,size; | ||
25 | unsigned char *c; | ||
26 | |||
27 | k = 0; | ||
28 | |||
29 | /* Head of the taglist */ | ||
30 | tag->hdr.tag = ATAG_CORE; | ||
31 | tag->hdr.size = tag_size(tag_core); | ||
32 | tag->u.core.flags = 1; | ||
33 | tag->u.core.pagesize = PAGE_SIZE; | ||
34 | tag->u.core.rootdev = 0; | ||
35 | |||
36 | /* Build up one tagged block for each memory region */ | ||
37 | size=0; | ||
38 | nr_banks=(unsigned int) buffer[0]; | ||
39 | for (j=0;j<nr_banks;j++){ | ||
40 | /* search the lowest address and put it into the next entry */ | ||
41 | /* not a fast sort algorithm, but there are at most 8 entries */ | ||
42 | /* and this is used only once anyway */ | ||
43 | m=0xffffffff; | ||
44 | for (i=0;i<(unsigned int) buffer[0];i++){ | ||
45 | if (buffer[2*i+1]<m) { | ||
46 | m=buffer[2*i+1]; | ||
47 | k=i; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | tag = tag_next(tag); | ||
52 | tag->hdr.tag = ATAG_MEM; | ||
53 | tag->hdr.size = tag_size(tag_mem32); | ||
54 | tag->u.mem.size = buffer[2*k+2]; | ||
55 | tag->u.mem.start = buffer[2*k+1]; | ||
56 | |||
57 | size += buffer[2*k+2]; | ||
58 | |||
59 | buffer[2*k+1]=0xffffffff; /* mark as copied */ | ||
60 | } | ||
61 | |||
62 | /* The command line */ | ||
63 | tag = tag_next(tag); | ||
64 | tag->hdr.tag = ATAG_CMDLINE; | ||
65 | |||
66 | c=(unsigned char *)(&buffer[34]); | ||
67 | j=0; | ||
68 | while (*c) tag->u.cmdline.cmdline[j++]=*c++; | ||
69 | |||
70 | tag->u.cmdline.cmdline[j]=0; | ||
71 | tag->hdr.size = (j + 7 + sizeof(struct tag_header)) >> 2; | ||
72 | |||
73 | /* Hardware revision */ | ||
74 | tag = tag_next(tag); | ||
75 | tag->hdr.tag = ATAG_REVISION; | ||
76 | tag->hdr.size = tag_size(tag_revision); | ||
77 | tag->u.revision.rev = ((unsigned char) buffer[33])-'0'; | ||
78 | |||
79 | /* End of the taglist */ | ||
80 | tag = tag_next(tag); | ||
81 | tag->hdr.tag = 0; | ||
82 | tag->hdr.size = 0; | ||
83 | } | ||
84 | |||
85 | |||
86 | typedef int (*ofw_handle_t)(void *); | ||
87 | |||
88 | /* Everything below is called with a wrong MMU setting. | ||
89 | * This means: no string constants, no initialization of | ||
90 | * arrays, no global variables! This is ugly but I didn't | ||
91 | * want to write this in assembler :-) | ||
92 | */ | ||
93 | |||
94 | int | ||
95 | of_decode_int(const unsigned char *p) | ||
96 | { | ||
97 | unsigned int i = *p++ << 8; | ||
98 | i = (i + *p++) << 8; | ||
99 | i = (i + *p++) << 8; | ||
100 | return (i + *p); | ||
101 | } | ||
102 | |||
103 | int | ||
104 | OF_finddevice(ofw_handle_t openfirmware, char *name) | ||
105 | { | ||
106 | unsigned int args[8]; | ||
107 | char service[12]; | ||
108 | |||
109 | service[0]='f'; | ||
110 | service[1]='i'; | ||
111 | service[2]='n'; | ||
112 | service[3]='d'; | ||
113 | service[4]='d'; | ||
114 | service[5]='e'; | ||
115 | service[6]='v'; | ||
116 | service[7]='i'; | ||
117 | service[8]='c'; | ||
118 | service[9]='e'; | ||
119 | service[10]='\0'; | ||
120 | |||
121 | args[0]=(unsigned int)service; | ||
122 | args[1]=1; | ||
123 | args[2]=1; | ||
124 | args[3]=(unsigned int)name; | ||
125 | |||
126 | if (openfirmware(args) == -1) | ||
127 | return -1; | ||
128 | return args[4]; | ||
129 | } | ||
130 | |||
131 | int | ||
132 | OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop) | ||
133 | { | ||
134 | unsigned int args[8]; | ||
135 | char service[12]; | ||
136 | |||
137 | service[0]='g'; | ||
138 | service[1]='e'; | ||
139 | service[2]='t'; | ||
140 | service[3]='p'; | ||
141 | service[4]='r'; | ||
142 | service[5]='o'; | ||
143 | service[6]='p'; | ||
144 | service[7]='l'; | ||
145 | service[8]='e'; | ||
146 | service[9]='n'; | ||
147 | service[10]='\0'; | ||
148 | |||
149 | args[0] = (unsigned int)service; | ||
150 | args[1] = 2; | ||
151 | args[2] = 1; | ||
152 | args[3] = (unsigned int)handle; | ||
153 | args[4] = (unsigned int)prop; | ||
154 | |||
155 | if (openfirmware(args) == -1) | ||
156 | return -1; | ||
157 | return args[5]; | ||
158 | } | ||
159 | |||
160 | int | ||
161 | OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen) | ||
162 | { | ||
163 | unsigned int args[8]; | ||
164 | char service[8]; | ||
165 | |||
166 | service[0]='g'; | ||
167 | service[1]='e'; | ||
168 | service[2]='t'; | ||
169 | service[3]='p'; | ||
170 | service[4]='r'; | ||
171 | service[5]='o'; | ||
172 | service[6]='p'; | ||
173 | service[7]='\0'; | ||
174 | |||
175 | args[0] = (unsigned int)service; | ||
176 | args[1] = 4; | ||
177 | args[2] = 1; | ||
178 | args[3] = (unsigned int)handle; | ||
179 | args[4] = (unsigned int)prop; | ||
180 | args[5] = (unsigned int)buf; | ||
181 | args[6] = buflen; | ||
182 | |||
183 | if (openfirmware(args) == -1) | ||
184 | return -1; | ||
185 | return args[7]; | ||
186 | } | ||
187 | |||
188 | asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) | ||
189 | { | ||
190 | int phandle,i,mem_len,buffer[32]; | ||
191 | char temp[15]; | ||
192 | |||
193 | temp[0]='/'; | ||
194 | temp[1]='m'; | ||
195 | temp[2]='e'; | ||
196 | temp[3]='m'; | ||
197 | temp[4]='o'; | ||
198 | temp[5]='r'; | ||
199 | temp[6]='y'; | ||
200 | temp[7]='\0'; | ||
201 | |||
202 | phandle=OF_finddevice(o,temp); | ||
203 | |||
204 | temp[0]='r'; | ||
205 | temp[1]='e'; | ||
206 | temp[2]='g'; | ||
207 | temp[3]='\0'; | ||
208 | |||
209 | mem_len = OF_getproplen(o,phandle, temp); | ||
210 | OF_getprop(o,phandle, temp, buffer, mem_len); | ||
211 | *nomr=mem_len >> 3; | ||
212 | |||
213 | for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]); | ||
214 | |||
215 | temp[0]='/'; | ||
216 | temp[1]='c'; | ||
217 | temp[2]='h'; | ||
218 | temp[3]='o'; | ||
219 | temp[4]='s'; | ||
220 | temp[5]='e'; | ||
221 | temp[6]='n'; | ||
222 | temp[7]='\0'; | ||
223 | |||
224 | phandle=OF_finddevice(o,temp); | ||
225 | |||
226 | temp[0]='b'; | ||
227 | temp[1]='o'; | ||
228 | temp[2]='o'; | ||
229 | temp[3]='t'; | ||
230 | temp[4]='a'; | ||
231 | temp[5]='r'; | ||
232 | temp[6]='g'; | ||
233 | temp[7]='s'; | ||
234 | temp[8]='\0'; | ||
235 | |||
236 | mem_len = OF_getproplen(o,phandle, temp); | ||
237 | OF_getprop(o,phandle, temp, buffer, mem_len); | ||
238 | if (mem_len > 128) mem_len=128; | ||
239 | for (i=0; i<=mem_len/4; i++) pointer[i+33]=buffer[i]; | ||
240 | pointer[i+33]=0; | ||
241 | |||
242 | temp[0]='/'; | ||
243 | temp[1]='\0'; | ||
244 | phandle=OF_finddevice(o,temp); | ||
245 | temp[0]='b'; | ||
246 | temp[1]='a'; | ||
247 | temp[2]='n'; | ||
248 | temp[3]='n'; | ||
249 | temp[4]='e'; | ||
250 | temp[5]='r'; | ||
251 | temp[6]='-'; | ||
252 | temp[7]='n'; | ||
253 | temp[8]='a'; | ||
254 | temp[9]='m'; | ||
255 | temp[10]='e'; | ||
256 | temp[11]='\0'; | ||
257 | mem_len = OF_getproplen(o,phandle, temp); | ||
258 | OF_getprop(o,phandle, temp, buffer, mem_len); | ||
259 | (unsigned char) pointer[32] = ((unsigned char *) buffer)[mem_len-2]; | ||
260 | } | ||
diff --git a/arch/arm/boot/compressed/piggy.S b/arch/arm/boot/compressed/piggy.S new file mode 100644 index 000000000000..54c951800ebd --- /dev/null +++ b/arch/arm/boot/compressed/piggy.S | |||
@@ -0,0 +1,6 @@ | |||
1 | .section .piggydata,#alloc | ||
2 | .globl input_data | ||
3 | input_data: | ||
4 | .incbin "arch/arm/boot/compressed/piggy.gz" | ||
5 | .globl input_data_end | ||
6 | input_data_end: | ||
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in new file mode 100644 index 000000000000..eed616113e47 --- /dev/null +++ b/arch/arm/boot/compressed/vmlinux.lds.in | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/boot/compressed/vmlinux.lds.in | ||
3 | * | ||
4 | * Copyright (C) 2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | OUTPUT_ARCH(arm) | ||
11 | ENTRY(_start) | ||
12 | SECTIONS | ||
13 | { | ||
14 | . = TEXT_START; | ||
15 | _text = .; | ||
16 | |||
17 | .text : { | ||
18 | _start = .; | ||
19 | *(.start) | ||
20 | *(.text) | ||
21 | *(.fixup) | ||
22 | *(.gnu.warning) | ||
23 | *(.rodata) | ||
24 | *(.rodata.*) | ||
25 | *(.glue_7) | ||
26 | *(.glue_7t) | ||
27 | *(.piggydata) | ||
28 | . = ALIGN(4); | ||
29 | } | ||
30 | |||
31 | _etext = .; | ||
32 | |||
33 | _got_start = .; | ||
34 | .got : { *(.got) } | ||
35 | _got_end = .; | ||
36 | .got.plt : { *(.got.plt) } | ||
37 | .data : { *(.data) } | ||
38 | _edata = .; | ||
39 | |||
40 | . = BSS_START; | ||
41 | __bss_start = .; | ||
42 | .bss : { *(.bss) } | ||
43 | _end = .; | ||
44 | |||
45 | .stack (NOLOAD) : { *(.stack) } | ||
46 | |||
47 | .stab 0 : { *(.stab) } | ||
48 | .stabstr 0 : { *(.stabstr) } | ||
49 | .stab.excl 0 : { *(.stab.excl) } | ||
50 | .stab.exclstr 0 : { *(.stab.exclstr) } | ||
51 | .stab.index 0 : { *(.stab.index) } | ||
52 | .stab.indexstr 0 : { *(.stab.indexstr) } | ||
53 | .comment 0 : { *(.comment) } | ||
54 | } | ||
55 | |||
diff --git a/arch/arm/boot/install.sh b/arch/arm/boot/install.sh new file mode 100644 index 000000000000..935bb27369e9 --- /dev/null +++ b/arch/arm/boot/install.sh | |||
@@ -0,0 +1,52 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # arch/arm/boot/install.sh | ||
4 | # | ||
5 | # This file is subject to the terms and conditions of the GNU General Public | ||
6 | # License. See the file "COPYING" in the main directory of this archive | ||
7 | # for more details. | ||
8 | # | ||
9 | # Copyright (C) 1995 by Linus Torvalds | ||
10 | # | ||
11 | # Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin | ||
12 | # Adapted from code in arch/i386/boot/install.sh by Russell King | ||
13 | # | ||
14 | # "make install" script for arm architecture | ||
15 | # | ||
16 | # Arguments: | ||
17 | # $1 - kernel version | ||
18 | # $2 - kernel image file | ||
19 | # $3 - kernel map file | ||
20 | # $4 - default install path (blank if root directory) | ||
21 | # | ||
22 | |||
23 | # User may have a custom install script | ||
24 | if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi | ||
25 | if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi | ||
26 | |||
27 | if [ "$(basename $2)" = "zImage" ]; then | ||
28 | # Compressed install | ||
29 | echo "Installing compressed kernel" | ||
30 | base=vmlinuz | ||
31 | else | ||
32 | # Normal install | ||
33 | echo "Installing normal kernel" | ||
34 | base=vmlinux | ||
35 | fi | ||
36 | |||
37 | if [ -f $4/$base-$1 ]; then | ||
38 | mv $4/$base-$1 $4/$base-$1.old | ||
39 | fi | ||
40 | cat $2 > $4/$base-$1 | ||
41 | |||
42 | # Install system map file | ||
43 | if [ -f $4/System.map-$1 ]; then | ||
44 | mv $4/System.map-$1 $4/System.map-$1.old | ||
45 | fi | ||
46 | cp $3 $4/System.map-$1 | ||
47 | |||
48 | if [ -x /sbin/loadmap ]; then | ||
49 | /sbin/loadmap | ||
50 | else | ||
51 | echo "You have to install it yourself" | ||
52 | fi | ||