1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2012 Amaury Pouly
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
30 #define MIN(a,b) ((a) < (b) ? (a) : (b))
33 const char crypto_key
[16] = "SanDiskSlotRadi";
35 static void rsrc_crypt(void *buf
, int size
)
38 printf("Size must be a multiple of 16 !\n");
40 for(int i
= 0; i
< size
; i
+= 16, p
+= 16)
42 for(int j
= 0; j
< 16; j
++)
43 p
[j
] ^= crypto_key
[j
];
47 enum rsrc_error_t
rsrc_write_file(struct rsrc_file_t
*rsrc
, const char *filename
)
49 FILE *f
= fopen(filename
, "wb");
51 return RSRC_OPEN_ERROR
;
52 fwrite(rsrc
->data
, 1, rsrc
->size
, f
);
57 struct rsrc_file_t
*rsrc_read_file(const char *filename
, void *u
,
58 rsrc_color_printf cprintf
, enum rsrc_error_t
*err
)
60 return rsrc_read_file_ex(filename
, 0, -1, u
, cprintf
, err
);
63 struct rsrc_file_t
*rsrc_read_file_ex(const char *filename
, size_t offset
, size_t size
, void *u
,
64 rsrc_color_printf cprintf
, enum rsrc_error_t
*err
)
66 #define fatal(e, ...) \
67 do { if(err) *err = e; \
68 cprintf(u, true, GREY, __VA_ARGS__); \
70 return NULL; } while(0)
72 FILE *f
= fopen(filename
, "rb");
75 fatal(RSRC_OPEN_ERROR
, "Cannot open file for reading\n");
76 fseek(f
, 0, SEEK_END
);
77 size_t read_size
= ftell(f
);
78 fseek(f
, offset
, SEEK_SET
);
79 if(size
!= (size_t)-1)
81 buf
= xmalloc(read_size
);
82 if(fread(buf
, read_size
, 1, f
) != 1)
85 fatal(RSRC_READ_ERROR
, "Cannot read file\n");
89 struct rsrc_file_t
*ret
= rsrc_read_memory(buf
, read_size
, u
, cprintf
, err
);
96 static const char *rsrc_table_entry_type_str(int type
)
100 case RSRC_TYPE_NONE
: return "empty";
101 case RSRC_TYPE_NESTED
: return "nested";
102 case RSRC_TYPE_IMAGE
: return "image";
103 case RSRC_TYPE_VALUE
: return "value";
104 case RSRC_TYPE_AUDIO
: return "audio";
105 case RSRC_TYPE_DATA
: return "data";
106 default: return "unknown";
110 static bool read_entries(struct rsrc_file_t
*f
, void *u
,
111 rsrc_color_printf cprintf
, enum rsrc_error_t
*err
,
112 int offset
, uint32_t base_index
, int level
, char *prefix
)
114 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
115 #define fatal(e, ...) \
116 do { if(err) *err = e; \
117 cprintf(u, true, GREY, __VA_ARGS__); \
120 if(offset
>= f
->size
)
121 fatal(RSRC_FORMAT_ERROR
, "Out of bounds at off=%x base=%x level=%d\n ouch\n");
123 fatal(RSRC_FORMAT_ERROR
, "Out of levels at off=%x base=%x level=%d\n aie\n");
124 for(int i
= 0; i
< 256; i
++)
126 uint32_t te
= *(uint32_t *)(f
->data
+ offset
+ 4 * i
);
127 if(RSRC_TABLE_ENTRY_TYPE(te
) == RSRC_TYPE_NONE
)
130 uint32_t off_off
= 0;
131 if(RSRC_TABLE_ENTRY_TYPE(te
) == RSRC_TYPE_VALUE
)
133 else if(RSRC_TABLE_ENTRY_TYPE(te
) == RSRC_TYPE_NESTED
)
137 sz
= *(uint32_t *)(f
->data
+ RSRC_TABLE_ENTRY_OFFSET(te
));
141 uint32_t index
= base_index
| i
<< (level
* 8);
143 struct rsrc_entry_t ent
;
144 memset(&ent
, 0, sizeof(ent
));
146 ent
.offset
= RSRC_TABLE_ENTRY_OFFSET(te
) + off_off
;
149 augment_array_ex((void **)&f
->entries
, sizeof(ent
), &f
->nr_entries
, &f
->capacity
, &ent
, 1);
151 printf(OFF
, "%s+-%s%#08x %s[%s]%s[size=%#x]", prefix
, YELLOW
, index
, BLUE
,
152 rsrc_table_entry_type_str(RSRC_TABLE_ENTRY_TYPE(te
)),
155 if(RSRC_TABLE_ENTRY_TYPE(te
) != RSRC_TYPE_VALUE
&&
156 RSRC_TABLE_ENTRY_TYPE(te
) == RSRC_TYPE_NESTED
)
158 uint8_t *p
= f
->data
+ ent
.offset
;
160 for(unsigned i
= 0; i
< MIN(sz
, 16); i
++)
161 printf(RED
, "%c", isprint(p
[i
]) ? p
[i
] : '.');
165 if(RSRC_TABLE_ENTRY_TYPE(te
) == RSRC_TYPE_NESTED
)
167 char *p
= prefix
+ strlen(prefix
);
168 sprintf(p
, "%s| ", RED
);
170 bool ok
= read_entries(f
, u
, cprintf
, err
,
171 RSRC_TABLE_ENTRY_OFFSET(te
), index
,
184 struct rsrc_file_t
*rsrc_read_memory(void *_buf
, size_t filesize
, void *u
,
185 rsrc_color_printf cprintf
, enum rsrc_error_t
*err
)
187 struct rsrc_file_t
*rsrc_file
= NULL
;
190 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
191 #define fatal(e, ...) \
192 do { if(err) *err = e; \
193 cprintf(u, true, GREY, __VA_ARGS__); \
194 rsrc_free(rsrc_file); \
195 return NULL; } while(0)
196 #define print_hex(c, p, len, nl) \
197 do { printf(c, ""); print_hex(p, len, nl); } while(0)
199 rsrc_file
= xmalloc(sizeof(struct rsrc_file_t
));
200 memset(rsrc_file
, 0, sizeof(struct rsrc_file_t
));
202 /* There is a padding sector at the beginning of the file with a RSRC string.
203 * It is unclear if this is a signature since no code I've disassembled
204 * actually checks it. Allow use of -force to bypass. */
205 if(memcmp(buf
+ 20, "RSRC", 4) != 0)
208 printf(GREY
, "Missing RSRC signature\n");
210 fatal(RSRC_FORMAT_ERROR
, "Missing RSRC signature\n");
213 rsrc_file
->data
= malloc(filesize
);
214 memcpy(rsrc_file
->data
, _buf
, filesize
);
215 rsrc_file
->size
= filesize
;
217 printf(BLUE
, "Entries\n");
219 sprintf(prefix
, "%s", RED
);
220 bool ok
= read_entries(rsrc_file
, u
, cprintf
, err
, RSRC_SECTOR_SIZE
, 0, 3, prefix
);
222 fatal(*err
, "Error while parsing rsrc table\n");
230 void rsrc_free(struct rsrc_file_t
*file
)
238 void rsrc_dump(struct rsrc_file_t
*file
, void *u
, rsrc_color_printf cprintf
)
240 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
241 #define print_hex(c, p, len, nl) \
242 do { printf(c, ""); print_hex(p, len, nl); } while(0)
250 printf(HEADER
, "RSRC File\n");