Rework and improve http download cache: check cache against file on the server and...
[Rockbox.git] / tools / creative.c
blob287df03a7c7ab3b17ba27d5da9520d49070a3eda
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <stdio.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "creative.h"
26 #include "hmac-sha1.h"
28 static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
29 static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
30 static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
31 static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
33 static const unsigned char bootloader_v1[] =
35 0xD3, 0xF0, 0x29, 0xE3, /* MSR CPSR_cf, #0xD3 */
36 0x09, 0xF6, 0xA0, 0xE3 /* MOV PC, #0x900000 */
39 static const unsigned char bootloader_v2[] =
41 0xD3, 0xF0, 0x29, 0xE3, /* MSR CPSR_cf, #0xD3 */
42 0x09, 0xF6, 0xA0, 0xE3 /* MOV PC, #0x40000000 */
45 static const unsigned char bootloader_v3[] =
47 0 /* Unknown */
50 static const struct device_info devices[] =
52 /* Creative Zen Vision:M */
53 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0:\0M", 42, null_key_v2, bootloader_v1, sizeof(bootloader_v1), 0x00900000},
54 /* Creative Zen Vision:M Go! */
55 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0:\0M\0 \0G\0o\0!", 50, null_key_v2, bootloader_v1, sizeof(bootloader_v1), 0x00900000},
56 /* Creative Zen Vision © TL */
57 /* The "©" should be ANSI encoded or the device won't accept the firmware package. */
58 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0 \0©\0T\0L", 46, null_key_v2, bootloader_v1, sizeof(bootloader_v1), 0x00900000},
59 /* Creative ZEN V */
60 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4, bootloader_v3, sizeof(bootloader_v3), 0x00000000},
61 /* Creative ZEN */
62 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N", 48, null_key_v3, bootloader_v2, sizeof(bootloader_v2), 0x40000000}
66 Create a Zen Vision:M FRESCUE structure file
68 extern void int2le(unsigned int val, unsigned char* addr);
69 extern unsigned int le2int(unsigned char* buf);
72 static int make_ciff_file(unsigned char *inbuf, unsigned int length,
73 unsigned char *outbuf, int device)
75 unsigned char key[20];
76 memcpy(outbuf, "FFIC", 4);
77 int2le(length+90, &outbuf[4]);
78 memcpy(&outbuf[8], "FNIC", 4);
79 int2le(96, &outbuf[0xC]);
80 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
81 memset(&outbuf[0x10+devices[device].cinf_size], 0,
82 96 - devices[device].cinf_size);
83 memcpy(&outbuf[0x70], "ATAD", 4);
84 int2le(length+32, &outbuf[0x74]);
85 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m",
86 32); /*Unicode encoded*/
87 memcpy(&outbuf[0x98], inbuf, length);
88 memcpy(&outbuf[0x98+length], "LLUN", 4);
89 int2le(20, &outbuf[0x98+length+4]);
90 /* Do checksum */
91 hmac_sha1((unsigned char *)devices[device].null, strlen(devices[device].null),
92 outbuf, 0x98+length, key);
93 memcpy(&outbuf[0x98+length+8], key, 20);
94 return length+0x90+0x1C+8;
97 static int make_jrm_file(unsigned char *inbuf, unsigned int length,
98 unsigned char *outbuf, int device)
100 unsigned int i;
101 unsigned int sum = 0;
103 /* Clear the header area to zero */
104 memset(outbuf, 0, 0x18);
106 /* Header (EDOC) */
107 memcpy(outbuf, "EDOC", 4);
108 /* Total Size */
109 #define SIZEOF_BOOTLOADER_CODE devices[device].bootloader_size
110 int2le(4+0xC+SIZEOF_BOOTLOADER_CODE+0xC+length, &outbuf[0x4]);
111 /* 4 bytes of zero */
112 memset(&outbuf[0x8], 0, 0x4);
114 /* First block starts here ... */
115 /* Address = 0x0 */
116 memset(&outbuf[0xC], 0, 0x4);
117 /* Size */
118 int2le(SIZEOF_BOOTLOADER_CODE, &outbuf[0x10]);
119 /* Checksum */
120 for(i=0; i<SIZEOF_BOOTLOADER_CODE; i+= 4)
121 sum += le2int((unsigned char*)&devices[device].bootloader[i]) + (le2int((unsigned char*)&devices[device].bootloader[i])>>16);
122 int2le(sum, &outbuf[0x14]);
123 outbuf[0x16] = 0;
124 outbuf[0x17] = 0;
125 /*Data */
126 memcpy(&outbuf[0x18], devices[device].bootloader, SIZEOF_BOOTLOADER_CODE);
128 /* Second block starts here ... */
129 /* Address = depends on target */
130 #define SB_START (0x18+SIZEOF_BOOTLOADER_CODE)
131 int2le(devices[device].memory_address, &outbuf[SB_START]);
132 /* Size */
133 int2le(length, &outbuf[SB_START+0x4]);
134 /* Checksum */
135 sum = 0;
136 for(i=0; i<length; i+= 4)
137 sum += le2int(&inbuf[i]) + (le2int(&inbuf[i])>>16);
138 int2le(sum, &outbuf[SB_START+0x8]);
139 outbuf[SB_START+0xA] = 0;
140 outbuf[SB_START+0xB] = 0;
141 /* Data */
142 memcpy(&outbuf[SB_START+0xC], inbuf, length);
144 return SB_START+0xC+length;
147 int zvm_encode(char *iname, char *oname, int device)
149 size_t len;
150 int length;
151 FILE *file;
152 unsigned char *outbuf;
153 unsigned char *buf;
155 file = fopen(iname, "rb");
156 if (!file) {
157 perror(iname);
158 return -1;
160 fseek(file, 0, SEEK_END);
161 length = ftell(file);
163 fseek(file, 0, SEEK_SET);
165 buf = (unsigned char*)malloc(length);
166 if ( !buf ) {
167 printf("out of memory!\n");
168 return -1;
171 len = fread(buf, 1, length, file);
172 if(len < (size_t)length) {
173 perror(iname);
174 return -2;
176 fclose(file);
178 outbuf = (unsigned char*)malloc(length+0x300);
179 if ( !outbuf ) {
180 free(buf);
181 printf("out of memory!\n");
182 return -1;
184 length = make_jrm_file(buf, len, outbuf, device);
185 free(buf);
186 buf = (unsigned char*)malloc(length+0x200);
187 memset(buf, 0, length+0x200);
188 length = make_ciff_file(outbuf, length, buf, device);
189 free(outbuf);
191 file = fopen(oname, "wb");
192 if (!file) {
193 free(buf);
194 perror(oname);
195 return -3;
198 len = fwrite(buf, 1, length, file);
199 if(len < (size_t)length) {
200 free(buf);
201 perror(oname);
202 return -4;
205 free(buf);
207 fclose(file);
209 return 0;