summaryrefslogtreecommitdiffstats
path: root/flash/extract/extract.c
blob: 2389f9290e777e92bcfda62393507dced0249e64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2003 by Jörg Hohensohn 
 * 
 * Tool to extract the scrambled image out of an Archos flash ROM dump
 *
 * 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.
 *
 * 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 <inttypes.h>

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long

#define IMAGE_HEADER 0x6000 // a 32 byte header in front of the software image
#define IMAGE_START  0x6020	// software image position in Flash


// place a 32 bit value into memory, big endian
void Write32(UINT8* pByte, UINT32 value)
{
	pByte[0] = (UINT8)(value >> 24);	
	pByte[1] = (UINT8)(value >> 16);	
	pByte[2] = (UINT8)(value >> 8);	
	pByte[3] = (UINT8)(value);	
}


// read a 32 bit value from memory, big endian
UINT32 Read32(UINT8* pByte)
{
	UINT32 value = 0;

	value |= (UINT32)pByte[0] << 24;
	value |= (UINT32)pByte[1] << 16;
	value |= (UINT32)pByte[2] << 8;
	value |= (UINT32)pByte[3];

	return value;
}


// entry point
int main(int argc, char* argv[])
{
	FILE* pInFile;
	FILE* pOutFile;
	UINT8 aHeader[6];
	UINT8 aImage[256*1024];
	UINT32 i;
	UINT32 uiSize, uiStart;
	UINT16 usChecksum = 0;
	
	if (argc < 2)
	{
		printf("Extract the software image out of an original Archos Flash ROM dump.\n");
		printf("Result is a scrambled file, use the descramble tool to get the binary,\n");
		printf(" always without the -fm option, even if processing an FM software.\n\n");
		printf("Usage: extract <flash dump file> <output file>\n");
		printf("Example: extract internal_rom_2000000-203FFFF.bin archos.ajz\n");
		exit(0);
	}
	
	pInFile = fopen(argv[1], "rb");
	if (pInFile == NULL)
	{
		printf("Error opening input file %s\n", argv[1]);
		exit(1);
	}

	if (fread(aImage, 1, sizeof(aImage), pInFile) != sizeof(aImage))
	{
		printf("Error reading input file %s, must be 256kB in size.\n", argv[1]);
		fclose(pInFile);
		exit(2);
	}
	fclose(pInFile);

	// find out about the type
	uiStart = Read32(aImage + 8);
	uiSize = Read32(aImage + 12); // booted ROM image
	if (uiStart == 0x02000100 && uiSize > 20000)
	{	// Player has no loader, starts directly with the image
		uiStart = 0x0100;
	}
	else
	{	// Recorder / FM / V2 Recorder
		uiStart = IMAGE_START;
		uiSize = Read32(aImage + IMAGE_HEADER + 4); // size record of header
	}

	// sanity check
	if (uiSize > sizeof(aImage) - uiStart || uiSize < 40000)
	{	
		printf("Error: Impossible image size %d bytes.\n", uiSize);
		exit(3);
	}

	// generate checksum
	for (i=0; i<uiSize; i++)
	{
		UINT8 byte;
		byte = aImage[uiStart + i];
		byte = ~((byte >> 1) | ((byte << 7) & 0x80)); /* poor man's ROR */
		usChecksum += byte;
	}

	// make header
	Write32(aHeader + 2, usChecksum); // checksum in 5th and 6th byte
	Write32(aHeader, uiSize); // size in first 4 bytes

	pOutFile = fopen(argv[2], "wb");
	if (pOutFile == NULL)
	{
		printf("Error opening output file %s\n", argv[2]);
		exit(4);
	}

	if (fwrite(aHeader, 1, sizeof(aHeader), pOutFile) != sizeof(aHeader)
	 || fwrite(aImage + uiStart, 1, uiSize, pOutFile) != uiSize)
	{
		printf("Write error\n");
		fclose(pOutFile);
		exit(5);
	}

	fclose(pOutFile);

	return 0;
}