mirror of
https://github.com/tiagovignatti/intel-gpu-tools.git
synced 2025-06-12 02:16:17 +00:00
intel_bios_reader: rewrite the mipi sequence block dumping
Simplify things a lot, make it correct, don't pass random pointers to free() on errors, etc. Signed-off-by: Jani Nikula <jani.nikula@intel.com>
This commit is contained in:
parent
68cfe4ba57
commit
9c4aa072f0
@ -763,22 +763,31 @@ struct bdb_mipi_sequence {
|
|||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* MIPI Sequnece Block definitions */
|
/* MIPI Sequence Block definitions */
|
||||||
enum MIPI_SEQ {
|
enum mipi_seq {
|
||||||
MIPI_SEQ_UNDEFINED = 0,
|
MIPI_SEQ_END = 0,
|
||||||
MIPI_SEQ_ASSERT_RESET,
|
MIPI_SEQ_ASSERT_RESET,
|
||||||
MIPI_SEQ_INIT_OTP,
|
MIPI_SEQ_INIT_OTP,
|
||||||
MIPI_SEQ_DISPLAY_ON,
|
MIPI_SEQ_DISPLAY_ON,
|
||||||
MIPI_SEQ_DISPLAY_OFF,
|
MIPI_SEQ_DISPLAY_OFF,
|
||||||
MIPI_SEQ_DEASSERT_RESET,
|
MIPI_SEQ_DEASSERT_RESET,
|
||||||
|
MIPI_SEQ_BACKLIGHT_ON, /* sequence block v2+ */
|
||||||
|
MIPI_SEQ_BACKLIGHT_OFF, /* sequence block v2+ */
|
||||||
|
MIPI_SEQ_TEAR_ON, /* sequence block v2+ */
|
||||||
|
MIPI_SEQ_TEAR_OFF, /* sequence block v3+ */
|
||||||
|
MIPI_SEQ_POWER_ON, /* sequence block v3+ */
|
||||||
|
MIPI_SEQ_POWER_OFF, /* sequence block v3+ */
|
||||||
MIPI_SEQ_MAX
|
MIPI_SEQ_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MIPI_SEQ_ELEMENT {
|
enum mipi_seq_element {
|
||||||
MIPI_SEQ_ELEM_UNDEFINED = 0,
|
MIPI_SEQ_ELEM_END = 0,
|
||||||
MIPI_SEQ_ELEM_SEND_PKT,
|
MIPI_SEQ_ELEM_SEND_PKT,
|
||||||
MIPI_SEQ_ELEM_DELAY,
|
MIPI_SEQ_ELEM_DELAY,
|
||||||
MIPI_SEQ_ELEM_GPIO,
|
MIPI_SEQ_ELEM_GPIO,
|
||||||
|
MIPI_SEQ_ELEM_I2C, /* sequence block v2+ */
|
||||||
|
MIPI_SEQ_ELEM_SPI, /* sequence block v3+ */
|
||||||
|
MIPI_SEQ_ELEM_PMIC, /* sequence block v3+ */
|
||||||
MIPI_SEQ_ELEM_MAX
|
MIPI_SEQ_ELEM_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,15 +71,6 @@ struct bdb_block {
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const seq_name[] = {
|
|
||||||
"UNDEFINED",
|
|
||||||
"MIPI_SEQ_ASSERT_RESET",
|
|
||||||
"MIPI_SEQ_INIT_OTP",
|
|
||||||
"MIPI_SEQ_DISPLAY_ON",
|
|
||||||
"MIPI_SEQ_DISPLAY_OFF",
|
|
||||||
"MIPI_SEQ_DEASSERT_RESET",
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bdb_header *bdb;
|
struct bdb_header *bdb;
|
||||||
struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
|
struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
|
||||||
static int tv_present;
|
static int tv_present;
|
||||||
@ -858,7 +849,7 @@ static void dump_mipi_config(const struct bdb_block *block)
|
|||||||
printf("\t\tPanel power cycle delay: %d\n", pps->panel_power_cycle_delay);
|
printf("\t\tPanel power cycle delay: %d\n", pps->panel_power_cycle_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *mipi_dump_send_packet(uint8_t *data)
|
static const uint8_t *mipi_dump_send_packet(const uint8_t *data)
|
||||||
{
|
{
|
||||||
uint8_t type, byte, count;
|
uint8_t type, byte, count;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
@ -878,14 +869,14 @@ static uint8_t *mipi_dump_send_packet(uint8_t *data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *mipi_dump_delay(uint8_t *data)
|
static const uint8_t *mipi_dump_delay(const uint8_t *data)
|
||||||
{
|
{
|
||||||
printf("\t\t Delay : 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3]);
|
printf("\t\t Delay : 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3]);
|
||||||
data += 4;
|
data += 4;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *mipi_dump_gpio(uint8_t *data)
|
static const uint8_t *mipi_dump_gpio(const uint8_t *data)
|
||||||
{
|
{
|
||||||
uint8_t gpio, action;
|
uint8_t gpio, action;
|
||||||
|
|
||||||
@ -898,119 +889,66 @@ static uint8_t *mipi_dump_gpio(uint8_t *data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef uint8_t * (*fn_mipi_elem_dump)(uint8_t *data);
|
typedef const uint8_t * (*fn_mipi_elem_dump)(const uint8_t *data);
|
||||||
|
|
||||||
static const fn_mipi_elem_dump dump_elem[] = {
|
static const fn_mipi_elem_dump dump_elem[] = {
|
||||||
NULL, /* reserved */
|
[MIPI_SEQ_ELEM_SEND_PKT] = mipi_dump_send_packet,
|
||||||
mipi_dump_send_packet,
|
[MIPI_SEQ_ELEM_DELAY] = mipi_dump_delay,
|
||||||
mipi_dump_delay,
|
[MIPI_SEQ_ELEM_GPIO] = mipi_dump_gpio,
|
||||||
mipi_dump_gpio,
|
|
||||||
NULL, /* status read; later */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dump_sequence(uint8_t *sequence)
|
static const char * const seq_name[] = {
|
||||||
|
[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
|
||||||
|
[MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP",
|
||||||
|
[MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON",
|
||||||
|
[MIPI_SEQ_DISPLAY_OFF] = "MIPI_SEQ_DISPLAY_OFF",
|
||||||
|
[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
|
||||||
|
[MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON",
|
||||||
|
[MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF",
|
||||||
|
[MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON",
|
||||||
|
[MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF",
|
||||||
|
[MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON",
|
||||||
|
[MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *sequence_name(enum mipi_seq seq_id)
|
||||||
{
|
{
|
||||||
uint8_t *data = sequence;
|
if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id])
|
||||||
fn_mipi_elem_dump mipi_elem_dump;
|
return seq_name[seq_id];
|
||||||
int index_no;
|
else
|
||||||
|
return "(unknown)";
|
||||||
if (!sequence)
|
|
||||||
return;
|
|
||||||
|
|
||||||
printf("\tSequence Name: %s\n", seq_name[*data]);
|
|
||||||
|
|
||||||
/* go to the first element of the sequence */
|
|
||||||
data++;
|
|
||||||
|
|
||||||
/* parse each byte till we reach end of sequence byte - 0x00 */
|
|
||||||
while (1) {
|
|
||||||
index_no = *data;
|
|
||||||
mipi_elem_dump = dump_elem[index_no];
|
|
||||||
if (!mipi_elem_dump) {
|
|
||||||
printf("Error: Unsupported MIPI element, skipping sequence execution\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* goto element payload */
|
|
||||||
data++;
|
|
||||||
|
|
||||||
/* execute the element specifc rotines */
|
|
||||||
data = mipi_elem_dump(data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* After processing the element, data should point to
|
|
||||||
* next element or end of sequence
|
|
||||||
* check if have we reached end of sequence
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (*data == 0x00)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *goto_next_sequence(uint8_t *data, int *size)
|
static const uint8_t *dump_sequence(const uint8_t *data)
|
||||||
{
|
{
|
||||||
uint16_t len;
|
fn_mipi_elem_dump mipi_elem_dump;
|
||||||
int tmp = *size;
|
|
||||||
|
|
||||||
if (--tmp < 0)
|
printf("\tSequence %u - %s\n", *data, sequence_name(*data));
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* goto first element */
|
/* Skip Sequence Byte. */
|
||||||
data++;
|
data++;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (*data) {
|
uint8_t operation_byte = *data++;
|
||||||
case MIPI_SEQ_ELEM_SEND_PKT:
|
|
||||||
/*
|
|
||||||
* skip by this element payload size
|
|
||||||
* skip elem id, command flag and data type
|
|
||||||
*/
|
|
||||||
tmp -= 5;
|
|
||||||
if (tmp < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
data += 3;
|
if (operation_byte == MIPI_SEQ_ELEM_END)
|
||||||
len = *((uint16_t *)data);
|
|
||||||
|
|
||||||
tmp -= len;
|
|
||||||
if (tmp < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* skip by len */
|
|
||||||
data = data + 2 + len;
|
|
||||||
break;
|
break;
|
||||||
case MIPI_SEQ_ELEM_DELAY:
|
|
||||||
/* skip by elem id, and delay is 4 bytes */
|
|
||||||
tmp -= 5;
|
|
||||||
if (tmp < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
data += 5;
|
if (operation_byte < ARRAY_SIZE(dump_elem) &&
|
||||||
break;
|
dump_elem[operation_byte])
|
||||||
case MIPI_SEQ_ELEM_GPIO:
|
mipi_elem_dump = dump_elem[operation_byte];
|
||||||
tmp -= 3;
|
else
|
||||||
if (tmp < 0)
|
mipi_elem_dump = NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
data += 3;
|
if (mipi_elem_dump) {
|
||||||
break;
|
data = mipi_elem_dump(data);
|
||||||
default:
|
} else {
|
||||||
printf("Unknown element\n");
|
printf("Error: Unsupported MIPI element %u\n",
|
||||||
|
operation_byte);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* end of sequence ? */
|
|
||||||
if (*data == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* goto next sequence or end of block byte */
|
|
||||||
if (--tmp < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
data++;
|
|
||||||
|
|
||||||
/* update amount of data left for the sequence block to be parsed */
|
|
||||||
*size = tmp;
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,7 +964,7 @@ static uint16_t get_blocksize(void *p)
|
|||||||
static void dump_mipi_sequence(const struct bdb_block *block)
|
static void dump_mipi_sequence(const struct bdb_block *block)
|
||||||
{
|
{
|
||||||
struct bdb_mipi_sequence *sequence = block->data;
|
struct bdb_mipi_sequence *sequence = block->data;
|
||||||
uint8_t *data, *seq_data;
|
const uint8_t *data;
|
||||||
int i, panel_id, seq_size;
|
int i, panel_id, seq_size;
|
||||||
uint16_t block_size;
|
uint16_t block_size;
|
||||||
|
|
||||||
@ -1043,27 +981,26 @@ static void dump_mipi_sequence(const struct bdb_block *block)
|
|||||||
|
|
||||||
block_size = get_blocksize(sequence);
|
block_size = get_blocksize(sequence);
|
||||||
|
|
||||||
/*
|
data = &sequence->data[0];
|
||||||
* parse the sequence block for individual sequences
|
|
||||||
*/
|
|
||||||
seq_data = &sequence->data[0];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sequence block is variable length and hence we need to parse and
|
* sequence block is variable length and hence we need to parse and
|
||||||
* get the sequence data for specific panel id
|
* get the sequence data for specific panel id
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) {
|
for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) {
|
||||||
panel_id = *seq_data;
|
panel_id = *data;
|
||||||
seq_size = *((uint16_t *) (seq_data + 1));
|
seq_size = *((uint16_t *) (data + 1));
|
||||||
|
data += 3;
|
||||||
|
|
||||||
|
if (data + seq_size > (const uint8_t *)sequence + block_size) {
|
||||||
|
printf("Invalid sequence block\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (panel_id == panel_type)
|
if (panel_id == panel_type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* skip the sequence including seq header of 3 bytes */
|
data += seq_size;
|
||||||
seq_data = seq_data + 3 + seq_size;
|
|
||||||
if ((seq_data - &sequence->data[0]) > block_size) {
|
|
||||||
printf("Sequence start is beyond sequence block size, corrupted sequence block\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == MAX_MIPI_CONFIGURATIONS) {
|
if (i == MAX_MIPI_CONFIGURATIONS) {
|
||||||
@ -1071,55 +1008,22 @@ static void dump_mipi_sequence(const struct bdb_block *block)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if found sequence is completely within the sequence block
|
|
||||||
* just being paranoid */
|
|
||||||
if (seq_size > block_size) {
|
|
||||||
printf("Corrupted sequence/size, bailing out\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip the panel id(1 byte) and seq size(2 bytes) */
|
|
||||||
data = (uint8_t *) calloc(1, seq_size);
|
|
||||||
if (data)
|
|
||||||
memmove(data, seq_data + 3, seq_size);
|
|
||||||
else {
|
|
||||||
printf("Memory not allocated for sequence data\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* loop into the sequence data and split into multiple sequneces
|
* loop into the sequence data and split into multiple sequneces
|
||||||
* There are only 5 types of sequences as of now
|
* There are only 5 types of sequences as of now
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* two consecutive 0x00 indicate end of all sequences */
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int seq_id = *data;
|
int seq_id = *data;
|
||||||
if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED)
|
if (seq_id == MIPI_SEQ_END)
|
||||||
dump_sequence(data);
|
break;
|
||||||
else {
|
|
||||||
printf("Error:undefined sequence\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* partial parsing to skip elements */
|
data = dump_sequence(data);
|
||||||
data = goto_next_sequence(data, &seq_size);
|
if (!data)
|
||||||
|
break;
|
||||||
if (data == NULL) {
|
|
||||||
printf("Sequence elements going beyond block itself. Sequence block parsing failed\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*data == 0)
|
|
||||||
break; /* end of sequence reached */
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
err:
|
|
||||||
free(data);
|
|
||||||
data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_device_id(unsigned char *bios, int size)
|
get_device_id(unsigned char *bios, int size)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user