Manual: Add a midiplay chapter in the viewers section. Based on the wiki page complet...
[kugel-rb.git] / tools / creative.c
blobfaa95650a479085fd377555abc85ecb06f580dde
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>
24 #include <elf.h>
26 #include "creative.h"
27 #include "hmac-sha1.h"
29 static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
30 static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
31 static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
32 static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
34 static const struct device_info devices[] =
36 /* Creative Zen Vision:M */
37 {"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},
38 /* Creative Zen Vision:M Go! */
39 {"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},
40 /* Creative Zen Vision © TL */
41 /* The "©" should be ANSI encoded or the device won't accept the firmware package. */
42 {"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},
43 /* Creative ZEN V */
44 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4},
45 /* Creative ZEN */
46 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N", 48, null_key_v3}
50 Create a Zen Vision:M FRESCUE structure file
52 extern void int2le(unsigned int val, unsigned char* addr);
53 extern unsigned int le2int(unsigned char* buf);
56 static int make_ciff_file(const unsigned char *inbuf, unsigned int length,
57 unsigned char *outbuf, int device)
59 unsigned char key[20];
60 memcpy(outbuf, "FFIC", 4);
61 int2le(length+90, &outbuf[4]);
62 memcpy(&outbuf[8], "FNIC", 4);
63 int2le(96, &outbuf[0xC]);
64 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
65 memset(&outbuf[0x10+devices[device].cinf_size], 0,
66 96 - devices[device].cinf_size);
67 memcpy(&outbuf[0x70], "ATAD", 4);
68 int2le(length+32, &outbuf[0x74]);
69 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m",
70 25); /*Unicode encoded*/
71 memset(&outbuf[0x78+25], 0, 32);
72 memcpy(&outbuf[0x98], inbuf, length);
73 memcpy(&outbuf[0x98+length], "LLUN", 4);
74 int2le(20, &outbuf[0x98+length+4]);
75 /* Do checksum */
76 hmac_sha1((unsigned char *)devices[device].null, strlen(devices[device].null),
77 outbuf, 0x98+length, key);
78 memcpy(&outbuf[0x98+length+8], key, 20);
79 return length+0x90+0x1C+8;
82 static int elf_convert(const unsigned char *inbuf, unsigned char *outbuf)
84 Elf32_Ehdr *main_header;
85 Elf32_Shdr *section_header;
86 unsigned int i, j, sum;
87 intptr_t startaddr;
89 main_header = (Elf32_Ehdr*)inbuf;
90 if( !( main_header->e_ident[0] == ELFMAG0 && main_header->e_ident[1] == ELFMAG1
91 && main_header->e_ident[2] == ELFMAG2 && main_header->e_ident[3] == ELFMAG3 ) )
93 printf("Invalid ELF header!\n");
94 return -1;
97 startaddr = (intptr_t)outbuf;
99 for(i = 0; i < main_header->e_shnum; i++)
101 section_header = (Elf32_Shdr*)(inbuf+main_header->e_shoff+i*sizeof(Elf32_Shdr));
103 if( (section_header->sh_flags & SHF_WRITE || section_header->sh_flags & SHF_ALLOC
104 || section_header->sh_flags & SHF_EXECINSTR) && section_header->sh_size > 0
105 && section_header->sh_type != SHT_NOBITS )
107 /* Address */
108 int2le(section_header->sh_addr, outbuf);
109 outbuf += 4;
110 /* Size */
111 int2le(section_header->sh_size, outbuf);
112 outbuf += 4;
113 /* Checksum */
114 sum = 0;
115 for(j=0; j<section_header->sh_size; j+= 4)
116 sum += le2int((unsigned char*)(inbuf+section_header->sh_offset+j)) + (le2int((unsigned char*)(inbuf+section_header->sh_offset+j))>>16);
117 int2le(sum, outbuf);
118 outbuf += 2;
119 memset(outbuf, 0, 2);
120 outbuf += 2;
121 /* Data */
122 memcpy(outbuf, inbuf+section_header->sh_offset, section_header->sh_size);
123 outbuf += section_header->sh_size;
126 return (int)((intptr_t)outbuf - startaddr);
129 static int make_jrm_file(const unsigned char *inbuf, unsigned char *outbuf)
131 int length;
133 /* Clear the header area to zero */
134 memset(outbuf, 0, 0x18);
136 /* Header (EDOC) */
137 memcpy(outbuf, "EDOC", 4);
138 /* Total Size: temporarily set to 0 */
139 memset(&outbuf[0x4], 0, 4);
140 /* 4 bytes of zero */
141 memset(&outbuf[0x8], 0, 4);
143 length = elf_convert(inbuf, &outbuf[0xC]);
144 if(length < 0)
145 return -1;
146 /* Now set the actual Total Size */
147 int2le(4+length, &outbuf[0x4]);
149 return 0xC+length;
152 int zvm_encode(const char *iname, const char *oname, int device)
154 size_t len;
155 int length;
156 FILE *file;
157 unsigned char *outbuf;
158 unsigned char *buf;
160 file = fopen(iname, "rb");
161 if (!file) {
162 perror(iname);
163 return -1;
165 fseek(file, 0, SEEK_END);
166 length = ftell(file);
168 fseek(file, 0, SEEK_SET);
170 buf = (unsigned char*)malloc(length);
171 if ( !buf ) {
172 printf("Out of memory!\n");
173 return -1;
176 len = fread(buf, 1, length, file);
177 if(len < (size_t)length) {
178 perror(iname);
179 return -2;
181 fclose(file);
183 outbuf = (unsigned char*)malloc(length+0x300);
184 if ( !outbuf ) {
185 free(buf);
186 printf("Out of memory!\n");
187 return -1;
189 length = make_jrm_file(buf, outbuf);
190 free(buf);
191 if(length < 0)
193 free(outbuf);
194 printf("Error in making JRM file!\n");
195 return -1;
197 buf = (unsigned char*)malloc(length+0x200);
198 memset(buf, 0, length+0x200);
199 length = make_ciff_file(outbuf, length, buf, device);
200 free(outbuf);
202 file = fopen(oname, "wb");
203 if (!file) {
204 free(buf);
205 perror(oname);
206 return -3;
209 len = fwrite(buf, 1, length, file);
210 if(len < (size_t)length) {
211 free(buf);
212 perror(oname);
213 return -4;
216 free(buf);
218 fclose(file);
220 return 0;