LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_displayid.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 62 0.0 %
Date: 2023-04-06 08:38:28 Functions: 0 7 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : /*
       3             :  * Copyright © 2021 Intel Corporation
       4             :  */
       5             : 
       6             : #include <drm/drm_displayid.h>
       7             : #include <drm/drm_edid.h>
       8             : #include <drm/drm_print.h>
       9             : 
      10             : static const struct displayid_header *
      11             : displayid_get_header(const u8 *displayid, int length, int index)
      12             : {
      13             :         const struct displayid_header *base;
      14             : 
      15           0 :         if (sizeof(*base) > length - index)
      16             :                 return ERR_PTR(-EINVAL);
      17             : 
      18           0 :         base = (const struct displayid_header *)&displayid[index];
      19             : 
      20             :         return base;
      21             : }
      22             : 
      23             : static const struct displayid_header *
      24           0 : validate_displayid(const u8 *displayid, int length, int idx)
      25             : {
      26             :         int i, dispid_length;
      27           0 :         u8 csum = 0;
      28             :         const struct displayid_header *base;
      29             : 
      30           0 :         base = displayid_get_header(displayid, length, idx);
      31           0 :         if (IS_ERR(base))
      32             :                 return base;
      33             : 
      34           0 :         DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
      35             :                       base->rev, base->bytes, base->prod_id, base->ext_count);
      36             : 
      37             :         /* +1 for DispID checksum */
      38           0 :         dispid_length = sizeof(*base) + base->bytes + 1;
      39           0 :         if (dispid_length > length - idx)
      40             :                 return ERR_PTR(-EINVAL);
      41             : 
      42           0 :         for (i = 0; i < dispid_length; i++)
      43           0 :                 csum += displayid[idx + i];
      44           0 :         if (csum) {
      45           0 :                 DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
      46           0 :                 return ERR_PTR(-EINVAL);
      47             :         }
      48             : 
      49             :         return base;
      50             : }
      51             : 
      52           0 : static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid,
      53             :                                               int *length, int *idx,
      54             :                                               int *ext_index)
      55             : {
      56           0 :         const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index);
      57             :         const struct displayid_header *base;
      58             : 
      59           0 :         if (!displayid)
      60             :                 return NULL;
      61             : 
      62             :         /* EDID extensions block checksum isn't for us */
      63           0 :         *length = EDID_LENGTH - 1;
      64           0 :         *idx = 1;
      65             : 
      66           0 :         base = validate_displayid(displayid, *length, *idx);
      67           0 :         if (IS_ERR(base))
      68             :                 return NULL;
      69             : 
      70           0 :         *length = *idx + sizeof(*base) + base->bytes;
      71             : 
      72           0 :         return displayid;
      73             : }
      74             : 
      75           0 : void displayid_iter_edid_begin(const struct drm_edid *drm_edid,
      76             :                                struct displayid_iter *iter)
      77             : {
      78           0 :         memset(iter, 0, sizeof(*iter));
      79             : 
      80           0 :         iter->drm_edid = drm_edid;
      81           0 : }
      82             : 
      83             : static const struct displayid_block *
      84             : displayid_iter_block(const struct displayid_iter *iter)
      85             : {
      86             :         const struct displayid_block *block;
      87             : 
      88           0 :         if (!iter->section)
      89             :                 return NULL;
      90             : 
      91           0 :         block = (const struct displayid_block *)&iter->section[iter->idx];
      92             : 
      93           0 :         if (iter->idx + sizeof(*block) <= iter->length &&
      94           0 :             iter->idx + sizeof(*block) + block->num_bytes <= iter->length)
      95             :                 return block;
      96             : 
      97             :         return NULL;
      98             : }
      99             : 
     100             : const struct displayid_block *
     101           0 : __displayid_iter_next(struct displayid_iter *iter)
     102             : {
     103             :         const struct displayid_block *block;
     104             : 
     105           0 :         if (!iter->drm_edid)
     106             :                 return NULL;
     107             : 
     108           0 :         if (iter->section) {
     109             :                 /* current block should always be valid */
     110           0 :                 block = displayid_iter_block(iter);
     111           0 :                 if (WARN_ON(!block)) {
     112           0 :                         iter->section = NULL;
     113           0 :                         iter->drm_edid = NULL;
     114           0 :                         return NULL;
     115             :                 }
     116             : 
     117             :                 /* next block in section */
     118           0 :                 iter->idx += sizeof(*block) + block->num_bytes;
     119             : 
     120           0 :                 block = displayid_iter_block(iter);
     121           0 :                 if (block)
     122             :                         return block;
     123             :         }
     124             : 
     125             :         for (;;) {
     126             :                 /* The first section we encounter is the base section */
     127           0 :                 bool base_section = !iter->section;
     128             : 
     129           0 :                 iter->section = drm_find_displayid_extension(iter->drm_edid,
     130             :                                                              &iter->length,
     131             :                                                              &iter->idx,
     132             :                                                              &iter->ext_index);
     133           0 :                 if (!iter->section) {
     134           0 :                         iter->drm_edid = NULL;
     135           0 :                         return NULL;
     136             :                 }
     137             : 
     138             :                 /* Save the structure version and primary use case. */
     139           0 :                 if (base_section) {
     140             :                         const struct displayid_header *base;
     141             : 
     142           0 :                         base = displayid_get_header(iter->section, iter->length,
     143             :                                                     iter->idx);
     144           0 :                         if (!IS_ERR(base)) {
     145           0 :                                 iter->version = base->rev;
     146           0 :                                 iter->primary_use = base->prod_id;
     147             :                         }
     148             :                 }
     149             : 
     150           0 :                 iter->idx += sizeof(struct displayid_header);
     151             : 
     152           0 :                 block = displayid_iter_block(iter);
     153           0 :                 if (block)
     154             :                         return block;
     155             :         }
     156             : }
     157             : 
     158           0 : void displayid_iter_end(struct displayid_iter *iter)
     159             : {
     160           0 :         memset(iter, 0, sizeof(*iter));
     161           0 : }
     162             : 
     163             : /* DisplayID Structure Version/Revision from the Base Section. */
     164           0 : u8 displayid_version(const struct displayid_iter *iter)
     165             : {
     166           0 :         return iter->version;
     167             : }
     168             : 
     169             : /*
     170             :  * DisplayID Primary Use Case (2.0+) or Product Type Identifier (1.0-1.3) from
     171             :  * the Base Section.
     172             :  */
     173           0 : u8 displayid_primary_use(const struct displayid_iter *iter)
     174             : {
     175           0 :         return iter->primary_use;
     176             : }

Generated by: LCOV version 1.14