diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/sbinfo/Makefile | 9 | ||||
-rw-r--r-- | utils/sbinfo/sbinfo.c | 257 |
2 files changed, 266 insertions, 0 deletions
diff --git a/utils/sbinfo/Makefile b/utils/sbinfo/Makefile new file mode 100644 index 0000000000..811249e924 --- /dev/null +++ b/utils/sbinfo/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | TGT = sbinfo | ||
2 | |||
3 | all: $(TGT) | ||
4 | |||
5 | $(TGT): sbinfo.c | ||
6 | $(CC) -ansi -o $(TGT) -W -Wall sbinfo.c | ||
7 | |||
8 | clean: | ||
9 | rm -fr $(TGT) | ||
diff --git a/utils/sbinfo/sbinfo.c b/utils/sbinfo/sbinfo.c new file mode 100644 index 0000000000..aa001d4023 --- /dev/null +++ b/utils/sbinfo/sbinfo.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Bertrik Sikken | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /* | ||
23 | * .sb file parser and chunk extractor | ||
24 | * | ||
25 | * Based on amsinfo, which is | ||
26 | * Copyright © 2008 Rafaël Carré <rafael.carre@gmail.com> | ||
27 | */ | ||
28 | |||
29 | #define _ISOC99_SOURCE /* snprintf() */ | ||
30 | #include <stdio.h> | ||
31 | #include <sys/types.h> | ||
32 | #include <sys/stat.h> | ||
33 | #include <fcntl.h> | ||
34 | #include <errno.h> | ||
35 | #include <unistd.h> | ||
36 | #include <stdlib.h> | ||
37 | #include <inttypes.h> | ||
38 | #include <string.h> | ||
39 | #include <ctype.h> | ||
40 | #include <time.h> | ||
41 | |||
42 | #if 1 /* ANSI colors */ | ||
43 | |||
44 | # define color(a) printf("%s",a) | ||
45 | char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' }; | ||
46 | |||
47 | char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' }; | ||
48 | char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' }; | ||
49 | char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' }; | ||
50 | char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' }; | ||
51 | char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; | ||
52 | |||
53 | #else | ||
54 | /* disable colors */ | ||
55 | # define color(a) | ||
56 | #endif | ||
57 | |||
58 | #define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) | ||
59 | #define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) | ||
60 | |||
61 | /* byte swapping */ | ||
62 | #define get32le(a) ((uint32_t) \ | ||
63 | ( buf[a+3] << 24 | buf[a+2] << 16 | buf[a+1] << 8 | buf[a] )) | ||
64 | #define get16le(a) ((uint16_t)( buf[a+1] << 8 | buf[a] )) | ||
65 | |||
66 | /* all blocks are sized as a multiple of 0x1ff */ | ||
67 | #define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff) | ||
68 | |||
69 | /* If you find a firmware that breaks the known format ^^ */ | ||
70 | #define assert(a) do { if(!(a)) { fprintf(stderr,"Assertion \"%s\" failed in %s() line %d!\n\nPlease send us your firmware!\n",#a,__func__,__LINE__); exit(1); } } while(0) | ||
71 | |||
72 | /* globals */ | ||
73 | |||
74 | size_t sz; /* file size */ | ||
75 | uint8_t *buf; /* file content */ | ||
76 | |||
77 | |||
78 | /* 1st block description */ | ||
79 | uint32_t idx,checksum,bs_multiplier,firmware_sz; | ||
80 | uint32_t unknown_4_1; uint16_t unknown_1, unknown_2; | ||
81 | uint32_t unknown_4_2,unknown_4_3; | ||
82 | |||
83 | static void *xmalloc(size_t s) /* malloc helper */ | ||
84 | { | ||
85 | void * r = malloc(s); | ||
86 | if(!r) bugp("malloc"); | ||
87 | return r; | ||
88 | } | ||
89 | |||
90 | static char getchr(int offset) | ||
91 | { | ||
92 | char c; | ||
93 | c = buf[offset]; | ||
94 | return isprint(c) ? c : '_'; | ||
95 | } | ||
96 | |||
97 | static void getstrle(char string[], int offset) | ||
98 | { | ||
99 | int i; | ||
100 | for (i = 0; i < 4; i++) { | ||
101 | string[i] = getchr(offset + 3 - i); | ||
102 | } | ||
103 | string[4] = 0; | ||
104 | } | ||
105 | |||
106 | static void getstrbe(char string[], int offset) | ||
107 | { | ||
108 | int i; | ||
109 | for (i = 0; i < 4; i++) { | ||
110 | string[i] = getchr(offset + i); | ||
111 | } | ||
112 | string[4] = 0; | ||
113 | } | ||
114 | |||
115 | static void printhex(int offset, int len) | ||
116 | { | ||
117 | int i; | ||
118 | |||
119 | for (i = 0; i < len; i++) { | ||
120 | printf("%02X ", buf[offset + i]); | ||
121 | } | ||
122 | printf("\n"); | ||
123 | } | ||
124 | |||
125 | /* verify the firmware header */ | ||
126 | static void check(unsigned long filesize) | ||
127 | { | ||
128 | /* check STMP marker */ | ||
129 | char stmp[5]; | ||
130 | getstrbe(stmp, 0x14); | ||
131 | assert(strcmp(stmp, "STMP") == 0); | ||
132 | color(GREEN); | ||
133 | |||
134 | /* get total size */ | ||
135 | unsigned long totalsize = 16 * get32le(0x1C); | ||
136 | color(GREEN); | ||
137 | assert(filesize == totalsize); | ||
138 | } | ||
139 | |||
140 | static void extract(unsigned long filesize) | ||
141 | { | ||
142 | /* Basic header info */ | ||
143 | color(BLUE); | ||
144 | printf("Basic info:\n"); | ||
145 | color(GREEN); | ||
146 | printf("\tHeader SHA-1: "); | ||
147 | printhex(0, 20); | ||
148 | printf("\tFlags: "); | ||
149 | printhex(0x18, 4); | ||
150 | printf("\tTotal file size : %ld\n", filesize); | ||
151 | |||
152 | /* Sizes and offsets */ | ||
153 | color(BLUE); | ||
154 | printf("Sizes and offsets:\n"); | ||
155 | color(GREEN); | ||
156 | int num_enc = get16le(0x28); | ||
157 | printf("\t# of encryption info = %d\n", num_enc); | ||
158 | int num_chunks = get16le(0x2E); | ||
159 | printf("\t# of chunk headers = %d\n", num_chunks); | ||
160 | |||
161 | /* Versions */ | ||
162 | color(BLUE); | ||
163 | printf("Versions\n"); | ||
164 | color(GREEN); | ||
165 | |||
166 | printf("\tRandom 1: "); | ||
167 | printhex(0x32, 6); | ||
168 | printf("\tRandom 2: "); | ||
169 | printhex(0x5A, 6); | ||
170 | |||
171 | uint64_t micros_l = get32le(0x38); | ||
172 | uint64_t micros_h = get32le(0x3c); | ||
173 | uint64_t micros = ((uint64_t)micros_h << 32) | micros_l; | ||
174 | time_t seconds = (micros / (uint64_t)1000000L); | ||
175 | seconds += 946684800; /* 2000/1/1 0:00:00 */ | ||
176 | struct tm *time = gmtime(&seconds); | ||
177 | color(GREEN); | ||
178 | printf("\tCreation date/time = %s", asctime(time)); | ||
179 | |||
180 | int p_maj = get32le(0x40); | ||
181 | int p_min = get32le(0x44); | ||
182 | int p_sub = get32le(0x48); | ||
183 | int c_maj = get32le(0x4C); | ||
184 | int c_min = get32le(0x50); | ||
185 | int c_sub = get32le(0x54); | ||
186 | color(GREEN); | ||
187 | printf("\tProduct version = %X.%X.%X\n", p_maj, p_min, p_sub); | ||
188 | printf("\tComponent version = %X.%X.%X\n", c_maj, c_min, c_sub); | ||
189 | |||
190 | /* chunks */ | ||
191 | color(BLUE); | ||
192 | printf("Chunks\n"); | ||
193 | |||
194 | int i; | ||
195 | for (i = 0; i < num_chunks; i++) { | ||
196 | uint32_t ofs = 0x60 + (i * 16); | ||
197 | |||
198 | char name[5]; | ||
199 | getstrle(name, ofs + 0); | ||
200 | int pos = 16 * get32le(ofs + 4); | ||
201 | int size = 16 * get32le(ofs + 8); | ||
202 | int flags = get32le(ofs + 12); | ||
203 | |||
204 | color(GREEN); | ||
205 | printf("\tChunk '%s'\n", name); | ||
206 | printf("\t\tpos = %8x - %8x\n", pos, pos+size); | ||
207 | printf("\t\tlen = %8x\n", size); | ||
208 | printf("\t\tflags = %8x\n", flags); | ||
209 | |||
210 | /* save it */ | ||
211 | char filename[16]; | ||
212 | strcpy(filename, name); | ||
213 | strcat(filename, ".bin"); | ||
214 | FILE *file = fopen(filename, "wb"); | ||
215 | if (file != NULL) { | ||
216 | fwrite(buf + pos, size, 1, file); | ||
217 | fclose(file); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | /* final signature */ | ||
222 | color(BLUE); | ||
223 | printf("Final signature:\n\t"); | ||
224 | color(GREEN); | ||
225 | printhex(filesize - 32, 16); | ||
226 | printf("\t"); | ||
227 | printhex(filesize - 16, 16); | ||
228 | } | ||
229 | |||
230 | int main(int argc, const char **argv) | ||
231 | { | ||
232 | int fd; | ||
233 | struct stat st; | ||
234 | if(argc != 2) | ||
235 | bug("Usage: %s <firmware>\n",*argv); | ||
236 | |||
237 | if( (fd = open(argv[1],O_RDONLY)) == -1 ) | ||
238 | bugp("opening firmware failed"); | ||
239 | |||
240 | if(fstat(fd,&st) == -1) | ||
241 | bugp("firmware stat() failed"); | ||
242 | sz = st.st_size; | ||
243 | |||
244 | buf=xmalloc(sz); | ||
245 | if(read(fd,buf,sz)!=(ssize_t)sz) /* load the whole file into memory */ | ||
246 | bugp("reading firmware"); | ||
247 | |||
248 | close(fd); | ||
249 | |||
250 | check(st.st_size); /* verify header and checksums */ | ||
251 | extract(st.st_size); /* split in blocks */ | ||
252 | |||
253 | color(OFF); | ||
254 | |||
255 | free(buf); | ||
256 | return 0; | ||
257 | } | ||