File: | util/nvidia/cbootimage/src/data_layout.c |
Warning: | line 980, column 2 Value stored to 'block_list' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, |
6 | * version 2, as published by the Free Software Foundation. |
7 | * |
8 | * This program is distributed in the hope it will be useful, but WITHOUT |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
11 | * more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | * |
16 | * See file CREDITS for list of people who contributed to this |
17 | * project. |
18 | */ |
19 | |
20 | /* |
21 | * data_layout.c - Code to manage the layout of data in the boot device. |
22 | * |
23 | */ |
24 | |
25 | #include "data_layout.h" |
26 | #include "cbootimage.h" |
27 | #include "crypto.h" |
28 | #include "set.h" |
29 | #include "context.h" |
30 | #include "parse.h" |
31 | #include <sys/param.h> |
32 | |
33 | typedef struct blk_data_rec |
34 | { |
35 | uint32_t blk_number; |
36 | uint32_t pages_used; /* pages always used starting from 0. */ |
37 | uint8_t *data; |
38 | |
39 | /* Pointer to ECC errors? */ |
40 | |
41 | struct blk_data_rec *next; |
42 | } block_data; |
43 | |
44 | /* Function prototypes */ |
45 | static block_data |
46 | *new_block(uint32_t blk_number, uint32_t block_size); |
47 | static block_data |
48 | *find_block(uint32_t blk_number, block_data *block_list); |
49 | static block_data |
50 | *add_block(uint32_t blk_number, block_data **block_list, |
51 | uint32_t block_size); |
52 | static int |
53 | erase_block(build_image_context *context, uint32_t blk_number); |
54 | |
55 | static int |
56 | write_page(build_image_context *context, |
57 | uint32_t blk_number, |
58 | uint32_t page_number, |
59 | uint8_t *data); |
60 | |
61 | static void |
62 | insert_padding(uint8_t *data, uint32_t length); |
63 | |
64 | static void |
65 | write_padding(uint8_t *data, uint32_t length); |
66 | |
67 | static int write_bct(build_image_context *context, |
68 | uint32_t block, |
69 | uint32_t bct_slot); |
70 | |
71 | static void |
72 | set_bl_data(build_image_context *context, |
73 | uint32_t instance, |
74 | uint32_t start_blk, |
75 | uint32_t start_page, |
76 | uint32_t length); |
77 | |
78 | static int write_image(build_image_context *context, file_type image_type); |
79 | |
80 | static void find_new_bct_blk(build_image_context *context); |
81 | static int finish_update(build_image_context *context); |
82 | |
83 | uint32_t |
84 | iceil_log2(uint32_t a, uint32_t b) |
85 | { |
86 | return (a + (1 << b) - 1) >> b; |
87 | } |
88 | |
89 | /* Returns the smallest power of 2 >= a */ |
90 | uint32_t |
91 | ceil_log2(uint32_t a) |
92 | { |
93 | uint32_t result; |
94 | |
95 | result = log2(a); |
96 | if ((1UL << result) < a) |
97 | result++; |
98 | |
99 | return result; |
100 | } |
101 | |
102 | static block_data *new_block(uint32_t blk_number, uint32_t block_size) |
103 | { |
104 | block_data *new_block = malloc(sizeof(block_data)); |
105 | if (new_block == NULL((void*)0)) |
106 | return NULL((void*)0); |
107 | |
108 | new_block->blk_number = blk_number; |
109 | new_block->pages_used = 0; |
110 | new_block->data = malloc(block_size); |
111 | if (new_block->data == NULL((void*)0)) { |
112 | free(new_block); |
113 | return NULL((void*)0); |
114 | } |
115 | new_block->next = NULL((void*)0); |
116 | |
117 | memset(new_block->data, 0, block_size); |
118 | |
119 | return new_block; |
120 | } |
121 | |
122 | block_data *new_block_list(void) |
123 | { |
124 | return NULL((void*)0); |
125 | } |
126 | |
127 | void destroy_block_list(block_data *block_list) |
128 | { |
129 | block_data *next; |
130 | |
131 | while (block_list) { |
132 | next = block_list->next; |
133 | free(block_list->data); |
134 | free(block_list); |
135 | block_list = next; |
136 | } |
137 | } |
138 | |
139 | static block_data *find_block(uint32_t blk_number, block_data *block_list) |
140 | { |
141 | while (block_list) { |
142 | if (block_list->blk_number == blk_number) |
143 | return block_list; |
144 | |
145 | block_list = block_list->next; |
146 | } |
147 | |
148 | return NULL((void*)0); |
149 | } |
150 | |
151 | /* Returns pointer to block after adding it to block_list, if needed. */ |
152 | static block_data *add_block(uint32_t blk_number, |
153 | block_data **block_list, |
154 | uint32_t block_size) |
155 | { |
156 | block_data *block = find_block(blk_number,*block_list); |
157 | block_data *parent; |
158 | |
159 | if (block == NULL((void*)0)) { |
160 | block = new_block(blk_number, block_size); |
161 | if (block == NULL((void*)0)) |
162 | return block; |
163 | |
164 | /* Insert block into the list */ |
165 | if ((*block_list == NULL((void*)0)) || |
166 | (blk_number < (*block_list)->blk_number)) { |
167 | block->next = *block_list; |
168 | *block_list = block; |
169 | } else { |
170 | /* Search for the correct place to insert the block. */ |
171 | parent = *block_list; |
172 | while (parent->next != NULL((void*)0) && |
173 | parent->next->blk_number < blk_number) { |
174 | parent = parent->next; |
175 | } |
176 | |
177 | block->next = parent->next; |
178 | parent->next = block; |
179 | } |
180 | } |
181 | |
182 | return block; |
183 | } |
184 | |
185 | static int |
186 | erase_block(build_image_context *context, uint32_t blk_number) |
187 | { |
188 | block_data *block; |
189 | |
190 | assert(context != NULL)((context != ((void*)0)) ? (void) (0) : __assert_fail ("context != NULL" , "util/nvidia/cbootimage/src/data_layout.c", 190, __extension__ __PRETTY_FUNCTION__)); |
191 | |
192 | block = add_block(blk_number, &(context->memory), context->block_size); |
193 | |
194 | if (block == NULL((void*)0)) |
195 | return -ENOMEM12; |
196 | if (block->data == NULL((void*)0)) |
197 | return -ENOMEM12; |
198 | |
199 | memset(block->data, 0, context->block_size); |
200 | block->pages_used = 0; |
201 | return 0; |
202 | } |
203 | |
204 | static int |
205 | write_page(build_image_context *context, |
206 | uint32_t blk_number, |
207 | uint32_t page_number, |
208 | uint8_t *data) |
209 | { |
210 | block_data *block; |
211 | uint8_t *page_ptr; |
212 | |
213 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 213, __extension__ __PRETTY_FUNCTION__)); |
214 | |
215 | block = add_block(blk_number, &(context->memory), context->block_size); |
216 | |
217 | if (block == NULL((void*)0)) |
218 | return -ENOMEM12; |
219 | if (block->data == NULL((void*)0)) |
220 | return -ENOMEM12; |
221 | if (((page_number + 1) * context->page_size) > context->block_size) { |
222 | printf("Page number outside block; likely config file error.\n"); |
223 | return -ENOMEM12; |
224 | } |
225 | |
226 | if (block->pages_used != page_number) { |
227 | printf("Warning: Writing page in block out of order.\n"); |
228 | printf(" block=%d page=%d\n", blk_number, page_number); |
229 | } |
230 | |
231 | page_ptr = block->data + (page_number * context->page_size); |
232 | memcpy(page_ptr, data, context->page_size); |
233 | if (block->pages_used < (page_number+1)) |
234 | block->pages_used = page_number+1; |
235 | return 0; |
236 | } |
237 | |
238 | static void |
239 | insert_padding(uint8_t *data, uint32_t length) |
240 | { |
241 | uint32_t aes_blks; |
242 | uint32_t remaining; |
243 | |
244 | aes_blks = iceil_log2(length, NVBOOT_AES_BLOCK_SIZE_LOG24); |
245 | remaining = (aes_blks << NVBOOT_AES_BLOCK_SIZE_LOG24) - length; |
246 | |
247 | write_padding(data + length, remaining); |
248 | } |
249 | |
250 | static void |
251 | write_padding(uint8_t *p, uint32_t remaining) |
252 | { |
253 | uint8_t value = 0x80; |
254 | |
255 | while (remaining) { |
256 | *p++ = value; |
257 | remaining--; |
258 | value = 0x00; |
259 | } |
260 | } |
261 | |
262 | static int |
263 | write_bct(build_image_context *context, |
264 | uint32_t block, |
265 | uint32_t bct_slot) |
266 | { |
267 | uint32_t pagesremaining; |
268 | uint32_t page; |
269 | uint32_t pages_per_bct; |
270 | uint8_t *buffer; |
271 | uint8_t *data; |
272 | int err = 0; |
273 | |
274 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 274, __extension__ __PRETTY_FUNCTION__)); |
275 | |
276 | pages_per_bct = iceil_log2(context->bct_size, context->page_size_log2); |
277 | pagesremaining = pages_per_bct; |
278 | page = bct_slot * pages_per_bct; |
279 | |
280 | /* Create a local copy of the BCT data */ |
281 | buffer = malloc(pages_per_bct * context->page_size); |
282 | if (buffer == NULL((void*)0)) |
283 | return -ENOMEM12; |
284 | memset(buffer, 0, pages_per_bct * context->page_size); |
285 | |
286 | memcpy(buffer, context->bct, context->bct_size); |
287 | |
288 | insert_padding(buffer, context->bct_size); |
289 | |
290 | /* Encrypt and compute hash */ |
291 | err = sign_bct(context, buffer); |
292 | if (err != 0) |
293 | goto fail; |
294 | |
295 | /* Write the BCT data to the storage device, picking up ECC errors */ |
296 | data = buffer; |
297 | while (pagesremaining > 0) { |
298 | err = write_page(context, block, page, data); |
299 | if (err != 0) |
300 | goto fail; |
301 | page++; |
302 | pagesremaining--; |
303 | data += context->page_size; |
304 | } |
305 | fail: |
306 | /* Cleanup */ |
307 | free(buffer); |
308 | return err; |
309 | } |
310 | |
311 | #define SET_BL_FIELD(instance, field, value)do { g_soc_config->setbl_param(instance, token_bl_field, & (value), context->bct); } while (0); \ |
312 | do { \ |
313 | g_soc_config->setbl_param(instance, \ |
314 | token_bl_##field, \ |
315 | &(value), \ |
316 | context->bct); \ |
317 | } while (0); |
318 | |
319 | #define GET_BL_FIELD(instance, field, ptr)g_soc_config->getbl_param(instance, token_bl_field, ptr, context ->bct); \ |
320 | g_soc_config->getbl_param(instance, \ |
321 | token_bl_##field, \ |
322 | ptr, \ |
323 | context->bct); |
324 | |
325 | #define COPY_BL_FIELD(from, to, field)do { uint32_t v; g_soc_config->getbl_param(from, token_bl_field , &v, context->bct);; do { g_soc_config->setbl_param (to, token_bl_field, &(v), context->bct); } while (0); ; } while (0); \ |
326 | do { \ |
327 | uint32_t v; \ |
328 | GET_BL_FIELD(from, field, &v)g_soc_config->getbl_param(from, token_bl_field, &v, context ->bct);; \ |
329 | SET_BL_FIELD(to, field, v)do { g_soc_config->setbl_param(to, token_bl_field, &(v ), context->bct); } while (0);; \ |
330 | } while (0); |
331 | |
332 | #define SET_MTS_FIELD(instance, field, value)do { g_soc_config->set_mts_info(context, instance, token_mts_info_field , value); } while (0); \ |
333 | do { \ |
334 | g_soc_config->set_mts_info(context, \ |
335 | instance, \ |
336 | token_mts_info_##field, \ |
337 | value); \ |
338 | } while (0); |
339 | |
340 | #define GET_MTS_FIELD(instance, field, ptr)g_soc_config->get_mts_info(context, instance, token_mts_info_field , ptr); \ |
341 | g_soc_config->get_mts_info(context, \ |
342 | instance, \ |
343 | token_mts_info_##field, \ |
344 | ptr); |
345 | |
346 | #define COPY_MTS_FIELD(from, to, field)do { uint32_t v; g_soc_config->get_mts_info(context, from, token_mts_info_field, &v);; do { g_soc_config->set_mts_info (context, to, token_mts_info_field, v); } while (0);; } while (0); \ |
347 | do { \ |
348 | uint32_t v; \ |
349 | GET_MTS_FIELD(from, field, &v)g_soc_config->get_mts_info(context, from, token_mts_info_field , &v);; \ |
350 | SET_MTS_FIELD(to, field, v)do { g_soc_config->set_mts_info(context, to, token_mts_info_field , v); } while (0);; \ |
351 | } while (0); |
352 | |
353 | #define SET_FIELD(is_bl, instance, field, value)do { if (is_bl) { do { g_soc_config->setbl_param(instance, token_bl_field, &(value), context->bct); } while (0); ; } else { do { g_soc_config->set_mts_info(context, instance , token_mts_info_field, value); } while (0);; } } while (0);\ |
354 | do { \ |
355 | if (is_bl) { \ |
356 | SET_BL_FIELD(instance, field,value)do { g_soc_config->setbl_param(instance, token_bl_field, & (value), context->bct); } while (0);; \ |
357 | } \ |
358 | else { \ |
359 | SET_MTS_FIELD(instance, field, value)do { g_soc_config->set_mts_info(context, instance, token_mts_info_field , value); } while (0);; \ |
360 | } \ |
361 | } while (0); |
362 | |
363 | #define GET_FIELD(is_bl, instance, field, ptr)do { if (is_bl) { g_soc_config->getbl_param(instance, token_bl_field , ptr, context->bct);; } else { g_soc_config->get_mts_info (context, instance, token_mts_info_field, ptr);; } } while (0 ); \ |
364 | do { \ |
365 | if (is_bl) { \ |
366 | GET_BL_FIELD(instance, field, ptr)g_soc_config->getbl_param(instance, token_bl_field, ptr, context ->bct);; \ |
367 | } \ |
368 | else { \ |
369 | GET_MTS_FIELD(instance, field, ptr)g_soc_config->get_mts_info(context, instance, token_mts_info_field , ptr);; \ |
370 | } \ |
371 | } while (0); |
372 | |
373 | #define COPY_FIELD(is_bl, from, to, field)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (from, token_bl_field, &v, context->bct);; do { g_soc_config ->setbl_param(to, token_bl_field, &(v), context->bct ); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config ->get_mts_info(context, from, token_mts_info_field, &v );; do { g_soc_config->set_mts_info(context, to, token_mts_info_field , v); } while (0);; } while (0);; } } while (0); \ |
374 | do { \ |
375 | if (is_bl) { \ |
376 | COPY_BL_FIELD(from, to, field)do { uint32_t v; g_soc_config->getbl_param(from, token_bl_field , &v, context->bct);; do { g_soc_config->setbl_param (to, token_bl_field, &(v), context->bct); } while (0); ; } while (0);; \ |
377 | } \ |
378 | else { \ |
379 | COPY_MTS_FIELD(from, to, field)do { uint32_t v; g_soc_config->get_mts_info(context, from, token_mts_info_field, &v);; do { g_soc_config->set_mts_info (context, to, token_mts_info_field, v); } while (0);; } while (0);; \ |
380 | } \ |
381 | } while (0); |
382 | |
383 | static void |
384 | set_bl_data(build_image_context *context, |
385 | uint32_t instance, |
386 | uint32_t start_blk, |
387 | uint32_t start_page, |
388 | uint32_t length) |
389 | { |
390 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 390, __extension__ __PRETTY_FUNCTION__)); |
391 | |
392 | SET_BL_FIELD(instance, version, context->version)do { g_soc_config->setbl_param(instance, token_bl_version, &(context->version), context->bct); } while (0);; |
393 | SET_BL_FIELD(instance, start_blk, start_blk)do { g_soc_config->setbl_param(instance, token_bl_start_blk , &(start_blk), context->bct); } while (0);; |
394 | SET_BL_FIELD(instance, start_page, start_page)do { g_soc_config->setbl_param(instance, token_bl_start_page , &(start_page), context->bct); } while (0);; |
395 | SET_BL_FIELD(instance, length, length)do { g_soc_config->setbl_param(instance, token_bl_length, & (length), context->bct); } while (0);; |
396 | SET_BL_FIELD(instance, load_addr, context->newbl_load_addr)do { g_soc_config->setbl_param(instance, token_bl_load_addr , &(context->newbl_load_addr), context->bct); } while (0);; |
397 | SET_BL_FIELD(instance, entry_point, context->newbl_entry_point)do { g_soc_config->setbl_param(instance, token_bl_entry_point , &(context->newbl_entry_point), context->bct); } while (0);; |
398 | SET_BL_FIELD(instance, attribute, context->newbl_attr)do { g_soc_config->setbl_param(instance, token_bl_attribute , &(context->newbl_attr), context->bct); } while (0 );; |
399 | } |
400 | |
401 | static void |
402 | set_mts_data(build_image_context *context, |
403 | uint32_t instance, |
404 | uint32_t start_blk, |
405 | uint32_t start_page, |
406 | uint32_t length) |
407 | { |
408 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 408, __extension__ __PRETTY_FUNCTION__)); |
409 | |
410 | SET_MTS_FIELD(instance, version, context->version)do { g_soc_config->set_mts_info(context, instance, token_mts_info_version , context->version); } while (0);; |
411 | SET_MTS_FIELD(instance, start_blk, start_blk)do { g_soc_config->set_mts_info(context, instance, token_mts_info_start_blk , start_blk); } while (0);; |
412 | SET_MTS_FIELD(instance, start_page, start_page)do { g_soc_config->set_mts_info(context, instance, token_mts_info_start_page , start_page); } while (0);; |
413 | SET_MTS_FIELD(instance, length, length)do { g_soc_config->set_mts_info(context, instance, token_mts_info_length , length); } while (0);; |
414 | SET_MTS_FIELD(instance, load_addr, context->mts_load_addr)do { g_soc_config->set_mts_info(context, instance, token_mts_info_load_addr , context->mts_load_addr); } while (0);; |
415 | SET_MTS_FIELD(instance, entry_point, context->mts_entry_point)do { g_soc_config->set_mts_info(context, instance, token_mts_info_entry_point , context->mts_entry_point); } while (0);; |
416 | SET_MTS_FIELD(instance, attribute, context->mts_attr)do { g_soc_config->set_mts_info(context, instance, token_mts_info_attribute , context->mts_attr); } while (0);; |
417 | } |
418 | |
419 | #define SET_DATA(is_bl, context, instance, start_blk, start_page, length)do { if (is_bl) set_bl_data(context, instance, start_blk, start_page , length); else set_mts_data(context, instance, start_blk, start_page , length); } while (0); \ |
420 | do { \ |
421 | if (is_bl) \ |
422 | set_bl_data(context, instance, start_blk, start_page, length); \ |
423 | else \ |
424 | set_mts_data(context, instance, start_blk, start_page, length); \ |
425 | } while (0); |
426 | |
427 | /* |
428 | * Load the image then update it with the information from config file. |
429 | * In the interest of expediency, all image's allocated from bottom to top |
430 | * start at page 0 of a block, and all image's allocated from top to bottom |
431 | * end at the end of a block. |
432 | * |
433 | * @param context The main context pointer |
434 | * @param image_type The image type. Can be file_type_bl or file_type_mts |
435 | * only right now |
436 | * @return 0 for success |
437 | */ |
438 | static int |
439 | write_image(build_image_context *context, file_type image_type) |
440 | { |
441 | uint32_t i, j; |
442 | uint32_t image_instance; |
443 | uint32_t image_move_count = 0; |
444 | uint32_t image_move_remaining; |
445 | uint32_t current_blk; |
446 | uint32_t current_page; |
447 | uint32_t pages_in_image; |
448 | uint32_t image_used; |
449 | uint8_t *image_storage; /* Holds the image after reading */ |
450 | uint8_t *buffer; /* Holds the image for writing */ |
451 | uint8_t *src; /* Scans through the image during writing */ |
452 | uint32_t image_actual_size; /* In bytes */ |
453 | uint32_t pagesremaining; |
454 | uint32_t virtual_blk; |
455 | uint32_t pages_per_blk; |
456 | uint32_t image_version; |
457 | uint8_t *hash_buffer; |
458 | uint32_t hash_size; |
459 | uint32_t image_max; |
460 | parse_token token; |
461 | int err = 0, is_bl; |
462 | |
463 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 463, __extension__ __PRETTY_FUNCTION__)); |
464 | |
465 | /* Only support bootloader and mts image right now */ |
466 | if (image_type == file_type_bl) { |
467 | is_bl = 1; |
468 | } |
469 | else if (image_type == file_type_mts) { |
470 | is_bl = 0; |
471 | } |
472 | else { |
473 | printf("Not supported image type!\n"); |
474 | return -EINVAL22; |
475 | } |
476 | |
477 | pages_per_blk = 1 << (context->block_size_log2 |
478 | - context->page_size_log2); |
479 | |
480 | g_soc_config->get_value(token_hash_size, |
481 | &hash_size, context->bct); |
482 | token = is_bl ? token_bootloaders_max : token_mts_max; |
483 | g_soc_config->get_value(token, &image_max, context->bct); |
484 | |
485 | hash_buffer = calloc(1, hash_size); |
486 | if (hash_buffer == NULL((void*)0)) |
487 | return -ENOMEM12; |
488 | |
489 | if (enable_debug) { |
490 | printf("writing %s\n", is_bl ? "bootloader" : "mts image"); |
491 | printf(" redundancy = %d\n", context->redundancy); |
492 | } |
493 | |
494 | /* Make room for the image in the BCT. */ |
495 | |
496 | /* Determine how many to move. |
497 | * Note that this code will count Mts[0] only if there is already |
498 | * a mts in the device. |
499 | */ |
500 | GET_FIELD(is_bl, 0, version, &image_version)do { if (is_bl) { g_soc_config->getbl_param(0, token_bl_version , &image_version, context->bct);; } else { g_soc_config ->get_mts_info(context, 0, token_mts_info_version, &image_version );; } } while (0);; |
501 | token = is_bl ? token_bootloader_used : token_mts_used; |
502 | g_soc_config->get_value(token, &image_used, context->bct); |
503 | for (image_instance = 0; image_instance < image_used; image_instance++) { |
504 | uint32_t tmp; |
505 | GET_FIELD(is_bl, image_instance, version, &tmp)do { if (is_bl) { g_soc_config->getbl_param(image_instance , token_bl_version, &tmp, context->bct);; } else { g_soc_config ->get_mts_info(context, image_instance, token_mts_info_version , &tmp);; } } while (0);; |
506 | if (tmp == image_version) |
507 | image_move_count++; |
508 | } |
509 | |
510 | /* Adjust the move count, if needed, to avoid overflowing the mts table. |
511 | * This can happen due to too much redundancy. |
512 | */ |
513 | image_move_count = MIN(image_move_count, image_max - context->redundancy)(((image_move_count)<(image_max - context->redundancy)) ?(image_move_count):(image_max - context->redundancy)); |
514 | |
515 | /* Move the mts entries down. */ |
516 | image_move_remaining = image_move_count; |
517 | while (image_move_remaining > 0) { |
518 | uint32_t inst_from = image_move_remaining - 1; |
519 | uint32_t inst_to = |
520 | image_move_remaining + context->redundancy - 1; |
521 | |
522 | COPY_FIELD(is_bl, inst_from, inst_to, version)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_version, &v, context->bct);; do { g_soc_config->setbl_param(inst_to, token_bl_version, & (v), context->bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config->get_mts_info(context, inst_from , token_mts_info_version, &v);; do { g_soc_config->set_mts_info (context, inst_to, token_mts_info_version, v); } while (0);; } while (0);; } } while (0);; |
523 | COPY_FIELD(is_bl, inst_from, inst_to, start_blk)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_start_blk, &v, context->bct);; do { g_soc_config->setbl_param(inst_to, token_bl_start_blk, & (v), context->bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config->get_mts_info(context, inst_from , token_mts_info_start_blk, &v);; do { g_soc_config->set_mts_info (context, inst_to, token_mts_info_start_blk, v); } while (0); ; } while (0);; } } while (0);; |
524 | COPY_FIELD(is_bl, inst_from, inst_to, start_page)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_start_page, &v, context->bct);; do { g_soc_config->setbl_param(inst_to, token_bl_start_page, &(v), context->bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config->get_mts_info(context, inst_from , token_mts_info_start_page, &v);; do { g_soc_config-> set_mts_info(context, inst_to, token_mts_info_start_page, v); } while (0);; } while (0);; } } while (0);; |
525 | COPY_FIELD(is_bl, inst_from, inst_to, length)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_length, &v, context->bct);; do { g_soc_config ->setbl_param(inst_to, token_bl_length, &(v), context-> bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config ->get_mts_info(context, inst_from, token_mts_info_length, & v);; do { g_soc_config->set_mts_info(context, inst_to, token_mts_info_length , v); } while (0);; } while (0);; } } while (0);; |
526 | COPY_FIELD(is_bl, inst_from, inst_to, load_addr)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_load_addr, &v, context->bct);; do { g_soc_config->setbl_param(inst_to, token_bl_load_addr, & (v), context->bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config->get_mts_info(context, inst_from , token_mts_info_load_addr, &v);; do { g_soc_config->set_mts_info (context, inst_to, token_mts_info_load_addr, v); } while (0); ; } while (0);; } } while (0);; |
527 | COPY_FIELD(is_bl, inst_from, inst_to, entry_point)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_entry_point, &v, context->bct);; do { g_soc_config->setbl_param(inst_to, token_bl_entry_point , &(v), context->bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config->get_mts_info(context, inst_from , token_mts_info_entry_point, &v);; do { g_soc_config-> set_mts_info(context, inst_to, token_mts_info_entry_point, v) ; } while (0);; } while (0);; } } while (0);; |
528 | COPY_FIELD(is_bl, inst_from, inst_to, attribute)do { if (is_bl) { do { uint32_t v; g_soc_config->getbl_param (inst_from, token_bl_attribute, &v, context->bct);; do { g_soc_config->setbl_param(inst_to, token_bl_attribute, & (v), context->bct); } while (0);; } while (0);; } else { do { uint32_t v; g_soc_config->get_mts_info(context, inst_from , token_mts_info_attribute, &v);; do { g_soc_config->set_mts_info (context, inst_to, token_mts_info_attribute, v); } while (0); ; } while (0);; } } while (0);; |
529 | |
530 | if (is_bl) { |
531 | g_soc_config->getbl_param(inst_from, |
532 | token_bl_crypto_hash, |
533 | (uint32_t*)hash_buffer, |
534 | context->bct); |
535 | g_soc_config->setbl_param(inst_to, |
536 | token_bl_crypto_hash, |
537 | (uint32_t*)hash_buffer, |
538 | context->bct); |
539 | } |
540 | |
541 | image_move_remaining--; |
542 | } |
543 | |
544 | /* Read the image into memory. */ |
545 | if (read_from_image( |
546 | is_bl ? context->newbl_filename : context->mts_filename, |
547 | 0, |
548 | is_bl ? MAX_BOOTLOADER_SIZE(16 * 1024 * 1024) : MAX_MTS_SIZE(4 * 1024 * 1024), |
549 | &image_storage, |
550 | &image_actual_size, |
551 | image_type) == 1) { |
552 | printf("Error reading image %s.\n", |
553 | is_bl ? context->newbl_filename : context->mts_filename); |
554 | exit(1); |
555 | } |
556 | |
557 | pages_in_image = iceil_log2(image_actual_size, context->page_size_log2); |
558 | |
559 | current_blk = context->next_bct_blk; |
560 | current_page = 0; |
561 | for (image_instance = 0; image_instance < context->redundancy; |
562 | image_instance++) { |
563 | |
564 | pagesremaining = pages_in_image; |
565 | /* Advance to the next block if needed. */ |
566 | if (current_page > 0) { |
567 | current_blk++; |
568 | current_page = 0; |
569 | } |
570 | |
571 | virtual_blk = 0; |
572 | |
573 | while (pagesremaining > 0) { |
574 | /* Update the bad block table with relative |
575 | * bad blocks. |
576 | */ |
577 | if (virtual_blk == 0) { |
578 | SET_DATA(is_bl,do { if (is_bl) set_bl_data(context, image_instance, current_blk , current_page, image_actual_size); else set_mts_data(context , image_instance, current_blk, current_page, image_actual_size ); } while (0); |
579 | context,do { if (is_bl) set_bl_data(context, image_instance, current_blk , current_page, image_actual_size); else set_mts_data(context , image_instance, current_blk, current_page, image_actual_size ); } while (0); |
580 | image_instance,do { if (is_bl) set_bl_data(context, image_instance, current_blk , current_page, image_actual_size); else set_mts_data(context , image_instance, current_blk, current_page, image_actual_size ); } while (0); |
581 | current_blk,do { if (is_bl) set_bl_data(context, image_instance, current_blk , current_page, image_actual_size); else set_mts_data(context , image_instance, current_blk, current_page, image_actual_size ); } while (0); |
582 | current_page,do { if (is_bl) set_bl_data(context, image_instance, current_blk , current_page, image_actual_size); else set_mts_data(context , image_instance, current_blk, current_page, image_actual_size ); } while (0); |
583 | image_actual_size)do { if (is_bl) set_bl_data(context, image_instance, current_blk , current_page, image_actual_size); else set_mts_data(context , image_instance, current_blk, current_page, image_actual_size ); } while (0);; |
584 | } |
585 | |
586 | if (pagesremaining > pages_per_blk) { |
587 | current_blk++; |
588 | virtual_blk++; |
589 | pagesremaining -= pages_per_blk; |
590 | } else { |
591 | current_page = pagesremaining; |
592 | pagesremaining = 0; |
593 | } |
594 | } |
595 | } |
596 | |
597 | /* Scan forwards to write each copy. */ |
598 | for (image_instance = 0; image_instance < context->redundancy; |
599 | image_instance++) { |
600 | |
601 | /* Create a local copy of the BCT data */ |
602 | buffer = malloc(pages_in_image * context->page_size); |
603 | if (buffer == NULL((void*)0)) |
604 | return -ENOMEM12; |
605 | |
606 | memset(buffer, 0, pages_in_image * context->page_size); |
607 | memcpy(buffer, image_storage, image_actual_size); |
608 | |
609 | insert_padding(buffer, image_actual_size); |
610 | |
611 | pagesremaining = pages_in_image; |
612 | |
613 | if (is_bl) { |
614 | GET_BL_FIELD(image_instance, start_blk, ¤t_blk)g_soc_config->getbl_param(image_instance, token_bl_start_blk , ¤t_blk, context->bct);; |
615 | GET_BL_FIELD(image_instance, start_page, ¤t_page)g_soc_config->getbl_param(image_instance, token_bl_start_page , ¤t_page, context->bct);; |
616 | |
617 | /* Encrypt and compute hash */ |
618 | sign_data_block(buffer, |
619 | image_actual_size, |
620 | hash_buffer); |
621 | g_soc_config->setbl_param(image_instance, |
622 | token_bl_crypto_hash, |
623 | (uint32_t*)hash_buffer, |
624 | context->bct); |
625 | } |
626 | |
627 | GET_FIELD(is_bl, image_instance, start_blk, ¤t_blk)do { if (is_bl) { g_soc_config->getbl_param(image_instance , token_bl_start_blk, ¤t_blk, context->bct);; } else { g_soc_config->get_mts_info(context, image_instance, token_mts_info_start_blk , ¤t_blk);; } } while (0);; |
628 | GET_FIELD(is_bl, image_instance, start_page, ¤t_page)do { if (is_bl) { g_soc_config->getbl_param(image_instance , token_bl_start_page, ¤t_page, context->bct);; } else { g_soc_config->get_mts_info(context, image_instance , token_mts_info_start_page, ¤t_page);; } } while ( 0);; |
629 | |
630 | /* Write the BCT data to the storage device, |
631 | * picking up ECC errors |
632 | */ |
633 | src = buffer; |
634 | |
635 | /* Write pages as we go. */ |
636 | virtual_blk = 0; |
637 | while (pagesremaining) { |
638 | if (current_page == 0) { |
639 | /* Erase the block before writing into it. */ |
640 | erase_block(context, current_blk); |
641 | } |
642 | |
643 | err = write_page(context, |
644 | current_blk, current_page, src); |
645 | if (err != 0) |
646 | goto fail; |
647 | pagesremaining--; |
648 | src += context->page_size; |
649 | current_page++; |
650 | if (current_page >= pages_per_blk) { |
651 | current_page = 0; |
652 | current_blk++; |
653 | virtual_blk++; |
654 | } |
655 | context->last_blk = current_blk; |
656 | } |
657 | context->next_bct_blk = context->last_blk + 1; |
658 | free(buffer); |
659 | } |
660 | |
661 | image_used = context->redundancy + image_move_count; |
662 | token = is_bl ? token_bootloader_used : token_mts_used; |
663 | g_soc_config->set_value(token, &image_used, context->bct); |
664 | |
665 | if (enable_debug) { |
666 | for (i = 0; i < image_max; i++) { |
667 | uint32_t version; |
668 | uint32_t start_blk; |
669 | uint32_t start_page; |
670 | uint32_t length; |
671 | uint32_t load_addr; |
672 | uint32_t entry_point; |
673 | |
674 | GET_FIELD(is_bl, i, version, &version)do { if (is_bl) { g_soc_config->getbl_param(i, token_bl_version , &version, context->bct);; } else { g_soc_config-> get_mts_info(context, i, token_mts_info_version, &version );; } } while (0);; |
675 | GET_FIELD(is_bl, i, start_blk, &start_blk)do { if (is_bl) { g_soc_config->getbl_param(i, token_bl_start_blk , &start_blk, context->bct);; } else { g_soc_config-> get_mts_info(context, i, token_mts_info_start_blk, &start_blk );; } } while (0);; |
676 | GET_FIELD(is_bl, i, start_page, &start_page)do { if (is_bl) { g_soc_config->getbl_param(i, token_bl_start_page , &start_page, context->bct);; } else { g_soc_config-> get_mts_info(context, i, token_mts_info_start_page, &start_page );; } } while (0);; |
677 | GET_FIELD(is_bl, i, length, &length)do { if (is_bl) { g_soc_config->getbl_param(i, token_bl_length , &length, context->bct);; } else { g_soc_config->get_mts_info (context, i, token_mts_info_length, &length);; } } while ( 0);; |
678 | GET_FIELD(is_bl, i, load_addr, &load_addr)do { if (is_bl) { g_soc_config->getbl_param(i, token_bl_load_addr , &load_addr, context->bct);; } else { g_soc_config-> get_mts_info(context, i, token_mts_info_load_addr, &load_addr );; } } while (0);; |
679 | GET_FIELD(is_bl, i, entry_point, &entry_point)do { if (is_bl) { g_soc_config->getbl_param(i, token_bl_entry_point , &entry_point, context->bct);; } else { g_soc_config-> get_mts_info(context, i, token_mts_info_entry_point, &entry_point );; } } while (0);; |
680 | |
681 | printf("%s%s[%d]: %d %04d %04d %04d 0x%08x 0x%08x\n", |
682 | i < image_used ? " " : "**", |
683 | is_bl ? "BL" : "MTS", |
684 | i, |
685 | version, |
686 | start_blk, |
687 | start_page, |
688 | length, |
689 | load_addr, |
690 | entry_point); |
691 | if (is_bl) { |
692 | g_soc_config->getbl_param(i, |
693 | token_bl_crypto_hash, |
694 | (uint32_t*)hash_buffer, |
695 | context->bct); |
696 | for (j = 0; j < hash_size / 4; j++) { |
697 | printf("%08x", |
698 | *((uint32_t*)(hash_buffer + 4*j))); |
699 | } |
700 | printf("\n"); |
701 | } |
702 | } |
703 | } |
704 | free(image_storage); |
705 | free(hash_buffer); |
706 | return 0; |
707 | |
708 | fail: |
709 | /* Cleanup. */ |
710 | free(buffer); |
711 | free(image_storage); |
712 | free(hash_buffer); |
713 | printf("Write image failed, error: %d.\n", err); |
714 | return err; |
715 | } |
716 | |
717 | void |
718 | update_context(struct build_image_context_rec *context) |
719 | { |
720 | g_soc_config->get_value(token_partition_size, |
721 | &context->partition_size, |
722 | context->bct); |
723 | g_soc_config->get_value(token_page_size_log2, |
724 | &context->page_size_log2, |
725 | context->bct); |
726 | g_soc_config->get_value(token_block_size_log2, |
727 | &context->block_size_log2, |
728 | context->bct); |
729 | g_soc_config->get_value(token_odm_data, |
730 | &context->odm_data, |
731 | context->bct); |
732 | |
733 | context->page_size = 1 << context->page_size_log2; |
734 | context->block_size = 1 << context->block_size_log2; |
735 | context->pages_per_blk = 1 << (context->block_size_log2 - |
736 | context->page_size_log2); |
737 | } |
738 | |
739 | /* |
740 | * Allocate and initialize the memory for bct data. |
741 | * |
742 | * @param context The main context pointer |
743 | * @return 0 for success |
744 | */ |
745 | int |
746 | init_bct(struct build_image_context_rec *context) |
747 | { |
748 | /* Allocate space for the bct. */ |
749 | context->bct = malloc(context->bct_size); |
750 | |
751 | if (context->bct == NULL((void*)0)) |
752 | return -ENOMEM12; |
753 | |
754 | memset(context->bct, 0, context->bct_size); |
755 | context->bct_init = 1; |
756 | |
757 | return 0; |
758 | } |
759 | |
760 | /* |
761 | * Read the bct data from given file to allocated memory. |
762 | * Assign the global parse interface to corresponding hardware interface |
763 | * according to the boot data version in bct file. |
764 | * |
765 | * @param context The main context pointer |
766 | * @return 0 for success |
767 | */ |
768 | int |
769 | read_bct_file(struct build_image_context_rec *context) |
770 | { |
771 | uint8_t *bct_storage; /* Holds the Bl after reading */ |
772 | uint32_t bct_actual_size; /* In bytes */ |
773 | file_type bct_filetype = file_type_bct; |
774 | int err = 0; |
775 | |
776 | if (read_from_image(context->bct_filename, |
777 | 0, |
778 | NVBOOT_CONFIG_TABLE_SIZE_MAX(10 * 1024), |
779 | &bct_storage, |
780 | &bct_actual_size, |
781 | bct_filetype) == 1) { |
782 | printf("Error reading bct file %s.\n", context->bct_filename); |
783 | exit(1); |
784 | } |
785 | |
786 | context->bct_size = bct_actual_size; |
787 | if (context->bct_init != 1) |
788 | err = init_bct(context); |
789 | if (err != 0) { |
790 | printf("Context initialization failed. Aborting.\n"); |
791 | return err; |
792 | } |
793 | memcpy(context->bct, bct_storage, context->bct_size); |
794 | free(bct_storage); |
795 | |
796 | if (!data_is_valid_bct(context)) |
797 | return -ENODATA61; |
798 | |
799 | return err; |
800 | } |
801 | |
802 | /* |
803 | * Update the next_bct_blk and make it point to the next |
804 | * new blank block according to bct_copy given. |
805 | * |
806 | * @param context The main context pointer |
807 | */ |
808 | static void |
809 | find_new_bct_blk(build_image_context *context) |
810 | { |
811 | uint32_t max_bct_search_blks; |
812 | |
813 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 813, __extension__ __PRETTY_FUNCTION__)); |
814 | |
815 | g_soc_config->get_value(token_max_bct_search_blks, |
816 | &max_bct_search_blks, context->bct); |
817 | |
818 | if (context->next_bct_blk > max_bct_search_blks) { |
819 | printf("Error: Unable to locate a journal block.\n"); |
820 | exit(1); |
821 | } |
822 | context->next_bct_blk++; |
823 | } |
824 | |
825 | /* |
826 | * Initialization before bct and bootloader update. |
827 | * Find the new blank block and erase it. |
828 | * |
829 | * @param context The main context pointer |
830 | * @return 0 for success |
831 | */ |
832 | int |
833 | begin_update(build_image_context *context) |
834 | { |
835 | uint32_t hash_size; |
836 | uint32_t reserved_size; |
837 | uint32_t reserved_offset; |
838 | int err = 0; |
839 | int i; |
840 | |
841 | assert(context)((context) ? (void) (0) : __assert_fail ("context", "util/nvidia/cbootimage/src/data_layout.c" , 841, __extension__ __PRETTY_FUNCTION__)); |
842 | |
843 | if (context->page_size_log2 < NVBOOT_AES_BLOCK_SIZE_LOG24) { |
844 | printf("Page size is too small; likely config file error\n"); |
845 | return 1; |
846 | } |
847 | |
848 | /* Ensure that the BCT block & page data is current. */ |
849 | if (enable_debug) { |
850 | uint32_t block_size_log2; |
851 | uint32_t page_size_log2; |
852 | |
853 | g_soc_config->get_value(token_block_size_log2, |
854 | &block_size_log2, context->bct); |
855 | g_soc_config->get_value(token_page_size_log2, |
856 | &page_size_log2, context->bct); |
857 | |
858 | printf("begin_update(): bct data: b=%d p=%d\n", |
859 | block_size_log2, page_size_log2); |
860 | } |
861 | |
862 | g_soc_config->set_value(token_boot_data_version, |
863 | &(context->boot_data_version), context->bct); |
864 | g_soc_config->get_value(token_hash_size, |
865 | &hash_size, context->bct); |
866 | g_soc_config->get_value(token_reserved_size, |
867 | &reserved_size, context->bct); |
868 | g_soc_config->get_value(token_reserved_offset, |
869 | &reserved_offset, context->bct); |
870 | /* Set the odm data */ |
871 | g_soc_config->set_value(token_odm_data, |
872 | &(context->odm_data), context->bct); |
873 | |
874 | /* Initialize the bad block table field. */ |
875 | g_soc_config->init_bad_block_table(context); |
876 | /* Fill the reserved data w/the padding pattern. */ |
877 | write_padding(context->bct + reserved_offset, reserved_size); |
878 | |
879 | /* Create the pad before the BCT starting at block 1 */ |
880 | for (i = 0; i < context->pre_bct_pad_blocks; i++) { |
881 | find_new_bct_blk(context); |
882 | err = erase_block(context, i); |
883 | if (err != 0) |
884 | goto fail; |
885 | } |
886 | /* Find the next bct block starting at block pre_bct_pad_blocks. */ |
887 | for (i = 0; i < context->bct_copy; i++) { |
888 | find_new_bct_blk(context); |
889 | err = erase_block(context, i + context->pre_bct_pad_blocks); |
890 | if (err != 0) |
891 | goto fail; |
892 | } |
893 | return 0; |
894 | fail: |
895 | printf("Erase block failed, error: %d.\n", err); |
896 | return err; |
897 | } |
898 | |
899 | /* |
900 | * Write the BCT(s) starting at slot 0 of block context->pre_bct_pad_blocks. |
901 | * |
902 | * @param context The main context pointer |
903 | * @return 0 for success |
904 | */ |
905 | static int |
906 | finish_update(build_image_context *context) |
907 | { |
908 | int err = 0; |
909 | int i; |
910 | |
911 | for (i = 0; i < context->bct_copy; i++) { |
912 | err = write_bct(context, i + context->pre_bct_pad_blocks, 0); |
913 | if (err != 0) |
914 | goto fail; |
915 | } |
916 | |
917 | return 0; |
918 | fail: |
919 | printf("Write BCT failed, error: %d.\n", err); |
920 | return err; |
921 | } |
922 | |
923 | /* |
924 | * For now, ignore end state. |
925 | */ |
926 | int |
927 | update_bl(build_image_context *context) |
928 | { |
929 | if (enable_debug) |
930 | printf("**update_bl()\n"); |
931 | |
932 | if (begin_update(context) != 0) |
933 | return 1; |
934 | if (write_image(context, file_type_bl) != 0) |
935 | return 1; |
936 | if (finish_update(context) != 0) |
937 | return 1; |
938 | return 0; |
939 | } |
940 | |
941 | int |
942 | update_mts_image(build_image_context *context) |
943 | { |
944 | if (enable_debug) |
945 | printf("**update_mts()\n"); |
946 | |
947 | if (begin_update(context) != 0) |
948 | return 1; |
949 | if (write_image(context, file_type_mts) != 0) |
950 | return 1; |
951 | if (finish_update(context) != 0) |
952 | return 1; |
953 | return 0; |
954 | } |
955 | |
956 | /* |
957 | * To write the current image: |
958 | * Loop over all blocks in the block data list: |
959 | * Write out the data of real blocks. |
960 | * Write out 0's for unused blocks. |
961 | * Stop on the last used page of the last used block. |
962 | * |
963 | * @param context The main context pointer |
964 | * @return 0 for success |
965 | */ |
966 | int |
967 | write_block_raw(build_image_context *context) |
968 | { |
969 | block_data *block_list; |
970 | block_data *block; |
971 | uint32_t blk_number; |
972 | uint32_t last_blk; |
973 | uint32_t pages_to_write; |
974 | uint8_t *data; |
975 | uint8_t *empty_blk = NULL((void*)0); |
976 | |
977 | assert(context != NULL)((context != ((void*)0)) ? (void) (0) : __assert_fail ("context != NULL" , "util/nvidia/cbootimage/src/data_layout.c", 977, __extension__ __PRETTY_FUNCTION__)); |
978 | assert(context->memory)((context->memory) ? (void) (0) : __assert_fail ("context->memory" , "util/nvidia/cbootimage/src/data_layout.c", 978, __extension__ __PRETTY_FUNCTION__)); |
979 | |
980 | block_list = context->memory; |
Value stored to 'block_list' is never read | |
981 | |
982 | /* Compute the end of the image. */ |
983 | block_list = context->memory; |
984 | while (block_list->next) |
985 | block_list = block_list->next; |
986 | |
987 | last_blk = block_list->blk_number; |
988 | |
989 | /* Loop over all the storage from block 0, page 0 to |
990 | *last_blk, Lastpage |
991 | */ |
992 | for (blk_number = 0; blk_number <= last_blk; blk_number++) { |
993 | block = find_block(blk_number, context->memory); |
994 | if (block) { |
995 | pages_to_write = (blk_number == last_blk) ? |
996 | block->pages_used : |
997 | context->pages_per_blk; |
998 | data = block->data; |
999 | } else { |
1000 | /* Allocate empty_blk if needed. */ |
1001 | if (empty_blk == NULL((void*)0)) { |
1002 | empty_blk = malloc(context->block_size); |
1003 | if (!empty_blk) |
1004 | return -ENOMEM12; |
1005 | memset(empty_blk, 0, context->block_size); |
1006 | } |
1007 | pages_to_write = context->pages_per_blk; |
1008 | data = empty_blk; |
1009 | } |
1010 | /* Write the data */ |
1011 | { |
1012 | size_t bytes = pages_to_write * context->page_size; |
1013 | |
1014 | if (fwrite(data, 1, bytes, context->raw_file) != bytes) { |
1015 | if (empty_blk) free(empty_blk); |
1016 | return -1; |
1017 | } |
1018 | } |
1019 | } |
1020 | |
1021 | if (empty_blk) free(empty_blk); |
1022 | return 0; |
1023 | } |
1024 | |
1025 | int write_data_block(FILE *fp, uint32_t offset, uint32_t size, uint8_t *buffer) |
1026 | { |
1027 | if (fseek(fp, offset, 0)) |
1028 | return -1; |
1029 | |
1030 | return fwrite(buffer, 1, size, fp); |
1031 | } |
1032 | |
1033 | int data_is_valid_bct(build_image_context *context) |
1034 | { |
1035 | /* get proper soc_config pointer by polling each supported chip */ |
1036 | if (if_bct_is_t20_get_soc_config(context, &g_soc_config)) |
1037 | return 1; |
1038 | if (if_bct_is_t30_get_soc_config(context, &g_soc_config)) |
1039 | return 1; |
1040 | if (if_bct_is_t114_get_soc_config(context, &g_soc_config)) |
1041 | return 1; |
1042 | if (if_bct_is_t124_get_soc_config(context, &g_soc_config)) |
1043 | return 1; |
1044 | if (if_bct_is_t132_get_soc_config(context, &g_soc_config)) |
1045 | return 1; |
1046 | if (if_bct_is_t210_get_soc_config(context, &g_soc_config)) |
1047 | return 1; |
1048 | |
1049 | return 0; |
1050 | } |
1051 | |
1052 | int get_bct_size_from_image(build_image_context *context) |
1053 | { |
1054 | uint8_t buffer[NVBOOT_CONFIG_TABLE_SIZE_MIN4080]; |
1055 | uint32_t bct_size = 0; |
1056 | FILE *fp; |
1057 | |
1058 | fp = fopen(context->input_image_filename, "r"); |
1059 | if (!fp) |
1060 | return -ENODATA61; |
1061 | |
1062 | if (fread(buffer, 1, NVBOOT_CONFIG_TABLE_SIZE_MIN4080, fp) != NVBOOT_CONFIG_TABLE_SIZE_MIN4080) { |
1063 | fclose(fp); |
1064 | return -ENODATA61; |
1065 | } |
1066 | |
1067 | context->bct = buffer; |
1068 | if (data_is_valid_bct(context) && g_soc_config->get_bct_size) |
1069 | bct_size = g_soc_config->get_bct_size(); |
1070 | |
1071 | fclose(fp); |
1072 | context->bct = 0; |
1073 | return bct_size; |
1074 | } |
1075 | |
1076 | int resign_bl(build_image_context *context) |
1077 | { |
1078 | int ret; |
1079 | uint8_t *buffer, *image; |
1080 | uint32_t image_instance = 0; /* support only one instance */ |
1081 | uint32_t image_actual_size; /* In bytes */ |
1082 | uint32_t bl_length; |
1083 | uint32_t pages_in_image; |
1084 | uint32_t blk_size, page_size, current_blk, current_page; |
1085 | uint32_t offset; |
1086 | |
1087 | /* read in bl from image */ |
1088 | g_soc_config->get_value(token_block_size, &blk_size, context->bct); |
1089 | g_soc_config->get_value(token_page_size, &page_size, context->bct); |
1090 | |
1091 | GET_BL_FIELD(image_instance, start_blk, ¤t_blk)g_soc_config->getbl_param(image_instance, token_bl_start_blk , ¤t_blk, context->bct);; |
1092 | GET_BL_FIELD(image_instance, start_page, ¤t_page)g_soc_config->getbl_param(image_instance, token_bl_start_page , ¤t_page, context->bct);; |
1093 | GET_BL_FIELD(image_instance, length, &bl_length)g_soc_config->getbl_param(image_instance, token_bl_length, &bl_length, context->bct);; |
1094 | |
1095 | offset = current_blk * blk_size + |
1096 | current_page * page_size; |
1097 | |
1098 | if (read_from_image(context->input_image_filename, |
1099 | offset, bl_length, |
1100 | &image, &image_actual_size, file_type_bin)) { |
1101 | printf("Error reading image file %s.\n", |
1102 | context->input_image_filename); |
1103 | return -ENOMEM12; |
1104 | } |
1105 | |
1106 | pages_in_image = ICEIL(image_actual_size, page_size)(((image_actual_size) + (page_size) - 1)/(page_size)); |
1107 | |
1108 | /* Create a local copy of the bl */ |
1109 | if ((buffer = malloc(pages_in_image * page_size)) == NULL((void*)0)) { |
1110 | ret = -ENOMEM12; |
1111 | goto fail; |
1112 | } |
1113 | |
1114 | memset(buffer, 0, pages_in_image * page_size); |
1115 | memcpy(buffer, image, image_actual_size); |
1116 | |
1117 | insert_padding(buffer, image_actual_size); |
1118 | |
1119 | /* sign bl */ |
1120 | ret = sign_bl(context, buffer, image_actual_size, image_instance); |
1121 | free (buffer); |
1122 | fail: |
1123 | free (image); |
1124 | return ret; |
1125 | } |