1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2022 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <asm/arch/rockchip_smccc.h>
9*4882a593Smuzhiyun #include <asm/arch/vendor.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define HDCP_SIGNED 0x4B534541 /* "AESK" */
12*4882a593Smuzhiyun #define HDCP_FLG_AES (1 << 0)
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun struct hdcpdata {
15*4882a593Smuzhiyun unsigned int signature;
16*4882a593Smuzhiyun unsigned int length;
17*4882a593Smuzhiyun unsigned int crc32;
18*4882a593Smuzhiyun unsigned int flags;
19*4882a593Smuzhiyun unsigned char data[0];
20*4882a593Smuzhiyun };
21*4882a593Smuzhiyun
vendor_handle_hdcp(struct vendor_item * vhead)22*4882a593Smuzhiyun int vendor_handle_hdcp(struct vendor_item *vhead)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct arm_smccc_res res;
25*4882a593Smuzhiyun struct hdcpdata *hdcp;
26*4882a593Smuzhiyun char *shm;
27*4882a593Smuzhiyun u32 crc, len;
28*4882a593Smuzhiyun int ret;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun hdcp = (void *)vhead + sizeof(struct vendor_item);
31*4882a593Smuzhiyun if ((hdcp->signature != HDCP_SIGNED) || !(hdcp->flags & HDCP_FLG_AES))
32*4882a593Smuzhiyun return 0;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun crc = crc32(0, hdcp->data, hdcp->length);
35*4882a593Smuzhiyun if (crc != hdcp->crc32) {
36*4882a593Smuzhiyun printf("%s: bad crc32 0x%08x != 0x%08x\n",
37*4882a593Smuzhiyun __func__, crc, hdcp->crc32);
38*4882a593Smuzhiyun return -EIO;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun res = sip_smc_request_share_mem(2, SHARE_PAGE_TYPE_HDCP);
42*4882a593Smuzhiyun if (res.a0) {
43*4882a593Smuzhiyun printf("%s: Can't get share mem\n", __func__);
44*4882a593Smuzhiyun return -EIO;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun shm = (char *)res.a1;
48*4882a593Smuzhiyun len = sizeof(struct hdcpdata) + hdcp->length;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun memcpy(shm, hdcp, len);
51*4882a593Smuzhiyun flush_dcache_range((ulong)shm, (ulong)(shm + len));
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun ret = sip_smc_hdcp_config(HDCP_FUNC_STORAGE_ENCRYPT, 0, 0);
54*4882a593Smuzhiyun if (ret) {
55*4882a593Smuzhiyun printf("%s: failed, ret=%d\n", __func__, ret);
56*4882a593Smuzhiyun return -EIO;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun invalidate_dcache_range((ulong)shm, (ulong)(shm + len));
60*4882a593Smuzhiyun memcpy(hdcp, shm, len);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun return 0;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65