1
2
3
4
5
6
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#include <drm/drm_property.h>
21#include <drm/drm_mode_object.h>
22#include <drm/drm_connector.h>
23
24#include "drm_internal.h"
25
26static inline void drm_hdcp_print_ksv(const u8 *ksv)
27{
28 DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n",
29 ksv[0], ksv[1], ksv[2], ksv[3], ksv[4]);
30}
31
32static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length)
33{
34 u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz;
35
36 while (parsed_bytes < vrls_length) {
37 vrl_ksv_cnt = *buf;
38 ksv_count += vrl_ksv_cnt;
39
40 vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1;
41 buf += vrl_sz;
42 parsed_bytes += vrl_sz;
43 }
44
45
46
47
48
49 if (parsed_bytes != vrls_length)
50 ksv_count = 0;
51
52 return ksv_count;
53}
54
55static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 **revoked_ksv_list,
56 u32 vrls_length)
57{
58 u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0;
59 u32 parsed_bytes = 0, ksv_count = 0;
60
61 do {
62 vrl_ksv_cnt = *buf;
63 vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN;
64
65 buf++;
66
67 DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++,
68 vrl_ksv_cnt);
69 memcpy((*revoked_ksv_list) + (ksv_count * DRM_HDCP_KSV_LEN),
70 buf, vrl_ksv_sz);
71
72 ksv_count += vrl_ksv_cnt;
73 buf += vrl_ksv_sz;
74
75 parsed_bytes += (vrl_ksv_sz + 1);
76 } while (parsed_bytes < vrls_length);
77
78 return ksv_count;
79}
80
81static inline u32 get_vrl_length(const u8 *buf)
82{
83 return drm_hdcp_be24_to_cpu(buf);
84}
85
86static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count,
87 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
88{
89 struct hdcp_srm_header *header;
90 u32 vrl_length, ksv_count;
91
92 if (count < (sizeof(struct hdcp_srm_header) +
93 DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) {
94 DRM_ERROR("Invalid blob length\n");
95 return -EINVAL;
96 }
97
98 header = (struct hdcp_srm_header *)buf;
99 DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
100 header->srm_id,
101 be16_to_cpu(header->srm_version), header->srm_gen_no);
102
103 WARN_ON(header->reserved);
104
105 buf = buf + sizeof(*header);
106 vrl_length = get_vrl_length(buf);
107 if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
108 vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
109 DRM_HDCP_1_4_DCP_SIG_SIZE)) {
110 DRM_ERROR("Invalid blob length or vrl length\n");
111 return -EINVAL;
112 }
113
114
115 vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
116 DRM_HDCP_1_4_DCP_SIG_SIZE);
117
118 if (!vrl_length) {
119 DRM_ERROR("No vrl found\n");
120 return -EINVAL;
121 }
122
123 buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE;
124 ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length);
125 if (!ksv_count) {
126 DRM_DEBUG("Revoked KSV count is 0\n");
127 return 0;
128 }
129
130 *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
131 if (!*revoked_ksv_list) {
132 DRM_ERROR("Out of Memory\n");
133 return -ENOMEM;
134 }
135
136 if (drm_hdcp_get_revoked_ksvs(buf, revoked_ksv_list,
137 vrl_length) != ksv_count) {
138 *revoked_ksv_cnt = 0;
139 kfree(*revoked_ksv_list);
140 return -EINVAL;
141 }
142
143 *revoked_ksv_cnt = ksv_count;
144 return 0;
145}
146
147static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count,
148 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
149{
150 struct hdcp_srm_header *header;
151 u32 vrl_length, ksv_count, ksv_sz;
152
153 if (count < (sizeof(struct hdcp_srm_header) +
154 DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) {
155 DRM_ERROR("Invalid blob length\n");
156 return -EINVAL;
157 }
158
159 header = (struct hdcp_srm_header *)buf;
160 DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
161 header->srm_id & DRM_HDCP_SRM_ID_MASK,
162 be16_to_cpu(header->srm_version), header->srm_gen_no);
163
164 if (header->reserved)
165 return -EINVAL;
166
167 buf = buf + sizeof(*header);
168 vrl_length = get_vrl_length(buf);
169
170 if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
171 vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE +
172 DRM_HDCP_2_DCP_SIG_SIZE)) {
173 DRM_ERROR("Invalid blob length or vrl length\n");
174 return -EINVAL;
175 }
176
177
178 vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE +
179 DRM_HDCP_2_DCP_SIG_SIZE);
180
181 if (!vrl_length) {
182 DRM_ERROR("No vrl found\n");
183 return -EINVAL;
184 }
185
186 buf += DRM_HDCP_2_VRL_LENGTH_SIZE;
187 ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1));
188 if (!ksv_count) {
189 DRM_DEBUG("Revoked KSV count is 0\n");
190 return 0;
191 }
192
193 *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
194 if (!*revoked_ksv_list) {
195 DRM_ERROR("Out of Memory\n");
196 return -ENOMEM;
197 }
198
199 ksv_sz = ksv_count * DRM_HDCP_KSV_LEN;
200 buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ;
201
202 DRM_DEBUG("Revoked KSVs: %d\n", ksv_count);
203 memcpy(*revoked_ksv_list, buf, ksv_sz);
204
205 *revoked_ksv_cnt = ksv_count;
206 return 0;
207}
208
209static inline bool is_srm_version_hdcp1(const u8 *buf)
210{
211 return *buf == (u8)(DRM_HDCP_1_4_SRM_ID << 4);
212}
213
214static inline bool is_srm_version_hdcp2(const u8 *buf)
215{
216 return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR);
217}
218
219static int drm_hdcp_srm_update(const u8 *buf, size_t count,
220 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
221{
222 if (count < sizeof(struct hdcp_srm_header))
223 return -EINVAL;
224
225 if (is_srm_version_hdcp1(buf))
226 return drm_hdcp_parse_hdcp1_srm(buf, count, revoked_ksv_list,
227 revoked_ksv_cnt);
228 else if (is_srm_version_hdcp2(buf))
229 return drm_hdcp_parse_hdcp2_srm(buf, count, revoked_ksv_list,
230 revoked_ksv_cnt);
231 else
232 return -EINVAL;
233}
234
235static int drm_hdcp_request_srm(struct drm_device *drm_dev,
236 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
237{
238 char fw_name[36] = "display_hdcp_srm.bin";
239 const struct firmware *fw;
240 int ret;
241
242 ret = request_firmware_direct(&fw, (const char *)fw_name,
243 drm_dev->dev);
244 if (ret < 0) {
245 *revoked_ksv_cnt = 0;
246 *revoked_ksv_list = NULL;
247 ret = 0;
248 goto exit;
249 }
250
251 if (fw->size && fw->data)
252 ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
253 revoked_ksv_cnt);
254
255exit:
256 release_firmware(fw);
257 return ret;
258}
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
286 u32 ksv_count)
287{
288 u32 revoked_ksv_cnt = 0, i, j;
289 u8 *revoked_ksv_list = NULL;
290 int ret = 0;
291
292 ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
293 &revoked_ksv_cnt);
294 if (ret)
295 return ret;
296
297
298 for (i = 0; i < revoked_ksv_cnt; i++)
299 for (j = 0; j < ksv_count; j++)
300 if (!memcmp(&ksvs[j * DRM_HDCP_KSV_LEN],
301 &revoked_ksv_list[i * DRM_HDCP_KSV_LEN],
302 DRM_HDCP_KSV_LEN)) {
303 DRM_DEBUG("Revoked KSV is ");
304 drm_hdcp_print_ksv(&ksvs[j * DRM_HDCP_KSV_LEN]);
305 ret++;
306 }
307
308 kfree(revoked_ksv_list);
309 return ret;
310}
311EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked);
312
313static struct drm_prop_enum_list drm_cp_enum_list[] = {
314 { DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
315 { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
316 { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" },
317};
318DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
319
320static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = {
321 { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" },
322 { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" },
323};
324DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name,
325 drm_hdcp_content_type_enum_list)
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357int drm_connector_attach_content_protection_property(
358 struct drm_connector *connector, bool hdcp_content_type)
359{
360 struct drm_device *dev = connector->dev;
361 struct drm_property *prop =
362 dev->mode_config.content_protection_property;
363
364 if (!prop)
365 prop = drm_property_create_enum(dev, 0, "Content Protection",
366 drm_cp_enum_list,
367 ARRAY_SIZE(drm_cp_enum_list));
368 if (!prop)
369 return -ENOMEM;
370
371 drm_object_attach_property(&connector->base, prop,
372 DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
373 dev->mode_config.content_protection_property = prop;
374
375 if (!hdcp_content_type)
376 return 0;
377
378 prop = dev->mode_config.hdcp_content_type_property;
379 if (!prop)
380 prop = drm_property_create_enum(dev, 0, "HDCP Content Type",
381 drm_hdcp_content_type_enum_list,
382 ARRAY_SIZE(
383 drm_hdcp_content_type_enum_list));
384 if (!prop)
385 return -ENOMEM;
386
387 drm_object_attach_property(&connector->base, prop,
388 DRM_MODE_HDCP_CONTENT_TYPE0);
389 dev->mode_config.hdcp_content_type_property = prop;
390
391 return 0;
392}
393EXPORT_SYMBOL(drm_connector_attach_content_protection_property);
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409void drm_hdcp_update_content_protection(struct drm_connector *connector,
410 u64 val)
411{
412 struct drm_device *dev = connector->dev;
413 struct drm_connector_state *state = connector->state;
414
415 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
416 if (state->content_protection == val)
417 return;
418
419 state->content_protection = val;
420 drm_sysfs_connector_status_event(connector,
421 dev->mode_config.content_protection_property);
422}
423EXPORT_SYMBOL(drm_hdcp_update_content_protection);
424