forked from len0rd/rockbox
Add generation of .mi4 files - the generic PortalPlayer firmware format used by the iriver H10, Sansa E200 etc. Based on the documentation available at http://daniel.haxx.se/sansa/mi4.html and examination of files produced by mkmi4.sh
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10816 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
e379225754
commit
530f31dbe9
4 changed files with 229 additions and 2 deletions
|
@ -10,17 +10,18 @@ CFLAGS := -O -ansi -g
|
|||
LDFLAGS := -g
|
||||
|
||||
CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \
|
||||
generate_rocklatin mkboot ipod_fw codepages uclpack
|
||||
generate_rocklatin mkboot ipod_fw codepages uclpack mi4
|
||||
|
||||
all:
|
||||
@echo "Run make in your build directory!"
|
||||
|
||||
scramble: scramble.o iriver.o
|
||||
scramble: scramble.o iriver.o mi4.o
|
||||
descramble: descramble.o iriver.o
|
||||
|
||||
scramble.o: scramble.c iriver.h
|
||||
descramble.o: descramble.c iriver.h
|
||||
iriver.o: iriver.c iriver.h
|
||||
mi4.o: mi4.c mi4.h
|
||||
|
||||
sh2d: sh2d.c
|
||||
|
||||
|
|
188
tools/mi4.c
Normal file
188
tools/mi4.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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(0x000000ec, &outbuf[0x2e4]); /* magic */
|
||||
int2le(length+4, &outbuf[0x2e8]); /* length plus 0xaa55aa55 */
|
||||
|
||||
int2le(0xaa55aa55, &outbuf[0x200+length]); /* More Magic */
|
||||
|
||||
/* 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;
|
||||
}
|
25
tools/mi4.h
Normal file
25
tools/mi4.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _MI4_H
|
||||
#define _MI4_H
|
||||
|
||||
int mi4_encode(char *iname, char *oname, int version);
|
||||
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "iriver.h"
|
||||
#include "mi4.h"
|
||||
|
||||
int iaudio_encode(char *iname, char *oname, char *idstring);
|
||||
int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc);
|
||||
|
@ -82,6 +83,8 @@ void usage(void)
|
|||
"\t-ipod3g ipod firmware partition format (3rd Gen)\n"
|
||||
"\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
|
||||
"\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
|
||||
"\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
|
||||
"\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
|
||||
"\t-add=X Rockbox generic \"add-up\" checksum format\n"
|
||||
"\t (X values: h100, h120, h140, h300, ipco, nano, ipvd\n"
|
||||
"\t ip3g, ip4g, mini, x5, h10, h10_5gb)\n"
|
||||
|
@ -241,6 +244,16 @@ int main (int argc, char** argv)
|
|||
oname = argv[3];
|
||||
return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
|
||||
}
|
||||
else if(!strcmp(argv[1], "-mi4v2")) {
|
||||
iname = argv[2];
|
||||
oname = argv[3];
|
||||
return mi4_encode(iname, oname, 0x00010201);
|
||||
}
|
||||
else if(!strcmp(argv[1], "-mi4v3")) {
|
||||
iname = argv[2];
|
||||
oname = argv[3];
|
||||
return mi4_encode(iname, oname, 0x00010301);
|
||||
}
|
||||
|
||||
/* open file */
|
||||
file = fopen(iname,"rb");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue