ramips: add code for relocating a kernel to the right place
authorFelix Fietkau <nbd@openwrt.org>
Sat, 17 Jan 2015 21:19:38 +0000 (21:19 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 17 Jan 2015 21:19:38 +0000 (21:19 +0000)
(used if the boot loader wants a different loadaddr/entry)

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 44014

target/linux/ramips/image/relocate/Makefile [new file with mode: 0644]
target/linux/ramips/image/relocate/cacheops.h [new file with mode: 0644]
target/linux/ramips/image/relocate/cp0regdef.h [new file with mode: 0644]
target/linux/ramips/image/relocate/head.S [new file with mode: 0644]
target/linux/ramips/image/relocate/loader.lds [new file with mode: 0644]

diff --git a/target/linux/ramips/image/relocate/Makefile b/target/linux/ramips/image/relocate/Makefile
new file mode 100644 (file)
index 0000000..a71bb00
--- /dev/null
@@ -0,0 +1,72 @@
+#
+# Makefile for the LZMA compressed kernel loader for
+# Atheros AR7XXX/AR9XXX based boards
+#
+# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+#
+# Some parts of this file was based on the OpenWrt specific lzma-loader
+# for the BCM47xx and ADM5120 based boards:
+#      Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
+#      Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com>
+#      Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+#
+# 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.
+#
+
+LOADADDR       :=
+LZMA_TEXT_START        := 0x81000000
+LOADER_DATA    :=
+BOARD          :=
+FLASH_OFFS     :=
+FLASH_MAX      :=
+PLATFORM       :=
+
+CC             := $(CROSS_COMPILE)gcc
+LD             := $(CROSS_COMPILE)ld
+OBJCOPY                := $(CROSS_COMPILE)objcopy
+OBJDUMP                := $(CROSS_COMPILE)objdump
+
+BIN_FLAGS      := -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
+
+CFLAGS         = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
+                 -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 \
+                 -mno-abicalls -fno-pic -ffunction-sections -pipe -mlong-calls \
+                 -fno-common -ffreestanding -fhonour-copts \
+                 -mabi=32 -march=mips32r2 \
+                 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap \
+                 -DCONFIG_CACHELINE_SIZE=32 -DKERNEL_ADDR=$(KERNEL_ADDR)
+
+ASFLAGS                = $(CFLAGS) -D__ASSEMBLY__
+
+LDFLAGS                = -static --gc-sections -no-warn-mismatch
+LDFLAGS                += -e startup -T loader.lds -Ttext $(LZMA_TEXT_START)
+
+O_FORMAT       = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
+
+OBJECTS                := head.o
+
+all: head.o loader.bin
+
+# Don't build dependencies, this may die if $(CC) isn't gcc
+dep:
+
+install:
+
+%.o : %.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+%.o : %.S
+       $(CC) $(ASFLAGS) -c -o $@ $<
+
+loader: $(OBJECTS)
+       $(LD) $(LDFLAGS) -o $@ $(OBJECTS)
+
+loader.bin: loader
+       $(OBJCOPY) $(BIN_FLAGS) $< $@
+
+mrproper: clean
+
+clean:
+       rm -f loader *.elf *.bin *.o
diff --git a/target/linux/ramips/image/relocate/cacheops.h b/target/linux/ramips/image/relocate/cacheops.h
new file mode 100644 (file)
index 0000000..70bcad7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Cache operations for the cache instruction.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle
+ * (C) Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef        __ASM_CACHEOPS_H
+#define        __ASM_CACHEOPS_H
+
+/*
+ * Cache Operations available on all MIPS processors with R4000-style caches
+ */
+#define Index_Invalidate_I      0x00
+#define Index_Writeback_Inv_D   0x01
+#define Index_Load_Tag_I       0x04
+#define Index_Load_Tag_D       0x05
+#define Index_Store_Tag_I      0x08
+#define Index_Store_Tag_D      0x09
+#if defined(CONFIG_CPU_LOONGSON2)
+#define Hit_Invalidate_I       0x00
+#else
+#define Hit_Invalidate_I       0x10
+#endif
+#define Hit_Invalidate_D       0x11
+#define Hit_Writeback_Inv_D    0x15
+
+/*
+ * R4000-specific cacheops
+ */
+#define Create_Dirty_Excl_D    0x0d
+#define Fill                   0x14
+#define Hit_Writeback_I                0x18
+#define Hit_Writeback_D                0x19
+
+/*
+ * R4000SC and R4400SC-specific cacheops
+ */
+#define Index_Invalidate_SI     0x02
+#define Index_Writeback_Inv_SD  0x03
+#define Index_Load_Tag_SI      0x06
+#define Index_Load_Tag_SD      0x07
+#define Index_Store_Tag_SI     0x0A
+#define Index_Store_Tag_SD     0x0B
+#define Create_Dirty_Excl_SD   0x0f
+#define Hit_Invalidate_SI      0x12
+#define Hit_Invalidate_SD      0x13
+#define Hit_Writeback_Inv_SD   0x17
+#define Hit_Writeback_SD       0x1b
+#define Hit_Set_Virtual_SI     0x1e
+#define Hit_Set_Virtual_SD     0x1f
+
+/*
+ * R5000-specific cacheops
+ */
+#define R5K_Page_Invalidate_S  0x17
+
+/*
+ * RM7000-specific cacheops
+ */
+#define Page_Invalidate_T      0x16
+
+/*
+ * R10000-specific cacheops
+ *
+ * Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
+ * Most of the _S cacheops are identical to the R4000SC _SD cacheops.
+ */
+#define Index_Writeback_Inv_S  0x03
+#define Index_Load_Tag_S       0x07
+#define Index_Store_Tag_S      0x0B
+#define Hit_Invalidate_S       0x13
+#define Cache_Barrier          0x14
+#define Hit_Writeback_Inv_S    0x17
+#define Index_Load_Data_I      0x18
+#define Index_Load_Data_D      0x19
+#define Index_Load_Data_S      0x1b
+#define Index_Store_Data_I     0x1c
+#define Index_Store_Data_D     0x1d
+#define Index_Store_Data_S     0x1f
+
+#endif /* __ASM_CACHEOPS_H */
diff --git a/target/linux/ramips/image/relocate/cp0regdef.h b/target/linux/ramips/image/relocate/cp0regdef.h
new file mode 100644 (file)
index 0000000..c1188ad
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
+ *
+ * Copyright (C) 2001, Monta Vista Software
+ * Author: jsun@mvista.com or jsun@junsun.net
+ */
+#ifndef _cp0regdef_h_
+#define _cp0regdef_h_
+
+#define CP0_INDEX $0
+#define CP0_RANDOM $1
+#define CP0_ENTRYLO0 $2
+#define CP0_ENTRYLO1 $3
+#define CP0_CONTEXT $4
+#define CP0_PAGEMASK $5
+#define CP0_WIRED $6
+#define CP0_BADVADDR $8
+#define CP0_COUNT $9
+#define CP0_ENTRYHI $10
+#define CP0_COMPARE $11
+#define CP0_STATUS $12
+#define CP0_CAUSE $13
+#define CP0_EPC $14
+#define CP0_PRID $15
+#define CP0_CONFIG $16
+#define CP0_LLADDR $17
+#define CP0_WATCHLO $18
+#define CP0_WATCHHI $19
+#define CP0_XCONTEXT $20
+#define CP0_FRAMEMASK $21
+#define CP0_DIAGNOSTIC $22
+#define CP0_PERFORMANCE $25
+#define CP0_ECC $26
+#define CP0_CACHEERR $27
+#define CP0_TAGLO $28
+#define CP0_TAGHI $29
+#define CP0_ERROREPC $30
+
+#endif
diff --git a/target/linux/ramips/image/relocate/head.S b/target/linux/ramips/image/relocate/head.S
new file mode 100644 (file)
index 0000000..3680cb7
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Some parts of this code was based on the OpenWrt specific lzma-loader
+ * for the BCM47xx and ADM5120 based boards:
+ *     Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
+ *     Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * 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 <asm/asm.h>
+#include <asm/regdef.h>
+#include "cp0regdef.h"
+#include "cacheops.h"
+
+#define KSEG0          0x80000000
+
+       .macro  ehb
+       sll     zero, 3
+       .endm
+
+       .macro reset
+       li t0, 0xbe000034
+       lw t1, 0(t0)
+       ori t1, 1
+       sw t1, 0(t0)
+       .endm
+
+       .text
+
+LEAF(startup)
+       .set noreorder
+       .set mips32
+
+       .fill 0x10000
+
+       mtc0    zero, CP0_WATCHLO       # clear watch registers
+       mtc0    zero, CP0_WATCHHI
+       mtc0    zero, CP0_CAUSE         # clear before writing status register
+
+       mfc0    t0, CP0_STATUS
+       li      t1, 0x1000001f
+       or      t0, t1
+       xori    t0, 0x1f
+       mtc0    t0, CP0_STATUS
+       ehb
+
+       mtc0    zero, CP0_COUNT
+       mtc0    zero, CP0_COMPARE
+       ehb
+
+       la      t0, __reloc_label       # get linked address of label
+       bal     __reloc_label           # branch and link to label to
+       nop                             # get actual address
+__reloc_label:
+       subu    t0, ra, t0              # get reloc_delta
+
+       /* Copy our code to the right place */
+       la      t1, _code_start         # get linked address of _code_start
+       la      t2, _code_end           # get linked address of _code_end
+
+       addu    t4, t2, t0              # calculate actual address of _code_end
+       lw      t5, 0(t4)               # get extra data size
+
+       add     t2, t5
+       add     t2, 4
+
+       add     t0, t1                  # calculate actual address of _code_start
+
+__reloc_copy:
+       lw      t3, 0(t0)
+       sw      t3, 0(t1)
+       add     t1, 4
+       blt     t1, t2, __reloc_copy
+       add     t0, 4
+
+       /* flush cache */
+       la      t0, _code_start
+       la      t1, _code_end
+
+       li      t2, ~(CONFIG_CACHELINE_SIZE - 1)
+       and     t0, t2
+       and     t1, t2
+       li      t2, CONFIG_CACHELINE_SIZE
+
+       b       __flush_check
+       nop
+
+__flush_line:
+       cache   Hit_Writeback_Inv_D, 0(t0)
+       cache   Hit_Invalidate_I, 0(t0)
+       add     t0, t2
+
+__flush_check:
+       bne     t0, t1, __flush_line
+       nop
+
+       sync
+
+       la      t0, __reloc_back
+       j       t0
+       nop
+
+__reloc_back:
+       la      t0, _code_end
+       add     t0, 4
+
+       addu    t1, t0, t5
+
+       li      t2, KERNEL_ADDR
+
+__kernel_copy:
+       lw      t3, 0(t0)
+       sw      t3, 0(t2)
+       add     t0, 4
+       blt     t0, t1, __kernel_copy
+       add     t2, 4
+
+       /* flush cache */
+       li      t0, KERNEL_ADDR
+       addu    t1, t0, t5
+
+       add t1, CONFIG_CACHELINE_SIZE - 1
+       li      t2, ~(CONFIG_CACHELINE_SIZE - 1)
+       and     t0, t2
+       and     t1, t2
+       li      t2, CONFIG_CACHELINE_SIZE
+
+       b       __kernel_flush_check
+       nop
+
+__kernel_flush_line:
+       cache   Hit_Writeback_Inv_D, 0(t0)
+       cache   Hit_Invalidate_I, 0(t0)
+       add     t0, t2
+
+__kernel_flush_check:
+       bne     t0, t1, __kernel_flush_line
+       nop
+
+       sync
+
+       li      t0, KERNEL_ADDR
+       jr      t0
+       nop
+
+       .set reorder
+END(startup)
diff --git a/target/linux/ramips/image/relocate/loader.lds b/target/linux/ramips/image/relocate/loader.lds
new file mode 100644 (file)
index 0000000..98ca209
--- /dev/null
@@ -0,0 +1,16 @@
+OUTPUT_ARCH(mips)
+SECTIONS {
+       .text : {
+               _code_start = .;
+               *(.text)
+               *(.text.*)
+               *(.rodata)
+               *(.rodata.*)
+               *(.data)
+               *(.data.*)
+       }
+
+       . = ALIGN(32);
+
+       _code_end = .;
+}