Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −12
Original line number Diff line number Diff line
@@ -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 */
+4 −2
Original line number Diff line number Diff line
@@ -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"
+9 −6
Original line number Diff line number Diff line
@@ -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:
+183 −184
Original line number Diff line number Diff line
@@ -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) {
+2 −3
Original line number Diff line number Diff line
@@ -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)
Loading