ArmPkg/ArmTransferListLib: Add utility functions

Added functionality TransferList Library

TransferListVerifyChecksum - Verify TransferList CheckSum
TransferListCheckHeader - Check if TransferList header is valid,
 return suitable opcodes validating the header
TransferListFindEntry - Find a specific entry on the TransferList
 using the TagId
TransferListDump - Dump the contents of the TransferList header
 and the entry headers

Signed-off-by: Prachotan Reddy Bathi <Prachotan.Bathi@arm.com>
This commit is contained in:
Prachotan Reddy Bathi
2025-01-30 15:52:29 -06:00
committed by mergify[bot]
parent 5fc1ba3f25
commit e841099600
3 changed files with 222 additions and 4 deletions

View File

@@ -2,7 +2,7 @@
Header file defining a Transfer List and Transfer Entry as specified by the
A-profile Firmware Handoff Protocol specification.
Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
Copyright (c) 2025, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -73,6 +73,16 @@
*/
#define TRANSFER_LIST_FL_HAS_CHECKSUM BIT0
/*
* Operation codes indicating the validity of the Transfer List.
*/
typedef enum {
TRANSFER_LIST_OPS_INVALID, /* invalid for any operation */
TRANSFER_LIST_OPS_ALL, /* valid for all operations */
TRANSFER_LIST_OPS_RO, /* valid for read only */
TRANSFER_LIST_OPS_CUSTOM, /* abort or switch to special code to interpret */
} TRANSFER_LIST_OPS;
/*
* Transfer list starts with the following header.
* Transfer entries followed after the following header.

View File

@@ -2,7 +2,7 @@
Library that implements the helper functions to parse and pack a Transfer
List as specified by the A-profile Firmware Handoff Specification.
Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
Copyright (c) 2022 - 2025, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -21,7 +21,7 @@
/**
Return the first Transfer Entry Node in the Transfer List.
@param [in] TransferListHeader TransferListHeader
@param [in] TransferListHeader Pointer to the Transfer List Header.
@return Pointer to the Transfer Entry Node if successful otherwise NULL
@@ -103,4 +103,58 @@ TransferListGetEntryData (
IN TRANSFER_ENTRY_HEADER *TransferEntry
);
/**
Dump the transfer list to the debug output.
@param [in] TransferListHeader Pointer to the Transfer List Header
**/
VOID
EFIAPI
TransferListDump (
IN TRANSFER_LIST_HEADER *TransferListHeader
);
/**
Verify the checksum of the transfer list.
@param [in] TransferListHeader Pointer to the Transfer List Header
@retval FALSE Invalid Checksum
@retval TRUE Valid Checksum
**/
BOOLEAN
EFIAPI
TransferListVerifyChecksum (
IN TRANSFER_LIST_HEADER *TransferListHeader
);
/**
Check the header of the Transfer List.
@param [in] TransferListHeader Pointer to the Transfer List Header
@return TRANSFER_LIST_OPS code indicating the validity of the Transfer List
**/
TRANSFER_LIST_OPS
EFIAPI
TransferListCheckHeader (
IN TRANSFER_LIST_HEADER *TransferListHeader
);
/**
Find a Transfer Entry Node in the Transfer List matched with the given tag-id.
@param [in] TransferListHeader Pointer to the Transfer List Header
@param [in] TagId Tag id
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TransferListFindEntry (
IN TRANSFER_LIST_HEADER *TransferListHeader,
IN UINT16 TagId
);
#endif // ARM_TRANSFER_LIST_LIB_

View File

@@ -2,7 +2,7 @@
Library that implements the helper functions to parse and pack a Transfer
List as specified by the A-profile Firmware Handoff Specification.
Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
Copyright (c) 2022 - 2025, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -14,6 +14,90 @@
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
/**
This function verifies the checksum of the Transfer List.
@param [in] TransferListHeader Pointer to the Transfer List Header
@retval FALSE Invalid Checksum
@retval TRUE Valid Checksum
**/
BOOLEAN
EFIAPI
TransferListVerifyChecksum (
IN TRANSFER_LIST_HEADER *TransferListHeader
)
{
if (TransferListHeader == NULL) {
return FALSE;
}
if ((TransferListHeader->Flags & TRANSFER_LIST_FL_HAS_CHECKSUM) == 0) {
return TRUE;
}
return (CalculateSum8 ((UINT8 *)TransferListHeader, TransferListHeader->UsedSize) == 0);
}
/**
This function checks the header of the Transfer List.
@param [in] TransferListHeader Pointer to the Transfer List Header
@return TRANSFER_LIST_OPS code indicating the validity of the Transfer List
**/
TRANSFER_LIST_OPS
EFIAPI
TransferListCheckHeader (
IN TRANSFER_LIST_HEADER *TransferListHeader
)
{
if (TransferListHeader == NULL) {
return TRANSFER_LIST_OPS_INVALID;
}
if (TransferListHeader->Signature != TRANSFER_LIST_SIGNATURE_64) {
DEBUG ((DEBUG_ERROR, "Bad transfer list signature 0x%x\n", TransferListHeader->Signature));
return TRANSFER_LIST_OPS_INVALID;
}
if (TransferListHeader->TotalSize == 0) {
DEBUG ((DEBUG_ERROR, "Bad transfer list total size 0x%x\n", TransferListHeader->TotalSize));
return TRANSFER_LIST_OPS_INVALID;
}
if (TransferListHeader->UsedSize > TransferListHeader->TotalSize) {
DEBUG ((DEBUG_ERROR, "Bad transfer list used size 0x%x\n", TransferListHeader->UsedSize));
return TRANSFER_LIST_OPS_INVALID;
}
if (TransferListHeader->HeaderSize != sizeof (TRANSFER_LIST_HEADER)) {
DEBUG ((DEBUG_ERROR, "Bad transfer list header size 0x%x\n", TransferListHeader->HeaderSize));
return TRANSFER_LIST_OPS_INVALID;
}
if (TransferListVerifyChecksum (TransferListHeader) == FALSE) {
DEBUG ((DEBUG_ERROR, "Bad transfer list checksum 0x%x\n", TransferListHeader->Checksum));
return TRANSFER_LIST_OPS_INVALID;
}
if (TransferListHeader->Version == 0) {
DEBUG ((DEBUG_ERROR, "Transfer list version is invalid\n"));
return TRANSFER_LIST_OPS_INVALID;
} else if (TransferListHeader->Version == ARM_FW_HANDOFF_PROTOCOL_VERSION) {
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Transfer list version is valid for all operations\n"));
return TRANSFER_LIST_OPS_ALL;
} else if (TransferListHeader->Version > ARM_FW_HANDOFF_PROTOCOL_VERSION) {
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Transfer list version is valid for read-only\n"));
return TRANSFER_LIST_OPS_RO;
}
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Old or custom transfer list version is detected\n"));
return TRANSFER_LIST_OPS_CUSTOM;
}
/**
Return the first Transfer Entry Node in the Transfer List.
@@ -165,3 +249,73 @@ TransferListGetEntryData (
return (VOID *)((UINTN)TransferEntry + TransferEntry->HeaderSize);
}
/**
Find a Transfer Entry Node in the Transfer List matched with the given tag-id.
@param [in] TransferListHeader Pointer to the Transfer List Header
@param [in] TagId Tag id
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TransferListFindEntry (
IN TRANSFER_LIST_HEADER *TransferListHeader,
IN UINT16 TagId
)
{
TRANSFER_ENTRY_HEADER *Entry = NULL;
do {
Entry = TransferListGetNextEntry (TransferListHeader, Entry);
} while ((Entry != NULL) && (Entry->TagId != TagId));
return Entry;
}
/**
Dump the transfer list to the debug output.
@param [in] TransferListHeader Pointer to the Transfer List Header
**/
VOID
EFIAPI
TransferListDump (
IN TRANSFER_LIST_HEADER *TransferListHeader
)
{
TRANSFER_ENTRY_HEADER *Entry;
UINTN Idx;
Entry = NULL;
Idx = 0;
if (TransferListHeader == NULL) {
return;
}
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Dump transfer list:\n"));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "signature 0x%x\n", TransferListHeader->Signature));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "checksum 0x%x\n", TransferListHeader->Checksum));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "version 0x%x\n", TransferListHeader->Version));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "hdr_size 0x%x\n", TransferListHeader->HeaderSize));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "alignment 0x%x\n", TransferListHeader->Alignment));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "used_size 0x%x\n", TransferListHeader->UsedSize));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "total_size 0x%x\n", TransferListHeader->TotalSize));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "flags 0x%x\n", TransferListHeader->Flags));
while (TRUE) {
Entry = TransferListGetNextEntry (TransferListHeader, Entry);
if (Entry == NULL) {
break;
}
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Entry %d:\n", Idx++));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "tag_id 0x%x\n", Entry->TagId));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "hdr_size 0x%x\n", Entry->HeaderSize));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "data_size 0x%x\n", Entry->DataSize));
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "data_addr 0x%lx\n", (UINTN)TransferListGetEntryData (Entry)));
}
}