From 3d987ecbdb68b0b0ee47fbb970f747010f863f67 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Mon, 2 Apr 2007 17:14:23 +0000
Subject: [PATCH] Entry point is now configurable via a Makefile variable.
 Entry point is detected automatically (Gabor Juhos)

SVN-Revision: 6841
---
 .../adm5120-2.6/image/lzma-loader/Makefile    | 16 +++--
 .../image/lzma-loader/src/Makefile            | 59 +++++++--------
 .../image/lzma-loader/src/decompress.c        | 26 +++----
 .../image/lzma-loader/src/decompress.lds.in   | 20 ------
 .../adm5120-2.6/image/lzma-loader/src/head.S  | 72 +++++++++++++------
 .../image/lzma-loader/src/loader.lds.in       | 14 +++-
 6 files changed, 113 insertions(+), 94 deletions(-)

diff --git a/target/linux/adm5120-2.6/image/lzma-loader/Makefile b/target/linux/adm5120-2.6/image/lzma-loader/Makefile
index e2afb186e0..8ce2688234 100644
--- a/target/linux/adm5120-2.6/image/lzma-loader/Makefile
+++ b/target/linux/adm5120-2.6/image/lzma-loader/Makefile
@@ -1,4 +1,4 @@
-# 
+#
 # Copyright (C) 2006 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
@@ -8,6 +8,9 @@
 
 include $(TOPDIR)/rules.mk
 
+LOADER := loader
+BZ_STARTUP_ORG := 0
+
 PKG_NAME := lzma-loader
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 
@@ -16,18 +19,19 @@ $(PKG_BUILD_DIR)/.prepared:
 	$(CP) ./src/* $(PKG_BUILD_DIR)/
 	touch $@
 
-$(PKG_BUILD_DIR)/loader.gz: $(PKG_BUILD_DIR)/.prepared
+$(PKG_BUILD_DIR)/$(LOADER).gz: $(PKG_BUILD_DIR)/.prepared
 	$(MAKE) -C $(PKG_BUILD_DIR) CC="$(TARGET_CC)" \
-		LD="$(TARGET_CROSS)ld" CROSS_COMPILE="$(TARGET_CROSS)"
+		LD="$(TARGET_CROSS)ld" CROSS_COMPILE="$(TARGET_CROSS)" \
+		LOADER=$(LOADER) BZ_STARTUP_ORG=$(BZ_STARTUP_ORG)
 
-download: 
+download:
 prepare: $(PKG_BUILD_DIR)/.prepared
-compile: $(PKG_BUILD_DIR)/loader.gz
+compile: $(PKG_BUILD_DIR)/$(LOADER).gz
 install:
 
 ifneq ($(TARGET),)
 install: compile
-	$(CP) $(PKG_BUILD_DIR)/loader.gz $(PKG_BUILD_DIR)/loader.elf $(TARGET)/
+	$(CP) $(PKG_BUILD_DIR)/$(LOADER).gz $(PKG_BUILD_DIR)/$(LOADER).elf $(TARGET)/
 endif
 
 clean:
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/Makefile b/target/linux/adm5120-2.6/image/lzma-loader/src/Makefile
index 85a864674b..e94be307da 100644
--- a/target/linux/adm5120-2.6/image/lzma-loader/src/Makefile
+++ b/target/linux/adm5120-2.6/image/lzma-loader/src/Makefile
@@ -3,7 +3,7 @@
 #
 # Copyright 2001-2003, Broadcom Corporation
 # All Rights Reserved.
-# 
+#
 # THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
 # KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
 # SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
@@ -16,9 +16,15 @@
 # Copyright 2005  Oleg I. Vdovikin <oleg@cs.msu.su>
 #   Cleaned up, modified for lzma support, removed from kernel
 #
+# Copyright 2007 Gabor Juhos <juhosg@freemail.hu>
+#   Modified to support user defined entry point address.
+#   Added support for make targets with different names
+#
 
-TEXT_START	:= 0x80001000
+LOADADDR	:= 0x80001000
 BZ_TEXT_START	:= 0x80300000
+BZ_STARTUP_ORG	:= 0
+LOADER		:= loader
 
 OBJCOPY		:= $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
 
@@ -26,52 +32,41 @@ 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 \
 		  -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
-CFLAGS		+= -DLOADADDR=$(TEXT_START) -D_LZMA_IN_CB
+CFLAGS		+= -DLOADADDR=$(LOADADDR) -D_LZMA_IN_CB
 
-ASFLAGS		= $(CFLAGS) -D__ASSEMBLY__ -DBZ_TEXT_START=$(BZ_TEXT_START)
+ASFLAGS		= $(CFLAGS) -D__ASSEMBLY__ -DBZ_STARTUP_ORG=$(BZ_STARTUP_ORG)
 
-SEDFLAGS	:= s/BZ_TEXT_START/$(BZ_TEXT_START)/;s/TEXT_START/$(TEXT_START)/
+LDFLAGS		= -static --gc-sections -no-warn-mismatch
+LDFLAGS		+= -e startup -Ttext $(BZ_TEXT_START) -T loader.lds.in
 
-OBJECTS		:= head.o data.o
+OBJECTS		:= $(LOADER)-head.o decompress.o LzmaDecode.o
 
-all: loader.gz loader.elf
+all: $(LOADER).gz $(LOADER).elf
 
 # Don't build dependencies, this may die if $(CC) isn't gcc
 dep:
 
 install:
 
-loader.gz: loader
-	gzip -nc9 $< > $@
-
-loader.elf: loader.o
-	cp $< $@
-
-loader: loader.o
-	$(OBJCOPY) $< $@
-
-loader.o: loader.lds $(OBJECTS)
-	$(LD) -static --gc-sections -no-warn-mismatch -T loader.lds -o $@ $(OBJECTS)
-
-loader.lds: loader.lds.in Makefile
-	@sed "$(SEDFLAGS)" < $< > $@
+decompress.o:
+	$(CC) $(CFLAGS) -c decompress.c -o $@
 
-data.o: data.lds decompress.image
-	$(LD) -no-warn-mismatch -T data.lds -r -o $@ -b binary decompress.image -b elf32-tradlittlemips
+$(LOADER)-head.o:
+	$(CC) $(ASFLAGS) -c head.S -o $@
 
-data.lds:
-	@echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > $@
+$(LOADER).gz: $(LOADER).bin
+	gzip -nc9 $< > $@
 
-decompress.image: decompress
-	$(OBJCOPY) $< $@
+$(LOADER).elf: $(LOADER).o
+	cp $< $@
 
-decompress: decompress.lds decompress.o LzmaDecode.o
-	$(LD) -static --gc-sections -no-warn-mismatch -T decompress.lds -o $@ decompress.o LzmaDecode.o
+$(LOADER).bin: $(LOADER).o
+	$(OBJCOPY) -O binary $< $@
 
-decompress.lds: decompress.lds.in Makefile
-	@sed "$(SEDFLAGS)" < $< > $@
+$(LOADER).o: $(OBJECTS)
+	$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
 
 mrproper: clean
 
 clean:
-	rm -f loader.gz loader decompress *.lds *.o *.image
+	rm -f *.gz *.elf *.bin *.o
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.c b/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.c
index d3610241f6..ec63ccb651 100644
--- a/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.c
+++ b/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.c
@@ -109,10 +109,10 @@ static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
 		val = *(unsigned int *)data;
 		data += 4;
 	}
-	
+
 	*bufferSize = 1;
 	*buffer = ((unsigned char *)&val) + (offset++ & 3);
-	
+
 	return LZMA_RESULT_OK;
 }
 
@@ -120,14 +120,16 @@ static __inline__ unsigned char get_byte(void)
 {
 	unsigned char *buffer;
 	UInt32 fake;
-	
+
 	return read_byte(0, &buffer, &fake), *buffer;
 }
 
+int uart_write_str(char * str);
+
 /* should be the first function */
-void entry(unsigned long reg_a0, unsigned long reg_a1,
+void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
 	unsigned long reg_a2, unsigned long reg_a3,
-	unsigned long icache_size, unsigned long icache_lsize, 
+	unsigned long icache_size, unsigned long icache_lsize,
 	unsigned long dcache_size, unsigned long dcache_lsize)
 {
 	unsigned int i;  /* temp value */
@@ -140,13 +142,13 @@ void entry(unsigned long reg_a0, unsigned long reg_a1,
 	callback.Read = read_byte;
 
     uart_write_str("decompress kernel ... ");
-    
+
 	/* look for trx header, 32-bit data access */
 	for (data = ((unsigned char *) KSEG1ADDR(BCM4710_FLASH));
 		((struct trx_header *)data)->magic != TRX_MAGIC; data += 65536);
 
 	/* compressed kernel is in the partition 0 or 1 */
-	if (((struct trx_header *)data)->offsets[1] > 65536) 
+	if (((struct trx_header *)data)->offsets[1] > 65536)
 		data += ((struct trx_header *)data)->offsets[0];
 	else
 		data += ((struct trx_header *)data)->offsets[1];
@@ -169,7 +171,7 @@ void entry(unsigned long reg_a0, unsigned long reg_a1,
 		((unsigned int)get_byte() << 24);
 
 	/* skip rest of the header (upper half of uncompressed size) */
-	for (i = 0; i < 4; i++) 
+	for (i = 0; i < 4; i++)
 		get_byte();
 
 	/* decompress kernel */
@@ -188,11 +190,11 @@ void entry(unsigned long reg_a0, unsigned long reg_a1,
 }
 
 /*  *********************************************************************
-    *  
+    *
     *  ADM5120 UART driver			File: dev_adm_uart.c
-    *  
+    *
     *  This is a console device driver for an ADM5120 UART
-    *  
+    *
     *********************************************************************
     *
     *  Copyright 2006
@@ -226,7 +228,7 @@ int uart_write_hex(int val)
 {
     int i;
     int tmp;
-    
+
     uart_write_str("0x");
     for ( i=0 ; i<8 ; i++ ) {
         tmp = (val >> ((7-i) * 4 )) & 0xf;
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.lds.in b/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.lds.in
index 33f56f8a09..e69de29bb2 100644
--- a/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.lds.in
+++ b/target/linux/adm5120-2.6/image/lzma-loader/src/decompress.lds.in
@@ -1,20 +0,0 @@
-OUTPUT_ARCH(mips)
-ENTRY(entry)
-SECTIONS {
-	. = BZ_TEXT_START;
-	.text : {
-		*(.text.entry)
-		*(.text)
-		*(.rodata)
-	}
-
-	.data : {
-		*(.data)
-	}
-
-	.bss : {
-		*(.bss)
-	}
-
-	workspace = .;
-}
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/head.S b/target/linux/adm5120-2.6/image/lzma-loader/src/head.S
index 7f0e9adc0d..3bfab9ff1b 100644
--- a/target/linux/adm5120-2.6/image/lzma-loader/src/head.S
+++ b/target/linux/adm5120-2.6/image/lzma-loader/src/head.S
@@ -1,6 +1,6 @@
-/* Copyright 2007 Gabor Juhos				*/
+/* Copyright 2007 Gabor Juhos <juhosg@freemail.hu>	*/
 /* keep original values of the a0,a1,a2,a3 registers	*/
-/* cache manipulation adapted from Broadcom code 	*/
+/* modifed to support user defined entry point address	*/
 /* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su)	*/
 /* cache manipulation adapted from Broadcom code 	*/
 /* idea taken from original bunzip2 decompressor code	*/
@@ -39,21 +39,44 @@
 #define Index_Writeback_Inv_D   0x01
 
 	.text
-	LEAF(startup)
+
+#if (BZ_STARTUP_ORG)
+	.set	noreorder
+
+	b	startup
+	nop
+
+	.org	BZ_STARTUP_ORG
+#endif
+
+LEAF(startup)
 	.set noreorder
-	
-	/* Copy decompressor code to the right place */
-	li	t0, BZ_TEXT_START
-
-	la      t1, code_start
-	la	t2, code_stop
-$L1:
-	lw	t3, 0(t1)
-	sw	t3, 0(t0)
+
+	move	t1, ra			# save return address
+	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
+	move	ra, t1			# restore return address
+
+	beqz	t0, __reloc_end         # if delta is 0 we are in the right place
+	nop
+
+	/* 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	t0, t0, t1		# calculate actual address of _code_start
+
+__reloc_copy:
+	lw	t3, 0(t0)
+	sw	t3, 0(t1)
 	add	t1, 4
-	blt	t1, t2, $L1
+	blt	t1, t2, __reloc_copy
 	add	t0, 4
 
+__reloc_end:
+
 	/* At this point we need to invalidate dcache and */
 	/* icache before jumping to new code */
 
@@ -100,10 +123,10 @@ $L1:
 	.set	mips0
 	bne	t0,t1,1b
 	addu	t0,s1
-	
+
 nodc:
 	/* Now we get to do it all again for the I$ */
-	
+
 	move	s3,zero			/* just in case there is no icache */
 	move	s4,zero
 
@@ -147,20 +170,25 @@ nodc:
 	addu	t0,s3
 
 noic:
-	li	t0, BZ_TEXT_START
-	
+	/* Setup new "C" stack */
+	la	sp, _stack
+
 	addiu	sp, -32			/* reserve stack for parameters */
-#if 0	
+#if 0
 	sw	a0, 0(sp)
 	sw	a1, 4(sp)
 	sw	a2, 8(sp)
 	sw	a3, 12(sp)
-#endif	
+#endif
 	sw	s3, 16(sp)		/* icache line size */
 	sw	s4, 20(sp)		/* icache size */
 	sw	s1, 24(sp)		/* dcache line size */
-	jr	t0
 	sw	s2, 28(sp)		/* dcache size */
-	
+
+	/* jump to the decompressor routine */
+	la	t0, decompress_entry
+	jr	t0
+	nop
+
 	.set reorder
-	END(startup)
+END(startup)
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/loader.lds.in b/target/linux/adm5120-2.6/image/lzma-loader/src/loader.lds.in
index 20f2ea98ec..8c1bb9bd6a 100644
--- a/target/linux/adm5120-2.6/image/lzma-loader/src/loader.lds.in
+++ b/target/linux/adm5120-2.6/image/lzma-loader/src/loader.lds.in
@@ -1,17 +1,27 @@
 OUTPUT_ARCH(mips)
-ENTRY(startup)
 SECTIONS {
-	. = TEXT_START;
 	.text : {
+		_code_start = .;
 		*(.text)
+		*(.text.*)
 		*(.rodata)
+		*(.rodata.*)
+		_code_end = .;
 	}
 
 	.data : {
 		*(.data)
+		*(.data.*)
 	}
 
 	.bss : {
 		*(.bss)
+		*(.bss.*)
 	}
+
+	. = ALIGN(16);
+	. = . + 8192;
+	_stack = .;
+
+	workspace = .;
 }
-- 
GitLab