[Intel-gfx] [i-g-t PATCH 3/5] intel_bios_reader: rewrite the mipi sequence block dumping

Jani Nikula jani.nikula at intel.com
Mon Dec 21 07:05:54 PST 2015


Simplify things a lot, make it correct, don't pass random pointers to
free() on errors, etc.

Signed-off-by: Jani Nikula <jani.nikula at intel.com>
---
 tools/intel_bios.h        |  19 ++--
 tools/intel_bios_reader.c | 224 +++++++++++++---------------------------------
 2 files changed, 78 insertions(+), 165 deletions(-)

diff --git a/tools/intel_bios.h b/tools/intel_bios.h
index 6135a2b47055..b7ebd48ef7e7 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 09ca50d44a77..1b1cb6bc8ebf 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)
 {
-- 
2.1.4



More information about the Intel-gfx mailing list