blob: 5e5409505c31132c4a1e4818cfb8de6c699fbadb [file] [log] [blame]
Ramalingam C6498bf52019-05-07 21:57:38 +05301// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 Intel Corporation.
4 *
5 * Authors:
6 * Ramalingam C <ramalingam.c@intel.com>
7 */
8
9#include <linux/device.h>
10#include <linux/err.h>
11#include <linux/gfp.h>
12#include <linux/export.h>
13#include <linux/slab.h>
14#include <linux/firmware.h>
15
16#include <drm/drm_hdcp.h>
17#include <drm/drm_sysfs.h>
18#include <drm/drm_print.h>
19#include <drm/drm_device.h>
20
21struct hdcp_srm {
22 u32 revoked_ksv_cnt;
23 u8 *revoked_ksv_list;
24
25 /* Mutex to protect above struct member */
26 struct mutex mutex;
27} *srm_data;
28
29static inline void drm_hdcp_print_ksv(const u8 *ksv)
30{
31 DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n",
32 ksv[0], ksv[1], ksv[2], ksv[3], ksv[4]);
33}
34
35static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length)
36{
37 u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz;
38
39 while (parsed_bytes < vrls_length) {
40 vrl_ksv_cnt = *buf;
41 ksv_count += vrl_ksv_cnt;
42
43 vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1;
44 buf += vrl_sz;
45 parsed_bytes += vrl_sz;
46 }
47
48 /*
49 * When vrls are not valid, ksvs are not considered.
50 * Hence SRM will be discarded.
51 */
52 if (parsed_bytes != vrls_length)
53 ksv_count = 0;
54
55 return ksv_count;
56}
57
58static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 *revoked_ksv_list,
59 u32 vrls_length)
60{
61 u32 parsed_bytes = 0, ksv_count = 0;
62 u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0;
63
64 do {
65 vrl_ksv_cnt = *buf;
66 vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN;
67
68 buf++;
69
70 DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++,
71 vrl_ksv_cnt);
72 memcpy(revoked_ksv_list, buf, vrl_ksv_sz);
73
74 ksv_count += vrl_ksv_cnt;
75 revoked_ksv_list += vrl_ksv_sz;
76 buf += vrl_ksv_sz;
77
78 parsed_bytes += (vrl_ksv_sz + 1);
79 } while (parsed_bytes < vrls_length);
80
81 return ksv_count;
82}
83
84static inline u32 get_vrl_length(const u8 *buf)
85{
86 return drm_hdcp_be24_to_cpu(buf);
87}
88
89static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count)
90{
91 struct hdcp_srm_header *header;
92 u32 vrl_length, ksv_count;
93
94 if (count < (sizeof(struct hdcp_srm_header) +
95 DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) {
96 DRM_ERROR("Invalid blob length\n");
97 return -EINVAL;
98 }
99
100 header = (struct hdcp_srm_header *)buf;
101 DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
102 header->srm_id,
103 be16_to_cpu(header->srm_version), header->srm_gen_no);
104
105 WARN_ON(header->reserved);
106
107 buf = buf + sizeof(*header);
108 vrl_length = get_vrl_length(buf);
109 if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
110 vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
111 DRM_HDCP_1_4_DCP_SIG_SIZE)) {
112 DRM_ERROR("Invalid blob length or vrl length\n");
113 return -EINVAL;
114 }
115
116 /* Length of the all vrls combined */
117 vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
118 DRM_HDCP_1_4_DCP_SIG_SIZE);
119
120 if (!vrl_length) {
121 DRM_ERROR("No vrl found\n");
122 return -EINVAL;
123 }
124
125 buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE;
126 ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length);
127 if (!ksv_count) {
128 DRM_DEBUG("Revoked KSV count is 0\n");
129 return count;
130 }
131
132 kfree(srm_data->revoked_ksv_list);
133 srm_data->revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN,
134 GFP_KERNEL);
135 if (!srm_data->revoked_ksv_list) {
136 DRM_ERROR("Out of Memory\n");
137 return -ENOMEM;
138 }
139
140 if (drm_hdcp_get_revoked_ksvs(buf, srm_data->revoked_ksv_list,
141 vrl_length) != ksv_count) {
142 srm_data->revoked_ksv_cnt = 0;
143 kfree(srm_data->revoked_ksv_list);
144 return -EINVAL;
145 }
146
147 srm_data->revoked_ksv_cnt = ksv_count;
148 return count;
149}
150
151static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count)
152{
153 struct hdcp_srm_header *header;
154 u32 vrl_length, ksv_count, ksv_sz;
155
156 if (count < (sizeof(struct hdcp_srm_header) +
157 DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) {
158 DRM_ERROR("Invalid blob length\n");
159 return -EINVAL;
160 }
161
162 header = (struct hdcp_srm_header *)buf;
163 DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
164 header->srm_id & DRM_HDCP_SRM_ID_MASK,
165 be16_to_cpu(header->srm_version), header->srm_gen_no);
166
167 if (header->reserved)
168 return -EINVAL;
169
170 buf = buf + sizeof(*header);
171 vrl_length = get_vrl_length(buf);
172
173 if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
174 vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE +
175 DRM_HDCP_2_DCP_SIG_SIZE)) {
176 DRM_ERROR("Invalid blob length or vrl length\n");
177 return -EINVAL;
178 }
179
180 /* Length of the all vrls combined */
181 vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE +
182 DRM_HDCP_2_DCP_SIG_SIZE);
183
184 if (!vrl_length) {
185 DRM_ERROR("No vrl found\n");
186 return -EINVAL;
187 }
188
189 buf += DRM_HDCP_2_VRL_LENGTH_SIZE;
190 ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1));
191 if (!ksv_count) {
192 DRM_DEBUG("Revoked KSV count is 0\n");
193 return count;
194 }
195
196 kfree(srm_data->revoked_ksv_list);
197 srm_data->revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN,
198 GFP_KERNEL);
199 if (!srm_data->revoked_ksv_list) {
200 DRM_ERROR("Out of Memory\n");
201 return -ENOMEM;
202 }
203
204 ksv_sz = ksv_count * DRM_HDCP_KSV_LEN;
205 buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ;
206
207 DRM_DEBUG("Revoked KSVs: %d\n", ksv_count);
208 memcpy(srm_data->revoked_ksv_list, buf, ksv_sz);
209
210 srm_data->revoked_ksv_cnt = ksv_count;
211 return count;
212}
213
214static inline bool is_srm_version_hdcp1(const u8 *buf)
215{
216 return *buf == (u8)(DRM_HDCP_1_4_SRM_ID << 4);
217}
218
219static inline bool is_srm_version_hdcp2(const u8 *buf)
220{
221 return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR);
222}
223
224static void drm_hdcp_srm_update(const u8 *buf, size_t count)
225{
226 if (count < sizeof(struct hdcp_srm_header))
227 return;
228
229 if (is_srm_version_hdcp1(buf))
230 drm_hdcp_parse_hdcp1_srm(buf, count);
231 else if (is_srm_version_hdcp2(buf))
232 drm_hdcp_parse_hdcp2_srm(buf, count);
233}
234
235void drm_hdcp_request_srm(struct drm_device *drm_dev)
236{
237 char fw_name[36] = "display_hdcp_srm.bin";
238 const struct firmware *fw;
239
240 int ret;
241
242 ret = request_firmware_direct(&fw, (const char *)fw_name,
243 drm_dev->dev);
244 if (ret < 0)
245 goto exit;
246
247 if (fw->size && fw->data)
248 drm_hdcp_srm_update(fw->data, fw->size);
249
250exit:
251 release_firmware(fw);
252}
253
254/**
255 * drm_hdcp_check_ksvs_revoked - Check the revoked status of the IDs
256 *
257 * @drm_dev: drm_device for which HDCP revocation check is requested
258 * @ksvs: List of KSVs (HDCP receiver IDs)
259 * @ksv_count: KSV count passed in through @ksvs
260 *
261 * This function reads the HDCP System renewability Message(SRM Table)
262 * from userspace as a firmware and parses it for the revoked HDCP
263 * KSVs(Receiver IDs) detected by DCP LLC. Once the revoked KSVs are known,
264 * revoked state of the KSVs in the list passed in by display drivers are
265 * decided and response is sent.
266 *
267 * SRM should be presented in the name of "display_hdcp_srm.bin".
268 *
269 * Returns:
270 * TRUE on any of the KSV is revoked, else FALSE.
271 */
272bool drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
273 u32 ksv_count)
274{
275 u32 rev_ksv_cnt, cnt, i, j;
276 u8 *rev_ksv_list;
277
278 if (!srm_data)
279 return false;
280
281 mutex_lock(&srm_data->mutex);
282 drm_hdcp_request_srm(drm_dev);
283
284 rev_ksv_cnt = srm_data->revoked_ksv_cnt;
285 rev_ksv_list = srm_data->revoked_ksv_list;
286
287 /* If the Revoked ksv list is empty */
288 if (!rev_ksv_cnt || !rev_ksv_list) {
289 mutex_unlock(&srm_data->mutex);
290 return false;
291 }
292
293 for (cnt = 0; cnt < ksv_count; cnt++) {
294 rev_ksv_list = srm_data->revoked_ksv_list;
295 for (i = 0; i < rev_ksv_cnt; i++) {
296 for (j = 0; j < DRM_HDCP_KSV_LEN; j++)
297 if (ksvs[j] != rev_ksv_list[j]) {
298 break;
299 } else if (j == (DRM_HDCP_KSV_LEN - 1)) {
300 DRM_DEBUG("Revoked KSV is ");
301 drm_hdcp_print_ksv(ksvs);
302 mutex_unlock(&srm_data->mutex);
303 return true;
304 }
305 /* Move the offset to next KSV in the revoked list */
306 rev_ksv_list += DRM_HDCP_KSV_LEN;
307 }
308
309 /* Iterate to next ksv_offset */
310 ksvs += DRM_HDCP_KSV_LEN;
311 }
312 mutex_unlock(&srm_data->mutex);
313 return false;
314}
315EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked);
316
317int drm_setup_hdcp_srm(struct class *drm_class)
318{
319 srm_data = kzalloc(sizeof(*srm_data), GFP_KERNEL);
320 if (!srm_data)
321 return -ENOMEM;
322 mutex_init(&srm_data->mutex);
323
324 return 0;
325}
326
327void drm_teardown_hdcp_srm(struct class *drm_class)
328{
329 if (srm_data) {
330 kfree(srm_data->revoked_ksv_list);
331 kfree(srm_data);
332 }
333}