/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2006 Dave Chapman * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include /* * CRC32 implementation taken from: * * efone - Distributed internet phone system. * * (c) 1999,2000 Krzysztof Dabrowski * (c) 1999,2000 ElysiuM deeZine * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */ /* based on implementation by Finn Yannick Jacobs */ #include #include /* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab(). * so make sure, you call it before using the other * functions! */ static unsigned int crc_tab[256]; /* chksum_crc() -- to a given block, this one calculates the * crc32-checksum until the length is * reached. the crc32-checksum will be * the result. */ static unsigned int chksum_crc32 (unsigned char *block, unsigned int length) { register unsigned long crc; unsigned long i; crc = 0; for (i = 0; i < length; i++) { crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; } return (crc); } /* chksum_crc32gentab() -- to a global crc_tab[256], this one will * calculate the crcTable for crc32-checksums. * it is generated to the polynom [..] */ static void chksum_crc32gentab (void) { unsigned long crc, poly; int i, j; poly = 0xEDB88320L; for (i = 0; i < 256; i++) { crc = i; for (j = 8; j > 0; j--) { if (crc & 1) { crc = (crc >> 1) ^ poly; } else { crc >>= 1; } } crc_tab[i] = crc; } } static void int2le(unsigned int val, unsigned char* addr) { addr[0] = val & 0xFF; addr[1] = (val >> 8) & 0xff; addr[2] = (val >> 16) & 0xff; addr[3] = (val >> 24) & 0xff; } int mi4_encode(char *iname, char *oname, int version, int magic, char *model, char *type) { size_t len; int length; int mi4length; FILE *file; unsigned int crc = 0; unsigned char *outbuf; file = fopen(iname, "rb"); if (!file) { perror(iname); return -1; } fseek(file,0,SEEK_END); length = ftell(file); fseek(file,0,SEEK_SET); /* Add 4 bytes to length (for magic), the 0x200 byte header and then round to an even 0x400 bytes */ mi4length = (length+4+0x200+0x3ff)&~0x3ff; outbuf = malloc(mi4length); if ( !outbuf ) { printf("out of memory!\n"); return -1; } /* Clear the buffer to zero */ memset(outbuf, 0, mi4length); len = fread(outbuf+0x200, 1, length, file); if(len < length) { perror(iname); return -2; } fclose(file); /* We need to write some data into the actual image - before calculating the CRC. */ int2le(0x00000100, &outbuf[0x2e0]); /* magic */ int2le(magic, &outbuf[0x2e4]); /* magic */ int2le(length+4, &outbuf[0x2e8]); /* length plus 0xaa55aa55 */ int2le(0xaa55aa55, &outbuf[0x200+length]); /* More Magic */ strncpy((char *)outbuf+0x1f8, type, 4); /* type of binary - RBBL, RBOS, ... */ strncpy((char *)outbuf+0x1fc, model, 4); /* type of binary - RBBL, RBOS, ... */ /* Calculate CRC32 checksum */ chksum_crc32gentab (); crc = chksum_crc32 (outbuf+28,mi4length-28); strncpy((char *)outbuf, "PPOS", 4); /* Magic */ int2le(version, &outbuf[0x04]); /* .mi4 version */ int2le(length+4, &outbuf[0x08]); /* Length of firmware plus magic */ int2le(crc, &outbuf[0x0c]); /* CRC32 of mi4 file */ int2le(0x00000002, &outbuf[0x10]); /* Encryption type: 2 = TEA */ int2le(mi4length, &outbuf[0x14]); /* Total .mi4 length */ int2le(mi4length-0x200, &outbuf[0x18]); /* Length of plaintext part */ /* v3 files require a dummy DSA signature */ if (version == 0x00010301) { outbuf[0x2f]=0x01; } file = fopen(oname, "wb"); if (!file) { perror(oname); return -3; } len = fwrite(outbuf, 1, mi4length, file); if(len < length) { perror(oname); return -4; } fclose(file); fprintf(stderr, "File encoded successfully\n" ); return 0; }