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 ****************************************************************************/
29 static int sdram_size_table
[] = {2, 8, 16, 32, 64};
31 #define NR_SDRAM_ENTRIES (int)(sizeof(sdram_size_table) / sizeof(sdram_size_table[0]))
33 int sb1_sdram_size_by_index(int index
)
35 if(index
< 0 || index
>= NR_SDRAM_ENTRIES
)
37 return sdram_size_table
[index
];
40 int sb1_sdram_index_by_size(int size
)
42 for(int i
= 0; i
< NR_SDRAM_ENTRIES
; i
++)
43 if(sdram_size_table
[i
] == size
)
48 static uint16_t swap16(uint16_t t
)
50 return (t
<< 8) | (t
>> 8);
53 static void fix_version(struct sb1_version_t
*ver
)
55 ver
->major
= swap16(ver
->major
);
56 ver
->minor
= swap16(ver
->minor
);
57 ver
->revision
= swap16(ver
->revision
);
60 enum sb1_error_t
sb1_write_file(struct sb1_file_t
*sb
, const char *filename
)
65 struct sb1_file_t
*sb1_read_file(const char *filename
, void *u
,
66 sb1_color_printf cprintf
, enum sb1_error_t
*err
)
68 return sb1_read_file_ex(filename
, 0, -1, u
, cprintf
, err
);
71 struct sb1_file_t
*sb1_read_file_ex(const char *filename
, size_t offset
, size_t size
, void *u
,
72 sb1_color_printf cprintf
, enum sb1_error_t
*err
)
74 #define fatal(e, ...) \
75 do { if(err) *err = e; \
76 cprintf(u, true, GREY, __VA_ARGS__); \
78 return NULL; } while(0)
80 FILE *f
= fopen(filename
, "rb");
83 fatal(SB1_OPEN_ERROR
, "Cannot open file for reading\n");
84 fseek(f
, 0, SEEK_END
);
85 size_t read_size
= ftell(f
);
86 fseek(f
, offset
, SEEK_SET
);
87 if(size
!= (size_t)-1)
89 buf
= xmalloc(read_size
);
90 if(fread(buf
, read_size
, 1, f
) != 1)
93 fatal(SB1_READ_ERROR
, "Cannot read file\n");
97 struct sb1_file_t
*ret
= sb1_read_memory(buf
, read_size
, u
, cprintf
, err
);
104 static const char *sb1_cmd_name(int cmd
)
108 case SB1_INST_LOAD
: return "load";
109 case SB1_INST_FILL
: return "fill";
110 case SB1_INST_JUMP
: return "jump";
111 case SB1_INST_CALL
: return "call";
112 case SB1_INST_MODE
: return "mode";
113 case SB1_INST_SDRAM
: return "sdram";
114 default: return "unknown";
118 static const char *sb1_datatype_name(int cmd
)
122 case SB1_DATATYPE_UINT32
: return "uint32";
123 case SB1_DATATYPE_UINT16
: return "uint16";
124 case SB1_DATATYPE_UINT8
: return "uint8";
125 default: return "unknown";
129 struct sb1_file_t
*sb1_read_memory(void *_buf
, size_t filesize
, void *u
,
130 sb1_color_printf cprintf
, enum sb1_error_t
*err
)
132 struct sb1_file_t
*file
= NULL
;
135 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
136 #define fatal(e, ...) \
137 do { if(err) *err = e; \
138 cprintf(u, true, GREY, __VA_ARGS__); \
140 return NULL; } while(0)
141 #define print_hex(c, p, len, nl) \
142 do { printf(c, ""); print_hex(p, len, nl); } while(0)
144 file
= xmalloc(sizeof(struct sb1_file_t
));
145 memset(file
, 0, sizeof(struct sb1_file_t
));
146 struct sb1_header_t
*header
= (struct sb1_header_t
*)buf
;
148 if(memcmp(header
->signature
, "STMP", 4) != 0)
149 fatal(SB1_FORMAT_ERROR
, "Bad signature\n");
150 if(header
->image_size
> filesize
)
151 fatal(SB1_FORMAT_ERROR
, "File too small (should be at least %d bytes)\n",
153 if(header
->header_size
!= sizeof(struct sb1_header_t
))
154 fatal(SB1_FORMAT_ERROR
, "Bad header size\n");
156 printf(BLUE
, "Basic info:\n");
157 printf(GREEN
, " ROM version: ");
158 printf(YELLOW
, "%x\n", header
->rom_version
);
159 printf(GREEN
, " Userdata offset: ");
160 printf(YELLOW
, "%x\n", header
->userdata_offset
);
161 printf(GREEN
, " Pad: ");
162 printf(YELLOW
, "%x\n", header
->pad2
);
164 struct sb1_version_t product_ver
= header
->product_ver
;
165 fix_version(&product_ver
);
166 struct sb1_version_t component_ver
= header
->component_ver
;
167 fix_version(&component_ver
);
169 printf(GREEN
, " Product version: ");
170 printf(YELLOW
, "%X.%X.%X\n", product_ver
.major
, product_ver
.minor
, product_ver
.revision
);
171 printf(GREEN
, " Component version: ");
172 printf(YELLOW
, "%X.%X.%X\n", component_ver
.major
, component_ver
.minor
, component_ver
.revision
);
174 printf(GREEN
, " Drive tag: ");
175 printf(YELLOW
, "%x\n", header
->drive_tag
);
177 /* copy rom version, padding and drive tag */
179 memcpy(&file
->product_ver
, &product_ver
, sizeof(product_ver
));
180 memcpy(&file
->component_ver
, &component_ver
, sizeof(component_ver
));
181 file
->rom_version
= header
->rom_version
;
182 file
->pad2
= header
->pad2
;
183 file
->drive_tag
= header
->drive_tag
;
185 /* reduce size w.r.t to userdata part */
186 uint32_t userdata_size
= 0;
187 if(header
->userdata_offset
!= 0)
189 userdata_size
= header
->image_size
- header
->userdata_offset
;
190 header
->image_size
-= userdata_size
;
193 if(header
->image_size
% SECTOR_SIZE
)
196 printf(GREY
, "Image size is not a multiple of sector size\n");
198 fatal(SB1_FORMAT_ERROR
, "Image size is not a multiple of sector size\n");
202 union xorcrypt_key_t key
[2];
203 bool valid_key
= false;
204 uint8_t sector
[SECTOR_SIZE
];
206 for(int i
= 0; i
< g_nr_keys
; i
++)
208 if(!g_key_array
[i
].method
== CRYPTO_XOR_KEY
)
210 /* copy key and data because it's modified by the crypto code */
211 memcpy(key
, g_key_array
[i
].u
.xor_key
, sizeof(key
));
212 memcpy(sector
, header
+ 1, SECTOR_SIZE
- header
->header_size
);
213 /* try to decrypt the first sector */
214 uint32_t mark
= xor_decrypt(key
, sector
, SECTOR_SIZE
- 4 - header
->header_size
);
215 if(mark
!= *(uint32_t *)§or
[SECTOR_SIZE
- 4 - header
->header_size
])
219 /* copy key again it's modified by the crypto code */
220 memcpy(key
, g_key_array
[i
].u
.xor_key
, sizeof(key
));
224 printf(BLUE
, "Crypto\n");
225 for(int i
= 0; i
< 2; i
++)
227 printf(RED
, " Key %d\n", i
);
229 for(int j
= 0; j
< 64; j
++)
231 printf(YELLOW
, "%02x ", key
[i
].key
[j
]);
232 if((j
+ 1) % 16 == 0)
242 fatal(SB1_NO_VALID_KEY
, "No valid key found\n");
244 /* decrypt image in-place (and removing crypto markers) */
245 void *ptr
= header
+ 1;
246 void *copy_ptr
= header
+ 1;
247 int offset
= header
->header_size
;
248 for(unsigned i
= 0; i
< header
->image_size
/ SECTOR_SIZE
; i
++)
250 int size
= SECTOR_SIZE
- 4 - offset
;
251 uint32_t mark
= xor_decrypt(key
, ptr
, size
);
252 if(mark
!= *(uint32_t *)(ptr
+ size
))
253 fatal(SB1_CHECKSUM_ERROR
, "Crypto mark mismatch\n");
254 memmove(copy_ptr
, ptr
, size
);
261 /* reduce image size given the removed marks */
262 header
->image_size
-= header
->image_size
/ SECTOR_SIZE
;
264 printf(BLUE
, "Commands\n");
265 struct sb1_cmd_header_t
*cmd
= (void *)(header
+ 1);
266 while((void *)cmd
< (void *)header
+ header
->image_size
)
268 printf(GREEN
, " Command");
269 printf(YELLOW
, " %#x\n", cmd
->cmd
);
270 printf(YELLOW
, " Size:");
271 printf(RED
, " %#x\n", SB1_CMD_SIZE(cmd
->cmd
));
272 printf(YELLOW
, " Critical:");
273 printf(RED
, " %d\n", SB1_CMD_CRITICAL(cmd
->cmd
));
274 printf(YELLOW
, " Data Type:");
275 printf(RED
, " %#x ", SB1_CMD_DATATYPE(cmd
->cmd
));
276 printf(GREEN
, "(%s)\n", sb1_datatype_name(SB1_CMD_DATATYPE(cmd
->cmd
)));
277 printf(YELLOW
, " Bytes:");
278 printf(RED
, " %#x\n", SB1_CMD_BYTES(cmd
->cmd
));
279 printf(YELLOW
, " Boot:");
280 printf(RED
, " %#x ", SB1_CMD_BOOT(cmd
->cmd
));
281 printf(GREEN
, "(%s)\n", sb1_cmd_name(SB1_CMD_BOOT(cmd
->cmd
)));
282 printf(YELLOW
, " Addr:");
283 printf(RED
, " %#x", cmd
->addr
);
285 if(SB1_CMD_BOOT(cmd
->cmd
) == SB1_INST_SDRAM
)
286 printf(GREEN
, " (Chip Select=%d, Size=%d)", SB1_ADDR_SDRAM_CS(cmd
->addr
),
287 sb1_sdram_size_by_index(SB1_ADDR_SDRAM_SZ(cmd
->addr
)));
289 if(SB1_CMD_BOOT(cmd
->cmd
) == SB1_INST_FILL
)
291 printf(YELLOW
, " Pattern:");
292 printf(RED
, " %#x\n", *(uint32_t *)(cmd
+ 1));
296 struct sb1_inst_t inst
;
297 memset(&inst
, 0, sizeof(inst
));
298 inst
.cmd
= SB1_CMD_BOOT(cmd
->cmd
);
299 inst
.critical
= SB1_CMD_CRITICAL(cmd
->cmd
);
300 inst
.datatype
= SB1_CMD_DATATYPE(cmd
->cmd
);
301 inst
.size
= SB1_CMD_BYTES(cmd
->cmd
);
303 switch(SB1_CMD_BOOT(cmd
->cmd
))
306 inst
.sdram
.chip_select
= SB1_ADDR_SDRAM_CS(cmd
->addr
);
307 inst
.sdram
.size_index
= SB1_ADDR_SDRAM_SZ(cmd
->addr
);
310 inst
.mode
= cmd
->addr
;
313 inst
.data
= malloc(inst
.size
);
314 memcpy(inst
.data
, cmd
+ 1, inst
.size
);
317 inst
.addr
= cmd
->addr
;
321 file
->insts
= augment_array(file
->insts
, sizeof(inst
), file
->nr_insts
, &inst
, 1);
324 /* last instruction ? */
325 if(SB1_CMD_BOOT(cmd
->cmd
) == SB1_INST_JUMP
||
326 SB1_CMD_BOOT(cmd
->cmd
) == SB1_INST_MODE
)
329 cmd
= (void *)cmd
+ 4 + 4 * SB1_CMD_SIZE(cmd
->cmd
);
333 file
->userdata_size
= userdata_size
;
334 if(userdata_size
> 0)
336 file
->userdata
= malloc(userdata_size
);
337 memcpy(file
->userdata
, (void *)header
+ header
->userdata_offset
, userdata_size
);
346 void sb1_free(struct sb1_file_t
*file
)
350 for(int i
= 0; i
< file
->nr_insts
; i
++)
351 free(file
->insts
[i
].data
);
353 free(file
->userdata
);
357 void sb1_dump(struct sb1_file_t
*file
, void *u
, sb1_color_printf cprintf
)
359 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
360 #define print_hex(c, p, len, nl) \
361 do { printf(c, ""); print_hex(p, len, nl); } while(0)
370 printf(BLUE
, "SB1 File\n");
372 printf(HEADER
, "Rom Ver: ");
373 printf(TEXT
, "%x\n", file
->rom_version
);
375 printf(HEADER
, "Pad: ");
376 printf(TEXT
, "%x\n", file
->pad2
);
378 printf(HEADER
, "Drive Tag: ");
379 printf(TEXT
, "%x\n", file
->drive_tag
);
381 printf(HEADER
, "Product Version: ");
382 printf(TEXT
, "%X.%X.%X\n", file
->product_ver
.major
, file
->product_ver
.minor
,
383 file
->product_ver
.revision
);
385 printf(HEADER
, "Component Version: ");
386 printf(TEXT
, "%X.%X.%X\n", file
->component_ver
.major
, file
->component_ver
.minor
,
387 file
->component_ver
.revision
);
389 for(int j
= 0; j
< file
->nr_insts
; j
++)
391 struct sb1_inst_t
*inst
= &file
->insts
[j
];
393 printf(HEADER
, "Command\n");
394 printf(TREE
, "| +-");
399 printf(HEADER
, "%s", inst
->cmd
== SB1_INST_CALL
? "CALL" : "JUMP");
401 printf(TEXT3
, "crit=%d", inst
->critical
);
403 printf(TEXT
, "addr=0x%08x\n", inst
->addr
);
406 printf(HEADER
, "LOAD");
408 printf(TEXT3
, "crit=%d", inst
->critical
);
410 printf(TEXT
, "addr=0x%08x", inst
->addr
);
412 printf(TEXT2
, "len=0x%08x\n", inst
->size
);
415 printf(HEADER
, "FILL");
417 printf(TEXT3
, "crit=%d", inst
->critical
);
419 printf(TEXT
, "addr=0x%08x", inst
->addr
);
421 printf(TEXT2
, "len=0x%08x", inst
->size
);
423 printf(TEXT2
, "pattern=0x%08x\n", inst
->pattern
);
426 printf(HEADER
, "MODE");
428 printf(TEXT3
, "crit=%d", inst
->critical
);
430 printf(TEXT
, "mode=0x%08x\n", inst
->addr
);
433 printf(HEADER
, "SRAM");
435 printf(TEXT3
, "crit=%d", inst
->critical
);
437 printf(TEXT
, "chip_select=%d", inst
->sdram
.chip_select
);
439 printf(TEXT2
, "chip_size=%d\n", sb1_sdram_size_by_index(inst
->sdram
.size_index
));
442 printf(GREY
, "[Unknown instruction %x]\n", inst
->cmd
);