summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/imxtools/sbtools/sb.c151
-rw-r--r--utils/imxtools/sbtools/sb.h4
2 files changed, 82 insertions, 73 deletions
diff --git a/utils/imxtools/sbtools/sb.c b/utils/imxtools/sbtools/sb.c
index 385c5e5ded..183434efad 100644
--- a/utils/imxtools/sbtools/sb.c
+++ b/utils/imxtools/sbtools/sb.c
@@ -27,6 +27,9 @@
27#include "crypto.h" 27#include "crypto.h"
28#include "sb.h" 28#include "sb.h"
29 29
30#define ALIGN_DOWN(n, a) (((n)/(a))*(a))
31#define ALIGN_UP(n, a) ALIGN_DOWN((n)+((a)-1),a)
32
30static void fill_gaps(struct sb_file_t *sb) 33static void fill_gaps(struct sb_file_t *sb)
31{ 34{
32 for(int i = 0; i < sb->nr_sections; i++) 35 for(int i = 0; i < sb->nr_sections; i++)
@@ -58,27 +61,33 @@ static void compute_sb_offsets(struct sb_file_t *sb, void *u, generic_printf_t c
58 /* sections */ 61 /* sections */
59 for(int i = 0; i < sb->nr_sections; i++) 62 for(int i = 0; i < sb->nr_sections; i++)
60 { 63 {
61 /* each section has a preliminary TAG command */
62 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE;
63 /* we might need to pad the section so compute next alignment */
64 uint32_t alignment = BLOCK_SIZE;
65 if((i + 1) < sb->nr_sections)
66 alignment = sb->sections[i + 1].alignment;
67 alignment /= BLOCK_SIZE; /* alignment in block sizes */
68
69 struct sb_section_t *sec = &sb->sections[i]; 64 struct sb_section_t *sec = &sb->sections[i];
65 /* we need to make sure section starts on the right alignment,
66 * and since each section starts with a boot tag, we need to ensure
67 * that the boot tag is at address X such that X+BLOCK_SIZE is a
68 * multiple of the alignment */
69 uint32_t alignment = sb->sections[i].alignment / BLOCK_SIZE;
70 sb->image_size = ALIGN_UP(sb->image_size + 1, alignment) - 1;
71 /* update padding of previous section */
72 if(i > 0)
73 sb->sections[i - 1].pad_size = sb->image_size -
74 sb->sections[i - 1].file_offset - sb->sections[i - 1].sec_size;
75 /* each section has a preliminary TAG command */
76 sb->image_size += 1;
77 sec->file_offset = sb->image_size;
78 /* compute section size */
70 sec->sec_size = 0; 79 sec->sec_size = 0;
80 sec->pad_size = 0;
71 81
72 char name[5]; 82 char name[5];
73 sb_fill_section_name(name, sec->identifier); 83 sb_fill_section_name(name, sec->identifier);
74 printf(BLUE, "%s", sec->is_data ? "Data" : "Boot"); 84 printf(BLUE, "%s", sec->is_data ? "Data" : "Boot");
75 printf(GREEN, " Section"); 85 printf(GREEN, " Section ");
76 printf(YELLOW, "'%s'", name); 86 printf(YELLOW, "'%s'", name);
77 if(sec->is_cleartext) 87 if(sec->is_cleartext)
78 printf(RED, " (cleartext)"); 88 printf(RED, " (cleartext)");
79 printf(OFF, "\n"); 89 printf(OFF, "\n");
80 90
81 sec->file_offset = sb->image_size;
82 for(int j = 0; j < sec->nr_insts; j++) 91 for(int j = 0; j < sec->nr_insts; j++)
83 { 92 {
84 struct sb_inst_t *inst = &sec->insts[j]; 93 struct sb_inst_t *inst = &sec->insts[j];
@@ -87,7 +96,6 @@ static void compute_sb_offsets(struct sb_file_t *sb, void *u, generic_printf_t c
87 printf(RED, " %s", inst->inst == SB_INST_CALL ? "CALL" : "JUMP"); 96 printf(RED, " %s", inst->inst == SB_INST_CALL ? "CALL" : "JUMP");
88 printf(OFF, " | "); printf(BLUE, "addr=0x%08x", inst->addr); 97 printf(OFF, " | "); printf(BLUE, "addr=0x%08x", inst->addr);
89 printf(OFF, " | "); printf(GREEN, "arg=0x%08x\n", inst->argument); 98 printf(OFF, " | "); printf(GREEN, "arg=0x%08x\n", inst->argument);
90 sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
91 sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; 99 sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
92 } 100 }
93 else if(inst->inst == SB_INST_FILL) 101 else if(inst->inst == SB_INST_FILL)
@@ -96,7 +104,6 @@ static void compute_sb_offsets(struct sb_file_t *sb, void *u, generic_printf_t c
96 printf(OFF, " | "); printf(BLUE, "addr=0x%08x", inst->addr); 104 printf(OFF, " | "); printf(BLUE, "addr=0x%08x", inst->addr);
97 printf(OFF, " | "); printf(GREEN, "len=0x%08x", inst->size); 105 printf(OFF, " | "); printf(GREEN, "len=0x%08x", inst->size);
98 printf(OFF, " | "); printf(YELLOW, "pattern=0x%08x\n", inst->pattern); 106 printf(OFF, " | "); printf(YELLOW, "pattern=0x%08x\n", inst->pattern);
99 sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
100 sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; 107 sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
101 } 108 }
102 else if(inst->inst == SB_INST_LOAD) 109 else if(inst->inst == SB_INST_LOAD)
@@ -105,30 +112,25 @@ static void compute_sb_offsets(struct sb_file_t *sb, void *u, generic_printf_t c
105 printf(OFF, " | "); printf(BLUE, "addr=0x%08x", inst->addr); 112 printf(OFF, " | "); printf(BLUE, "addr=0x%08x", inst->addr);
106 printf(OFF, " | "); printf(GREEN, "len=0x%08x\n", inst->size); 113 printf(OFF, " | "); printf(GREEN, "len=0x%08x\n", inst->size);
107 /* load header */ 114 /* load header */
108 sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
109 sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; 115 sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
110 /* data + alignment */ 116 /* data + alignment */
111 sb->image_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
112 sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE; 117 sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
113 } 118 }
114 else if(inst->inst == SB_INST_MODE) 119 else if(inst->inst == SB_INST_MODE)
115 { 120 {
116 printf(RED, " MODE"); 121 printf(RED, " MODE");
117 printf(OFF, " | "); printf(BLUE, "mod=0x%08x\n", inst->addr); 122 printf(OFF, " | "); printf(BLUE, "mod=0x%08x\n", inst->addr);
118 sb->image_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
119 sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE; 123 sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
120 } 124 }
121 else if(inst->inst == SB_INST_DATA) 125 else if(inst->inst == SB_INST_DATA)
122 { 126 {
123 printf(RED, " DATA"); 127 printf(RED, " DATA");
124 printf(OFF, " | "); printf(BLUE, "size=0x%08x\n", inst->size); 128 printf(OFF, " | "); printf(BLUE, "size=0x%08x\n", inst->size);
125 sb->image_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
126 sec->sec_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE; 129 sec->sec_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
127 } 130 }
128 else if(inst->inst == SB_INST_NOP) 131 else if(inst->inst == SB_INST_NOP)
129 { 132 {
130 printf(RED, " NOOP\n"); 133 printf(RED, " NOOP\n");
131 sb->image_size += sizeof(struct sb_instruction_nop_t) / BLOCK_SIZE;
132 sec->sec_size += sizeof(struct sb_instruction_nop_t) / BLOCK_SIZE; 134 sec->sec_size += sizeof(struct sb_instruction_nop_t) / BLOCK_SIZE;
133 } 135 }
134 else 136 else
@@ -136,50 +138,7 @@ static void compute_sb_offsets(struct sb_file_t *sb, void *u, generic_printf_t c
136 cprintf(u, true, GREY, "die on inst %d\n", inst->inst); 138 cprintf(u, true, GREY, "die on inst %d\n", inst->inst);
137 } 139 }
138 } 140 }
139 /* we need to make sure next section starts on the right alignment. 141 sb->image_size += sec->sec_size;
140 * Since each section starts with a boot tag, we thus need to ensure
141 * that this sections ends at adress X such that X+BLOCK_SIZE is
142 * a multiple of the alignment.
143 * For data sections, we just add random data, otherwise we add nops */
144 uint32_t missing_sz = alignment - ((sb->image_size + 1) % alignment);
145 if(missing_sz != alignment)
146 {
147 struct sb_inst_t *aug_insts;
148 int nr_aug_insts = 0;
149
150 if(sb->sections[i].is_data)
151 {
152 nr_aug_insts = 1;
153 aug_insts = xmalloc(sizeof(struct sb_inst_t));
154 memset(aug_insts, 0, sizeof(struct sb_inst_t));
155 aug_insts[0].inst = SB_INST_DATA;
156 aug_insts[0].size = missing_sz * BLOCK_SIZE;
157 aug_insts[0].data = xmalloc(missing_sz * BLOCK_SIZE);
158 generate_random_data(aug_insts[0].data, missing_sz * BLOCK_SIZE);
159 printf(RED, " DATA");
160 printf(OFF, " | "); printf(BLUE, "size=0x%08x\n", aug_insts[0].size);
161 }
162 else
163 {
164 nr_aug_insts = missing_sz;
165 aug_insts = xmalloc(sizeof(struct sb_inst_t) * nr_aug_insts);
166 memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts);
167 for(int j = 0; j < nr_aug_insts; j++)
168 {
169 aug_insts[j].inst = SB_INST_NOP;
170 printf(RED, " NOOP\n");
171 }
172 }
173
174 sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t),
175 sb->sections[i].nr_insts, aug_insts, nr_aug_insts);
176 sb->sections[i].nr_insts += nr_aug_insts;
177 free(aug_insts);
178
179 /* augment image and section size */
180 sb->image_size += missing_sz;
181 sec->sec_size += missing_sz;
182 }
183 } 142 }
184 /* final signature */ 143 /* final signature */
185 sb->image_size += 2; 144 sb->image_size += 2;
@@ -222,14 +181,13 @@ static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
222 sb_hdr->flags = sb->flags; 181 sb_hdr->flags = sb->flags;
223 sb_hdr->image_size = sb->image_size; 182 sb_hdr->image_size = sb->image_size;
224 sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE; 183 sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE;
225 sb_hdr->first_boot_sec_id = sb->sections[0].identifier; 184 sb_hdr->first_boot_sec_id = sb->sections[sb->first_boot_sec].identifier;
226 sb_hdr->nr_keys = g_nr_keys; 185 sb_hdr->nr_keys = g_nr_keys;
227 sb_hdr->nr_sections = sb->nr_sections; 186 sb_hdr->nr_sections = sb->nr_sections;
228 sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE; 187 sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE;
229 sb_hdr->key_dict_off = sb_hdr->header_size + 188 sb_hdr->key_dict_off = sb_hdr->header_size +
230 sb_hdr->sec_hdr_size * sb_hdr->nr_sections; 189 sb_hdr->sec_hdr_size * sb_hdr->nr_sections;
231 sb_hdr->first_boot_tag_off = sb_hdr->key_dict_off + 190 sb_hdr->first_boot_tag_off = sb->sections[sb->first_boot_sec].file_offset - 1;
232 sizeof(struct sb_key_dictionary_entry_t) * sb_hdr->nr_keys / BLOCK_SIZE;
233 generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0)); 191 generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0));
234 generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1)); 192 generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1));
235 /* Version 1.0 has 6 bytes of random padding, 193 /* Version 1.0 has 6 bytes of random padding,
@@ -277,7 +235,11 @@ static void produce_section_tag_cmd(struct sb_section_t *sec,
277 tag->hdr.opcode = SB_INST_TAG; 235 tag->hdr.opcode = SB_INST_TAG;
278 tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0; 236 tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0;
279 tag->identifier = sec->identifier; 237 tag->identifier = sec->identifier;
280 tag->len = sec->sec_size; 238 /* there is a catch here: in the section header at the beginning of the SB
239 * file, we put the *useful* length of the section (without padding) but
240 * the bootloader will not use those and only use the TAG commande which
241 * need to give the *actual* length (with padding) */
242 tag->len = sec->sec_size + sec->pad_size;
281 tag->flags = (sec->is_data ? 0 : SECTION_BOOTABLE) 243 tag->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
282 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0) 244 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0)
283 | sec->other_flags; 245 | sec->other_flags;
@@ -330,15 +292,24 @@ enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename, void *
330 /* init CBC-MACs */ 292 /* init CBC-MACs */
331 for(int i = 0; i < g_nr_keys; i++) 293 for(int i = 0; i < g_nr_keys; i++)
332 memset(cbc_macs[i], 0, 16); 294 memset(cbc_macs[i], 0, 16);
333 295 /* fill gaps */
334 fill_gaps(sb); 296 fill_gaps(sb);
335 if(sb->nr_sections == 0 || sb->sections[0].is_data) 297 /* find first bootable section */
298 sb->first_boot_sec = -1;
299 for(int i = 0; i < sb->nr_sections; i++)
300 if(!sb->sections[i].is_data)
301 {
302 sb->first_boot_sec = i;
303 break;
304 }
305 if(sb->first_boot_sec == -1)
336 { 306 {
337 cprintf(u, true, GREY, "First section of the image is not bootable, I cannot handle that.\n"); 307 cprintf(u, true, GREY, "Image contains no bootable section, I cannot handle that.\n");
338 return SB_ERROR; 308 return SB_ERROR;
339 } 309 }
310 /* compute section offsets */
340 compute_sb_offsets(sb, u, cprintf); 311 compute_sb_offsets(sb, u, cprintf);
341 312 /* generate random real key */
342 generate_random_data(real_key.u.key, 16); 313 generate_random_data(real_key.u.key, 16);
343 314
344 /* global SHA-1 */ 315 /* global SHA-1 */
@@ -406,6 +377,17 @@ enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename, void *
406 printf(YELLOW, "%02x", crypto_iv[j]); 377 printf(YELLOW, "%02x", crypto_iv[j]);
407 printf(OFF, "\n"); 378 printf(OFF, "\n");
408 } 379 }
380 /* the first section might not start right after the header, pad with
381 * random data */
382 unsigned init_gap = (sb->sections[0].file_offset - 1) * BLOCK_SIZE - (buf_p - buf);
383 if(init_gap > 0)
384 {
385 byte *data = xmalloc(init_gap);
386 generate_random_data(data, init_gap);
387 sha_1_update(&file_sha1, data, init_gap);
388 write(data, init_gap);
389 free(data);
390 }
409 /* produce sections data */ 391 /* produce sections data */
410 for(int i = 0; i< sb_hdr.nr_sections; i++) 392 for(int i = 0; i< sb_hdr.nr_sections; i++)
411 { 393 {
@@ -449,6 +431,31 @@ enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename, void *
449 free(data); 431 free(data);
450 } 432 }
451 } 433 }
434 /* pad section with random data or NOP */
435 uint32_t pad_size = sb->sections[i].pad_size;
436 if(sb->sections[i].is_data)
437 {
438 byte *data = xmalloc(pad_size * BLOCK_SIZE);
439 generate_random_data(data, pad_size * BLOCK_SIZE);
440 sha_1_update(&file_sha1, data, pad_size * BLOCK_SIZE);
441 write(data, pad_size * BLOCK_SIZE);
442 free(data);
443 }
444 else
445 {
446 for(unsigned j = 0; j < pad_size; j++)
447 {
448 struct sb_instruction_nop_t cmd;
449 memset(&cmd, 0, sizeof(cmd));
450 cmd.hdr.opcode = SB_INST_NOP;
451 cmd.hdr.checksum = instruction_checksum(&cmd.hdr);
452 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
453 crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
454 &real_key, cur_cbc_mac, &cur_cbc_mac, 1);
455 sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
456 write(&cmd, sizeof(cmd));
457 }
458 }
452 } 459 }
453 /* write file SHA-1 */ 460 /* write file SHA-1 */
454 byte final_sig[32]; 461 byte final_sig[32];
@@ -458,11 +465,11 @@ enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename, void *
458 if(g_nr_keys > 0) 465 if(g_nr_keys > 0)
459 crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1); 466 crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1);
460 write(final_sig, 32); 467 write(final_sig, 32);
461
462 if(buf_p - buf != sb_hdr.image_size * BLOCK_SIZE) 468 if(buf_p - buf != sb_hdr.image_size * BLOCK_SIZE)
463 { 469 {
464 if(g_debug) 470 printf(GREY, "[ERROR][INTERNAL] SB image buffer was not entirely filled !\n");
465 printf(GREY, u, true, "SB image buffer was not entirely filled !\n"); 471 printf(GREY, "[ERROR][INTERNAL] expected %u blocks, got %u\n",
472 (buf_p - buf) / BLOCK_SIZE, sb_hdr.image_size);
466 return SB_ERROR; 473 return SB_ERROR;
467 } 474 }
468 475
diff --git a/utils/imxtools/sbtools/sb.h b/utils/imxtools/sbtools/sb.h
index cf826362de..9ab7fe7aba 100644
--- a/utils/imxtools/sbtools/sb.h
+++ b/utils/imxtools/sbtools/sb.h
@@ -195,7 +195,8 @@ struct sb_section_t
195 struct sb_inst_t *insts; 195 struct sb_inst_t *insts;
196 /* for production use */ 196 /* for production use */
197 uint32_t file_offset; /* in blocks */ 197 uint32_t file_offset; /* in blocks */
198 uint32_t sec_size; /* in blocks */ 198 uint32_t sec_size; /* in blocks, without padding */
199 uint32_t pad_size; /* padding size after the section until next section */
199}; 200};
200 201
201struct sb_file_t 202struct sb_file_t
@@ -217,6 +218,7 @@ struct sb_file_t
217 struct sb_version_t product_ver; 218 struct sb_version_t product_ver;
218 struct sb_version_t component_ver; 219 struct sb_version_t component_ver;
219 /* for production use */ 220 /* for production use */
221 int first_boot_sec; /* index in sections[] */
220 uint32_t image_size; /* in blocks */ 222 uint32_t image_size; /* in blocks */
221}; 223};
222 224