From patchwork Tue Feb 26 07:36:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramalingam C X-Patchwork-Id: 10829623 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B039E1390 for ; Tue, 26 Feb 2019 07:42:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A358E2AAA1 for ; Tue, 26 Feb 2019 07:42:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 97A4A2AAAE; Tue, 26 Feb 2019 07:42:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0C3732AAA1 for ; Tue, 26 Feb 2019 07:42:22 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9654C89C93; Tue, 26 Feb 2019 07:42:11 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id C1FDD89C96; Tue, 26 Feb 2019 07:42:09 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Feb 2019 23:42:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,414,1544515200"; d="scan'208";a="125259472" Received: from mint-dev.iind.intel.com ([10.223.25.164]) by fmsmga007.fm.intel.com with ESMTP; 25 Feb 2019 23:42:07 -0800 From: Ramalingam C To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, daniel.vetter@ffwll.ch, uma.shankar@intel.com Date: Tue, 26 Feb 2019 13:06:03 +0530 Message-Id: <1551166569-19683-5-git-send-email-ramalingam.c@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1551166569-19683-1-git-send-email-ramalingam.c@intel.com> References: <1551166569-19683-1-git-send-email-ramalingam.c@intel.com> Subject: [Intel-gfx] [PATCH 04/10] drm/i915: Add HDCP SRM Blob parsing X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a drm blob property to selected connectors. And also adds capability to parse the new HDCP1.4 srm blob passed through cp_srm_property. The revocated KSV list and their counts are stored in the intel_hdcp. This list should be used for revocation check of BKSVs in first stage HDCP authentication and for revocation check of ksv_fifo in second stage authentication. Signed-off-by: Ramalingam C --- drivers/gpu/drm/i915/intel_ddi.c | 6 +- drivers/gpu/drm/i915/intel_drv.h | 8 ++- drivers/gpu/drm/i915/intel_hdcp.c | 147 +++++++++++++++++++++++++++++++++++++- include/drm/drm_hdcp.h | 14 ++++ 4 files changed, 170 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index ffe7759a3f3a..1f935fe9c466 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3500,7 +3500,8 @@ static void intel_enable_ddi(struct intel_encoder *encoder, if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) intel_hdcp_enable(to_intel_connector(conn_state->connector), - (u8)conn_state->cp_content_type); + (u8)conn_state->cp_content_type, + conn_state->cp_srm_blob_id); } static void intel_disable_ddi_dp(struct intel_encoder *encoder, @@ -3570,7 +3571,8 @@ static void intel_ddi_update_hdcp(struct intel_encoder *encoder, if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) intel_hdcp_enable(to_intel_connector(conn_state->connector), - (u8)conn_state->cp_content_type); + (u8)conn_state->cp_content_type, + conn_state->cp_srm_blob_id); else if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) intel_hdcp_disable(to_intel_connector(conn_state->connector)); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 04cff672aead..53a463d40f43 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -482,6 +482,11 @@ struct intel_hdcp { wait_queue_head_t cp_irq_queue; atomic_t cp_irq_count; int cp_irq_count_cached; + + /* list of Revocated KSVs and their count from SRM blob Parsing */ + unsigned int revocated_ksv_cnt; + u8 *revocated_ksv_list; + u32 srm_blob_id; }; struct intel_connector { @@ -2151,7 +2156,8 @@ void intel_hdcp_atomic_check(struct drm_connector *connector, struct drm_connector_state *new_state); int intel_hdcp_init(struct intel_connector *connector, const struct intel_hdcp_shim *hdcp_shim); -int intel_hdcp_enable(struct intel_connector *connector, u8 content_type); +int intel_hdcp_enable(struct intel_connector *connector, u8 content_type, + u32 srm_blob_id); int intel_hdcp_disable(struct intel_connector *connector); bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port); bool intel_hdcp_capable(struct intel_connector *connector); diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c index ab25264a74a4..4b12274d8987 100644 --- a/drivers/gpu/drm/i915/intel_hdcp.c +++ b/drivers/gpu/drm/i915/intel_hdcp.c @@ -1805,6 +1805,10 @@ int intel_hdcp_init(struct intel_connector *connector, if (ret) return ret; + ret = drm_connector_attach_cp_srm_property(&connector->base); + if (ret) + return ret; + hdcp->shim = shim; mutex_init(&hdcp->mutex); INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work); @@ -1817,7 +1821,144 @@ int intel_hdcp_init(struct intel_connector *connector, return 0; } -int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) +static u32 intel_hdcp_get_revocated_ksv_count(u8 *buf, u32 vrls_length) +{ + u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz; + + do { + vrl_ksv_cnt = *buf; + ksv_count += vrl_ksv_cnt; + + vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1; + buf += vrl_sz; + parsed_bytes += vrl_sz; + } while (parsed_bytes < vrls_length); + + return ksv_count; +} + +static u32 intel_hdcp_get_revocated_ksvs(u8 *ksv_list, const u8 *buf, + u32 vrls_length) +{ + u32 parsed_bytes = 0, ksv_count = 0; + u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0; + + do { + vrl_ksv_cnt = *buf; + vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN; + buf++; + + DRM_DEBUG_KMS("vrl: %d, Revoked KSVs: %d\n", vrl_idx++, + vrl_ksv_cnt); + memcpy(ksv_list, buf, vrl_ksv_sz); + ksv_count += vrl_ksv_cnt; + ksv_list += vrl_ksv_sz; + buf += vrl_ksv_sz; + + parsed_bytes += (vrl_ksv_sz + 1); + } while (parsed_bytes < vrls_length); + + return ksv_count; +} + +static int intel_hdcp_parse_srm(struct drm_connector *connector, + struct drm_property_blob *blob) +{ + struct intel_hdcp *hdcp = &(to_intel_connector(connector)->hdcp); + struct hdcp_srm_header *header; + u32 vrl_length, ksv_count; + u8 *buf; + + if (blob->length < (sizeof(struct hdcp_srm_header) + + DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) { + DRM_ERROR("Invalid blob length\n"); + return -EINVAL; + } + + header = (struct hdcp_srm_header *)blob->data; + + DRM_DEBUG_KMS("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n", + header->spec_indicator.srm_id, + __swab16(header->srm_version), header->srm_gen_no); + WARN_ON(header->spec_indicator.reserved_hi || + header->spec_indicator.reserved_lo); + + if (header->spec_indicator.srm_id != DRM_HDCP_1_4_SRM_ID) { + DRM_ERROR("Invalid srm_id\n"); + return -EINVAL; + } + + buf = blob->data + sizeof(*header); + vrl_length = (*buf << 16 | *(buf + 1) << 8 | *(buf + 2)); + if (blob->length < (sizeof(struct hdcp_srm_header) + vrl_length) || + vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE + + DRM_HDCP_1_4_DCP_SIG_SIZE)) { + DRM_ERROR("Invalid blob length or vrl length\n"); + return -EINVAL; + } + + /* Length of the all vrls combined */ + vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE + + DRM_HDCP_1_4_DCP_SIG_SIZE); + if (!vrl_length) { + DRM_DEBUG("No vrl found\n"); + return -EINVAL; + } + buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE; + + ksv_count = intel_hdcp_get_revocated_ksv_count(buf, vrl_length); + if (!ksv_count) { + DRM_DEBUG_KMS("Revocated KSV count is 0\n"); + return 0; + } + + kfree(hdcp->revocated_ksv_list); + hdcp->revocated_ksv_list = kzalloc(ksv_count * DRM_HDCP_KSV_LEN, + GFP_KERNEL); + if (!hdcp->revocated_ksv_list) { + DRM_ERROR("Out of Memory\n"); + return -ENOMEM; + } + + if (intel_hdcp_get_revocated_ksvs(hdcp->revocated_ksv_list, + buf, vrl_length) != ksv_count) { + hdcp->revocated_ksv_cnt = 0; + kfree(hdcp->revocated_ksv_list); + return -EINVAL; + } + + hdcp->revocated_ksv_cnt = ksv_count; + return 0; +} + +static void intel_hdcp_update_srm(struct intel_connector *intel_connector, + u32 srm_blob_id) +{ + struct drm_connector *connector = &intel_connector->base; + struct intel_hdcp *hdcp = &intel_connector->hdcp; + struct drm_property_blob *blob; + + DRM_DEBUG_KMS("srm_blob_id %u\n", srm_blob_id); + + if (!srm_blob_id) { + kfree(hdcp->revocated_ksv_list); + hdcp->revocated_ksv_cnt = 0; + hdcp->srm_blob_id = srm_blob_id; + return; + } + + blob = drm_property_lookup_blob(connector->dev, srm_blob_id); + if (!blob || !blob->data) + return; + + if (!intel_hdcp_parse_srm(connector, blob)) + hdcp->srm_blob_id = srm_blob_id; + + drm_property_blob_put(blob); +} + +int intel_hdcp_enable(struct intel_connector *connector, u8 content_type, + u32 srm_blob_id) { struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; @@ -1828,9 +1969,11 @@ int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) mutex_lock(&hdcp->mutex); WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; + if (srm_blob_id != hdcp->srm_blob_id) + intel_hdcp_update_srm(connector, srm_blob_id); + /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index f243408ecf26..1ccae47fcff5 100644 --- a/include/drm/drm_hdcp.h +++ b/include/drm/drm_hdcp.h @@ -265,4 +265,18 @@ void drm_hdcp2_u32_to_seq_num(u8 seq_num[HDCP_2_2_SEQ_NUM_LEN], u32 val) seq_num[2] = val; } +#define DRM_HDCP_1_4_SRM_ID 0x8 +#define DRM_HDCP_1_4_VRL_LENGTH_SIZE 3 +#define DRM_HDCP_1_4_DCP_SIG_SIZE 40 + +struct hdcp_srm_header { + struct { + u8 reserved_hi:4; + u8 srm_id:4; + u8 reserved_lo; + } spec_indicator; + u16 srm_version; + u8 srm_gen_no; +} __packed; + #endif