sbtools: add support for the stmp36xx format
[maemo-rb.git] / utils / imxtools / sbtools / sb1.c
blob19f53b00156447e6150d67c349c054e113d469cf
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
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 "sb1.h"
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)
43 return SB1_ERROR;
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__); \
58 free(buf); \
59 return NULL; } while(0)
61 FILE *f = fopen(filename, "rb");
62 void *buf = NULL;
63 if(f == NULL)
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)
69 read_size = size;
70 buf = xmalloc(read_size);
71 if(fread(buf, read_size, 1, f) != 1)
73 fclose(f);
74 fatal(SB1_READ_ERROR, "Cannot read file\n");
76 fclose(f);
78 struct sb1_file_t *ret = sb1_read_memory(buf, read_size, u, cprintf, err);
79 free(buf);
80 return ret;
82 #undef fatal
85 static const char *sb1_cmd_name(int cmd)
87 switch(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;
103 uint8_t *buf = _buf;
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",
122 header->image_size);
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)
160 if(g_force)
161 printf(GREY, "Image size is not a multiple of sector size\n");
162 else
163 fatal(SB1_FORMAT_ERROR, "Image size is not a multiple of sector size\n");
166 /* find key */
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)
174 continue;
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 *)&sector[SECTOR_SIZE - 4 - header->header_size])
181 continue;
182 /* found ! */
183 valid_key = true;
184 /* copy key again it's modified by the crypto code */
185 memcpy(key, g_key_array[i].u.xor_key, sizeof(key));
186 break;
189 printf(BLUE, "Crypto\n");
190 for(int i = 0; i < 2; i++)
192 printf(RED, " Key %d\n", i);
193 printf(OFF, " ");
194 for(int j = 0; j < 64; j++)
196 printf(YELLOW, "%02x ", key[i].key[j]);
197 if((j + 1) % 16 == 0)
199 printf(OFF, "\n");
200 if(j + 1 != 64)
201 printf(OFF, " ");
206 if(!valid_key)
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);
220 ptr += size + 4;
221 copy_ptr += size;
222 offset = 0;
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)
250 break;
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);
259 return sb1_file;
260 #undef printf
261 #undef fatal
262 #undef print_hex
265 void sb1_free(struct sb1_file_t *file)
267 if(!file) return;
269 free(file->data);
270 free(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)
279 #define TREE RED
280 #define HEADER GREEN
281 #define TEXT YELLOW
282 #define TEXT2 BLUE
283 #define SEP OFF
285 #undef printf
286 #undef print_hex