summaryrefslogtreecommitdiff
path: root/utils/mktccboot/mktccboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/mktccboot/mktccboot.c')
-rw-r--r--utils/mktccboot/mktccboot.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/utils/mktccboot/mktccboot.c b/utils/mktccboot/mktccboot.c
new file mode 100644
index 0000000000..4f2c3258db
--- /dev/null
+++ b/utils/mktccboot/mktccboot.c
@@ -0,0 +1,176 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Dave Chapman
11 *
12 * Based on mkboot, Copyright (C) 2005 by Linus Nielsen Feltzing
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <fcntl.h>
30#include <inttypes.h>
31#include "mktccboot.h"
32#include "telechips.h"
33
34/*
35
36Append a Rockbox bootloader to a Telechips original firmware file.
37
38The first instruction in a TCC firmware file is always of the form:
39
40 ldr pc, [pc, #xxx]
41
42where [pc, #xxx] is the entry point of the firmware - e.g. 0x20000020
43
44mktccboot appends the Rockbox bootloader to the end of the original
45firmware image and replaces the contents of [pc, #xxx] with the entry
46point of our bootloader - i.e. the length of the original firmware plus
470x20000000.
48
49It then stores the original entry point from [pc, #xxx] in a fixed
50offset in the Rockbox boootloader, which is used by the bootloader to
51dual-boot.
52
53Finally, mktccboot corrects the length and CRCs in the main firmware
54header, creating a new legal firmware file which can be installed on
55the device.
56
57*/
58
59/* win32 compatibility */
60
61#ifndef O_BINARY
62#define O_BINARY 0
63#endif
64
65static void put_uint32le(uint32_t x, unsigned char* p)
66{
67 p[0] = x & 0xff;
68 p[1] = (x >> 8) & 0xff;
69 p[2] = (x >> 16) & 0xff;
70 p[3] = (x >> 24) & 0xff;
71}
72
73static uint32_t get_uint32le(unsigned char* p)
74{
75 return (p[3] << 24) | (p[2] << 16) | (p[1]<<8) | p[0];
76}
77
78static off_t filesize(int fd) {
79 struct stat buf;
80
81 if (fstat(fd,&buf) < 0) {
82 perror("[ERR] Checking filesize of input file");
83 return -1;
84 } else {
85 return(buf.st_size);
86 }
87}
88
89#define DRAMORIG 0x20000000
90/* Injects a bootloader into a Telechips 77X/78X firmware file */
91unsigned char *patch_firmware_tcc(unsigned char *of_buf, int of_size,
92 unsigned char *boot_buf, int boot_size, int *patched_size)
93{
94 unsigned char *patched_buf;
95 uint32_t ldr, old_ep_offset, new_ep_offset;
96 int of_offset;
97
98 patched_buf = malloc(of_size + boot_size);
99 if (!patched_buf)
100 return NULL;
101
102 memcpy(patched_buf, of_buf, of_size);
103 memcpy(patched_buf + of_size, boot_buf, boot_size);
104
105 ldr = get_uint32le(patched_buf);
106
107 /* TODO: Verify it's a LDR instruction */
108 of_offset = (ldr & 0xfff) + 8;
109 old_ep_offset = get_uint32le(patched_buf + of_offset);
110 new_ep_offset = DRAMORIG + of_size;
111
112 printf("OF entry point: 0x%08x\n", old_ep_offset);
113 printf("New entry point: 0x%08x\n", new_ep_offset + 8);
114
115 /* Save the OF entry point at the start of the bootloader image */
116 put_uint32le(old_ep_offset, patched_buf + of_size);
117 put_uint32le(new_ep_offset, patched_buf + of_size + 4);
118
119 /* Change the OF entry point to the third word in our bootloader */
120 put_uint32le(new_ep_offset + 8, patched_buf + of_offset);
121
122 telechips_encode_crc(patched_buf, of_size + boot_size);
123 *patched_size = of_size + boot_size;
124
125 return patched_buf;
126}
127
128unsigned char *file_read(char *filename, int *size)
129{
130 unsigned char *buf = NULL;
131 int n, fd = -1;
132
133 /* Open file for reading */
134 fd = open(filename, O_RDONLY|O_BINARY);
135 if (fd < 0)
136 {
137 printf("[ERR] Could open file for reading, aborting\n");
138 perror(filename);
139 goto error;
140 }
141
142 /* Get file size, and allocate a buffer of that size */
143 *size = filesize(fd);
144 buf = malloc(*size);
145 if (buf == NULL)
146 {
147 printf("[ERR] Could not allocate memory, aborting\n");
148 goto error;
149 }
150
151 /* Read the file's content to the buffer */
152 n = read(fd, buf, *size);
153 if (n != *size)
154 {
155 printf("[ERR] Could not read from %s\n", filename);
156 goto error;
157 }
158
159 return buf;
160
161error:
162 if (fd >= 0)
163 close(fd);
164
165 if (buf)
166 free(buf);
167
168 return NULL;
169}
170
171/* A CRC test in order to reject non OF file */
172int test_firmware_tcc(unsigned char* buf, int length)
173{
174 return telechips_test_crc(buf, length);
175}
176