From 9c4aa072f071d4cfe1513a723419f43e43fe3293 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Dec 2015 16:18:20 +0200 Subject: 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 --- tools/intel_bios.h | 19 ++-- tools/intel_bios_reader.c | 224 +++++++++++++--------------------------------- 2 files changed, 78 insertions(+), 165 deletions(-) (limited to 'tools') diff --git a/tools/intel_bios.h b/tools/intel_bios.h index 6135a2b4..b7ebd48e 100644 --- a/tools/intel_bios.h +++ b/tools/intel_bios.h @@ -763,22 +763,31 @@ struct bdb_mipi_sequence { uint8_t data[0]; } __attribute__ ((packed)); -/* MIPI Sequnece Block definitions */ -enum MIPI_SEQ { - MIPI_SEQ_UNDEFINED = 0, +/* MIPI Sequence Block definitions */ +enum mipi_seq { + MIPI_SEQ_END = 0, MIPI_SEQ_ASSERT_RESET, MIPI_SEQ_INIT_OTP, MIPI_SEQ_DISPLAY_ON, MIPI_SEQ_DISPLAY_OFF, 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 }; -enum MIPI_SEQ_ELEMENT { - MIPI_SEQ_ELEM_UNDEFINED = 0, +enum mipi_seq_element { + MIPI_SEQ_ELEM_END = 0, MIPI_SEQ_ELEM_SEND_PKT, MIPI_SEQ_ELEM_DELAY, 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 }; diff --git a/tools/intel_bios_reader.c b/tools/intel_bios_reader.c index 09ca50d4..1b1cb6bc 100644 --- a/tools/intel_bios_reader.c +++ b/tools/intel_bios_reader.c @@ -71,15 +71,6 @@ struct bdb_block { 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_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; 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); } -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; uint16_t len; @@ -878,14 +869,14 @@ static uint8_t *mipi_dump_send_packet(uint8_t *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]); data += 4; 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; @@ -898,119 +889,66 @@ static uint8_t *mipi_dump_gpio(uint8_t *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[] = { - NULL, /* reserved */ - mipi_dump_send_packet, - mipi_dump_delay, - mipi_dump_gpio, - NULL, /* status read; later */ + [MIPI_SEQ_ELEM_SEND_PKT] = mipi_dump_send_packet, + [MIPI_SEQ_ELEM_DELAY] = mipi_dump_delay, + [MIPI_SEQ_ELEM_GPIO] = mipi_dump_gpio, }; -static void dump_sequence(uint8_t *sequence) -{ - uint8_t *data = sequence; - fn_mipi_elem_dump mipi_elem_dump; - int index_no; - - 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 - */ +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", +}; - if (*data == 0x00) - break; - } +static const char *sequence_name(enum mipi_seq seq_id) +{ + if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id]) + return seq_name[seq_id]; + else + return "(unknown)"; } -static uint8_t *goto_next_sequence(uint8_t *data, int *size) +static const uint8_t *dump_sequence(const uint8_t *data) { - uint16_t len; - int tmp = *size; + fn_mipi_elem_dump mipi_elem_dump; - if (--tmp < 0) - return NULL; + printf("\tSequence %u - %s\n", *data, sequence_name(*data)); - /* goto first element */ + /* Skip Sequence Byte. */ data++; - while (1) { - switch (*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; - len = *((uint16_t *)data); - - tmp -= len; - if (tmp < 0) - return NULL; - - /* skip by len */ - data = data + 2 + len; - break; - case MIPI_SEQ_ELEM_DELAY: - /* skip by elem id, and delay is 4 bytes */ - tmp -= 5; - if (tmp < 0) - return NULL; - data += 5; - break; - case MIPI_SEQ_ELEM_GPIO: - tmp -= 3; - if (tmp < 0) - return NULL; - - data += 3; - break; - default: - printf("Unknown element\n"); - return NULL; - } + while (1) { + uint8_t operation_byte = *data++; - /* end of sequence ? */ - if (*data == 0) + if (operation_byte == MIPI_SEQ_ELEM_END) break; - } - /* goto next sequence or end of block byte */ - if (--tmp < 0) - return NULL; + if (operation_byte < ARRAY_SIZE(dump_elem) && + dump_elem[operation_byte]) + mipi_elem_dump = dump_elem[operation_byte]; + else + mipi_elem_dump = NULL; - data++; + if (mipi_elem_dump) { + data = mipi_elem_dump(data); + } else { + printf("Error: Unsupported MIPI element %u\n", + operation_byte); + return NULL; + } + } - /* update amount of data left for the sequence block to be parsed */ - *size = tmp; return data; } @@ -1026,7 +964,7 @@ static uint16_t get_blocksize(void *p) static void dump_mipi_sequence(const struct bdb_block *block) { struct bdb_mipi_sequence *sequence = block->data; - uint8_t *data, *seq_data; + const uint8_t *data; int i, panel_id, seq_size; uint16_t block_size; @@ -1043,27 +981,26 @@ static void dump_mipi_sequence(const struct bdb_block *block) block_size = get_blocksize(sequence); - /* - * parse the sequence block for individual sequences - */ - seq_data = &sequence->data[0]; + data = &sequence->data[0]; /* * sequence block is variable length and hence we need to parse and * get the sequence data for specific panel id */ for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) { - panel_id = *seq_data; - seq_size = *((uint16_t *) (seq_data + 1)); - if (panel_id == panel_type) - break; + panel_id = *data; + seq_size = *((uint16_t *) (data + 1)); + data += 3; - /* skip the sequence including seq header of 3 bytes */ - 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"); + if (data + seq_size > (const uint8_t *)sequence + block_size) { + printf("Invalid sequence block\n"); return; } + + if (panel_id == panel_type) + break; + + data += seq_size; } if (i == MAX_MIPI_CONFIGURATIONS) { @@ -1071,55 +1008,22 @@ static void dump_mipi_sequence(const struct bdb_block *block) 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 * There are only 5 types of sequences as of now */ - /* two consecutive 0x00 indicate end of all sequences */ while (1) { int seq_id = *data; - if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED) - dump_sequence(data); - else { - printf("Error:undefined sequence\n"); - goto err; - } - - /* partial parsing to skip elements */ - data = goto_next_sequence(data, &seq_size); - - 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; + if (seq_id == MIPI_SEQ_END) + break; -err: - free(data); - data = NULL; + data = dump_sequence(data); + if (!data) + break; + } } - static int get_device_id(unsigned char *bios, int size) { -- cgit v1.2.3