Colour targets: Revert an optimisation from almost 18 months ago that actually turned...
[Rockbox.git] / tools / creative.c
blob2d60fdd94c64643aa6107da65348cbdeedf093cf
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 #include <elf.h>
28 #include "creative.h"
29 #include "hmac-sha1.h"
31 static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
32 static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
33 static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
34 static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
36 static const struct device_info devices[] =
38 /* Creative Zen Vision:M */
39 {"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},
40 /* Creative Zen Vision:M Go! */
41 {"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},
42 /* Creative Zen Vision © TL */
43 /* The "©" should be ANSI encoded or the device won't accept the firmware package. */
44 {"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},
45 /* Creative ZEN V */
46 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4},
47 /* Creative ZEN */
48 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N", 48, null_key_v3}
52 Create a Zen Vision:M FRESCUE structure file
54 extern void int2le(unsigned int val, unsigned char* addr);
55 extern unsigned int le2int(unsigned char* buf);
58 static int make_ciff_file(const unsigned char *inbuf, unsigned int length,
59 unsigned char *outbuf, int device)
61 unsigned char key[20];
62 memcpy(outbuf, "FFIC", 4);
63 int2le(length+90, &outbuf[4]);
64 memcpy(&outbuf[8], "FNIC", 4);
65 int2le(96, &outbuf[0xC]);
66 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
67 memset(&outbuf[0x10+devices[device].cinf_size], 0,
68 96 - devices[device].cinf_size);
69 memcpy(&outbuf[0x70], "ATAD", 4);
70 int2le(length+32, &outbuf[0x74]);
71 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m",
72 25); /*Unicode encoded*/
73 memset(&outbuf[0x78+25], 0, 32);
74 memcpy(&outbuf[0x98], inbuf, length);
75 memcpy(&outbuf[0x98+length], "LLUN", 4);
76 int2le(20, &outbuf[0x98+length+4]);
77 /* Do checksum */
78 hmac_sha1((unsigned char *)devices[device].null, strlen(devices[device].null),
79 outbuf, 0x98+length, key);
80 memcpy(&outbuf[0x98+length+8], key, 20);
81 return length+0x90+0x1C+8;
84 static int elf_convert(const unsigned char *inbuf, unsigned char *outbuf)
86 Elf32_Ehdr *main_header;
87 Elf32_Shdr *section_header;
88 unsigned int i, j, sum;
89 intptr_t startaddr;
91 main_header = (Elf32_Ehdr*)inbuf;
92 if( !( main_header->e_ident[0] == ELFMAG0 && main_header->e_ident[1] == ELFMAG1
93 && main_header->e_ident[2] == ELFMAG2 && main_header->e_ident[3] == ELFMAG3 ) )
95 printf("Invalid ELF header!\n");
96 return -1;
99 startaddr = (intptr_t)outbuf;
101 for(i = 0; i < main_header->e_shnum; i++)
103 section_header = (Elf32_Shdr*)(inbuf+main_header->e_shoff+i*sizeof(Elf32_Shdr));
105 if( (section_header->sh_flags & SHF_WRITE || section_header->sh_flags & SHF_ALLOC
106 || section_header->sh_flags & SHF_EXECINSTR) && section_header->sh_size > 0
107 && section_header->sh_type != SHT_NOBITS )
109 /* Address */
110 int2le(section_header->sh_addr, outbuf);
111 outbuf += 4;
112 /* Size */
113 int2le(section_header->sh_size, outbuf);
114 outbuf += 4;
115 /* Checksum */
116 sum = 0;
117 for(j=0; j<section_header->sh_size; j+= 4)
118 sum += le2int((unsigned char*)(inbuf+section_header->sh_offset+j)) + (le2int((unsigned char*)(inbuf+section_header->sh_offset+j))>>16);
119 int2le(sum, outbuf);
120 outbuf += 2;
121 memset(outbuf, 0, 2);
122 outbuf += 2;
123 /* Data */
124 memcpy(outbuf, inbuf+section_header->sh_offset, section_header->sh_size);
125 outbuf += section_header->sh_size;
128 return (int)((intptr_t)outbuf - startaddr);
131 static int make_jrm_file(const unsigned char *inbuf, unsigned char *outbuf)
133 int length;
135 /* Clear the header area to zero */
136 memset(outbuf, 0, 0x18);
138 /* Header (EDOC) */
139 memcpy(outbuf, "EDOC", 4);
140 /* Total Size: temporarily set to 0 */
141 memset(&outbuf[0x4], 0, 4);
142 /* 4 bytes of zero */
143 memset(&outbuf[0x8], 0, 4);
145 length = elf_convert(inbuf, &outbuf[0xC]);
146 if(length < 0)
147 return -1;
148 /* Now set the actual Total Size */
149 int2le(4+length, &outbuf[0x4]);
151 return 0xC+length;
154 int zvm_encode(const char *iname, const char *oname, int device)
156 size_t len;
157 int length;
158 FILE *file;
159 unsigned char *outbuf;
160 unsigned char *buf;
162 file = fopen(iname, "rb");
163 if (!file) {
164 perror(iname);
165 return -1;
167 fseek(file, 0, SEEK_END);
168 length = ftell(file);
170 fseek(file, 0, SEEK_SET);
172 buf = (unsigned char*)malloc(length);
173 if ( !buf ) {
174 printf("Out of memory!\n");
175 return -1;
178 len = fread(buf, 1, length, file);
179 if(len < (size_t)length) {
180 perror(iname);
181 return -2;
183 fclose(file);
185 outbuf = (unsigned char*)malloc(length+0x300);
186 if ( !outbuf ) {
187 free(buf);
188 printf("Out of memory!\n");
189 return -1;
191 length = make_jrm_file(buf, outbuf);
192 free(buf);
193 if(length < 0)
195 free(outbuf);
196 printf("Error in making JRM file!\n");
197 return -1;
199 buf = (unsigned char*)malloc(length+0x200);
200 memset(buf, 0, length+0x200);
201 length = make_ciff_file(outbuf, length, buf, device);
202 free(outbuf);
204 file = fopen(oname, "wb");
205 if (!file) {
206 free(buf);
207 perror(oname);
208 return -3;
211 len = fwrite(buf, 1, length, file);
212 if(len < (size_t)length) {
213 free(buf);
214 perror(oname);
215 return -4;
218 free(buf);
220 fclose(file);
222 return 0;