build(handoff)!: switch to LibTL submodule

Removes in-tree Transfer List implementation and updates all references
to use the external LibTL submodule. Updates include paths, Makefile
macros, and platform integration logic to link with LibTL as a static
library.

If you cloned TF-A without the `--recurse-submodules` flag, you can
ensure that this submodule is present by running:

    git submodule update --init --recursive

BREAKING-CHANGE: LibTL is now included in TF-A as a submodule.
  Please run `git submodule update --init --recursive` if you encounter
  issues after migrating to the latest version of TF-A.

Change-Id: I1fa31f7b730066c27985d968698e553b00b07c38
Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
diff --git a/contrib/libtl b/contrib/libtl
index 9630cb0..67d85f1 160000
--- a/contrib/libtl
+++ b/contrib/libtl
@@ -1 +1 @@
-Subproject commit 9630cb01984503a9fe6974d31b0d581fb693540c
+Subproject commit 67d85f181b726d2823eea43e8bb4ffb97559d348
diff --git a/include/drivers/measured_boot/event_log/event_handoff.h b/include/drivers/measured_boot/event_log/event_handoff.h
index e969d1f..f8c8716 100644
--- a/include/drivers/measured_boot/event_log/event_handoff.h
+++ b/include/drivers/measured_boot/event_log/event_handoff.h
@@ -10,7 +10,7 @@
 
 #include <stdint.h>
 
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 
 /**
  * Initializes or extends the TPM event log in the transfer list.
diff --git a/include/drivers/measured_boot/event_log/event_log.h b/include/drivers/measured_boot/event_log/event_log.h
index b5adfdc..1313111 100644
--- a/include/drivers/measured_boot/event_log/event_log.h
+++ b/include/drivers/measured_boot/event_log/event_log.h
@@ -11,7 +11,9 @@
 #include <stdint.h>
 
 #include <drivers/auth/crypto_mod.h>
+#if TRANSFER_LIST
 #include "event_handoff.h"
+#endif
 #include "tcg.h"
 
 /*
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
deleted file mode 100644
index bdc6349..0000000
--- a/include/lib/transfer_list.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2023-2024, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __TRANSFER_LIST_H
-#define __TRANSFER_LIST_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <common/ep_info.h>
-#include <lib/utils_def.h>
-
-#define TRANSFER_LIST_SIGNATURE U(0x4a0fb10b)
-#define TRANSFER_LIST_VERSION U(0x0001)
-
-/*
- * Init value of maximum alignment required by any TE data in the TL
- * specified as a power of two
- */
-#define TRANSFER_LIST_INIT_MAX_ALIGN U(3)
-
-/* Alignment required by TE header start address, in bytes */
-#define TRANSFER_LIST_GRANULE U(8)
-
-/*
- * Version of the register convention used.
- * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
- */
-#define REGISTER_CONVENTION_VERSION_SHIFT_64	UL(32)
-#define REGISTER_CONVENTION_VERSION_SHIFT_32	UL(24)
-#define REGISTER_CONVENTION_VERSION_MASK	UL(0xff)
-#define REGISTER_CONVENTION_VERSION 	UL(1)
-
-#define TRANSFER_LIST_HANDOFF_X1_VALUE(__version) 	\
-	((TRANSFER_LIST_SIGNATURE &	\
-	((1UL << REGISTER_CONVENTION_VERSION_SHIFT_64) - 1)) | 	\
-	(((__version) & REGISTER_CONVENTION_VERSION_MASK) <<	\
-	 REGISTER_CONVENTION_VERSION_SHIFT_64))
-
-#define TRANSFER_LIST_HANDOFF_R1_VALUE(__version) 	\
-	((TRANSFER_LIST_SIGNATURE &	\
-	((1UL << REGISTER_CONVENTION_VERSION_SHIFT_32) - 1)) | 	\
-	(((__version) & REGISTER_CONVENTION_VERSION_MASK) <<	\
-	 REGISTER_CONVENTION_VERSION_SHIFT_32))
-
-#ifndef __ASSEMBLER__
-
-#define TL_FLAGS_HAS_CHECKSUM BIT(0)
-
-enum transfer_list_tag_id {
-	TL_TAG_EMPTY = 0,
-	TL_TAG_FDT = 1,
-	TL_TAG_HOB_BLOCK = 2,
-	TL_TAG_HOB_LIST = 3,
-	TL_TAG_ACPI_TABLE_AGGREGATE = 4,
-	TL_TAG_TPM_EVLOG = 5,
-	TL_TAG_OPTEE_PAGABLE_PART = 0x100,
-	TL_TAG_DT_SPMC_MANIFEST = 0x101,
-	TL_TAG_EXEC_EP_INFO64 = 0x102,
-	TL_TAG_SRAM_LAYOUT64 = 0x104,
-	TL_TAG_MBEDTLS_HEAP_INFO = 0x105,
-	TL_TAG_EXEC_EP_INFO32 = 0x106,
-	TL_TAG_SRAM_LAYOUT32 = 0x107,
-};
-
-enum transfer_list_ops {
-	TL_OPS_NON, /* invalid for any operation */
-	TL_OPS_ALL, /* valid for all operations */
-	TL_OPS_RO, /* valid for read only */
-	TL_OPS_CUS, /* abort or switch to special code to interpret */
-};
-
-struct transfer_list_header {
-	uint32_t signature;
-	uint8_t checksum;
-	uint8_t version;
-	uint8_t hdr_size;
-	uint8_t alignment; /* max alignment of TE data */
-	uint32_t size; /* TL header + all TEs */
-	uint32_t max_size;
-	uint32_t flags;
-	uint32_t reserved; /* spare bytes */
-	/*
-	 * Commented out element used to visualize dynamic part of the
-	 * data structure.
-	 *
-	 * Note that struct transfer_list_entry also is dynamic in size
-	 * so the elements can't be indexed directly but instead must be
-	 * traversed in order
-	 *
-	 * struct transfer_list_entry entries[];
-	 */
-};
-
-struct __attribute__((packed)) transfer_list_entry {
-	uint32_t tag_id : 24;
-	uint8_t hdr_size;
-	uint32_t data_size;
-	/*
-	 * Commented out element used to visualize dynamic part of the
-	 * data structure.
-	 *
-	 * Note that padding is added at the end of @data to make to reach
-	 * a 8-byte boundary.
-	 *
-	 * uint8_t	data[ROUNDUP(data_size, 8)];
-	 */
-};
-
-CASSERT(sizeof(struct transfer_list_entry) == U(0x8), assert_transfer_list_entry_size);
-
-void transfer_entry_dump(struct transfer_list_entry *te);
-void transfer_list_dump(struct transfer_list_header *tl);
-struct transfer_list_header *transfer_list_ensure(void *addr, size_t size);
-entry_point_info_t *
-transfer_list_set_handoff_args(struct transfer_list_header *tl,
-			       entry_point_info_t *ep_info);
-struct transfer_list_header *transfer_list_init(void *addr, size_t max_size);
-
-struct transfer_list_header *
-transfer_list_relocate(struct transfer_list_header *tl, void *addr,
-		       size_t max_size);
-enum transfer_list_ops
-transfer_list_check_header(const struct transfer_list_header *tl);
-
-void transfer_list_update_checksum(struct transfer_list_header *tl);
-bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
-
-bool transfer_list_set_data_size(struct transfer_list_header *tl,
-				 struct transfer_list_entry *entry,
-				 uint32_t new_data_size);
-
-void *transfer_list_entry_data(struct transfer_list_entry *entry);
-bool transfer_list_rem(struct transfer_list_header *tl,
-		       struct transfer_list_entry *entry);
-
-struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
-					      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, uint32_t tag_id,
-			     uint32_t data_size, const void *data,
-			     uint8_t alignment);
-
-struct transfer_list_entry *
-transfer_list_next(struct transfer_list_header *tl,
-		   struct transfer_list_entry *last);
-
-struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
-					       uint32_t tag_id);
-
-#endif /*__ASSEMBLER__*/
-#endif /*__TRANSFER_LIST_H*/
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index aed85f5..4a9c2d8 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -17,9 +17,11 @@
 #include <lib/el3_runtime/cpu_data.h>
 #include <lib/gpt_rme/gpt_rme.h>
 #include <lib/spinlock.h>
-#include <lib/transfer_list.h>
 #include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
+#if TRANSFER_LIST
+#include <transfer_list.h>
+#endif
 
 /*******************************************************************************
  * Forward declarations
@@ -290,6 +292,7 @@
 void arm_bl31_plat_arch_setup(void);
 
 /* Firmware Handoff utility functions */
+#if TRANSFER_LIST
 void arm_transfer_list_dyn_cfg_init(struct transfer_list_header *secure_tl);
 void arm_transfer_list_populate_ep_info(bl_mem_params_node_t *next_param_node,
 					struct transfer_list_header *secure_tl);
@@ -298,6 +301,7 @@
 struct transfer_list_entry *
 arm_transfer_list_set_heap_info(struct transfer_list_header *tl);
 void arm_transfer_list_get_heap_info(void **heap_addr, size_t *heap_size);
+#endif
 
 /* TSP utility functions */
 void arm_tsp_early_platform_setup(u_register_t arg0, u_register_t arg1,
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
deleted file mode 100644
index 4d4a167..0000000
--- a/lib/transfer_list/transfer_list.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <assert.h>
-#include <inttypes.h>
-#include <string.h>
-
-#include <common/debug.h>
-#include <lib/transfer_list.h>
-#include <lib/utils_def.h>
-
-void transfer_list_dump(struct transfer_list_header *tl)
-{
-	struct transfer_list_entry *te = NULL;
-	int i = 0;
-
-	if (!tl) {
-		return;
-	}
-	INFO("Dump transfer list:\n");
-	INFO("signature  0x%x\n", tl->signature);
-	INFO("checksum   0x%x\n", tl->checksum);
-	INFO("version    0x%x\n", tl->version);
-	INFO("hdr_size   0x%x\n", tl->hdr_size);
-	INFO("alignment  0x%x\n", tl->alignment);
-	INFO("size       0x%x\n", tl->size);
-	INFO("max_size   0x%x\n", tl->max_size);
-	INFO("flags      0x%x\n", tl->flags);
-	while (true) {
-		te = transfer_list_next(tl, te);
-		if (!te) {
-			break;
-		}
-
-		INFO("Entry %d:\n", i++);
-		transfer_entry_dump(te);
-	}
-}
-
-void transfer_entry_dump(struct transfer_list_entry *te)
-{
-	if (te) {
-		INFO("tag_id     0x%x\n", te->tag_id);
-		INFO("hdr_size   0x%x\n", te->hdr_size);
-		INFO("data_size  0x%x\n", te->data_size);
-		INFO("data_addr  0x%lx\n",
-		     (unsigned long)transfer_list_entry_data(te));
-	}
-}
-
-/*******************************************************************************
- * Set the handoff arguments according to the transfer list payload
- * Return pointer to the entry point info if arguments are set properly
- * or NULL if not
- ******************************************************************************/
-entry_point_info_t *
-transfer_list_set_handoff_args(struct transfer_list_header *tl,
-			       entry_point_info_t *ep_info)
-{
-	struct transfer_list_entry *te = NULL;
-	void *dt = NULL;
-
-	if (!ep_info || !tl || transfer_list_check_header(tl) == TL_OPS_NON) {
-		return NULL;
-	}
-
-	te = transfer_list_find(tl, TL_TAG_FDT);
-	dt = transfer_list_entry_data(te);
-
-#ifdef __aarch64__
-	if (GET_RW(ep_info->spsr) == MODE_RW_64) {
-		ep_info->args.arg0 = (uintptr_t)dt;
-		ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
-		ep_info->args.arg2 = 0;
-	} else
-#endif
-	{
-		ep_info->args.arg0 = 0;
-		ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
-		ep_info->args.arg2 = (uintptr_t)dt;
-	}
-
-	ep_info->args.arg3 = (uintptr_t)tl;
-
-	return ep_info;
-}
-
-/*******************************************************************************
- * Creating a transfer list in a reserved memory region specified
- * Compliant to 2.4.5 of Firmware handoff specification (v0.9)
- * Return pointer to the created transfer list or NULL on error
- ******************************************************************************/
-struct transfer_list_header *transfer_list_init(void *addr, size_t max_size)
-{
-	struct transfer_list_header *tl = addr;
-
-	if (!addr || max_size == 0) {
-		return NULL;
-	}
-
-	if (!is_aligned((uintptr_t)addr, 1 << TRANSFER_LIST_INIT_MAX_ALIGN) ||
-	    !is_aligned(max_size, 1 << TRANSFER_LIST_INIT_MAX_ALIGN) ||
-	    max_size < sizeof(*tl)) {
-		return NULL;
-	}
-
-	memset(tl, 0, max_size);
-	tl->signature = TRANSFER_LIST_SIGNATURE;
-	tl->version = TRANSFER_LIST_VERSION;
-	tl->hdr_size = sizeof(*tl);
-	tl->alignment = TRANSFER_LIST_INIT_MAX_ALIGN; /* initial max align */
-	tl->size = sizeof(*tl); /* initial size is the size of header */
-	tl->max_size = max_size;
-	tl->flags = TL_FLAGS_HAS_CHECKSUM;
-
-	transfer_list_update_checksum(tl);
-
-	return tl;
-}
-
-/*******************************************************************************
- * Relocating a transfer list to a reserved memory region specified
- * Compliant to 2.4.6 of Firmware handoff specification (v0.9)
- * Return pointer to the relocated transfer list or NULL on error
- ******************************************************************************/
-struct transfer_list_header *
-transfer_list_relocate(struct transfer_list_header *tl, void *addr,
-		       size_t max_size)
-{
-	uintptr_t new_addr, align_mask, align_off;
-	struct transfer_list_header *new_tl;
-	uint32_t new_max_size;
-
-	if (!tl || !addr || max_size == 0) {
-		return NULL;
-	}
-
-	align_mask = (1 << tl->alignment) - 1;
-	align_off = (uintptr_t)tl & align_mask;
-	new_addr = ((uintptr_t)addr & ~align_mask) + align_off;
-
-	if (new_addr < (uintptr_t)addr) {
-		new_addr += (1 << tl->alignment);
-	}
-
-	new_max_size = max_size - (new_addr - (uintptr_t)addr);
-
-	/* the new space is not sufficient for the tl */
-	if (tl->size > new_max_size) {
-		return NULL;
-	}
-
-	new_tl = (struct transfer_list_header *)new_addr;
-	memmove(new_tl, tl, tl->size);
-	new_tl->max_size = new_max_size;
-
-	transfer_list_update_checksum(new_tl);
-
-	return new_tl;
-}
-
-/*******************************************************************************
- * Verifying the header of a transfer list
- * Compliant to 2.4.1 of Firmware handoff specification (v0.9)
- * Return transfer list operation status code
- ******************************************************************************/
-enum transfer_list_ops
-transfer_list_check_header(const struct transfer_list_header *tl)
-{
-	if (!tl) {
-		return TL_OPS_NON;
-	}
-
-	if (tl->signature != TRANSFER_LIST_SIGNATURE) {
-		VERBOSE("Bad transfer list signature 0x%x\n", tl->signature);
-		return TL_OPS_NON;
-	}
-
-	if (!tl->max_size) {
-		VERBOSE("Bad transfer list max size 0x%x\n", tl->max_size);
-		return TL_OPS_NON;
-	}
-
-	if (tl->size > tl->max_size) {
-		VERBOSE("Bad transfer list size 0x%x\n", tl->size);
-		return TL_OPS_NON;
-	}
-
-	if (tl->hdr_size != sizeof(struct transfer_list_header)) {
-		VERBOSE("Bad transfer list header size 0x%x\n", tl->hdr_size);
-		return TL_OPS_NON;
-	}
-
-	if (!transfer_list_verify_checksum(tl)) {
-		VERBOSE("Bad transfer list checksum 0x%x\n", tl->checksum);
-		return TL_OPS_NON;
-	}
-
-	if (tl->version == 0) {
-		VERBOSE("Transfer list version is invalid\n");
-		return TL_OPS_NON;
-	} else if (tl->version == TRANSFER_LIST_VERSION) {
-		INFO("Transfer list version is valid for all operations\n");
-		return TL_OPS_ALL;
-	} else if (tl->version > TRANSFER_LIST_VERSION) {
-		INFO("Transfer list version is valid for read-only\n");
-		return TL_OPS_RO;
-	}
-
-	INFO("Old transfer list version is detected\n");
-	return TL_OPS_CUS;
-}
-
-/*******************************************************************************
- * Enumerate the next transfer entry
- * Return pointer to the next transfer entry or NULL on error
- ******************************************************************************/
-struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl,
-					       struct transfer_list_entry *last)
-{
-	struct transfer_list_entry *te = NULL;
-	uintptr_t tl_ev = 0;
-	uintptr_t va = 0;
-	uintptr_t ev = 0;
-	size_t sz = 0;
-
-	if (!tl) {
-		return NULL;
-	}
-
-	tl_ev = (uintptr_t)tl + tl->size;
-
-	if (last) {
-		va = (uintptr_t)last;
-		/* check if the total size overflow */
-		if (add_overflow(last->hdr_size, last->data_size, &sz)) {
-			return NULL;
-		}
-		/* roundup to the next entry */
-		if (add_with_round_up_overflow(va, sz, TRANSFER_LIST_GRANULE,
-					       &va)) {
-			return NULL;
-		}
-	} else {
-		va = (uintptr_t)tl + tl->hdr_size;
-	}
-
-	te = (struct transfer_list_entry *)va;
-
-	if (va + sizeof(*te) > tl_ev || te->hdr_size < sizeof(*te) ||
-	    add_overflow(te->hdr_size, te->data_size, &sz) ||
-	    add_overflow(va, sz, &ev) || ev > tl_ev) {
-		return NULL;
-	}
-
-	return te;
-}
-
-/*******************************************************************************
- * Calculate the byte sum of a transfer list
- * Return byte sum of the transfer list
- ******************************************************************************/
-static uint8_t calc_byte_sum(const struct transfer_list_header *tl)
-{
-	uint8_t *b = (uint8_t *)tl;
-	uint8_t cs = 0;
-	size_t n = 0;
-
-	for (n = 0; n < tl->size; n++) {
-		cs += b[n];
-	}
-
-	return cs;
-}
-
-/*******************************************************************************
- * Update the checksum of a transfer list
- * Return updated checksum of the transfer list
- ******************************************************************************/
-void transfer_list_update_checksum(struct transfer_list_header *tl)
-{
-	uint8_t cs;
-
-	if (!tl || !(tl->flags & TL_FLAGS_HAS_CHECKSUM)) {
-		return;
-	}
-
-	cs = calc_byte_sum(tl);
-	cs -= tl->checksum;
-	cs = 256 - cs;
-	tl->checksum = cs;
-	assert(transfer_list_verify_checksum(tl));
-}
-
-/*******************************************************************************
- * Verify the checksum of a transfer list
- * Return true if verified or false if not
- ******************************************************************************/
-bool transfer_list_verify_checksum(const struct transfer_list_header *tl)
-{
-	if (!tl) {
-		return false;
-	}
-
-	if (!(tl->flags & TL_FLAGS_HAS_CHECKSUM)) {
-		return true;
-	}
-
-	return !calc_byte_sum(tl);
-}
-
-/*******************************************************************************
- * Update the data size of a transfer entry
- * Return true on success or false on error
- ******************************************************************************/
-bool transfer_list_set_data_size(struct transfer_list_header *tl,
-				 struct transfer_list_entry *te,
-				 uint32_t new_data_size)
-{
-	uintptr_t tl_old_ev, new_ev = 0, old_ev = 0, ru_new_ev;
-	struct transfer_list_entry *dummy_te = NULL;
-	size_t gap = 0;
-	size_t mov_dis = 0;
-	size_t sz = 0;
-
-	if (!tl || !te) {
-		return false;
-	}
-	tl_old_ev = (uintptr_t)tl + tl->size;
-
-	/*
-	 * calculate the old and new end of TE
-	 * both must be roundup to align with TRANSFER_LIST_GRANULE
-	 */
-	if (add_overflow(te->hdr_size, te->data_size, &sz) ||
-	    add_with_round_up_overflow((uintptr_t)te, sz, TRANSFER_LIST_GRANULE,
-				       &old_ev)) {
-		return false;
-	}
-	if (add_overflow(te->hdr_size, new_data_size, &sz) ||
-	    add_with_round_up_overflow((uintptr_t)te, sz, TRANSFER_LIST_GRANULE,
-				       &new_ev)) {
-		return false;
-	}
-
-	if (new_ev > old_ev) {
-		/*
-		 * move distance should be roundup
-		 * to meet the requirement of TE data max alignment
-		 * ensure that the increased size doesn't exceed
-		 * the max size of TL
-		 */
-		mov_dis = new_ev - old_ev;
-		if (round_up_overflow(mov_dis, 1 << tl->alignment, &mov_dis) ||
-		    tl->size + mov_dis > tl->max_size) {
-			return false;
-		}
-		ru_new_ev = old_ev + mov_dis;
-		memmove((void *)ru_new_ev, (void *)old_ev, tl_old_ev - old_ev);
-		tl->size += mov_dis;
-		gap = ru_new_ev - new_ev;
-	} else {
-		gap = old_ev - new_ev;
-	}
-
-	if (gap >= sizeof(*dummy_te)) {
-		/* 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->hdr_size = sizeof(*dummy_te);
-		dummy_te->data_size = gap - sizeof(*dummy_te);
-	}
-
-	te->data_size = new_data_size;
-
-	transfer_list_update_checksum(tl);
-	return true;
-}
-
-/*******************************************************************************
- * Remove a specified transfer entry from a transfer list
- * Return true on success or false on error
- ******************************************************************************/
-bool transfer_list_rem(struct transfer_list_header *tl,
-		       struct transfer_list_entry *te)
-{
-	if (!tl || !te || (uintptr_t)te > (uintptr_t)tl + tl->size) {
-		return false;
-	}
-	te->tag_id = TL_TAG_EMPTY;
-	transfer_list_update_checksum(tl);
-	return true;
-}
-
-/*******************************************************************************
- * Add a new transfer entry into a transfer list
- * Compliant to 2.4.3 of Firmware handoff specification (v0.9)
- * Return pointer to the added transfer entry or NULL on error
- ******************************************************************************/
-struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
-					      uint32_t tag_id,
-					      uint32_t data_size,
-					      const void *data)
-{
-	uintptr_t max_tl_ev, tl_ev, ev;
-	struct transfer_list_entry *te = NULL;
-	uint8_t *te_data = NULL;
-	size_t sz = 0;
-
-	if (!tl) {
-		return NULL;
-	}
-
-	max_tl_ev = (uintptr_t)tl + tl->max_size;
-	tl_ev = (uintptr_t)tl + tl->size;
-	ev = tl_ev;
-
-	/*
-	 * skip the step 1 (optional step)
-	 * new TE will be added into the tail
-	 */
-	if (add_overflow(sizeof(*te), data_size, &sz) ||
-	    add_with_round_up_overflow(ev, sz, TRANSFER_LIST_GRANULE, &ev) ||
-	    ev > max_tl_ev) {
-		return NULL;
-	}
-
-	te = (struct transfer_list_entry *)tl_ev;
-	te->tag_id = tag_id;
-	te->hdr_size = sizeof(*te);
-	te->data_size = data_size;
-	tl->size += ev - tl_ev;
-
-	if (data) {
-		/* get TE data pointer */
-		te_data = transfer_list_entry_data(te);
-		if (!te_data) {
-			return NULL;
-		}
-		memmove(te_data, data, data_size);
-	}
-
-	transfer_list_update_checksum(tl);
-
-	return te;
-}
-
-/*******************************************************************************
- * Add a new transfer entry into a transfer list with specified new data
- * alignment requirement
- * Compliant to 2.4.4 of Firmware handoff specification (v0.9)
- * 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, uint32_t tag_id,
-			     uint32_t data_size, const void *data,
-			     uint8_t alignment)
-{
-	struct transfer_list_entry *te = NULL;
-	uintptr_t tl_ev, ev, new_tl_ev;
-	size_t dummy_te_data_sz = 0;
-
-	if (!tl) {
-		return NULL;
-	}
-
-	tl_ev = (uintptr_t)tl + tl->size;
-	ev = tl_ev + sizeof(struct transfer_list_entry);
-
-	if (!is_aligned(ev, 1 << alignment)) {
-		/*
-		 * TE data address is not aligned to the new alignment
-		 * fill the gap with an empty TE as a placeholder before
-		 * adding the desire TE
-		 */
-		new_tl_ev = round_up(ev, 1 << alignment) -
-			    sizeof(struct transfer_list_entry);
-		dummy_te_data_sz =
-			new_tl_ev - tl_ev - sizeof(struct transfer_list_entry);
-		if (!transfer_list_add(tl, TL_TAG_EMPTY, dummy_te_data_sz,
-				       NULL)) {
-			return NULL;
-		}
-	}
-
-	te = transfer_list_add(tl, tag_id, data_size, data);
-
-	if (alignment > tl->alignment) {
-		tl->alignment = alignment;
-		transfer_list_update_checksum(tl);
-	}
-
-	return te;
-}
-
-/*******************************************************************************
- * Search for an existing transfer entry with the specified tag id from a
- * transfer list
- * Return pointer to the found transfer entry or NULL on error
- ******************************************************************************/
-struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
-					       uint32_t tag_id)
-{
-	struct transfer_list_entry *te = NULL;
-
-	do {
-		te = transfer_list_next(tl, te);
-	} while (te && (te->tag_id != tag_id));
-
-	return te;
-}
-
-/*******************************************************************************
- * Retrieve the data pointer of a specified transfer entry
- * Return pointer to the transfer entry data or NULL on error
- ******************************************************************************/
-void *transfer_list_entry_data(struct transfer_list_entry *entry)
-{
-	if (!entry) {
-		return NULL;
-	}
-	return (uint8_t *)entry + entry->hdr_size;
-}
-
-/*******************************************************************************
- * Verifies that the transfer list has not already been initialized, then
- * initializes it at the specified memory location.
- *
- * Return pointer to the transfer list or NULL on error
- * *****************************************************************************/
-struct transfer_list_header *transfer_list_ensure(void *addr, size_t size)
-{
-	struct transfer_list_header *tl = NULL;
-
-	if (transfer_list_check_header(addr) == TL_OPS_ALL) {
-		return (struct transfer_list_header *)addr;
-	}
-
-	tl = transfer_list_init((void *)addr, size);
-
-	return tl;
-}
diff --git a/lib/transfer_list/transfer_list.mk b/lib/transfer_list/transfer_list.mk
index 3ec4df2..91b6b57 100644
--- a/lib/transfer_list/transfer_list.mk
+++ b/lib/transfer_list/transfer_list.mk
@@ -1,21 +1,25 @@
 #
-# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 ifeq (${TRANSFER_LIST},1)
 
-ifeq (${ARCH},aarch32)
-$(eval $(call add_define,TRANSFER_LIST_AARCH32))
-endif
+# Default path if not set externally
+LIBTL_PATH	?=	contrib/libtl
 
-TRANSFER_LIST_SOURCES	+=	$(addprefix lib/transfer_list/,	\
-				transfer_list.c)
+# Common include paths (always needed)
+INCLUDES	+=	-I$(LIBTL_PATH)/include \
+			-I$(LIBTL_PATH)/include/arm
 
-BL31_SOURCES	+=	$(TRANSFER_LIST_SOURCES)
-BL2_SOURCES	+=	$(TRANSFER_LIST_SOURCES)
-BL1_SOURCES	+=	$(TRANSFER_LIST_SOURCES)
+LIBTL_SRC_PATH	:=	$(LIBTL_PATH)/src
 
-endif	# TRANSFER_LIST
+LIBTL_SRCS	:=	$(addprefix $(LIBTL_SRC_PATH)/, \
+				arm/ep_info.c \
+				generic/logging.c \
+				generic/transfer_list.c)
 
+$(eval $(call MAKE_LIB,tl))
+
+endif	# TRANSFER_LIST
diff --git a/plat/amd/common/include/plat_xfer_list.h b/plat/amd/common/include/plat_xfer_list.h
index 24a9c0c..1563200 100644
--- a/plat/amd/common/include/plat_xfer_list.h
+++ b/plat/amd/common/include/plat_xfer_list.h
@@ -7,7 +7,7 @@
 #ifndef PLAT_XFER_LIST_H
 #define PLAT_XFER_LIST_H
 
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 
 int32_t transfer_list_populate_ep_info(entry_point_info_t *bl32,
 				       entry_point_info_t *bl33);
diff --git a/plat/amd/common/plat_xfer_list.c b/plat/amd/common/plat_xfer_list.c
index 19c882b..d8dc09d 100644
--- a/plat/amd/common/plat_xfer_list.c
+++ b/plat/amd/common/plat_xfer_list.c
@@ -4,11 +4,12 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <stddef.h>
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <lib/transfer_list.h>
+
 #include <platform_def.h>
 
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <transfer_list.h>
 
 static struct transfer_list_header *tl_hdr;
 static int32_t tl_ops_holder;
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index 989f058..852a1e7 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -12,7 +12,9 @@
 #include <fvp_pas_def.h>
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
-#include <lib/transfer_list.h>
+#if TRANSFER_LIST
+#include <transfer_list.h>
+#endif
 
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 06a919c..adfc848 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -15,7 +15,7 @@
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 522017f..78ab862 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -20,7 +20,7 @@
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/gpt_rme/gpt_rme.h>
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #ifdef SPD_opteed
 #include <lib/optee_utils.h>
@@ -321,6 +321,7 @@
 {
 	entry_point_info_t *ep __unused;
 
+#if TRANSFER_LIST
 	/*
 	 * Information might have been added to the TL before this (i.e. event log)
 	 * make sure the checksum is up to date.
@@ -332,4 +333,5 @@
 	assert(ep != NULL);
 
 	arm_transfer_list_populate_ep_info(next_param_node, secure_tl);
+#endif
 }
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index f196269..ce6b21e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -18,7 +18,7 @@
 #include <lib/gpt_rme/gpt_rme.h>
 #include <lib/mmio.h>
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 53fe806..6c2b1ba 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -320,8 +320,11 @@
 endif
 
 ifeq (${TRANSFER_LIST}, 1)
-	include lib/transfer_list/transfer_list.mk
-	TRANSFER_LIST_SOURCES += plat/arm/common/arm_transfer_list.c
+include lib/transfer_list/transfer_list.mk
+
+BL1_SOURCES += plat/arm/common/arm_transfer_list.c
+BL2_SOURCES += plat/arm/common/arm_transfer_list.c
+BL31_SOURCES += plat/arm/common/arm_transfer_list.c
 endif
 
 ifneq ($(filter 1,${ENABLE_PMF} ${ETHOSN_NPU_DRIVER}),)
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index 4772bad..f10f2d7 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -9,7 +9,9 @@
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
-#include <lib/transfer_list.h>
+#if TRANSFER_LIST
+#include <transfer_list.h>
+#endif
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
 #include <services/arm_arch_svc.h>
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index 3452fde..209dcd7 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -20,7 +20,7 @@
 #include <common/fdt_wrappers.h>
 #include <lib/optee_utils.h>
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #include <lib/utils.h>
 #include <plat/common/platform.h>
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
index 51fee64..a350ce5 100644
--- a/plat/qemu/common/qemu_bl31_setup.c
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -10,7 +10,7 @@
 #include <drivers/arm/pl061_gpio.h>
 #include <lib/gpt_rme/gpt_rme.h>
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #include <plat/common/platform.h>
 #if ENABLE_RME
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index 5e232f9..adfb298 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -28,7 +28,7 @@
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/optee_utils.h>
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #if OPTEE_ALLOW_SMC_LOAD
diff --git a/services/std_svc/spm/spm_mm/spm_mm_setup.c b/services/std_svc/spm/spm_mm/spm_mm_setup.c
index 66ce84c..ebc5387 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_setup.c
@@ -20,7 +20,7 @@
 #include <lib/hob/mpinfo.h>
 #endif
 #if TRANSFER_LIST
-#include <lib/transfer_list.h>
+#include <transfer_list.h>
 #endif
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <platform_def.h>