drivers/ddr: Fix possible out of bounds error

This is a theoretical possible out of bounds error in DDR driver. Adding
check before using array index. Also change some runtime conditions to
pre-compiling conditions.

Signed-off-by: York Sun <yorksun@freescale.com>
Reviewed-by: York Sun <yorksun@freescale.com>
This commit is contained in:
York Sun 2014-04-01 14:20:49 -07:00
parent 2ee6c52e22
commit 349689b802
3 changed files with 66 additions and 60 deletions

View File

@ -507,8 +507,8 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
wrrec_mclk = picos_to_mclk(common_dimm->twr_ps); wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4); acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4);
wrtord_mclk = max(2, picos_to_mclk(2500)); wrtord_mclk = max(2, picos_to_mclk(2500));
if (wrrec_mclk > 24) if ((wrrec_mclk < 1) || (wrrec_mclk > 24))
printf("Error: WRREC doesn't support more than 24 clocks\n"); printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
else else
wrrec_mclk = wrrec_table[wrrec_mclk - 1]; wrrec_mclk = wrrec_table[wrrec_mclk - 1];
#else #else
@ -516,8 +516,8 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
wrrec_mclk = picos_to_mclk(common_dimm->twr_ps); wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps); acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps);
wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps); wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps);
if (wrrec_mclk > 16) if ((wrrec_mclk < 1) || (wrrec_mclk > 16))
printf("Error: WRREC doesn't support more than 16 clocks\n"); printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
else else
wrrec_mclk = wrrec_table[wrrec_mclk - 1]; wrrec_mclk = wrrec_table[wrrec_mclk - 1];
#endif #endif

View File

@ -220,6 +220,11 @@ const char * step_to_string(unsigned int step) {
if ((1 << s) != step) if ((1 << s) != step)
return step_string_tbl[7]; return step_string_tbl[7];
if (s >= ARRAY_SIZE(step_string_tbl)) {
printf("Error for the step in %s\n", __func__);
s = 0;
}
return step_string_tbl[s]; return step_string_tbl[s];
} }
@ -520,6 +525,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
/* STEP 5: Assign addresses to chip selects */ /* STEP 5: Assign addresses to chip selects */
check_interleaving_options(pinfo); check_interleaving_options(pinfo);
total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust);
debug("Total mem %llu assigned\n", total_mem);
case STEP_COMPUTE_REGS: case STEP_COMPUTE_REGS:
/* STEP 6: compute controller register values */ /* STEP 6: compute controller register values */

View File

@ -525,67 +525,66 @@ unsigned int populate_memctl_options(int all_dimms_registered,
defined(CONFIG_SYS_FSL_DDR2) || \ defined(CONFIG_SYS_FSL_DDR2) || \
defined(CONFIG_SYS_FSL_DDR4) defined(CONFIG_SYS_FSL_DDR4)
/* Chip select options. */ /* Chip select options. */
if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) { #if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
switch (pdimm[0].n_ranks) { switch (pdimm[0].n_ranks) {
case 1: case 1:
pdodt = single_S; pdodt = single_S;
break; break;
case 2: case 2:
pdodt = single_D; pdodt = single_D;
break; break;
case 4: case 4:
pdodt = single_Q; pdodt = single_Q;
break; break;
} }
} else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) { #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
switch (pdimm[0].n_ranks) { switch (pdimm[0].n_ranks) {
#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE #ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
case 4: case 4:
pdodt = single_Q; pdodt = single_Q;
if (pdimm[1].n_ranks) if (pdimm[1].n_ranks)
printf("Error: Quad- and Dual-rank DIMMs " printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n");
"cannot be used together\n"); break;
break;
#endif #endif
case 2:
switch (pdimm[1].n_ranks) {
case 2: case 2:
switch (pdimm[1].n_ranks) { pdodt = dual_DD;
case 2:
pdodt = dual_DD;
break;
case 1:
pdodt = dual_DS;
break;
case 0:
pdodt = dual_D0;
break;
}
break; break;
case 1: case 1:
switch (pdimm[1].n_ranks) { pdodt = dual_DS;
case 2:
pdodt = dual_SD;
break;
case 1:
pdodt = dual_SS;
break;
case 0:
pdodt = dual_S0;
break;
}
break; break;
case 0: case 0:
switch (pdimm[1].n_ranks) { pdodt = dual_D0;
case 2:
pdodt = dual_0D;
break;
case 1:
pdodt = dual_0S;
break;
}
break; break;
} }
break;
case 1:
switch (pdimm[1].n_ranks) {
case 2:
pdodt = dual_SD;
break;
case 1:
pdodt = dual_SS;
break;
case 0:
pdodt = dual_S0;
break;
}
break;
case 0:
switch (pdimm[1].n_ranks) {
case 2:
pdodt = dual_0D;
break;
case 1:
pdodt = dual_0S;
break;
}
break;
} }
#endif #endif /* CONFIG_DIMM_SLOTS_PER_CTLR */
#endif /* CONFIG_SYS_FSL_DDR2, 3, 4 */
/* Pick chip-select local options. */ /* Pick chip-select local options. */
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
@ -847,8 +846,7 @@ unsigned int populate_memctl_options(int all_dimms_registered,
popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING; popts->memctl_interleaving_mode = FSL_DDR_256B_INTERLEAVING;
popts->memctl_interleaving = 1; popts->memctl_interleaving = 1;
debug("256 Byte interleaving\n"); debug("256 Byte interleaving\n");
goto done; #else
#endif
/* /*
* test null first. if CONFIG_HWCONFIG is not defined * test null first. if CONFIG_HWCONFIG is not defined
* hwconfig_arg_cmp returns non-zero * hwconfig_arg_cmp returns non-zero
@ -930,8 +928,9 @@ unsigned int populate_memctl_options(int all_dimms_registered,
popts->memctl_interleaving = 0; popts->memctl_interleaving = 0;
printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
} }
#endif /* CONFIG_SYS_FSL_DDR_INTLV_256B */
done: done:
#endif #endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */
if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
/* test null first. if CONFIG_HWCONFIG is not defined, /* test null first. if CONFIG_HWCONFIG is not defined,
@ -1106,10 +1105,11 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo)
case FSL_DDR_PAGE_INTERLEAVING: case FSL_DDR_PAGE_INTERLEAVING:
case FSL_DDR_BANK_INTERLEAVING: case FSL_DDR_BANK_INTERLEAVING:
case FSL_DDR_SUPERBANK_INTERLEAVING: case FSL_DDR_SUPERBANK_INTERLEAVING:
if (3 == CONFIG_NUM_DDR_CONTROLLERS) #if (3 == CONFIG_NUM_DDR_CONTROLLERS)
k = 2; k = 2;
else #else
k = CONFIG_NUM_DDR_CONTROLLERS; k = CONFIG_NUM_DDR_CONTROLLERS;
#endif
break; break;
case FSL_DDR_3WAY_1KB_INTERLEAVING: case FSL_DDR_3WAY_1KB_INTERLEAVING:
case FSL_DDR_3WAY_4KB_INTERLEAVING: case FSL_DDR_3WAY_4KB_INTERLEAVING: