summaryrefslogtreecommitdiff
path: root/drivers/ddr/fsl
diff options
context:
space:
mode:
authorYork Sun <yorksun@freescale.com>2014-04-01 14:20:49 -0700
committerYork Sun <yorksun@freescale.com>2014-04-22 17:58:49 -0700
commit349689b8021f0a7d7923099bd8bbe5eab117d4fa (patch)
treeeafb5be0e0ad33d739baa1ed885a7cdc9f412561 /drivers/ddr/fsl
parent2ee6c52e229e1d0d1e78c3efbc67bc8bb868fb25 (diff)
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>
Diffstat (limited to 'drivers/ddr/fsl')
-rw-r--r--drivers/ddr/fsl/ctrl_regs.c8
-rw-r--r--drivers/ddr/fsl/main.c6
-rw-r--r--drivers/ddr/fsl/options.c108
3 files changed, 64 insertions, 58 deletions
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index d01eea05f3..78e82bba3d 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -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);
acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4);
wrtord_mclk = max(2, picos_to_mclk(2500));
- if (wrrec_mclk > 24)
- printf("Error: WRREC doesn't support more than 24 clocks\n");
+ if ((wrrec_mclk < 1) || (wrrec_mclk > 24))
+ printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
else
wrrec_mclk = wrrec_table[wrrec_mclk - 1];
#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);
acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps);
wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps);
- if (wrrec_mclk > 16)
- printf("Error: WRREC doesn't support more than 16 clocks\n");
+ if ((wrrec_mclk < 1) || (wrrec_mclk > 16))
+ printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk);
else
wrrec_mclk = wrrec_table[wrrec_mclk - 1];
#endif
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index f95704f3df..5e001fcb99 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -220,6 +220,11 @@ const char * step_to_string(unsigned int step) {
if ((1 << s) != step)
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];
}
@@ -520,6 +525,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
/* STEP 5: Assign addresses to chip selects */
check_interleaving_options(pinfo);
total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust);
+ debug("Total mem %llu assigned\n", total_mem);
case STEP_COMPUTE_REGS:
/* STEP 6: compute controller register values */
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index bf0d1da7cf..5986e1a0b9 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -525,67 +525,66 @@ unsigned int populate_memctl_options(int all_dimms_registered,
defined(CONFIG_SYS_FSL_DDR2) || \
defined(CONFIG_SYS_FSL_DDR4)
/* Chip select options. */
- if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
- switch (pdimm[0].n_ranks) {
- case 1:
- pdodt = single_S;
- break;
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+ switch (pdimm[0].n_ranks) {
+ case 1:
+ pdodt = single_S;
+ break;
+ case 2:
+ pdodt = single_D;
+ break;
+ case 4:
+ pdodt = single_Q;
+ break;
+ }
+#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+ switch (pdimm[0].n_ranks) {
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ case 4:
+ pdodt = single_Q;
+ if (pdimm[1].n_ranks)
+ printf("Error: Quad- and Dual-rank DIMMs cannot be used together\n");
+ break;
+#endif
+ case 2:
+ switch (pdimm[1].n_ranks) {
case 2:
- pdodt = single_D;
+ pdodt = dual_DD;
break;
- case 4:
- pdodt = single_Q;
+ case 1:
+ pdodt = dual_DS;
break;
- }
- } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
- switch (pdimm[0].n_ranks) {
-#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
- case 4:
- pdodt = single_Q;
- if (pdimm[1].n_ranks)
- printf("Error: Quad- and Dual-rank DIMMs "
- "cannot be used together\n");
+ case 0:
+ pdodt = dual_D0;
break;
-#endif
+ }
+ break;
+ case 1:
+ switch (pdimm[1].n_ranks) {
case 2:
- switch (pdimm[1].n_ranks) {
- case 2:
- pdodt = dual_DD;
- break;
- case 1:
- pdodt = dual_DS;
- break;
- case 0:
- pdodt = dual_D0;
- break;
- }
+ pdodt = dual_SD;
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;
- }
+ pdodt = dual_SS;
break;
case 0:
- switch (pdimm[1].n_ranks) {
- case 2:
- pdodt = dual_0D;
- break;
- case 1:
- pdodt = dual_0S;
- break;
- }
+ 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. */
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 = 1;
debug("256 Byte interleaving\n");
- goto done;
-#endif
+#else
/*
* test null first. if CONFIG_HWCONFIG is not defined
* hwconfig_arg_cmp returns non-zero
@@ -930,8 +928,9 @@ unsigned int populate_memctl_options(int all_dimms_registered,
popts->memctl_interleaving = 0;
printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
}
+#endif /* CONFIG_SYS_FSL_DDR_INTLV_256B */
done:
-#endif
+#endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */
if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
/* 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_BANK_INTERLEAVING:
case FSL_DDR_SUPERBANK_INTERLEAVING:
- if (3 == CONFIG_NUM_DDR_CONTROLLERS)
+#if (3 == CONFIG_NUM_DDR_CONTROLLERS)
k = 2;
- else
+#else
k = CONFIG_NUM_DDR_CONTROLLERS;
+#endif
break;
case FSL_DDR_3WAY_1KB_INTERLEAVING:
case FSL_DDR_3WAY_4KB_INTERLEAVING: