summaryrefslogtreecommitdiffstats
path: root/SecurityPkg/Library
diff options
context:
space:
mode:
authorEric Dong <eric.dong@intel.com>2016-03-29 14:41:20 +0800
committerFeng Tian <feng.tian@intel.com>2016-03-29 15:37:29 +0800
commit085dcf01f7f4ed84a0ecc58e46ad5122b26539f9 (patch)
tree4019fadf6877719c5db0d220ee6f5ebb856b918f /SecurityPkg/Library
parent79af8319e0d05a44defbc5c0d4d4fa211bd57888 (diff)
downloadedk2-085dcf01f7f4ed84a0ecc58e46ad5122b26539f9.tar.gz
edk2-085dcf01f7f4ed84a0ecc58e46ad5122b26539f9.tar.bz2
edk2-085dcf01f7f4ed84a0ecc58e46ad5122b26539f9.zip
SecurityPkg: TcgStorageCoreLib: Add TCG storage core library.
APIs used to create commands defined by TCG storage core spec. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com>
Diffstat (limited to 'SecurityPkg/Library')
-rw-r--r--SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c1650
-rw-r--r--SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf38
-rw-r--r--SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c907
3 files changed, 2595 insertions, 0 deletions
diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c
new file mode 100644
index 0000000000..e333b55352
--- /dev/null
+++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCore.c
@@ -0,0 +1,1650 @@
+/** @file
+ Provide functions to provide tcg storage core spec related functions.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/TcgStorageCoreLib.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+//#include <Library/PrintLib.h>
+
+/**
+ Required to be called before calling any other Tcg functions with the TCG_CREATE_STRUCT.
+ Initializes the packet variables to NULL. Additionally, the buffer will be memset.
+
+ @param [in/out] CreateStruct Structure to initialize
+ @param [in] Buffer Buffer allocated by client of library. It will contain the Tcg encoded packet. This cannot be null.
+ @param [in] BufferSize Size of buffer provided. It cannot be 0.
+
+ @retval Return the action result.
+**/
+TCG_RESULT
+EFIAPI
+TcgInitTcgCreateStruct(
+ TCG_CREATE_STRUCT *CreateStruct,
+ VOID *Buffer,
+ UINT32 BufferSize
+ )
+{
+ NULL_CHECK(CreateStruct);
+ NULL_CHECK(Buffer);
+
+ if (BufferSize == 0) {
+ DEBUG ((DEBUG_INFO, "BufferSize=0\n"));
+ return (TcgResultFailureZeroSize);
+ }
+
+ ZeroMem(Buffer, BufferSize);
+ CreateStruct->BufferSize = BufferSize;
+ CreateStruct->Buffer = Buffer;
+ CreateStruct->ComPacket = NULL;
+ CreateStruct->CurPacket = NULL;
+ CreateStruct->CurSubPacket = NULL;
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Encodes the ComPacket header to the data structure.
+
+ @param[in/out] CreateStruct Structure to initialize
+ @param[in] ComId ComID of the Tcg ComPacket.
+ @param[in] ComIdExtension ComID Extension of the Tcg ComPacket.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgStartComPacket(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT16 ComId,
+ UINT16 ComIdExtension
+ )
+{
+ NULL_CHECK(CreateStruct);
+
+ if (CreateStruct->ComPacket != NULL ||
+ CreateStruct->CurPacket != NULL ||
+ CreateStruct->CurSubPacket != NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket,
+ CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ if (sizeof(TCG_COM_PACKET) > CreateStruct->BufferSize) {
+ DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ CreateStruct->ComPacket = (TCG_COM_PACKET*)CreateStruct->Buffer;
+ CreateStruct->ComPacket->ComIDBE = SwapBytes16(ComId);
+ CreateStruct->ComPacket->ComIDExtensionBE = SwapBytes16(ComIdExtension);
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Starts a new ComPacket in the Data structure.
+
+ @param [in/out] CreateStruct Structure used to add Tcg Packet
+ @param[in] Tsn Packet Tper session number
+ @param[in] Hsn Packet Host session number
+ @param[in] SeqNumber Packet Sequence Number
+ @param[in] AckType Packet Acknowledge Type
+ @param[in] Ack Packet Acknowledge
+
+**/
+TCG_RESULT
+EFIAPI
+TcgStartPacket(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 Tsn,
+ UINT32 Hsn,
+ UINT32 SeqNumber,
+ UINT16 AckType,
+ UINT32 Ack
+ )
+{
+ UINT32 AddedSize;
+ NULL_CHECK(CreateStruct);
+
+ AddedSize = 0;
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket != NULL ||
+ CreateStruct->CurSubPacket != NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ // update TCG_COM_PACKET and packet lengths
+ AddedSize = sizeof(TCG_PACKET);
+
+ if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) {
+ DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ CreateStruct->CurPacket = (TCG_PACKET*)(CreateStruct->ComPacket->Payload + SwapBytes32(CreateStruct->ComPacket->LengthBE));
+
+ CreateStruct->CurPacket->TperSessionNumberBE = SwapBytes32( Tsn );
+ CreateStruct->CurPacket->HostSessionNumberBE = SwapBytes32( Hsn );
+ CreateStruct->CurPacket->SequenceNumberBE = SwapBytes32( SeqNumber );
+ CreateStruct->CurPacket->AckTypeBE = SwapBytes16( AckType );
+ CreateStruct->CurPacket->AcknowledgementBE = SwapBytes32( Ack );
+
+ CreateStruct->CurPacket->LengthBE = 0;
+
+ // update TCG_COM_PACKET Length for next pointer
+ CreateStruct->ComPacket->LengthBE = SwapBytes32( SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize );
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Starts a new SubPacket in the Data structure.
+
+ @param[in/out] CreateStruct Structure used to start Tcg SubPacket
+ @param[in] Kind SubPacket kind
+
+**/
+TCG_RESULT
+EFIAPI
+TcgStartSubPacket(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT16 Kind
+ )
+{
+ UINT32 AddedSize;
+
+ NULL_CHECK(CreateStruct);
+
+ AddedSize = 0;
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket != NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ AddedSize = sizeof(TCG_SUB_PACKET);
+
+ if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) {
+ DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ CreateStruct->CurSubPacket = (TCG_SUB_PACKET*)(CreateStruct->CurPacket->Payload + SwapBytes32(CreateStruct->CurPacket->LengthBE));
+ CreateStruct->CurSubPacket->KindBE = SwapBytes16(Kind);
+
+ // update lengths
+ CreateStruct->CurSubPacket->LengthBE = 0;
+
+ // update TCG_COM_PACKET and packet lengths
+ CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize);
+ CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + AddedSize);
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Ends the current SubPacket in the Data structure. This function will also perform the 4-byte padding
+ required for Subpackets.
+
+ @param[in/out] CreateStruct Structure used to end the current Tcg SubPacket
+
+**/
+TCG_RESULT
+EFIAPI
+TcgEndSubPacket(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ UINT32 PadSize;
+
+ NULL_CHECK(CreateStruct);
+
+ PadSize = 0;
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ // align to 4-byte boundaries, so shift padding
+ // pad Size does not apply to subpacket Length
+ PadSize = TCG_SUBPACKET_ALIGNMENT - (SwapBytes32(CreateStruct->CurSubPacket->LengthBE) & (TCG_SUBPACKET_ALIGNMENT - 1));
+
+ if (PadSize == TCG_SUBPACKET_ALIGNMENT) {
+ PadSize = 0;
+ }
+
+ if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + PadSize) > CreateStruct->BufferSize) {
+ DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + PadSize);
+ CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + PadSize);
+
+ CreateStruct->CurSubPacket = NULL;
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Ends the current Packet in the Data structure.
+
+ @param[in/out] CreateStruct Structure used to end the current Tcg Packet
+
+**/
+TCG_RESULT
+EFIAPI
+TcgEndPacket(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ NULL_CHECK(CreateStruct);
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket != NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ CreateStruct->CurPacket = NULL;
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Ends the ComPacket in the Data structure and ret
+
+ @param [in/out] CreateStruct Structure used to end the Tcg ComPacket
+ @param [in/out] Size Describes the Size of the entire ComPacket (Header and payload). Filled out by function.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgEndComPacket(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 *Size
+ )
+{
+ NULL_CHECK(CreateStruct);
+ NULL_CHECK(Size);
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket != NULL ||
+ CreateStruct->CurSubPacket != NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ *Size = SwapBytes32(CreateStruct->ComPacket->LengthBE) + sizeof(*CreateStruct->ComPacket);
+ CreateStruct->ComPacket = NULL;
+
+ return (TcgResultSuccess);
+}
+
+/**
+ Adds raw Data with optional Header
+
+ @param CreateStruct The create structure.
+ @param Header The header structure.
+ @param HeaderSize The header size.
+ @param Data The data need to add.
+ @param DataSize The data size.
+ @param ByteSwapData Whether byte or swap data.
+
+**/
+TCG_RESULT
+TcgAddRawTokenData(
+ TCG_CREATE_STRUCT *CreateStruct,
+ const VOID *Header,
+ UINT8 HeaderSize,
+ const VOID *Data,
+ UINT32 DataSize,
+ BOOLEAN ByteSwapData
+ )
+{
+ UINT32 AddedSize;
+ UINT8* Dest;
+ const UINT8* DataBytes;
+ UINT32 Index;
+
+ AddedSize = 0;
+ Index = 0;
+ Dest = NULL;
+
+ NULL_CHECK(CreateStruct);
+
+ if ((HeaderSize != 0 && Header == NULL) ||
+ (DataSize != 0 && Data == NULL)
+ ) {
+ DEBUG ((DEBUG_INFO, "HeaderSize=0x%X Header=%p DataSize=0x%X Data=%p\n", HeaderSize, Header, DataSize, Data));
+ return (TcgResultFailureNullPointer);
+ }
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ // verify there is enough Buffer Size
+ AddedSize = HeaderSize + DataSize;
+ if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) {
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ // Get a pointer to where the new bytes should go
+ Dest = CreateStruct->ComPacket->Payload + SwapBytes32(CreateStruct->ComPacket->LengthBE);
+
+ switch (HeaderSize) {
+ case sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM):
+ case sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM):
+ case sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM):
+ CopyMem(Dest, Header, HeaderSize);
+ Dest += HeaderSize;
+ case 0: // no Header is valid
+ break;
+ // invalid Header Size
+ default:
+ DEBUG ((DEBUG_INFO, "unsupported HeaderSize=%u\n", HeaderSize));
+ return TcgResultFailure;
+ }
+
+ // copy the Data bytes
+ if (ByteSwapData) {
+ DataBytes = (const UINT8*)Data;
+ for (Index = 0; Index < DataSize; Index++) {
+ Dest[Index] = DataBytes[DataSize - 1 - Index];
+ }
+ } else {
+ CopyMem(Dest, Data, DataSize);
+ }
+
+ // Update all the packet sizes
+ CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize);
+ CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + AddedSize);
+ CreateStruct->CurSubPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurSubPacket->LengthBE) + AddedSize);
+
+ return (TcgResultSuccess);
+}
+
+/**
+
+ Adds a single raw token byte to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the byte
+ @param[in] Byte Byte to add
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddRawByte(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT8 Byte
+ )
+{
+ return TcgAddRawTokenData(CreateStruct, NULL, 0, &Byte, 1, FALSE);
+}
+
+
+/**
+ simple tokens - atoms: tiny, short, medium, long and empty atoms.
+ tiny atom can be a signed or unsigned integer.
+ short, medium, long can be a signed or unsigned integer OR a complete or non-final byte sequence.
+
+ @param CreateStruct The create structure.
+ @param Data The data need to add.
+ @param DataSize The data size.
+ @param ByteOrInt, Data format is byte or int.
+ @param SignOrCont sign or cont.
+
+
+**/
+TCG_RESULT
+TcgAddAtom(
+ TCG_CREATE_STRUCT *CreateStruct,
+ const VOID *Data,
+ UINT32 DataSize,
+ UINT8 ByteOrInt,
+ UINT8 SignOrCont
+ )
+{
+ const UINT8* DataBytes;
+ TCG_SIMPLE_TOKEN_TINY_ATOM TinyAtom;
+ TCG_SIMPLE_TOKEN_SHORT_ATOM ShortAtom;
+ TCG_SIMPLE_TOKEN_MEDIUM_ATOM MediumAtom;
+ TCG_SIMPLE_TOKEN_LONG_ATOM LongAtom;
+
+ NULL_CHECK(CreateStruct);
+
+ if (DataSize == 0) {
+ if (ByteOrInt == TCG_ATOM_TYPE_INTEGER) {
+ DEBUG ((DEBUG_INFO, "0-Size integer not allowed\n"));
+ return TcgResultFailure;
+ }
+ } else {
+ // if DataSize != 0, Data must be valid
+ NULL_CHECK(Data);
+ }
+
+ // encode Data using the shortest possible atom
+ DataBytes = (const UINT8*)Data;
+ if ((DataSize == 1) &&
+ (ByteOrInt == TCG_ATOM_TYPE_INTEGER) &&
+ ((SignOrCont != 0 && ((TCG_TOKEN_TINYATOM_SIGNED_MIN_VALUE <= *(INT8*)Data) && (*(INT8*)Data <= TCG_TOKEN_TINYATOM_SIGNED_MAX_VALUE))) ||
+ (SignOrCont == 0 && ((*DataBytes <= TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE))))
+ ) {
+ TinyAtom.TinyAtomBits.IsZero = 0;
+ TinyAtom.TinyAtomBits.Sign = SignOrCont;
+ TinyAtom.TinyAtomBits.Data = *DataBytes & TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE;
+ return TcgAddRawTokenData(CreateStruct, NULL, 0, (UINT8*)&TinyAtom, sizeof(TCG_SIMPLE_TOKEN_TINY_ATOM), FALSE);
+ }
+
+ if (DataSize <= TCG_TOKEN_SHORTATOM_MAX_BYTE_SIZE) {
+ ShortAtom.ShortAtomBits.IsOne = 1;
+ ShortAtom.ShortAtomBits.IsZero = 0;
+ ShortAtom.ShortAtomBits.ByteOrInt = ByteOrInt;
+ ShortAtom.ShortAtomBits.SignOrCont = SignOrCont;
+ ShortAtom.ShortAtomBits.Length = DataSize & 0x0F;
+ return TcgAddRawTokenData(CreateStruct, &ShortAtom, sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER);
+ }
+
+ if (DataSize <= TCG_TOKEN_MEDIUMATOM_MAX_BYTE_SIZE) {
+ MediumAtom.MediumAtomBits.IsOne1 = 1;
+ MediumAtom.MediumAtomBits.IsOne2 = 1;
+ MediumAtom.MediumAtomBits.IsZero = 0;
+ MediumAtom.MediumAtomBits.ByteOrInt = ByteOrInt;
+ MediumAtom.MediumAtomBits.SignOrCont = SignOrCont;
+ MediumAtom.MediumAtomBits.LengthLow = DataSize & 0xFF;
+ MediumAtom.MediumAtomBits.LengthHigh = (DataSize >> TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) & TCG_MEDIUM_ATOM_LENGTH_HIGH_MASK;
+ return TcgAddRawTokenData(CreateStruct, &MediumAtom, sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER);
+ }
+
+ LongAtom.LongAtomBits.IsOne1 = 1;
+ LongAtom.LongAtomBits.IsOne2 = 1;
+ LongAtom.LongAtomBits.IsOne3 = 1;
+ LongAtom.LongAtomBits.IsZero = 0;
+ LongAtom.LongAtomBits.ByteOrInt = ByteOrInt;
+ LongAtom.LongAtomBits.SignOrCont = SignOrCont;
+ LongAtom.LongAtomBits.LengthLow = DataSize & 0xFF;
+ LongAtom.LongAtomBits.LengthMid = (DataSize >> TCG_LONG_ATOM_LENGTH_MID_SHIFT) & 0xFF;
+ LongAtom.LongAtomBits.LengthHigh = (DataSize >> TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) & 0xFF;
+ return TcgAddRawTokenData(CreateStruct, &LongAtom, sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER);
+}
+
+/**
+
+ Adds the Data parameter as a byte sequence to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the byte sequence
+ @param[in] Data Byte sequence that will be encoded and copied into Data structure
+ @param[in] DataSize Length of Data provided
+ @param[in] Continued TRUE if byte sequence is continued or
+ FALSE if the Data contains the entire byte sequence to be encoded
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddByteSequence(
+ TCG_CREATE_STRUCT *CreateStruct,
+ const VOID *Data,
+ UINT32 DataSize,
+ BOOLEAN Continued
+ )
+{
+ return TcgAddAtom(CreateStruct, Data, DataSize, TCG_ATOM_TYPE_BYTE, Continued ? 1 : 0);
+}
+
+/**
+
+ Adds an arbitrary-Length integer to the Data structure.
+ The integer will be encoded using the shortest possible atom.
+
+ @param[in/out] CreateStruct Structure used to add the integer
+ @param[in] Data Integer in host byte order that will be encoded and copied into Data structure
+ @param[in] DataSize Length in bytes of the Data provided
+ @param[in] SignedInteger TRUE if the integer is signed or FALSE if the integer is unsigned
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddInteger(
+ TCG_CREATE_STRUCT *CreateStruct,
+ const VOID *Data,
+ UINT32 DataSize,
+ BOOLEAN SignedInteger
+ )
+{
+ const UINT8* DataBytes;
+ UINT32 ActualDataSize;
+ BOOLEAN ValueIsNegative;
+
+ NULL_CHECK(CreateStruct);
+ NULL_CHECK(Data);
+
+ if (DataSize == 0) {
+ DEBUG ((DEBUG_INFO, "invalid DataSize=0\n"));
+ return TcgResultFailure;
+ }
+
+ DataBytes = (const UINT8*)Data;
+
+ // integer should be represented by smallest atom possible
+ // so calculate real Data Size
+ ValueIsNegative = SignedInteger && DataBytes[ DataSize - 1 ] & 0x80;
+
+ // assumes native Data is little endian
+ // shorten Data to smallest byte representation
+ for (ActualDataSize = DataSize; ActualDataSize > 1; ActualDataSize--) {
+ // ignore sign extended FFs
+ if (ValueIsNegative && (DataBytes[ActualDataSize - 1] != 0xFF)) {
+ break;
+ } else if (!ValueIsNegative && (DataBytes[ActualDataSize - 1] != 0)) {
+ // ignore extended 00s
+ break;
+ }
+ }
+
+ return TcgAddAtom(CreateStruct, Data, ActualDataSize, TCG_ATOM_TYPE_INTEGER, SignedInteger ? 1 : 0);
+}
+
+/**
+ Adds an 8-bit unsigned integer to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the integer
+ @param[in] Value Integer Value to add
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddUINT8(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT8 Value
+ )
+{
+ return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
+}
+
+/**
+
+ Adds a 16-bit unsigned integer to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the integer
+ @param[in] Value Integer Value to add
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddUINT16 (
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT16 Value
+ )
+{
+ return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
+}
+
+/**
+
+ Adds a 32-bit unsigned integer to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the integer
+ @param[in] Value Integer Value to add
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddUINT32(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 Value
+ )
+{
+ return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
+}
+
+
+/**
+
+ Adds a 64-bit unsigned integer to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the integer
+ @param[in] Value Integer Value to add
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddUINT64(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT64 Value
+ )
+{
+ return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
+}
+
+/**
+ Adds a BOOLEAN to the Data structure.
+
+ @param[in/out] CreateStruct Structure used to add the integer
+ @param[in] Value BOOLEAN Value to add
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddBOOLEAN(
+ TCG_CREATE_STRUCT *CreateStruct,
+ BOOLEAN Value
+ )
+{
+ return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
+}
+
+/**
+ Add tcg uid info.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+ @param Uid Input uid info.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddTcgUid(
+ TCG_CREATE_STRUCT *CreateStruct,
+ TCG_UID Uid
+ )
+{
+ return TcgAddByteSequence(CreateStruct, &Uid, sizeof(TCG_UID), FALSE);
+}
+
+/**
+ Add start list.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddStartList(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTLIST);
+}
+
+/**
+ Add end list.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddEndList(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDLIST);
+}
+
+/**
+ Add start name.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddStartName(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTNAME);
+}
+
+/**
+ Add end name.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddEndName(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDNAME);
+}
+
+/**
+ Add end call.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddCall(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_CALL);
+}
+
+/**
+ Add end of data.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddEndOfData(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDDATA);
+}
+
+/**
+ Add end of session.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddEndOfSession(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDSESSION);
+}
+
+/**
+ Add start transaction.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddStartTransaction(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTTRANSACTION);
+}
+
+/**
+ Add end transaction.
+
+ @param [in/out] CreateStruct Structure used to add the integer
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgAddEndTransaction(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDTRANSACTION);
+}
+
+/**
+ Initial the tcg parse stucture.
+
+ @param ParseStruct Input parse structure.
+ @param Buffer Input buffer data.
+ @param BufferSize Input buffer size.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgInitTcgParseStruct(
+ TCG_PARSE_STRUCT *ParseStruct,
+ const VOID *Buffer,
+ UINT32 BufferSize
+ )
+{
+ UINT32 ComPacketLength;
+ UINT32 PacketLength;
+
+ NULL_CHECK(ParseStruct);
+ NULL_CHECK(Buffer);
+
+ if (BufferSize < sizeof(TCG_COM_PACKET)) {
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ ParseStruct->ComPacket = (TCG_COM_PACKET*)Buffer;
+
+ ComPacketLength = SwapBytes32(ParseStruct->ComPacket->LengthBE);
+
+ if ((BufferSize - sizeof(TCG_COM_PACKET)) < ComPacketLength) {
+ DEBUG ((DEBUG_INFO, "Buffer %u too small for ComPacket %u\n", BufferSize, ComPacketLength));
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ ParseStruct->BufferSize = BufferSize;
+ ParseStruct->Buffer = Buffer;
+
+ ParseStruct->CurPacket = NULL;
+ ParseStruct->CurSubPacket = NULL;
+ ParseStruct->CurPtr = NULL;
+
+ // if payload > 0, then must have a packet
+ if (ComPacketLength != 0) {
+ if (ComPacketLength < sizeof(TCG_PACKET)) {
+ DEBUG ((DEBUG_INFO, "ComPacket too small for Packet\n"));
+ return (TcgResultFailureBufferTooSmall);
+ }
+ ParseStruct->CurPacket = (TCG_PACKET*)ParseStruct->ComPacket->Payload;
+
+ PacketLength = SwapBytes32(ParseStruct->CurPacket->LengthBE);
+
+ if (PacketLength > 0) {
+ if (PacketLength < sizeof(TCG_SUB_PACKET)) {
+ DEBUG ((DEBUG_INFO, "Packet too small for SubPacket\n"));
+ return (TcgResultFailureBufferTooSmall);
+ }
+
+ ParseStruct->CurSubPacket = (TCG_SUB_PACKET*)ParseStruct->CurPacket->Payload;
+ }
+ }
+
+ //TODO should check for method status list at this point?
+
+ return (TcgResultSuccess);
+}
+
+/**
+ Get next token info.
+
+ @param ParseStruct Input parse structure info.
+ @param TcgToken return the tcg token info.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextToken(
+ TCG_PARSE_STRUCT *ParseStruct,
+ TCG_TOKEN *TcgToken
+ )
+{
+ const UINT8* EndOfSubPacket;
+ UINT8* TokenEnd;
+ UINT8 Hdr;
+ TCG_SIMPLE_TOKEN_SHORT_ATOM* TmpShort;
+ const TCG_SIMPLE_TOKEN_MEDIUM_ATOM* TmpMed;
+ const TCG_SIMPLE_TOKEN_LONG_ATOM* TmpLong;
+
+ NULL_CHECK(ParseStruct);
+ NULL_CHECK(TcgToken);
+
+ if (ParseStruct->ComPacket == NULL ||
+ ParseStruct->CurPacket == NULL ||
+ ParseStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", ParseStruct->ComPacket, ParseStruct->CurPacket, ParseStruct->CurSubPacket));
+ return TcgResultFailureInvalidAction;
+ }
+
+ // initial call, start at sub packet
+ if (ParseStruct->CurPtr == NULL) {
+ ParseStruct->CurPtr = ParseStruct->CurSubPacket->Payload;
+ }
+
+ EndOfSubPacket = ParseStruct->CurSubPacket->Payload + SwapBytes32(ParseStruct->CurSubPacket->LengthBE);
+ TokenEnd = NULL;
+
+ // confirmed that subpacket Length falls within end of Buffer and TCG_COM_PACKET,
+ // so simply need to verify the loop stays within current subpacket
+ if (ParseStruct->CurPtr >= EndOfSubPacket) {
+ DEBUG ((DEBUG_INFO, "ParseStruct->CurPtr >= EndOfSubPacket\n"));
+ return (TcgResultFailureEndBuffer);
+ }
+
+ Hdr = *ParseStruct->CurPtr;
+ TcgToken->HdrStart = ParseStruct->CurPtr;
+
+ // Tiny Atom range
+ if (Hdr <= 0x7F) {
+ // tiny atom Header is only 1 byte, so don't need to verify Size before cast and access
+ TcgToken->Type = TcgTokenTypeTinyAtom;
+
+ TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_TINY_ATOM);
+
+ // verify caller will have enough Size to reference token
+ if (TokenEnd >= EndOfSubPacket) {
+ DEBUG ((DEBUG_INFO, "Tiny Atom TokenEnd >= EndOfSubPacket\n"));
+ return (TcgResultFailureEndBuffer);
+ }
+ }
+ // Short Atom Range
+ else if (0x80 <= Hdr && Hdr <= 0xBF) {
+ // short atom Header is only 1 byte, so don't need to verify Size before cast and access
+ TmpShort = (TCG_SIMPLE_TOKEN_SHORT_ATOM*)(ParseStruct->CurPtr);
+ TcgToken->Type = TcgTokenTypeShortAtom;
+
+ TokenEnd = (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM) + TmpShort->ShortAtomBits.Length);
+
+ // verify caller will have enough Size to reference token
+ if (TokenEnd >= EndOfSubPacket) {
+ DEBUG ((DEBUG_INFO, "Short Atom TokenEnd >= EndOfSubPacket\n"));
+ return (TcgResultFailureEndBuffer);
+ }
+ }
+ // Medium Atom Range
+ else if (0xC0 <= Hdr && Hdr <= 0xDF) {
+ if (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM) >= EndOfSubPacket) {
+ return (TcgResultFailureEndBuffer);
+ }
+ TmpMed = (const TCG_SIMPLE_TOKEN_MEDIUM_ATOM*)ParseStruct->CurPtr;
+ TcgToken->Type = TcgTokenTypeMediumAtom;
+ TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM) +
+ ((TmpMed->MediumAtomBits.LengthHigh << TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) |
+ TmpMed->MediumAtomBits.LengthLow);
+
+ // verify caller will have enough Size to reference token
+ if (TokenEnd >= EndOfSubPacket) {
+ DEBUG ((DEBUG_INFO, "Medium Atom TokenEnd >= EndOfSubPacket\n"));
+ return (TcgResultFailureEndBuffer);
+ }
+ }
+ // Long Atom Range
+ else if (0xE0 <= Hdr && Hdr <= 0xE3) {
+ if (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM) >= EndOfSubPacket) {
+ return (TcgResultFailureEndBuffer);
+ }
+ TmpLong = (const TCG_SIMPLE_TOKEN_LONG_ATOM*)ParseStruct->CurPtr;
+ TcgToken->Type = TcgTokenTypeLongAtom;
+
+ TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM) +
+ ((TmpLong->LongAtomBits.LengthHigh << TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) |
+ (TmpLong->LongAtomBits.LengthMid << TCG_LONG_ATOM_LENGTH_MID_SHIFT) |
+ TmpLong->LongAtomBits.LengthLow);
+
+ // verify caller will have enough Size to reference token
+ if (TokenEnd >= EndOfSubPacket) {
+ DEBUG ((DEBUG_INFO, "Long Atom TokenEnd >= EndOfSubPacket\n"));
+ return (TcgResultFailureEndBuffer);
+ }
+ } else {
+ // single byte tokens
+ switch (Hdr) {
+ case TCG_TOKEN_STARTLIST:
+ TcgToken->Type = TcgTokenTypeStartList;
+ break;
+ case TCG_TOKEN_ENDLIST:
+ TcgToken->Type = TcgTokenTypeEndList;
+ break;
+ case TCG_TOKEN_STARTNAME:
+ TcgToken->Type = TcgTokenTypeStartName;
+ break;
+ case TCG_TOKEN_ENDNAME:
+ TcgToken->Type = TcgTokenTypeEndName;
+ break;
+ case TCG_TOKEN_CALL:
+ TcgToken->Type = TcgTokenTypeCall;
+ break;
+ case TCG_TOKEN_ENDDATA:
+ TcgToken->Type = TcgTokenTypeEndOfData;
+ break;
+ case TCG_TOKEN_ENDSESSION:
+ TcgToken->Type = TcgTokenTypeEndOfSession;
+ break;
+ case TCG_TOKEN_STARTTRANSACTION:
+ TcgToken->Type = TcgTokenTypeStartTransaction;
+ break;
+ case TCG_TOKEN_ENDTRANSACTION:
+ TcgToken->Type = TcgTokenTypeEndTransaction;
+ break;
+ case TCG_TOKEN_EMPTY:
+ TcgToken->Type = TcgTokenTypeEmptyAtom;
+ break;
+ default:
+ DEBUG ((DEBUG_INFO, "WARNING: reserved token Type 0x%02X\n", Hdr));
+ TcgToken->Type = TcgTokenTypeReserved;
+ break;
+ }
+ ParseStruct->CurPtr++;
+ TokenEnd = TcgToken->HdrStart + 1;
+ }
+
+ // increment curptr for next call
+ ParseStruct->CurPtr = TokenEnd;
+ return (TcgResultSuccess);
+}
+
+/**
+ Get atom info.
+
+ @param TcgToken Input token info.
+ @param HeaderLength return the header length.
+ @param DataLength return the data length.
+ @param ByteOrInt return the atom Type.
+ @param SignOrCont return the sign or count info.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetAtomInfo(
+ const TCG_TOKEN *TcgToken,
+ UINT32 *HeaderLength,
+ UINT32 *DataLength,
+ UINT8 *ByteOrInt,
+ UINT8 *SignOrCont
+ )
+{
+ TCG_SIMPLE_TOKEN_TINY_ATOM* TinyAtom;
+ TCG_SIMPLE_TOKEN_SHORT_ATOM* ShortAtom;
+ TCG_SIMPLE_TOKEN_MEDIUM_ATOM* MediumAtom;
+ TCG_SIMPLE_TOKEN_LONG_ATOM* LongAtom;
+
+ NULL_CHECK(TcgToken);
+ NULL_CHECK(HeaderLength);
+ NULL_CHECK(DataLength);
+ NULL_CHECK(ByteOrInt);
+ NULL_CHECK(SignOrCont);
+
+ switch (TcgToken->Type) {
+ case TcgTokenTypeTinyAtom: {
+ TinyAtom = (TCG_SIMPLE_TOKEN_TINY_ATOM*)TcgToken->HdrStart;
+ *ByteOrInt = TCG_ATOM_TYPE_INTEGER;
+ *SignOrCont = TinyAtom->TinyAtomBits.Sign;
+ *HeaderLength = 0;
+ *DataLength = 0; // tiny atom must be handled as a special case - Header and Data in the same byte
+ return TcgResultSuccess;
+ }
+
+ case TcgTokenTypeShortAtom: {
+ ShortAtom = (TCG_SIMPLE_TOKEN_SHORT_ATOM*)TcgToken->HdrStart;
+ *ByteOrInt = ShortAtom->ShortAtomBits.ByteOrInt;
+ *SignOrCont = ShortAtom->ShortAtomBits.SignOrCont;
+ *HeaderLength = sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM);
+ *DataLength = ShortAtom->ShortAtomBits.Length;
+ return TcgResultSuccess;
+ }
+
+ case TcgTokenTypeMediumAtom: {
+ MediumAtom = (TCG_SIMPLE_TOKEN_MEDIUM_ATOM*)TcgToken->HdrStart;
+ *ByteOrInt = MediumAtom->MediumAtomBits.ByteOrInt;
+ *SignOrCont = MediumAtom->MediumAtomBits.SignOrCont;
+ *HeaderLength = sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM);
+ *DataLength = (MediumAtom->MediumAtomBits.LengthHigh << TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) | MediumAtom->MediumAtomBits.LengthLow;
+ return TcgResultSuccess;
+ }
+
+ case TcgTokenTypeLongAtom: {
+ LongAtom = (TCG_SIMPLE_TOKEN_LONG_ATOM*)TcgToken->HdrStart;
+ *ByteOrInt = LongAtom->LongAtomBits.ByteOrInt;
+ *SignOrCont = LongAtom->LongAtomBits.SignOrCont;
+ *HeaderLength = sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM);
+ *DataLength = (LongAtom->LongAtomBits.LengthHigh << TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) |
+ (LongAtom->LongAtomBits.LengthMid << TCG_LONG_ATOM_LENGTH_MID_SHIFT) |
+ LongAtom->LongAtomBits.LengthLow;
+ return TcgResultSuccess;
+ }
+
+ default:
+ DEBUG ((DEBUG_INFO, "Token Type is not simple atom (%d)\n", TcgToken->Type));
+ return (TcgResultFailureInvalidType);
+ }
+}
+
+/**
+ Get token specified value.
+
+ @param TcgToken Input token info.
+ @param Value return the value.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetTokenUINT64(
+ const TCG_TOKEN *TcgToken,
+ UINT64 *Value
+ )
+{
+ UINT32 HdrLength;
+ UINT32 DataLength;
+ UINT8 ByteOrInt;
+ UINT8 IsSigned;
+ TCG_SIMPLE_TOKEN_TINY_ATOM* TmpTiny;
+ const UINT8* Data;
+ UINT32 Index;
+
+ NULL_CHECK(TcgToken);
+ NULL_CHECK(Value);
+
+ Index = 0;
+ *Value = 0;
+ ERROR_CHECK(TcgGetAtomInfo(TcgToken, &HdrLength, &DataLength, &ByteOrInt, &IsSigned));
+
+ if (ByteOrInt != TCG_ATOM_TYPE_INTEGER) {
+ DEBUG ((DEBUG_INFO, "Invalid Type, expected integer not byte sequence\n"));
+ return TcgResultFailureInvalidType;
+ }
+
+ if (IsSigned != 0) {
+ DEBUG ((DEBUG_INFO, "Integer is signed, expected unsigned\n"));
+ return TcgResultFailureInvalidType;
+ }
+
+ // special case for tiny atom
+ // Header and Data are in one byte, so extract only the Data bitfield
+ if (TcgToken->Type == TcgTokenTypeTinyAtom) {
+ TmpTiny = (TCG_SIMPLE_TOKEN_TINY_ATOM*)TcgToken->HdrStart;
+ *Value = TmpTiny->TinyAtomBits.Data;
+ return TcgResultSuccess;
+ }
+
+ if (DataLength > sizeof(UINT64)) {
+ DEBUG ((DEBUG_INFO, "Length %d is greater than Size of UINT64\n", DataLength));
+ return TcgResultFailureBufferTooSmall;
+ }
+
+ // read big-endian integer
+ Data = TcgToken->HdrStart + HdrLength;
+ for (Index = 0; Index < DataLength; Index++) {
+ *Value = LShiftU64(*Value, 8) | Data[Index];
+ }
+
+ return TcgResultSuccess;
+}
+
+/**
+ Get token byte sequence.
+
+ @param TcgToken Input token info.
+ @param Length Input the length info.
+
+ @retval Return the value data.
+
+**/
+UINT8*
+EFIAPI
+TcgGetTokenByteSequence(
+ const TCG_TOKEN *TcgToken,
+ UINT32 *Length
+ )
+{
+ UINT32 HdrLength;
+ UINT8 ByteOrInt;
+ UINT8 SignOrCont;
+
+ if (TcgToken == NULL || Length == NULL) {
+ return NULL;
+ }
+
+ *Length = 0;
+ if (TcgGetAtomInfo(TcgToken, &HdrLength, Length, &ByteOrInt, &SignOrCont) != TcgResultSuccess) {
+ DEBUG ((DEBUG_INFO, "Failed to get simple token info\n"));
+ return NULL;
+ }
+
+ if (ByteOrInt != TCG_ATOM_TYPE_BYTE) {
+ DEBUG ((DEBUG_INFO, "Invalid Type, expected byte sequence not integer\n"));
+ return NULL;
+ }
+
+ return (TcgToken->HdrStart + HdrLength);
+}
+
+/**
+ Get next specify value.
+
+ @param ParseStruct Input parse structure.
+ @param Value Return vlaue.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextUINT8(
+ TCG_PARSE_STRUCT *ParseStruct,
+ UINT8 *Value
+ )
+{
+ UINT64 Value64;
+ TCG_TOKEN Tok;
+
+ NULL_CHECK(Value);
+
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
+
+ if (Value64 > MAX_UINT8) {
+ return TcgResultFailure;
+ }
+
+ *Value = (UINT8)Value64;
+
+ return TcgResultSuccess;
+}
+
+/**
+ Get next specify value.
+
+ @param ParseStruct Input parse structure.
+ @param Value Return vlaue.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextUINT16(
+ TCG_PARSE_STRUCT *ParseStruct,
+ UINT16 *Value
+ )
+{
+ UINT64 Value64;
+ TCG_TOKEN Tok;
+
+ NULL_CHECK(Value);
+
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
+
+ if (Value64 > MAX_UINT16) {
+ return TcgResultFailure;
+ }
+
+ *Value = (UINT16)Value64;
+
+ return TcgResultSuccess;
+}
+
+/**
+ Get next specify value.
+
+ @param ParseStruct Input parse structure.
+ @param Value Return vlaue.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextUINT32(
+ TCG_PARSE_STRUCT *ParseStruct,
+ UINT32 *Value
+ )
+{
+ UINT64 Value64;
+ TCG_TOKEN Tok;
+
+ NULL_CHECK(Value);
+
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
+
+ if (Value64 > MAX_UINT32) {
+ return TcgResultFailure;
+ }
+
+ *Value = (UINT32)Value64;
+
+ return TcgResultSuccess;
+}
+
+/**
+ Get next specify value.
+
+ @param ParseStruct Input parse structure.
+ @param Value Return vlaue.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextUINT64(
+ TCG_PARSE_STRUCT *ParseStruct,
+ UINT64 *Value
+ )
+{
+ TCG_TOKEN Tok;
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ ERROR_CHECK(TcgGetTokenUINT64(&Tok, Value));
+ return TcgResultSuccess;
+}
+
+/**
+ Get next specify value.
+
+ @param ParseStruct Input parse structure.
+ @param Value Return vlaue.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextBOOLEAN(
+ TCG_PARSE_STRUCT *ParseStruct,
+ BOOLEAN *Value
+ )
+{
+ UINT64 Value64;
+ TCG_TOKEN Tok;
+
+ NULL_CHECK(Value);
+
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
+
+ if (Value64 > 1) {
+ return TcgResultFailure;
+ }
+
+ *Value = (BOOLEAN)Value64;
+
+ return TcgResultSuccess;
+}
+
+/**
+ Get next tcg uid info.
+
+ @param ParseStruct Input parse structure.
+ @param Uid Get the uid info.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextTcgUid(
+ TCG_PARSE_STRUCT *ParseStruct,
+ TCG_UID *Uid
+ )
+{
+ TCG_TOKEN Tok;
+ UINT32 Length;
+ const UINT8* ByteSeq;
+
+ NULL_CHECK(Uid);
+
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ ByteSeq = TcgGetTokenByteSequence(&Tok, &Length);
+
+ if (Length != sizeof(TCG_UID)) {
+ DEBUG ((DEBUG_INFO, "Token Length %u != TCG_UID Size %u\n", Length, (UINT32)sizeof(TCG_UID)));
+ return TcgResultFailure;
+ }
+
+ CopyMem(Uid, ByteSeq, sizeof(TCG_UID));
+
+ return TcgResultSuccess;
+}
+
+/**
+ Get next byte sequence.
+
+ @param ParseStruct Input parse structure.
+ @param Data return the data.
+ @param Length return the length.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextByteSequence(
+ TCG_PARSE_STRUCT *ParseStruct,
+ const VOID **Data,
+ UINT32 *Length
+ )
+{
+ TCG_TOKEN Tok;
+ const UINT8* Bs;
+
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ Bs = TcgGetTokenByteSequence(&Tok, Length);
+
+ if (Bs == NULL) {
+ return TcgResultFailure;
+ }
+ *Data = Bs;
+ return TcgResultSuccess;
+}
+
+/**
+ Get next token Type.
+
+ @param ParseStruct Input parse structure.
+ @param Type Input the type need to check.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextTokenType(
+ TCG_PARSE_STRUCT *ParseStruct,
+ TCG_TOKEN_TYPE Type
+ )
+{
+ TCG_TOKEN Tok;
+ ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
+ if (Tok.Type != Type) {
+ DEBUG ((DEBUG_INFO, "expected Type %u, got Type %u\n", Type, Tok.Type));
+ return TcgResultFailure;
+ }
+ return TcgResultSuccess;
+}
+
+/**
+ Get next start list.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextStartList(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartList);
+}
+
+/**
+ Get next end list.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextEndList(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndList);
+}
+
+/**
+ Get next start name.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextStartName(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartName);
+}
+
+/**
+ Get next end name.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextEndName(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndName);
+}
+
+/**
+ Get next call.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextCall(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeCall);
+}
+
+/**
+ Get next end data.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextEndOfData(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndOfData);
+}
+
+/**
+ Get next end of session.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextEndOfSession(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndOfSession);
+}
+
+/**
+ Get next start transaction.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextStartTransaction(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartTransaction);
+}
+
+/**
+ Get next end transaction.
+
+ @param ParseStruct Input parse structure.
+
+ @retval return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetNextEndTransaction(
+ TCG_PARSE_STRUCT *ParseStruct
+ )
+{
+ return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndTransaction);
+}
diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
new file mode 100644
index 0000000000..a80cb00a9c
--- /dev/null
+++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf
@@ -0,0 +1,38 @@
+## @file
+# This is a Tcg Storage core library.
+#
+# This module is used to provide API used by Opal password solution.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = TcgStorageCoreLib
+ FILE_GUID = ad63b09b-1fc9-4789-af0c-5af8a3fb1f9c
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = TcgStorageCoreLib|DXE_DRIVER DXE_CORE DXE_SMM_DRIVER
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[Sources]
+ TcgStorageCore.c
+ TcgStorageUtil.c
diff --git a/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c
new file mode 100644
index 0000000000..30808cd835
--- /dev/null
+++ b/SecurityPkg/Library/TcgStorageCoreLib/TcgStorageUtil.c
@@ -0,0 +1,907 @@
+/** @file
+ Provide functions to provide tcg storage core spec related functions.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/TcgStorageCoreLib.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+typedef struct {
+ UINT16 FeatureCode;
+ TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feature;
+ UINTN FeatureSize;
+} TCG_FIND_FEATURE_CTX;
+
+/**
+ Returns a human-readable string representing a method status return code.
+
+ @param[in] MethodStatus Method status to translate to a string
+
+
+ @retval return the string info.
+**/
+CHAR8*
+EFIAPI
+TcgMethodStatusString(
+ UINT8 MethodStatus
+ )
+{
+ switch (MethodStatus) {
+ #define C(status) case TCG_METHOD_STATUS_CODE_ ## status: return #status
+ C(SUCCESS);
+ C(NOT_AUTHORIZED);
+ C(OBSOLETE);
+ C(SP_BUSY);
+ C(SP_FAILED);
+ C(SP_DISABLED);
+ C(SP_FROZEN);
+ C(NO_SESSIONS_AVAILABLE);
+ C(UNIQUENESS_CONFLICT);
+ C(INSUFFICIENT_SPACE);
+ C(INSUFFICIENT_ROWS);
+ C(INVALID_PARAMETER);
+ C(OBSOLETE2);
+ C(OBSOLETE3);
+ C(TPER_MALFUNCTION);
+ C(TRANSACTION_FAILURE);
+ C(RESPONSE_OVERFLOW);
+ C(AUTHORITY_LOCKED_OUT);
+ C(FAIL);
+ #undef C
+ }
+ return "unknown";
+}
+
+
+/**
+ adds call token and method Header (invoking id, and method id).
+
+ @param CreateStruct The input create structure.
+ @param InvokingId Invoking id.
+ @param MethodId Method id.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgStartMethodCall(
+ TCG_CREATE_STRUCT *CreateStruct,
+ TCG_UID InvokingId,
+ TCG_UID MethodId
+ )
+{
+ NULL_CHECK(CreateStruct);
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ ERROR_CHECK(TcgAddCall(CreateStruct));
+ ERROR_CHECK(TcgAddTcgUid(CreateStruct, InvokingId));
+ ERROR_CHECK(TcgAddTcgUid(CreateStruct, MethodId));
+
+ return TcgResultSuccess;
+}
+
+/**
+ Adds START LIST token.
+
+ @param CreateStruct The input create structure.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgStartParameters(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ NULL_CHECK(CreateStruct);
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ return TcgAddStartList(CreateStruct);
+}
+
+/**
+ Adds END LIST token.
+
+ @param CreateStruct The input create structure.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgEndParameters(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ NULL_CHECK(CreateStruct);
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ return TcgAddEndList(CreateStruct);
+}
+
+/**
+ Adds END Data token and method list.
+
+ @param CreateStruct The input create structure.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgEndMethodCall(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ NULL_CHECK(CreateStruct);
+
+ if (CreateStruct->ComPacket == NULL ||
+ CreateStruct->CurPacket == NULL ||
+ CreateStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
+ return (TcgResultFailureInvalidAction);
+ }
+
+ ERROR_CHECK(TcgAddEndOfData(CreateStruct));
+
+ ERROR_CHECK(TcgAddStartList(CreateStruct));
+ ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); // expected to complete properly
+ ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); // reserved
+ ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); // reserved
+ ERROR_CHECK(TcgAddEndList(CreateStruct));
+
+ return TcgResultSuccess;
+}
+
+/**
+ Retrieves the comID and Extended comID of the ComPacket in the Tcg response.
+ It is intended to be used to confirm the received Tcg response is intended for user that received it.
+
+ @param [in] ParseStruct Structure used to parse received TCG response.
+ @param [in/out] ComId comID retrieved from received ComPacket.
+ @param [in/out] ComIdExtension Extended comID retrieved from received ComPacket
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetComIds(
+ const TCG_PARSE_STRUCT *ParseStruct,
+ UINT16 *ComId,
+ UINT16 *ComIdExtension
+ )
+{
+ NULL_CHECK(ParseStruct);
+ NULL_CHECK(ComId);
+ NULL_CHECK(ComIdExtension);
+
+ if (ParseStruct->ComPacket == NULL) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p\n", ParseStruct->ComPacket));
+ return TcgResultFailureInvalidAction;
+ }
+
+ *ComId = SwapBytes16(ParseStruct->ComPacket->ComIDBE);
+ *ComIdExtension = SwapBytes16(ParseStruct->ComPacket->ComIDExtensionBE);
+
+ return TcgResultSuccess;
+}
+
+/**
+ Checks if the ComIDs of the response match the expected values.
+
+ @param[in] ParseStruct Structure used to parse received TCG response
+ @param[in] ExpectedComId Expected comID
+ @param[in] ExpectedComIdExtension Expected extended comID
+
+**/
+TCG_RESULT
+EFIAPI
+TcgCheckComIds(
+ const TCG_PARSE_STRUCT *ParseStruct,
+ UINT16 ExpectedComId,
+ UINT16 ExpectedComIdExtension
+ )
+{
+ UINT16 ParseComId;
+ UINT16 ParseComIdExtension;
+
+ ERROR_CHECK(TcgGetComIds(ParseStruct, &ParseComId, &ParseComIdExtension));
+ if (ParseComId != ExpectedComId || ParseComIdExtension != ExpectedComIdExtension) {
+ DEBUG ((DEBUG_INFO, "Com ID: Actual 0x%02X Expected 0x%02X\n", ParseComId, ExpectedComId));
+ DEBUG ((DEBUG_INFO, "Extended Com ID: 0x%02X Expected 0x%02X\n", ParseComIdExtension, ExpectedComIdExtension));
+ return TcgResultFailure;
+ }
+ return TcgResultSuccess;
+}
+
+/**
+ Returns the method status of the current subpacket. Does not affect the current position
+ in the ComPacket. In other words, it can be called whenever you have a valid SubPacket.
+
+ @param [in/out] ParseStruct Structure used to parse received TCG response
+ @param [in/out] MethodStatus Method status retrieved of the current SubPacket
+
+**/
+TCG_RESULT
+EFIAPI
+TcgGetMethodStatus(
+ const TCG_PARSE_STRUCT *ParseStruct,
+ UINT8 *MethodStatus
+ )
+{
+ TCG_PARSE_STRUCT TmpParseStruct;
+ TCG_TOKEN TcgToken;
+ UINT8 Reserved1, Reserved2;
+
+ NULL_CHECK(ParseStruct);
+ NULL_CHECK(MethodStatus);
+
+ if (ParseStruct->ComPacket == NULL ||
+ ParseStruct->CurPacket == NULL ||
+ ParseStruct->CurSubPacket == NULL
+ ) {
+ DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", ParseStruct->ComPacket, ParseStruct->CurPacket, ParseStruct->CurSubPacket));
+ return TcgResultFailureInvalidAction;
+ }
+
+ // duplicate ParseStruct, then don't need to "reset" location cur ptr
+ CopyMem (&TmpParseStruct, ParseStruct, sizeof(TCG_PARSE_STRUCT));
+
+ // method status list exists after the end method call in the subpacket
+ // skip tokens until ENDDATA is found
+ do {
+ ERROR_CHECK(TcgGetNextToken(&TmpParseStruct, &TcgToken));
+ } while (TcgToken.Type != TcgTokenTypeEndOfData);
+
+ // only reach here if enddata is found
+ // at this point, the curptr is pointing at method status list beginning
+ ERROR_CHECK(TcgGetNextStartList(&TmpParseStruct));
+ ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, MethodStatus));
+ ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, &Reserved1));
+ ERROR_CHECK(TcgGetNextUINT8(&TmpParseStruct, &Reserved2));
+ ERROR_CHECK(TcgGetNextEndList(&TmpParseStruct));
+
+ if (Reserved1 != 0) {
+ DEBUG ((DEBUG_INFO, "Method status reserved1 = 0x%02X (expected 0)\n", Reserved1));
+ return TcgResultFailure;
+ }
+
+ if (Reserved2 != 0) {
+ DEBUG ((DEBUG_INFO, "Method status reserved2 = 0x%02X (expected 0)\n", Reserved1));
+ return TcgResultFailure;
+ }
+
+ return TcgResultSuccess;
+}
+
+/**
+ Return the toke type string info.
+
+ @param Type Input the type info.
+
+ @retval Return the string for this type.
+
+**/
+CHAR8*
+EFIAPI
+TcgTokenTypeString(
+ TCG_TOKEN_TYPE Type
+ )
+{
+ switch (Type) {
+ case TcgTokenTypeReserved: return "Reserved";
+ case TcgTokenTypeTinyAtom: return "Tiny Atom";
+ case TcgTokenTypeShortAtom: return "Short Atom";
+ case TcgTokenTypeMediumAtom: return "Medium Atom";
+ case TcgTokenTypeLongAtom: return "Long Atom";
+ case TcgTokenTypeStartList: return "Start List";
+ case TcgTokenTypeEndList: return "End List";
+ case TcgTokenTypeStartName: return "Start Name";
+ case TcgTokenTypeEndName: return "End Name";
+ case TcgTokenTypeCall: return "Call";
+ case TcgTokenTypeEndOfData: return "End of Data";
+ case TcgTokenTypeEndOfSession: return "End of Session";
+ case TcgTokenTypeStartTransaction: return "Start Transaction";
+ case TcgTokenTypeEndTransaction: return "End Transaction";
+ case TcgTokenTypeEmptyAtom: return "Empty atom";
+ }
+ return "Unknown";
+}
+
+
+/**
+
+ Adds Start Session call to the data structure. This creates the entire ComPacket structure and
+ returns the size of the entire compacket in the size parameter.
+
+ @param [in/out] CreateStruct Structure used to add the start session call
+ @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function.
+ @param [in] ComId ComID for the ComPacket
+ @param [in] ComIdExtension Extended ComID for the ComPacket
+ @param [in] HostSessionId Host Session ID
+ @param [in] SpId Security Provider to start session with
+ @param [in] Write Write option for start session. TRUE = start session requests write access
+ @param [in] HostChallengeLength Length of the host challenge. Length should be 0 if hostChallenge is NULL
+ @param [in] HostChallenge Host challenge for Host Signing Authority. If NULL, then no Host Challenge shall be sent.
+ @param [in] HostSigningAuthority Host Signing Authority used for start session. If NULL, then no Host Signing Authority shall be sent.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgCreateStartSession(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 *Size,
+ UINT16 ComId,
+ UINT16 ComIdExtension,
+ UINT32 HostSessionId,
+ TCG_UID SpId,
+ BOOLEAN Write,
+ UINT32 HostChallengeLength,
+ const VOID *HostChallenge,
+ TCG_UID HostSigningAuthority
+ )
+{
+ ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
+ ERROR_CHECK(TcgStartPacket(CreateStruct, 0x0, 0x0, 0x0, 0x0, 0x0)) ;
+ ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
+ ERROR_CHECK(TcgStartMethodCall(CreateStruct, TCG_UID_SMUID, TCG_UID_SM_START_SESSION));
+ ERROR_CHECK(TcgStartParameters(CreateStruct));
+ ERROR_CHECK(TcgAddUINT32(CreateStruct, HostSessionId));
+ ERROR_CHECK(TcgAddTcgUid(CreateStruct, SpId));
+ ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, Write));
+
+ // optional parameters
+ if (HostChallenge != NULL && HostChallengeLength != 0) {
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x00)); //TODO Create Enum for Method Optional Parameters?
+ ERROR_CHECK(TcgAddByteSequence(CreateStruct, HostChallenge, HostChallengeLength, FALSE));
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+ }
+ // optional parameters
+ if (HostSigningAuthority != 0) {
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x03)); //TODO Create Enum for Method Optional Parameters?
+ ERROR_CHECK(TcgAddTcgUid(CreateStruct, HostSigningAuthority));
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+ }
+
+ ERROR_CHECK(TcgEndParameters(CreateStruct));
+ ERROR_CHECK(TcgEndMethodCall(CreateStruct));
+ ERROR_CHECK(TcgEndSubPacket(CreateStruct));
+ ERROR_CHECK(TcgEndPacket(CreateStruct));
+ ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
+
+ return TcgResultSuccess;
+}
+
+/**
+ Parses the Sync Session response contained in the parseStruct to retrieve Tper session ID. If the Sync Session response
+ parameters do not match the comID, extended ComID and host session ID then a failure is returned.
+
+ @param[in/out] ParseStruct Structure used to parse received TCG response, contains Sync Session response.
+ @param[in] ComId Expected ComID that is compared to actual ComID of response
+ @param[in] ComIdExtension Expected Extended ComID that is compared to actual Extended ComID of response
+ @param[in] HostSessionId Expected Host Session ID that is compared to actual Host Session ID of response
+ @param[in/out] TperSessionId Tper Session ID retrieved from the Sync Session response.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgParseSyncSession(
+ const TCG_PARSE_STRUCT *ParseStruct,
+ UINT16 ComId,
+ UINT16 ComIdExtension,
+ UINT32 HostSessionId,
+ UINT32 *TperSessionId
+ )
+{
+ UINT8 MethodStatus;
+ TCG_PARSE_STRUCT TmpParseStruct;
+ UINT16 ParseComId;
+ UINT16 ParseExtComId;
+ TCG_UID InvokingUID;
+ TCG_UID MethodUID;
+ UINT32 RecvHostSessionId;
+
+ NULL_CHECK(ParseStruct);
+ NULL_CHECK(TperSessionId);
+
+ CopyMem (&TmpParseStruct, ParseStruct, sizeof(TCG_PARSE_STRUCT));
+
+ // verify method status is good
+ ERROR_CHECK(TcgGetMethodStatus(&TmpParseStruct, &MethodStatus));
+ METHOD_STATUS_ERROR_CHECK (MethodStatus, TcgResultFailure);
+
+ // verify comids
+ ERROR_CHECK(TcgGetComIds(&TmpParseStruct, &ParseComId, &ParseExtComId));
+
+ if ((ComId != ParseComId) || (ComIdExtension != ParseExtComId)) {
+ DEBUG ((DEBUG_INFO, "unmatched comid (exp: 0x%X recv: 0x%X) or comid extension (exp: 0x%X recv: 0x%X)\n", ComId, ParseComId, ComIdExtension, ParseExtComId));
+ return TcgResultFailure;
+ }
+ ERROR_CHECK(TcgGetNextCall(&TmpParseStruct));
+ ERROR_CHECK(TcgGetNextTcgUid(&TmpParseStruct, &InvokingUID));
+ ERROR_CHECK(TcgGetNextTcgUid(&TmpParseStruct, &MethodUID));
+ ERROR_CHECK(TcgGetNextStartList(&TmpParseStruct));
+ ERROR_CHECK(TcgGetNextUINT32(&TmpParseStruct, &RecvHostSessionId));
+ ERROR_CHECK(TcgGetNextUINT32(&TmpParseStruct, TperSessionId));
+ ERROR_CHECK(TcgGetNextEndList(&TmpParseStruct));
+ ERROR_CHECK(TcgGetNextEndOfData(&TmpParseStruct));
+
+ if (InvokingUID != TCG_UID_SMUID) {
+ DEBUG ((DEBUG_INFO, "Invoking UID did not match UID_SMUID\n"));
+ return TcgResultFailure;
+ }
+
+ if (MethodUID != TCG_UID_SM_SYNC_SESSION) {
+ DEBUG ((DEBUG_INFO, "Method UID did not match UID_SM_SYNC_SESSION\n"));
+ return TcgResultFailure;
+ }
+
+ if (HostSessionId != RecvHostSessionId) {
+ DEBUG ((DEBUG_INFO, "unmatched HostSessionId (exp: 0x%X recv: 0x%X)\n", HostSessionId, RecvHostSessionId));
+ return TcgResultFailure;
+ }
+
+ return TcgResultSuccess;
+}
+
+/**
+
+ Creates ComPacket with EndSession.
+ This assumes a start session has already been opened.
+
+ @param [in/out] CreateStruct Structure used to add Endsession
+ @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function.
+ @param [in] ComId ComID for the ComPacket
+ @param [in] ComIdExtension Extended ComID for the ComPacket
+ @param [in] HostSessionId Host Session ID for the Packet
+ @param [in] TpSessionId Tper Session ID for the Packet
+
+**/
+TCG_RESULT
+EFIAPI
+TcgCreateEndSession(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 *Size,
+ UINT16 ComId,
+ UINT16 ComIdExtension,
+ UINT32 HostSessionId,
+ UINT32 TpSessionId
+ )
+{
+ ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
+ ERROR_CHECK(TcgStartPacket(CreateStruct, TpSessionId, HostSessionId, 0x0, 0x0, 0x0));
+ ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
+ ERROR_CHECK(TcgAddEndOfSession(CreateStruct));
+ ERROR_CHECK(TcgEndSubPacket(CreateStruct));
+ ERROR_CHECK(TcgEndPacket(CreateStruct));
+ ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
+
+ return TcgResultSuccess;
+}
+
+/**
+ Set start method.
+
+ @param CreateStruct Input create structure.
+ @param Row Input the row info.
+ @param ColumnNumber the column info.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgStartMethodSet(
+ TCG_CREATE_STRUCT *CreateStruct,
+ TCG_UID Row,
+ UINT32 ColumnNumber
+ )
+{
+ ERROR_CHECK(TcgStartMethodCall(CreateStruct, Row, TCG_UID_METHOD_SET));
+ ERROR_CHECK(TcgStartParameters(CreateStruct));
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x01)); // "Values"
+ ERROR_CHECK(TcgAddStartList(CreateStruct));
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddUINT32(CreateStruct, ColumnNumber));
+ return TcgResultSuccess;
+}
+
+/**
+ Set end method.
+
+ @param CreateStruct Input create structure.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgEndMethodSet(
+ TCG_CREATE_STRUCT *CreateStruct
+ )
+{
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+ ERROR_CHECK(TcgAddEndList(CreateStruct));
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+ ERROR_CHECK(TcgEndParameters(CreateStruct));
+ ERROR_CHECK(TcgEndMethodCall(CreateStruct));
+ return TcgResultSuccess;
+}
+
+/**
+ Creates ComPacket with a Method call that sets the PIN column for the row specified.
+ This assumes a start session has already been opened with the desired SP.
+
+ @param [in/out] CreateStruct Structure used to add method call.
+ @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function.
+ @param [in] ComId ComID for the ComPacket
+ @param [in] ComIdExtension Extended ComID for the ComPacket
+ @param [in] TperSession Tper Session ID for the Packet
+ @param [in] HostSession Host Session ID for the Packet
+ @param [in] SidRow UID of row of current SP to set PIN column
+ @param [in] Password value of PIN to set
+ @param [in] PasswordSize Size of PIN
+
+**/
+TCG_RESULT
+EFIAPI
+TcgCreateSetCPin(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 *Size,
+ UINT16 ComId,
+ UINT16 ComIdExtension,
+ UINT32 TperSession,
+ UINT32 HostSession,
+ TCG_UID SidRow,
+ const VOID *Password,
+ UINT32 PasswordSize
+ )
+{
+ // set new SID Password
+ ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
+ ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0));
+ ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
+ ERROR_CHECK(TcgStartMethodSet(CreateStruct, SidRow, 0x03)); // "PIN"
+ ERROR_CHECK(TcgAddByteSequence(CreateStruct, Password, PasswordSize, FALSE));
+ ERROR_CHECK(TcgEndMethodSet(CreateStruct));
+ ERROR_CHECK(TcgEndSubPacket(CreateStruct));
+ ERROR_CHECK(TcgEndPacket(CreateStruct));
+ ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
+ return TcgResultSuccess;
+}
+
+/**
+ Creates ComPacket with a Method call that sets the "Enabled" column for the row specified using the value specified.
+ This assumes a start session has already been opened with the desired SP.
+
+ @param [in/out] CreateStruct Structure used to add method call
+ @param [in/out] Size Describes the size of the entire ComPacket (header and payload). Filled out by function.
+ @param [in] ComId ComID for the ComPacket
+ @param [in] ComIdExtension Extended ComID for the ComPacket
+ @param [in] TperSession Tper Session ID for the Packet
+ @param [in] HostSession Host Session ID for the Packet
+ @param [in] AuthorityUid Authority UID to modify the "Enabled" column for
+ @param [in] Enabled Value to set the "Enabled" column to
+
+**/
+TCG_RESULT
+EFIAPI
+TcgSetAuthorityEnabled(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 *Size,
+ UINT16 ComId,
+ UINT16 ComIdExtension,
+ UINT32 TperSession,
+ UINT32 HostSession,
+ TCG_UID AuthorityUid,
+ BOOLEAN Enabled
+ )
+{
+ ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
+ ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0));
+ ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
+ ERROR_CHECK(TcgStartMethodSet(CreateStruct, AuthorityUid, 0x05)); // "Enabled"
+ ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, Enabled));
+ ERROR_CHECK(TcgEndMethodSet(CreateStruct));
+ ERROR_CHECK(TcgEndSubPacket(CreateStruct));
+ ERROR_CHECK(TcgEndPacket(CreateStruct));
+ ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
+ return TcgResultSuccess;
+}
+
+/**
+ Create set ace.
+
+ @param CreateStruct Input create structure.
+ @param Size size info.
+ @param ComId ComId info.
+ @param ComIdExtension ComId extension info.
+ @param TperSession Tper session data.
+ @param HostSession Host session data.
+ @param AceRow Ace row info.
+ @param Authority1 Authority 1 info.
+ @param LogicalOperator Logiccal operator info.
+ @param Authority2 Authority 2 info.
+
+ @retval Return the action result.
+
+**/
+TCG_RESULT
+EFIAPI
+TcgCreateSetAce(
+ TCG_CREATE_STRUCT *CreateStruct,
+ UINT32 *Size,
+ UINT16 ComId,
+ UINT16 ComIdExtension,
+ UINT32 TperSession,
+ UINT32 HostSession,
+ TCG_UID AceRow,
+ TCG_UID Authority1,
+ BOOLEAN LogicalOperator,
+ TCG_UID Authority2
+ )
+{
+ UINT8 HalfUidAuthorityObjectRef[4];
+ UINT8 HalfUidBooleanAce[4];
+
+ HalfUidAuthorityObjectRef[0] = 0x0;
+ HalfUidAuthorityObjectRef[1] = 0x0;
+ HalfUidAuthorityObjectRef[2] = 0xC;
+ HalfUidAuthorityObjectRef[3] = 0x5;
+
+ HalfUidBooleanAce[0] = 0x0;
+ HalfUidBooleanAce[1] = 0x0;
+ HalfUidBooleanAce[2] = 0x4;
+ HalfUidBooleanAce[3] = 0xE;
+
+ ERROR_CHECK(TcgStartComPacket(CreateStruct, ComId, ComIdExtension));
+ ERROR_CHECK(TcgStartPacket(CreateStruct, TperSession, HostSession, 0x0, 0x0, 0x0));
+ ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
+ ERROR_CHECK(TcgStartMethodSet(CreateStruct, AceRow, 0x03)); // "BooleanExpr"
+ ERROR_CHECK(TcgAddStartList(CreateStruct));
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidAuthorityObjectRef, sizeof(HalfUidAuthorityObjectRef), FALSE));
+ ERROR_CHECK(TcgAddTcgUid(CreateStruct, Authority1));
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidAuthorityObjectRef, sizeof(HalfUidAuthorityObjectRef), FALSE));
+ ERROR_CHECK(TcgAddTcgUid(CreateStruct, Authority2));
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+
+ ERROR_CHECK(TcgAddStartName(CreateStruct));
+ ERROR_CHECK(TcgAddByteSequence(CreateStruct, HalfUidBooleanAce, sizeof(HalfUidBooleanAce), FALSE));
+ ERROR_CHECK(TcgAddBOOLEAN(CreateStruct, LogicalOperator));
+ ERROR_CHECK(TcgAddEndName(CreateStruct));
+ ERROR_CHECK(TcgAddEndList(CreateStruct));
+ ERROR_CHECK(TcgEndMethodSet(CreateStruct));
+ ERROR_CHECK(TcgEndSubPacket(CreateStruct));
+ ERROR_CHECK(TcgEndPacket(CreateStruct));
+ ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
+ return TcgResultSuccess;
+}
+
+/**
+ Enum level 0 discovery.
+
+ @param DiscoveryHeader Discovery header.
+ @param Callback Callback function.
+ @param Context The context for the function.
+
+ @retval return true if the callback return TRUE, else return FALSE.
+
+**/
+BOOLEAN
+EFIAPI
+TcgEnumLevel0Discovery(
+ const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader,
+ TCG_LEVEL0_ENUM_CALLBACK Callback,
+ VOID *Context
+ )
+{
+ UINT32 BytesLeft;
+ const UINT8 *DiscoveryBufferPtr;
+ UINT32 FeatLength;
+ TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feat;
+
+ //
+ // Total bytes including descriptors but not including the Length field
+ //
+ BytesLeft = SwapBytes32(DiscoveryHeader->LengthBE);
+
+ //
+ // If discovery Header is not valid, exit
+ //
+ if (BytesLeft == 0) {
+ return FALSE;
+ }
+
+ //
+ // Subtract the Length of the Header, except the Length field, which is not included
+ //
+ BytesLeft -= (sizeof(TCG_LEVEL0_DISCOVERY_HEADER) - sizeof(DiscoveryHeader->LengthBE));
+
+ //
+ // Move ptr to first descriptor
+ //
+ DiscoveryBufferPtr = (const UINT8*)DiscoveryHeader + sizeof(TCG_LEVEL0_DISCOVERY_HEADER);
+
+ while (BytesLeft > sizeof(TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER)) {
+ //
+ // Pointer to beginning of descriptor (including common Header)
+ //
+ Feat = (TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER*)DiscoveryBufferPtr;
+
+ FeatLength = Feat->Length + sizeof(TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER);
+
+ //
+ // Not enough bytes left for Feature descriptor
+ //
+ if (BytesLeft < FeatLength) {
+ break;
+ }
+
+ //
+ // Report the Feature to the callback
+ //
+ if (Callback(DiscoveryHeader, Feat, FeatLength, Context)) {
+ return TRUE;
+ }
+
+ //
+ // Descriptor Length only describes Data after common Header
+ //
+ BytesLeft -= FeatLength;
+ DiscoveryBufferPtr += FeatLength;
+ }
+
+ return FALSE;
+}
+
+/**
+ The callback function for Get Feature function.
+
+ @param DiscoveryHeader Input discovery header.
+ @param Feature Input Feature.
+ @param FeatureSize Input Feature size.
+ @param Context The context.
+
+**/
+BOOLEAN
+EFIAPI
+TcgFindFeatureCallback(
+ const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader,
+ TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER *Feature,
+ UINTN FeatureSize,
+ VOID *Context
+ )
+{
+ TCG_FIND_FEATURE_CTX* FindCtx;
+
+ FindCtx = (TCG_FIND_FEATURE_CTX*)Context;
+ if ( SwapBytes16( Feature->FeatureCode_BE ) == FindCtx->FeatureCode ) {
+ FindCtx->Feature = Feature;
+ FindCtx->FeatureSize = FeatureSize;
+ return TRUE; // done enumerating features
+ }
+ return FALSE; // continue enumerating
+}
+
+/**
+ Get Feature code from the header.
+
+ @param DiscoveryHeader The discovery header.
+ @param FeatureCode reutrn the Feature code.
+ @param FeatureSize return the Feature size.
+
+ @retval return the Feature code data.
+**/
+TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER*
+EFIAPI
+TcgGetFeature(
+ const TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader,
+ UINT16 FeatureCode,
+ UINTN *FeatureSize
+ )
+{
+ TCG_FIND_FEATURE_CTX FindCtx;
+
+ FindCtx.FeatureCode = FeatureCode;
+ FindCtx.Feature = NULL;
+ FindCtx.FeatureSize = 0;
+
+ TcgEnumLevel0Discovery(DiscoveryHeader, TcgFindFeatureCallback, &FindCtx);
+ if (FeatureSize != NULL) {
+ *FeatureSize = FindCtx.FeatureSize;
+ }
+ return FindCtx.Feature;
+}
+
+/**
+ Determines if the protocol provided is part of the provided supported protocol list.
+
+ @param[in] ProtocolList Supported protocol list to investigate
+ @param[in] Protocol Protocol value to determine if supported
+
+ @return TRUE = protocol is supported, FALSE = protocol is not supported
+**/
+BOOLEAN
+EFIAPI
+TcgIsProtocolSupported(
+ const TCG_SUPPORTED_SECURITY_PROTOCOLS *ProtocolList,
+ UINT16 Protocol
+ )
+{
+ UINT16 Index;
+ UINT16 ListLength;
+
+ ListLength = SwapBytes16(ProtocolList->ListLength_BE);
+
+ if (ListLength > sizeof(ProtocolList->List)) {
+ DEBUG ((DEBUG_INFO, "WARNING: list Length is larger than max allowed Value; truncating\n"));
+ ListLength = sizeof(ProtocolList->List);
+ }
+
+ for (Index = 0; Index < ListLength; Index++) {
+ if (ProtocolList->List[Index] == Protocol) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether lock or not.
+
+ @param Discovery
+
+ @retval TURE if lock, FALSE if not lock.
+**/
+BOOLEAN
+EFIAPI
+TcgIsLocked(
+ const TCG_LEVEL0_DISCOVERY_HEADER *Discovery
+ )
+{
+ UINTN Size;
+ TCG_LOCKING_FEATURE_DESCRIPTOR *LockDescriptor;
+
+ Size = 0;
+ LockDescriptor =(TCG_LOCKING_FEATURE_DESCRIPTOR*) TcgGetFeature (Discovery, TCG_FEATURE_LOCKING, &Size);
+
+ if (LockDescriptor != NULL && Size >= sizeof(*LockDescriptor)) {
+ DEBUG ((DEBUG_INFO, "locked: %d\n", LockDescriptor->Locked));
+ return LockDescriptor->Locked;
+ }
+
+ //
+ // Descriptor was not found
+ //
+ return FALSE;
+}