diff --git a/plat/rockchip/rk3399/drivers/dp/cdn_dp.c b/plat/rockchip/rk3399/drivers/dp/cdn_dp.c new file mode 100644 index 0000000000000000000000000000000000000000..d0e5986107b7f26776a41c1501184f43bf83d576 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/dp/cdn_dp.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * 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" + ".global hdcp_handler\n" + ".balign 4\n" + "hdcp_handler:\n" + ".incbin \"" __XSTRING(HDCPFW) "\"\n" + ".type hdcp_handler, %function\n" + ".size hdcp_handler, .- hdcp_handler\n" + ".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 index 0000000000000000000000000000000000000000..3b9a108431443bf5290b15692483c5cea4cc89a7 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/dp/cdn_dp.h @@ -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 diff --git a/plat/rockchip/rk3399/drivers/dp/hdcp.bin b/plat/rockchip/rk3399/drivers/dp/hdcp.bin new file mode 100644 index 0000000000000000000000000000000000000000..28db923669fe63812c25f016753df10558334fee Binary files /dev/null and b/plat/rockchip/rk3399/drivers/dp/hdcp.bin differ diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c index 77b7c3ed1ba0d8c12037a1f6d7af36ff05a57d9b..1a016042f27d0ddefa2a0fb112d2a4c5400180ec 100644 --- a/plat/rockchip/rk3399/plat_sip_calls.c +++ b/plat/rockchip/rk3399/plat_sip_calls.c @@ -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); diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 61071243080fb64a30d74357d6acd7382ff6ed23..85cca1b6b462c70886c121c1ce981caa5e32b1a1 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -18,6 +18,7 @@ PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ -I${RK_PLAT_SOC}/drivers/secure/ \ -I${RK_PLAT_SOC}/drivers/soc/ \ -I${RK_PLAT_SOC}/drivers/dram/ \ + -I${RK_PLAT_SOC}/drivers/dp/ \ -I${RK_PLAT_SOC}/include/ \ -I${RK_PLAT_SOC}/include/shared/ \ @@ -49,6 +50,7 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_COMMON}/aarch64/platform_common.c \ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ ${RK_PLAT_SOC}/plat_sip_calls.c \ + ${RK_PLAT_SOC}/drivers/dp/cdn_dp.c \ ${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c \ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c \ @@ -75,11 +77,17 @@ BUILD_M0 := ${BUILD_PLAT}/m0 RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin $(eval $(call add_define,RK3399M0FW)) +HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin +$(eval $(call add_define,HDCPFW)) + # CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin export CCACHE_EXTRAFILES ${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW) ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW) +${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW) +${RK_PLAT_SOC}/drivers/dp/cdn_dp.c: $(HDCPFW) + $(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},)) .PHONY: $(RK3399M0FW) $(RK3399M0FW): | ${BUILD_M0}