Fix sansa c200 battery type comment.
[kugel-rb.git] / tools / creative.c
blob1698f58930012c9536c149e621af66ec0c41c158
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * 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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <stdio.h>
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #if !defined(__APPLE__)
27 #include <elf.h>
28 #else
29 #include "mac-elf.h" /* Mac OS X doesn't distribuate elf.h... */
30 #endif
32 #include "creative.h"
33 #include "hmac-sha1.h"
35 static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
36 static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
37 static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
38 static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
40 static const struct device_info devices[] =
42 /* Creative Zen Vision:M */
43 {"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},
44 /* Creative Zen Vision:M Go! */
45 {"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},
46 /* Creative Zen Vision © TL */
47 /* The "©" should be ANSI encoded or the device won't accept the firmware package. */
48 {"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},
49 /* Creative ZEN V */
50 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4},
51 /* Creative ZEN */
52 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N", 48, null_key_v3}
56 Create a Zen Vision:M FRESCUE structure file
58 extern void int2le(unsigned int val, unsigned char* addr);
59 extern unsigned int le2int(unsigned char* buf);
62 static int make_ciff_file(const unsigned char *inbuf, unsigned int length,
63 unsigned char *outbuf, int device)
65 unsigned char key[20];
66 memcpy(outbuf, "FFIC", 4);
67 int2le(length+90, &outbuf[4]);
68 memcpy(&outbuf[8], "FNIC", 4);
69 int2le(96, &outbuf[0xC]);
70 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
71 memset(&outbuf[0x10+devices[device].cinf_size], 0,
72 96 - devices[device].cinf_size);
73 memcpy(&outbuf[0x70], "ATAD", 4);
74 int2le(length+32, &outbuf[0x74]);
75 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m",
76 25); /*Unicode encoded*/
77 memset(&outbuf[0x78+25], 0, 32);
78 memcpy(&outbuf[0x98], inbuf, length);
79 memcpy(&outbuf[0x98+length], "LLUN", 4);
80 int2le(20, &outbuf[0x98+length+4]);
81 /* Do checksum */
82 hmac_sha1((unsigned char *)devices[device].null, strlen(devices[device].null),
83 outbuf, 0x98+length, key);
84 memcpy(&outbuf[0x98+length+8], key, 20);
85 return length+0x90+0x1C+8;
88 static int elf_convert(const unsigned char *inbuf, unsigned char *outbuf)
90 Elf32_Ehdr *main_header;
91 Elf32_Shdr *section_header;
92 unsigned int i, j, sum;
93 intptr_t startaddr;
95 main_header = (Elf32_Ehdr*)inbuf;
96 if( !( main_header->e_ident[0] == ELFMAG0 && main_header->e_ident[1] == ELFMAG1
97 && main_header->e_ident[2] == ELFMAG2 && main_header->e_ident[3] == ELFMAG3 ) )
99 printf("Invalid ELF header!\n");
100 return -1;
103 startaddr = (intptr_t)outbuf;
105 for(i = 0; i < main_header->e_shnum; i++)
107 section_header = (Elf32_Shdr*)(inbuf+main_header->e_shoff+i*sizeof(Elf32_Shdr));
109 if( (section_header->sh_flags & SHF_WRITE || section_header->sh_flags & SHF_ALLOC
110 || section_header->sh_flags & SHF_EXECINSTR) && section_header->sh_size > 0
111 && section_header->sh_type != SHT_NOBITS )
113 /* Address */
114 int2le(section_header->sh_addr, outbuf);
115 outbuf += 4;
116 /* Size */
117 int2le(section_header->sh_size, outbuf);
118 outbuf += 4;
119 /* Checksum */
120 sum = 0;
121 for(j=0; j<section_header->sh_size; j+= 4)
122 sum += le2int((unsigned char*)(inbuf+section_header->sh_offset+j)) + (le2int((unsigned char*)(inbuf+section_header->sh_offset+j))>>16);
123 int2le(sum, outbuf);
124 outbuf += 2;
125 memset(outbuf, 0, 2);
126 outbuf += 2;
127 /* Data */
128 memcpy(outbuf, inbuf+section_header->sh_offset, section_header->sh_size);
129 outbuf += section_header->sh_size;
132 return (int)((intptr_t)outbuf - startaddr);
135 static int make_jrm_file(const unsigned char *inbuf, unsigned char *outbuf)
137 int length;
139 /* Clear the header area to zero */
140 memset(outbuf, 0, 0x18);
142 /* Header (EDOC) */
143 memcpy(outbuf, "EDOC", 4);
144 /* Total Size: temporarily set to 0 */
145 memset(&outbuf[0x4], 0, 4);
146 /* 4 bytes of zero */
147 memset(&outbuf[0x8], 0, 4);
149 length = elf_convert(inbuf, &outbuf[0xC]);
150 if(length < 0)
151 return -1;
152 /* Now set the actual Total Size */
153 int2le(4+length, &outbuf[0x4]);
155 return 0xC+length;
158 int zvm_encode(const char *iname, const char *oname, int device, bool enable_ciff)
160 size_t len;
161 int length;
162 FILE *file;
163 unsigned char *outbuf;
164 unsigned char *buf;
166 file = fopen(iname, "rb");
167 if (!file)
169 perror(iname);
170 return -1;
172 fseek(file, 0, SEEK_END);
173 length = ftell(file);
175 fseek(file, 0, SEEK_SET);
177 buf = (unsigned char*)malloc(length);
178 if ( !buf )
180 printf("Out of memory!\n");
181 return -1;
184 len = fread(buf, 1, length, file);
185 if(len < (size_t)length)
187 perror(iname);
188 return -2;
190 fclose(file);
192 outbuf = (unsigned char*)malloc(length+0x300);
193 if ( !outbuf )
195 free(buf);
196 printf("Out of memory!\n");
197 return -1;
199 length = make_jrm_file(buf, outbuf);
200 free(buf);
201 if(length < 0)
203 free(outbuf);
204 printf("Error in making JRM file!\n");
205 return -1;
207 if(enable_ciff)
209 buf = (unsigned char*)malloc(length+0x200);
210 if ( !buf )
212 free(outbuf);
213 printf("Out of memory!\n");
214 return -1;
216 memset(buf, 0, length+0x200);
217 length = make_ciff_file(outbuf, length, buf, device);
218 free(outbuf);
220 else
221 buf = outbuf;
223 file = fopen(oname, "wb");
224 if (!file)
226 free(buf);
227 perror(oname);
228 return -3;
231 len = fwrite(buf, 1, length, file);
232 if(len < (size_t)length)
234 free(buf);
235 perror(oname);
236 return -4;
239 free(buf);
241 fclose(file);
243 return 0;