From f582a9c3eafd3cfcfb8a49e4dc72be1e277baf9e Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 17 Apr 2002 20:44:06 +0100 Subject: [PATCH] This changeset adds a new feature to ARM - the ability to load the kernel zImage almost anywhere in RAM and call it directly, without having to copy it to a specific address. This removes a dependency between the boot loader and the kernel. --- arch/arm/Config.help | 12 ++++ arch/arm/boot/Makefile | 77 +++++++--------------- arch/arm/boot/compressed/Makefile | 10 +-- arch/arm/boot/compressed/head-clps7500.S | 2 +- arch/arm/boot/compressed/head-epxa10db.S | 2 +- arch/arm/boot/compressed/head-ftvpci.S | 2 +- arch/arm/boot/compressed/head-integrator.S | 2 +- arch/arm/boot/compressed/head-l7200.S | 2 +- arch/arm/boot/compressed/head-netwinder.S | 45 ++----------- arch/arm/boot/compressed/head-sa1100.S | 2 +- arch/arm/boot/compressed/head-shark.S | 2 +- arch/arm/boot/compressed/head-xscale.S | 2 +- arch/arm/boot/compressed/head.S | 71 +++++++++++++++----- arch/arm/boot/compressed/vmlinux.lds.in | 31 ++++----- arch/arm/config.in | 6 ++ arch/arm/def-configs/iq80310 | 3 + arch/arm/def-configs/lusl7200 | 3 + arch/arm/def-configs/sherman | 3 + arch/arm/def-configs/victor | 3 + 19 files changed, 139 insertions(+), 141 deletions(-) diff --git a/arch/arm/Config.help b/arch/arm/Config.help index cbcfba911f55..09a07f780c7c 100644 --- a/arch/arm/Config.help +++ b/arch/arm/Config.help @@ -836,3 +836,15 @@ CONFIG_DEBUG_BUGVERBOSE of the BUG call as well as the EIP and oops trace. This aids debugging but costs about 70-100K of memory. +CONFIG_ZBOOT_ROM + Say Y here if you intend to execute your compressed kernel image (zImage) + directly from ROM or flash. If unsure, say N. + +CONFIG_ZBOOT_ROM_TEXT + The base address for zImage. Unless you have special requirements, you + should not change this value. + +CONFIG_ZBOOT_ROM_BSS + The base address of 64KiB of read/write memory, which must be available + while the decompressor is running. Unless you have special requirements, + you should not change this value. diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 1a045f06843f..1628584cf340 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -5,31 +5,31 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1995-2000 Russell King +# Copyright (C) 1995-2002 Russell King # SYSTEM =$(TOPDIR)/vmlinux ifeq ($(CONFIG_CPU_26),y) -ZTEXTADDR = 0x02080000 +ZRELADDR = 0x02080000 PARAMS_PHYS = 0x0207c000 INITRD_PHYS = 0x02180000 INITRD_VIRT = 0x02180000 endif ifeq ($(CONFIG_ARCH_RPC),y) -ZTEXTADDR = 0x10008000 +ZRELADDR = 0x10008000 PARAMS_PHYS = 0x10000100 INITRD_PHYS = 0x18000000 INITRD_VIRT = 0xc8000000 endif ifeq ($(CONFIG_ARCH_CLPS7500),y) -ZTEXTADDR = 0x10008000 +ZRELADDR = 0x10008000 endif ifeq ($(CONFIG_ARCH_EBSA110),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 PARAMS_PHYS = 0x00000400 INITRD_PHYS = 0x00800000 INITRD_VIRT = 0xc0800000 @@ -41,41 +41,34 @@ ZRELADDR = 0x08008000 endif ifeq ($(CONFIG_FOOTBRIDGE),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 PARAMS_PHYS = 0x00000100 INITRD_PHYS = 0x00800000 INITRD_VIRT = 0xc0800000 endif ifeq ($(CONFIG_ARCH_INTEGRATOR),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 PARAMS_PHYS = 0x00000100 INITRD_PHYS = 0x00800000 INITRD_VIRT = 0xc0800000 endif ifeq ($(CONFIG_ARCH_CAMELOT),y) -ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 endif ifeq ($(CONFIG_ARCH_NEXUSPCI),y) -ZTEXTADDR = 0x40008000 +ZRELADDR = 0x40008000 endif ifeq ($(CONFIG_ARCH_L7200),y) -# RAM based kernel -#ZTEXTADDR = 0xf0400000 -#ZRELADDR = 0xf0008000 - -# FLASH based kernel -ZTEXTADDR = 0x00010000 ZRELADDR = 0xf0008000 -ZBSSADDR = 0xf03e0000 endif # The standard locations for stuff on CLPS711x type processors ifeq ($(CONFIG_ARCH_CLPS711X),y) -ZTEXTADDR = 0xc0028000 +ZRELADDR = 0xc0028000 PARAMS_PHYS = 0xc0000100 endif @@ -90,60 +83,40 @@ INITRD_VIRT = 0xc0300000 endif ifeq ($(CONFIG_ARCH_SA1100),y) -ZTEXTADDR = 0xc0008000 ZRELADDR = 0xc0008000 -ifeq ($(CONFIG_SA1100_VICTOR),y) - ZTEXTADDR = 0x00002000 - ZBSSADDR = 0xc0200000 -endif -ifeq ($(CONFIG_SA1100_SHERMAN),y) - ZTEXTADDR = 0x00050000 - ZBSSADDR = 0xc0200000 -endif -ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) - ZTEXTADDR = 0xC0200000 -endif -ifeq ($(CONFIG_SA1100_GRAPHICSMASTER),y) - ZTEXTADDR = 0xC0400000 -endif -ifeq ($(CONFIG_SA1100_ADSBITSY),y) - ZTEXTADDR = 0xC0400000 -endif -ifeq ($(CONFIG_SA1100_YOPY),y) - ZTEXTADDR = 0x00080000 - ZBSSADDR = 0xc0200000 -endif +# No defconfig file to move this into... +#ifeq ($(CONFIG_SA1100_YOPY),y) +# ZTEXTADDR = 0x00080000 +# ZBSSADDR = 0xc0200000 +#endif ifeq ($(CONFIG_SA1111),y) ZRELADDR = 0xc0208000 endif endif ifeq ($(CONFIG_ARCH_ANAKIN),y) -ZTEXTADDR = 0x20008000 +ZRELADDR = 0x20008000 endif ifeq ($(CONFIG_ARCH_IQ80310),y) ZRELADDR = 0xa0008000 - -# for serial upload -ZTEXTADDR = 0xa1008000 - -# for direct flash execution -# ZTEXTADDR = 0x00060000 -# ZBSSADDR = 0xa1008000 endif ifeq ($(CONFIG_ARCH_ADIFCC),y) ZRELADDR = 0xc0008000 -ZTEXTADDR = 0xc1000000 endif # -# If you don't define ZRELADDR above, -# then it defaults to ZTEXTADDR +# 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) # -ifeq ($(ZRELADDR),) -ZRELADDR = $(ZTEXTADDR) +ifeq ($(CONFIG_ZBOOT_ROM),y) +ZTEXTADDR =0x$(CONFIG_ZBOOT_ROM_TEXT) +ZBSSADDR =0x$(CONFIG_ZBOOT_ROM_BSS) +else +ZTEXTADDR =0 +ZBSSADDR =ALIGN(4) endif export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 112e8209ec53..2f5c0eee43ea 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -9,7 +9,7 @@ HEAD = head.o OBJS = misc.o -CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_BOOT) +CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_BOOT) -fpic FONTC = $(TOPDIR)/drivers/video/font_acorn_8x8.c ZLDFLAGS = -p -X -T vmlinux.lds @@ -65,13 +65,7 @@ ifeq ($(CONFIG_CPU_XSCALE),y) OBJS += head-xscale.o endif -SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/; - -ifneq ($(ZBSSADDR),) -SEDFLAGS += s/BSS_START/$(ZBSSADDR)/ -else -SEDFLAGS += s/BSS_START/ALIGN(4)/ -endif +SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/ LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) diff --git a/arch/arm/boot/compressed/head-clps7500.S b/arch/arm/boot/compressed/head-clps7500.S index 80000db087ad..a1a0c847dda2 100644 --- a/arch/arm/boot/compressed/head-clps7500.S +++ b/arch/arm/boot/compressed/head-clps7500.S @@ -13,7 +13,7 @@ /* 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", #alloc, #execinstr + .section ".start", "ax" 2: b 1f .word 0xffff diff --git a/arch/arm/boot/compressed/head-epxa10db.S b/arch/arm/boot/compressed/head-epxa10db.S index 211a16e6e744..757681f12a39 100644 --- a/arch/arm/boot/compressed/head-epxa10db.S +++ b/arch/arm/boot/compressed/head-epxa10db.S @@ -1,5 +1,5 @@ #include #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" mov r7, #MACH_TYPE_CAMELOT diff --git a/arch/arm/boot/compressed/head-ftvpci.S b/arch/arm/boot/compressed/head-ftvpci.S index 8e10667cae06..aa272a384702 100644 --- a/arch/arm/boot/compressed/head-ftvpci.S +++ b/arch/arm/boot/compressed/head-ftvpci.S @@ -13,7 +13,7 @@ * 2 of the License, or (at your option) any later version. */ - .section ".start", #alloc, #execinstr + .section ".start", "ax" ftv_start: mcr p15, 0, r0, c7, c5, 0 @ flush I cache mrc p15, 0, r0, c1, c0 diff --git a/arch/arm/boot/compressed/head-integrator.S b/arch/arm/boot/compressed/head-integrator.S index 0f901b761447..e9bf350d6687 100644 --- a/arch/arm/boot/compressed/head-integrator.S +++ b/arch/arm/boot/compressed/head-integrator.S @@ -1,4 +1,4 @@ #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" mov r7, #MACH_TYPE_INTEGRATOR diff --git a/arch/arm/boot/compressed/head-l7200.S b/arch/arm/boot/compressed/head-l7200.S index 8ab9eafdbf08..1eb2246c3077 100644 --- a/arch/arm/boot/compressed/head-l7200.S +++ b/arch/arm/boot/compressed/head-l7200.S @@ -13,7 +13,7 @@ #error What am I doing here... #endif - .section ".start", #alloc, #execinstr + .section ".start", "ax" __L7200_start: mov r0, #0x00100000 @ FLASH address of initrd diff --git a/arch/arm/boot/compressed/head-netwinder.S b/arch/arm/boot/compressed/head-netwinder.S index 5eecdec422d0..e7313442873e 100644 --- a/arch/arm/boot/compressed/head-netwinder.S +++ b/arch/arm/boot/compressed/head-netwinder.S @@ -1,50 +1,13 @@ /* * linux/arch/arm/boot/compressed/head-netwinder.S * - * Copyright (C) 2000 Russell King + * Copyright (C) 2000-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. */ -#define K(a,b,c) ((a) << 24 | (b) << 12 | (c)) + .section ".start", "ax" - .section ".start", #alloc, #execinstr - - /* - * check to see if we are running from the correct address. - * If not, we move ourselves in a two stage process. Firstly, - * we copy the start of the kernel (which includes this code) - * to 0x8000, and then jump to this code to continue with the - * rest (since this code will get overwritten). - */ - adr r2, 1f - ldmdb r2, {r9, r10} - and r3, r2, #0xc000 - teq r3, #0x8000 @ correctly located? - beq 2f @ skip this code - bic r3, r2, #0xc000 - orr r3, r3, #0x8000 - mov r0, r3 @ new address if '1' - mov r4, #64 @ number of bytes to copy - sub r5, r10, r9 @ total number of bytes to copy - b 1f - - .word _start - .word __bss_start - -1: - .rept 4 - ldmia r2!, {r6, r9, r10, r11} - stmia r3!, {r6, r9, r10, r11} - .endr - subs r4, r4, #64 - bcs 1b - movs r4, r5 @ remaining length - mov r5, #0 @ no more to copy - movne pc, r0 @ jump back to 1 (in the newly copied - @ code) - mov r7, #5 @ only here to fix NeTTroms which dont - mov r8, #2 << 24 @ scheduled for removal in 2.5.xx - orr r8, r8, #5 << 12 -2: + mov r7, #5 + mov r8, #0 diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S index b0dd98d1fedb..ca6f27b83fcf 100644 --- a/arch/arm/boot/compressed/head-sa1100.S +++ b/arch/arm/boot/compressed/head-sa1100.S @@ -11,7 +11,7 @@ #include #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" __SA1100_start: diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S index 26da294e9285..611a5bd1ec8f 100644 --- a/arch/arm/boot/compressed/head-shark.S +++ b/arch/arm/boot/compressed/head-shark.S @@ -16,7 +16,7 @@ #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" b __beginning diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index abe2fe19a0fb..cf9a9c9d065d 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -9,7 +9,7 @@ #include #include - .section ".start", #alloc, #execinstr + .section ".start", "ax" __XScale_start: diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 8142db27d233..bf2f4a57488a 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -132,10 +132,28 @@ not_angel: */ .text -1: adr r2, LC0 - ldmia r2, {r2, r3, r4, r5, sp} + adr r0, LC0 + ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} + subs r0, r0, r1 @ calculate the delta offset + + teq r0, #0 @ if delta is zero, we're + beq not_relocated @ running at the address we + @ were linked at. + + add r2, r2, r0 @ different address, so we + add r3, r3, r0 @ need to fix up various + add r5, r5, r0 @ pointers. + add r6, r6, r0 + add ip, ip, r0 + add sp, sp, r0 + +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 + blt 1b - mov r0, #0 +not_relocated: mov r0, #0 1: str r0, [r2], #4 @ clear bss str r0, [r2], #4 str r0, [r2], #4 @@ -149,17 +167,26 @@ not_angel: mov r1, sp @ malloc space above stack add r2, sp, #0x10000 @ 64k max - teq r4, r5 @ will we overwrite ourselves? - moveq r5, r2 @ decompress after image - movne r5, r4 @ decompress to final location +/* + * 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 SYMBOL_NAME(decompress_kernel) - teq r4, r5 @ do we need to relocate - beq call_kernel @ the kernel? - add r0, r0, #127 bic r0, r0, #127 @ align the kernel length /* @@ -184,12 +211,26 @@ not_angel: 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 SYMBOL_NAME(decompress_kernel) + b call_kernel + .type LC0, #object -LC0: .word __bss_start - .word _end - .word _load_addr - .word _start - .word user_stack+4096 +LC0: .word LC0 @ r1 + .word __bss_start @ r2 + .word _end @ r3 + .word _load_addr @ r4 + .word _start @ r5 + .word _got_start @ r6 + .word _got_end @ r7 + .word user_stack+4096 @ r8 .size LC0, . - LC0 /* @@ -518,5 +559,5 @@ memdump: mov r12, r0 reloc_end: .align - .section ".stack" + .section ".stack", "aw" user_stack: .space 4096 diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 6cd1348d868b..0fc786166f87 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -35,29 +35,26 @@ SECTIONS _etext = .; - .data : { - *(.data) - } - + _got_start = .; + .got : { *(.got) } + _got_end = .; + .got.plt : { *(.got.plt) } + .data : { *(.data) } _edata = .; . = BSS_START; __bss_start = .; - .bss : { - *(.bss) - } + .bss : { *(.bss) } _end = .; - .stack : { - *(.stack) - } + .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) } + .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) } } diff --git a/arch/arm/config.in b/arch/arm/config.in index 5f1712405979..808cd4046672 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -433,6 +433,12 @@ else define_bool CONFIG_FIQ n fi +# Compressed boot loader in ROM. Yes, we really want to ask about +# TEXT and BSS so we preserve their values in the config files. +bool 'Compressed boot loader in ROM/flash' CONFIG_ZBOOT_ROM +hex 'Compressed ROM boot loader base address' CONFIG_ZBOOT_ROM_TEXT 0 +hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0 + if [ "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL diff --git a/arch/arm/def-configs/iq80310 b/arch/arm/def-configs/iq80310 index 25fe045db605..16ac62b92532 100644 --- a/arch/arm/def-configs/iq80310 +++ b/arch/arm/def-configs/iq80310 @@ -139,6 +139,9 @@ CONFIG_ARM_THUMB=y # # General setup # +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00060000 +CONFIG_ZBOOT_ROM_BSS=0xa1008000 CONFIG_PCI=y # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set diff --git a/arch/arm/def-configs/lusl7200 b/arch/arm/def-configs/lusl7200 index 18010c8997b2..3b1325925b83 100644 --- a/arch/arm/def-configs/lusl7200 +++ b/arch/arm/def-configs/lusl7200 @@ -23,6 +23,9 @@ CONFIG_CPU_32=y # CONFIG_CPU_26 is not set CONFIG_CPU_32v4=y CONFIG_CPU_ARM720=y +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00010000 +CONFIG_ZBOOT_ROM_BSS=0xf03e0000 # CONFIG_PCI is not set # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set diff --git a/arch/arm/def-configs/sherman b/arch/arm/def-configs/sherman index 174bef0483cc..e7bcb1cfdec2 100644 --- a/arch/arm/def-configs/sherman +++ b/arch/arm/def-configs/sherman @@ -47,6 +47,9 @@ CONFIG_MODULES=y # # General setup # +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00050000 +CONFIG_ZBOOT_ROM_BSS=0xc0200000 # CONFIG_NET is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set diff --git a/arch/arm/def-configs/victor b/arch/arm/def-configs/victor index 2377cc4df05b..9232411d83fd 100644 --- a/arch/arm/def-configs/victor +++ b/arch/arm/def-configs/victor @@ -46,6 +46,9 @@ CONFIG_MODULES=y # # General setup # +CONFIG_ZBOOT_ROM=y +CONFIG_ZBOOT_ROM_TEXT=0x00002000 +CONFIG_ZBOOT_ROM_BSS=0xc0200000 # CONFIG_NET is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set -- 2.39.5