summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/sbinfo/Makefile9
-rw-r--r--utils/sbinfo/sbinfo.c257
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 @@
1TGT = sbinfo
2
3all: $(TGT)
4
5$(TGT): sbinfo.c
6 $(CC) -ansi -o $(TGT) -W -Wall sbinfo.c
7
8clean:
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)
45char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' };
46
47char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' };
48char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' };
49char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' };
50char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' };
51char 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
74size_t sz; /* file size */
75uint8_t *buf; /* file content */
76
77
78/* 1st block description */
79uint32_t idx,checksum,bs_multiplier,firmware_sz;
80uint32_t unknown_4_1; uint16_t unknown_1, unknown_2;
81uint32_t unknown_4_2,unknown_4_3;
82
83static void *xmalloc(size_t s) /* malloc helper */
84{
85 void * r = malloc(s);
86 if(!r) bugp("malloc");
87 return r;
88}
89
90static char getchr(int offset)
91{
92 char c;
93 c = buf[offset];
94 return isprint(c) ? c : '_';
95}
96
97static 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
106static 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
115static 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 */
126static 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
140static 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
230int 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}