rockchip: implement hdcp key decryption feature for rk3399
authorZiyuan Xu <xzy.xu@rock-chips.com>
Fri, 10 Feb 2017 03:54:52 +0000 (11:54 +0800)
committerCaesar Wang <wxt@rock-chips.com>
Wed, 5 Jul 2017 09:58:23 +0000 (17:58 +0800)
Decrypt device private keys which transfer from kernel, then stuff it to
DP controller. So that DP driver could start HDCP authentication in
kernel.

Change-Id: If3c2cd99bca811fe5fc30acc88bf5dc1afd7416d
Signed-off-by: Ziyuan Xu <xzy.xu@rock-chips.com>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
plat/rockchip/rk3399/drivers/dp/cdn_dp.c
plat/rockchip/rk3399/drivers/dp/cdn_dp.h [new file with mode: 0644]
plat/rockchip/rk3399/plat_sip_calls.c

index 9fc623b9756d1772a88c2abd69c0ecd62f375dac..d0e5986107b7f26776a41c1501184f43bf83d576 100644 (file)
@@ -4,7 +4,10 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <cdn_dp.h>
+#include <smcc.h>
 #include <stdlib.h>
+#include <string.h>
 
 __asm__(
        ".pushsection .text.hdcp_handler, \"ax\", %progbits\n"
@@ -17,3 +20,46 @@ __asm__(
        ".popsection\n"
 );
 
+static uint64_t *hdcp_key_pdata;
+static struct cdn_dp_hdcp_key_1x key;
+
+int hdcp_handler(struct cdn_dp_hdcp_key_1x *key);
+
+uint64_t dp_hdcp_ctrl(uint64_t type)
+{
+       switch (type) {
+       case HDCP_KEY_DATA_START_TRANSFER:
+               memset(&key, 0x00, sizeof(key));
+               hdcp_key_pdata = (uint64_t *)&key;
+               return 0;
+       case HDCP_KEY_DATA_START_DECRYPT:
+               if (hdcp_key_pdata == (uint64_t *)(&key + 1))
+                       return hdcp_handler(&key);
+               else
+                       return PSCI_E_INVALID_PARAMS;
+       default:
+               return SMC_UNK;
+       }
+}
+
+uint64_t dp_hdcp_store_key(uint64_t x1,
+                          uint64_t x2,
+                          uint64_t x3,
+                          uint64_t x4,
+                          uint64_t x5,
+                          uint64_t x6)
+{
+       if (hdcp_key_pdata < (uint64_t *)&key ||
+               hdcp_key_pdata + 6 > (uint64_t *)(&key + 1))
+               return PSCI_E_INVALID_PARAMS;
+
+       hdcp_key_pdata[0] = x1;
+       hdcp_key_pdata[1] = x2;
+       hdcp_key_pdata[2] = x3;
+       hdcp_key_pdata[3] = x4;
+       hdcp_key_pdata[4] = x5;
+       hdcp_key_pdata[5] = x6;
+       hdcp_key_pdata += 6;
+
+       return 0;
+}
diff --git a/plat/rockchip/rk3399/drivers/dp/cdn_dp.h b/plat/rockchip/rk3399/drivers/dp/cdn_dp.h
new file mode 100644 (file)
index 0000000..3b9a108
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SOC_ROCKCHIP_RK3399_DP_H__
+#define __SOC_ROCKCHIP_RK3399_DP_H__
+#include <plat_private.h>
+
+enum {
+       CDN_DP_HDCP_1X_KSV_LEN = 5,
+       CDN_DP_HDCP_KSV_LEN = 8,
+       CDN_DP_HDCP_RESERVED_LEN = 10,
+       CDN_DP_HDCP_UID_LEN = 16,
+       CDN_DP_HDCP_SHA_LEN = 20,
+       CDN_DP_HDCP_DPK_LEN = 280,
+       CDN_DP_HDCP_1X_KEYS_LEN = 285,
+       CDN_DP_HDCP_KEY_LEN = 326,
+};
+
+struct cdn_dp_hdcp_key_1x {
+       uint8_t ksv[CDN_DP_HDCP_KSV_LEN];
+       uint8_t device_key[CDN_DP_HDCP_DPK_LEN];
+       uint8_t sha1[CDN_DP_HDCP_SHA_LEN];
+       uint8_t uid[CDN_DP_HDCP_UID_LEN];
+       uint16_t seed;
+       uint8_t reserved[CDN_DP_HDCP_RESERVED_LEN];
+};
+
+#define HDCP_KEY_DATA_START_TRANSFER   0
+#define HDCP_KEY_DATA_START_DECRYPT    1
+#define HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE      (6 * 64) / 8
+
+/* Checks the cdn_dp_hdcp_key_1x must be aligned on 6 x 64-bit word boundary */
+CASSERT(sizeof(struct cdn_dp_hdcp_key_1x) % HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE, \
+       assert_hdcp_key_1x_store_data_align_size_mismatch);
+
+uint64_t dp_hdcp_ctrl(uint64_t type);
+
+uint64_t dp_hdcp_store_key(uint64_t x1,
+                          uint64_t x2,
+                          uint64_t x3,
+                          uint64_t x4,
+                          uint64_t x5,
+                          uint64_t x6);
+#endif
index 77b7c3ed1ba0d8c12037a1f6d7af36ff05a57d9b..1a016042f27d0ddefa2a0fb112d2a4c5400180ec 100644 (file)
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <cdn_dp.h>
 #include <debug.h>
 #include <mmio.h>
 #include <plat_sip_calls.h>
@@ -22,6 +23,9 @@
 #define DRAM_SET_PARAM         0x07
 #define DRAM_SET_ODT_PD                0x08
 
+#define RK_SIP_HDCP_CONTROL    0x82000009
+#define RK_SIP_HDCP_KEY_DATA64 0xC200000A
+
 uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1,
                         uint64_t id, uint64_t arg2)
 {
@@ -51,9 +55,17 @@ uint64_t rockchip_plat_sip_handler(uint32_t smc_fid,
                                   void *handle,
                                   uint64_t flags)
 {
+       uint64_t x5, x6;
+
        switch (smc_fid) {
        case RK_SIP_DDR_CFG:
                SMC_RET1(handle, ddr_smc_handler(x1, x2, x3, x4));
+       case RK_SIP_HDCP_CONTROL:
+               SMC_RET1(handle, dp_hdcp_ctrl(x1));
+       case RK_SIP_HDCP_KEY_DATA64:
+               x5 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X5);
+               x6 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X6);
+               SMC_RET1(handle, dp_hdcp_store_key(x1, x2, x3, x4, x5, x6));
        default:
                ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
                SMC_RET1(handle, SMC_UNK);