summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-11-29 17:27:34 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2012-11-29 17:30:54 +0100
commitee36a396cd1619585a83803630db2d79b6cbefbd (patch)
treed24e9737433147ef3e57f00f8734f0e54123b810
parent0ee512ca04e52b62550bd06532ffa67bdeab3d04 (diff)
downloadrockbox-ee36a396cd1619585a83803630db2d79b6cbefbd.tar.gz
rockbox-ee36a396cd1619585a83803630db2d79b6cbefbd.zip
imxtools: introduce rsrctool to manipulate rsrc sections
This tool is very preliminary but could be use for whatever purpose since the format of the rsrc sections is now known. By the way it appears that this format is the same as the one use by the stmp36xx for its resources. Change-Id: Idd7057f5cdce5af9726904169bb100c8bacb0981
-rw-r--r--utils/imxtools/sbtools/Makefile5
-rw-r--r--utils/imxtools/sbtools/rsrc.c227
-rw-r--r--utils/imxtools/sbtools/rsrc.h76
-rw-r--r--utils/imxtools/sbtools/rsrctool.c198
4 files changed, 505 insertions, 1 deletions
diff --git a/utils/imxtools/sbtools/Makefile b/utils/imxtools/sbtools/Makefile
index 7d00e4b8c1..bc7180d866 100644
--- a/utils/imxtools/sbtools/Makefile
+++ b/utils/imxtools/sbtools/Makefile
@@ -3,7 +3,7 @@ CC=gcc
3LD=gcc 3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES) 4CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES)
5LDFLAGS=`pkg-config --libs libusb-1.0` 5LDFLAGS=`pkg-config --libs libusb-1.0`
6BINS=elftosb sbtoelf sbloader 6BINS=elftosb sbtoelf sbloader rsrctool
7 7
8all: $(BINS) 8all: $(BINS)
9 9
@@ -19,6 +19,9 @@ elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o
19sbloader: sbloader.o 19sbloader: sbloader.o
20 $(LD) -o $@ $^ $(LDFLAGS) 20 $(LD) -o $@ $^ $(LDFLAGS)
21 21
22rsrctool: rsrctool.o rsrc.o misc.o
23 $(LD) -o $@ $^ $(LDFLAGS)
24
22clean: 25clean:
23 rm -fr *.o 26 rm -fr *.o
24 27
diff --git a/utils/imxtools/sbtools/rsrc.c b/utils/imxtools/sbtools/rsrc.c
new file mode 100644
index 0000000000..da3c418d2c
--- /dev/null
+++ b/utils/imxtools/sbtools/rsrc.c
@@ -0,0 +1,227 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
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#include <stdio.h>
22#include <time.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include "misc.h"
26#include "crypto.h"
27#include "rsrc.h"
28
29const char crypto_key[16] = "SanDiskSlotRadi";
30
31static void rsrc_crypt(void *buf, int size)
32{
33 if(size % 16)
34 printf("Size must be a multiple of 16 !\n");
35 uint8_t *p = buf;
36 for(int i = 0; i < size; i+= 16, p += 16)
37 {
38 for(int j = 0; j < 16; j++)
39 p[j] ^= crypto_key[j];
40 }
41}
42
43enum rsrc_error_t rsrc_write_file(struct rsrc_file_t *rsrc, const char *filename)
44{
45 FILE *f = fopen(filename, "wb");
46 if(f == NULL)
47 return RSRC_OPEN_ERROR;
48 fwrite(rsrc->data, 1, rsrc->size, f);
49 fclose(f);
50 return RSRC_SUCCESS;
51}
52
53struct rsrc_file_t *rsrc_read_file(const char *filename, void *u,
54 rsrc_color_printf cprintf, enum rsrc_error_t *err)
55{
56 return rsrc_read_file_ex(filename, 0, -1, u, cprintf, err);
57}
58
59struct rsrc_file_t *rsrc_read_file_ex(const char *filename, size_t offset, size_t size, void *u,
60 rsrc_color_printf cprintf, enum rsrc_error_t *err)
61{
62 #define fatal(e, ...) \
63 do { if(err) *err = e; \
64 cprintf(u, true, GREY, __VA_ARGS__); \
65 free(buf); \
66 return NULL; } while(0)
67
68 FILE *f = fopen(filename, "rb");
69 void *buf = NULL;
70 if(f == NULL)
71 fatal(RSRC_OPEN_ERROR, "Cannot open file for reading\n");
72 fseek(f, 0, SEEK_END);
73 size_t read_size = ftell(f);
74 fseek(f, offset, SEEK_SET);
75 if(size != (size_t)-1)
76 read_size = size;
77 buf = xmalloc(read_size);
78 if(fread(buf, read_size, 1, f) != 1)
79 {
80 fclose(f);
81 fatal(RSRC_READ_ERROR, "Cannot read file\n");
82 }
83 fclose(f);
84
85 struct rsrc_file_t *ret = rsrc_read_memory(buf, read_size, u, cprintf, err);
86 free(buf);
87 return ret;
88
89 #undef fatal
90}
91
92static const char *rsrc_table_entry_type_str(int type)
93{
94 switch(type)
95 {
96 case RSRC_TYPE_NONE: return "empty";
97 case RSRC_TYPE_NESTED: return "nested";
98 case RSRC_TYPE_IMAGE: return "image";
99 case RSRC_TYPE_VALUE: return "value";
100 case RSRC_TYPE_AUDIO: return "audio";
101 case RSRC_TYPE_DATA: return "data";
102 default: return "unknown";
103 }
104}
105
106static bool read_entries(void *buf, int filesize, void *u,
107 rsrc_color_printf cprintf, enum rsrc_error_t *err,
108 int offset, uint32_t base_index, int level, char *prefix)
109{
110 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
111 #define fatal(e, ...) \
112 do { if(err) *err = e; \
113 cprintf(u, true, GREY, __VA_ARGS__); \
114 return e; } while(0)
115
116 if(offset >= filesize)
117 fatal(RSRC_FORMAT_ERROR, "Out of bounds at off=%x base=%x level=%d\n ouch\n");
118 if(level < 0)
119 fatal(RSRC_FORMAT_ERROR, "Out of levels at off=%x base=%x level=%d\n aie\n");
120 for(int i = 0; i < 256; i++)
121 {
122 uint32_t te = *(uint32_t *)(buf + offset + 4 * i);
123 if(RSRC_TABLE_ENTRY_TYPE(te) == RSRC_TYPE_NONE)
124 continue;
125 uint32_t sz = 0;
126 if(RSRC_TABLE_ENTRY_TYPE(te) == RSRC_TYPE_VALUE)
127 sz = 2;
128 else if(RSRC_TABLE_ENTRY_TYPE(te) == RSRC_TYPE_NESTED)
129 sz = 4 * 256;
130 else
131 sz = *(uint32_t *)(buf + RSRC_TABLE_ENTRY_OFFSET(te));
132
133 uint32_t index = base_index | i << (level * 8);
134 printf(OFF, "%s+-%s%#08x %s[%s]%s[size=%#x]\n", prefix, YELLOW, index, BLUE,
135 rsrc_table_entry_type_str(RSRC_TABLE_ENTRY_TYPE(te)),
136 GREEN, sz);
137
138 if(RSRC_TABLE_ENTRY_TYPE(te) == RSRC_TYPE_NESTED)
139 {
140 char *p = prefix + strlen(prefix);
141 sprintf(p, "%s| ", RED);
142
143 bool ok = read_entries(buf, filesize, u, cprintf, err,
144 RSRC_TABLE_ENTRY_OFFSET(te), index,
145 level - 1, prefix);
146 if(!ok)
147 return false;
148 *p = 0;
149 }
150 }
151
152 return true;
153 #undef printf
154 #undef fatal
155}
156
157struct rsrc_file_t *rsrc_read_memory(void *_buf, size_t filesize, void *u,
158 rsrc_color_printf cprintf, enum rsrc_error_t *err)
159{
160 struct rsrc_file_t *rsrc_file = NULL;
161 uint8_t *buf = _buf;
162
163 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
164 #define fatal(e, ...) \
165 do { if(err) *err = e; \
166 cprintf(u, true, GREY, __VA_ARGS__); \
167 rsrc_free(rsrc_file); \
168 return NULL; } while(0)
169 #define print_hex(c, p, len, nl) \
170 do { printf(c, ""); print_hex(p, len, nl); } while(0)
171
172 rsrc_file = xmalloc(sizeof(struct rsrc_file_t));
173 memset(rsrc_file, 0, sizeof(struct rsrc_file_t));
174
175 /* There is a padding sector at the beginning of the file with a RSRC string.
176 * It is unclear if this is a signature since no code I've disassembled
177 * actually checks it. Allow use of -force to bypass. */
178 if(memcmp(buf + 20, "RSRC", 4) != 0)
179 {
180 if(g_force)
181 printf(GREY, "Missing RSRC signature\n");
182 else
183 fatal(RSRC_FORMAT_ERROR, "Missing RSRC signature\n");
184 }
185
186 printf(BLUE, "Entries\n");
187 char prefix[1024];
188 sprintf(prefix, "%s", RED);
189 bool ok = read_entries(buf, filesize, u, cprintf, err,
190 RSRC_SECTOR_SIZE, 0, 3, prefix);
191 if(!ok)
192 fatal(*err, "Error while parsing rsrc table\n");
193
194 rsrc_file->data = malloc(filesize);
195 memcpy(rsrc_file->data, _buf, filesize);
196 rsrc_file->size = filesize;
197
198 return rsrc_file;
199 #undef printf
200 #undef fatal
201 #undef print_hex
202}
203
204void rsrc_free(struct rsrc_file_t *file)
205{
206 if(!file) return;
207 free(file);
208}
209
210void rsrc_dump(struct rsrc_file_t *file, void *u, rsrc_color_printf cprintf)
211{
212 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
213 #define print_hex(c, p, len, nl) \
214 do { printf(c, ""); print_hex(p, len, nl); } while(0)
215
216 #define TREE RED
217 #define HEADER GREEN
218 #define TEXT YELLOW
219 #define TEXT2 BLUE
220 #define SEP OFF
221
222 printf(HEADER, "RSRC File\n");
223
224 #undef printf
225 #undef print_hex
226}
227
diff --git a/utils/imxtools/sbtools/rsrc.h b/utils/imxtools/sbtools/rsrc.h
new file mode 100644
index 0000000000..fc310e348d
--- /dev/null
+++ b/utils/imxtools/sbtools/rsrc.h
@@ -0,0 +1,76 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
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#ifndef __RSRC_H__
22#define __RSRC_H__
23
24#include <stdint.h>
25#include <stdbool.h>
26
27#include "misc.h"
28
29#define RSRC_SECTOR_SIZE 2048
30
31#define RSRC_TABLE_ENTRY_TYPE(e) ((e) >> 28)
32#define RSRC_TABLE_ENTRY_OFFSET(e) ((e) & 0xfffffff)
33
34#define RSRC_TYPE_NONE 0 /* empty entry */
35#define RSRC_TYPE_NESTED 1 /* nested entry: points to a sub-table */
36#define RSRC_TYPE_IMAGE 2 /* image entry */
37#define RSRC_TYPE_VALUE 3 /* value stored on 28-bits */
38#define RSRC_TYPE_AUDIO 4 /* audio entry */
39#define RSRC_TYPE_DATA 5 /* data entry */
40
41struct rsrc_file_t
42{
43 void *data;
44 int size;
45};
46
47enum rsrc_error_t
48{
49 RSRC_SUCCESS = 0,
50 RSRC_ERROR = -1,
51 RSRC_OPEN_ERROR = -2,
52 RSRC_READ_ERROR = -3,
53 RSRC_WRITE_ERROR = -4,
54 RSRC_FORMAT_ERROR = -5,
55 RSRC_CHECKSUM_ERROR = -6,
56 RSRC_NO_VALID_KEY = -7,
57 RSRC_FIRST_CRYPTO_ERROR = -8,
58 RSRC_LAST_CRYPTO_ERROR = RSRC_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS,
59};
60
61enum rsrc_error_t rsrc_write_file(struct rsrc_file_t *rsrc, const char *filename);
62
63typedef void (*rsrc_color_printf)(void *u, bool err, color_t c, const char *f, ...);
64struct rsrc_file_t *rsrc_read_file(const char *filename, void *u,
65 rsrc_color_printf printf, enum rsrc_error_t *err);
66/* use size_t(-1) to use maximum size */
67struct rsrc_file_t *rsrc_read_file_ex(const char *filename, size_t offset, size_t size, void *u,
68 rsrc_color_printf printf, enum rsrc_error_t *err);
69struct rsrc_file_t *rsrc_read_memory(void *buffer, size_t size, void *u,
70 rsrc_color_printf printf, enum rsrc_error_t *err);
71
72void rsrc_dump(struct rsrc_file_t *file, void *u, rsrc_color_printf printf);
73void rsrc_free(struct rsrc_file_t *file);
74
75#endif /* __RSRC_H__ */
76
diff --git a/utils/imxtools/sbtools/rsrctool.c b/utils/imxtools/sbtools/rsrctool.c
new file mode 100644
index 0000000000..cb0582245a
--- /dev/null
+++ b/utils/imxtools/sbtools/rsrctool.c
@@ -0,0 +1,198 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
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#define _ISOC99_SOURCE /* snprintf() */
23#include <stdio.h>
24#include <errno.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28#include <time.h>
29#include <stdarg.h>
30#include <strings.h>
31#include <getopt.h>
32
33#include "crypto.h"
34#include "rsrc.h"
35#include "misc.h"
36
37/* all blocks are sized as a multiple of 0x1ff */
38#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
39
40/* If you find a firmware that breaks the known format ^^ */
41#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)
42
43#define crypto_cbc(...) \
44 do { int ret = crypto_cbc(__VA_ARGS__); \
45 if(ret != CRYPTO_ERROR_SUCCESS) \
46 bug("crypto_cbc error: %d\n", ret); \
47 }while(0)
48
49/* globals */
50
51char *g_out_prefix;
52
53static void extract_rsrc_file(struct rsrc_file_t *file)
54{
55
56}
57
58static void usage(void)
59{
60 printf("Usage: rsrctool [options] rsrc-file\n");
61 printf("Options:\n");
62 printf(" -?/--help\tDisplay this message\n");
63 printf(" -o <prefix>\tEnable output and set prefix\n");
64 printf(" -d/--debug\tEnable debug output*\n");
65 printf(" -k <file>\tAdd key file\n");
66 printf(" -z\t\tAdd zero key\n");
67 printf(" -a/--add-key <key>\tAdd single key (hex or usbotp)\n");
68 printf(" -n/--no-color\tDisable output colors\n");
69 printf(" -l/--loopback <file>\tProduce rsrc file out of extracted description*\n");
70 printf(" -f/--force\tForce reading even without a key*\n");
71 printf("Options marked with a * are for debug purpose only\n");
72 exit(1);
73}
74
75static void rsrc_printf(void *user, bool error, color_t c, const char *fmt, ...)
76{
77 (void) user;
78 (void) error;
79 va_list args;
80 va_start(args, fmt);
81 color(c);
82 vprintf(fmt, args);
83 va_end(args);
84}
85
86static struct crypto_key_t g_zero_key =
87{
88 .method = CRYPTO_KEY,
89 .u.key = {0}
90};
91
92int main(int argc, char **argv)
93{
94 const char *loopback = NULL;
95
96 while(1)
97 {
98 static struct option long_options[] =
99 {
100 {"help", no_argument, 0, '?'},
101 {"debug", no_argument, 0, 'd'},
102 {"add-key", required_argument, 0, 'a'},
103 {"no-color", no_argument, 0, 'n'},
104 {"loopback", required_argument, 0, 'l'},
105 {"force", no_argument, 0, 'f' },
106 {0, 0, 0, 0}
107 };
108
109 int c = getopt_long(argc, argv, "?do:k:za:nl:f", long_options, NULL);
110 if(c == -1)
111 break;
112 switch(c)
113 {
114 case -1:
115 break;
116 case 'l':
117 if(loopback)
118 bug("Only one loopback file can be specified !\n");
119 loopback = optarg;
120 break;
121 case 'n':
122 enable_color(false);
123 break;
124 case 'd':
125 g_debug = true;
126 break;
127 case '?':
128 usage();
129 break;
130 case 'o':
131 g_out_prefix = optarg;
132 break;
133 case 'f':
134 g_force = true;
135 break;
136 case 'k':
137 {
138 if(!add_keys_from_file(optarg))
139 bug("Cannot add keys from %s\n", optarg);
140 break;
141 }
142 case 'z':
143 {
144 add_keys(&g_zero_key, 1);
145 break;
146 }
147 case 'a':
148 {
149 struct crypto_key_t key;
150 char *s = optarg;
151 if(!parse_key(&s, &key))
152 bug("Invalid key specified as argument\n");
153 if(*s != 0)
154 bug("Trailing characters after key specified as argument\n");
155 add_keys(&key, 1);
156 break;
157 }
158 default:
159 abort();
160 }
161 }
162
163 if(argc - optind != 1)
164 {
165 usage();
166 return 1;
167 }
168
169 const char *rsrc_filename = argv[optind];
170
171 enum rsrc_error_t err;
172 struct rsrc_file_t *file = rsrc_read_file(rsrc_filename, NULL, rsrc_printf, &err);
173 if(file == NULL)
174 {
175 color(OFF);
176 printf("RSRC read failed: %d\n", err);
177 return 1;
178 }
179
180 color(OFF);
181 if(g_out_prefix)
182 extract_rsrc_file(file);
183 if(g_debug)
184 {
185 color(GREY);
186 printf("[Debug output]\n");
187 rsrc_dump(file, NULL, rsrc_printf);
188 }
189 if(loopback)
190 {
191 rsrc_write_file(file, loopback);
192 }
193 rsrc_free(file);
194 clear_keys();
195
196 return 0;
197}
198