On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@xxxxxxxxxxxxxxx> wrote: > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > Currently get_lvds_fp_timing() still returns a pointer to the original > data block rather than our copy. Let's convert the data pointer offsets > to be relative to the data block rather than the whole BDB. With that > we can make get_lvds_fp_timing() return a pointer to the copy. > > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Reviewed-by: Jani Nikula <jani.nikula@xxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_bios.c | 41 +++++++++++++++++++---- > 1 file changed, 34 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c > index 2e9f639d092e..000544280c35 100644 > --- a/drivers/gpu/drm/i915/display/intel_bios.c > +++ b/drivers/gpu/drm/i915/display/intel_bios.c > @@ -191,6 +191,29 @@ static const struct { > .min_size = sizeof(struct bdb_generic_dtd), }, > }; > > +/* make the data table offsets relative to the data block */ > +static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block) > +{ > + struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block; > + u32 offset; > + int i; > + > + offset = block_offset(bdb, BDB_LVDS_LFP_DATA); > + > + for (i = 0; i < 16; i++) { > + if (ptrs->ptr[i].fp_timing.offset < offset || > + ptrs->ptr[i].dvo_timing.offset < offset || > + ptrs->ptr[i].panel_pnp_id.offset < offset) > + return false; > + > + ptrs->ptr[i].fp_timing.offset -= offset; > + ptrs->ptr[i].dvo_timing.offset -= offset; > + ptrs->ptr[i].panel_pnp_id.offset -= offset; > + } > + > + return true; > +} > + > static void > init_bdb_block(struct drm_i915_private *i915, > const void *bdb, enum bdb_block_id section_id, > @@ -217,6 +240,13 @@ init_bdb_block(struct drm_i915_private *i915, > drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n", > section_id, block_size, min_size); > > + if (section_id == BDB_LVDS_LFP_DATA_PTRS && > + !fixup_lfp_data_ptrs(bdb, entry->data + 3)) { > + drm_err(&i915->drm, "VBT has malformed LFP data table pointers\n"); > + kfree(entry); > + return; > + } > + > list_add_tail(&entry->node, &i915->vbt.bdb_blocks); > } > > @@ -312,22 +342,19 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data, > * this function may return NULL if the corresponding entry is invalid > */ > static const struct lvds_fp_timing * > -get_lvds_fp_timing(const struct bdb_header *bdb, > - const struct bdb_lvds_lfp_data *data, > +get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data, > const struct bdb_lvds_lfp_data_ptrs *ptrs, > int index) > { > - size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA); > u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ > size_t ofs; > > if (index >= ARRAY_SIZE(ptrs->ptr)) > return NULL; > ofs = ptrs->ptr[index].fp_timing.offset; > - if (ofs < data_ofs || > - ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) > + if (ofs + sizeof(struct lvds_fp_timing) > data_size) > return NULL; > - return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); > + return (const struct lvds_fp_timing *)((const u8 *)data + ofs); > } > > /* Parse general panel options */ > @@ -426,7 +453,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915, > "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n", > DRM_MODE_ARG(panel_fixed_mode)); > > - fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, > + fp_timing = get_lvds_fp_timing(lvds_lfp_data, > lvds_lfp_data_ptrs, > panel_type); > if (fp_timing) { -- Jani Nikula, Intel Open Source Graphics Center