ArmPkg/Library: Introduce ArmTransferListLib

ArmTransferList is used to pass boot information according to
firmware handoff protocol specification [0].

When initializing StandaloneMm, it gets boot information from
the PHIT HOB in the TransferList.

[0] https://github.com/FirmwareHandoff/firmware_handoff

Signed-off-by: Levi Yun <yeoreum.yun@arm.com>
This commit is contained in:
levi.yun 2024-02-21 16:09:38 +00:00 committed by mergify[bot]
parent 6087382c62
commit fbeab84945
6 changed files with 443 additions and 0 deletions

View File

@ -93,6 +93,11 @@
#
StandaloneMmMmuLib|Include/Library/StandaloneMmMmuLib.h
## @libraryclass Provides an interface for a Arm Transfer List.
#
ArmTransferListLib|Include/Library/ArmTransferListLib.h
[Guids.common]
gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } }

View File

@ -86,6 +86,7 @@
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
ArmTransferListLib|ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
@ -129,6 +130,7 @@
ArmPkg/Library/ArmSmcLibNull/ArmSmcLibNull.inf
ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
ArmPkg/Library/OpteeLib/OpteeLib.inf
ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf

View File

@ -0,0 +1,130 @@
/** @file
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>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- https://github.com/FirmwareHandoff/firmware_handoff
@par Glossary:
- TL - Transfer list
- TE - Transfer entry
- HOB - Hand off block.
**/
#ifndef ARM_TRANSFER_LIST_
#define ARM_TRANSFER_LIST_
#include <Base.h>
#include <Uefi.h>
#define ARM_FW_HANDOFF_PROTOCOL_VERSION 1
#define TRANSFER_LIST_ALIGNMENT 8 // 8 byte alignment
#define TRANSFER_LIST_SIGNATURE_64 (0x4a0fb10b)
#define TRANSFER_LIST_SIGNATURE_32 (0xfb10b)
/*
* For register convention, please see below:
* https://github.com/FirmwareHandoff/firmware_handoff/blob/main/source/register_conventions.rst
*/
#define REGISTER_CONVENTION_VERSION_SHIFT_64 (32)
#define TRANSFER_LIST_SIGNATURE_MASK_64 \
((1ULL << REGISTER_CONVENTION_VERSION_SHIFT_64) - 1)
#define REGISTER_CONVENTION_VERSION_SHIFT_32 (24)
#define TRANSFER_LIST_SIGNATURE_MASK_32 \
((1UL << REGISTER_CONVENTION_VERSION_SHIFT_32) - 1)
#define REGISTER_CONVENTION_VERSION_MASK (0xff)
#define REGISTER_CONVENTION_VERSION (1)
#define CREATE_TRANSFER_LIST_HANDOFF_X1_VALUE(version) \
((TRANSFER_LIST_SIGNATURE & \
(REGISTER_CONVENTION_VERSION_SHIFT_64 - 1)) | \
((version) << REGISTER_CONVENTION_VERSION_SHIFT_64))
#define CREATE_TRANSFER_LIST_HANDOFF_R1_VALUE(version) \
((TRANSFER_LIST_SIGNATURE & \
(REGISTER_CONVENTION_VERSION_SHIFT_32 - 1)) | \
((version) << REGISTER_CONVENTION_VERSION_SHIFT_32))
/*
* tag id identifies contents of transfer entry.
* below is the standard tag id used in transfer entry.
* please see:
* https://github.com/FirmwareHandoff/firmware_handoff/blob/main/source/transfer_list.rst
* "Standard transfer entries" Section.
*/
#define TRANSFER_ENTRY_TAG_ID_EMPTY 0
#define TRANSFER_ENTRY_TAG_ID_FDT 1
#define TRANSFER_ENTRY_TAG_ID_HOB 2
#define TRANSFER_ENTRY_TAG_ID_HOB_LIST 3
#define TRANSFER_ENTRY_TAG_ID_ACPI_TABLE_AGGREGATE 4
#define TRANSFER_ENTRY_TAG_ID_TPM_EVENT_LOG 5
#define TRANSFER_ENTRY_TAG_ID_TPM_CRB_BASE 6
/*
* Flag value in TransferListHeader->Flags.
* please see:
* https://github.com/FirmwareHandoff/firmware_handoff/blob/main/source/transfer_list.rst
*/
#define TRANSFER_LIST_FL_HAS_CHECKSUM BIT0
/*
* Transfer list starts with the following header.
* Transfer entries followed after the following header.
*/
typedef struct TransferListHeader {
/// Signature, must be TRANSFER_LIST_SIGNATURE
UINT32 Signature;
/// Checksum
UINT8 Checksum;
/// Version of the TL Header.
UINT8 Version;
/// The size of this TL header in bytes.
UINT8 HeaderSize;
/// The maximum alignment required by any transfer entry in the transfer list,
/// specified as a power of two.
UINT8 Alignment;
/// The number of bytes occupied by the TL. This field
/// accounts for the size of the TL header plus the size
/// of all the entries contained in the TL.
UINT32 UsedSize;
/// The number of bytes occupied by the entire TL,
/// including any spare space at the end after UsedSize.
UINT32 TotalSize;
/// Flags word.
UINT32 Flags;
/// Reserved.
UINT32 Reserved;
} TRANSFER_LIST_HEADER;
/*
* Transfer entry in transfer list starts with the following header.
*/
typedef struct TransferEntryHeader {
/// The entry type identifier.
UINT16 TagId;
/// Reserved.
UINT8 Reserved0;
/// The size of this entry header in bytes.
UINT8 HeaderSize;
/// The size of the data content in bytes.
UINT32 DataSize;
} TRANSFER_ENTRY_HEADER;
#endif // ARM_TRANSFER_LIST_

View File

@ -0,0 +1,109 @@
/** @file
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>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- https://github.com/FirmwareHandoff/firmware_handoff
@par Glossary:
- TL - Transfer list
- TE - Transfer entry
- HOB - Hand off block.
**/
#ifndef ARM_TRANSFER_LIST_LIB_
#define ARM_TRANSFER_LIST_LIB_
#include <Base.h>
#include <Uefi.h>
#include <IndustryStandard/ArmTransferList.h>
#include <Pi/PiBootMode.h>
#include <Pi/PiHob.h>
/**
Return the first Transfer Entry Node in the Transfer List.
@param [in] Tlh TransferListHeader
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlGetFirstEntry (
IN TRANSFER_LIST_HEADER *Tlh
);
/**
Return the next Transfer Entry Node in the Transfer List from
last Transfer Entry Node.
@param [in] Tlh TransferListHeader
@param [in] CurrentTe Pointer to the Current Transfer Entry.
If this is NULL, the first Transfer Entry is returned.
@return Pointer to the next Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlGetNextEntry (
IN TRANSFER_LIST_HEADER *Tlh,
IN TRANSFER_ENTRY_HEADER *CurrentTe
);
/**
Return the first Transfer Entry Node in the Transfer List
matched with given tag-id.
@param [in] Tlh TransferListHeader
@param [in] TagId Tag id
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlFindFirstEntry (
IN TRANSFER_LIST_HEADER *Tlh,
IN UINT16 TagId
);
/**
Return the Next Transfer Entry Node in the Transfer List
matched with given tag-id from last Transfer Entry Node.
@param [in] Tlh TransferListHeader
@param [in] CurrentTe Pointer to the Current Transfer Entry.
If this is NULL, the first Transfer Entry is returned.
@param [in] TagId Tag id
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlFindNextEntry (
IN TRANSFER_LIST_HEADER *Tlh,
IN TRANSFER_ENTRY_HEADER *CurrentTe,
IN UINT16 TagId
);
/**
Return the data in Transfer Entry.
@param [in] Te TransferEntryHeader
@return Pointer to the Data of Transfer Entry Node if successful otherwise NULL
**/
VOID *
EFIAPI
TlGetEntryData (
IN TRANSFER_ENTRY_HEADER *Te
);
#endif // ARM_TRANSFER_LIST_LIB_

View File

@ -0,0 +1,170 @@
/** @file
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>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- https://github.com/FirmwareHandoff/firmware_handoff
@par Glossary:
- TL - Transfer list
- TE - Transfer entry
- Tlh - Transfer list header
**/
#include <Base.h>
#include <Library/ArmTransferListLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
/**
Return the first Transfer Entry Node in the Transfer List.
@param [in] Tlh TransferListHeader
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlGetFirstEntry (
IN TRANSFER_LIST_HEADER *Tlh
)
{
return TlGetNextEntry (Tlh, NULL);
}
/**
Return the next Transfer Entry Node in the Transfer List from
last Transfer Entry Node.
@param [in] Tlh TransferListHeader
@param [in] CurrentTe Pointer to the Current Transfer Entry.
If this is NULL, the first Transfer Entry is returned.
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlGetNextEntry (
IN TRANSFER_LIST_HEADER *Tlh,
IN TRANSFER_ENTRY_HEADER *CurrentTe
)
{
TRANSFER_ENTRY_HEADER *Te;
UINTN CurrentAddr;
UINTN EndAddr;
if (Tlh == NULL) {
return NULL;
}
EndAddr = (UINTN)Tlh + Tlh->UsedSize;
if (CurrentTe != NULL) {
CurrentAddr = (UINTN)CurrentTe + CurrentTe->HeaderSize + CurrentTe->DataSize;
} else {
CurrentAddr = (UINTN)Tlh + Tlh->HeaderSize;
}
CurrentAddr = ALIGN_VALUE (CurrentAddr, (1 << Tlh->Alignment));
Te = (TRANSFER_ENTRY_HEADER *)CurrentAddr;
if (((CurrentAddr + sizeof (TRANSFER_LIST_HEADER)) < CurrentAddr) ||
((CurrentAddr + sizeof (TRANSFER_ENTRY_HEADER)) > EndAddr) ||
((CurrentAddr + Te->HeaderSize + Te->DataSize) < CurrentAddr) ||
((CurrentAddr + Te->HeaderSize + Te->DataSize) > EndAddr))
{
return NULL;
}
return Te;
}
/**
Return the first Transfer Entry Node in the Transfer List
matched with given tag-id.
@param [in] Tlh TransferListHeader
@param [in] TagId Tag id
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlFindFirstEntry (
IN TRANSFER_LIST_HEADER *Tlh,
IN UINT16 TagId
)
{
TRANSFER_ENTRY_HEADER *Te;
Te = TlGetFirstEntry (Tlh);
while ((Te != NULL) && ((Te->TagId != TagId) || Te->Reserved0 != 0)) {
Te = TlGetNextEntry (Tlh, Te);
}
return Te;
}
/**
Return the Next Transfer Entry Node in the Transfer List
matched with given tag-id from last Transfer Entry Node.
@param [in] Tlh TransferListHeader
@param [in] CurrentTe Pointer to the Current Transfer Entry.
If this is NULL, the first Transfer Entry is returned.
@param [in] TagId Tag id
@return Pointer to the Transfer Entry Node if successful otherwise NULL
**/
TRANSFER_ENTRY_HEADER *
EFIAPI
TlFindNextEntry (
IN TRANSFER_LIST_HEADER *Tlh,
IN TRANSFER_ENTRY_HEADER *CurrentTe,
IN UINT16 TagId
)
{
TRANSFER_ENTRY_HEADER *Te;
if (CurrentTe == NULL) {
return TlFindFirstEntry (Tlh, TagId);
} else {
Te = TlGetNextEntry (Tlh, CurrentTe);
}
while ((Te != NULL) && ((Te->TagId != TagId) || Te->Reserved0 != 0)) {
Te = TlGetNextEntry (Tlh, Te);
}
return Te;
}
/**
Return the data in Transfer Entry.
@param [in] Te TransferEntryHeader
@return Pointer to the Data of Transfer Entry Node if successful otherwise NULL
**/
VOID *
EFIAPI
TlGetEntryData (
IN TRANSFER_ENTRY_HEADER *Te
)
{
if ((Te == NULL) || (Te->DataSize == 0)) {
return NULL;
}
return (VOID *)((UINTN)Te + Te->HeaderSize);
}

View File

@ -0,0 +1,27 @@
## @file
# Library that implements the helper functions to parse and pack a
# Transfer List according to the A-profile Firmware Handoff Specification.
#
# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x0001001C
BASE_NAME = ArmTransferListLib
FILE_GUID = 3BD1750F-FB52-4AA8-B91E-D00EFA5D7D29
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = ArmTransferListLib
[Sources]
ArmTransferListLib.c
[Packages]
ArmPkg/ArmPkg.dec
MdePkg/MdePkg.dec
[LibraryClasses]
BaseLib