A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 338 lines 12 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2008 by Maurus Cuelenaere 11 * 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. 16 * 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 <stdbool.h> 24#include <stdlib.h> 25#include <string.h> 26#include "creative.h" 27#include "hmac-sha1.h" 28/* 29 --------------------------------------------------------------------------- 30 Shamelessly taken from elf.h (for compatibility reasons included) 31 --------------------------------------------------------------------------- 32 33 This file defines standard ELF types, structures, and macros. 34 Copyright (C) 1995-2003,2004,2005,2006,2007 Free Software Foundation, Inc. 35 This file is part of the GNU C Library. 36 37 The GNU C Library is free software; you can redistribute it and/or 38 modify it under the terms of the GNU Lesser General Public 39 License as published by the Free Software Foundation; either 40 version 2.1 of the License, or (at your option) any later version. 41 42 The GNU C Library is distributed in the hope that it will be useful, 43 but WITHOUT ANY WARRANTY; without even the implied warranty of 44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 45 Lesser General Public License for more details. 46 47 You should have received a copy of the GNU Lesser General Public 48 License along with the GNU C Library; if not, write to the Free 49 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 50 02111-1307 USA. 51*/ 52 53#include <stdint.h> 54 55/* Type for a 16-bit quantity. */ 56typedef uint16_t Elf32_Half; 57 58/* Types for signed and unsigned 32-bit quantities. */ 59typedef uint32_t Elf32_Word; 60typedef int32_t Elf32_Sword; 61 62/* Types for signed and unsigned 64-bit quantities. */ 63typedef uint64_t Elf32_Xword; 64typedef int64_t Elf32_Sxword; 65 66/* Type of addresses. */ 67typedef uint32_t Elf32_Addr; 68 69/* Type of file offsets. */ 70typedef uint32_t Elf32_Off; 71 72/* Type for section indices, which are 16-bit quantities. */ 73typedef uint16_t Elf32_Section; 74 75#define EI_NIDENT (16) 76 77typedef struct 78{ 79 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 80 Elf32_Half e_type; /* Object file type */ 81 Elf32_Half e_machine; /* Architecture */ 82 Elf32_Word e_version; /* Object file version */ 83 Elf32_Addr e_entry; /* Entry point virtual address */ 84 Elf32_Off e_phoff; /* Program header table file offset */ 85 Elf32_Off e_shoff; /* Section header table file offset */ 86 Elf32_Word e_flags; /* Processor-specific flags */ 87 Elf32_Half e_ehsize; /* ELF header size in bytes */ 88 Elf32_Half e_phentsize; /* Program header table entry size */ 89 Elf32_Half e_phnum; /* Program header table entry count */ 90 Elf32_Half e_shentsize; /* Section header table entry size */ 91 Elf32_Half e_shnum; /* Section header table entry count */ 92 Elf32_Half e_shstrndx; /* Section header string table index */ 93} Elf32_Ehdr; 94 95typedef struct 96{ 97 Elf32_Word sh_name; /* Section name (string tbl index) */ 98 Elf32_Word sh_type; /* Section type */ 99 Elf32_Word sh_flags; /* Section flags */ 100 Elf32_Addr sh_addr; /* Section virtual addr at execution */ 101 Elf32_Off sh_offset; /* Section file offset */ 102 Elf32_Word sh_size; /* Section size in bytes */ 103 Elf32_Word sh_link; /* Link to another section */ 104 Elf32_Word sh_info; /* Additional section information */ 105 Elf32_Word sh_addralign; /* Section alignment */ 106 Elf32_Word sh_entsize; /* Entry size if section holds table */ 107} Elf32_Shdr; 108 109#define ELFMAG0 0x7f /* Magic number byte 0 */ 110#define ELFMAG1 'E' /* Magic number byte 1 */ 111#define ELFMAG2 'L' /* Magic number byte 2 */ 112#define ELFMAG3 'F' /* Magic number byte 3 */ 113 114#define SHF_WRITE (1 << 0) /* Writable */ 115#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ 116#define SHF_EXECINSTR (1 << 2) /* Executable */ 117 118#define SHT_NOBITS 8 /* Program space with no data (bss) */ 119 120/* 121 --------------------------------------------------------------------------- 122 End of elf.h 123 --------------------------------------------------------------------------- 124*/ 125 126static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP."; 127static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP."; 128static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP."; 129 130static const struct device_info devices[] = 131{ 132 /* Creative Zen Vision:M */ 133 {"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}, 134 /* Creative Zen Vision:M Go! */ 135 {"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}, 136 /* Creative Zen Vision © TL */ 137 /* The "©" should be ANSI encoded or the device won't accept the firmware package. */ 138 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0 \0\xA9\0T\0L", 46, null_key_v2}, 139 /* Creative ZEN V */ 140 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4}, 141 /* Creative ZEN */ 142 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N", 48, null_key_v3}, 143 /* Creative ZEN X-Fi */ 144 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0X\0-\0F\0i\0", 34, null_key_v4}, 145 /* Creative ZEN Mozaic */ 146 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0M\0o\0z\0a\0i\0c\0", 38, null_key_v4} 147}; 148 149/* 150Create a Zen Vision:M FRESCUE structure file 151*/ 152extern void int2le(unsigned int val, unsigned char* addr); 153extern unsigned int le2int(unsigned char* buf); 154 155 156static int make_ciff_file(const unsigned char *inbuf, unsigned int length, 157 unsigned char *outbuf, int device) 158{ 159 unsigned char key[20]; 160 memcpy(outbuf, "FFIC", 4); 161 int2le(length+90, &outbuf[4]); 162 memcpy(&outbuf[8], "FNIC", 4); 163 int2le(96, &outbuf[0xC]); 164 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size); 165 memset(&outbuf[0x10+devices[device].cinf_size], 0, 166 96 - devices[device].cinf_size); 167 memcpy(&outbuf[0x70], "ATAD", 4); 168 int2le(length+32, &outbuf[0x74]); 169 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m", 170 25); /*Unicode encoded*/ 171 memset(&outbuf[0x78+25], 0, 32); 172 memcpy(&outbuf[0x98], inbuf, length); 173 memcpy(&outbuf[0x98+length], "LLUN", 4); 174 int2le(20, &outbuf[0x98+length+4]); 175 /* Do checksum */ 176 hmac_sha1((unsigned char *)devices[device].null, strlen(devices[device].null), 177 outbuf, 0x98+length, key); 178 memcpy(&outbuf[0x98+length+8], key, 20); 179 return length+0x90+0x1C+8; 180} 181 182static int elf_convert(const unsigned char *inbuf, unsigned char *outbuf) 183{ 184 Elf32_Ehdr *main_header; 185 Elf32_Shdr *section_header; 186 unsigned int i, j, sum; 187 intptr_t startaddr; 188 189 main_header = (Elf32_Ehdr*)inbuf; 190 if( !( main_header->e_ident[0] == ELFMAG0 && main_header->e_ident[1] == ELFMAG1 191 && main_header->e_ident[2] == ELFMAG2 && main_header->e_ident[3] == ELFMAG3 ) ) 192 { 193 printf("Invalid ELF header!\n"); 194 return -1; 195 } 196 197 startaddr = (intptr_t)outbuf; 198 199 for(i = 0; i < main_header->e_shnum; i++) 200 { 201 section_header = (Elf32_Shdr*)(inbuf+main_header->e_shoff+i*sizeof(Elf32_Shdr)); 202 203 if( (section_header->sh_flags & SHF_WRITE || section_header->sh_flags & SHF_ALLOC 204 || section_header->sh_flags & SHF_EXECINSTR) && section_header->sh_size > 0 205 && section_header->sh_type != SHT_NOBITS ) 206 { 207 /* Address */ 208 int2le(section_header->sh_addr, outbuf); 209 outbuf += 4; 210 /* Size */ 211 int2le(section_header->sh_size, outbuf); 212 outbuf += 4; 213 /* Checksum */ 214 sum = 0; 215 for(j=0; j<section_header->sh_size; j+= 4) 216 sum += le2int((unsigned char*)(inbuf+section_header->sh_offset+j)) + (le2int((unsigned char*)(inbuf+section_header->sh_offset+j))>>16); 217 int2le(sum, outbuf); 218 outbuf += 2; 219 memset(outbuf, 0, 2); 220 outbuf += 2; 221 /* Data */ 222 memcpy(outbuf, inbuf+section_header->sh_offset, section_header->sh_size); 223 outbuf += section_header->sh_size; 224 } 225 } 226 return (int)((intptr_t)outbuf - startaddr); 227} 228 229static int make_jrm_file(const unsigned char *inbuf, unsigned char *outbuf) 230{ 231 int length; 232 233 /* Clear the header area to zero */ 234 memset(outbuf, 0, 0x18); 235 236 /* Header (EDOC) */ 237 memcpy(outbuf, "EDOC", 4); 238 /* Total Size: temporarily set to 0 */ 239 memset(&outbuf[0x4], 0, 4); 240 /* 4 bytes of zero */ 241 memset(&outbuf[0x8], 0, 4); 242 243 length = elf_convert(inbuf, &outbuf[0xC]); 244 if(length < 0) 245 return -1; 246 /* Now set the actual Total Size */ 247 int2le(4+length, &outbuf[0x4]); 248 249 return 0xC+length; 250} 251 252int zvm_encode(const char *iname, const char *oname, int device, bool enable_ciff) 253{ 254 size_t len; 255 int length; 256 FILE *file; 257 unsigned char *outbuf; 258 unsigned char *buf; 259 260 file = fopen(iname, "rb"); 261 if (!file) 262 { 263 perror(iname); 264 return -1; 265 } 266 fseek(file, 0, SEEK_END); 267 length = ftell(file); 268 269 fseek(file, 0, SEEK_SET); 270 271 buf = (unsigned char*)malloc(length); 272 if ( !buf ) 273 { 274 printf("Out of memory!\n"); 275 return -1; 276 } 277 278 len = fread(buf, 1, length, file); 279 if(len < (size_t)length) 280 { 281 perror(iname); 282 return -2; 283 } 284 fclose(file); 285 286 outbuf = (unsigned char*)malloc(length+0x300); 287 if ( !outbuf ) 288 { 289 free(buf); 290 printf("Out of memory!\n"); 291 return -1; 292 } 293 length = make_jrm_file(buf, outbuf); 294 free(buf); 295 if(length < 0) 296 { 297 free(outbuf); 298 printf("Error in making JRM file!\n"); 299 return -1; 300 } 301 if(enable_ciff) 302 { 303 buf = (unsigned char*)malloc(length+0x200); 304 if ( !buf ) 305 { 306 free(outbuf); 307 printf("Out of memory!\n"); 308 return -1; 309 } 310 memset(buf, 0, length+0x200); 311 length = make_ciff_file(outbuf, length, buf, device); 312 free(outbuf); 313 } 314 else 315 buf = outbuf; 316 317 file = fopen(oname, "wb"); 318 if (!file) 319 { 320 free(buf); 321 perror(oname); 322 return -3; 323 } 324 325 len = fwrite(buf, 1, length, file); 326 if(len < (size_t)length) 327 { 328 free(buf); 329 perror(oname); 330 return -4; 331 } 332 333 free(buf); 334 335 fclose(file); 336 337 return 0; 338}