fix(handoff): correct representation of tag_id

The tag ID is a 3-byte field used to identify the contents of a TE. In
our library, the internal representation of the tag is a 2 byte field.
We currently ignore the top byte of this field, marking it res0. This
causes problems when dealing with non-standard TE types, whose range
starts at 0xff_f000.  This commit fixes this by using a bit-field with a
24-bit width, and packing `transfer_list_entry`.

Change-Id: Ib3c212f964b64f528ad6f3dd6ab8b4597b877cd9
Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index 5ea5a41..9a5e692 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023-2024, Linaro Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -73,9 +73,8 @@
 	 */
 };
 
-struct transfer_list_entry {
-	uint16_t tag_id;
-	uint8_t reserved0; /* place holder */
+struct __attribute__((packed)) transfer_list_entry {
+	uint32_t tag_id : 24;
 	uint8_t hdr_size;
 	uint32_t data_size;
 	/*
@@ -89,6 +88,8 @@
 	 */
 };
 
+CASSERT(sizeof(struct transfer_list_entry) == U(0x8), assert_transfer_list_entry_size);
+
 void transfer_list_dump(struct transfer_list_header *tl);
 entry_point_info_t *
 transfer_list_set_handoff_args(struct transfer_list_header *tl,
@@ -113,12 +114,12 @@
 		       struct transfer_list_entry *entry);
 
 struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
-					      uint16_t tag_id,
+					      uint32_t tag_id,
 					      uint32_t data_size,
 					      const void *data);
 
 struct transfer_list_entry *
-transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id,
+transfer_list_add_with_align(struct transfer_list_header *tl, uint32_t tag_id,
 			     uint32_t data_size, const void *data,
 			     uint8_t alignment);
 
@@ -127,7 +128,7 @@
 		   struct transfer_list_entry *last);
 
 struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
-					       uint16_t tag_id);
+					       uint32_t tag_id);
 
 #endif /*__ASSEMBLER__*/
 #endif /*__TRANSFER_LIST_H*/
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index 63969e9..b7fedfa 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -366,7 +366,6 @@
 		/* create a dummy TE to fill up the gap */
 		dummy_te = (struct transfer_list_entry *)new_ev;
 		dummy_te->tag_id = TL_TAG_EMPTY;
-		dummy_te->reserved0 = 0;
 		dummy_te->hdr_size = sizeof(*dummy_te);
 		dummy_te->data_size = gap - sizeof(*dummy_te);
 	}
@@ -388,7 +387,6 @@
 		return false;
 	}
 	te->tag_id = TL_TAG_EMPTY;
-	te->reserved0 = 0;
 	transfer_list_update_checksum(tl);
 	return true;
 }
@@ -399,7 +397,7 @@
  * Return pointer to the added transfer entry or NULL on error
  ******************************************************************************/
 struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
-					      uint16_t tag_id,
+					      uint32_t tag_id,
 					      uint32_t data_size,
 					      const void *data)
 {
@@ -428,7 +426,6 @@
 
 	te = (struct transfer_list_entry *)tl_ev;
 	te->tag_id = tag_id;
-	te->reserved0 = 0;
 	te->hdr_size = sizeof(*te);
 	te->data_size = data_size;
 	tl->size += ev - tl_ev;
@@ -454,7 +451,7 @@
  * Return pointer to the added transfer entry or NULL on error
  ******************************************************************************/
 struct transfer_list_entry *
-transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id,
+transfer_list_add_with_align(struct transfer_list_header *tl, uint32_t tag_id,
 			     uint32_t data_size, const void *data,
 			     uint8_t alignment)
 {
@@ -501,13 +498,13 @@
  * Return pointer to the found transfer entry or NULL on error
  ******************************************************************************/
 struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
-					       uint16_t tag_id)
+					       uint32_t tag_id)
 {
 	struct transfer_list_entry *te = NULL;
 
 	do {
 		te = transfer_list_next(tl, te);
-	} while (te && (te->tag_id != tag_id || te->reserved0 != 0));
+	} while (te && (te->tag_id != tag_id));
 
 	return te;
 }