summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-08-30 23:17:04 +0000
committerDave Chapman <dave@dchapman.com>2006-08-30 23:17:04 +0000
commit530f31dbe9fe404d41fd21867c8ed9cec1addd96 (patch)
treeec4caa9ead19f3e0756e4cb02bf11d6f8e4163e2
parente379225754b326806df1a037a7610e3b2c1a11bc (diff)
downloadrockbox-530f31dbe9fe404d41fd21867c8ed9cec1addd96.tar.gz
rockbox-530f31dbe9fe404d41fd21867c8ed9cec1addd96.zip
Add generation of .mi4 files - the generic PortalPlayer firmware format used by the iriver H10, Sansa E200 etc. Based on the documentation available at http://daniel.haxx.se/sansa/mi4.html and examination of files produced by mkmi4.sh
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10816 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--tools/Makefile5
-rw-r--r--tools/mi4.c188
-rw-r--r--tools/mi4.h25
-rw-r--r--tools/scramble.c13
4 files changed, 229 insertions, 2 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 68fcd4b6bc..53b1200fce 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -10,17 +10,18 @@ CFLAGS := -O -ansi -g
10LDFLAGS := -g 10LDFLAGS := -g
11 11
12CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ 12CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \
13 generate_rocklatin mkboot ipod_fw codepages uclpack 13 generate_rocklatin mkboot ipod_fw codepages uclpack mi4
14 14
15all: 15all:
16 @echo "Run make in your build directory!" 16 @echo "Run make in your build directory!"
17 17
18scramble: scramble.o iriver.o 18scramble: scramble.o iriver.o mi4.o
19descramble: descramble.o iriver.o 19descramble: descramble.o iriver.o
20 20
21scramble.o: scramble.c iriver.h 21scramble.o: scramble.c iriver.h
22descramble.o: descramble.c iriver.h 22descramble.o: descramble.c iriver.h
23iriver.o: iriver.c iriver.h 23iriver.o: iriver.c iriver.h
24mi4.o: mi4.c mi4.h
24 25
25sh2d: sh2d.c 26sh2d: sh2d.c
26 27
diff --git a/tools/mi4.c b/tools/mi4.c
new file mode 100644
index 0000000000..b0fff98e1c
--- /dev/null
+++ b/tools/mi4.c
@@ -0,0 +1,188 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24/*
25 * CRC32 implementation taken from:
26 *
27 * efone - Distributed internet phone system.
28 *
29 * (c) 1999,2000 Krzysztof Dabrowski
30 * (c) 1999,2000 ElysiuM deeZine
31 *
32 * This program is free software; you can redistribute it and/or
33 * modify it under the terms of the GNU General Public License
34 * as published by the Free Software Foundation; either version
35 * 2 of the License, or (at your option) any later version.
36 *
37 */
38
39/* based on implementation by Finn Yannick Jacobs */
40
41#include <stdio.h>
42#include <stdlib.h>
43
44/* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab().
45 * so make sure, you call it before using the other
46 * functions!
47 */
48static unsigned int crc_tab[256];
49
50/* chksum_crc() -- to a given block, this one calculates the
51 * crc32-checksum until the length is
52 * reached. the crc32-checksum will be
53 * the result.
54 */
55static unsigned int chksum_crc32 (unsigned char *block, unsigned int length)
56{
57 register unsigned long crc;
58 unsigned long i;
59
60 crc = 0;
61 for (i = 0; i < length; i++)
62 {
63 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
64 }
65 return (crc);
66}
67
68/* chksum_crc32gentab() -- to a global crc_tab[256], this one will
69 * calculate the crcTable for crc32-checksums.
70 * it is generated to the polynom [..]
71 */
72
73static void chksum_crc32gentab (void)
74{
75 unsigned long crc, poly;
76 int i, j;
77
78 poly = 0xEDB88320L;
79 for (i = 0; i < 256; i++)
80 {
81 crc = i;
82 for (j = 8; j > 0; j--)
83 {
84 if (crc & 1)
85 {
86 crc = (crc >> 1) ^ poly;
87 }
88 else
89 {
90 crc >>= 1;
91 }
92 }
93 crc_tab[i] = crc;
94 }
95}
96
97static void int2le(unsigned int val, unsigned char* addr)
98{
99 addr[0] = val & 0xFF;
100 addr[1] = (val >> 8) & 0xff;
101 addr[2] = (val >> 16) & 0xff;
102 addr[3] = (val >> 24) & 0xff;
103}
104
105int mi4_encode(char *iname, char *oname, int version)
106{
107 size_t len;
108 int length;
109 int mi4length;
110 FILE *file;
111 unsigned int crc = 0;
112 unsigned char *outbuf;
113
114 file = fopen(iname, "rb");
115 if (!file) {
116 perror(iname);
117 return -1;
118 }
119 fseek(file,0,SEEK_END);
120 length = ftell(file);
121
122 fseek(file,0,SEEK_SET);
123
124 /* Add 4 bytes to length (for magic), the 0x200 byte header and
125 then round to an even 0x400 bytes
126 */
127 mi4length = (length+4+0x200+0x3ff)&~0x3ff;
128
129 outbuf = malloc(mi4length);
130
131 if ( !outbuf ) {
132 printf("out of memory!\n");
133 return -1;
134 }
135
136 /* Clear the buffer to zero */
137 memset(outbuf, 0, mi4length);
138
139 len = fread(outbuf+0x200, 1, length, file);
140 if(len < length) {
141 perror(iname);
142 return -2;
143 }
144 fclose(file);
145
146 /* We need to write some data into the actual image - before calculating
147 the CRC. */
148 int2le(0x00000100, &outbuf[0x2e0]); /* magic */
149 int2le(0x000000ec, &outbuf[0x2e4]); /* magic */
150 int2le(length+4, &outbuf[0x2e8]); /* length plus 0xaa55aa55 */
151
152 int2le(0xaa55aa55, &outbuf[0x200+length]); /* More Magic */
153
154 /* Calculate CRC32 checksum */
155 chksum_crc32gentab ();
156 crc = chksum_crc32 (outbuf+28,mi4length-28);
157
158 strncpy((char *)outbuf, "PPOS", 4); /* Magic */
159 int2le(version, &outbuf[0x04]); /* .mi4 version */
160 int2le(length+4, &outbuf[0x08]); /* Length of firmware plus magic */
161 int2le(crc, &outbuf[0x0c]); /* CRC32 of mi4 file */
162 int2le(0x00000002, &outbuf[0x10]); /* Encryption type: 2 = TEA */
163 int2le(mi4length, &outbuf[0x14]); /* Total .mi4 length */
164 int2le(mi4length-0x200, &outbuf[0x18]); /* Length of plaintext part */
165
166 /* v3 files require a dummy DSA signature */
167 if (version == 0x00010301) {
168 outbuf[0x2f]=0x01;
169 }
170
171 file = fopen(oname, "wb");
172 if (!file) {
173 perror(oname);
174 return -3;
175 }
176
177 len = fwrite(outbuf, 1, mi4length, file);
178 if(len < length) {
179 perror(oname);
180 return -4;
181 }
182
183 fclose(file);
184
185 fprintf(stderr, "File encoded successfully\n" );
186
187 return 0;
188}
diff --git a/tools/mi4.h b/tools/mi4.h
new file mode 100644
index 0000000000..ec3a7342d0
--- /dev/null
+++ b/tools/mi4.h
@@ -0,0 +1,25 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _MI4_H
21#define _MI4_H
22
23int mi4_encode(char *iname, char *oname, int version);
24
25#endif
diff --git a/tools/scramble.c b/tools/scramble.c
index c3eb1782af..d1e3d1d341 100644
--- a/tools/scramble.c
+++ b/tools/scramble.c
@@ -22,6 +22,7 @@
22#include <stdbool.h> 22#include <stdbool.h>
23#include <string.h> 23#include <string.h>
24#include "iriver.h" 24#include "iriver.h"
25#include "mi4.h"
25 26
26int iaudio_encode(char *iname, char *oname, char *idstring); 27int iaudio_encode(char *iname, char *oname, char *idstring);
27int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc); 28int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc);
@@ -82,6 +83,8 @@ void usage(void)
82 "\t-ipod3g ipod firmware partition format (3rd Gen)\n" 83 "\t-ipod3g ipod firmware partition format (3rd Gen)\n"
83 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n" 84 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
84 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n" 85 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
86 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
87 "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
85 "\t-add=X Rockbox generic \"add-up\" checksum format\n" 88 "\t-add=X Rockbox generic \"add-up\" checksum format\n"
86 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd\n" 89 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd\n"
87 "\t ip3g, ip4g, mini, x5, h10, h10_5gb)\n" 90 "\t ip3g, ip4g, mini, x5, h10, h10_5gb)\n"
@@ -241,6 +244,16 @@ int main (int argc, char** argv)
241 oname = argv[3]; 244 oname = argv[3];
242 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */ 245 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
243 } 246 }
247 else if(!strcmp(argv[1], "-mi4v2")) {
248 iname = argv[2];
249 oname = argv[3];
250 return mi4_encode(iname, oname, 0x00010201);
251 }
252 else if(!strcmp(argv[1], "-mi4v3")) {
253 iname = argv[2];
254 oname = argv[3];
255 return mi4_encode(iname, oname, 0x00010301);
256 }
244 257
245 /* open file */ 258 /* open file */
246 file = fopen(iname,"rb"); 259 file = fopen(iname,"rb");