blob: fe663555634f21bf8497c8a46b18733a120bba10 [file] [log] [blame]
Dave Chapman530f31d2006-08-30 23:17:04 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Dave Chapman
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Dave Chapman530f31d2006-08-30 23:17:04 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26/*
27 * CRC32 implementation taken from:
28 *
29 * efone - Distributed internet phone system.
30 *
31 * (c) 1999,2000 Krzysztof Dabrowski
32 * (c) 1999,2000 ElysiuM deeZine
33 *
34 * This program is free software; you can redistribute it and/or
35 * modify it under the terms of the GNU General Public License
36 * as published by the Free Software Foundation; either version
37 * 2 of the License, or (at your option) any later version.
38 *
39 */
40
41/* based on implementation by Finn Yannick Jacobs */
42
43#include <stdio.h>
44#include <stdlib.h>
45
46/* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab().
47 * so make sure, you call it before using the other
48 * functions!
49 */
50static unsigned int crc_tab[256];
51
52/* chksum_crc() -- to a given block, this one calculates the
53 * crc32-checksum until the length is
54 * reached. the crc32-checksum will be
55 * the result.
56 */
57static unsigned int chksum_crc32 (unsigned char *block, unsigned int length)
58{
59 register unsigned long crc;
60 unsigned long i;
61
62 crc = 0;
63 for (i = 0; i < length; i++)
64 {
65 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
66 }
67 return (crc);
68}
69
70/* chksum_crc32gentab() -- to a global crc_tab[256], this one will
71 * calculate the crcTable for crc32-checksums.
72 * it is generated to the polynom [..]
73 */
74
75static void chksum_crc32gentab (void)
76{
77 unsigned long crc, poly;
78 int i, j;
79
80 poly = 0xEDB88320L;
81 for (i = 0; i < 256; i++)
82 {
83 crc = i;
84 for (j = 8; j > 0; j--)
85 {
86 if (crc & 1)
87 {
88 crc = (crc >> 1) ^ poly;
89 }
90 else
91 {
92 crc >>= 1;
93 }
94 }
95 crc_tab[i] = crc;
96 }
97}
98
99static void int2le(unsigned int val, unsigned char* addr)
100{
101 addr[0] = val & 0xFF;
102 addr[1] = (val >> 8) & 0xff;
103 addr[2] = (val >> 16) & 0xff;
104 addr[3] = (val >> 24) & 0xff;
105}
106
Barry Wardell12df7742007-03-14 13:51:05 +0000107int mi4_encode(char *iname, char *oname, int version, int magic,
108 char *model, char *type)
Dave Chapman530f31d2006-08-30 23:17:04 +0000109{
110 size_t len;
111 int length;
112 int mi4length;
113 FILE *file;
114 unsigned int crc = 0;
115 unsigned char *outbuf;
116
117 file = fopen(iname, "rb");
118 if (!file) {
119 perror(iname);
120 return -1;
121 }
122 fseek(file,0,SEEK_END);
123 length = ftell(file);
124
125 fseek(file,0,SEEK_SET);
126
127 /* Add 4 bytes to length (for magic), the 0x200 byte header and
128 then round to an even 0x400 bytes
129 */
130 mi4length = (length+4+0x200+0x3ff)&~0x3ff;
131
132 outbuf = malloc(mi4length);
133
134 if ( !outbuf ) {
135 printf("out of memory!\n");
136 return -1;
137 }
138
139 /* Clear the buffer to zero */
140 memset(outbuf, 0, mi4length);
141
142 len = fread(outbuf+0x200, 1, length, file);
Daniel Stenbergafc39fb2008-04-09 13:18:59 +0000143 if(len < (size_t)length) {
Dave Chapman530f31d2006-08-30 23:17:04 +0000144 perror(iname);
145 return -2;
146 }
147 fclose(file);
148
149 /* We need to write some data into the actual image - before calculating
150 the CRC. */
151 int2le(0x00000100, &outbuf[0x2e0]); /* magic */
Daniel Stenberg34080492007-02-23 22:45:00 +0000152 int2le(magic, &outbuf[0x2e4]); /* magic */
Dave Chapman530f31d2006-08-30 23:17:04 +0000153 int2le(length+4, &outbuf[0x2e8]); /* length plus 0xaa55aa55 */
154
155 int2le(0xaa55aa55, &outbuf[0x200+length]); /* More Magic */
Barry Wardell12df7742007-03-14 13:51:05 +0000156
Barry Wardell84ff46a2007-03-15 13:04:38 +0000157 strncpy((char *)outbuf+0x1f8, type, 4); /* type of binary (RBBL, RBOS) */
158 strncpy((char *)outbuf+0x1fc, model, 4); /* 4 character model id */
Barry Wardell12df7742007-03-14 13:51:05 +0000159
Dave Chapman530f31d2006-08-30 23:17:04 +0000160 /* Calculate CRC32 checksum */
161 chksum_crc32gentab ();
Barry Wardell84ff46a2007-03-15 13:04:38 +0000162 crc = chksum_crc32 (outbuf+0x200,mi4length-0x200);
Dave Chapman530f31d2006-08-30 23:17:04 +0000163
164 strncpy((char *)outbuf, "PPOS", 4); /* Magic */
165 int2le(version, &outbuf[0x04]); /* .mi4 version */
166 int2le(length+4, &outbuf[0x08]); /* Length of firmware plus magic */
167 int2le(crc, &outbuf[0x0c]); /* CRC32 of mi4 file */
168 int2le(0x00000002, &outbuf[0x10]); /* Encryption type: 2 = TEA */
169 int2le(mi4length, &outbuf[0x14]); /* Total .mi4 length */
170 int2le(mi4length-0x200, &outbuf[0x18]); /* Length of plaintext part */
171
172 /* v3 files require a dummy DSA signature */
173 if (version == 0x00010301) {
174 outbuf[0x2f]=0x01;
175 }
176
177 file = fopen(oname, "wb");
178 if (!file) {
179 perror(oname);
180 return -3;
181 }
182
183 len = fwrite(outbuf, 1, mi4length, file);
Daniel Stenbergafc39fb2008-04-09 13:18:59 +0000184 if(len < (size_t)length) {
Dave Chapman530f31d2006-08-30 23:17:04 +0000185 perror(oname);
186 return -4;
187 }
188
189 fclose(file);
190
191 fprintf(stderr, "File encoded successfully\n" );
192
193 return 0;
194}