0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/err.h>
0011 #include <linux/gfp.h>
0012 #include <linux/export.h>
0013 #include <linux/slab.h>
0014 #include <linux/firmware.h>
0015
0016 #include <drm/display/drm_hdcp_helper.h>
0017 #include <drm/drm_sysfs.h>
0018 #include <drm/drm_print.h>
0019 #include <drm/drm_device.h>
0020 #include <drm/drm_property.h>
0021 #include <drm/drm_mode_object.h>
0022 #include <drm/drm_connector.h>
0023
0024 static inline void drm_hdcp_print_ksv(const u8 *ksv)
0025 {
0026 DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n",
0027 ksv[0], ksv[1], ksv[2], ksv[3], ksv[4]);
0028 }
0029
0030 static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length)
0031 {
0032 u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz;
0033
0034 while (parsed_bytes < vrls_length) {
0035 vrl_ksv_cnt = *buf;
0036 ksv_count += vrl_ksv_cnt;
0037
0038 vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1;
0039 buf += vrl_sz;
0040 parsed_bytes += vrl_sz;
0041 }
0042
0043
0044
0045
0046
0047 if (parsed_bytes != vrls_length)
0048 ksv_count = 0;
0049
0050 return ksv_count;
0051 }
0052
0053 static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 **revoked_ksv_list,
0054 u32 vrls_length)
0055 {
0056 u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0;
0057 u32 parsed_bytes = 0, ksv_count = 0;
0058
0059 do {
0060 vrl_ksv_cnt = *buf;
0061 vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN;
0062
0063 buf++;
0064
0065 DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++,
0066 vrl_ksv_cnt);
0067 memcpy((*revoked_ksv_list) + (ksv_count * DRM_HDCP_KSV_LEN),
0068 buf, vrl_ksv_sz);
0069
0070 ksv_count += vrl_ksv_cnt;
0071 buf += vrl_ksv_sz;
0072
0073 parsed_bytes += (vrl_ksv_sz + 1);
0074 } while (parsed_bytes < vrls_length);
0075
0076 return ksv_count;
0077 }
0078
0079 static inline u32 get_vrl_length(const u8 *buf)
0080 {
0081 return drm_hdcp_be24_to_cpu(buf);
0082 }
0083
0084 static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count,
0085 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
0086 {
0087 struct hdcp_srm_header *header;
0088 u32 vrl_length, ksv_count;
0089
0090 if (count < (sizeof(struct hdcp_srm_header) +
0091 DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) {
0092 DRM_ERROR("Invalid blob length\n");
0093 return -EINVAL;
0094 }
0095
0096 header = (struct hdcp_srm_header *)buf;
0097 DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
0098 header->srm_id,
0099 be16_to_cpu(header->srm_version), header->srm_gen_no);
0100
0101 WARN_ON(header->reserved);
0102
0103 buf = buf + sizeof(*header);
0104 vrl_length = get_vrl_length(buf);
0105 if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
0106 vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
0107 DRM_HDCP_1_4_DCP_SIG_SIZE)) {
0108 DRM_ERROR("Invalid blob length or vrl length\n");
0109 return -EINVAL;
0110 }
0111
0112
0113 vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
0114 DRM_HDCP_1_4_DCP_SIG_SIZE);
0115
0116 if (!vrl_length) {
0117 DRM_ERROR("No vrl found\n");
0118 return -EINVAL;
0119 }
0120
0121 buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE;
0122 ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length);
0123 if (!ksv_count) {
0124 DRM_DEBUG("Revoked KSV count is 0\n");
0125 return 0;
0126 }
0127
0128 *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
0129 if (!*revoked_ksv_list) {
0130 DRM_ERROR("Out of Memory\n");
0131 return -ENOMEM;
0132 }
0133
0134 if (drm_hdcp_get_revoked_ksvs(buf, revoked_ksv_list,
0135 vrl_length) != ksv_count) {
0136 *revoked_ksv_cnt = 0;
0137 kfree(*revoked_ksv_list);
0138 return -EINVAL;
0139 }
0140
0141 *revoked_ksv_cnt = ksv_count;
0142 return 0;
0143 }
0144
0145 static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count,
0146 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
0147 {
0148 struct hdcp_srm_header *header;
0149 u32 vrl_length, ksv_count, ksv_sz;
0150
0151 if (count < (sizeof(struct hdcp_srm_header) +
0152 DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) {
0153 DRM_ERROR("Invalid blob length\n");
0154 return -EINVAL;
0155 }
0156
0157 header = (struct hdcp_srm_header *)buf;
0158 DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
0159 header->srm_id & DRM_HDCP_SRM_ID_MASK,
0160 be16_to_cpu(header->srm_version), header->srm_gen_no);
0161
0162 if (header->reserved)
0163 return -EINVAL;
0164
0165 buf = buf + sizeof(*header);
0166 vrl_length = get_vrl_length(buf);
0167
0168 if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
0169 vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE +
0170 DRM_HDCP_2_DCP_SIG_SIZE)) {
0171 DRM_ERROR("Invalid blob length or vrl length\n");
0172 return -EINVAL;
0173 }
0174
0175
0176 vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE +
0177 DRM_HDCP_2_DCP_SIG_SIZE);
0178
0179 if (!vrl_length) {
0180 DRM_ERROR("No vrl found\n");
0181 return -EINVAL;
0182 }
0183
0184 buf += DRM_HDCP_2_VRL_LENGTH_SIZE;
0185 ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1));
0186 if (!ksv_count) {
0187 DRM_DEBUG("Revoked KSV count is 0\n");
0188 return 0;
0189 }
0190
0191 *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
0192 if (!*revoked_ksv_list) {
0193 DRM_ERROR("Out of Memory\n");
0194 return -ENOMEM;
0195 }
0196
0197 ksv_sz = ksv_count * DRM_HDCP_KSV_LEN;
0198 buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ;
0199
0200 DRM_DEBUG("Revoked KSVs: %d\n", ksv_count);
0201 memcpy(*revoked_ksv_list, buf, ksv_sz);
0202
0203 *revoked_ksv_cnt = ksv_count;
0204 return 0;
0205 }
0206
0207 static inline bool is_srm_version_hdcp1(const u8 *buf)
0208 {
0209 return *buf == (u8)(DRM_HDCP_1_4_SRM_ID << 4);
0210 }
0211
0212 static inline bool is_srm_version_hdcp2(const u8 *buf)
0213 {
0214 return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR);
0215 }
0216
0217 static int drm_hdcp_srm_update(const u8 *buf, size_t count,
0218 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
0219 {
0220 if (count < sizeof(struct hdcp_srm_header))
0221 return -EINVAL;
0222
0223 if (is_srm_version_hdcp1(buf))
0224 return drm_hdcp_parse_hdcp1_srm(buf, count, revoked_ksv_list,
0225 revoked_ksv_cnt);
0226 else if (is_srm_version_hdcp2(buf))
0227 return drm_hdcp_parse_hdcp2_srm(buf, count, revoked_ksv_list,
0228 revoked_ksv_cnt);
0229 else
0230 return -EINVAL;
0231 }
0232
0233 static int drm_hdcp_request_srm(struct drm_device *drm_dev,
0234 u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
0235 {
0236 char fw_name[36] = "display_hdcp_srm.bin";
0237 const struct firmware *fw;
0238 int ret;
0239
0240 ret = request_firmware_direct(&fw, (const char *)fw_name,
0241 drm_dev->dev);
0242 if (ret < 0) {
0243 *revoked_ksv_cnt = 0;
0244 *revoked_ksv_list = NULL;
0245 ret = 0;
0246 goto exit;
0247 }
0248
0249 if (fw->size && fw->data)
0250 ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
0251 revoked_ksv_cnt);
0252
0253 exit:
0254 release_firmware(fw);
0255 return ret;
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
0284 u32 ksv_count)
0285 {
0286 u32 revoked_ksv_cnt = 0, i, j;
0287 u8 *revoked_ksv_list = NULL;
0288 int ret = 0;
0289
0290 ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
0291 &revoked_ksv_cnt);
0292 if (ret)
0293 return ret;
0294
0295
0296 for (i = 0; i < revoked_ksv_cnt; i++)
0297 for (j = 0; j < ksv_count; j++)
0298 if (!memcmp(&ksvs[j * DRM_HDCP_KSV_LEN],
0299 &revoked_ksv_list[i * DRM_HDCP_KSV_LEN],
0300 DRM_HDCP_KSV_LEN)) {
0301 DRM_DEBUG("Revoked KSV is ");
0302 drm_hdcp_print_ksv(&ksvs[j * DRM_HDCP_KSV_LEN]);
0303 ret++;
0304 }
0305
0306 kfree(revoked_ksv_list);
0307 return ret;
0308 }
0309 EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked);
0310
0311 static struct drm_prop_enum_list drm_cp_enum_list[] = {
0312 { DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
0313 { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
0314 { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" },
0315 };
0316 DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
0317
0318 static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = {
0319 { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" },
0320 { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" },
0321 };
0322 DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name,
0323 drm_hdcp_content_type_enum_list)
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 int drm_connector_attach_content_protection_property(
0356 struct drm_connector *connector, bool hdcp_content_type)
0357 {
0358 struct drm_device *dev = connector->dev;
0359 struct drm_property *prop =
0360 dev->mode_config.content_protection_property;
0361
0362 if (!prop)
0363 prop = drm_property_create_enum(dev, 0, "Content Protection",
0364 drm_cp_enum_list,
0365 ARRAY_SIZE(drm_cp_enum_list));
0366 if (!prop)
0367 return -ENOMEM;
0368
0369 drm_object_attach_property(&connector->base, prop,
0370 DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
0371 dev->mode_config.content_protection_property = prop;
0372
0373 if (!hdcp_content_type)
0374 return 0;
0375
0376 prop = dev->mode_config.hdcp_content_type_property;
0377 if (!prop)
0378 prop = drm_property_create_enum(dev, 0, "HDCP Content Type",
0379 drm_hdcp_content_type_enum_list,
0380 ARRAY_SIZE(
0381 drm_hdcp_content_type_enum_list));
0382 if (!prop)
0383 return -ENOMEM;
0384
0385 drm_object_attach_property(&connector->base, prop,
0386 DRM_MODE_HDCP_CONTENT_TYPE0);
0387 dev->mode_config.hdcp_content_type_property = prop;
0388
0389 return 0;
0390 }
0391 EXPORT_SYMBOL(drm_connector_attach_content_protection_property);
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 void drm_hdcp_update_content_protection(struct drm_connector *connector,
0408 u64 val)
0409 {
0410 struct drm_device *dev = connector->dev;
0411 struct drm_connector_state *state = connector->state;
0412
0413 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
0414 if (state->content_protection == val)
0415 return;
0416
0417 state->content_protection = val;
0418 drm_sysfs_connector_status_event(connector,
0419 dev->mode_config.content_protection_property);
0420 }
0421 EXPORT_SYMBOL(drm_hdcp_update_content_protection);