diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/arm/boot/compressed |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/arm/boot/compressed')
-rw-r--r-- | arch/arm/boot/compressed/Makefile | 114 | ||||
-rw-r--r-- | arch/arm/boot/compressed/Makefile.debug | 23 | ||||
-rw-r--r-- | arch/arm/boot/compressed/big-endian.S | 13 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-clps7500.S | 87 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-epxa10db.S | 5 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-l7200.S | 30 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-sa1100.S | 48 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-shark.S | 115 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-sharpsl.S | 92 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head-xscale.S | 49 | ||||
-rw-r--r-- | arch/arm/boot/compressed/head.S | 786 | ||||
-rw-r--r-- | arch/arm/boot/compressed/ice-dcc.S | 17 | ||||
-rw-r--r-- | arch/arm/boot/compressed/ll_char_wr.S | 134 | ||||
-rw-r--r-- | arch/arm/boot/compressed/misc.c | 329 | ||||
-rw-r--r-- | arch/arm/boot/compressed/ofw-shark.c | 260 | ||||
-rw-r--r-- | arch/arm/boot/compressed/piggy.S | 6 | ||||
-rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.in | 55 |
17 files changed, 2163 insertions, 0 deletions
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile new file mode 100644 index 00000000000..6b505ce41a7 --- /dev/null +++ b/arch/arm/boot/compressed/Makefile @@ -0,0 +1,114 @@ +# +# linux/arch/arm/boot/compressed/Makefile +# +# create a compressed vmlinuz image from the original vmlinux +# + +HEAD = head.o +OBJS = misc.o +FONTC = drivers/video/console/font_acorn_8x8.c + +FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o) + +# +# Architecture dependencies +# +ifeq ($(CONFIG_ARCH_ACORN),y) +OBJS += ll_char_wr.o $(FONT) +endif + +ifeq ($(CONFIG_ARCH_SHARK),y) +OBJS += head-shark.o ofw-shark.o +endif + +ifeq ($(CONFIG_ARCH_CAMELOT),y) +OBJS += head-epxa10db.o +endif + +ifeq ($(CONFIG_ARCH_L7200),y) +OBJS += head-l7200.o +endif + +ifeq ($(CONFIG_ARCH_CLPS7500),y) +HEAD = head-clps7500.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_CPU_XSCALE),y) +OBJS += head-xscale.o +endif + +ifeq ($(CONFIG_PXA_SHARPSL),y) +OBJS += head-sharpsl.o +endif + +ifeq ($(CONFIG_DEBUG_ICEDCC),y) +OBJS += ice-dcc.o +endif + +ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) +OBJS += big-endian.o +endif + +# +# We now have a PIC decompressor implementation. Decompressors running +# from RAM should not define ZTEXTADDR. Decompressors running directly +# from ROM or Flash must define ZTEXTADDR (preferably via the config) +# FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK +ifeq ($(CONFIG_ZBOOT_ROM),y) +ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) +ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) +else +ZTEXTADDR := 0 +ZBSSADDR := ALIGN(4) +endif + +SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ + +targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \ + head.o misc.o $(OBJS) +EXTRA_CFLAGS := -fpic +EXTRA_AFLAGS := + +# Supply ZRELADDR, INITRD_PHYS and PARAMS_PHYS to the decompressor via +# linker symbols. We only define initrd_phys and params_phys if the +# machine class defined the corresponding makefile variable. +LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) +ifneq ($(INITRD_PHYS),) +LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS) +endif +ifneq ($(PARAMS_PHYS),) +LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) +endif +LDFLAGS_vmlinux += -p --no-undefined -X \ + $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -T + +# Don't allow any static data in misc.o, which +# would otherwise mess up our GOT table +CFLAGS_misc.o := -Dstatic= + +$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \ + $(addprefix $(obj)/, $(OBJS)) FORCE + $(call if_changed,ld) + @: + +$(obj)/piggy.gz: $(obj)/../Image FORCE + $(call if_changed,gzip) + +$(obj)/piggy.o: $(obj)/piggy.gz FORCE + +CFLAGS_font_acorn_8x8.o := -Dstatic= + +$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config + @sed "$(SEDFLAGS)" < $< > $@ + +$(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c + diff --git a/arch/arm/boot/compressed/Makefile.debug b/arch/arm/boot/compressed/Makefile.debug new file mode 100644 index 00000000000..491a037b297 --- /dev/null +++ b/arch/arm/boot/compressed/Makefile.debug @@ -0,0 +1,23 @@ +# +# linux/arch/arm/boot/compressed/Makefile +# +# create a compressed vmlinux image from the original vmlinux +# + +COMPRESSED_EXTRA=../../lib/ll_char_wr.o +OBJECTS=misc-debug.o ll_char_wr.aout.o + +CFLAGS=-D__KERNEL__ -O2 -DSTDC_HEADERS -DSTANDALONE_DEBUG -Wall -I../../../../include -c + +test-gzip: piggy.aout.o $(OBJECTS) + $(CC) -o $@ $(OBJECTS) piggy.aout.o + +misc-debug.o: misc.c + $(CC) $(CFLAGS) -o $@ misc.c + +piggy.aout.o: piggy.o + arm-linuxelf-objcopy --change-leading-char -I elf32-arm -O arm-aout32-linux piggy.o piggy.aout.o + +ll_char_wr.aout.o: $(COMPRESSED_EXTRA) + arm-linuxelf-objcopy --change-leading-char -I elf32-arm -O arm-aout32-linux $(COMPRESSED_EXTRA) ll_char_wr.aout.o + diff --git a/arch/arm/boot/compressed/big-endian.S b/arch/arm/boot/compressed/big-endian.S new file mode 100644 index 00000000000..25ab26f1c6f --- /dev/null +++ b/arch/arm/boot/compressed/big-endian.S @@ -0,0 +1,13 @@ +/* + * linux/arch/arm/boot/compressed/big-endian.S + * + * Switch CPU into big endian mode. + * Author: Nicolas Pitre + */ + + .section ".start", #alloc, #execinstr + + mrc p15, 0, r0, c1, c0, 0 @ read control reg + orr r0, r0, #(1 << 7) @ enable big endian mode + mcr p15, 0, r0, c1, c0, 0 @ write control reg + diff --git a/arch/arm/boot/compressed/head-clps7500.S b/arch/arm/boot/compressed/head-clps7500.S new file mode 100644 index 00000000000..4a8a689d15e --- /dev/null +++ b/arch/arm/boot/compressed/head-clps7500.S @@ -0,0 +1,87 @@ +/* + * linux/arch/arm/boot/compressed/head.S + * + * Copyright (C) 1999, 2000, 2001 Nexus Electronics Ltd + */ + +#include <linux/config.h> + + /* There are three different ways the kernel can be + booted on a 7500 system: from Angel (loaded in RAM), from + 16-bit ROM or from 32-bit Flash. Luckily, a single kernel + image does for them all. */ + /* This branch is taken if the CPU memory width matches the + actual device in use. The default at power on is 16 bits + so we must be prepared for a mismatch. */ + .section ".start", "ax" +2: + b 1f + .word 0xffff + .word 0xb632 @ mov r11, #0x03200000 + .word 0xe3a0 + .word 0x0000 @ mov r0, #0 + .word 0xe3a0 + .word 0x0080 @ strb r0, [r11, #0x80] + .word 0xe5cb + .word 0xf000 @ mov pc, #0 + .word 0xe3a0 +1: + adr r1, 2b + teq r1, #0 + bne .Langel + /* This is a direct-from-ROM boot. Copy the kernel into + RAM and run it there. */ + mov r0, #0x30 + mcr p15, 0, r0, c1, c0, 0 + mov r0, #0x13 + msr cpsr_cxsf, r0 + mov r12, #0x03000000 @ point to LEDs + orr r12, r12, #0x00020000 + orr r12, r12, #0xba00 + mov r0, #0x5500 + str r0, [r12] + mov r0, #0x10000000 + orr r0, r0, #0x8000 + mov r4, r0 + ldr r2, =_end +2: + ldr r3, [r1], #4 + str r3, [r0], #4 + teq r0, r2 + bne 2b + mov r0, #0xff00 + str r0, [r12] +1: + mov r12, #0x03000000 @ point to LEDs + orr r12, r12, #0x00020000 + orr r12, r12, #0xba00 + mov r0, #0xfe00 + str r0, [r12] + + adr lr, 1f + mov r0, #0 + mov r1, #14 /* MACH_TYPE_CLPS7500 */ + mov pc, lr +.Langel: +#ifdef CONFIG_ANGELBOOT + /* Call Angel to switch into SVC mode. */ + mov r0, #0x17 + swi 0x123456 +#endif + /* Ensure all interrupts are off and MMU disabled */ + mrs r0, cpsr + orr r0, r0, #0xc0 + msr cpsr_cxsf, r0 + + adr lr, 1b + orr lr, lr, #0x10000000 + mov r0, #0x30 @ MMU off + mcr p15, 0, r0, c1, c0, 0 + mov r0, r0 + mov pc, lr + + .ltorg + +1: +/* And the rest */ +#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 00000000000..757681f12a3 --- /dev/null +++ b/arch/arm/boot/compressed/head-epxa10db.S @@ -0,0 +1,5 @@ +#include <asm/mach-types.h> +#include <asm/arch/excalibur.h> + + .section ".start", "ax" + 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 00000000000..b08bd23f8d1 --- /dev/null +++ b/arch/arm/boot/compressed/head-l7200.S @@ -0,0 +1,30 @@ +/* + * linux/arch/arm/boot/compressed/head-l7200.S + * + * Copyright (C) 2000 Steve Hill <sjhill@cotw.com> + * + * Some code borrowed from Nicolas Pitre's 'head-sa1100.S' file. This + * is merged with head.S by the linker. + */ + +#include <linux/config.h> +#include <asm/mach-types.h> + +#ifndef CONFIG_ARCH_L7200 +#error What am I doing here... +#endif + + .section ".start", "ax" + +__L7200_start: + mov r0, #0x00100000 @ FLASH address of initrd + mov r2, #0xf1000000 @ RAM address of initrd + add r3, r2, #0x00700000 @ Size of initrd +1: + ldmia r0!, {r4, r5, r6, r7} + stmia r2!, {r4, r5, r6, r7} + cmp r2, r3 + ble 1b + + mov r8, #0 @ Zero it out + 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 00000000000..5aefffd4604 --- /dev/null +++ b/arch/arm/boot/compressed/head-sa1100.S @@ -0,0 +1,48 @@ +/* + * linux/arch/arm/boot/compressed/head-sa1100.S + * + * Copyright (C) 1999 Nicolas Pitre <nico@cam.org> + * + * SA1100 specific tweaks. This is merged into head.S by the linker. + * + */ + +#include <linux/config.h> +#include <linux/linkage.h> +#include <asm/mach-types.h> + + .section ".start", "ax" + +__SA1100_start: + + @ Preserve r8/r7 i.e. kernel entry values +#ifdef CONFIG_SA1100_COLLIE + mov r7, #MACH_TYPE_COLLIE +#endif +#ifdef CONFIG_SA1100_SIMPAD + @ UNTIL we've something like an open bootldr + mov r7, #MACH_TYPE_SIMPAD @should be 87 +#endif + mrc p15, 0, r0, c1, c0, 0 @ read control reg + ands r0, r0, #0x0d + beq 99f + + @ Data cache might be active. + @ Be sure to flush kernel binary out of the cache, + @ whatever state it is, before it is turned off. + @ This is done by fetching through currently executed + @ memory to be sure we hit the same cache. + bic r2, pc, #0x1f + add r3, r2, #0x4000 @ 16 kb is quite enough... +1: ldr r0, [r2], #32 + teq r2, r3 + bne 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches + + @ disabling MMU and caches + mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #0x0d @ clear WB, DC, MMU + bic r0, r0, #0x1000 @ clear Icache + mcr p15, 0, r0, c1, c0, 0 +99: diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S new file mode 100644 index 00000000000..848f60e5429 --- /dev/null +++ b/arch/arm/boot/compressed/head-shark.S @@ -0,0 +1,115 @@ +/* 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 0x08508000 +__copy_end: .long 0x08608000 + + .word _start + .word __bss_start + + .align +__temp_stack: .space 128 + +__mmu_off: + adr r0, __ofw_data + ldr r0, [r0, #4] + orr r0, r0, #0x00600000 + + 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 + */ + + +__Copy: ldr r2, [r0], #-4 + str r2, [r1], #-4 + teq r1, r3 + bne __Copy + /* and jump to it */ + adr r2, __go_on + adr r0, __ofw_data + ldr r0, [r0, #4] + sub r2, r2, r0 + sub r2, r2, #0x00500000 + ldr r0, __copy_target + add r2, r2, r0 + mov pc, r2 + +__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-sharpsl.S b/arch/arm/boot/compressed/head-sharpsl.S new file mode 100644 index 00000000000..d6bf8a2b090 --- /dev/null +++ b/arch/arm/boot/compressed/head-sharpsl.S @@ -0,0 +1,92 @@ +/* + * linux/arch/arm/boot/compressed/head-sharpsl.S + * + * Copyright (C) 2004-2005 Richard Purdie <rpurdie@rpsys.net> + * + * Sharp's bootloader doesn't pass any kind of machine ID + * so we have to figure out the machine for ourselves... + * + * Support for Poodle, Corgi (SL-C700), Shepherd (SL-C750) + * and Husky (SL-C760). + * + */ + +#include <linux/config.h> +#include <linux/linkage.h> +#include <asm/mach-types.h> + +#ifndef CONFIG_PXA_SHARPSL +#error What am I doing here... +#endif + + .section ".start", "ax" + +__SharpSL_start: + + ldr r1, .W100ADDR @ Base address of w100 chip + regs offset + + mov r6, #0x31 @ Load Magic Init value + str r6, [r1, #0x280] @ to SCRATCH_UMSK + mov r5, #0x3000 +.W100LOOP: + subs r5, r5, #1 + bne .W100LOOP + mov r6, #0x30 @ Load 2nd Magic Init value + str r6, [r1, #0x280] @ to SCRATCH_UMSK + + ldr r6, [r1, #0] @ Load Chip ID + ldr r3, .W100ID + ldr r7, .POODLEID + cmp r6, r3 + bne .SHARPEND @ We have no w100 - Poodle + + mrc p15, 0, r6, c0, c0 @ Get Processor ID + and r6, r6, #0xffffff00 + ldr r7, .CORGIID + ldr r3, .PXA255ID + cmp r6, r3 + blo .SHARPEND @ We have a PXA250 - Corgi + + mov r1, #0x0c000000 @ Base address of NAND chip + ldrb r3, [r1, #24] @ Load FLASHCTL + bic r3, r3, #0x11 @ SET NCE + orr r3, r3, #0x0a @ SET CLR + FLWP + strb r3, [r1, #24] @ Save to FLASHCTL + mov r2, #0x90 @ Command "readid" + strb r2, [r1, #20] @ Save to FLASHIO + bic r3, r3, #2 @ CLR CLE + orr r3, r3, #4 @ SET ALE + strb r3, [r1, #24] @ Save to FLASHCTL + mov r2, #0 @ Address 0x00 + strb r2, [r1, #20] @ Save to FLASHIO + bic r3, r3, #4 @ CLR ALE + strb r3, [r1, #24] @ Save to FLASHCTL +.SHARP1: + ldrb r3, [r1, #24] @ Load FLASHCTL + tst r3, #32 @ Is chip ready? + beq .SHARP1 + ldrb r2, [r1, #20] @ NAND Manufacturer ID + ldrb r3, [r1, #20] @ NAND Chip ID + ldr r7, .SHEPHERDID + cmp r3, #0x76 @ 64MiB flash + beq .SHARPEND @ We have Shepherd + ldr r7, .HUSKYID @ Must be Husky + b .SHARPEND + +.PXA255ID: + .word 0x69052d00 @ PXA255 Processor ID +.W100ID: + .word 0x57411002 @ w100 Chip ID +.W100ADDR: + .word 0x08010000 @ w100 Chip ID Reg Address +.POODLEID: + .word MACH_TYPE_POODLE +.CORGIID: + .word MACH_TYPE_CORGI +.SHEPHERDID: + .word MACH_TYPE_SHEPHERD +.HUSKYID: + .word MACH_TYPE_HUSKY +.SHARPEND: + + diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S new file mode 100644 index 00000000000..665bd2c2074 --- /dev/null +++ b/arch/arm/boot/compressed/head-xscale.S @@ -0,0 +1,49 @@ +/* + * linux/arch/arm/boot/compressed/head-xscale.S + * + * XScale specific tweaks. This is merged into head.S by the linker. + * + */ + +#include <linux/config.h> +#include <linux/linkage.h> +#include <asm/mach-types.h> + + .section ".start", "ax" + +__XScale_start: + + @ Preserve r8/r7 i.e. kernel entry values + + @ Data cache might be active. + @ Be sure to flush kernel binary out of the cache, + @ whatever state it is, before it is turned off. + @ This is done by fetching through currently executed + @ memory to be sure we hit the same cache. + bic r2, pc, #0x1f + add r3, r2, #0x10000 @ 64 kb is quite enough... +1: ldr r0, [r2], #32 + teq r2, r3 + bne 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches + + @ disabling MMU and caches + mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #0x05 @ clear DC, MMU + bic r0, r0, #0x1000 @ clear Icache + mcr p15, 0, r0, c1, c0, 0 + +#ifdef CONFIG_ARCH_LUBBOCK + mov r7, #MACH_TYPE_LUBBOCK +#endif + +#ifdef CONFIG_ARCH_COTULLA_IDP + mov r7, #MACH_TYPE_COTULLA_IDP +#endif + +#ifdef CONFIG_MACH_GTWX5715 + mov r7, #(MACH_TYPE_GTWX5715 & 0xff) + orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00) +#endif + diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S new file mode 100644 index 00000000000..c0e7aff3dec --- /dev/null +++ b/arch/arm/boot/compressed/head.S @@ -0,0 +1,786 @@ +/* + * linux/arch/arm/boot/compressed/head.S + * + * Copyright (C) 1996-2002 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/config.h> +#include <linux/linkage.h> + +/* + * Debugging stuff + * + * Note that these macros must not contain any code which is not + * 100% relocatable. Any attempt to do so will result in a crash. + * Please select one of the following when turning on debugging. + */ +#ifdef DEBUG +#if defined(CONFIG_DEBUG_DC21285_PORT) + .macro loadsp, rb + mov \rb, #0x42000000 + .endm + .macro writeb, rb + str \rb, [r3, #0x160] + .endm +#elif defined(CONFIG_DEBUG_ICEDCC) + .macro loadsp, rb + .endm + .macro writeb, rb + mcr p14, 0, \rb, c0, c1, 0 + .endm +#elif defined(CONFIG_FOOTBRIDGE) + .macro loadsp, rb + mov \rb, #0x7c000000 + .endm + .macro writeb, rb + strb \rb, [r3, #0x3f8] + .endm +#elif defined(CONFIG_ARCH_RPC) + .macro loadsp, rb + mov \rb, #0x03000000 + orr \rb, \rb, #0x00010000 + .endm + .macro writeb, rb + strb \rb, [r3, #0x3f8 << 2] + .endm +#elif defined(CONFIG_ARCH_INTEGRATOR) + .macro loadsp, rb + mov \rb, #0x16000000 + .endm + .macro writeb, rb + strb \rb, [r3, #0] + .endm +#elif defined(CONFIG_ARCH_PXA) /* Xscale-type */ + .macro loadsp, rb + mov \rb, #0x40000000 + orr \rb, \rb, #0x00100000 + .endm + .macro writeb, rb + strb \rb, [r3, #0] + .endm +#elif defined(CONFIG_ARCH_SA1100) + .macro loadsp, rb + mov \rb, #0x80000000 @ physical base address +# if defined(CONFIG_DEBUG_LL_SER3) + add \rb, \rb, #0x00050000 @ Ser3 +# else + add \rb, \rb, #0x00010000 @ Ser1 +# endif + .endm + .macro writeb, rb + str \rb, [r3, #0x14] @ UTDR + .endm +#elif defined(CONFIG_ARCH_IXP4XX) + .macro loadsp, rb + mov \rb, #0xc8000000 + .endm + .macro writeb, rb + str \rb, [r3, #0] +#elif defined(CONFIG_ARCH_IXP2000) + .macro loadsp, rb + mov \rb, #0xc0000000 + orr \rb, \rb, #0x00030000 + .endm + .macro writeb, rb + str \rb, [r3, #0] + .endm +#elif defined(CONFIG_ARCH_LH7A40X) + .macro loadsp, rb + ldr \rb, =0x80000700 @ UART2 UARTBASE + .endm + .macro writeb, rb + strb \rb, [r3, #0] + .endm +#elif defined(CONFIG_ARCH_OMAP) + .macro loadsp, rb + mov \rb, #0xff000000 @ physical base address + add \rb, \rb, #0x00fb0000 +#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3) + add \rb, \rb, #0x00000800 +#endif +#ifdef CONFIG_OMAP_LL_DEBUG_UART3 + add \rb, \rb, #0x00009000 +#endif + .endm + .macro writeb, rb + strb \rb, [r3] + .endm +#elif defined(CONFIG_ARCH_IOP331) + .macro loadsp, rb + mov \rb, #0xff000000 + orr \rb, \rb, #0x00ff0000 + orr \rb, \rb, #0x0000f700 @ location of the UART + .endm + .macro writeb, rb + str \rb, [r3, #0] + .endm +#elif defined(CONFIG_ARCH_S3C2410) + .macro loadsp, rb + mov \rb, #0x50000000 + add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT + .endm + .macro writeb, rb + strb \rb, [r3, #0x20] + .endm +#else +#error no serial architecture defined +#endif +#endif + + .macro kputc,val + mov r0, \val + bl putc + .endm + + .macro kphex,val,len + mov r0, \val + mov r1, #\len + bl phex + .endm + + .macro debug_reloc_start +#ifdef DEBUG + kputc #'\n' + kphex r6, 8 /* processor id */ + kputc #':' + kphex r7, 8 /* architecture id */ + kputc #':' + mrc p15, 0, r0, c1, c0 + kphex r0, 8 /* control reg */ + kputc #'\n' + kphex r5, 8 /* decompressed kernel start */ + kputc #'-' + kphex r8, 8 /* decompressed kernel end */ + kputc #'>' + kphex r4, 8 /* kernel execution address */ + kputc #'\n' +#endif + .endm + + .macro debug_reloc_end +#ifdef DEBUG + kphex r5, 8 /* end of kernel */ + kputc #'\n' + mov r0, r4 + bl memdump /* dump 256 bytes at start of kernel */ +#endif + .endm + + .section ".start", #alloc, #execinstr +/* + * sort out different calling conventions + */ + .align +start: + .type start,#function + .rept 8 + mov r0, r0 + .endr + + b 1f + .word 0x016f2818 @ Magic numbers to help the loader + .word start @ absolute load/run zImage address + .word _edata @ zImage end address +1: mov r7, r1 @ save architecture ID + mov r8, #0 @ save r0 + +#ifndef __ARM_ARCH_2__ + /* + * Booting from Angel - need to enter SVC mode and disable + * FIQs/IRQs (numeric definitions from angel arm.h source). + * We only do this if we were in user mode on entry. + */ + mrs r2, cpsr @ get current mode + tst r2, #3 @ not user? + bne not_angel + mov r0, #0x17 @ angel_SWIreason_EnterSVC + swi 0x123456 @ angel_SWI_ARM +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 + + /* + * Note that some cache flushing and other stuff may + * be needed here - is there an Angel SWI call for this? + */ + + /* + * some architecture specific code can be inserted + * by the linker here, but it should preserve r7 and r8. + */ + + .text + adr r0, LC0 + ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} + subs r0, r0, r1 @ calculate the delta offset + + @ if delta is zero, we are + beq not_relocated @ running at the address we + @ were linked at. + + /* + * We're running at a different address. We need to fix + * up various pointers: + * r5 - zImage base address + * r6 - GOT start + * ip - GOT end + */ + add r5, r5, r0 + add r6, r6, r0 + add ip, ip, r0 + +#ifndef CONFIG_ZBOOT_ROM + /* + * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, + * we need to fix up pointers into the BSS region. + * r2 - BSS start + * r3 - BSS end + * sp - stack pointer + */ + add r2, r2, r0 + add r3, r3, r0 + add sp, sp, r0 + + /* + * Relocate all entries in the GOT table. + */ +1: ldr r1, [r6, #0] @ relocate entries in the GOT + add r1, r1, r0 @ table. This fixes up the + str r1, [r6], #4 @ C references. + cmp r6, ip + blo 1b +#else + + /* + * Relocate entries in the GOT table. We only relocate + * the entries that are outside the (relocated) BSS region. + */ +1: ldr r1, [r6, #0] @ relocate entries in the GOT + cmp r1, r2 @ entry < bss_start || + cmphs r3, r1 @ _end < entry + addlo r1, r1, r0 @ table. This fixes up the + str r1, [r6], #4 @ C references. + cmp r6, ip + blo 1b +#endif + +not_relocated: mov r0, #0 +1: str r0, [r2], #4 @ clear bss + str r0, [r2], #4 + str r0, [r2], #4 + str r0, [r2], #4 + cmp r2, r3 + blo 1b + + /* + * The C runtime environment should now be setup + * sufficiently. Turn the cache on, set up some + * pointers, and start decompressing. + */ + bl cache_on + + mov r1, sp @ malloc space above stack + add r2, sp, #0x10000 @ 64k max + +/* + * Check to see if we will overwrite ourselves. + * r4 = final kernel address + * r5 = start of this image + * r2 = end of malloc space (and therefore this image) + * We basically want: + * r4 >= r2 -> OK + * r4 + image length <= r5 -> OK + */ + cmp r4, r2 + bhs wont_overwrite + add r0, r4, #4096*1024 @ 4MB largest kernel size + cmp r0, r5 + bls wont_overwrite + + mov r5, r2 @ decompress after malloc space + mov r0, r5 + mov r3, r7 + bl decompress_kernel + + add r0, r0, #127 + bic r0, r0, #127 @ align the kernel length +/* + * r0 = decompressed kernel length + * r1-r3 = unused + * r4 = kernel execution address + * r5 = decompressed kernel start + * r6 = processor ID + * r7 = architecture ID + * r8-r14 = unused + */ + add r1, r5, r0 @ end of decompressed kernel + adr r2, reloc_start + ldr r3, LC1 + add r3, r2, r3 +1: ldmia r2!, {r8 - r13} @ copy relocation code + stmia r1!, {r8 - r13} + ldmia r2!, {r8 - r13} + stmia r1!, {r8 - r13} + cmp r2, r3 + blo 1b + + bl cache_clean_flush + add pc, r5, r0 @ call relocation code + +/* + * We're not in danger of overwriting ourselves. Do this the simple way. + * + * r4 = kernel execution address + * r7 = architecture ID + */ +wont_overwrite: mov r0, r4 + mov r3, r7 + bl decompress_kernel + b call_kernel + + .type LC0, #object +LC0: .word LC0 @ r1 + .word __bss_start @ r2 + .word _end @ r3 + .word zreladdr @ r4 + .word _start @ r5 + .word _got_start @ r6 + .word _got_end @ ip + .word user_stack+4096 @ sp +LC1: .word reloc_end - reloc_start + .size LC0, . - LC0 + +#ifdef CONFIG_ARCH_RPC + .globl params +params: ldr r0, =params_phys + mov pc, lr + .ltorg + .align +#endif + +/* + * Turn on the cache. We need to setup some page tables so that we + * can have both the I and D caches on. + * + * We place the page tables 16k down from the kernel execution address, + * and we hope that nothing else is using it. If we're using it, we + * will go pop! + * + * On entry, + * r4 = kernel execution address + * r6 = processor ID + * r7 = architecture number + * r8 = run-time address of "start" + * On exit, + * r1, r2, r3, r8, r9, r12 corrupted + * This routine must preserve: + * r4, r5, r6, r7 + */ + .align 5 +cache_on: mov r3, #8 @ cache_on function + b call_cache_fn + +__setup_mmu: sub r3, r4, #16384 @ Page directory size + bic r3, r3, #0xff @ Align the pointer + bic r3, r3, #0x3f00 +/* + * Initialise the page tables, turning on the cacheable and bufferable + * bits for the RAM area only. + */ + mov r0, r3 + mov r8, r0, lsr #18 + mov r8, r8, lsl #18 @ start of RAM + add r9, r8, #0x10000000 @ a reasonable RAM size + mov r1, #0x12 + orr r1, r1, #3 << 10 + add r2, r3, #16384 +1: cmp r1, r8 @ if virt > start of RAM + orrhs r1, r1, #0x0c @ set cacheable, bufferable + cmp r1, r9 @ if virt > end of RAM + bichs r1, r1, #0x0c @ clear cacheable, bufferable + str r1, [r0], #4 @ 1:1 mapping + add r1, r1, #1048576 + teq r0, r2 + bne 1b +/* + * If ever we are running from Flash, then we surely want the cache + * to be enabled also for our execution instance... We map 2MB of it + * 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, r1, #3 << 10 + mov r2, pc, lsr #20 + orr r1, r1, r2, lsl #20 + add r0, r3, r2, lsl #2 + str r1, [r0], #4 + add r1, r1, #1048576 + str r1, [r0] + mov pc, lr + +__armv4_cache_on: + mov r12, lr + bl __setup_mmu + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs + mrc p15, 0, r0, c1, c0, 0 @ read control reg + orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement + orr r0, r0, #0x0030 + bl __common_cache_on + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs + mov pc, r12 + +__arm6_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_cache_on + mov r0, #0 + mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 + mov pc, r12 + +__common_cache_on: +#ifndef DEBUG + orr r0, r0, #0x000d @ Write buffer, mmu +#endif + mov r1, #-1 + mcr p15, 0, r3, c2, c0, 0 @ load page table pointer + mcr p15, 0, r1, c3, c0, 0 @ load domain access control + mcr p15, 0, r0, c1, c0, 0 @ load control register + mov pc, lr + +/* + * All code following this line is relocatable. It is relocated by + * the above code to the end of the decompressed kernel image and + * executed there. During this time, we have no stacks. + * + * r0 = decompressed kernel length + * r1-r3 = unused + * r4 = kernel execution address + * r5 = decompressed kernel start + * r6 = processor ID + * r7 = architecture ID + * r8-r14 = unused + */ + .align 5 +reloc_start: add r8, r5, r0 + debug_reloc_start + mov r1, r4 +1: + .rept 4 + ldmia r5!, {r0, r2, r3, r9 - r13} @ relocate kernel + stmia r1!, {r0, r2, r3, r9 - r13} + .endr + + cmp r5, r8 + blo 1b + debug_reloc_end + +call_kernel: bl cache_clean_flush + bl cache_off + mov r0, #0 + mov r1, r7 @ restore architecture number + mov pc, r4 @ call kernel + +/* + * Here follow the relocatable cache support functions for the + * various processors. This is a generic hook for locating an + * entry and jumping to an instruction at the specified offset + * from the start of the block. Please note this is all position + * independent code. + * + * r1 = corrupted + * r2 = corrupted + * r3 = block offset + * r6 = corrupted + * r12 = corrupted + */ + +call_cache_fn: adr r12, proc_types + mrc p15, 0, r6, c0, c0 @ get processor ID +1: ldr r1, [r12, #0] @ get value + ldr r2, [r12, #4] @ get mask + eor r1, r1, r6 @ (real ^ match) + tst r1, r2 @ & mask + addeq pc, r12, r3 @ call cache function + add r12, r12, #4*5 + b 1b + +/* + * Table for cache operations. This is basically: + * - CPU ID match + * - CPU ID mask + * - 'cache on' method instruction + * - 'cache off' method instruction + * - 'cache flush' method instruction + * + * We match an entry using: ((real_id ^ match) & mask) == 0 + * + * Writethrough caches generally only need 'on' and 'off' + * methods. Writeback caches _must_ have the flush method + * defined. + */ + .type proc_types,#object +proc_types: + .word 0x41560600 @ ARM6/610 + .word 0xffffffe0 + b __arm6_cache_off @ works, but slow + b __arm6_cache_off + mov pc, lr +@ b __arm6_cache_on @ untested +@ b __arm6_cache_off +@ b __armv3_cache_flush + + .word 0x00000000 @ old ARM ID + .word 0x0000f000 + mov pc, lr + mov pc, lr + mov pc, lr + + .word 0x41007000 @ ARM7/710 + .word 0xfff8fe00 + b __arm7_cache_off + b __arm7_cache_off + mov pc, lr + + .word 0x41807200 @ ARM720T (writethrough) + .word 0xffffff00 + b __armv4_cache_on + b __armv4_cache_off + mov pc, lr + + .word 0x00007000 @ ARM7 IDs + .word 0x0000f000 + mov pc, lr + mov pc, lr + mov pc, lr + + @ Everything from here on will be the new ID system. + + .word 0x4401a100 @ sa110 / sa1100 + .word 0xffffffe0 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x6901b110 @ sa1110 + .word 0xfffffff0 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + @ These match on the architecture ID + + .word 0x00020000 @ ARMv4T + .word 0x000f0000 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x00050000 @ ARMv5TE + .word 0x000f0000 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x00060000 @ ARMv5TEJ + .word 0x000f0000 + b __armv4_cache_on + b __armv4_cache_off + b __armv4_cache_flush + + .word 0x00070000 @ ARMv6 + .word 0x000f0000 + b __armv4_cache_on + b __armv4_cache_off + b __armv6_cache_flush + + .word 0 @ unrecognised type + .word 0 + mov pc, lr + mov pc, lr + mov pc, lr + + .size proc_types, . - proc_types + +/* + * Turn off the Cache and MMU. ARMv3 does not support + * reading the control register, but ARMv4 does. + * + * On entry, r6 = processor ID + * On exit, r0, r1, r2, r3, r12 corrupted + * This routine must preserve: r4, r6, r7 + */ + .align 5 +cache_off: mov r3, #12 @ cache_off function + b call_cache_fn + +__armv4_cache_off: + mrc p15, 0, r0, c1, c0 + bic r0, r0, #0x000d + mcr p15, 0, r0, c1, c0 @ turn MMU and cache off + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 + mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 + mov pc, lr + +__arm6_cache_off: + mov r0, #0x00000030 @ ARM6 control reg. + b __armv3_cache_off + +__arm7_cache_off: + mov r0, #0x00000070 @ ARM7 control reg. + b __armv3_cache_off + +__armv3_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. + * + * On entry, + * r6 = processor ID + * On exit, + * r1, r2, r3, r11, r12 corrupted + * This routine must preserve: + * r0, r4, r5, r6, r7 + */ + .align 5 +cache_clean_flush: + mov r3, #16 + b call_cache_fn + +__armv6_cache_flush: + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D + mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB + mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +__armv4_cache_flush: + mov r2, #64*1024 @ default: 32K dcache size (*2) + mov r11, #32 @ default: 32 byte line size + mrc p15, 0, r3, c0, c0, 1 @ read cache type + teq r3, r6 @ cache ID register present? + beq no_cache_id + mov r1, r3, lsr #18 + and r1, r1, #7 + mov r2, #1024 + mov r2, r2, lsl r1 @ base dcache size *2 + tst r3, #1 << 14 @ test M bit + addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 + mov r3, r3, lsr #12 + and r3, r3, #3 + mov r11, #8 + mov r11, r11, lsl r3 @ cache line size in bytes +no_cache_id: + bic r1, pc, #63 @ align to longest cache line + add r2, r1, r2 +1: ldr r3, [r1], r11 @ s/w flush D cache + teq r1, r2 + bne 1b + + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mcr p15, 0, r1, c7, c6, 0 @ flush D cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + +__armv3_cache_flush: + mov r1, #0 + mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 + mov pc, lr + +/* + * Various debugging routines for printing hex characters and + * memory, which again must be relocatable. + */ +#ifdef DEBUG + .type phexbuf,#object +phexbuf: .space 12 + .size phexbuf, . - phexbuf + +phex: adr r3, phexbuf + mov r2, #0 + strb r2, [r3, r1] +1: subs r1, r1, #1 + movmi r0, r3 + bmi puts + and r2, r0, #15 + mov r0, r0, lsr #4 + cmp r2, #10 + addge r2, r2, #7 + add r2, r2, #'0' + strb r2, [r3, r1] + b 1b + +puts: loadsp r3 +1: ldrb r2, [r0], #1 + teq r2, #0 + moveq pc, lr +2: writeb r2 + mov r1, #0x00020000 +3: subs r1, r1, #1 + bne 3b + teq r2, #'\n' + moveq r2, #'\r' + beq 2b + teq r0, #0 + bne 1b + mov pc, lr +putc: + mov r2, r0 + mov r0, #0 + loadsp r3 + b 2b + +memdump: mov r12, r0 + mov r10, lr + mov r11, #0 +2: mov r0, r11, lsl #2 + add r0, r0, r12 + mov r1, #8 + bl phex + mov r0, #':' + bl putc +1: mov r0, #' ' + bl putc + ldr r0, [r12, r11, lsl #2] + mov r1, #8 + bl phex + and r0, r11, #7 + teq r0, #3 + moveq r0, #' ' + bleq putc + and r0, r11, #7 + add r11, r11, #1 + teq r0, #7 + bne 1b + mov r0, #'\n' + bl putc + cmp r11, #64 + blt 2b + mov pc, r10 +#endif + +reloc_end: + + .align + .section ".stack", "w" +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 00000000000..104377a199b --- /dev/null +++ b/arch/arm/boot/compressed/ice-dcc.S @@ -0,0 +1,17 @@ + + + .text + + .global icedcc_putc + +icedcc_putc: + mov r2, #0x4000000 +1: + subs r2, r2, #1 + movlt pc, r14 + mrc p14, 0, r1, c0, c0, 0 + tst r1, #2 + bne 1b + + mcr p14, 0, r0, c1, c0, 0 + 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 00000000000..d7bbd9da2fc --- /dev/null +++ b/arch/arm/boot/compressed/ll_char_wr.S @@ -0,0 +1,134 @@ +/* + * linux/arch/arm/lib/ll_char_wr.S + * + * Copyright (C) 1995, 1996 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Speedups & 1bpp code (C) 1996 Philip Blundell & Russell King. + * + * 10-04-96 RMK Various cleanups & reduced register usage. + * 08-04-98 RMK Shifts re-ordered + */ + +@ Regs: [] = corruptible +@ {} = used +@ () = do not use + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +LC0: .word LC0 + .word bytes_per_char_h + .word video_size_row + .word acorndata_8x8 + .word con_charconvtable + +/* + * r0 = ptr + * r1 = char + * r2 = white + */ +ENTRY(ll_write_char) + stmfd sp!, {r4 - r7, lr} +@ +@ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc) +@ + /* + * calculate offset into character table + */ + mov r1, r1, lsl #3 + /* + * calculate offset required for each row. + */ + adr ip, LC0 + ldmia ip, {r3, r4, r5, r6, lr} + sub ip, ip, r3 + add r6, r6, ip + add lr, lr, ip + ldr r4, [r4, ip] + ldr r5, [r5, ip] + /* + * Go to resolution-dependent routine... + */ + cmp r4, #4 + blt Lrow1bpp + add r0, r0, r5, lsl #3 @ Move to bottom of character + orr r1, r1, #7 + ldrb r7, [r6, r1] + teq r4, #8 + beq Lrow8bpplp +@ +@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) +@ +Lrow4bpplp: + ldr r7, [lr, r7, lsl #2] + mul r7, r2, r7 + sub r1, r1, #1 @ avoid using r7 directly after + str r7, [r0, -r5]! + ldrb r7, [r6, r1] + ldr r7, [lr, r7, lsl #2] + mul r7, r2, r7 + tst r1, #7 @ avoid using r7 directly after + str r7, [r0, -r5]! + subne r1, r1, #1 + ldrneb r7, [r6, r1] + bne Lrow4bpplp + LOADREGS(fd, sp!, {r4 - r7, pc}) + +@ +@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) +@ +Lrow8bpplp: + mov ip, r7, lsr #4 + ldr ip, [lr, ip, lsl #2] + mul r4, r2, ip + and ip, r7, #15 @ avoid r4 + ldr ip, [lr, ip, lsl #2] @ avoid r4 + mul ip, r2, ip @ avoid r4 + sub r1, r1, #1 @ avoid ip + sub r0, r0, r5 @ avoid ip + stmia r0, {r4, ip} + ldrb r7, [r6, r1] + mov ip, r7, lsr #4 + ldr ip, [lr, ip, lsl #2] + mul r4, r2, ip + and ip, r7, #15 @ avoid r4 + ldr ip, [lr, ip, lsl #2] @ avoid r4 + mul ip, r2, ip @ avoid r4 + tst r1, #7 @ avoid ip + sub r0, r0, r5 @ avoid ip + stmia r0, {r4, ip} + subne r1, r1, #1 + ldrneb r7, [r6, r1] + bne Lrow8bpplp + LOADREGS(fd, sp!, {r4 - r7, pc}) + +@ +@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc) +@ +Lrow1bpp: + add r6, r6, r1 + ldmia r6, {r4, r7} + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + LOADREGS(fd, sp!, {r4 - r7, pc}) + + .bss +ENTRY(con_charconvtable) + .space 1024 diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c new file mode 100644 index 00000000000..23434b56786 --- /dev/null +++ b/arch/arm/boot/compressed/misc.c @@ -0,0 +1,329 @@ +/* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * + * Modified for ARM Linux by Russell King + * + * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : + * For this code to run directly from Flash, all constant variables must + * be marked with 'const' and all other variables initialized at run-time + * only. This way all non constant variables will end up in the bss segment, + * which should point to addresses in RAM and cleared to 0 on start. + * This allows for a much quicker boot time. + */ + +unsigned int __machine_arch_type; + +#include <linux/string.h> + +#include <asm/arch/uncompress.h> + +#ifdef STANDALONE_DEBUG +#define putstr printf +#endif + +#ifdef CONFIG_DEBUG_ICEDCC +#define putstr icedcc_putstr +#define putc icedcc_putc + +extern void idedcc_putc(int ch); + +static void +icedcc_putstr(const char *ptr) +{ + for (; *ptr != '\0'; ptr++) { + icedcc_putc(*ptr); + } +} + +#endif + +#define __ptr_t void * + +/* + * Optimised C version of memzero for the ARM. + */ +void __memzero (__ptr_t s, size_t n) +{ + union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; + int i; + + u.vp = s; + + for (i = n >> 5; i > 0; i--) { + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + } + + if (n & 1 << 4) { + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + } + + if (n & 1 << 3) { + *u.ulp++ = 0; + *u.ulp++ = 0; + } + + if (n & 1 << 2) + *u.ulp++ = 0; + + if (n & 1 << 1) { + *u.ucp++ = 0; + *u.ucp++ = 0; + } + + if (n & 1) + *u.ucp++ = 0; +} + +static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __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 delarations + */ +#define OF(args) args +#define STATIC static + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize; /* valid bytes in inbuf */ +static unsigned inptr; /* index of next byte to be processed in inbuf */ +static unsigned outcnt; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +extern char input_data[]; +extern char input_data_end[]; + +static uch *output_data; +static ulg output_ptr; +static ulg bytes_out; + +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +static void putstr(const char *); + +extern int end; +static ulg free_mem_ptr; +static ulg free_mem_ptr_end; + +#define HEAP_SIZE 0x2000 + +#include "../../../../lib/inflate.c" + +#ifndef STANDALONE_DEBUG +static void *malloc(int size) +{ + void *p; + + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *)free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_ptr_end) + error("Out of memory"); + return p; +} + +static void free(void *where) +{ /* gzip_mark & gzip_release do the free */ +} + +static void gzip_mark(void **ptr) +{ + arch_decomp_wdog(); + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + arch_decomp_wdog(); + free_mem_ptr = (long) *ptr; +} +#else +static void gzip_mark(void **ptr) +{ +} + +static void gzip_release(void **ptr) +{ +} +#endif + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +int fill_inbuf(void) +{ + if (insize != 0) + error("ran out of input data"); + + inbuf = input_data; + insize = &input_data_end[0] - &input_data[0]; + + inptr = 1; + return inbuf[0]; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +void flush_window(void) +{ + ulg c = crc; + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out++ = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; + putstr("."); +} + +static void error(char *x) +{ + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System halted"); + + while(1); /* Halt */ +} + +#ifndef STANDALONE_DEBUG + +ulg +decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, + int arch_id) +{ + output_data = (uch *)output_start; /* Points to kernel start */ + free_mem_ptr = free_mem_ptr_p; + free_mem_ptr_end = free_mem_ptr_end_p; + __machine_arch_type = arch_id; + + arch_decomp_setup(); + + makecrc(); + putstr("Uncompressing Linux..."); + gunzip(); + putstr(" done, booting the kernel.\n"); + return output_ptr; +} +#else + +char output_buffer[1500*1024]; + +int main() +{ + output_data = output_buffer; + + makecrc(); + putstr("Uncompressing Linux..."); + gunzip(); + putstr("done.\n"); + return 0; +} +#endif + diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c new file mode 100644 index 00000000000..7f6f5db0d06 --- /dev/null +++ b/arch/arm/boot/compressed/ofw-shark.c @@ -0,0 +1,260 @@ +/* + * 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.S b/arch/arm/boot/compressed/piggy.S new file mode 100644 index 00000000000..54c951800eb --- /dev/null +++ b/arch/arm/boot/compressed/piggy.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/boot/compressed/piggy.gz" + .globl input_data_end +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 00000000000..eed616113e4 --- /dev/null +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -0,0 +1,55 @@ +/* + * linux/arch/arm/boot/compressed/vmlinux.lds.in + * + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = TEXT_START; + _text = .; + + .text : { + _start = .; + *(.start) + *(.text) + *(.fixup) + *(.gnu.warning) + *(.rodata) + *(.rodata.*) + *(.glue_7) + *(.glue_7t) + *(.piggydata) + . = ALIGN(4); + } + + _etext = .; + + _got_start = .; + .got : { *(.got) } + _got_end = .; + .got.plt : { *(.got.plt) } + .data : { *(.data) } + _edata = .; + + . = BSS_START; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + + .stack (NOLOAD) : { *(.stack) } + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} + |