diff options
Diffstat (limited to 'utils/AMS')
-rw-r--r-- | utils/AMS/hacking/extract_fw.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/utils/AMS/hacking/extract_fw.c b/utils/AMS/hacking/extract_fw.c new file mode 100644 index 0000000000..bee6a234c4 --- /dev/null +++ b/utils/AMS/hacking/extract_fw.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | |||
3 | extract_fw.c - extract the main firmware image from a Sansa V2 (AMS) firmware | ||
4 | file | ||
5 | |||
6 | Copyright (C) Dave Chapman 2008 | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | ||
21 | |||
22 | */ | ||
23 | |||
24 | |||
25 | #include <stdio.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <stdint.h> | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/stat.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <unistd.h> | ||
32 | #include <string.h> | ||
33 | |||
34 | |||
35 | /* Win32 compatibility */ | ||
36 | #ifndef O_BINARY | ||
37 | #define O_BINARY 0 | ||
38 | #endif | ||
39 | |||
40 | |||
41 | static off_t filesize(int fd) { | ||
42 | struct stat buf; | ||
43 | |||
44 | if (fstat(fd,&buf) < 0) { | ||
45 | perror("[ERR] Checking filesize of input file"); | ||
46 | return -1; | ||
47 | } else { | ||
48 | return(buf.st_size); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | static uint32_t get_uint32le(unsigned char* p) | ||
53 | { | ||
54 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
55 | } | ||
56 | |||
57 | void usage(void) | ||
58 | { | ||
59 | printf("Usage: extract_fw <firmware file> <output file>\n"); | ||
60 | |||
61 | exit(1); | ||
62 | } | ||
63 | |||
64 | int main(int argc, char* argv[]) | ||
65 | { | ||
66 | char *infile, *outfile; | ||
67 | int fdin, fdout; | ||
68 | off_t len; | ||
69 | uint32_t n; | ||
70 | unsigned char* buf; | ||
71 | uint32_t firmware_size; | ||
72 | |||
73 | if(argc != 3) { | ||
74 | usage(); | ||
75 | } | ||
76 | |||
77 | infile = argv[1]; | ||
78 | outfile = argv[2]; | ||
79 | |||
80 | /* Open the firmware file */ | ||
81 | fdin = open(infile,O_RDONLY|O_BINARY); | ||
82 | |||
83 | if (fdin < 0) { | ||
84 | fprintf(stderr,"[ERR] Could not open %s for reading\n",infile); | ||
85 | return 1; | ||
86 | } | ||
87 | |||
88 | if ((len = filesize(fdin)) < 0) | ||
89 | return 1; | ||
90 | |||
91 | /* We will need no more memory than the total size plus the bootloader size | ||
92 | padded to a boundary */ | ||
93 | if ((buf = malloc(len)) == NULL) { | ||
94 | fprintf(stderr,"[ERR] Could not allocate buffer for input file (%d bytes)\n",(int)len); | ||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | n = read(fdin, buf, len); | ||
99 | |||
100 | if (n != (uint32_t)len) { | ||
101 | fprintf(stderr,"[ERR] Could not read firmware file\n"); | ||
102 | return 1; | ||
103 | } | ||
104 | |||
105 | close(fdin); | ||
106 | |||
107 | /* Get the firmware size */ | ||
108 | if (get_uint32le(&buf[0x04])==0x0000f000) | ||
109 | firmware_size = get_uint32le(&buf[0x10]); /* v2 format */ | ||
110 | else | ||
111 | firmware_size = get_uint32le(&buf[0x0c]); /* v1 format */ | ||
112 | |||
113 | fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); | ||
114 | |||
115 | if (fdout < 0) { | ||
116 | fprintf(stderr,"[ERR] Could not open %s for writing\n",outfile); | ||
117 | return 1; | ||
118 | } | ||
119 | |||
120 | n = write(fdout, buf + 0x400, firmware_size); | ||
121 | |||
122 | if (n != (uint32_t)firmware_size) { | ||
123 | fprintf(stderr,"[ERR] Could not write firmware block\n"); | ||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | /* Clean up */ | ||
128 | close(fdout); | ||
129 | free(buf); | ||
130 | |||
131 | return 0; | ||
132 | } | ||