From 104b81ea9a1a9c7b67e9e060fef4d0a97a547b7b Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Mon, 28 Nov 2005 23:40:57 +0000 Subject: Fixed self-extracting loader: (1) Proper startup code, ensuring the stack pointer is set to the desired location. (2) Code cleanup. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8103 a1c6a512-1295-4272-9138-f99709370657 --- firmware/decompressor/Makefile | 2 +- firmware/decompressor/decompressor.c | 33 +++++++-------------- firmware/decompressor/startup.S | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 24 deletions(-) create mode 100755 firmware/decompressor/startup.S diff --git a/firmware/decompressor/Makefile b/firmware/decompressor/Makefile index 99e91aa35e..29a78523ea 100644 --- a/firmware/decompressor/Makefile +++ b/firmware/decompressor/Makefile @@ -21,7 +21,7 @@ MEMORYSIZE = 2 LDS := link.lds LINKFILE = $(OBJDIR)/linkage.lds -OBJS := $(OBJDIR)/decompressor.o $(OBJDIR)/rockboxucl.o +OBJS := $(OBJDIR)/decompressor.o $(OBJDIR)/rockboxucl.o $(OBJDIR)/startup.o CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns diff --git a/firmware/decompressor/decompressor.c b/firmware/decompressor/decompressor.c index 1223ff2f05..9cd7d5998e 100644 --- a/firmware/decompressor/decompressor.c +++ b/firmware/decompressor/decompressor.c @@ -31,7 +31,8 @@ extern char imgstart[], imgend[]; extern char loadaddress[], dramend[]; /* Prototypes */ -void start(void) __attribute__ ((section (".start"))); +extern void start(void); + void main(void) ICODE_ATTR; int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst, unsigned long *dst_len) ICODE_ATTR; @@ -45,22 +46,6 @@ void (*vbr[]) (void) __attribute__ ((section (".vectors"))) = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; -/* Inline copy function */ -static inline void longcopy(long *dst, long *dst_end, const long *src) - __attribute__ ((always_inline)); -static inline void longcopy(long *dst, long *dst_end, const long *src) -{ - while (dst < dst_end) - *dst++ = *src++; -} - -/* Entry point */ -void start(void) -{ - longcopy((long *)iramstart, (long *)iramend, (long *)iramcopy); - main(); -} - /** All subsequent functions are executed from IRAM **/ /* Thinned out version of the UCL 2e decompression sourcecode @@ -133,18 +118,20 @@ void main(void) { unsigned long dst_len; /* dummy */ unsigned long img_len = (unsigned long)(imgend - imgstart); - - longcopy((long *)(dramend - img_len), (long *) dramend, - (long *) imgstart); - + unsigned long *src = (unsigned long *)imgstart; + unsigned long *dst = (unsigned long *)(dramend - img_len); + + do + *dst++ = *src++; + while (dst < (unsigned long *)dramend); + ucl_nrv2e_decompress_8(dramend - img_len + UCL_HEADER, loadaddress, &dst_len); asm( "mov.l @%0+,r0 \n" - "mov.l @%0+,r15 \n" "jmp @r0 \n" - "nop \n" + "mov.l @%0+,r15 \n" : : "r"(loadaddress) : "r0" ); } diff --git a/firmware/decompressor/startup.S b/firmware/decompressor/startup.S new file mode 100755 index 0000000000..62efef9cc3 --- /dev/null +++ b/firmware/decompressor/startup.S @@ -0,0 +1,57 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Jens Arnold + * based on crt0.S by Linus Nielsen Feltzing + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + .section .start,"ax",@progbits + .global _start +_start: + /* copy the .iram section */ + mov.l .iramcopy_k,r0 + mov.l .iram_k,r1 + mov.l .iramend_k,r2 + /* Note: We cannot put a PC relative load into the delay slot of a 'bra' + instruction (the offset would be wrong), but there is nothing else to + do before the loop, so the delay slot would be 'nop'. The cmp / bf + sequence is the same length, but more efficient. */ + cmp/hi r1,r2 + bf .noiramcopy +.iramloop: + mov.l @r0+,r3 + mov.l r3,@r1 + add #4,r1 + cmp/hi r1,r2 + bt .iramloop +.noiramcopy: + + /* call the mainline */ + mov.l .main_k,r0 + mov.l .stackend_k,r15 + jmp @r0 + nop + + .align 2 +.iramcopy_k: + .long _iramcopy +.iram_k: + .long _iramstart +.iramend_k: + .long _iramend +.stackend_k: + .long _stackend +.main_k: + .long _main -- cgit v1.2.3