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 <memory.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;
}
|