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) ...@@ -1295,12 +1295,16 @@ void atom_destroy(struct atom_context *ctx)
kfree(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 * size, uint8_t * frev, uint8_t * crev,
uint16_t * data_start) uint16_t * data_start)
{ {
int offset = index * 2 + 4; int offset = index * 2 + 4;
int idx = CU16(ctx->data_table + offset); int idx = CU16(ctx->data_table + offset);
u16 *mdt = (u16 *)(ctx->bios + ctx->data_table + 4);
if (!mdt[index])
return false;
if (size) if (size)
*size = CU16(idx); *size = CU16(idx);
...@@ -1309,38 +1313,42 @@ void atom_parse_data_header(struct atom_context *ctx, int index, ...@@ -1309,38 +1313,42 @@ void atom_parse_data_header(struct atom_context *ctx, int index,
if (crev) if (crev)
*crev = CU8(idx + 3); *crev = CU8(idx + 3);
*data_start = idx; *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) uint8_t * crev)
{ {
int offset = index * 2 + 4; int offset = index * 2 + 4;
int idx = CU16(ctx->cmd_table + offset); int idx = CU16(ctx->cmd_table + offset);
u16 *mct = (u16 *)(ctx->bios + ctx->cmd_table + 4);
if (!mct[index])
return false;
if (frev) if (frev)
*frev = CU8(idx + 2); *frev = CU8(idx + 2);
if (crev) if (crev)
*crev = CU8(idx + 3); *crev = CU8(idx + 3);
return; return true;
} }
int atom_allocate_fb_scratch(struct atom_context *ctx) int atom_allocate_fb_scratch(struct atom_context *ctx)
{ {
int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware); int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
uint16_t data_offset; uint16_t data_offset;
int usage_bytes; int usage_bytes = 0;
struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage; 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);
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset); DRM_DEBUG("atom firmware requested %08x %dkb\n",
firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
DRM_DEBUG("atom firmware requested %08x %dkb\n", usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware, }
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
if (usage_bytes == 0) if (usage_bytes == 0)
usage_bytes = 20 * 1024; usage_bytes = 20 * 1024;
/* allocate some scratch memory */ /* allocate some scratch memory */
......
...@@ -143,8 +143,10 @@ struct atom_context *atom_parse(struct card_info *, void *); ...@@ -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_execute_table(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *); int atom_asic_init(struct atom_context *);
void atom_destroy(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); bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); 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); int atom_allocate_fb_scratch(struct atom_context *ctx);
#include "atom-types.h" #include "atom-types.h"
#include "atombios.h" #include "atombios.h"
......
...@@ -541,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -541,8 +541,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
int index; int index;
index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev); &crev))
return adjusted_clock;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
...@@ -630,8 +631,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc) ...@@ -630,8 +631,9 @@ static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev); &crev))
return;
switch (frev) { switch (frev) {
case 1: case 1:
...@@ -705,8 +707,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -705,8 +707,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
&ref_div, &post_div); &ref_div, &post_div);
index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev); &crev))
return;
switch (frev) { switch (frev) {
case 1: case 1:
......
This diff is collapsed.
...@@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) ...@@ -368,10 +368,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
if (rdev->bios) { if (rdev->bios) {
if (rdev->is_atom_bios) { if (rdev->is_atom_bios) {
if (rdev->family >= CHIP_R600) ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
if (ret == false)
ret = radeon_get_atom_connector_info_from_object_table(dev); ret = radeon_get_atom_connector_info_from_object_table(dev);
else
ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
} else { } else {
ret = radeon_get_legacy_connector_info_from_bios(dev); ret = radeon_get_legacy_connector_info_from_bios(dev);
if (ret == false) if (ret == false)
......
...@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) ...@@ -519,7 +519,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
break; 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) { switch (frev) {
case 1: case 1:
...@@ -725,7 +726,8 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) ...@@ -725,7 +726,8 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
} }
num = dig->dig_encoder + 1; 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.ucAction = action;
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); 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 ...@@ -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; args.v1.ucAction = action;
if (action == ATOM_TRANSMITTER_ACTION_INIT) { if (action == ATOM_TRANSMITTER_ACTION_INIT) {
...@@ -1103,7 +1106,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder) ...@@ -1103,7 +1106,8 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
memset(&args, 0, sizeof(args)); 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) { switch (frev) {
case 1: case 1:
...@@ -1411,7 +1415,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn ...@@ -1411,7 +1415,8 @@ atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *conn
memset(&args, 0, sizeof(args)); 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; args.sDacload.ucMisc = 0;
......
...@@ -58,42 +58,57 @@ static void rs690_gpu_init(struct radeon_device *rdev) ...@@ -58,42 +58,57 @@ 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) void rs690_pm_info(struct radeon_device *rdev)
{ {
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
struct _ATOM_INTEGRATED_SYSTEM_INFO *info; union igp_info *info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
void *ptr;
uint16_t data_offset; uint16_t data_offset;
uint8_t frev, crev; uint8_t frev, crev;
fixed20_12 tmp; fixed20_12 tmp;
atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
&frev, &crev, &data_offset); &frev, &crev, &data_offset)) {
ptr = rdev->mode_info.atom_context->bios + data_offset; info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset);
info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr; /* Get various system informations from bios */
/* Get various system informations from bios */ switch (crev) {
switch (crev) { case 1:
case 1: tmp.full = rfixed_const(100);
tmp.full = rfixed_const(100); rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info.ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock); rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
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->info.usK8MemoryClock));
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->info.usFSBClock));
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); rdev->pm.igp_ht_link_width.full = rfixed_const(info->info.ucHTLinkWidth);
rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); break;
break; case 2:
case 2: tmp.full = rfixed_const(100);
tmp.full = rfixed_const(100); rdev->pm.igp_sideport_mclk.full = rfixed_const(info->info_v2.ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock); rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); rdev->pm.igp_system_mclk.full = rfixed_const(info->info_v2.ulBootUpUMAClock);
rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock); rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); rdev->pm.igp_ht_link_clk.full = rfixed_const(info->info_v2.ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq); rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
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->info_v2.usMinHTLinkWidth));
rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth)); break;
break; default:
default: 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");
break;
}
} else {
tmp.full = rfixed_const(100); tmp.full = rfixed_const(100);
/* We assume the slower possible clock ie worst case */ /* We assume the slower possible clock ie worst case */
/* DDR 333Mhz */ /* DDR 333Mhz */
...@@ -104,7 +119,6 @@ void rs690_pm_info(struct radeon_device *rdev) ...@@ -104,7 +119,6 @@ void rs690_pm_info(struct radeon_device *rdev)
rdev->pm.igp_ht_link_clk.full = rfixed_const(200); rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
rdev->pm.igp_ht_link_width.full = rfixed_const(8); rdev->pm.igp_ht_link_width.full = rfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n"); DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
} }
/* Compute various bandwidth */ /* Compute various bandwidth */
/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 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