Commit a084e6ee authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms/atom: make sure tables are valid (v2)

Check that atom cmd and data tables are valid
before using them.

(v2)
- fix some whitespace errors noticed by Rafał Miłecki
- check a few more cases
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent c1bcad9d
......@@ -1295,12 +1295,16 @@ void atom_destroy(struct atom_context *ctx)
kfree(ctx);
}
void atom_parse_data_header(struct atom_context *ctx, int index,
bool atom_parse_data_header(struct atom_context *ctx, int index,
uint16_t * size, uint8_t * frev, uint8_t * crev,
uint16_t * data_start)
{
int offset = index * 2 + 4;
int idx = CU16(ctx->data_table + offset);
u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
if (!mdt[index])
return false;
if (size)
*size = CU16(idx);
......@@ -1309,31 +1313,34 @@ void atom_parse_data_header(struct atom_context *ctx, int index,
if (crev)
*crev = CU8(idx + 3);
*data_start = idx;
return;
return true;
}
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
bool atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
uint8_t * crev)
{
int offset = index * 2 + 4;
int idx = CU16(ctx->cmd_table + offset);
u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4);
if (!mct[index])
return false;
if (frev)
*frev = CU8(idx + 2);
if (crev)
*crev = CU8(idx + 3);
return;
return true;
}
int atom_allocate_fb_scratch(struct atom_context *ctx)
{
int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
uint16_t data_offset;
int usage_bytes;
int usage_bytes = 0;
struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
DRM_DEBUG("atom firmware requested %08x %dkb\n",
......@@ -1341,6 +1348,7 @@ int atom_allocate_fb_scratch(struct atom_context *ctx)
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
}
if (usage_bytes == 0)
usage_bytes = 20 * 1024;
/* allocate some scratch memory */
......
......@@ -143,8 +143,10 @@ struct atom_context *atom_parse(struct card_info *, void *);
int atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *);
void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
uint8_t *frev, uint8_t *crev, uint16_t *data_start);
bool atom_parse_cmd_header(struct atom_context *ctx, int index,
uint8_t *frev, uint8_t *crev);
int atom_allocate_fb_scratch(struct atom_context *ctx);
#include "atom-types.h"
#include "atombios.h"
......
......@@ -541,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
int index;
index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev))
return adjusted_clock;
memset(&args, 0, sizeof(args));
......@@ -630,8 +631,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
memset(&args, 0, sizeof(args));
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev))
return;
switch (frev) {
case 1:
......@@ -705,8 +707,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
&ref_div, &post_div);
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev))
return;
switch (frev) {
case 1:
......
......@@ -75,11 +75,9 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
i2c.valid = false;
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
gpio = &i2c_info->asGPIO_Info[i];
......@@ -117,6 +115,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
break;
}
}
}
return i2c;
}
......@@ -135,11 +134,11 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd
memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
gpio.valid = false;
atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset);
if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
for (i = 0; i < num_indices; i++) {
pin = &gpio_info->asGPIO_Pin[i];
......@@ -151,6 +150,7 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd
break;
}
}
}
return gpio;
}
......@@ -395,9 +395,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
struct radeon_gpio_rec gpio;
struct radeon_hpd hpd;
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
if (data_offset == 0)
if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
return false;
if (crev < 2)
......@@ -449,8 +447,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
GetIndexIntoMasterTable(DATA,
IntegratedSystemInfo);
atom_parse_data_header(ctx, index, &size, &frev,
&crev, &igp_offset);
if (atom_parse_data_header(ctx, index, &size, &frev,
&crev, &igp_offset)) {
if (crev >= 2) {
igp_obj =
......@@ -486,6 +484,12 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
object_connector_convert[con_obj_id];
connector_object_id = con_obj_id;
}
} else {
igp_lane_info = 0;
connector_type =
object_connector_convert[con_obj_id];
connector_object_id = con_obj_id;
}
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
continue;
......@@ -627,7 +631,7 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
uint8_t frev, crev;
ATOM_XTMDS_INFO *xtmds;
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
......@@ -641,6 +645,9 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
else
return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
}
} else
return supported_devices_connector_object_id_convert
[connector_type];
} else {
return supported_devices_connector_object_id_convert
[connector_type];
......@@ -672,7 +679,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
int i, j, max_device;
struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
return false;
supported_devices =
(union atom_supported_devices *)(ctx->bios + data_offset);
......@@ -865,14 +873,11 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
struct radeon_pll *mpll = &rdev->clock.mpll;
uint16_t data_offset;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
firmware_info =
(union firmware_info *)(mode_info->atom_context->bios +
data_offset);
if (firmware_info) {
/* pixel clocks */
p1pll->reference_freq =
le16_to_cpu(firmware_info->info.usReferenceClock);
......@@ -1006,13 +1011,10 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
u8 frev, crev;
u16 data_offset;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
igp_info = (union igp_info *)(mode_info->atom_context->bios +
data_offset);
if (igp_info) {
switch (crev) {
case 1:
if (igp_info->info.ucMemoryType & 0xf0)
......@@ -1043,14 +1045,12 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
uint16_t maxfreq;
int i;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
tmds_info =
(struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
data_offset);
if (tmds_info) {
maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
for (i = 0; i < 4; i++) {
tmds->tmds_pll[i].freq =
......@@ -1099,13 +1099,11 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
if (id > ATOM_MAX_SS_ENTRY)
return NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
ss_info =
(struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
if (ss_info) {
ss =
kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
......@@ -1146,13 +1144,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
uint8_t frev, crev;
struct radeon_encoder_atom_dig *lvds = NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
lvds_info =
(union lvds_info *)(mode_info->atom_context->bios + data_offset);
if (lvds_info) {
lvds =
kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
......@@ -1228,11 +1223,11 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
uint8_t bg, dac;
struct radeon_encoder_primary_dac *p_dac = NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
dac_info = (struct _COMPASSIONATE_DATA *)
(mode_info->atom_context->bios + data_offset);
dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
if (dac_info) {
p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
if (!p_dac)
......@@ -1257,7 +1252,9 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
u8 frev, crev;
u16 data_offset, misc;
atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
&frev, &crev, &data_offset))
return false;
switch (crev) {
case 1:
......@@ -1349,9 +1346,11 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
struct _ATOM_ANALOG_TV_INFO *tv_info;
enum radeon_tv_std tv_std = TV_STD_NTSC;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
tv_info = (struct _ATOM_ANALOG_TV_INFO *)
(mode_info->atom_context->bios + data_offset);
switch (tv_info->ucTV_BootUpDefaultStandard) {
case ATOM_TV_NTSC:
......@@ -1391,6 +1390,7 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
break;
}
}
return tv_std;
}
......@@ -1407,11 +1407,12 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
uint8_t bg, dac;
struct radeon_encoder_tv_dac *tv_dac = NULL;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
dac_info = (struct _COMPASSIONATE_DATA *)
(mode_info->atom_context->bios + data_offset);
if (dac_info) {
tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
if (!tv_dac)
......@@ -1479,13 +1480,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
int state_index = 0, mode_index = 0;
struct radeon_i2c_bus_rec i2c_bus;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
rdev->pm.default_power_state = NULL;
if (power_info) {
if (atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset)) {
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
if (frev < 4) {
/* add the i2c bus for thermal/fan chip */
if (power_info->info.ucOverdriveThermalController > 0) {
......
......@@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
if (rdev->bios) {
if (rdev->is_atom_bios) {
if (rdev->family >= CHIP_R600)
ret = radeon_get_atom_connector_info_from_object_table(dev);
else
ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
if (ret == false)
ret = radeon_get_atom_connector_info_from_object_table(dev);
} else {
ret = radeon_get_legacy_connector_info_from_bios(dev);
if (ret == false)
......
......@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
break;
}
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
switch (frev) {
case 1:
......@@ -725,7 +726,8 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
}
num = dig->dig_encoder + 1;
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
args.v1.ucAction = action;
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
......@@ -813,7 +815,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
}
}
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
args.v1.ucAction = action;
if (action == ATOM_TRANSMITTER_ACTION_INIT) {
......@@ -1103,7 +1106,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
memset(&args, 0, sizeof(args));
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
switch (frev) {
case 1:
......@@ -1411,7 +1415,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn
memset(&args, 0, sizeof(args));
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return false;
args.sDacload.ucMisc = 0;
......
......@@ -58,40 +58,42 @@ static void rs690_gpu_init(struct radeon_device *rdev)
}
}
union igp_info {
struct _ATOM_INTEGRATED_SYSTEM_INFO info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_v2;
};
void rs690_pm_info(struct radeon_device *rdev)
{
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
struct _ATOM_INTEGRATED_SYSTEM_INFO *info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
void *ptr;
union igp_info *info;
uint16_t data_offset;
uint8_t frev, crev;
fixed20_12 tmp;
atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
&frev, &crev, &data_offset);
ptr = rdev->mode_info.atom_context->bios + data_offset;
info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr;
if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
&frev, &crev, &data_offset)) {
info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset);
/* Get various system informations from bios */
switch (crev) {
case 1:
tmp.full = rfixed_const(100);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info.ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock));
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock));
rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth);
rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->info.usK8MemoryClock));
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->info.usFSBClock));
rdev->pm.igp_ht_link_width.full = rfixed_const(info->info.ucHTLinkWidth);
break;
case 2:
tmp.full = rfixed_const(100);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info_v2.ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock);
rdev->pm.igp_system_mclk.full = rfixed_const(info->info_v2.ulBootUpUMAClock);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = rfixed_const(info->info_v2.ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth));
rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth));
break;
default:
tmp.full = rfixed_const(100);
......@@ -106,6 +108,18 @@ void rs690_pm_info(struct radeon_device *rdev)
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
}
} else {
tmp.full = rfixed_const(100);
/* We assume the slower possible clock ie worst case */
/* DDR 333Mhz */
rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
/* FIXME: system clock ? */
rdev->pm.igp_system_mclk.full = rfixed_const(100);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
rdev->pm.igp_ht_link_width.full = rfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
}
/* Compute various bandwidth */
/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */
tmp.full = rfixed_const(4);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment