DF-1333 / fix.diff
diff --git a/sys/dev/drm/radeon/rv770_dpm.c b/sys/dev/drm/radeon/rv770_dpm.c --- a/sys/dev/drm/radeon/rv770_dpm.c +++ b/sys/dev/drm/radeon/rv770_dpm.c @@ -2277,11 +2277,11 @@ union pplib_clock_info *clock_info; union power_info *power_info; int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; + u16 data_offset, data_size; u8 frev, crev; struct rv7xx_ps *ps; - if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + if (!atom_parse_data_header(mode_info->atom_context, index, &data_size, &frev, &crev, &data_offset)) return -EINVAL; power_info = (union power_info *)((uint8_t*)mode_info->atom_context->bios + data_offset); @@ -2292,15 +2292,23 @@ return -ENOMEM; for (i = 0; i < power_info->pplib.ucNumStates; i++) { + u32 state_off, nc_off; + + state_off = le16_to_cpu(power_info->pplib.usStateArrayOffset) + + i * power_info->pplib.ucStateEntrySize; + if (state_off + power_info->pplib.ucStateEntrySize > data_size) + break; power_state = (union pplib_power_state *) ((uint8_t*)mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usStateArrayOffset) + - i * power_info->pplib.ucStateEntrySize); + state_off); + nc_off = le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + + (power_state->v1.ucNonClockStateIndex * + power_info->pplib.ucNonClockSize); + if (nc_off + power_info->pplib.ucNonClockSize > data_size) + break; non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) ((uint8_t*)mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + - (power_state->v1.ucNonClockStateIndex * - power_info->pplib.ucNonClockSize)); + nc_off); if (power_info->pplib.ucStateEntrySize - 1) { u8 *idx; ps = kzalloc(sizeof(struct rv7xx_ps), GFP_KERNEL); @@ -2314,17 +2322,22 @@ power_info->pplib.ucNonClockSize); idx = (u8 *)&power_state->v1.ucClockStateIndices[0]; for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { + u32 cl_off; + + cl_off = le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + + (idx[j] * power_info->pplib.ucClockInfoSize); + if (cl_off + power_info->pplib.ucClockInfoSize > data_size) + break; clock_info = (union pplib_clock_info *) ((uint8_t*)mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + - (idx[j] * power_info->pplib.ucClockInfoSize)); + cl_off); rv7xx_parse_pplib_clock_info(rdev, &rdev->pm.dpm.ps[i], j, clock_info); } } } - rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates; + rdev->pm.dpm.num_ps = i; return 0; } |