blob: 70c952233f950a1479bcf304d710ff62f10ae01c [file] [log] [blame]
Peer Chen8d782ee2011-01-18 21:34:18 -05001/**
2 * Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
3 *
4 * See file CREDITS for list of people who contributed to this
5 * project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23/*
24 * set.c - State setting support for the cbootimage tool
25 */
26
27#include "set.h"
28#include "cbootimage.h"
29#include "crypto.h"
30#include "data_layout.h"
31
32/*
33 * Function prototypes
34 *
35 * ParseXXX() parses XXX in the input
36 * SetXXX() sets state based on the parsing results but does not perform
37 * any parsing of its own
38 * A ParseXXX() function may call other parse functions and set functions.
39 * A SetXXX() function may not call any parseing functions.
40 */
41
Peer Chen7557d9b2011-02-24 09:29:23 -080042#define CASE_DEVICE_VALUE(prefix, id) \
43 case token_##id: \
44 (void)context->bctlib.setdev_param(index, \
45 nvbct_lib_id_##prefix##_##id, \
46 value, \
47 context->bct); \
48 break
49
Peer Chen3a834ed2011-03-04 09:30:05 -080050#define CASE_SDRAM_VALUE(id) \
51 case token_##id: \
52 (void)context->bctlib.set_sdram_params(index, \
53 nvbct_lib_id_sdram_##id, \
54 value, \
55 context->bct); \
56 break
57
Peer Chen7557d9b2011-02-24 09:29:23 -080058#define DEFAULT() \
59 default: \
60 printf("Unexpected token %d at line %d\n", \
61 token, __LINE__); \
62 return 1
63
Peer Chen8d782ee2011-01-18 21:34:18 -050064int
65read_from_image(char *filename,
66 u_int32_t page_size,
67 u_int8_t **image,
68 u_int32_t *storage_size,
69 u_int32_t *actual_size,
70 file_type f_type)
71{
72 int result = 0; /* 0 = success, 1 = failure */
73 FILE *fp;
74 struct stat stats;
75
76 fp = fopen(filename, "r");
77 if (fp == NULL) {
78 result = 1;
79 return result;
80 }
81
82 if (stat(filename, &stats) != 0) {
83 printf("Error: Unable to query info on bootloader path %s\n",
Peer Chen7557d9b2011-02-24 09:29:23 -080084 filename);
Peer Chen8d782ee2011-01-18 21:34:18 -050085 result = 1;
86 goto cleanup;
87 }
88
89 *actual_size = (u_int32_t)stats.st_size;
90 *storage_size =
91 (u_int32_t)(ICEIL(stats.st_size, page_size) * page_size);
92
93 if (f_type == file_type_bl) {
94 if (stats.st_size > MAX_BOOTLOADER_SIZE) {
95 printf("Error: Bootloader file %s is too large.\n",
96 filename);
97 result = 1;
98 goto cleanup;
99 }
100
101
102 /* Workaround for a bug in release 1.0 of the boot rom.
103 * Any BL whose padded size is an integral multiple of page size
104 * has its length extended by 16 bytes to bump it to end on a
105 * partial page.
106 */
107 if ((*storage_size - *actual_size) < 16) {
108 *actual_size += 16;
109 *storage_size += page_size;
110 }
111 }
112 *image = malloc(*storage_size);
113 if (*image == NULL) {
114 result = 1;
115 goto cleanup;
116 }
117
118 memset(*image, 0, *storage_size);
119
120 if (fread(*image, 1, (size_t)stats.st_size, fp) != stats.st_size) {
121 result = 1;
122 goto cleanup;
123 }
124
125cleanup:
126 fclose(fp);
127 return result;
128}
129
130
131/*
132 * set_bootloader(): Processes commands to set a bootloader.
133 */
134int
135set_bootloader(build_image_context *context,
136 char *filename,
137 u_int32_t load_addr,
138 u_int32_t entry_point)
139{
140 context->newbl_filename = filename;
141 context->newbl_load_addr = load_addr;
142 context->newbl_entry_point = entry_point;
143 return update_bl(context);
144}
145
146#define DEFAULT() \
147 default: \
148 printf("Unexpected token %d at line %d\n", \
149 token, __LINE__); \
150 return 1
151
152/*
153 * context_set_array(): Sets an array value.
154 */
155int
156context_set_array(build_image_context *context,
157 u_int32_t index,
158 parse_token token,
159 u_int32_t value)
160{
161 assert(context != NULL);
162 assert(context->bct != NULL);
163
164 switch (token) {
165 case token_attribute:
166 (void)context->bctlib.setbl_param(index,
167 nvbct_lib_id_bl_attribute,
168 &value,
169 context->bct);
170 break;
171
Peer Chen7557d9b2011-02-24 09:29:23 -0800172 case token_dev_type:
173 (void)context->bctlib.setdev_param(index,
174 nvbct_lib_id_dev_type,
175 value,
176 context->bct);
177 break;
178
179 DEFAULT();
Peer Chen8d782ee2011-01-18 21:34:18 -0500180 }
181 return 0;
182}
183
184/*
185 * context_set_value(): General handler for setting values in config files.
186 */
187int context_set_value(build_image_context *context,
188 parse_token token,
189 u_int32_t value)
190{
191 assert(context != NULL);
192
193 switch (token) {
194 case token_attribute:
195 context->newbl_attr = value;
196 break;
197
Peer Chen7557d9b2011-02-24 09:29:23 -0800198 case token_block_size:
199 context->block_size = value;
200 context->block_size_log2 = log2(value);
201
202 if (context->memory != NULL) {
203 printf("Error: Too late to change block size.\n");
204 return 1;
205 }
206
207 if (value != (u_int32_t)(1 << context->block_size_log2)) {
208 printf("Error: Block size must be a power of 2.\n");
209 return 1;
210 }
211 context->pages_per_blk= 1 << (context->block_size_log2-
212 context->page_size_log2);
213 SET_VALUE(block_size_log2, context->block_size_log2);
214 break;
215
216 case token_partition_size:
217 if (context->memory != NULL) {
218 printf("Error: Too late to change block size.\n");
219 return 1;
220 }
221
222 context->partition_size= value;
223 SET_VALUE(partition_size, value);
224 break;
225
Peer Chen8d782ee2011-01-18 21:34:18 -0500226 case token_page_size:
227 context->page_size = value;
Peer Chen7557d9b2011-02-24 09:29:23 -0800228 context->page_size_log2 = log2(value);
229 context->pages_per_blk= 1 << (context->block_size_log2-
230 context->page_size_log2);
231
232 SET_VALUE(page_size_log2, context->page_size_log2);
Peer Chen8d782ee2011-01-18 21:34:18 -0500233 break;
234 case token_redundancy:
235 context->redundancy = value;
236 break;
237
238 case token_version:
239 context->version = value;
240 break;
241
242 DEFAULT();
243 }
244
245 return 0;
246}
247
248int
249set_addon_filename(build_image_context *context,
250 char *filename,
251 int index)
252{
253
254 struct addon_item_rec **current;
255 int i;
256
257 current = &(context->addon_tbl.addon_item_list);
258
259 for(i = 0; i <= index; i++) {
260 if (*current == NULL) {
261 (*current) = malloc(sizeof(struct addon_item_rec));
262 if (*current == NULL)
263 return -ENOMEM;
264 memset((*current), 0, sizeof(struct addon_item_rec));
265 memcpy((*current)->addon_filename,
266 filename, MAX_BUFFER);
267 (*current)->item_index = index;
268 (*current)->next = NULL;
269 context->addon_tbl.addon_item_no++;
270 } else if ((*current)->item_index == index) {
271 memcpy((*current)->addon_filename,
272 filename, MAX_BUFFER);
273 } else
274 current = &((*current)->next);
275 }
276 return 0;
277}
278
279int set_addon_attr(build_image_context *context,
280 u_int32_t file_attr,
281 int index)
282{
283 struct addon_item_rec **current;
284 int i;
285
286 current = &(context->addon_tbl.addon_item_list);
287
288 for(i = 0; i <= index; i++) {
289 if (*current == NULL) {
290 (*current) = malloc(sizeof(struct addon_item_rec));
291 if (*current == NULL)
292 return -ENOMEM;
293 memset((*current), 0, sizeof(struct addon_item_rec));
294 (*current)->item.attribute= file_attr;
295 (*current)->item_index = index;
296 (*current)->next = NULL;
297 context->addon_tbl.addon_item_no++;
298 } else if ((*current)->item_index == index) {
299 (*current)->item.attribute= file_attr;
300 } else
301 current = &((*current)->next);
302 }
303 return 0;
304}
305
306int set_unique_name(build_image_context *context, char *uname, int index)
307{
308 struct addon_item_rec **current;
309 int i;
310
311 current = &(context->addon_tbl.addon_item_list);
312
313 for(i = 0; i <= index; i++) {
314 if (*current == NULL) {
315 (*current) = malloc(sizeof(struct addon_item_rec));
316 if (*current == NULL)
317 return -ENOMEM;
318 memset((*current), 0, sizeof(struct addon_item_rec));
319 memcpy((*current)->item.unique_name, uname, 4);
320 (*current)->item_index = index;
321 (*current)->next = NULL;
322 context->addon_tbl.addon_item_no++;
323 } else if ((*current)->item_index == index) {
324 memcpy((*current)->item.unique_name, uname, 4);
325 } else
326 current = &((*current)->next);
327 }
328 return 0;
329}
330
331int
332set_other_field(build_image_context *context,
333 char *other_str,
334 int other,
335 int index)
336{
337 struct addon_item_rec **current;
338 int i;
339
340 current = &(context->addon_tbl.addon_item_list);
341
342 for(i = 0; i <= index; i++) {
343 if (*current == NULL) {
344 (*current) = malloc(sizeof(struct addon_item_rec));
345 if (*current == NULL)
346 return -ENOMEM;
347 memset((*current), 0, sizeof(struct addon_item_rec));
348 if (other_str == NULL)
349 (*current)->item.reserve[0] = other;
350 else
351 memcpy((*current)->item.reserve,
352 other_str, 16);
353 (*current)->item_index = index;
354 (*current)->next = NULL;
355 context->addon_tbl.addon_item_no++;
356 } else if ((*current)->item_index == index) {
357 if (other_str == NULL)
358 (*current)->item.reserve[0] = other;
359 else
360 memcpy((*current)->item.reserve,
361 other_str, 16);
362 } else
363 current = &((*current)->next);
364 }
365 return 0;
366
367}
368
Peer Chen7557d9b2011-02-24 09:29:23 -0800369static void
370update_num_param_sets(build_image_context *context, u_int32_t index)
371{
372 u_int32_t num_params;
373
374 GET_VALUE(num_param_sets, &num_params);
375 num_params = NV_MAX(num_params, index + 1);
376 SET_VALUE(num_param_sets, num_params);
377}
378
379/*
Peer Chen053d5782011-03-03 10:12:58 -0800380 * set_nand_param(): Processes commands to set Nand parameters.
381 */
382int
383set_nand_param(build_image_context *context,
384 u_int32_t index,
385 parse_token token,
386 u_int32_t value)
387{
388 assert(context != NULL);
389 assert(context->bct != NULL);
390
391 update_num_param_sets(context, index);
392
393 switch (token) {
394 CASE_DEVICE_VALUE(nand, clock_divider);
395 CASE_DEVICE_VALUE(nand, nand_timing);
396 CASE_DEVICE_VALUE(nand, nand_timing2);
397 CASE_DEVICE_VALUE(nand, block_size_log2);
398 CASE_DEVICE_VALUE(nand, page_size_log2);
399 DEFAULT();
400 }
401
402 return 0;
403}
404
405/*
Peer Chen7557d9b2011-02-24 09:29:23 -0800406 * set_sdmmc_param(): Processes commands to set MoviNand parameters.
407 */
408int
409set_sdmmc_param(build_image_context *context,
410 u_int32_t index,
411 parse_token token,
412 u_int32_t value)
413{
414 assert(context != NULL);
415 assert(context->bct != NULL);
416
417 update_num_param_sets(context, index);
418
419 switch (token) {
420 CASE_DEVICE_VALUE(sdmmc, clock_divider);
421 CASE_DEVICE_VALUE(sdmmc, data_width);
422 CASE_DEVICE_VALUE(sdmmc, max_power_class_supported);
423 DEFAULT();
424 }
425
426 return 0;
427}
428
429/*
430 * set_spiflash_param(): Processes commands to set SpiFlash parameters.
431 */
432int
433set_spiflash_param(build_image_context *context,
434 u_int32_t index,
435 parse_token token,
436 u_int32_t value)
437{
438 assert(context != NULL);
439 assert(context->bct != NULL);
440
441 update_num_param_sets(context, index);
442
443 switch (token) {
444 CASE_DEVICE_VALUE(spiflash, clock_divider);
445 CASE_DEVICE_VALUE(spiflash, clock_source);
446 CASE_DEVICE_VALUE(spiflash, read_command_type_fast);
447 DEFAULT();
448 }
449
450 return 0;
451}
Peer Chen3a834ed2011-03-04 09:30:05 -0800452
453int
454set_sdram_param(build_image_context *context,
455 u_int32_t index,
456 parse_token token,
457 u_int32_t value)
458{
459 u_int32_t num_sdram_sets;
460
461 assert(context != NULL);
462 assert(context->bct != NULL);
463
464 // Update the number of SDRAM parameter sets.
465 GET_VALUE(num_sdram_sets, &num_sdram_sets);
466 num_sdram_sets = NV_MAX(num_sdram_sets, index + 1);
467 SET_VALUE(num_sdram_sets, num_sdram_sets);
468
469 switch (token) {
470
471 CASE_SDRAM_VALUE(memory_type);
472 CASE_SDRAM_VALUE(pllm_charge_pump_setup_ctrl);
473 CASE_SDRAM_VALUE(pllm_loop_filter_setup_ctrl);
474 CASE_SDRAM_VALUE(pllm_input_divider);
475 CASE_SDRAM_VALUE(pllm_feedback_divider);
476 CASE_SDRAM_VALUE(pllm_post_divider);
477 CASE_SDRAM_VALUE(pllm_stable_time);
478 CASE_SDRAM_VALUE(emc_clock_divider);
479 CASE_SDRAM_VALUE(emc_auto_cal_interval);
480 CASE_SDRAM_VALUE(emc_auto_cal_config);
481 CASE_SDRAM_VALUE(emc_auto_cal_wait);
482 CASE_SDRAM_VALUE(emc_pin_program_wait);
483 CASE_SDRAM_VALUE(emc_rc);
484 CASE_SDRAM_VALUE(emc_rfc);
485 CASE_SDRAM_VALUE(emc_ras);
486 CASE_SDRAM_VALUE(emc_rp);
487 CASE_SDRAM_VALUE(emc_r2w);
488 CASE_SDRAM_VALUE(emc_w2r);
489 CASE_SDRAM_VALUE(emc_r2p);
490 CASE_SDRAM_VALUE(emc_w2p);
491 CASE_SDRAM_VALUE(emc_rd_rcd);
492 CASE_SDRAM_VALUE(emc_wr_rcd);
493 CASE_SDRAM_VALUE(emc_rrd);
494 CASE_SDRAM_VALUE(emc_rext);
495 CASE_SDRAM_VALUE(emc_wdv);
496 CASE_SDRAM_VALUE(emc_quse);
497 CASE_SDRAM_VALUE(emc_qrst);
498 CASE_SDRAM_VALUE(emc_qsafe);
499 CASE_SDRAM_VALUE(emc_rdv);
500 CASE_SDRAM_VALUE(emc_refresh);
501 CASE_SDRAM_VALUE(emc_burst_refresh_num);
502 CASE_SDRAM_VALUE(emc_pdex2wr);
503 CASE_SDRAM_VALUE(emc_pdex2rd);
504 CASE_SDRAM_VALUE(emc_pchg2pden);
505 CASE_SDRAM_VALUE(emc_act2pden);
506 CASE_SDRAM_VALUE(emc_ar2pden);
507 CASE_SDRAM_VALUE(emc_rw2pden);
508 CASE_SDRAM_VALUE(emc_txsr);
509 CASE_SDRAM_VALUE(emc_tcke);
510 CASE_SDRAM_VALUE(emc_tfaw);
511 CASE_SDRAM_VALUE(emc_trpab);
512 CASE_SDRAM_VALUE(emc_tclkstable);
513 CASE_SDRAM_VALUE(emc_tclkstop);
514 CASE_SDRAM_VALUE(emc_trefbw);
515 CASE_SDRAM_VALUE(emc_quse_extra);
516 CASE_SDRAM_VALUE(emc_fbio_cfg1);
517 CASE_SDRAM_VALUE(emc_fbio_dqsib_dly);
518 CASE_SDRAM_VALUE(emc_fbio_dqsib_dly_msb);
519 CASE_SDRAM_VALUE(emc_fbio_quse_dly);
520 CASE_SDRAM_VALUE(emc_fbio_quse_dly_msb);
521 CASE_SDRAM_VALUE(emc_fbio_cfg5);
522 CASE_SDRAM_VALUE(emc_fbio_cfg6);
523 CASE_SDRAM_VALUE(emc_fbio_spare);
524 CASE_SDRAM_VALUE(emc_mrs);
525 CASE_SDRAM_VALUE(emc_emrs);
526 CASE_SDRAM_VALUE(emc_mrw1);
527 CASE_SDRAM_VALUE(emc_mrw2);
528 CASE_SDRAM_VALUE(emc_mrw3);
529 CASE_SDRAM_VALUE(emc_mrw_reset_command);
530 CASE_SDRAM_VALUE(emc_mrw_reset_ninit_wait);
531 CASE_SDRAM_VALUE(emc_adr_cfg);
532 CASE_SDRAM_VALUE(emc_adr_cfg1);
533 CASE_SDRAM_VALUE(mc_emem_Cfg);
534 CASE_SDRAM_VALUE(mc_lowlatency_config);
535 CASE_SDRAM_VALUE(emc_cfg);
536 CASE_SDRAM_VALUE(emc_cfg2);
537 CASE_SDRAM_VALUE(emc_dbg);
538 CASE_SDRAM_VALUE(ahb_arbitration_xbar_ctrl);
539 CASE_SDRAM_VALUE(emc_cfg_dig_dll);
540 CASE_SDRAM_VALUE(emc_dll_xform_dqs);
541 CASE_SDRAM_VALUE(emc_dll_xform_quse);
542 CASE_SDRAM_VALUE(warm_boot_wait);
543 CASE_SDRAM_VALUE(emc_ctt_term_ctrl);
544 CASE_SDRAM_VALUE(emc_odt_write);
545 CASE_SDRAM_VALUE(emc_odt_read);
546 CASE_SDRAM_VALUE(emc_zcal_ref_cnt);
547 CASE_SDRAM_VALUE(emc_zcal_wait_cnt);
548 CASE_SDRAM_VALUE(emc_zcal_mrw_cmd);
549 CASE_SDRAM_VALUE(emc_mrs_reset_dll);
550 CASE_SDRAM_VALUE(emc_mrw_zq_init_dev0);
551 CASE_SDRAM_VALUE(emc_mrw_zq_init_dev1);
552 CASE_SDRAM_VALUE(emc_mrw_zq_init_wait);
553 CASE_SDRAM_VALUE(emc_mrs_reset_dll_wait);
554 CASE_SDRAM_VALUE(emc_emrs_emr2);
555 CASE_SDRAM_VALUE(emc_emrs_emr3);
556 CASE_SDRAM_VALUE(emc_emrs_ddr2_dll_enable);
557 CASE_SDRAM_VALUE(emc_mrs_ddr2_dll_reset);
558 CASE_SDRAM_VALUE(emc_emrs_ddr2_ocd_calib);
559 CASE_SDRAM_VALUE(emc_ddr2_wait);
560 CASE_SDRAM_VALUE(emc_cfg_clktrim0);
561 CASE_SDRAM_VALUE(emc_cfg_clktrim1);
562 CASE_SDRAM_VALUE(emc_cfg_clktrim2);
563 CASE_SDRAM_VALUE(pmc_ddr_pwr);
564 CASE_SDRAM_VALUE(apb_misc_gp_xm2cfga_pad_ctrl);
565 CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgc_pad_ctrl);
566 CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgc_pad_ctrl2);
567 CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgd_pad_ctrl);
568 CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgd_pad_ctrl2);
569 CASE_SDRAM_VALUE(apb_misc_gp_xm2clkcfg_Pad_ctrl);
570 CASE_SDRAM_VALUE(apb_misc_gp_xm2comp_pad_ctrl);
571 CASE_SDRAM_VALUE(apb_misc_gp_xm2vttgen_pad_ctrl);
572
573 DEFAULT();
574 }
575 return 0;
576}