dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Zimmermann <tzimmermann@suse.de>
To: javierm@redhat.com, jani.nikula@linux.intel.com,
	airlied@redhat.com, sean@poorly.run
Cc: dri-devel@lists.freedesktop.org, Thomas Zimmermann <tzimmermann@suse.de>
Subject: [PATCH 2/7] drm/edid: Test for EDID header in drm_edit_probe_custom()
Date: Thu,  4 Apr 2024 17:03:19 +0200	[thread overview]
Message-ID: <20240404150857.5520-3-tzimmermann@suse.de> (raw)
In-Reply-To: <20240404150857.5520-1-tzimmermann@suse.de>

EDID read functions do not validate their return data. So they might
return the required number of bytes of probing, but with invalid
data. Therefore test for the presence of an EDID header similar to
the code in edid_block_check().

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/drm_edid.c | 50 +++++++++++++++++++++++++++++---------
 include/drm/drm_edid.h     |  2 +-
 2 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a3e9333f9177a..4e12d4b83a720 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1758,6 +1758,18 @@ static void edid_header_fix(void *edid)
 	memcpy(edid, edid_header, sizeof(edid_header));
 }
 
+static int edid_header_score(const u8 *header)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++) {
+		if (header[i] == edid_header[i])
+			score++;
+	}
+
+	return score;
+}
+
 /**
  * drm_edid_header_is_valid - sanity check the header of the base EDID block
  * @_edid: pointer to raw base EDID block
@@ -1769,14 +1781,8 @@ static void edid_header_fix(void *edid)
 int drm_edid_header_is_valid(const void *_edid)
 {
 	const struct edid *edid = _edid;
-	int i, score = 0;
 
-	for (i = 0; i < sizeof(edid_header); i++) {
-		if (edid->header[i] == edid_header[i])
-			score++;
-	}
-
-	return score;
+	return edid_header_score(edid->header);
 }
 EXPORT_SYMBOL(drm_edid_header_is_valid);
 
@@ -2612,17 +2618,37 @@ EXPORT_SYMBOL(drm_edid_free);
  * drm_edid_probe_custom() - probe DDC presence
  * @read_block: EDID block read function
  * @context: Private data passed to the block read function
+ * @validate: True to validate the EDID header
  *
  * Probes for EDID data. Only reads enough data to detect the presence
- * of the EDID channel.
+ * of the EDID channel. Some EDID block read functions do not fail,
+ * but return invalid data if no EDID data is available. If @validate
+ * has been specified, drm_edid_probe_custom() validates the retrieved
+ * EDID header before signalling success.
  *
  * Return: True on success, false on failure.
  */
-bool drm_edid_probe_custom(read_block_fn read_block, void *context)
+bool drm_edid_probe_custom(read_block_fn read_block, void *context, bool validate)
 {
-	unsigned char out;
+	u8 header[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+	int ret;
+	size_t len = 1;
+
+	if (validate)
+		len = sizeof(header); // read full header
+
+	ret = read_block(context, header, 0, len);
+	if (ret)
+		return false;
+
+	if (validate) {
+		int score = edid_header_score(header);
+
+		if (score < clamp(edid_fixup, 0, 8))
+			return false;
+	}
 
-	return (read_block(context, &out, 0, 1) == 0);
+	return true;
 }
 EXPORT_SYMBOL(drm_edid_probe_custom);
 
@@ -2635,7 +2661,7 @@ EXPORT_SYMBOL(drm_edid_probe_custom);
 bool
 drm_probe_ddc(struct i2c_adapter *adapter)
 {
-	return drm_edid_probe_custom(drm_do_probe_ddc_edid, adapter);
+	return drm_edid_probe_custom(drm_do_probe_ddc_edid, adapter, false);
 }
 EXPORT_SYMBOL(drm_probe_ddc);
 
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 4d1797ade5f1d..299278c7ee1c2 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -412,7 +412,7 @@ static inline void drm_edid_decode_panel_id(u32 panel_id, char vend[4], u16 *pro
 
 bool
 drm_edid_probe_custom(int (*read_block)(void *context, u8 *buf, unsigned int block, size_t len),
-		      void *context);
+		      void *context, bool validate);
 bool drm_probe_ddc(struct i2c_adapter *adapter);
 struct edid *drm_do_get_edid(struct drm_connector *connector,
 	int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
-- 
2.44.0


  parent reply	other threads:[~2024-04-04 15:09 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-04 15:03 [PATCH 0/7] drm/udl: Convert to struct drm_edid Thomas Zimmermann
2024-04-04 15:03 ` [PATCH 1/7] drm/edid: Implement drm_probe_ddc() with drm_edid_probe_custom() Thomas Zimmermann
2024-04-04 15:03 ` Thomas Zimmermann [this message]
2024-04-05  6:38   ` [PATCH 2/7] drm/edid: Test for EDID header in drm_edit_probe_custom() Jani Nikula
2024-04-05  7:06     ` Thomas Zimmermann
2024-04-04 15:03 ` [PATCH 3/7] drm/udl: Remove DRM_CONNECTOR_POLL_HPD Thomas Zimmermann
2024-04-04 15:03 ` [PATCH 4/7] drm/udl: Move drm_dev_{enter, exit}() into udl_get_edid_block() Thomas Zimmermann
2024-04-04 15:03 ` [PATCH 5/7] drm/udl: Clean up Makefile Thomas Zimmermann
2024-04-04 15:03 ` [PATCH 6/7] drm/udl: Untangle .get_modes() and .detect_ctx() Thomas Zimmermann
2024-04-05  7:09   ` Jani Nikula
2024-04-05  7:38     ` Thomas Zimmermann
2024-04-04 15:03 ` [PATCH 7/7] drm/udl: Remove struct udl_connector Thomas Zimmermann
2024-04-05  6:52   ` Dan Carpenter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240404150857.5520-3-tzimmermann@suse.de \
    --to=tzimmermann@suse.de \
    --cc=airlied@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=javierm@redhat.com \
    --cc=sean@poorly.run \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox