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 uint16_t swap16(uint16_t t
)
31 return (t
<< 8) | (t
>> 8);
34 static void fix_version(struct sb1_version_t
*ver
)
36 ver
->major
= swap16(ver
->major
);
37 ver
->minor
= swap16(ver
->minor
);
38 ver
->revision
= swap16(ver
->revision
);
41 enum sb1_error_t
sb1_write_file(struct sb1_file_t
*sb
, const char *filename
)
46 struct sb1_file_t
*sb1_read_file(const char *filename
, void *u
,
47 sb1_color_printf cprintf
, enum sb1_error_t
*err
)
49 return sb1_read_file_ex(filename
, 0, -1, u
, cprintf
, err
);
52 struct sb1_file_t
*sb1_read_file_ex(const char *filename
, size_t offset
, size_t size
, void *u
,
53 sb1_color_printf cprintf
, enum sb1_error_t
*err
)
55 #define fatal(e, ...) \
56 do { if(err) *err = e; \
57 cprintf(u, true, GREY, __VA_ARGS__); \
59 return NULL; } while(0)
61 FILE *f
= fopen(filename
, "rb");
64 fatal(SB1_OPEN_ERROR
, "Cannot open file for reading\n");
65 fseek(f
, 0, SEEK_END
);
66 size_t read_size
= ftell(f
);
67 fseek(f
, offset
, SEEK_SET
);
68 if(size
!= (size_t)-1)
70 buf
= xmalloc(read_size
);
71 if(fread(buf
, read_size
, 1, f
) != 1)
74 fatal(SB1_READ_ERROR
, "Cannot read file\n");
78 struct sb1_file_t
*ret
= sb1_read_memory(buf
, read_size
, u
, cprintf
, err
);
85 static const char *sb1_cmd_name(int cmd
)
89 case SB1_INST_LOAD
: return "load";
90 case SB1_INST_FILL
: return "fill";
91 case SB1_INST_JUMP
: return "jump";
92 case SB1_INST_CALL
: return "call";
93 case SB1_INST_MODE
: return "mode";
94 case SB1_INST_SDRAM
: return "sdram";
95 default: return "unknown";
99 struct sb1_file_t
*sb1_read_memory(void *_buf
, size_t filesize
, void *u
,
100 sb1_color_printf cprintf
, enum sb1_error_t
*err
)
102 struct sb1_file_t
*sb1_file
= NULL
;
105 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
106 #define fatal(e, ...) \
107 do { if(err) *err = e; \
108 cprintf(u, true, GREY, __VA_ARGS__); \
109 sb1_free(sb1_file); \
110 return NULL; } while(0)
111 #define print_hex(c, p, len, nl) \
112 do { printf(c, ""); print_hex(p, len, nl); } while(0)
114 sb1_file
= xmalloc(sizeof(struct sb1_file_t
));
115 memset(sb1_file
, 0, sizeof(struct sb1_file_t
));
116 struct sb1_header_t
*header
= (struct sb1_header_t
*)buf
;
118 if(memcmp(header
->signature
, "STMP", 4) != 0)
119 fatal(SB1_FORMAT_ERROR
, "Bad signature\n");
120 if(header
->image_size
> filesize
)
121 fatal(SB1_FORMAT_ERROR
, "File too small (should be at least %d bytes)\n",
123 if(header
->header_size
!= sizeof(struct sb1_header_t
))
124 fatal(SB1_FORMAT_ERROR
, "Bad header size\n");
126 printf(BLUE
, "Basic info:\n");
127 printf(GREEN
, " ROM version: ");
128 printf(YELLOW
, "%x\n", header
->rom_version
);
129 printf(GREEN
, " Userdata offset: ");
130 printf(YELLOW
, "%x\n", header
->userdata_offset
);
131 printf(GREEN
, " Pad: ");
132 printf(YELLOW
, "%x\n", header
->pad2
);
134 struct sb1_version_t product_ver
= header
->product_ver
;
135 fix_version(&product_ver
);
136 struct sb1_version_t component_ver
= header
->component_ver
;
137 fix_version(&component_ver
);
139 memcpy(&sb1_file
->product_ver
, &product_ver
, sizeof(product_ver
));
140 memcpy(&sb1_file
->component_ver
, &component_ver
, sizeof(component_ver
));
142 printf(GREEN
, " Product version: ");
143 printf(YELLOW
, "%X.%X.%X\n", product_ver
.major
, product_ver
.minor
, product_ver
.revision
);
144 printf(GREEN
, " Component version: ");
145 printf(YELLOW
, "%X.%X.%X\n", component_ver
.major
, component_ver
.minor
, component_ver
.revision
);
147 printf(GREEN
, " Drive tag: ");
148 printf(YELLOW
, "%x\n", header
->drive_tag
);
150 /* reduce size w.r.t to userdata part */
151 uint32_t userdata_size
= 0;
152 if(header
->userdata_offset
!= 0)
154 userdata_size
= header
->image_size
- header
->userdata_offset
;
155 header
->image_size
-= userdata_size
;
158 if(header
->image_size
% SECTOR_SIZE
)
161 printf(GREY
, "Image size is not a multiple of sector size\n");
163 fatal(SB1_FORMAT_ERROR
, "Image size is not a multiple of sector size\n");
167 union xorcrypt_key_t key
[2];
168 bool valid_key
= false;
169 uint8_t sector
[SECTOR_SIZE
];
171 for(int i
= 0; i
< g_nr_keys
; i
++)
173 if(!g_key_array
[i
].method
== CRYPTO_XOR_KEY
)
175 /* copy key and data because it's modified by the crypto code */
176 memcpy(key
, g_key_array
[i
].u
.xor_key
, sizeof(key
));
177 memcpy(sector
, header
+ 1, SECTOR_SIZE
- header
->header_size
);
178 /* try to decrypt the first sector */
179 uint32_t mark
= xor_decrypt(key
, sector
, SECTOR_SIZE
- 4 - header
->header_size
);
180 if(mark
!= *(uint32_t *)§or
[SECTOR_SIZE
- 4 - header
->header_size
])
184 /* copy key again it's modified by the crypto code */
185 memcpy(key
, g_key_array
[i
].u
.xor_key
, sizeof(key
));
189 printf(BLUE
, "Crypto\n");
190 for(int i
= 0; i
< 2; i
++)
192 printf(RED
, " Key %d\n", i
);
194 for(int j
= 0; j
< 64; j
++)
196 printf(YELLOW
, "%02x ", key
[i
].key
[j
]);
197 if((j
+ 1) % 16 == 0)
207 fatal(SB1_NO_VALID_KEY
, "No valid key found\n");
209 /* decrypt image in-place (and removing crypto markers) */
210 void *ptr
= header
+ 1;
211 void *copy_ptr
= header
+ 1;
212 int offset
= header
->header_size
;
213 for(unsigned i
= 0; i
< header
->image_size
/ SECTOR_SIZE
; i
++)
215 int size
= SECTOR_SIZE
- 4 - offset
;
216 uint32_t mark
= xor_decrypt(key
, ptr
, size
);
217 if(mark
!= *(uint32_t *)(ptr
+ size
))
218 fatal(SB1_CHECKSUM_ERROR
, "Crypto mark mismatch\n");
219 memmove(copy_ptr
, ptr
, size
);
225 /* reduce image size given the removed marks */
226 header
->image_size
-= header
->image_size
/ SECTOR_SIZE
;
228 printf(BLUE
, "Commands\n");
229 struct sb1_cmd_header_t
*cmd
= (void *)(header
+ 1);
230 while((void *)cmd
< (void *)header
+ header
->image_size
)
232 printf(GREEN
, " Command");
233 printf(YELLOW
, " %#x\n", cmd
->cmd
);
234 printf(YELLOW
, " Size:");
235 printf(RED
, " %#x\n", SB1_CMD_SIZE(cmd
->cmd
));
236 printf(YELLOW
, " Critical:");
237 printf(RED
, " %d\n", SB1_CMD_CRITICAL(cmd
->cmd
));
238 printf(YELLOW
, " Data Type:");
239 printf(RED
, " %#x\n", SB1_CMD_DATATYPE(cmd
->cmd
));
240 printf(YELLOW
, " Bytes:");
241 printf(RED
, " %#x\n", SB1_CMD_BYTES(cmd
->cmd
));
242 printf(YELLOW
, " Boot:");
243 printf(RED
, " %#x (%s)\n", SB1_CMD_BOOT(cmd
->cmd
), sb1_cmd_name(SB1_CMD_BOOT(cmd
->cmd
)));
244 printf(YELLOW
, " Addr:");
245 printf(RED
, " %#x\n", cmd
->addr
);
247 /* last instruction ? */
248 if(SB1_CMD_BOOT(cmd
->cmd
) == SB1_INST_JUMP
||
249 SB1_CMD_BOOT(cmd
->cmd
) == SB1_INST_MODE
)
252 cmd
= (void *)cmd
+ 4 + 4 * SB1_CMD_SIZE(cmd
->cmd
);
255 sb1_file
->data_size
= header
->image_size
- header
->header_size
;
256 sb1_file
->data
= malloc(sb1_file
->data_size
);
257 memcpy(sb1_file
->data
, header
+ 1, sb1_file
->data_size
);
265 void sb1_free(struct sb1_file_t
*file
)
273 void sb1_dump(struct sb1_file_t
*file
, void *u
, sb1_color_printf cprintf
)
275 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
276 #define print_hex(c, p, len, nl) \
277 do { printf(c, ""); print_hex(p, len, nl); } while(0)