summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2022-03-26 21:51:24 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2022-06-22 15:38:36 +0300
commit5225af309a5ab7d3c8d153e91046ed328e5113e3 (patch)
treea99bb7a5462b78a3d4167e36084508e8561fbd13
parentea28ce99ce79940fbc09964e550da431af712d33 (diff)
tools/intel_vbt_decode: Convert LFP data pointers to be relative to the data block
For some crazy reason the LFP data pointer offsets are specified as relative to the BDB header. That won't work with out private BDB block copies, so let's convert them to be relative to the start of the LFP data block. Reviewed-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
-rw-r--r--tools/intel_vbt_decode.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/tools/intel_vbt_decode.c b/tools/intel_vbt_decode.c
index 740940f9..8f80c79a 100644
--- a/tools/intel_vbt_decode.c
+++ b/tools/intel_vbt_decode.c
@@ -132,6 +132,21 @@ static const void *find_raw_section(const struct context *context, int section_i
return NULL;
}
+/*
+ * Offset from the start of BDB to the start of the
+ * block data (just past the block header).
+ */
+static u32 raw_block_offset(const struct context *context, enum bdb_block_id section_id)
+{
+ const void *block;
+
+ block = find_raw_section(context, section_id);
+ if (!block)
+ return 0;
+
+ return block - (const void *)context->bdb;
+}
+
static const void *block_data(const struct bdb_block *block)
{
return block->data + 3;
@@ -181,6 +196,37 @@ static size_t block_min_size(const struct context *context, int section_id)
}
}
+/* make the data table offsets relative to the data block */
+static bool fixup_lfp_data_ptrs(const struct context *context,
+ void *ptrs_block)
+{
+ struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block;
+ u32 offset;
+ int i;
+
+ offset = raw_block_offset(context, 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;
+ }
+
+ if (ptrs->panel_name.table_size) {
+ if (ptrs->panel_name.offset < offset)
+ return false;
+
+ ptrs->panel_name.offset -= offset;
+ }
+
+ return true;
+}
+
static struct bdb_block *find_section(const struct context *context, int section_id)
{
size_t min_size = block_min_size(context, section_id);
@@ -202,6 +248,13 @@ static struct bdb_block *find_section(const struct context *context, int section
block->size = size;
memcpy(block->data, data - 3, 3 + size);
+ if (section_id == BDB_LVDS_LFP_DATA_PTRS &&
+ !fixup_lfp_data_ptrs(context, 3 + block->data)) {
+ fprintf(stderr, "VBT has malformed LFP data table pointers\n");
+ free(block);
+ return NULL;
+ }
+
return block;
}