/** @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;
  }

  ASSERT (ByteSeq != NULL);

  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);
}
