1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 by Dave Chapman
12 * Based on mkboot, Copyright (C) 2005 by Linus Nielsen Feltzing
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
24 #include <sys/types.h>
28 #include "telechips.h"
32 Append a Rockbox bootloader to a Telechips original firmware file.
34 The first instruction in a TCC firmware file is always of the form:
38 where [pc, #xxx] is the entry point of the firmware - e.g. 0x20000020
40 mktccboot appends the Rockbox bootloader to the end of the original
41 firmware image and replaces the contents of [pc, #xxx] with the entry
42 point of our bootloader - i.e. the length of the original firmware plus
45 It then stores the original entry point from [pc, #xxx] in a fixed
46 offset in the Rockbox boootloader, which is used by the bootloader to
49 Finally, mktccboot corrects the length and CRCs in the main firmware
50 header, creating a new legal firmware file which can be installed on
55 /* win32 compatibility */
61 static void put_uint32le(uint32_t x
, unsigned char* p
)
64 p
[1] = (x
>> 8) & 0xff;
65 p
[2] = (x
>> 16) & 0xff;
66 p
[3] = (x
>> 24) & 0xff;
69 static uint32_t get_uint32le(unsigned char* p
)
71 return (p
[3] << 24) | (p
[2] << 16) | (p
[1]<<8) | p
[0];
76 printf("Usage: mktccboot <firmware file> <boot file> <output file>\n");
81 off_t
filesize(int fd
) {
84 if (fstat(fd
,&buf
) < 0) {
85 perror("[ERR] Checking filesize of input file");
93 int main(int argc
, char *argv
[])
95 char *infile
, *bootfile
, *outfile
;
96 int fdin
, fdboot
,fdout
;
98 int inlength
,bootlength
;
100 unsigned char* image
;
111 fdin
= open(infile
, O_RDONLY
|O_BINARY
);
117 fdboot
= open(bootfile
, O_RDONLY
|O_BINARY
);
123 inlength
= filesize(fdin
);
124 bootlength
= filesize(fdboot
);
126 image
= malloc(inlength
+ bootlength
);
130 printf("[ERR] Could not allocate memory, aborting\n");
134 n
= read(fdin
, image
, inlength
);
137 printf("[ERR] Could not read from %s\n",infile
);
141 n
= read(fdboot
, image
+ inlength
, bootlength
);
144 printf("[ERR] Could not read from %s\n",bootfile
);
148 ldr
= get_uint32le(image
);
150 /* TODO: Verify it's a LDR instruction */
151 origoffset
= (ldr
&0xfff) + 8;
153 printf("original firmware entry point: 0x%08x\n",get_uint32le(image
+ origoffset
));
154 printf("New entry point: 0x%08x\n",0x20000000 + inlength
+ 8);
156 /* Save the original firmware entry point at the start of the bootloader image */
157 put_uint32le(get_uint32le(image
+ origoffset
),image
+inlength
);
158 put_uint32le(0x20000000 + inlength
,image
+ inlength
+ 4);
160 /* Change the original firmware entry point to the third word in our bootloader */
161 put_uint32le(0x20000000 + inlength
+ 8,image
+origoffset
);
164 telechips_encode_crc(image
, inlength
+ bootlength
);
166 fdout
= open(outfile
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_BINARY
, 0644);
172 n
= write(fdout
, image
, inlength
+ bootlength
);
173 if (n
!= inlength
+ bootlength
)
175 printf("[ERR] Could not write output file %s\n",outfile
);