1 /** @file
2   Provide functions to provide tcg storage core spec related functions.
3 
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <Library/TcgStorageCoreLib.h>
10 
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 //#include <Library/PrintLib.h>
15 
16 /**
17   Required to be called before calling any other Tcg functions with the TCG_CREATE_STRUCT.
18   Initializes the packet variables to NULL.  Additionally, the buffer will be memset.
19 
20   @param [in/out]    CreateStruct    Structure to initialize
21   @param [in]        Buffer          Buffer allocated by client of library.  It will contain the Tcg encoded packet.  This cannot be null.
22   @param [in]        BufferSize      Size of buffer provided.  It cannot be 0.
23 
24   @retval       Return the action result.
25 **/
26 TCG_RESULT
27 EFIAPI
TcgInitTcgCreateStruct(TCG_CREATE_STRUCT * CreateStruct,VOID * Buffer,UINT32 BufferSize)28 TcgInitTcgCreateStruct(
29   TCG_CREATE_STRUCT      *CreateStruct,
30   VOID                   *Buffer,
31   UINT32                 BufferSize
32   )
33 {
34   NULL_CHECK(CreateStruct);
35   NULL_CHECK(Buffer);
36 
37   if (BufferSize == 0) {
38     DEBUG ((DEBUG_INFO, "BufferSize=0\n"));
39     return (TcgResultFailureZeroSize);
40   }
41 
42   ZeroMem(Buffer, BufferSize);
43   CreateStruct->BufferSize = BufferSize;
44   CreateStruct->Buffer = Buffer;
45   CreateStruct->ComPacket = NULL;
46   CreateStruct->CurPacket = NULL;
47   CreateStruct->CurSubPacket = NULL;
48 
49   return (TcgResultSuccess);
50 }
51 
52 /**
53 
54   Encodes the ComPacket header to the data structure.
55 
56   @param[in/out]    CreateStruct          Structure to initialize
57   @param[in]        ComId                 ComID of the Tcg ComPacket.
58   @param[in]        ComIdExtension        ComID Extension of the Tcg ComPacket.
59 
60 **/
61 TCG_RESULT
62 EFIAPI
TcgStartComPacket(TCG_CREATE_STRUCT * CreateStruct,UINT16 ComId,UINT16 ComIdExtension)63 TcgStartComPacket(
64   TCG_CREATE_STRUCT   *CreateStruct,
65   UINT16              ComId,
66   UINT16              ComIdExtension
67   )
68 {
69   NULL_CHECK(CreateStruct);
70 
71   if (CreateStruct->ComPacket != NULL ||
72       CreateStruct->CurPacket != NULL ||
73       CreateStruct->CurSubPacket != NULL
74      ) {
75     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket,
76     CreateStruct->CurSubPacket));
77     return (TcgResultFailureInvalidAction);
78   }
79 
80   if (sizeof(TCG_COM_PACKET) > CreateStruct->BufferSize) {
81     DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
82     return (TcgResultFailureBufferTooSmall);
83   }
84 
85   CreateStruct->ComPacket = (TCG_COM_PACKET*)CreateStruct->Buffer;
86   CreateStruct->ComPacket->ComIDBE = SwapBytes16(ComId);
87   CreateStruct->ComPacket->ComIDExtensionBE = SwapBytes16(ComIdExtension);
88 
89   return (TcgResultSuccess);
90 }
91 
92 /**
93 
94   Starts a new ComPacket in the Data structure.
95 
96   @param [in/out]     CreateStruct    Structure used to add Tcg Packet
97   @param[in]          Tsn             Packet Tper session number
98   @param[in]          Hsn             Packet Host session number
99   @param[in]          SeqNumber       Packet Sequence Number
100   @param[in]          AckType         Packet Acknowledge Type
101   @param[in]          Ack             Packet Acknowledge
102 
103 **/
104 TCG_RESULT
105 EFIAPI
TcgStartPacket(TCG_CREATE_STRUCT * CreateStruct,UINT32 Tsn,UINT32 Hsn,UINT32 SeqNumber,UINT16 AckType,UINT32 Ack)106 TcgStartPacket(
107   TCG_CREATE_STRUCT    *CreateStruct,
108   UINT32               Tsn,
109   UINT32               Hsn,
110   UINT32               SeqNumber,
111   UINT16               AckType,
112   UINT32               Ack
113   )
114 {
115   UINT32 AddedSize;
116   NULL_CHECK(CreateStruct);
117 
118   AddedSize = 0;
119 
120   if (CreateStruct->ComPacket == NULL ||
121       CreateStruct->CurPacket != NULL ||
122       CreateStruct->CurSubPacket != NULL
123      ) {
124     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
125     return (TcgResultFailureInvalidAction);
126   }
127 
128   // update TCG_COM_PACKET and packet lengths
129   AddedSize = sizeof(TCG_PACKET);
130 
131   if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) {
132     DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
133     return (TcgResultFailureBufferTooSmall);
134   }
135 
136   CreateStruct->CurPacket = (TCG_PACKET*)(CreateStruct->ComPacket->Payload + SwapBytes32(CreateStruct->ComPacket->LengthBE));
137 
138   CreateStruct->CurPacket->TperSessionNumberBE = SwapBytes32( Tsn );
139   CreateStruct->CurPacket->HostSessionNumberBE = SwapBytes32( Hsn );
140   CreateStruct->CurPacket->SequenceNumberBE = SwapBytes32( SeqNumber );
141   CreateStruct->CurPacket->AckTypeBE = SwapBytes16( AckType );
142   CreateStruct->CurPacket->AcknowledgementBE = SwapBytes32( Ack );
143 
144   CreateStruct->CurPacket->LengthBE = 0;
145 
146   // update TCG_COM_PACKET Length for next pointer
147   CreateStruct->ComPacket->LengthBE = SwapBytes32( SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize );
148 
149   return (TcgResultSuccess);
150 }
151 
152 /**
153 
154   Starts a new SubPacket in the Data structure.
155 
156   @param[in/out]    CreateStruct        Structure used to start Tcg SubPacket
157   @param[in]        Kind                SubPacket kind
158 
159 **/
160 TCG_RESULT
161 EFIAPI
TcgStartSubPacket(TCG_CREATE_STRUCT * CreateStruct,UINT16 Kind)162 TcgStartSubPacket(
163   TCG_CREATE_STRUCT    *CreateStruct,
164   UINT16               Kind
165   )
166 {
167   UINT32 AddedSize;
168 
169   NULL_CHECK(CreateStruct);
170 
171   AddedSize = 0;
172 
173   if (CreateStruct->ComPacket == NULL ||
174       CreateStruct->CurPacket == NULL ||
175       CreateStruct->CurSubPacket != NULL
176      ) {
177     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
178     return (TcgResultFailureInvalidAction);
179   }
180 
181   AddedSize = sizeof(TCG_SUB_PACKET);
182 
183   if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) {
184     DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
185     return (TcgResultFailureBufferTooSmall);
186   }
187 
188   CreateStruct->CurSubPacket = (TCG_SUB_PACKET*)(CreateStruct->CurPacket->Payload + SwapBytes32(CreateStruct->CurPacket->LengthBE));
189   CreateStruct->CurSubPacket->KindBE = SwapBytes16(Kind);
190 
191   // update lengths
192   CreateStruct->CurSubPacket->LengthBE = 0;
193 
194   // update TCG_COM_PACKET and packet lengths
195   CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize);
196   CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + AddedSize);
197 
198   return (TcgResultSuccess);
199 }
200 
201 /**
202 
203   Ends the current SubPacket in the Data structure.  This function will also perform the 4-byte padding
204   required for Subpackets.
205 
206   @param[in/out]       CreateStruct        Structure used to end the current Tcg SubPacket
207 
208 **/
209 TCG_RESULT
210 EFIAPI
TcgEndSubPacket(TCG_CREATE_STRUCT * CreateStruct)211 TcgEndSubPacket(
212   TCG_CREATE_STRUCT   *CreateStruct
213   )
214 {
215   UINT32 PadSize;
216 
217   NULL_CHECK(CreateStruct);
218 
219   PadSize = 0;
220 
221   if (CreateStruct->ComPacket == NULL ||
222       CreateStruct->CurPacket == NULL  ||
223       CreateStruct->CurSubPacket == NULL
224      ) {
225     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
226     return (TcgResultFailureInvalidAction);
227   }
228 
229   // align to 4-byte boundaries, so shift padding
230   // pad Size does not apply to subpacket Length
231   PadSize = TCG_SUBPACKET_ALIGNMENT - (SwapBytes32(CreateStruct->CurSubPacket->LengthBE) & (TCG_SUBPACKET_ALIGNMENT - 1));
232 
233   if (PadSize == TCG_SUBPACKET_ALIGNMENT) {
234     PadSize = 0;
235   }
236 
237   if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + PadSize) > CreateStruct->BufferSize) {
238     DEBUG ((DEBUG_INFO, "BufferSize=0x%X\n", CreateStruct->BufferSize));
239     return (TcgResultFailureBufferTooSmall);
240   }
241 
242   CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + PadSize);
243   CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + PadSize);
244 
245   CreateStruct->CurSubPacket = NULL;
246 
247   return (TcgResultSuccess);
248 }
249 
250 /**
251 
252   Ends the current Packet in the Data structure.
253 
254   @param[in/out]       CreateStruct        Structure used to end the current Tcg Packet
255 
256 **/
257 TCG_RESULT
258 EFIAPI
TcgEndPacket(TCG_CREATE_STRUCT * CreateStruct)259 TcgEndPacket(
260   TCG_CREATE_STRUCT     *CreateStruct
261   )
262 {
263   NULL_CHECK(CreateStruct);
264 
265   if (CreateStruct->ComPacket == NULL ||
266       CreateStruct->CurPacket == NULL ||
267       CreateStruct->CurSubPacket != NULL
268      ) {
269     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
270     return (TcgResultFailureInvalidAction);
271   }
272 
273   CreateStruct->CurPacket = NULL;
274 
275   return (TcgResultSuccess);
276 }
277 
278 /**
279 
280   Ends the ComPacket in the Data structure and ret
281 
282   @param [in/out]       CreateStruct       Structure used to end the Tcg ComPacket
283   @param [in/out]       Size               Describes the Size of the entire ComPacket (Header and payload). Filled out by function.
284 
285 **/
286 TCG_RESULT
287 EFIAPI
TcgEndComPacket(TCG_CREATE_STRUCT * CreateStruct,UINT32 * Size)288 TcgEndComPacket(
289   TCG_CREATE_STRUCT      *CreateStruct,
290   UINT32                 *Size
291   )
292 {
293   NULL_CHECK(CreateStruct);
294   NULL_CHECK(Size);
295 
296   if (CreateStruct->ComPacket == NULL ||
297       CreateStruct->CurPacket != NULL ||
298       CreateStruct->CurSubPacket != NULL
299      ) {
300     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
301     return (TcgResultFailureInvalidAction);
302   }
303 
304   *Size = SwapBytes32(CreateStruct->ComPacket->LengthBE) + sizeof(*CreateStruct->ComPacket);
305   CreateStruct->ComPacket = NULL;
306 
307   return (TcgResultSuccess);
308 }
309 
310 /**
311   Adds raw Data with optional Header
312 
313   @param       CreateStruct       The create structure.
314   @param       Header             The header structure.
315   @param       HeaderSize         The header size.
316   @param       Data               The data need to add.
317   @param       DataSize           The data size.
318   @param       ByteSwapData       Whether byte or swap data.
319 
320 **/
321 TCG_RESULT
TcgAddRawTokenData(TCG_CREATE_STRUCT * CreateStruct,const VOID * Header,UINT8 HeaderSize,const VOID * Data,UINT32 DataSize,BOOLEAN ByteSwapData)322 TcgAddRawTokenData(
323   TCG_CREATE_STRUCT      *CreateStruct,
324   const VOID             *Header,
325   UINT8                  HeaderSize,
326   const VOID             *Data,
327   UINT32                 DataSize,
328   BOOLEAN                ByteSwapData
329   )
330 {
331   UINT32 AddedSize;
332   UINT8* Dest;
333   const UINT8* DataBytes;
334   UINT32 Index;
335 
336   AddedSize = 0;
337   Index = 0;
338   Dest = NULL;
339 
340   NULL_CHECK(CreateStruct);
341 
342   if ((HeaderSize != 0 && Header == NULL) ||
343       (DataSize != 0 && Data == NULL)
344      ) {
345     DEBUG ((DEBUG_INFO, "HeaderSize=0x%X Header=%p DataSize=0x%X Data=%p\n", HeaderSize, Header, DataSize, Data));
346     return (TcgResultFailureNullPointer);
347   }
348 
349   if (CreateStruct->ComPacket == NULL ||
350       CreateStruct->CurPacket == NULL ||
351       CreateStruct->CurSubPacket == NULL
352      ) {
353     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", CreateStruct->ComPacket, CreateStruct->CurPacket, CreateStruct->CurSubPacket));
354     return (TcgResultFailureInvalidAction);
355   }
356 
357   // verify there is enough Buffer Size
358   AddedSize = HeaderSize + DataSize;
359   if ((SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize) > CreateStruct->BufferSize) {
360     return (TcgResultFailureBufferTooSmall);
361   }
362 
363   // Get a pointer to where the new bytes should go
364   Dest = CreateStruct->ComPacket->Payload + SwapBytes32(CreateStruct->ComPacket->LengthBE);
365 
366   switch (HeaderSize) {
367     case sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM):
368     case sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM):
369     case sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM):
370       CopyMem(Dest, Header, HeaderSize);
371       Dest += HeaderSize;
372     case 0: // no Header is valid
373       break;
374     // invalid Header Size
375     default:
376       DEBUG ((DEBUG_INFO, "unsupported HeaderSize=%u\n", HeaderSize));
377       return TcgResultFailure;
378   }
379 
380   // copy the Data bytes
381   if (ByteSwapData) {
382     DataBytes = (const UINT8*)Data;
383     for (Index = 0; Index < DataSize; Index++) {
384       Dest[Index] = DataBytes[DataSize - 1 - Index];
385     }
386   } else {
387     CopyMem(Dest, Data, DataSize);
388   }
389 
390   // Update all the packet sizes
391   CreateStruct->ComPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->ComPacket->LengthBE) + AddedSize);
392   CreateStruct->CurPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurPacket->LengthBE) + AddedSize);
393   CreateStruct->CurSubPacket->LengthBE = SwapBytes32(SwapBytes32(CreateStruct->CurSubPacket->LengthBE) + AddedSize);
394 
395   return (TcgResultSuccess);
396 }
397 
398 /**
399 
400   Adds a single raw token byte to the Data structure.
401 
402   @param[in/out]   CreateStruct        Structure used to add the byte
403   @param[in]       Byte                Byte to add
404 
405 **/
406 TCG_RESULT
407 EFIAPI
TcgAddRawByte(TCG_CREATE_STRUCT * CreateStruct,UINT8 Byte)408 TcgAddRawByte(
409   TCG_CREATE_STRUCT     *CreateStruct,
410   UINT8                 Byte
411   )
412 {
413   return TcgAddRawTokenData(CreateStruct, NULL, 0, &Byte, 1, FALSE);
414 }
415 
416 
417 /**
418    simple tokens - atoms: tiny, short, medium, long and empty atoms.
419    tiny atom can be a signed or unsigned integer.
420    short, medium, long can be a signed or unsigned integer OR a complete or non-final byte sequence.
421 
422   @param       CreateStruct       The create structure.
423   @param       Data               The data need to add.
424   @param       DataSize           The data size.
425   @param       ByteOrInt,         Data format is byte or int.
426   @param       SignOrCont         sign or cont.
427 
428 
429 **/
430 TCG_RESULT
TcgAddAtom(TCG_CREATE_STRUCT * CreateStruct,const VOID * Data,UINT32 DataSize,UINT8 ByteOrInt,UINT8 SignOrCont)431 TcgAddAtom(
432   TCG_CREATE_STRUCT   *CreateStruct,
433   const VOID          *Data,
434   UINT32              DataSize,
435   UINT8               ByteOrInt,
436   UINT8               SignOrCont
437   )
438 {
439   const UINT8* DataBytes;
440   TCG_SIMPLE_TOKEN_TINY_ATOM TinyAtom;
441   TCG_SIMPLE_TOKEN_SHORT_ATOM ShortAtom;
442   TCG_SIMPLE_TOKEN_MEDIUM_ATOM MediumAtom;
443   TCG_SIMPLE_TOKEN_LONG_ATOM LongAtom;
444 
445   NULL_CHECK(CreateStruct);
446 
447   if (DataSize == 0) {
448     if (ByteOrInt == TCG_ATOM_TYPE_INTEGER) {
449       DEBUG ((DEBUG_INFO, "0-Size integer not allowed\n"));
450       return TcgResultFailure;
451     }
452   } else {
453     // if DataSize != 0, Data must be valid
454     NULL_CHECK(Data);
455   }
456 
457   // encode Data using the shortest possible atom
458   DataBytes = (const UINT8*)Data;
459   if ((DataSize == 1) &&
460       (ByteOrInt == TCG_ATOM_TYPE_INTEGER) &&
461       ((SignOrCont != 0 && ((TCG_TOKEN_TINYATOM_SIGNED_MIN_VALUE <= *(INT8*)Data) && (*(INT8*)Data <= TCG_TOKEN_TINYATOM_SIGNED_MAX_VALUE))) ||
462        (SignOrCont == 0 && ((*DataBytes <= TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE))))
463      ) {
464     TinyAtom.TinyAtomBits.IsZero = 0;
465     TinyAtom.TinyAtomBits.Sign = SignOrCont;
466     TinyAtom.TinyAtomBits.Data = *DataBytes & TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE;
467     return TcgAddRawTokenData(CreateStruct, NULL, 0, (UINT8*)&TinyAtom, sizeof(TCG_SIMPLE_TOKEN_TINY_ATOM), FALSE);
468   }
469 
470   if (DataSize <= TCG_TOKEN_SHORTATOM_MAX_BYTE_SIZE) {
471     ShortAtom.ShortAtomBits.IsOne = 1;
472     ShortAtom.ShortAtomBits.IsZero = 0;
473     ShortAtom.ShortAtomBits.ByteOrInt = ByteOrInt;
474     ShortAtom.ShortAtomBits.SignOrCont = SignOrCont;
475     ShortAtom.ShortAtomBits.Length = DataSize & 0x0F;
476     return TcgAddRawTokenData(CreateStruct, &ShortAtom, sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER);
477   }
478 
479   if (DataSize <= TCG_TOKEN_MEDIUMATOM_MAX_BYTE_SIZE) {
480     MediumAtom.MediumAtomBits.IsOne1 = 1;
481     MediumAtom.MediumAtomBits.IsOne2 = 1;
482     MediumAtom.MediumAtomBits.IsZero = 0;
483     MediumAtom.MediumAtomBits.ByteOrInt = ByteOrInt;
484     MediumAtom.MediumAtomBits.SignOrCont = SignOrCont;
485     MediumAtom.MediumAtomBits.LengthLow = DataSize & 0xFF;
486     MediumAtom.MediumAtomBits.LengthHigh = (DataSize >> TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) & TCG_MEDIUM_ATOM_LENGTH_HIGH_MASK;
487     return TcgAddRawTokenData(CreateStruct, &MediumAtom, sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER);
488   }
489 
490   LongAtom.LongAtomBits.IsOne1 = 1;
491   LongAtom.LongAtomBits.IsOne2 = 1;
492   LongAtom.LongAtomBits.IsOne3 = 1;
493   LongAtom.LongAtomBits.IsZero = 0;
494   LongAtom.LongAtomBits.ByteOrInt = ByteOrInt;
495   LongAtom.LongAtomBits.SignOrCont = SignOrCont;
496   LongAtom.LongAtomBits.LengthLow = DataSize & 0xFF;
497   LongAtom.LongAtomBits.LengthMid = (DataSize >> TCG_LONG_ATOM_LENGTH_MID_SHIFT) & 0xFF;
498   LongAtom.LongAtomBits.LengthHigh = (DataSize >> TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) & 0xFF;
499   return TcgAddRawTokenData(CreateStruct, &LongAtom, sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM), Data, DataSize, ByteOrInt == TCG_ATOM_TYPE_INTEGER);
500 }
501 
502 /**
503 
504   Adds the Data parameter as a byte sequence to the Data structure.
505 
506   @param[in/out]    CreateStruct      Structure used to add the byte sequence
507   @param[in]        Data              Byte sequence that will be encoded and copied into Data structure
508   @param[in]        DataSize          Length of Data provided
509   @param[in]        Continued         TRUE if byte sequence is continued or
510                                       FALSE if the Data contains the entire byte sequence to be encoded
511 
512 **/
513 TCG_RESULT
514 EFIAPI
TcgAddByteSequence(TCG_CREATE_STRUCT * CreateStruct,const VOID * Data,UINT32 DataSize,BOOLEAN Continued)515 TcgAddByteSequence(
516   TCG_CREATE_STRUCT     *CreateStruct,
517   const VOID            *Data,
518   UINT32                DataSize,
519   BOOLEAN               Continued
520   )
521 {
522   return TcgAddAtom(CreateStruct, Data, DataSize, TCG_ATOM_TYPE_BYTE, Continued ? 1 : 0);
523 }
524 
525 /**
526 
527   Adds an arbitrary-Length integer to the Data structure.
528   The integer will be encoded using the shortest possible atom.
529 
530   @param[in/out]     CreateStruct      Structure used to add the integer
531   @param[in]         Data              Integer in host byte order that will be encoded and copied into Data structure
532   @param[in]         DataSize          Length in bytes of the Data provided
533   @param[in]         SignedInteger     TRUE if the integer is signed or FALSE if the integer is unsigned
534 
535 **/
536 TCG_RESULT
537 EFIAPI
TcgAddInteger(TCG_CREATE_STRUCT * CreateStruct,const VOID * Data,UINT32 DataSize,BOOLEAN SignedInteger)538 TcgAddInteger(
539   TCG_CREATE_STRUCT  *CreateStruct,
540   const VOID         *Data,
541   UINT32             DataSize,
542   BOOLEAN            SignedInteger
543   )
544 {
545   const UINT8* DataBytes;
546   UINT32 ActualDataSize;
547   BOOLEAN ValueIsNegative;
548 
549   NULL_CHECK(CreateStruct);
550   NULL_CHECK(Data);
551 
552   if (DataSize == 0) {
553     DEBUG ((DEBUG_INFO, "invalid DataSize=0\n"));
554     return TcgResultFailure;
555   }
556 
557   DataBytes = (const UINT8*)Data;
558 
559   // integer should be represented by smallest atom possible
560   // so calculate real Data Size
561   ValueIsNegative = SignedInteger && DataBytes[ DataSize - 1 ] & 0x80;
562 
563   // assumes native Data is little endian
564   // shorten Data to smallest byte representation
565   for (ActualDataSize = DataSize; ActualDataSize > 1; ActualDataSize--) {
566     // ignore sign extended  FFs
567     if (ValueIsNegative && (DataBytes[ActualDataSize - 1] != 0xFF)) {
568       break;
569     } else if (!ValueIsNegative && (DataBytes[ActualDataSize - 1] != 0)) {
570       // ignore extended 00s
571       break;
572     }
573   }
574 
575   return TcgAddAtom(CreateStruct, Data, ActualDataSize, TCG_ATOM_TYPE_INTEGER, SignedInteger ? 1 : 0);
576 }
577 
578 /**
579   Adds an 8-bit unsigned integer to the Data structure.
580 
581   @param[in/out]       CreateStruct        Structure used to add the integer
582   @param[in]           Value               Integer Value to add
583 
584 **/
585 TCG_RESULT
586 EFIAPI
TcgAddUINT8(TCG_CREATE_STRUCT * CreateStruct,UINT8 Value)587 TcgAddUINT8(
588   TCG_CREATE_STRUCT   *CreateStruct,
589   UINT8               Value
590   )
591 {
592   return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
593 }
594 
595 /**
596 
597   Adds a 16-bit unsigned integer to the Data structure.
598 
599   @param[in/out]       CreateStruct        Structure used to add the integer
600   @param[in]           Value               Integer Value to add
601 
602 **/
603 TCG_RESULT
604 EFIAPI
TcgAddUINT16(TCG_CREATE_STRUCT * CreateStruct,UINT16 Value)605 TcgAddUINT16 (
606   TCG_CREATE_STRUCT   *CreateStruct,
607   UINT16              Value
608   )
609 {
610   return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
611 }
612 
613 /**
614 
615   Adds a 32-bit unsigned integer to the Data structure.
616 
617   @param[in/out]        CreateStruct        Structure used to add the integer
618   @param[in]            Value               Integer Value to add
619 
620 **/
621 TCG_RESULT
622 EFIAPI
TcgAddUINT32(TCG_CREATE_STRUCT * CreateStruct,UINT32 Value)623 TcgAddUINT32(
624   TCG_CREATE_STRUCT    *CreateStruct,
625   UINT32               Value
626   )
627 {
628   return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
629 }
630 
631 
632 /**
633 
634   Adds a 64-bit unsigned integer to the Data structure.
635 
636   @param[in/out]      CreateStruct        Structure used to add the integer
637   @param[in]          Value               Integer Value to add
638 
639 **/
640 TCG_RESULT
641 EFIAPI
TcgAddUINT64(TCG_CREATE_STRUCT * CreateStruct,UINT64 Value)642 TcgAddUINT64(
643   TCG_CREATE_STRUCT   *CreateStruct,
644   UINT64              Value
645   )
646 {
647   return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
648 }
649 
650 /**
651   Adds a BOOLEAN to the Data structure.
652 
653   @param[in/out]       CreateStruct     Structure used to add the integer
654   @param[in]           Value              BOOLEAN Value to add
655 
656 **/
657 TCG_RESULT
658 EFIAPI
TcgAddBOOLEAN(TCG_CREATE_STRUCT * CreateStruct,BOOLEAN Value)659 TcgAddBOOLEAN(
660   TCG_CREATE_STRUCT    *CreateStruct,
661   BOOLEAN              Value
662   )
663 {
664   return TcgAddInteger(CreateStruct, &Value, sizeof(Value), FALSE);
665 }
666 
667 /**
668   Add tcg uid info.
669 
670   @param [in/out]       CreateStruct       Structure used to add the integer
671   @param                Uid                Input uid info.
672 
673   @retval   return the action result.
674 
675 **/
676 TCG_RESULT
677 EFIAPI
TcgAddTcgUid(TCG_CREATE_STRUCT * CreateStruct,TCG_UID Uid)678 TcgAddTcgUid(
679   TCG_CREATE_STRUCT   *CreateStruct,
680   TCG_UID             Uid
681   )
682 {
683   return TcgAddByteSequence(CreateStruct, &Uid, sizeof(TCG_UID), FALSE);
684 }
685 
686 /**
687   Add start list.
688 
689   @param [in/out]       CreateStruct       Structure used to add the integer
690 
691   @retval   return the action result.
692 
693 **/
694 TCG_RESULT
695 EFIAPI
TcgAddStartList(TCG_CREATE_STRUCT * CreateStruct)696 TcgAddStartList(
697   TCG_CREATE_STRUCT          *CreateStruct
698   )
699 {
700   return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTLIST);
701 }
702 
703 /**
704   Add end list.
705 
706   @param [in/out]       CreateStruct       Structure used to add the integer
707 
708   @retval   return the action result.
709 
710 **/
711 TCG_RESULT
712 EFIAPI
TcgAddEndList(TCG_CREATE_STRUCT * CreateStruct)713 TcgAddEndList(
714   TCG_CREATE_STRUCT       *CreateStruct
715   )
716 {
717   return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDLIST);
718 }
719 
720 /**
721   Add start name.
722 
723   @param [in/out]       CreateStruct       Structure used to add the integer
724 
725   @retval   return the action result.
726 
727 **/
728 TCG_RESULT
729 EFIAPI
TcgAddStartName(TCG_CREATE_STRUCT * CreateStruct)730 TcgAddStartName(
731   TCG_CREATE_STRUCT          *CreateStruct
732   )
733 {
734   return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTNAME);
735 }
736 
737 /**
738   Add end name.
739 
740   @param [in/out]       CreateStruct       Structure used to add the integer
741 
742   @retval   return the action result.
743 
744 **/
745 TCG_RESULT
746 EFIAPI
TcgAddEndName(TCG_CREATE_STRUCT * CreateStruct)747 TcgAddEndName(
748   TCG_CREATE_STRUCT          *CreateStruct
749   )
750 {
751   return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDNAME);
752 }
753 
754 /**
755   Add end call.
756 
757   @param [in/out]       CreateStruct       Structure used to add the integer
758 
759   @retval   return the action result.
760 
761 **/
762 TCG_RESULT
763 EFIAPI
TcgAddCall(TCG_CREATE_STRUCT * CreateStruct)764 TcgAddCall(
765   TCG_CREATE_STRUCT      *CreateStruct
766   )
767 {
768   return TcgAddRawByte(CreateStruct, TCG_TOKEN_CALL);
769 }
770 
771 /**
772   Add end of data.
773 
774   @param [in/out]       CreateStruct       Structure used to add the integer
775 
776   @retval   return the action result.
777 
778 **/
779 TCG_RESULT
780 EFIAPI
TcgAddEndOfData(TCG_CREATE_STRUCT * CreateStruct)781 TcgAddEndOfData(
782   TCG_CREATE_STRUCT          *CreateStruct
783   )
784 {
785   return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDDATA);
786 }
787 
788 /**
789   Add end of session.
790 
791   @param [in/out]       CreateStruct       Structure used to add the integer
792 
793   @retval   return the action result.
794 
795 **/
796 TCG_RESULT
797 EFIAPI
TcgAddEndOfSession(TCG_CREATE_STRUCT * CreateStruct)798 TcgAddEndOfSession(
799   TCG_CREATE_STRUCT              *CreateStruct
800   )
801 {
802   return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDSESSION);
803 }
804 
805 /**
806   Add start transaction.
807 
808   @param [in/out]       CreateStruct       Structure used to add the integer
809 
810   @retval   return the action result.
811 
812 **/
813 TCG_RESULT
814 EFIAPI
TcgAddStartTransaction(TCG_CREATE_STRUCT * CreateStruct)815 TcgAddStartTransaction(
816   TCG_CREATE_STRUCT             *CreateStruct
817   )
818 {
819   return TcgAddRawByte(CreateStruct, TCG_TOKEN_STARTTRANSACTION);
820 }
821 
822 /**
823   Add end transaction.
824 
825   @param [in/out]       CreateStruct       Structure used to add the integer
826 
827   @retval   return the action result.
828 
829 **/
830 TCG_RESULT
831 EFIAPI
TcgAddEndTransaction(TCG_CREATE_STRUCT * CreateStruct)832 TcgAddEndTransaction(
833   TCG_CREATE_STRUCT           *CreateStruct
834   )
835 {
836   return TcgAddRawByte(CreateStruct, TCG_TOKEN_ENDTRANSACTION);
837 }
838 
839 /**
840   Initial the tcg parse stucture.
841 
842   @param    ParseStruct    Input parse structure.
843   @param    Buffer         Input buffer data.
844   @param    BufferSize     Input buffer size.
845 
846   @retval   return the action result.
847 
848 **/
849 TCG_RESULT
850 EFIAPI
TcgInitTcgParseStruct(TCG_PARSE_STRUCT * ParseStruct,const VOID * Buffer,UINT32 BufferSize)851 TcgInitTcgParseStruct(
852   TCG_PARSE_STRUCT          *ParseStruct,
853   const VOID                *Buffer,
854   UINT32                    BufferSize
855   )
856 {
857   UINT32 ComPacketLength;
858   UINT32 PacketLength;
859 
860   NULL_CHECK(ParseStruct);
861   NULL_CHECK(Buffer);
862 
863   if (BufferSize < sizeof(TCG_COM_PACKET)) {
864     return (TcgResultFailureBufferTooSmall);
865   }
866 
867   ParseStruct->ComPacket = (TCG_COM_PACKET*)Buffer;
868 
869   ComPacketLength = SwapBytes32(ParseStruct->ComPacket->LengthBE);
870 
871   if ((BufferSize - sizeof(TCG_COM_PACKET)) < ComPacketLength) {
872     DEBUG ((DEBUG_INFO, "Buffer %u too small for ComPacket %u\n", BufferSize, ComPacketLength));
873     return (TcgResultFailureBufferTooSmall);
874   }
875 
876   ParseStruct->BufferSize = BufferSize;
877   ParseStruct->Buffer = Buffer;
878 
879   ParseStruct->CurPacket = NULL;
880   ParseStruct->CurSubPacket = NULL;
881   ParseStruct->CurPtr = NULL;
882 
883   // if payload > 0, then must have a packet
884   if (ComPacketLength != 0) {
885     if (ComPacketLength < sizeof(TCG_PACKET)) {
886       DEBUG ((DEBUG_INFO, "ComPacket too small for Packet\n"));
887       return (TcgResultFailureBufferTooSmall);
888     }
889     ParseStruct->CurPacket = (TCG_PACKET*)ParseStruct->ComPacket->Payload;
890 
891     PacketLength = SwapBytes32(ParseStruct->CurPacket->LengthBE);
892 
893     if (PacketLength > 0) {
894       if (PacketLength < sizeof(TCG_SUB_PACKET)) {
895           DEBUG ((DEBUG_INFO, "Packet too small for SubPacket\n"));
896           return (TcgResultFailureBufferTooSmall);
897       }
898 
899       ParseStruct->CurSubPacket = (TCG_SUB_PACKET*)ParseStruct->CurPacket->Payload;
900     }
901   }
902 
903   //TODO should check for method status list at this point?
904 
905   return (TcgResultSuccess);
906 }
907 
908 /**
909   Get next token info.
910 
911   @param    ParseStruct      Input parse structure info.
912   @param    TcgToken         return the tcg token info.
913 
914   @retval   return the action result.
915 
916 **/
917 TCG_RESULT
918 EFIAPI
TcgGetNextToken(TCG_PARSE_STRUCT * ParseStruct,TCG_TOKEN * TcgToken)919 TcgGetNextToken(
920   TCG_PARSE_STRUCT      *ParseStruct,
921   TCG_TOKEN             *TcgToken
922   )
923 {
924   const UINT8* EndOfSubPacket;
925   UINT8* TokenEnd;
926   UINT8 Hdr;
927   TCG_SIMPLE_TOKEN_SHORT_ATOM* TmpShort;
928   const TCG_SIMPLE_TOKEN_MEDIUM_ATOM* TmpMed;
929   const TCG_SIMPLE_TOKEN_LONG_ATOM* TmpLong;
930 
931   NULL_CHECK(ParseStruct);
932   NULL_CHECK(TcgToken);
933 
934   if (ParseStruct->ComPacket == NULL ||
935       ParseStruct->CurPacket == NULL ||
936       ParseStruct->CurSubPacket == NULL
937      ) {
938     DEBUG ((DEBUG_INFO, "unexpected state: ComPacket=%p CurPacket=%p CurSubPacket=%p\n", ParseStruct->ComPacket, ParseStruct->CurPacket, ParseStruct->CurSubPacket));
939     return TcgResultFailureInvalidAction;
940   }
941 
942   // initial call, start at sub packet
943   if (ParseStruct->CurPtr == NULL) {
944     ParseStruct->CurPtr = ParseStruct->CurSubPacket->Payload;
945   }
946 
947   EndOfSubPacket = ParseStruct->CurSubPacket->Payload + SwapBytes32(ParseStruct->CurSubPacket->LengthBE);
948   TokenEnd = NULL;
949 
950   // confirmed that subpacket Length falls within end of Buffer and TCG_COM_PACKET,
951   // so simply need to verify the loop stays within current subpacket
952   if (ParseStruct->CurPtr >= EndOfSubPacket) {
953     DEBUG ((DEBUG_INFO, "ParseStruct->CurPtr >= EndOfSubPacket\n"));
954     return (TcgResultFailureEndBuffer);
955   }
956 
957   Hdr = *ParseStruct->CurPtr;
958   TcgToken->HdrStart = ParseStruct->CurPtr;
959 
960   // Tiny Atom range
961   if (Hdr <= 0x7F) {
962     // tiny atom Header is only 1 byte, so don't need to verify Size before cast and access
963     TcgToken->Type = TcgTokenTypeTinyAtom;
964 
965     TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_TINY_ATOM);
966 
967     // verify caller will have enough Size to reference token
968     if (TokenEnd >= EndOfSubPacket) {
969       DEBUG ((DEBUG_INFO, "Tiny Atom TokenEnd >= EndOfSubPacket\n"));
970       return (TcgResultFailureEndBuffer);
971     }
972   }
973   // Short Atom Range
974   else if (0x80 <= Hdr && Hdr <= 0xBF) {
975     // short atom Header is only 1 byte, so don't need to verify Size before cast and access
976     TmpShort = (TCG_SIMPLE_TOKEN_SHORT_ATOM*)(ParseStruct->CurPtr);
977     TcgToken->Type = TcgTokenTypeShortAtom;
978 
979     TokenEnd = (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM) + TmpShort->ShortAtomBits.Length);
980 
981     // verify caller will have enough Size to reference token
982     if (TokenEnd >= EndOfSubPacket) {
983       DEBUG ((DEBUG_INFO, "Short Atom TokenEnd >= EndOfSubPacket\n"));
984       return (TcgResultFailureEndBuffer);
985     }
986   }
987   // Medium Atom Range
988   else if (0xC0 <= Hdr && Hdr <= 0xDF) {
989     if (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM) >= EndOfSubPacket) {
990       return (TcgResultFailureEndBuffer);
991     }
992     TmpMed = (const TCG_SIMPLE_TOKEN_MEDIUM_ATOM*)ParseStruct->CurPtr;
993     TcgToken->Type = TcgTokenTypeMediumAtom;
994     TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM) +
995                ((TmpMed->MediumAtomBits.LengthHigh << TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) |
996                 TmpMed->MediumAtomBits.LengthLow);
997 
998     // verify caller will have enough Size to reference token
999     if (TokenEnd >= EndOfSubPacket) {
1000       DEBUG ((DEBUG_INFO, "Medium Atom TokenEnd >= EndOfSubPacket\n"));
1001       return (TcgResultFailureEndBuffer);
1002     }
1003   }
1004   // Long Atom Range
1005   else if (0xE0 <= Hdr && Hdr <= 0xE3) {
1006     if (TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM) >= EndOfSubPacket) {
1007       return (TcgResultFailureEndBuffer);
1008     }
1009     TmpLong = (const TCG_SIMPLE_TOKEN_LONG_ATOM*)ParseStruct->CurPtr;
1010     TcgToken->Type = TcgTokenTypeLongAtom;
1011 
1012     TokenEnd = TcgToken->HdrStart + sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM) +
1013                ((TmpLong->LongAtomBits.LengthHigh << TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) |
1014                 (TmpLong->LongAtomBits.LengthMid << TCG_LONG_ATOM_LENGTH_MID_SHIFT)   |
1015                 TmpLong->LongAtomBits.LengthLow);
1016 
1017     // verify caller will have enough Size to reference token
1018     if (TokenEnd >= EndOfSubPacket) {
1019       DEBUG ((DEBUG_INFO, "Long Atom TokenEnd >= EndOfSubPacket\n"));
1020       return (TcgResultFailureEndBuffer);
1021     }
1022   } else {
1023     // single byte tokens
1024     switch (Hdr) {
1025       case TCG_TOKEN_STARTLIST:
1026           TcgToken->Type = TcgTokenTypeStartList;
1027           break;
1028       case TCG_TOKEN_ENDLIST:
1029           TcgToken->Type = TcgTokenTypeEndList;
1030           break;
1031       case TCG_TOKEN_STARTNAME:
1032           TcgToken->Type = TcgTokenTypeStartName;
1033           break;
1034       case TCG_TOKEN_ENDNAME:
1035           TcgToken->Type = TcgTokenTypeEndName;
1036           break;
1037       case TCG_TOKEN_CALL:
1038           TcgToken->Type = TcgTokenTypeCall;
1039           break;
1040       case TCG_TOKEN_ENDDATA:
1041           TcgToken->Type = TcgTokenTypeEndOfData;
1042           break;
1043       case TCG_TOKEN_ENDSESSION:
1044           TcgToken->Type = TcgTokenTypeEndOfSession;
1045           break;
1046       case TCG_TOKEN_STARTTRANSACTION:
1047           TcgToken->Type = TcgTokenTypeStartTransaction;
1048           break;
1049       case TCG_TOKEN_ENDTRANSACTION:
1050           TcgToken->Type = TcgTokenTypeEndTransaction;
1051           break;
1052       case TCG_TOKEN_EMPTY:
1053           TcgToken->Type = TcgTokenTypeEmptyAtom;
1054           break;
1055       default:
1056           DEBUG ((DEBUG_INFO, "WARNING: reserved token Type 0x%02X\n", Hdr));
1057           TcgToken->Type = TcgTokenTypeReserved;
1058           break;
1059     }
1060     ParseStruct->CurPtr++;
1061     TokenEnd = TcgToken->HdrStart + 1;
1062   }
1063 
1064   // increment curptr for next call
1065   ParseStruct->CurPtr = TokenEnd;
1066   return (TcgResultSuccess);
1067 }
1068 
1069 /**
1070   Get atom info.
1071 
1072   @param    TcgToken          Input token info.
1073   @param    HeaderLength      return the header length.
1074   @param    DataLength        return the data length.
1075   @param    ByteOrInt         return the atom Type.
1076   @param    SignOrCont        return the sign or count info.
1077 
1078   @retval   return the action result.
1079 
1080 **/
1081 TCG_RESULT
1082 EFIAPI
TcgGetAtomInfo(const TCG_TOKEN * TcgToken,UINT32 * HeaderLength,UINT32 * DataLength,UINT8 * ByteOrInt,UINT8 * SignOrCont)1083 TcgGetAtomInfo(
1084   const TCG_TOKEN      *TcgToken,
1085   UINT32               *HeaderLength,
1086   UINT32               *DataLength,
1087   UINT8                *ByteOrInt,
1088   UINT8                *SignOrCont
1089   )
1090 {
1091   TCG_SIMPLE_TOKEN_TINY_ATOM* TinyAtom;
1092   TCG_SIMPLE_TOKEN_SHORT_ATOM* ShortAtom;
1093   TCG_SIMPLE_TOKEN_MEDIUM_ATOM* MediumAtom;
1094   TCG_SIMPLE_TOKEN_LONG_ATOM* LongAtom;
1095 
1096   NULL_CHECK(TcgToken);
1097   NULL_CHECK(HeaderLength);
1098   NULL_CHECK(DataLength);
1099   NULL_CHECK(ByteOrInt);
1100   NULL_CHECK(SignOrCont);
1101 
1102   switch (TcgToken->Type) {
1103     case TcgTokenTypeTinyAtom: {
1104       TinyAtom = (TCG_SIMPLE_TOKEN_TINY_ATOM*)TcgToken->HdrStart;
1105       *ByteOrInt      = TCG_ATOM_TYPE_INTEGER;
1106       *SignOrCont     = TinyAtom->TinyAtomBits.Sign;
1107       *HeaderLength   = 0;
1108       *DataLength     = 0; // tiny atom must be handled as a special case - Header and Data in the same byte
1109       return TcgResultSuccess;
1110     }
1111 
1112     case TcgTokenTypeShortAtom: {
1113       ShortAtom = (TCG_SIMPLE_TOKEN_SHORT_ATOM*)TcgToken->HdrStart;
1114       *ByteOrInt      = ShortAtom->ShortAtomBits.ByteOrInt;
1115       *SignOrCont     = ShortAtom->ShortAtomBits.SignOrCont;
1116       *HeaderLength   = sizeof(TCG_SIMPLE_TOKEN_SHORT_ATOM);
1117       *DataLength     = ShortAtom->ShortAtomBits.Length;
1118       return TcgResultSuccess;
1119     }
1120 
1121     case TcgTokenTypeMediumAtom: {
1122       MediumAtom = (TCG_SIMPLE_TOKEN_MEDIUM_ATOM*)TcgToken->HdrStart;
1123       *ByteOrInt      = MediumAtom->MediumAtomBits.ByteOrInt;
1124       *SignOrCont     = MediumAtom->MediumAtomBits.SignOrCont;
1125       *HeaderLength   = sizeof(TCG_SIMPLE_TOKEN_MEDIUM_ATOM);
1126       *DataLength     = (MediumAtom->MediumAtomBits.LengthHigh << TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT) | MediumAtom->MediumAtomBits.LengthLow;
1127       return TcgResultSuccess;
1128     }
1129 
1130     case TcgTokenTypeLongAtom: {
1131       LongAtom = (TCG_SIMPLE_TOKEN_LONG_ATOM*)TcgToken->HdrStart;
1132       *ByteOrInt      = LongAtom->LongAtomBits.ByteOrInt;
1133       *SignOrCont     = LongAtom->LongAtomBits.SignOrCont;
1134       *HeaderLength   = sizeof(TCG_SIMPLE_TOKEN_LONG_ATOM);
1135       *DataLength     = (LongAtom->LongAtomBits.LengthHigh << TCG_LONG_ATOM_LENGTH_HIGH_SHIFT) |
1136                         (LongAtom->LongAtomBits.LengthMid << TCG_LONG_ATOM_LENGTH_MID_SHIFT) |
1137                         LongAtom->LongAtomBits.LengthLow;
1138       return TcgResultSuccess;
1139     }
1140 
1141     default:
1142       DEBUG ((DEBUG_INFO, "Token Type is not simple atom (%d)\n", TcgToken->Type));
1143       return (TcgResultFailureInvalidType);
1144   }
1145 }
1146 
1147 /**
1148   Get token specified value.
1149 
1150   @param    TcgToken   Input token info.
1151   @param    Value      return the value.
1152 
1153   @retval   return the action result.
1154 
1155 **/
1156 TCG_RESULT
1157 EFIAPI
TcgGetTokenUINT64(const TCG_TOKEN * TcgToken,UINT64 * Value)1158 TcgGetTokenUINT64(
1159   const TCG_TOKEN      *TcgToken,
1160   UINT64               *Value
1161   )
1162 {
1163   UINT32 HdrLength;
1164   UINT32 DataLength;
1165   UINT8 ByteOrInt;
1166   UINT8 IsSigned;
1167   TCG_SIMPLE_TOKEN_TINY_ATOM* TmpTiny;
1168   const UINT8* Data;
1169   UINT32 Index;
1170 
1171   NULL_CHECK(TcgToken);
1172   NULL_CHECK(Value);
1173 
1174   Index = 0;
1175   *Value = 0;
1176   ERROR_CHECK(TcgGetAtomInfo(TcgToken, &HdrLength, &DataLength, &ByteOrInt, &IsSigned));
1177 
1178   if (ByteOrInt != TCG_ATOM_TYPE_INTEGER) {
1179     DEBUG ((DEBUG_INFO, "Invalid Type, expected integer not byte sequence\n"));
1180     return TcgResultFailureInvalidType;
1181   }
1182 
1183   if (IsSigned != 0) {
1184     DEBUG ((DEBUG_INFO, "Integer is signed, expected unsigned\n"));
1185     return TcgResultFailureInvalidType;
1186   }
1187 
1188   // special case for tiny atom
1189   // Header and Data are in one byte, so extract only the Data bitfield
1190   if (TcgToken->Type == TcgTokenTypeTinyAtom) {
1191     TmpTiny = (TCG_SIMPLE_TOKEN_TINY_ATOM*)TcgToken->HdrStart;
1192     *Value = TmpTiny->TinyAtomBits.Data;
1193     return TcgResultSuccess;
1194   }
1195 
1196   if (DataLength > sizeof(UINT64)) {
1197     DEBUG ((DEBUG_INFO, "Length %d is greater than Size of UINT64\n", DataLength));
1198     return TcgResultFailureBufferTooSmall;
1199   }
1200 
1201   // read big-endian integer
1202   Data = TcgToken->HdrStart + HdrLength;
1203   for (Index = 0; Index < DataLength; Index++) {
1204     *Value = LShiftU64(*Value, 8) | Data[Index];
1205   }
1206 
1207   return TcgResultSuccess;
1208 }
1209 
1210 /**
1211   Get token byte sequence.
1212 
1213   @param    TcgToken   Input token info.
1214   @param    Length     Input the length info.
1215 
1216   @retval   Return the value data.
1217 
1218 **/
1219 UINT8*
1220 EFIAPI
TcgGetTokenByteSequence(const TCG_TOKEN * TcgToken,UINT32 * Length)1221 TcgGetTokenByteSequence(
1222   const TCG_TOKEN     *TcgToken,
1223   UINT32              *Length
1224   )
1225 {
1226   UINT32 HdrLength;
1227   UINT8 ByteOrInt;
1228   UINT8 SignOrCont;
1229 
1230   if (TcgToken == NULL || Length == NULL) {
1231     return NULL;
1232   }
1233 
1234   *Length = 0;
1235   if (TcgGetAtomInfo(TcgToken, &HdrLength, Length, &ByteOrInt, &SignOrCont) != TcgResultSuccess) {
1236     DEBUG ((DEBUG_INFO, "Failed to get simple token info\n"));
1237     return NULL;
1238   }
1239 
1240   if (ByteOrInt != TCG_ATOM_TYPE_BYTE) {
1241     DEBUG ((DEBUG_INFO, "Invalid Type, expected byte sequence not integer\n"));
1242     return NULL;
1243   }
1244 
1245   return (TcgToken->HdrStart + HdrLength);
1246 }
1247 
1248 /**
1249   Get next specify value.
1250 
1251   @param    ParseStruct   Input parse structure.
1252   @param    Value         Return vlaue.
1253 
1254   @retval   return the action result.
1255 
1256 **/
1257 TCG_RESULT
1258 EFIAPI
TcgGetNextUINT8(TCG_PARSE_STRUCT * ParseStruct,UINT8 * Value)1259 TcgGetNextUINT8(
1260   TCG_PARSE_STRUCT      *ParseStruct,
1261   UINT8                 *Value
1262   )
1263 {
1264   UINT64 Value64;
1265   TCG_TOKEN Tok;
1266 
1267   NULL_CHECK(Value);
1268 
1269   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1270   ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
1271 
1272   if (Value64 > MAX_UINT8) {
1273     return TcgResultFailure;
1274   }
1275 
1276   *Value = (UINT8)Value64;
1277 
1278   return TcgResultSuccess;
1279 }
1280 
1281 /**
1282   Get next specify value.
1283 
1284   @param    ParseStruct   Input parse structure.
1285   @param    Value         Return vlaue.
1286 
1287   @retval   return the action result.
1288 
1289 **/
1290 TCG_RESULT
1291 EFIAPI
TcgGetNextUINT16(TCG_PARSE_STRUCT * ParseStruct,UINT16 * Value)1292 TcgGetNextUINT16(
1293   TCG_PARSE_STRUCT     *ParseStruct,
1294   UINT16               *Value
1295   )
1296 {
1297   UINT64 Value64;
1298   TCG_TOKEN Tok;
1299 
1300   NULL_CHECK(Value);
1301 
1302   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1303   ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
1304 
1305   if (Value64 > MAX_UINT16) {
1306     return TcgResultFailure;
1307   }
1308 
1309   *Value = (UINT16)Value64;
1310 
1311   return TcgResultSuccess;
1312 }
1313 
1314 /**
1315   Get next specify value.
1316 
1317   @param    ParseStruct   Input parse structure.
1318   @param    Value         Return vlaue.
1319 
1320   @retval   return the action result.
1321 
1322 **/
1323 TCG_RESULT
1324 EFIAPI
TcgGetNextUINT32(TCG_PARSE_STRUCT * ParseStruct,UINT32 * Value)1325 TcgGetNextUINT32(
1326   TCG_PARSE_STRUCT          *ParseStruct,
1327   UINT32                    *Value
1328   )
1329 {
1330   UINT64 Value64;
1331   TCG_TOKEN Tok;
1332 
1333   NULL_CHECK(Value);
1334 
1335   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1336   ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
1337 
1338   if (Value64 > MAX_UINT32) {
1339     return TcgResultFailure;
1340   }
1341 
1342   *Value = (UINT32)Value64;
1343 
1344   return TcgResultSuccess;
1345 }
1346 
1347 /**
1348   Get next specify value.
1349 
1350   @param    ParseStruct   Input parse structure.
1351   @param    Value         Return vlaue.
1352 
1353   @retval   return the action result.
1354 
1355 **/
1356 TCG_RESULT
1357 EFIAPI
TcgGetNextUINT64(TCG_PARSE_STRUCT * ParseStruct,UINT64 * Value)1358 TcgGetNextUINT64(
1359   TCG_PARSE_STRUCT           *ParseStruct,
1360   UINT64                     *Value
1361   )
1362 {
1363   TCG_TOKEN Tok;
1364   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1365   ERROR_CHECK(TcgGetTokenUINT64(&Tok, Value));
1366   return TcgResultSuccess;
1367 }
1368 
1369 /**
1370   Get next specify value.
1371 
1372   @param    ParseStruct   Input parse structure.
1373   @param    Value         Return vlaue.
1374 
1375   @retval   return the action result.
1376 
1377 **/
1378 TCG_RESULT
1379 EFIAPI
TcgGetNextBOOLEAN(TCG_PARSE_STRUCT * ParseStruct,BOOLEAN * Value)1380 TcgGetNextBOOLEAN(
1381   TCG_PARSE_STRUCT        *ParseStruct,
1382   BOOLEAN                 *Value
1383   )
1384 {
1385   UINT64 Value64;
1386   TCG_TOKEN Tok;
1387 
1388   NULL_CHECK(Value);
1389 
1390   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1391   ERROR_CHECK(TcgGetTokenUINT64(&Tok, &Value64));
1392 
1393   if (Value64 > 1) {
1394     return TcgResultFailure;
1395   }
1396 
1397   *Value = (BOOLEAN)Value64;
1398 
1399   return TcgResultSuccess;
1400 }
1401 
1402 /**
1403   Get next tcg uid info.
1404 
1405   @param    ParseStruct    Input parse structure.
1406   @param    Uid            Get the uid info.
1407 
1408   @retval   return the action result.
1409 
1410 **/
1411 TCG_RESULT
1412 EFIAPI
TcgGetNextTcgUid(TCG_PARSE_STRUCT * ParseStruct,TCG_UID * Uid)1413 TcgGetNextTcgUid(
1414   TCG_PARSE_STRUCT         *ParseStruct,
1415   TCG_UID                  *Uid
1416   )
1417 {
1418   TCG_TOKEN Tok;
1419   UINT32 Length;
1420   const UINT8* ByteSeq;
1421 
1422   NULL_CHECK(Uid);
1423 
1424   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1425   ByteSeq = TcgGetTokenByteSequence(&Tok, &Length);
1426 
1427   if (Length != sizeof(TCG_UID)) {
1428     DEBUG ((DEBUG_INFO, "Token Length %u != TCG_UID Size %u\n", Length, (UINT32)sizeof(TCG_UID)));
1429     return TcgResultFailure;
1430   }
1431 
1432   ASSERT (ByteSeq != NULL);
1433 
1434   CopyMem(Uid, ByteSeq, sizeof(TCG_UID));
1435 
1436   return TcgResultSuccess;
1437 }
1438 
1439 /**
1440   Get next byte sequence.
1441 
1442   @param    ParseStruct     Input parse structure.
1443   @param    Data            return the data.
1444   @param    Length          return the length.
1445 
1446   @retval   return the action result.
1447 
1448 **/
1449 TCG_RESULT
1450 EFIAPI
TcgGetNextByteSequence(TCG_PARSE_STRUCT * ParseStruct,const VOID ** Data,UINT32 * Length)1451 TcgGetNextByteSequence(
1452   TCG_PARSE_STRUCT      *ParseStruct,
1453   const VOID            **Data,
1454   UINT32                *Length
1455   )
1456 {
1457   TCG_TOKEN Tok;
1458   const UINT8* Bs;
1459 
1460   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1461   Bs = TcgGetTokenByteSequence(&Tok, Length);
1462 
1463   if (Bs == NULL) {
1464     return TcgResultFailure;
1465   }
1466   *Data = Bs;
1467   return TcgResultSuccess;
1468 }
1469 
1470 /**
1471   Get next token Type.
1472 
1473   @param    ParseStruct    Input parse structure.
1474   @param    Type           Input the type need to check.
1475 
1476   @retval   return the action result.
1477 
1478 **/
1479 TCG_RESULT
1480 EFIAPI
TcgGetNextTokenType(TCG_PARSE_STRUCT * ParseStruct,TCG_TOKEN_TYPE Type)1481 TcgGetNextTokenType(
1482   TCG_PARSE_STRUCT        *ParseStruct,
1483   TCG_TOKEN_TYPE          Type
1484   )
1485 {
1486   TCG_TOKEN Tok;
1487   ERROR_CHECK(TcgGetNextToken(ParseStruct, &Tok));
1488   if (Tok.Type != Type) {
1489     DEBUG ((DEBUG_INFO, "expected Type %u, got Type %u\n", Type, Tok.Type));
1490     return TcgResultFailure;
1491   }
1492   return TcgResultSuccess;
1493 }
1494 
1495 /**
1496   Get next start list.
1497 
1498   @param    ParseStruct   Input parse structure.
1499 
1500   @retval   return the action result.
1501 
1502 **/
1503 TCG_RESULT
1504 EFIAPI
TcgGetNextStartList(TCG_PARSE_STRUCT * ParseStruct)1505 TcgGetNextStartList(
1506   TCG_PARSE_STRUCT          *ParseStruct
1507   )
1508 {
1509   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartList);
1510 }
1511 
1512 /**
1513   Get next end list.
1514 
1515   @param    ParseStruct   Input parse structure.
1516 
1517   @retval   return the action result.
1518 
1519 **/
1520 TCG_RESULT
1521 EFIAPI
TcgGetNextEndList(TCG_PARSE_STRUCT * ParseStruct)1522 TcgGetNextEndList(
1523   TCG_PARSE_STRUCT             *ParseStruct
1524   )
1525 {
1526   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndList);
1527 }
1528 
1529 /**
1530   Get next start name.
1531 
1532   @param    ParseStruct   Input parse structure.
1533 
1534   @retval   return the action result.
1535 
1536 **/
1537 TCG_RESULT
1538 EFIAPI
TcgGetNextStartName(TCG_PARSE_STRUCT * ParseStruct)1539 TcgGetNextStartName(
1540   TCG_PARSE_STRUCT              *ParseStruct
1541   )
1542 {
1543   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartName);
1544 }
1545 
1546 /**
1547   Get next end name.
1548 
1549   @param    ParseStruct   Input parse structure.
1550 
1551   @retval   return the action result.
1552 
1553 **/
1554 TCG_RESULT
1555 EFIAPI
TcgGetNextEndName(TCG_PARSE_STRUCT * ParseStruct)1556 TcgGetNextEndName(
1557   TCG_PARSE_STRUCT               *ParseStruct
1558   )
1559 {
1560   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndName);
1561 }
1562 
1563 /**
1564   Get next call.
1565 
1566   @param    ParseStruct   Input parse structure.
1567 
1568   @retval   return the action result.
1569 
1570 **/
1571 TCG_RESULT
1572 EFIAPI
TcgGetNextCall(TCG_PARSE_STRUCT * ParseStruct)1573 TcgGetNextCall(
1574   TCG_PARSE_STRUCT                   *ParseStruct
1575   )
1576 {
1577   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeCall);
1578 }
1579 
1580 /**
1581   Get next end data.
1582 
1583   @param    ParseStruct   Input parse structure.
1584 
1585   @retval   return the action result.
1586 
1587 **/
1588 TCG_RESULT
1589 EFIAPI
TcgGetNextEndOfData(TCG_PARSE_STRUCT * ParseStruct)1590 TcgGetNextEndOfData(
1591   TCG_PARSE_STRUCT                    *ParseStruct
1592   )
1593 {
1594   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndOfData);
1595 }
1596 
1597 /**
1598   Get next end of session.
1599 
1600   @param    ParseStruct   Input parse structure.
1601 
1602   @retval   return the action result.
1603 
1604 **/
1605 TCG_RESULT
1606 EFIAPI
TcgGetNextEndOfSession(TCG_PARSE_STRUCT * ParseStruct)1607 TcgGetNextEndOfSession(
1608   TCG_PARSE_STRUCT                      *ParseStruct
1609   )
1610 {
1611   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndOfSession);
1612 }
1613 
1614 /**
1615   Get next start transaction.
1616 
1617   @param    ParseStruct   Input parse structure.
1618 
1619   @retval   return the action result.
1620 
1621 **/
1622 TCG_RESULT
1623 EFIAPI
TcgGetNextStartTransaction(TCG_PARSE_STRUCT * ParseStruct)1624 TcgGetNextStartTransaction(
1625   TCG_PARSE_STRUCT                        *ParseStruct
1626   )
1627 {
1628   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeStartTransaction);
1629 }
1630 
1631 /**
1632   Get next end transaction.
1633 
1634   @param    ParseStruct   Input parse structure.
1635 
1636   @retval   return the action result.
1637 
1638 **/
1639 TCG_RESULT
1640 EFIAPI
TcgGetNextEndTransaction(TCG_PARSE_STRUCT * ParseStruct)1641 TcgGetNextEndTransaction(
1642   TCG_PARSE_STRUCT                  *ParseStruct
1643   )
1644 {
1645   return TcgGetNextTokenType(ParseStruct, TcgTokenTypeEndTransaction);
1646 }
1647