summaryrefslogtreecommitdiff
path: root/utils/mktccboot
diff options
context:
space:
mode:
Diffstat (limited to 'utils/mktccboot')
-rw-r--r--utils/mktccboot/Makefile28
-rw-r--r--utils/mktccboot/README35
-rw-r--r--utils/mktccboot/main.c133
-rw-r--r--utils/mktccboot/mktccboot.c176
-rw-r--r--utils/mktccboot/mktccboot.h50
5 files changed, 422 insertions, 0 deletions
diff --git a/utils/mktccboot/Makefile b/utils/mktccboot/Makefile
new file mode 100644
index 0000000000..4943a8c568
--- /dev/null
+++ b/utils/mktccboot/Makefile
@@ -0,0 +1,28 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10# We use the Telechips code available in the Rockbox tools/ directory
11TOOLSDIR = ../../tools/
12CFLAGS += -O -g -W -Wall -Wshadow -pedantic -I$(TOOLSDIR)
13
14OUTPUT = mktccboot
15
16
17# inputs
18LIBSOURCES := mktccboot.c $(TOOLSDIR)telechips.c
19SOURCES := main.c
20EXTRADEPS :=
21
22include ../libtools.make
23
24# rule for sources from tools dir
25# Rules go _after_ including mkboot.make to have OBJDIR set up correctly.
26# Paths are assumed to end with a /
27telechips.o: $(OBJDIR)telechips.o
28
diff --git a/utils/mktccboot/README b/utils/mktccboot/README
new file mode 100644
index 0000000000..719846f2e8
--- /dev/null
+++ b/utils/mktccboot/README
@@ -0,0 +1,35 @@
1mktccboot
2---------
3
4A tool to inject a bootloader into a Telechips 77X/78X firmware file.
5
6Usage
7-----
8
9mktccboot <firmware file> <boot file> <output file>
10
11<firmware file> is an original Telechips firmware file.
12
13<boot file> is the code you want to execute (a rockbox bootloader), previously
14 scrambled with tools/scramble utility.
15
16<output file> is the resulting firmware file which you'll have to copy on your
17 player. See "Firmware filenames".
18
19Dual-Boot
20---------
21
22The purpose of this program is to provide dual-boot between the original
23firmware and the new (rockbox) firmware.
24
25By default the player will boot into the new firmware.
26
27To boot into the Original Firmware, you need to press the <???> key.
28
29The player will boot into the Original Firmware as well if it is powered up by
30inserting an usb cable.
31
32Hacking
33-------
34
35See comments in mktccboot.c for more information.
diff --git a/utils/mktccboot/main.c b/utils/mktccboot/main.c
new file mode 100644
index 0000000000..4dd5d0c6c4
--- /dev/null
+++ b/utils/mktccboot/main.c
@@ -0,0 +1,133 @@
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
34static void usage(void)
35{
36 printf("Usage: mktccboot <firmware file> <boot file> <output file>\n");
37
38 exit(1);
39}
40
41int main(int argc, char *argv[])
42{
43 char *infile, *bootfile, *outfile;
44 int fdout = -1;
45 int n, of_size, boot_size, patched_size;
46 unsigned char *of_buf;
47 unsigned char *boot_buf = NULL;
48 unsigned char* image = NULL;
49 int ret = 0;
50
51 if(argc < 3) {
52 usage();
53 }
54
55 infile = argv[1];
56 bootfile = argv[2];
57 outfile = argv[3];
58
59 /* Read OF and boot files */
60 of_buf = file_read(infile, &of_size);
61 if (!of_buf)
62 {
63 ret = 1;
64 goto error_exit;
65 }
66
67 /* Validate input file */
68 if (test_firmware_tcc(of_buf, of_size))
69 {
70 printf("[ERR] Unknown OF file used, aborting\n");
71 ret = 2;
72 goto error_exit;
73 }
74
75 boot_buf = file_read(bootfile, &boot_size);
76 if (!boot_buf)
77 {
78 ret = 3;
79 goto error_exit;
80 }
81
82 /* Allocate buffer for patched firmware */
83 image = malloc(of_size + boot_size);
84 if (image == NULL)
85 {
86 printf("[ERR] Could not allocate memory, aborting\n");
87 ret = 4;
88 goto error_exit;
89 }
90
91 /* Create the patched firmware */
92 image = patch_firmware_tcc(of_buf, of_size, boot_buf, boot_size,
93 &patched_size);
94 if (!image)
95 {
96 printf("[ERR] Error creating patched firmware, aborting\n");
97 ret = 5;
98 goto error_exit;
99 }
100
101 fdout = open(outfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644);
102 if (fdout < 0)
103 {
104 perror(outfile);
105 ret = 6;
106 goto error_exit;
107 }
108
109 n = write(fdout, image, patched_size);
110 if (n != patched_size)
111 {
112 printf("[ERR] Could not write output file %s\n",outfile);
113 ret = 7;
114 goto error_exit;
115 }
116
117error_exit:
118
119 if (fdout >= 0)
120 close(fdout);
121
122 if (of_buf)
123 free(of_buf);
124
125 if (boot_buf)
126 free(boot_buf);
127
128 if (image)
129 free(image);
130
131 return ret;
132}
133
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
diff --git a/utils/mktccboot/mktccboot.h b/utils/mktccboot/mktccboot.h
new file mode 100644
index 0000000000..17179c11e7
--- /dev/null
+++ b/utils/mktccboot/mktccboot.h
@@ -0,0 +1,50 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * mktccboot.h - a tool to inject a bootloader into a Telechips 77X/78X firmware
11 * file.
12 *
13 * Copyright (C) 2009 Tomer Shalev
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#ifndef _MKTCCBOOT_H_
26#define _MKTCCBOOT_H_
27
28/* win32 compatibility */
29#ifndef O_BINARY
30#define O_BINARY 0
31
32#endif
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37/* Injects a bootloader into a Telechips 77X/78X firmware file */
38unsigned char *patch_firmware_tcc(unsigned char *of_buf, int of_size,
39 unsigned char *boot_buf, int boot_size, int *patched_size);
40
41unsigned char *file_read(char *filename, int *size);
42
43/* Test TCC firmware file for consistency using CRC test */
44int test_firmware_tcc(unsigned char* buf, int length);
45
46#ifdef __cplusplus
47};
48#endif
49
50#endif